christian-putzke / CardDAV-PHP

A cardDAV PHP-Class
http://www.graviox.de/
GNU Affero General Public License v3.0
98 stars 47 forks source link

Works good with SOGo, SabreDAV fix for simplify() method #13

Open user678 opened 12 years ago

user678 commented 12 years ago

Hi,

SOGo catalog list for simplify:

<?xml version="1.0" encoding="utf-8" ?> 
- <D:multistatus xmlns:ap="http://apache.org/dav/props/" xmlns:D="DAV:">
- <D:response>
  <D:href>/SOGo/dav/sogo1/Contacts/</D:href> 
- <D:propstat>
  <D:status>HTTP/1.1 200 OK</D:status> 
- <D:prop>
  <D:getlastmodified>Mon, 25 Jun 2012 08:45:47 -0400</D:getlastmodified> 
  <D:getetag>"None"</D:getetag> 
- <D:resourcetype>
  <D:collection /> 
  </D:resourcetype>
  <D:getcontenttype>httpd/unix-directory</D:getcontenttype> 
  <D:displayname>Contacts</D:displayname> 
  <D:href>/SOGo/dav/sogo1/Contacts/</D:href> 
  <ap:executable>0</ap:executable> 
  </D:prop>
  </D:propstat>
  </D:response>
+ <D:response>
  <D:href>/SOGo/dav/sogo1/Contacts/personal/</D:href> 
- <D:propstat>
  <D:status>HTTP/1.1 200 OK</D:status> 
- <D:prop>
  <D:getlastmodified>Mon, 25 Jun 2012 08:45:47 -0400</D:getlastmodified> 
  <D:getetag>"None"</D:getetag> 
- <D:resourcetype>
  <D:collection /> 
  <vcard-collection xmlns="http://groupdav.org/" /> 
  <addressbook xmlns="urn:ietf:params:xml:ns:carddav" /> 
  </D:resourcetype>
  <D:getcontenttype>httpd/unix-directory</D:getcontenttype> 
  <D:displayname>Hermeegille</D:displayname> 
  <D:href>/SOGo/dav/sogo1/Contacts/personal/</D:href> 
  <ap:executable>0</ap:executable> 
  </D:prop>
  </D:propstat>
  </D:response>
  </D:multistatus>

produces this output:

<?xml version="1.0" encoding="UTF-8" ?> 
- <response>
- <addressbook_element>
  <display_name>Contacts</display_name> 
  <url>http://sogo-demo.inverse.ca/SOGo/dav/sogo1/Contacts/</url> 
  <last_modified>Mon, 25 Jun 2012 08:45:47 -0400</last_modified> 
  </addressbook_element>
- <addressbook_element>
  <display_name>Hermeegille</display_name> 
  <url>http://sogo-demo.inverse.ca/SOGo/dav/sogo1/Contacts/personal/</url> 
  <last_modified>Mon, 25 Jun 2012 08:45:47 -0400</last_modified> 
  </addressbook_element>

SabreDAV returns list folders in following format:

  <?xml version="1.0" encoding="utf-8" ?> 
- <d:multistatus xmlns:d="DAV:" xmlns:s="http://sabredav.org/ns" xmlns:cal="urn:ietf:params:xml:ns:caldav" xmlns:cs="http://calendarserver.org/ns/" xmlns:card="urn:ietf:params:xml:ns:carddav">
- <d:response>
  <d:href>/trunk/dav.php/addressbooks/test%40localhost/</d:href> 
- <d:propstat>
- <d:prop>
- <d:resourcetype>
  <d:collection /> 
  </d:resourcetype>
  </d:prop>
  <d:status>HTTP/1.1 200 OK</d:status> 
  </d:propstat>
  </d:response>
- <d:response>
  <d:href>/trunk/dav.php/addressbooks/test%40localhost/Default/</d:href> 
- <d:propstat>
- <d:prop>
- <d:resourcetype>
  <d:collection /> 
  <card:addressbook /> 
  </d:resourcetype>
  </d:prop>
  <d:status>HTTP/1.1 200 OK</d:status> 
  </d:propstat>
  </d:response>
+ <d:response>
  <d:href>/trunk/dav.php/addressbooks/test%40localhost/Collected/</d:href> 
- <d:propstat>
- <d:prop>
- <d:resourcetype>
  <d:collection /> 
  <card:addressbook /> 
  </d:resourcetype>
  </d:prop>
  <d:status>HTTP/1.1 200 OK</d:status> 
  </d:propstat>
  </d:response>
  </d:multistatus>

simplify() returns empty node. You may add the following fix:


    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();
                    }
                    else // fix here
                    {
                        if (isset($response->href))
                        {
                            $href = $response->href;

                          $url = str_replace($this->url_parts['path'], null, $this->url) . $href;
                          $simplified_xml->startElement('addressbook_element');
                          $simplified_xml->writeElement('display_name', $href);
                          $simplified_xml->writeElement('url', $url);
                          $simplified_xml->endElement();

                        }                        
                    }
                }

            $simplified_xml->endElement();
        $simplified_xml->endDocument();

        return $simplified_xml->outputMemory();
    }
xbgmsharp commented 12 years ago

The 'else // fix here' is not a good enough condition to be consider as a vcard list. The check should :

else if (preg_match('/x-vlist/', $response->propstat->prop->getcontenttype))

However the extension is not the same now ie: '.vlf' So it still won't work but it is a start.

user678 commented 12 years ago

It is possible only to check <card:addressbook /> empty node?

hhfeuer commented 12 years ago

i've fixed it like that: -else if (preg_match('/unix-directory/', $response->propstat->prop->getcontenttype)) +else if ($response->propstat->prop->resourcetype->addressbook->getName()=="addressbook")

and in private function clean_response($response) { $response = utf8_encode($response); $response = str_replace('card:', null, $response); $response = str_replace('D:', null, $response);

Maybe a combination of preg_match and getName would be better?

xbgmsharp commented 11 years ago

I implement it in commit https://github.com/xbgmsharp/sogosync/commit/88febac5c886d66f539041a248bf715cfcb0b7a8