Carddav & Caldav

Sun 07 September 2014

In tech.

CardDav

Importer un vcard vers Carddav

Après avoir installé le serveur, il faut le peupler. Soit on envoie les contacts individuellement soit on importe un carnet d'adresse déjà existant.

On commence par récupérer notre carnet d'adresses au format vcard. C'est un fait un fichier contenant des contacts au format vcard les uns au dessous des autres. Pour l'envoyer sur notre serveur, il suffit juste de découper chaque contact, d'y ajouter un UID si nécessaire et de l'envoyer via un PUT HTTP. Le script suivant fait l'affaire:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
#!/bin/env python
import sys
import urllib.request
import uuid

# On découpe le fichier source pour extraire chaque contact
def split_vcf(filename):
    try:
        fd = open(filename, 'r')
    except:
        sys.exit("Unable to open vcard file: %s" % filename)

    START_LINE = "BEGIN:VCARD"
    END_LINE = "END:VCARD"

    card = None

    for line in fd:
        sline = line.strip()
        if card == None:
            if sline == START_LINE:
                card = line
        else:
            if sline == END_LINE:
                card += line
                yield card
                card = None
            else:
                card += line

    fd.close()

# On récupère l'UID s'il existe, sinon on en ajoute un
def add_uid(card):
    lines = card.split("\n")
    uid = None
    for line in lines:
        if line.strip().startswith("UID"):
            uid = line.strip()[4:]
            break

    if not uid:
        uid = str(uuid.uuid4())
        lines.insert(2, "UID:%s" % uid)
        card = "\n".join(lines)

    return card, uid

# On envoie le contact via PUT HTTP
def put_vcard(collection, card, uid, auth):
    url = collection + uid + ".vcf"

    headers = {"Authorization": auth,
               "Content-type": "text/vcard"}

    req = urllib.request.Request(url=url,
            data=bytes(card, 'utf-8'),
            method='PUT',
            headers=headers)
    try:
        result = urllib.request.urlopen(req)
        if result.status != 201:
           return result.reason 
    except:
        return "Exception thrown"


if __name__=="__main__":
    if len(sys.argv) < 2:
        sys.exit("Usage: %s <filename>" % sys.argv[0])
    filename = sys.argv[1]

    for card in split_vcf(filename):
        card, uid = add_uid(card)
        print(card)
        res = put_vcard("https://dav.duraffourg.eu/f/Contacts.vcf/", card, uid, "Basic ZjpPVkhQb21tZQ==")
        if res:
            print("Failed to put the following card because '%s':\n%s\n\n" % (res, card))
        print("-> OK\n")