Hi all Some while ago, Shu-Hao Chang posted a link to his utility vcf2ldap: http://www.linux.org.tw/~shchang/vcf2ldif/vcf2ldif.tgz Yesterday, I played with it and improved a bit. I use it for transferring contacts from my Nokia 7650 (with SuperVCard preparing .vcf files) to openldap server. New features: 1. "Smart" processing of inetOrgPerson and organization objects. 2. Abiliby to use UID field (for object dn and attributs) 3. Strict compliance to ldap schemas (cross-related to #1) 4. Ability to convert photos in base64 format. I attach the patch - hope someone will find it useful (and hope 7K will not create me bad fame here). Cheers, -- Sergey
diff -u vcf2ldif/vcf2ldif.c vcf2ldif.svu/vcf2ldif.c --- vcf2ldif/vcf2ldif.c 2000-05-11 02:19:17.000000000 +0100 +++ vcf2ldif.svu/vcf2ldif.c 2003-06-03 11:49:02.000000000 +0100 @@ -13,13 +13,91 @@ return 0; s = fakeCString(vObjectUStringZValue(p)); - if (name && s) { + if (name && s && (s[0]!='\0')) { fprintf(stdout, "%s%s%s", name, sp, s); return 1; } return 0; } +int present2c(VObject* o, const char* pid, const char* cid) +{ + VObject* parent; + VObject* p; + char* s; + + if (!(parent=(VObject*)isAPropertyOf(o, pid))) + return 0; + if (!(p=(VObject*)isAPropertyOf(parent, cid))) + return 0; + s = fakeCString(vObjectUStringZValue(p)); + return (s && (s[0] != '\0')); +} + +void dumpBase64(unsigned const char *s, long len) +{ + long cur = 0; + int i, numQuads = 0; + unsigned long trip; + unsigned char b; + char quad[5]; +#define MAXQUADS 16 + + quad[4] = 0; + + while (cur < len) { + // collect the triplet of bytes into 'trip' + trip = 0; + for (i = 0; i < 3; i++) { + b = (cur < len) ? *(s + cur) : 0; + cur++; + trip = trip << 8 | b; + } + // fill in 'quad' with the appropriate four characters + for (i = 3; i >= 0; i--) { + b = (unsigned char)(trip & 0x3F); + trip = trip >> 6; + if ((3 - i) < (cur - len)) + quad[i] = '='; // pad char + else if (b < 26) quad[i] = (char)b + 'A'; + else if (b < 52) quad[i] = (char)(b - 26) + 'a'; + else if (b < 62) quad[i] = (char)(b - 52) + '0'; + else if (b == 62) quad[i] = '+'; + else quad[i] = '/'; + } + // now output 'quad' with appropriate whitespace and line ending + fprintf(stdout, (numQuads == 0 ? " " : "")); + fprintf(stdout, quad); + fprintf(stdout, ((cur >= len)?"\n" :(numQuads==MAXQUADS-1?"\n" : ""))); + numQuads = (numQuads + 1) % MAXQUADS; + } + fprintf(stdout,"\n"); +} + +int generate64(const char* name, + VObject* o, const char* id) +{ + VObject* p; + VObject* lp; + void* s; + long l; + + if (!(p=(VObject*)isAPropertyOf(o, id))) + return 0; + + if (name) { + s = vObjectAnyValue(p); + lp=(VObject*)isAPropertyOf(p, VCDataSizeProp); + l = vObjectLongValue(lp); + if (s) { + fprintf(stdout, "%s::", name); + dumpBase64((const char*)s,l); + return 1; + } + } + return 0; +} + int generate2c(const char* name, const char* sp, VObject* o, const char* pid, const char* cid) { @@ -32,7 +110,7 @@ if (!(p=(VObject*)isAPropertyOf(parent, cid))) return 0; s = fakeCString(vObjectUStringZValue(p)); - if (name && s) { + if (name && s && (s[0] != '\0')) { fprintf(stdout, "%s%s%s", name, sp, s); return 1; } @@ -43,6 +121,7 @@ VObject* o, const char* pid, const char* cid) { VObjectIterator i; + int rv = 0; initPropIterator(&i, o); while (moreIteration(&i)) { VObject* p = nextVObject(&i); @@ -51,13 +130,16 @@ if ((VObject*)isAPropertyOf(p, cid)) { char* s = fakeCString(vObjectUStringZValue(p)); - if (name && s) { + if (name && s && (s[0]!= '\0') ) { + if ( rv == 1 ) + fprintf(stdout, "\n" ); fprintf(stdout, "%s%s%s", name, sp, s); - return 1; +// return 1; + rv = 1; } } } - return 0; + return rv; } /* @@ -65,6 +147,7 @@ */ const char* cs = ": "; const char* eq = "="; +const char* uid = "uid"; const char* givenname = "givenname"; const char* sn = "sn"; const char* cn = "cn"; @@ -83,21 +166,37 @@ const char* homephone = "homephone"; const char* facsimiletelephonenumber = "facsimiletelephonenumber"; const char* pagerphone = "pagerphone"; -const char* cellphone = "cellphone"; +const char* mobile = "mobile"; const char* homeurl = "homeurl"; +const char* jpegPhoto = "jpegPhoto"; void print_ldif(VObject* v, char* suffix) { + int isPerson = 0; + int isOrg = 0; + int hasUid = 1; fprintf(stdout, "dn: "); - if (!generate(cn, eq, v, VCFullNameProp)) { - /* - * if vCard file don't have FN(fullname) - * use givename & sn to generate fullname - */ - if (generate2c(givenname, eq, v, VCNameProp, VCGivenNameProp)) - fprintf(stdout, " "); - if (generate2c(sn, eq, v, VCNameProp, VCFamilyNameProp)) - fprintf(stdout, " "); + if (!generate(uid, eq, v, VCUniqueStringProp)) { + hasUid = 0; + if (!generate(cn, eq, v, VCFullNameProp)) { + /* + * if vCard file don't have FN(fullname) + * use givename & sn to generate fullname + */ + if (generate2c(givenname, eq, v, VCNameProp, VCGivenNameProp)) + { + isPerson = 1; + fprintf(stdout, " "); + if (generate2c(sn, eq, v, VCNameProp, VCFamilyNameProp)) + fprintf(stdout, " "); + } else + if (generate2c(o, eq, v, VCOrgProp, VCOrgNameProp)) + { + isOrg = 1; + fprintf(stdout, " "); + } + } } + if (suffix) fprintf(stdout, ", %s", suffix); fprintf(stdout, "\n"); @@ -105,7 +204,22 @@ fprintf(stdout, "objectClass: top"); fprintf(stdout, "\n"); - fprintf(stdout, "objectClass: person"); + if (hasUid) + { + fprintf(stdout, "objectClass: uidObject"); + fprintf(stdout, "\n"); + } + + if (present2c(v, VCNameProp, VCGivenNameProp)) + { + isPerson = 1; + } + if (present2c(v, VCOrgProp, VCOrgNameProp)) + { + isOrg = 1; + } + + fprintf(stdout, "objectClass: %s", isPerson ? "inetOrgPerson" : isOrg ? "organization" : "GK" ); fprintf(stdout, "\n"); if (generate2c(givenname, cs, v, VCNameProp, VCGivenNameProp)) @@ -113,12 +227,24 @@ if (generate2c(sn, cs, v, VCNameProp, VCFamilyNameProp)) fprintf(stdout, "\n"); + else + if (isPerson) + fprintf(stdout, "%s%s%s\n", sn, cs, "???"); - if (generate(cn, cs, v, VCFullNameProp)) + if (generate(uid, cs, v, VCUniqueStringProp)) fprintf(stdout, "\n"); - if (generate2p(mail, cs, v, VCEmailAddressProp, VCInternetProp)) + if (generate(cn, cs, v, VCFullNameProp)) fprintf(stdout, "\n"); + else + if (isPerson) + { + generate2c(cn, cs, v, VCNameProp, VCGivenNameProp); + if (generate2c("", " " , v, VCNameProp, VCFamilyNameProp)) + fprintf(stdout, "\n"); + else + fprintf(stdout, "%s%s%s\n", "", " ", "???"); + } /* xmozillanickname no match */ @@ -160,8 +286,22 @@ if (generate2p(pagerphone, cs, v, VCTelephoneProp, VCPagerProp)) fprintf(stdout, "\n"); - if (generate2p(cellphone, cs, v, VCTelephoneProp, VCCellularProp)) - fprintf(stdout, "\n"); + if (isOrg) + { + if (generate2p(telephonenumber, cs, v, VCTelephoneProp, VCCellularProp)) + fprintf(stdout, "\n"); + } + if (isPerson) + { + if (generate2p(mail, cs, v, VCEmailAddressProp, VCInternetProp)) + fprintf(stdout, "\n"); + + if (generate2p(mobile, cs, v, VCTelephoneProp, VCCellularProp)) + fprintf(stdout, "\n"); + + if (generate64(jpegPhoto, v, VCPhotoProp)) + fprintf(stdout, "\n"); + } if (generate(homeurl, cs, v, VCURLProp)) fprintf(stdout, "\n");
Attachment:
signature.asc
Description: =?koi8-r?Q?=FC=D4=C1?= =?koi8-r?Q?_=DE=C1=D3=D4=D8?= =?koi8-r?Q?_=D3=CF=CF=C2=DD=C5=CE=C9=D1?= =?koi8-r?Q?_=D0=CF=C4=D0=C9=D3=C1=CE=C1?= =?koi8-r?Q?_=C3=C9=C6=D2=CF=D7=CF=CA?= =?koi8-r?Q?_=D0=CF=C4=D0=C9=D3=D8=C0?=