Roundcube-CardDAV icon indicating copy to clipboard operation
Roundcube-CardDAV copied to clipboard

Mountain Lion Contacts cardDAV server sync problems.

Open geoxry opened this issue 12 years ago • 21 comments

Hi everyone,

I am trying to use the latest version of Roundcube along with the current version of the graviox/ Roundcube-CardDAV plugin.

When entering server and login info the connection with the server seems to be ok (server gets accepted and is added) but when I synchronize I cannot see any contacts in my cardDAV folder.

Does anyone else had the same problem? Any solutions or any hints about what could be wrong.

Thank you very much. George

geoxry avatar Aug 18 '12 12:08 geoxry

I get:

"capi:logs ladmin$ cat CardDAV [29-Aug-2012 01:14:53 +0200]: v0.5.1 | carddav_server_id: 1 | Starting CardDAV-Addressbook synchronization [29-Aug-2012 01:14:53 +0200]: v0.5.1 | carddav_server_id: 1 | Connected to the CardDAV-Server http://capi.ro/addressbooks/users/bogdan/addressbook/ [29-Aug-2012 01:14:53 +0200]: v0.5.1 | carddav_server_id: 1 | CardDAV-Server XML-Response is malformed. Synchronization aborted! [29-Aug-2012 01:15:07 +0200]: v0.5.1 | carddav_server_id: 1 | Starting CardDAV-Addressbook synchronization [29-Aug-2012 01:15:08 +0200]: v0.5.1 | carddav_server_id: 1 | Connected to the CardDAV-Server http://capi.ro/addressbooks/users/bogdan/addressbook/ [29-Aug-2012 01:15:08 +0200]: v0.5.1 | carddav_server_id: 1 | CardDAV-Server XML-Response is malformed. Synchronization aborted!"

catara avatar Aug 28 '12 23:08 catara

I am unable to get synchronization working as well.

OSX 10.8 Server RoundCube 0.8.1 CardDAV 0.5.1

I am able to get the CardDav settings to recgnize my server. However no contacts are synced to the addressbook. When I attempt to sync manually, I get the following error: An error occurred while synchronizing the CardDAV contacts

niwrik avatar Sep 04 '12 20:09 niwrik

possibly help section 2 in https://github.com/graviox/Roundcube-CardDAV/issues/36

schum avatar Sep 23 '12 14:09 schum

I am also able to get the CardDav settings to recgnize my server. and like nlwrik no contacts are synced to the addressbook. When I attempt to sync manually, I get the following error: An error occurred while synchronizing the CardDAV contacts

anybody successful sync with a mountain lion server???

mvdbent avatar Oct 17 '12 20:10 mvdbent

I found a message board where someone had posted a fix for this. I was able to get it running in the end. It involved modifying some code (that I didn't understand) in one of the files. I'll look later and see if I can find it for you.

BK

Sent from my iPhone

On Oct 17, 2012, at 4:00 PM, mvdbent [email protected] wrote:

I am also able to get the CardDav settings to recgnize my server. and like nlwrik no contacts are synced to the addressbook. When I attempt to sync manually, I get the following error: An error occurred while synchronizing the CardDAV contacts

anybody successful sync with a mountain lion server???

— Reply to this email directly or view it on GitHub.

niwrik avatar Oct 17 '12 21:10 niwrik

@mvdbent schum posted the answer above. I was able to make this work following the link he posted. If you are unable to get it working, I'll look back at my config and reference the changes I made that worked.

niwrik avatar Oct 18 '12 01:10 niwrik

@niwrik Can you please share your carddav config files, and also the carddav user config (e.g. http://example.com:8080...)

catara avatar Nov 09 '12 19:11 catara

I'm seeing the CardDAV-Server XML-Response is malformed. Synchronization aborted! error as well. My setup is as follows:

  • Mac OS X Server 10.8.2
  • Roundcube Webmail 0.8.4 (hosted on an Ubuntu Linux box)
  • graviox / Roundcube-CardDAV 0.5.1

One note for setup: I had to use http instead of https when configuring the server connection, even though the OS X machine is properly configured to serve https. Trying a secure connection just caused the setup to fail. As soon as I changed to normal http it connected just fine.

I added a self::write_log($e); line to the carddav_addressbook.php file to get a better look at the exception when it gets thrown, and this is what I see:

[25-Jan-2013 15:10:35 -0800]: v0.5.1 |  carddav_server_id: 2 | Starting CardDAV-Addressbook synchronization
[25-Jan-2013 15:10:35 -0800]: v0.5.1 |  carddav_server_id: 2 | Connected to the CardDAV-Server http://SERVER.ADDRESS/addressbooks/users/michael/addressbook/
[25-Jan-2013 15:10:35 -0800]: v0.5.1 |  carddav_server_id: 2 | CardDAV-Server XML-Response is malformed. Synchronization aborted!
[25-Jan-2013 15:10:35 -0800]: v0.5.1 |  carddav_server_id: 2 | exception 'Exception' with message 'String could not be parsed as XML' in /usr/local/etc/roundcube/plugins/carddav/carddav_addressbook.php:402
Stack trace:
#0 /usr/local/etc/roundcube/plugins/carddav/carddav_addressbook.php(402): SimpleXMLElement->__construct('')
#1 /usr/local/etc/roundcube/plugins/carddav/carddav.php(305): carddav_addressbook->carddav_addressbook_sync(Array)
#2 [internal function]: carddav->carddav_addressbook_sync()
#3 /usr/local/etc/roundcube/program/include/rcube_plugin_api.php(316): call_user_func(Array)
#4 /usr/local/etc/roundcube/index.php(279): rcube_plugin_api->exec_action('plugin.carddav-...')
#5 {main}

It looks like carddav_addressbook.php:402 is trying to make a new SimpleXMLElement object by passing an empty string instead of valid XML data.

I tried replacing the PROPFIND line in carddav_backend.php with the three lines from #29, but that has no effect on the problem.

beornlake avatar Jan 25 '13 23:01 beornlake

Have anyone got this plugin working on Mountain Lion? I've tried the fixes in #29 and #36; however, I still have problems. I still receive the "ardDAV-Server XML-Response is malformed. Synchronization aborted!" error. Thanks so much!

bryan977 avatar Feb 01 '13 15:02 bryan977

Hello. I stopped using this awhile back and haven't gotten back to it. An OSX update broke roundcude on me (something to do with postgres), so I had to recreate the database using mysql. Prior to that, I was able to sync carddav address book after making the changes to carddav_backend.php. Sorry, but I don't recall the exact lines of code I change (per instructions in the message board). If it helps, here's the code from the file that worked for me:

set_auth('username', 'password'); - echo $carddav->get(); * * - Simple vCard query - ------------------ - $carddav = new carddav_backend('https://davical.example.com/user/contacts/'); - $carddav->set_auth('username', 'password'); - echo $carddav->get_vcard('0126FFB4-2EB74D0A-302EA17F'); * * - XML vCard query - ------------------ - $carddav = new carddav_backend('https://davical.example.com/user/contacts/'); - $carddav->set_auth('username', 'password'); - echo $carddav->get_xml_vcard('0126FFB4-2EB74D0A-302EA17F'); * * - Check CardDAV server connection - ------------------------------- - $carddav = new carddav_backend('https://davical.example.com/user/contacts/'); - $carddav->set_auth('username', 'password'); - var_dump($carddav->check_connection()); * * - CardDAV delete query - -------------------- - $carddav = new carddav_backend('https://davical.example.com/user/contacts/'); - $carddav->set_auth('username', 'password'); - $carddav->delete('0126FFB4-2EB74D0A-302EA17F'); * * - CardDAV add query - -------------------- - $vcard = 'BEGIN:VCARD - VERSION:3.0 - UID:1f5ea45f-b28a-4b96-25as-ed4f10edf57b - FN:Christian Putzke - N:Christian;Putzke;;; - EMAIL;TYPE=OTHER:[email protected] - END:VCARD'; * - $carddav = new carddav_backend('https://davical.example.com/user/contacts/'); - $carddav->set_auth('username', 'password'); - $vcard_id = $carddav->add($vcard); * * - CardDAV update query - -------------------- - $vcard = 'BEGIN:VCARD - VERSION:3.0 - UID:1f5ea45f-b28a-4b96-25as-ed4f10edf57b - FN:Christian Putzke - N:Christian;Putzke;;; - EMAIL;TYPE=OTHER:[email protected] - END:VCARD'; * - $carddav = new carddav_backend('https://davical.example.com/user/contacts/'); - $carddav->set_auth('username', 'password'); - $carddav->update($vcard, '0126FFB4-2EB74D0A-302EA17F'); * * - CardDAV server list - ------------------- - DAViCal: https://example.com/{resource|principal|username}/{collection}/ - Apple Addressbook Server: https://example.com/addressbooks/users/{resource|principal|username}/{collection}/ - memotoo: https://sync.memotoo.com/cardDAV/ - SabreDAV: https://example.com/addressbooks/{resource|principal|username}/{collection}/ - ownCloud: https://example.com/apps/contacts/carddav.php/addressbooks/{resource|principal|username}/{collection}/ - SOGo: http://sogo-demo.inverse.ca/SOGo/dav/{resource|principal|username}/Contacts/{collection}/ * * - @author Christian Putzke [email protected] - @copyright Christian Putzke @ Graviox Studios - @link http://www.graviox.de/ - @link https://twitter.com/graviox/ - @since 20.07.2011 - @version 0.5.1 - @license http://www.gnu.org/licenses/agpl.html GNU AGPL v3 or later * */ class carddav_backend { /** \* CardDAV PHP Version * \* @constant string */ const VERSION = '0.5.1'; ``` /** * User agent displayed in http requests * * @constant string */ const USERAGENT = 'CardDAV PHP/'; /** * CardDAV server url * * @var string */ private $url = null; /** * CardDAV server url_parts * * @var array */ private $url_parts = null; /** * Authentication string * * @var string */ private $auth = null; /** * Authentication: username * * @var string */ private $username = null; /** * Authentication: password * * @var string */ private $password = null; /** * Characters used for vCard id generation * * @var array */ private $vcard_id_chars = array(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 'A', 'B', 'C', 'D', 'E', 'F'); /** * CardDAV server connection (curl handle) * * @var resource */ private $curl; /** * Constructor * Sets the CardDAV server url * * @param string $url CardDAV server url * @return void */ public function __construct($url = null) { if ($url !== null) { $this->set_url($url); } } /** * Sets the CardDAV server url * * @param string $url CardDAV server url * @return void */ public function set_url($url) { $this->url = $url; if (substr($this->url, -1, 1) !== '/') { $this->url = $this->url . '/'; } $this->url_parts = parse_url($this->url); } /** * Sets authentication string * * @param string $username CardDAV server username * @param string $password CardDAV server password * @return void */ public function set_auth($username, $password) { $this->username = $username; $this->password = $password; $this->auth = $username . ':' . $password; } /** * Gets propfind XML response from the CardDAV server * * @param boolean $include_vcards vCards include vCards in the response (simplified only) * @param boolean $raw Get response raw or simplified * @return string Raw or simplified XML response */ public function get($include_vcards = true, $raw = false) { /** $response = $this->query($this->url, 'PROPFIND'); */ $content = '
                <D:sync-collection xmlns:D="DAV:" xmlns:C="urn:ietf:params:xml:ns:carddav">
                <D:sync-token></D:sync-token>
                <D:sync-level>1</D:sync-level>
                <D:prop><D:getcontenttype/><D:getetag/><D:allprop/>
                <C:address-data><C:allprop/></C:address-data></D:prop>
                <C:filter/></D:sync-collection>';
$content_type = 'application/xml';
$response = $this->query($this->url, 'REPORT', $content, $content_type);



if ($response === false || $raw === true)
{
    return $response;
}
else
{
    return $this->simplify($response, $include_vcards);
}

}

/**

  • Gets a clean vCard from the CardDAV server
  • @param string $vcard_id vCard id on the CardDAV server
  • @return string vCard (text/vcard) */ public function get_vcard($vcard_id) { $vcard_id = str_replace('.vcf', null, $vcard_id); return $this->query($this->url . $vcard_id . '.vcf', 'GET'); }

/**

  • Gets a vCard + XML from the CardDAV Server

  • @param string $vcard_id vCard id on the CardDAV Server

  • @param boolean $raw Get response raw or simplified

  • @return string Raw or simplified vCard (text/xml) */ public function get_xml_vcard($vcard_id, $raw = false) { $vcard_id = str_replace('.vcf', null, $vcard_id);

    $xml = new XMLWriter(); $xml->openMemory(); $xml->setIndent(4); $xml->startDocument('1.0', 'utf-8'); $xml->startElement('C:addressbook-multiget'); $xml->writeAttribute('xmlns:D', 'DAV:'); $xml->writeAttribute('xmlns:C', 'urn:ietf:params:xml:ns:carddav'); $xml->startElement('D:prop'); $xml->writeElement('D:getetag'); $xml->writeElement('D:getlastmodified'); $xml->endElement(); $xml->writeElement('D:href', $this->url_parts['path'] . $vcard_id . '.vcf'); $xml->endElement(); $xml->endDocument();

    $response = $this->query($this->url, 'REPORT', $xml->outputMemory(), 'text/xml');

    if ($raw === true || $response === false) { return $response; } else { return $this->simplify($response, true); } }

/**

  • Checks if the CardDAV server is reachable
  • @return boolean */ public function check_connection() { return $this->query($this->url, 'OPTIONS', null, null, true); }

/**

  • Cleans the vCard

  • @param string $vcard vCard

  • @return string $vcard vCard */ private function clean_vcard($vcard) { $vcard = str_replace("\t", null, $vcard);

    return $vcard; }

/**

  • Deletes an entry from the CardDAV server
  • @param string $vcard_id vCard id on the CardDAV server
  • @return boolean */ public function delete($vcard_id) { return $this->query($this->url . $vcard_id . '.vcf', 'DELETE', null, null, true); }

/**

  • Adds an entry to the CardDAV server

  • @param string $vcard vCard

  • @return string The new vCard id */ public function add($vcard) { $vcard_id = $this->generate_vcard_id(); $vcard = $this->clean_vcard($vcard);

    if ($this->query($this->url . $vcard_id . '.vcf', 'PUT', $vcard, 'text/vcard', true) === true) { return $vcard_id; } else { return false; } }

/**

  • Updates an entry to the CardDAV server

  • @param string $vcard vCard

  • @param string $vcard_id vCard id on the CardDAV server

  • @return boolean */ public function update($vcard, $vcard_id) { $vcard_id = str_replace('.vcf', null, $vcard_id); $vcard = $this->clean_vcard($vcard);

    return $this->query($this->url . $vcard_id . '.vcf', 'PUT', $vcard, 'text/vcard', true); }

/**

  • Simplify CardDAV XML response

  • @param string $response CardDAV XML response

  • @param boolean $include_vcards Include vCards or not

  • @return string Simplified CardDAV XML response */ private function simplify($response, $include_vcards = true) { $response = $this->clean_response($response); $xml = new SimpleXMLElement($response);

    $simplified_xml = new XMLWriter(); $simplified_xml->openMemory(); $simplified_xml->setIndent(4);

    $simplified_xml->startDocument('1.0', 'utf-8'); $simplified_xml->startElement('response');

         foreach ($xml->response as $response)
         {
             if (preg_match('/vcard/', $response->propstat->prop->getcontenttype) || preg_match('/vcf/', $response->href))
             {
                 $id = basename($response->href);
                 $id = str_replace('.vcf', null, $id);
    
                 if (!empty($id))
                 {
                     $simplified_xml->startElement('element');
                         $simplified_xml->writeElement('id', $id);
                         $simplified_xml->writeElement('etag', str_replace('"', null, $response->propstat->prop->getetag));
                         $simplified_xml->writeElement('last_modified', $response->propstat->prop->getlastmodified);
    
                         if ($include_vcards === true)
                         {
                             $simplified_xml->writeElement('vcard', $this->get_vcard($id));
                         }
                     $simplified_xml->endElement();
                 }
             }
             else if (preg_match('/unix-directory/', $response->propstat->prop->getcontenttype))
             {
                 if (isset($response->propstat->prop->href))
                 {
                     $href = $response->propstat->prop->href;
                 }
                 else if (isset($response->href))
                 {
                     $href = $response->href;
                 }
                 else
                 {
                     $href = null;
                 }
    
                 $url = str_replace($this->url_parts['path'], null, $this->url) . $href;
                 $simplified_xml->startElement('addressbook_element');
                     $simplified_xml->writeElement('display_name', $response->propstat->prop->displayname);
                     $simplified_xml->writeElement('url', $url);
                     $simplified_xml->writeElement('last_modified', $response->propstat->prop->getlastmodified);
                 $simplified_xml->endElement();
             }
         }
    
     $simplified_xml->endElement();
    

    $simplified_xml->endDocument();

    return $simplified_xml->outputMemory(); }

/**

  • Cleans CardDAV XML response

  • @param string $response CardDAV XML response

  • @return string $response Cleaned CardDAV XML response */ private function clean_response($response) { $response = utf8_encode($response); $response = str_replace('D:', null, $response); $response = str_replace('d:', null, $response); $response = str_replace('C:', null, $response); $response = str_replace('c:', null, $response);

    return $response; }

/**

  • Curl initialization

  • @return void */ public function curl_init() { if (empty($this->curl)) { $this->curl = curl_init(); curl_setopt($this->curl, CURLOPT_HEADER, false); 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);
     }
    

    } }

/**

  • Quries the CardDAV server via curl and returns the response

  • @param string $url CardDAV server URL

  • @param string $method HTTP-Method like (OPTIONS, GET, HEAD, POST, PUT, DELETE, TRACE, COPY, MOVE)

  • @param string $content Content for CardDAV queries

  • @param string $content_type Set content type

  • @param boolean $return_boolean Return just a boolean

  • @return string CardDAV XML response */ private function query($url, $method, $content = null, $content_type = null, $return_boolean = false) { $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()); }

    $response = curl_exec($this->curl); $http_code = curl_getinfo($this->curl, CURLINFO_HTTP_CODE);

    if (in_array($http_code, array(200, 207))) { return ($return_boolean === true ? true : $response); } else if ($return_boolean === true && in_array($http_code, array(201, 204))) { return true; } else { return false; } }

/**

  • Returns a valid and unused vCard id

  • @return string Valid vCard id */ private function generate_vcard_id() { $id = null;

    for ($number = 0; $number <= 25; $number ++) { if ($number == 8 || $number == 17) { $id .= '-'; } else { $id .= $this->vcard_id_chars[mt_rand(0, (count($this->vcard_id_chars) - 1))]; } }

    $carddav = new carddav_backend($this->url); $carddav->set_auth($this->username, $this->password);

    if ($carddav->query($this->url . $id . '.vcf', 'GET', null, null, true)) { return $this->generate_vcard_id(); } else { return $id; } }

/**

  • Destructor
  • Close curl connection if it's open
  • @return void */ public function __destruct() { if (!empty($this->curl)) { curl_close($this->curl); } }

}

On Feb 1, 2013, at 10:33 AM, bryan977 [email protected] wrote:

> Have anyone got this plugin working on Mountain Lion? I've tried the fixes in #29 and #36; however, I still have problems. I still receive the "ardDAV-Server XML-Response is malformed. Synchronization aborted!" error. Thanks so much!
> 
> —
> Reply to this email directly or view it on GitHub.

niwrik avatar Feb 01 '13 15:02 niwrik

Thank you niwrik! I'll give this a try. I've been using Kerio Connect for the last several years, but, was considering going the "free" route and using the butil-in services to ML. This is just my home personal email server for family and friends, so, I can be pretty nimble. Thanks so much!

bryan977 avatar Feb 01 '13 16:02 bryan977

has anyone managed to get CardDAV working with Mountain Lion Server (10.8.2) and RoundCube 0.8.5? I can add the server but then on sync it just says:

"an error occurred while synchronizing the CardDave contacts"

any pointers?

benjennings avatar Mar 01 '13 19:03 benjennings

I have not. I am hoping, at some point, someone smarter than I can make it work and share. Or, the connector is updated to work with ML Server.

bryan977 avatar Mar 01 '13 19:03 bryan977

hey @bryan977 thanks for getting back - glad it's not just me! so any genius out there with a solution? :)

benjennings avatar Mar 01 '13 20:03 benjennings

Have you tried using another CardDav service like Radicale? There is a repo on Github. I haven't used it with Mountain Lion, but its a pretty lightweight python application that works behind Apache or on its on. I have it working with RoundCube.

hscissors avatar Mar 02 '13 00:03 hscissors

@hscissors thanks for the pointer - but it would be great if it were possible to get CardDAV working with a default Mountain Lion Server install :)

benjennings avatar Mar 03 '13 13:03 benjennings

I had a request this morning to get carddav working on roundcube at the office. I hadn't gotten back to this since my earlier post, as I'd never bothered to restore the configuration following my move from postgres to mysql for the roundcube db. Again, I ran into the same problems as above. Luckily, I had made a backup of the working plugin folder, and restored it to my current config. Confirmed working on 10.8.2 - I have no idea which files were modified to make it work, but I can post the folder in .zip format somewhere if anyone wants to try it out in their deployment.

niwrik avatar Jun 17 '13 14:06 niwrik

I would be interested in that.

bpwats avatar Jun 23 '13 00:06 bpwats

@bpwats Send me a message and I'll send you a link. My public e-mail address is now published.

niwrik avatar Jun 24 '13 17:06 niwrik

Hello Everyone. I have this running on OSX 10.8.2 Server 2.2.1 with RC 0.8.2. I found the solution here: https://github.com/graviox/Roundcube-CardDAV/issues/36 (about half-way down the page)

In carddav_backend.php replace the following line:

$response = $this->query($this->url, 'PROPFIND');

with this: screen shot 2013-06-26 at 2 27 04 pm

niwrik avatar Jun 26 '13 18:06 niwrik

Hello You can modify in the carddav_backend.php the auth type. I had the same problem of XML because the response is empty. change this line curl_setopt($this->curl, CURLOPT_HTTPAUTH, CURLAUTH_ANY); by curl_setopt($this->curl, CURLOPT_HTTPAUTH, CURLAUTH_DIGEST); the url : https://xxxxx:8843/addressbooks/users/[username]/addressbook/ For me it's working. Is it possible to add a DropDownList to configure the server like calendar.

sylvestrerd avatar Sep 09 '13 06:09 sylvestrerd