[Date Prev][Date Next] [Chronological] [Thread] [Top]

vCard to LDIF translator



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