1

Searched thru serverfault.com, stackoverflow.com, apple.stackexchange.com, googled and still not getting far. Need someone to help.

I'm trying to get all vCards from iCloud accounts.

I'm starting from the plugin from Roundcube/CardDav.

From the articles such as:

stackoverflow.com/questions/24202551/manipulate-groups-in-icloud-with-carddav-protocol sabre.io/dav/building-a-carddav-client/ sabre.io/dav/clients/osx-addressbook/ stackoverflow.com/questions/15111887/how-to-import-icloud-contacts-in-php# tools.ietf.org/html/rfc6352#section-8.7.1

I managed to get the Principal, the Principal's address. But the last step of getting the card returns ContentLength of 0.

Here is what I do:

- use icloud email as username
- use icloud password

To get the Principal, using "https : / / contacts.icloud.com/" as URL, PROPFIND, DEPTH 0:

<?xml version="1.0" encoding="UTF-8"?> 
    <d:propfind xmlns:d="DAV:">  
        <d:prop>   
        <d:current-user-principal/>  
        </d:prop> 
    </d:propfind> 

Response:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?> 
    <multistatus xmlns="DAV:">  
        <response>      
            <href>/</href>                      
            <propstat>              
                <prop>                                                                        
                    <current-user-principal>
                        <href>/1331115018/principal/</href>
                    </current-user-principal>                                                               
                </prop>             
                <status>HTTP/1.1 200 OK</status>        
            </propstat>     
        </response> 
    </multistatus>

Next, here is what I do to get the home, using "https : / /contacts.icloud.com/1331115018/principal/", PROPFIND, DEPTH 0:

<?xml version="1.0" encoding="UTF-8"?> 
    <d:propfind xmlns:d="DAV:" xmlns:card="urn:ietf:params:xml:ns:carddav">  
        <d:prop>   
            <card:addressbook-home-set/>  
        </d:prop> 
    </d:propfind>

Response:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?> 
    <multistatus xmlns="DAV:">  
        <response>      
            <href>/1331115018/principal/</href>                     
            <propstat>              
                <prop>                                                                           
                    <addressbook-home-set xmlns="urn:ietf:params:xml:ns:carddav">
                        <href xmlns="DAV:">https://p44-contacts.icloud.com:443/1331115018/carddavhome/</href>
                    </addressbook-home-set>                                                             
                </prop>             
            <status>HTTP/1.1 200 OK</status>        
            </propstat>     
        </response> 
    </multistatus>

Finally, here is what I do to try to get all the vCards, using https : / / p44-contacts.icloud.com:443/1331115018/carddavhome/, REPORT, DEPTH 1:

<?xml version="1.0" encoding="utf-8" ?>    
<C:addressbook-multiget xmlns:D="DAV:" xmlns:C="urn:ietf:params:xml:ns:carddav">      
    <D:prop>        
    <D:getetag/>        
        <C:address-data>          
        <C:prop name="UID"/>          
        <C:prop name="EMAIL"/>          
        <C:prop name="FN"/>        
        </C:address-data>      
    </D:prop>    
</C:addressbook-multiget>

Response:

<?xml version="1.0" encoding="UTF-8"?> 
    <multistatus xmlns="DAV:" xmlns:CD="urn:ietf:params:xml:ns:carddav" xmlns:CS="http://calendarserver.org/ns/">  
    </multistatus>

or

<?xml version="1.0" encoding="utf-8" ?>
<C:addressbook-query xmlns:D="DAV:" xmlns:C="urn:ietf:params:xml:ns:carddav">      
    <D:prop>        
    <D:getetag/>        
        <C:address-data>          
        <C:prop name="UID"/>          
        <C:prop name="EMAIL"/>          
        <C:prop name="FN"/>        
        </C:address-data>      
    </D:prop>    
</C:addressbook-query>

Response:

<?xml version="1.0" encoding="UTF-8"?> 
<multistatus xmlns="DAV:" xmlns:CD="urn:ietf:params:xml:ns:carddav" xmlns:CS="http://calendarserver.org/ns/">  
    <response>     
        <href>/1331115018/carddavhome/</href>                   
        <propstat>                  
            <prop>                                                                                      <getetag>"C=0@U=9123588c-8038-439c-a547-19c866d1ed06"</getetag>                                                                                                                 
            <address-data xmlns="urn:ietf:params:xml:ns:carddav">
            </address-data>                                                                         
            </prop>                     
        <status>HTTP/1.1 200 OK</status>                
        </propstat>              
    </response>   
</multistatus> 

or

<?xml version="1.0" encoding="utf-8" ?>
<C:addressbook-query xmlns:D="DAV:" xmlns:C="urn:ietf:params:xml:ns:carddav">      
    <D:prop>        
    <D:getetag/>        
        <C:address-data>          
        <C:prop name="UID"/>          
        <C:prop name="EMAIL"/>          
        <C:prop name="FN"/>        
        </C:address-data>      
    </D:prop>      
    <C:prop-filter name="EMAIL">          
        <C:text-match collation="i;unicode-casemap" match-type="equals">me</C:text-match>        
        </C:prop-filter>      
    </C:filter>    
</C:addressbook-query>

Response:

"Didn't understand the report"

What do I have to do?

FelixSFD
  • 6,052
  • 10
  • 43
  • 117
charleslcso
  • 182
  • 1
  • 1
  • 16

3 Answers3

1

The CardDAV home (your https://p44-contacts.icloud.com:443/1331115018/carddavhome/) contains the CardDAV collections (aka the 'address books'), not the vCards (which contain contacts and contact groups). You need to take one more hop.

You can list the addressbook collections in the home using a regular PROPFIND Depth 1 and then query those for the contacts with the report you specify. Like so:

PROPFIND /1331115018/carddavhome/ HTTP/1.1
Depth: 1
Host: p44-contacts.icloud.com:443
Authorization: ...
Content-Type: text/xml; charset=utf-8
Content-Length: ...

<propfind xmlns="DAV:">
  <prop>
    <displayname />
    <resourcetype />
  </prop>
</propfind>

This returns you the list of all sub-collections in the CardDAV home collection.

The collections which have an addressbook resourcetype are CardDAV addressbook collections and can be queried using an addressbook-query or addressbook-multiget report, using a sync-report if that is supported (iCloud does) or again using a simple PROPFIND. Depends on what you want.

Given an address book collection URL a 'real' client would usually use a sync-report to grab the URLs of all changed objects if the server supports that, or just grab the URLs, Content-Type and ETags of all contained vCards using a PROPFIND as a fallback. For example:

PROPFIND /1331115018/carddavhome/contacts/ HTTP/1.1
Depth: 1
Host: p44-contacts.icloud.com:443
Authorization: ...
Content-Type: text/xml; charset=utf-8
Content-Length: ...

<propfind xmlns="DAV:">
  <prop>
    <getetag />
    <getcontenttype />
  </prop>
</propfind>

This gives you the URLs of all objects in the address book collection. Which you can then retrieve using simple GETs or a multiget REPORT.

BTW: In your addressbook-multiget REPORT you do not list any vCard URLs, hence the result set will always be empty ... You can read about multiget in RFC 6352.

Note: In iCloud there is usually just one addressbook collection in the home, but in other servers it is quite common to have multiple. Also in some servers the CalDAV and CardDAV homes are the same collection (i.e. remember to actually check the resourcetype of the sub-collections in the respective home collections).

This is a great introduction on CardDAV: Building a CardDAV client. Or this one on YouTube: FOSDEM 2009 CalDAV.

Community
  • 1
  • 1
hnh
  • 13,957
  • 6
  • 30
  • 40
0

<card:addressbook-multiget xmlns:d="DAV:" xmlns:card="urn:ietf:params:xml:ns:carddav">
<d:prop>
        <d:getetag />
        <card:address-data />
    </d:prop>
    <d:href>/1331115018/carddavhome/card/vcard_UUID.vcf</d:href>
</card:addressbook-multiget>

Let try this in the REPORT Request.

HaiN
  • 917
  • 11
  • 31
-1

Getting your credentials: https://github.com/muhlba91/icloud/blob/master/groovy_java/gui-2.1.0.zip! Keep in mind: https://support.apple.com/en-us/HT204397

Getting your vCards: https://github.com/andig/carddav2fb - just use the download command: php carddav2fb download yourdownload.vcf

Black Senator
  • 449
  • 3
  • 11