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?=