我想使用 php 连接到我自己的 cardDAV 服务器。 这就是我现在所拥有的:
<?php
$carddav = new carddav_backend('https://localhost/contacts/carddav/SynoContacts/');
$carddav->set_auth('myUsername', 'myPassword');
// CardDAV add query
$vcard = 'BEGIN:VCARD
VERSION:3.0
UID:1f5ea45f-b28a-4b96-25as-ed4f10edf57b
FN:Max Mustermann
N:Max;Mustermann;;;
EMAIL;TYPE=OTHER:max.mustermann@mail.de
END:VCARD';
echo '<pre>';
var_dump($carddav->add($vcard));
echo '</pre>';
// CARDDAV
class carddav_backend {
const VERSION = '0.6';
const USERAGENT = 'CardDAV PHP/';
private $url = null;
private $auth = null;
private $username = null;
private $password = null;
private $vcard_id_chars = array(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 'a', 'b', 'c', 'd', 'e', 'f');
const EXCEPTION_WRONG_HTTP_STATUS_CODE_ADD = 1004;
const EXCEPTION_MALFORMED_XML_RESPONSE = 1006;
const EXCEPTION_COULD_NOT_GENERATE_NEW_VCARD_ID = 1007;
// Gets a clean vCard from the CardDAV server
public function get_vcard($vcard_id) {
$result = $this->query($this->url . $vcard_id . '.vcf', 'GET');
switch ($result['http_code']) {
case 200:
case 207:
return $result['response'];
break;
default:
throw new Exception('Error ' . $result['http_code'] . '.', self::EXCEPTION_WRONG_HTTP_STATUS_CODE_GET_VCARD);
break;
}
}
// Sets the CardDAV server url
public function __construct($url = null) {
$this->url = $url;
}
// Sets authentication information
public function set_auth($username, $password) {
$this->username = $username;
$this->password = $password;
$this->auth = $username . ':' . $password;
}
// Checks if the CardDAV server is reachable
public function check_connection() {
$result = $this->query($this->url, 'OPTIONS');
if ($result['http_code'] === 200) {
return true;
} else {
return false;
}
}
// Add Contact
public function add($vcard) {
$vcard_id = $this->generate_vcard_id();
$result = $this->query($this->url . $vcard_id . '.vcf', 'PUT', $vcard, 'text/vcard');
return $result;
}
// Returns a valid and unused vCard id
private function generate_vcard_id() {
$vcard_id = null;
for ($number = 0; $number <= 35; $number ++) {
if ($number == 8 || $number == 13 || $number == 18 || $number == 23) {
$vcard_id .= '-';
} else {
$vcard_id .= $this->vcard_id_chars[mt_rand(0, (count($this->vcard_id_chars) - 1))];
}
}
try {
$carddav = new carddav_backend($this->url);
$carddav->set_auth($this->username, $this->password);
$result = $carddav->query($this->url . $vcard_id . '.vcf', 'GET');
if ($result['http_code'] !== 404) {
$vcard_id = $this->generate_vcard_id();
}
return $vcard_id;
}
catch (Exception $e) {
throw new Exception($e->getMessage(), self::EXCEPTION_COULD_NOT_GENERATE_NEW_VCARD_ID);
}
}
// Curl initialization
public function curl_init() {
if (empty($this->curl)) {
$this->curl = curl_init();
curl_setopt($this->curl, CURLOPT_HEADER, true);
curl_setopt($this->curl, CURLOPT_SSL_VERIFYHOST, false);
curl_setopt($this->curl, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($this->curl, CURLOPT_RETURNTRANSFER, true);
curl_setopt($this->curl, CURLOPT_USERAGENT, self::USERAGENT.self::VERSION);
if ($this->auth !== null) {
curl_setopt($this->curl, CURLOPT_HTTPAUTH, CURLAUTH_ANY);
curl_setopt($this->curl, CURLOPT_USERPWD, $this->auth);
}
}
}
// Query the CardDAV server via curl and returns the response
private function query($url, $method, $content = null, $content_type = null) {
$this->curl_init();
curl_setopt($this->curl, CURLOPT_URL, $url);
curl_setopt($this->curl, CURLOPT_CUSTOMREQUEST, $method);
if ($content !== null) {
curl_setopt($this->curl, CURLOPT_POST, true);
curl_setopt($this->curl, CURLOPT_POSTFIELDS, $content);
} else {
curl_setopt($this->curl, CURLOPT_POST, false);
curl_setopt($this->curl, CURLOPT_POSTFIELDS, null);
}
if ($content_type !== null) {
curl_setopt($this->curl, CURLOPT_HTTPHEADER, array('Content-type: '.$content_type));
} else {
curl_setopt($this->curl, CURLOPT_HTTPHEADER, array());
}
$complete_response = curl_exec($this->curl);
$header_size = curl_getinfo($this->curl, CURLINFO_HEADER_SIZE);
$http_code = curl_getinfo($this->curl, CURLINFO_HTTP_CODE);
$header = trim(substr($complete_response, 0, $header_size));
$return = array(
'response' => $complete_response,
'http_code' => $http_code
);
return $return;
}
// Close curl connection if it's open
public function __destruct() {
if (!empty($this->curl)) {
curl_close($this->curl);
}
}
}
?>
结果: 连接应该没问题,因为php代码成功创建了一个新的联系人“Max Mustermann”。
但是输出 var_dump($carddav->add($vcard));
显示了这一点:
array(2) {
["response"]=>
string(412) "HTTP/1.1 401 Unauthorized
Server: nginx
Date: Tue, 05 Jan 2021 12:49:06 GMT
Content-Type: text/plain; charset=utf-8
Content-Length: 43
Connection: keep-alive
Keep-Alive: timeout=20
WWW-Authenticate: Basic realm="Radicale - Password Required"
HTTP/1.1 201 Created
Server: nginx
Date: Tue, 05 Jan 2021 12:49:07 GMT
Content-Length: 0
Connection: keep-alive
Keep-Alive: timeout=20
ETag: "43_1144"
"
["http_code"]=>
int(201)
}
为什么我得到 HTTP/1.1 401 Unauthorized
?