summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorniko <niko>2012-10-07 12:07:27 (GMT)
committerniko <niko>2012-10-07 12:07:27 (GMT)
commit131a82456a97a057dd16942e4201314f58c4dcfc (patch)
tree03698c3b68e5a64067bbc6efae1968b6048e07b7
parent1b345176e3942b5909862878e772bfe83b6c9f94 (diff)
downloadsynckolab-131a82456a97a057dd16942e4201314f58c4dcfc.tar.gz
kolab3 vcard format writing
-rw-r--r--src/chrome/content/synckolab/addressbookTools.js461
-rw-r--r--src/chrome/content/synckolab/tools/text.js8
-rw-r--r--test/suite.js4
-rw-r--r--test/synckolab/parser/kolab2/contactTest.js2
-rw-r--r--test/synckolab/parser/kolab3/contactTest.js10
-rw-r--r--test/synckolab/parser/kolab3/json/complex.vcf.mime.json9
-rw-r--r--test/synckolab/parser/kolab3/json/simple.vcf.mime.json2
-rw-r--r--test/synckolab/parser/kolab3/raw/complex.vcf.mime1
-rw-r--r--test/synckolab/tools/textTest.js6
9 files changed, 430 insertions, 73 deletions
diff --git a/src/chrome/content/synckolab/addressbookTools.js b/src/chrome/content/synckolab/addressbookTools.js
index a88e322..cc2a6a3 100644
--- a/src/chrome/content/synckolab/addressbookTools.js
+++ b/src/chrome/content/synckolab/addressbookTools.js
@@ -552,7 +552,8 @@ synckolab.addressbookTools.findCard = function (cards, vId, directory) {
/**
* Tools to work with the address book. Parsing functions for vcard, Kolab xml
* to and from contact plus some utility functions.
- *
+ * This function autodetects kolab2/kolab3 format
+ *
* @param xml a dom node of a card or a string with the xml
* @param card the card object to update
*/
@@ -631,7 +632,8 @@ synckolab.addressbookTools.xml2Card = function (xml, card) {
var found = false;
var tok; // for tokenizer
var email = 0;
- var num; // temp
+ var where, types; // for type resolution (phone/address)
+ var value; // temp
while (cur) {
if (cur.nodeType === Node.ELEMENT_NODE)//1
@@ -647,6 +649,11 @@ synckolab.addressbookTools.xml2Card = function (xml, card) {
// kolab2: directly
if(uid === "") {
uid = cur.getFirstData();
+ } else {
+ // remove the urn:uuid prefix
+ if(uid.indexOf("urn:uuid:") !== -1) {
+ uid = uid.substring(9);
+ }
}
this.setUID(card, uid);
break;
@@ -702,30 +709,8 @@ synckolab.addressbookTools.xml2Card = function (xml, card) {
this.setCardProperty(card, "DisplayName", cur.getFirstData());
break;
- // set the prefer mail format (this is not covered by kolab itself)
- case "PREFER-MAIL-FORMAT":
- // 0: unknown
- // 1: plaintext
- // 2: html
- var format = cur.getFirstData().toUpperCase();
- this.setCardProperty(card, "PreferMailFormat", synckolab.addressbookTools.MAIL_FORMAT_UNKNOWN);
- switch (format) {
- case 'PLAINTEXT':
- case 'TEXT':
- case 'TXT':
- case 'PLAIN':
- case '1':
- this.setCardProperty(card, "PreferMailFormat", synckolab.addressbookTools.MAIL_FORMAT_PLAINTEXT);
- break;
- case 'HTML':
- case 'RICHTEXT':
- case 'RICH':
- case '2':
- this.setCardProperty(card, "PreferMailFormat", synckolab.addressbookTools.MAIL_FORMAT_HTML);
- }
- break;
-
- case "JOB-TITLE":
+ case "TITLE": // kolab3
+ case "JOB-TITLE": // kolab2
if (cur.firstChild === null) {
break;
}
@@ -733,8 +718,8 @@ synckolab.addressbookTools.xml2Card = function (xml, card) {
found = true;
break;
- case "NICKNAME":
- case "NICK-NAME":
+ case "NICKNAME": // kolab3
+ case "NICK-NAME": // kolab2
if (cur.firstChild === null) {
break;
}
@@ -785,13 +770,13 @@ synckolab.addressbookTools.xml2Card = function (xml, card) {
case "TEL": // kolab3
- num = cur.getFirstData();
+ value = cur.getFirstData();
// figure out the right type
var type = 0; // 0 = phone; 1 = mobile; 2 = fax;
- var where = 0; // 0 = default; 1 = home; 2 = work
+ where = 0; // 0 = default; 1 = home; 2 = work
- var types = cur.getChildNode("parameters");
+ types = cur.getChildNode("parameters");
if(types) {
types = types.getChildNode("type");
if(types) {
@@ -818,21 +803,21 @@ synckolab.addressbookTools.xml2Card = function (xml, card) {
switch(where) {
case 0: // def
case 1: // home
- this.setCardProperty(card, "HomePhone", num);
+ this.setCardProperty(card, "HomePhone", value);
break;
case 2: // work
- this.setCardProperty(card, "WorkPhone", num);
+ this.setCardProperty(card, "WorkPhone", value);
break;
}
break;
case 1: // cell
- this.setCardProperty(card, "CellularNumber", num);
+ this.setCardProperty(card, "CellularNumber", value);
break;
case 2: // fax
- this.setCardProperty(card, "FaxNumber", num);
+ this.setCardProperty(card, "FaxNumber", value);
break;
case 3:
- this.setCardProperty(card, "PagerNumber", num);
+ this.setCardProperty(card, "PagerNumber", value);
break;
}
found = true;
@@ -840,30 +825,30 @@ synckolab.addressbookTools.xml2Card = function (xml, card) {
case "PHONE": // kolab2
- num = cur.getXmlResult("NUMBER", "");
+ value = cur.getXmlResult("NUMBER", "");
switch (cur.getXmlResult("TYPE", "CELLULAR").toUpperCase()) {
case "MOBILE":
case "CELLULAR":
- this.setCardProperty(card, "CellularNumber", num);
+ this.setCardProperty(card, "CellularNumber", value);
break;
case "HOME":
case "HOME1":
- this.setCardProperty(card, "HomePhone", num);
+ this.setCardProperty(card, "HomePhone", value);
break;
case "FAX":
case "BUSINESSFAX":
- this.setCardProperty(card, "FaxNumber", num);
+ this.setCardProperty(card, "FaxNumber", value);
break;
case "BUSINESS":
case "BUSINESS1":
- this.setCardProperty(card, "WorkPhone", num);
+ this.setCardProperty(card, "WorkPhone", value);
break;
case "PAGE":
- this.setCardProperty(card, "PagerNumber", num);
+ this.setCardProperty(card, "PagerNumber", value);
break;
default:
// remember other phone numbers
- this.setCardProperty(card, "PHONE_" + cur.getXmlResult("TYPE", "CELLULAR"), num, true);
+ this.setCardProperty(card, "PHONE_" + cur.getXmlResult("TYPE", "CELLULAR"), value, true);
break;
}
found = true;
@@ -892,7 +877,7 @@ synckolab.addressbookTools.xml2Card = function (xml, card) {
tok = synckolab.tools.text.string2DateTime(tok);
this.setCardProperty(card, "BirthYear", tok.getFullYear());
- this.setCardProperty(card, "BirthMonth", tok.getMonth());
+ this.setCardProperty(card, "BirthMonth", tok.getMonth()+1); // getMoth starts with jan=0
this.setCardProperty(card, "BirthDay", tok.getDate());
found = true;
break;
@@ -919,15 +904,15 @@ synckolab.addressbookTools.xml2Card = function (xml, card) {
tok = synckolab.tools.text.string2DateTime(tok);
this.setCardProperty(card, "AnniversaryYear", tok.getFullYear());
- this.setCardProperty(card, "AnniversaryMonth", tok.getMonth());
+ this.setCardProperty(card, "AnniversaryMonth", tok.getMonth()+1); // getMoth starts with jan=0
this.setCardProperty(card, "AnniversaryDay", tok.getDate());
found = true;
break;
case "ADR": // kolab3
// figure out the right type
- var where = 0; // 0 = default; 1 = home; 2 = work
- var types = cur.getChildNode("parameters");
+ where = 0; // 0 = default; 1 = home; 2 = work
+ types = cur.getChildNode("parameters");
if(types) {
types = types.getChildNode("type");
if(types) {
@@ -1041,7 +1026,7 @@ synckolab.addressbookTools.xml2Card = function (xml, card) {
if (cur.firstChild === null) {
break;
}
- var value = cur.getXmlResult("URI", "");
+ value = cur.getXmlResult("URI", "");
if(!card.WebPage1 || card.WebPage1 === "") {
this.setCardProperty(card, "WebPage1", value);
@@ -1070,56 +1055,111 @@ synckolab.addressbookTools.xml2Card = function (xml, card) {
found = true;
break;
- case "CUSTOM1":
+ case "IMPP": // kolab3
+ case "IM-ADDRESS": // kolab2
+ if (cur.firstChild === null) {
+ break;
+ }
+ this.setCardProperty(card, "AimScreenName", cur.getFirstData());
+ break;
+
+
+ case "CUSTOM1": // kolab2
if (cur.firstChild === null) {
break;
}
this.setCardProperty(card, "Custom1", cur.getFirstData());
break;
- case "CUSTOM2":
+ case "CUSTOM2": // kolab2
if (cur.firstChild === null) {
break;
}
this.setCardProperty(card, "Custom2", cur.getFirstData());
break;
- case "CUSTOM3":
+ case "CUSTOM3": // kolab2
if (cur.firstChild === null) {
break;
}
this.setCardProperty(card, "Custom3", cur.getFirstData());
break;
- case "CUSTOM4":
+ case "CUSTOM4": // kolab2
if (cur.firstChild === null) {
break;
}
this.setCardProperty(card, "Custom4", cur.getFirstData());
break;
- case "IMPP":
- case "IM-ADDRESS":
+ case "ALLOW-REMOTE-CONTENT": // kolab2
if (cur.firstChild === null) {
break;
}
- this.setCardProperty(card, "AimScreenName", cur.getFirstData());
+ this.setCardProperty(card, "AllowRemoteContent", 'TRUE' === cur.getFirstData().toUpperCase());
break;
- case "ALLOW-REMOTE-CONTENT":
- if (cur.firstChild === null) {
+ // set the prefer mail format (this is not covered by kolab itself)
+ case "PREFER-MAIL-FORMAT":
+ // 0: unknown
+ // 1: plaintext
+ // 2: html
+ var format = cur.getFirstData().toUpperCase();
+ this.setCardProperty(card, "PreferMailFormat", synckolab.addressbookTools.MAIL_FORMAT_UNKNOWN);
+ switch (format) {
+ case 'PLAINTEXT':
+ case 'TEXT':
+ case 'TXT':
+ case 'PLAIN':
+ case '1':
+ this.setCardProperty(card, "PreferMailFormat", synckolab.addressbookTools.MAIL_FORMAT_PLAINTEXT);
break;
+ case 'HTML':
+ case 'RICHTEXT':
+ case 'RICH':
+ case '2':
+ this.setCardProperty(card, "PreferMailFormat", synckolab.addressbookTools.MAIL_FORMAT_HTML);
}
- this.setCardProperty(card, "AllowRemoteContent", 'TRUE' === cur.firstChild.data.toUpperCase());
break;
-
+
case "X-CUSTOM": // kolab3
+ tok = cur.getXmlResult("identifier", "");
+ value = cur.getXmlResult("value", "");
+ switch(tok) {
+ case "X-AllowRemoteContent": this.setCardProperty(card, "AllowRemoteContent", 'TRUE' === value.toUpperCase()); break;
+ case "X-Custom1": this.setCardProperty(card, "Custom1", value); break;
+ case "X-Custom2": this.setCardProperty(card, "Custom2", value); break;
+ case "X-Custom3": this.setCardProperty(card, "Custom3", value); break;
+ case "X-Custom4": this.setCardProperty(card, "Custom4", value); break;
+ case "X-PreferMailFormat":
+ this.setCardProperty(card, "PreferMailFormat", synckolab.addressbookTools.MAIL_FORMAT_UNKNOWN);
+ switch(value.toUpperCase()) {
+ case 'PLAINTEXT':
+ case 'TEXT':
+ case 'TXT':
+ case 'PLAIN':
+ case '1':
+ this.setCardProperty(card, "PreferMailFormat", synckolab.addressbookTools.MAIL_FORMAT_PLAINTEXT);
+ break;
+ case 'HTML':
+ case 'RICHTEXT':
+ case 'RICH':
+ case '2':
+ this.setCardProperty(card, "PreferMailFormat", synckolab.addressbookTools.MAIL_FORMAT_HTML);
+ }
+ break;
+ default:
+ synckolab.tools.logMessage("X-CUSTOM not found: identifier:'" + tok + "' value='" + value+"'", synckolab.global.LOG_WARNING + synckolab.global.LOG_AB);
+ }
+
// dunno if we need to support this
break;
+
+
case "PHOTO": // kolab3
// handle photo VERY special... TODO
break;
case "GROUP":
- // should wehandle this?
+ // how is this handled?
break;
// fields we know and can skip
case "PRODID":
@@ -1130,7 +1170,6 @@ synckolab.addressbookTools.xml2Card = function (xml, card) {
// fields we "know" about but just cannot work with
case "RELATED": //kolab3
- case "TITLE":
case "CREATION-DATE":
case "LATITUDE":
case "LONGITUDE":
@@ -1211,6 +1250,77 @@ synckolab.addressbookTools.list2Pojo = function (card) {
return pojo;
};
+/**
+ * Creates xml (kolab2) out of a given card.
+ * The return is the xml as string.
+ * @param card nsIAbCard: the adress book list card
+ * @param fields Array: all the fields not being held in the default card
+ */
+synckolab.addressbookTools.list2Kolab3 = function (card, fields) {
+ var xml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
+ xml += "<vlist version=\"1.0\" >\n";
+ xml += " <product-id>SyncKolab, Kolab resource</product-id>\n";
+ xml += " <uid>" + this.getUID(card) + "</uid>\n";
+ xml += " <creation-date>" + synckolab.tools.text.date2String(new Date(this.getCardProperty(card, "LastModifiedDate") * 1000)) + "T" + synckolab.tools.text.time2String(new Date(this.getCardProperty(card, "LastModifiedDate") * 1000)) + "Z</creation-date>\n";
+ xml += " <last-modification-date>" + synckolab.tools.text.date2String(new Date(this.getCardProperty(card, "LastModifiedDate") * 1000)) + "T" + synckolab.tools.text.time2String(new Date(this.getCardProperty(card, "LastModifiedDate") * 1000)) + "Z</last-modification-date>\n";
+
+ // default: public - tbird doesnt know of other types of list like private
+ xml += " <sensitivity>public</sensitivity>\n";
+
+ xml += " <name>" + synckolab.tools.text.encode4XML(this.getCardProperty(card, "DisplayName")) + "</name>\n";
+
+ if (this.haveCardProperty(card, "Notes")) {
+ xml += " <notes><text>" + synckolab.tools.text.encode4XML(this.getCardProperty(card, "Notes")) + "</text></notes>\n";
+ }
+ if (this.haveCardProperty(card, "NickName")) {
+ xml += " <nickname>" + synckolab.tools.text.encode4XML(this.getCardProperty(card, "NickName")) + "</nickname>\n";
+ }
+
+ synckolab.tools.logMessage("going through child cards", synckolab.global.LOG_DEBUG + synckolab.global.LOG_AB);
+ var cList = this.abListObject(card);
+ var lCards = cList.childCards;
+ if (lCards) {
+ if (lCards.hasMoreElements) {
+ var curCard = null;
+ while (lCards.hasMoreElements() && (curCard = lCards.getNext())) {
+ // get the right interface
+ var cur = curCard.QueryInterface(Components.interfaces.nsIAbCard);
+ // get the uid or generate it
+ var uid = this.getUID(cur);
+ if (!uid) {
+ uid = "sk-vc-" + synckolab.tools.text.randomVcardId();
+ synckolab.addressbookTools.setUID(cur, uid);
+ }
+
+ xml += " <member>\n";
+ if (this.haveCardProperty(cur, "DisplayName")) {
+ xml += " " + synckolab.tools.text.nodeWithContent("display-name", this.getCardProperty(cur, "DisplayName"), false);
+ }
+ if (this.haveCardProperty(cur, "PrimaryEmail")) {
+ xml += " " + synckolab.tools.text.nodeWithContent("smtp-address", this.getCardProperty(cur, "PrimaryEmail"), false);
+ } else if (this.haveCardProperty(cur, "SecondEmail")) {
+ xml += " " + synckolab.tools.text.nodeWithContent("smtp-address", this.getCardProperty(cur, "SecondEmail"), false);
+ } else {
+ synckolab.tools.logMessage("List entry without an email!" + this.getUID(cur), synckolab.global.LOG_WARNING + synckolab.global.LOG_AB);
+ }
+
+ xml += " " + synckolab.tools.text.nodeWithContent("uid", uid, false);
+ xml += " </member>\n";
+ }
+ } else {
+ synckolab.tools.logMessage("lists not supported " + xml, synckolab.global.LOG_WARNING + synckolab.global.LOG_AB);
+ return null;
+ }
+ } else {
+ synckolab.tools.logMessage("lists not supported " + xml, synckolab.global.LOG_WARNING + synckolab.global.LOG_AB);
+ return null;
+ }
+
+ xml += "</vlist>\n";
+ synckolab.tools.logMessage("list: " + xml, synckolab.global.LOG_INFO + synckolab.global.LOG_AB);
+
+ return xml;
+};
/**
* Creates xml (kolab2) out of a given card.
@@ -1381,6 +1491,223 @@ synckolab.addressbookTools.copyImage = function (newName) {
return fileTo.exists();
};
+synckolab.addressbookTools.getXmlProperty = function(card, field, nodeName, nodeName2) {
+ // only create nodes if they exist
+ if (!this.haveCardProperty(card, field)) {
+ return "";
+ }
+
+ var xml = "";
+ if(nodeName2) {
+ xml += "<" + nodeName + ">\n";
+ xml += " " + synckolab.tools.text.nodeWithContent(nodeName2, this.getCardProperty(card, field));
+ xml += "</" + nodeName + ">\n";
+ } else {
+ xml += " " + synckolab.tools.text.nodeWithContent(nodeName, this.getCardProperty(card, field)) + "\n";
+ }
+ return xml;
+};
+
+/**
+ * Creates xml (kolab3) out of a given card.
+ * The return is the xml as string.
+ * @param card nsIAbCard: the adress book card
+ * @param skipHeader true to skip xml header and container creation (i.e. for lists)
+ * @param fields Array: all the fields not being held in the default card
+ */
+synckolab.addressbookTools.card2Kolab3 = function (card, skipHeader, fields) {
+ // translate the card: base64xml, xml, vcard
+ //synckolab.tools.logMessage ("XML: \n" + card.translateTo("xml"), synckolab.global.LOG_WARNING + synckolab.global.LOG_AB); - dont work is actually a HTML
+ //synckolab.tools.logMessage ("VCARD: \n" + card.translateTo("vcard"), synckolab.global.LOG_WARNING + synckolab.global.LOG_AB); // converts a little too much and ignores uuid
+
+ // debug for photo:
+
+ var displayName = "";
+ var xml = "";
+ if(!skipHeader) {
+ xml += "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\" ?>\n";
+ xml += "<vcards xmlns=\"urn:ietf:params:xml:ns:vcard-4.0\">\n";
+ }
+
+ xml += "<vcard>\n";
+ xml += " <uid><uri>urn:uuid:" + synckolab.tools.text.encode4XML(this.getUID(card)) + "</uri></uid>\n";
+ xml += " <prodid><text>SyncKolab , Kolab resource</text></prodid>\n"; // TODO add version
+ xml += " <rev><timestamp>" + synckolab.tools.text.calDateTime2String(new Date(this.getCardProperty(card, "LastModifiedDate")), false, true) + "Z</timestamp></rev>\n";
+
+ // ??
+ //xml += synckolab.tools.text.nodeWithContent("categories", this.getCardProperty(card, "Category"), false);
+ //xml += " <sensitivity>public</sensitivity>\n";
+
+ xml += this.getXmlProperty(card, "Notes", "note", "text");
+
+ if (this.haveCardProperty(card, "FirstName") || this.haveCardProperty(card, "LastName") || this.haveCardProperty(card, "DisplayName") || this.haveCardProperty(card, "NickName")) {
+ xml += " <n>\n";
+ xml += this.getXmlProperty(card, "FirstName", "given");
+ xml += this.getXmlProperty(card, "LastName", "surname");
+ xml += " </n>\n";
+
+ if (this.haveCardProperty(card, "DisplayName")) {
+ xml += synckolab.tools.text.nodeContainerWithContent("fn", "text", this.getCardProperty(card, "DisplayName"));
+ } else if (this.haveCardProperty(card, "FirstName") || this.haveCardProperty(card, "LastName")) {
+ displayName = this.getCardProperty(card, "FirstName") + " " + this.getCardProperty(card, "LastName");
+ xml += synckolab.tools.text.nodeContainerWithContent("fn", "text", displayName);
+ }
+
+ }
+ xml += this.getXmlProperty(card, "FirstName", "given");
+ xml += synckolab.tools.text.nodeWithContent("organization", this.getCardProperty(card, "Company"), false);
+
+ xml += this.getXmlProperty(card, "WebPage1", "url", "uri");
+ xml += this.getXmlProperty(card, "WebPage2", "url", "uri");
+ xml += this.getXmlProperty(card, "AimScreenName", "impp", "uri");
+
+ //xml += synckolab.tools.text.nodeWithContent("department", this.getCardProperty(card, "Department"), false);
+ //" <office-location>zuhaus</office-location>\n";
+ //" <profession>programmierer</profession>\n";
+ xml += this.getXmlProperty(card, "JobTitle", "title", "text");
+ xml += this.getXmlProperty(card, "NickName", "nickname", "text");
+
+ var adate;
+ if (this.haveCardProperty(card, "BirthYear") && this.haveCardProperty(card, "BirthMonth") && this.haveCardProperty(card, "BirthDay")) {
+ adate = this.getCardProperty(card, "BirthYear") + this.getCardProperty(card, "BirthMonth") + this.getCardProperty(card, "BirthDay");
+ xml += " <bday>" + synckolab.tools.text.nodeWithContent("date-time", adate, false) + "</bday>\n";
+ }
+
+ if (this.haveCardProperty(card, "AnniversaryYear") && this.haveCardProperty(card, "AnniversaryMonth") && this.haveCardProperty(card, "AnniversaryDay")) {
+ adate = this.getCardProperty(card, "AnniversaryYear") + "-" + this.getCardProperty(card, "AnniversaryMonth") + "-" + this.getCardProperty(card, "AnniversaryDay");
+ xml += " <anniversary>" + synckolab.tools.text.nodeWithContent("date-time", adate, false) + "</anniversary>\n";
+ }
+
+ if (this.haveCardProperty(card, "HomePhone")) {
+ xml += " <tel>\n";
+ xml += " <parameters><type><text>home</text></type></parameters>\n";
+ xml += " <text>" + this.getCardProperty(card, "HomePhone") + "</text>\n";
+ xml += " </tel>\n";
+ }
+ if (this.haveCardProperty(card, "WorkPhone")) {
+ xml += " <tel>\n";
+ xml += " <parameters><type><text>work</text></type></parameters>\n";
+ xml += " <text>" + this.getCardProperty(card, "WorkPhone") + "</text>\n";
+ xml += " </tel>\n";
+ }
+ if (this.haveCardProperty(card, "FaxNumber")) {
+ xml += " <tel>\n";
+ xml += " <parameters><type><text>fax</text><text>work</text></type></parameters>\n";
+ xml += " <text>" + this.getCardProperty(card, "FaxNumber") + "</text>\n";
+ xml += " </tel>\n";
+ }
+ if (this.haveCardProperty(card, "CellularNumber")) {
+ xml += " <tel>\n";
+ xml += " <parameters><type><text>cell</text></type></parameters>\n";
+ xml += " <text>" + this.getCardProperty(card, "CellularNumber") + "</text>\n";
+ xml += " </tel>\n";
+ }
+ if (this.haveCardProperty(card, "PagerNumber")) {
+ xml += " <tel>\n";
+ xml += " <parameters><type><text>page</text></type></parameters>\n";
+ xml += " <text>" + this.getCardProperty(card, "PagerNumber") + "</text>\n";
+ xml += " </tel>\n";
+ }
+
+ if (this.haveCardProperty(card, "PrimaryEmail")) {
+ xml += " <email>\n";
+ xml += " <parameters><pref><integer>1</integer></pref></parameters>\n";
+ //xml += " <display-name>" + synckolab.tools.text.encode4XML(displayName) + "</display-name>\n";
+ xml += " <text>" + synckolab.tools.text.encode4XML(this.getCardProperty(card, "PrimaryEmail")) + "</text>\n";
+ xml += " </email>\n";
+ }
+
+ if (this.haveCardProperty(card, "SecondEmail")) {
+ xml += " <email>\n";
+ //xml += " <display-name>" + synckolab.tools.text.encode4XML(displayName) + "</display-name>\n";
+ xml += " <text>" + synckolab.tools.text.encode4XML(this.getCardProperty(card, "SecondEmail")) + "</text>\n";
+ xml += " </email>\n";
+ }
+
+ // if the mail format is set...
+ if (this.getCardProperty(card, "PreferMailFormat") && this.getCardProperty(card, "PreferMailFormat") !== synckolab.addressbookTools.MAIL_FORMAT_UNKNOWN) {
+ if (Number(this.getCardProperty(card, "PreferMailFormat")) === this.MAIL_FORMAT_PLAINTEXT) {
+ xml += "<x-custom><identifier>X-PreferMailFormat</identifier><value>text</value></x-custom>\n";
+ } else if (Number(this.getCardProperty(card, "PreferMailFormat")) === this.MAIL_FORMAT_HTML) {
+ xml += "<x-custom><identifier>X-PreferMailFormat</identifier><value>html</value></x-custom>\n";
+ }
+ }
+
+ if (this.haveCardProperty(card, "HomeAddress") || this.haveCardProperty(card, "HomeAddress2") || this.haveCardProperty(card, "HomeCity") || this.haveCardProperty(card, "HomeState") || this.haveCardProperty(card, "HomeZipCode") || this.haveCardProperty(card, "HomeCountry")) {
+ xml += " <adr>\n";
+ xml += " <parameters><type><text>home</text></type></parameters>\n";
+ xml += this.getXmlProperty(card, "HomeAddress", "street");
+ xml += this.getXmlProperty(card, "HomeAddress2", "street2");
+ xml += this.getXmlProperty(card, "HomeCity", "locality");
+ xml += this.getXmlProperty(card, "HomeState", "region");
+ xml += this.getXmlProperty(card, "HomeZipCode", "code");
+ xml += this.getXmlProperty(card, "HomeCountry", "country");
+ xml += " </adr>\n";
+ }
+
+ if (this.haveCardProperty(card, "WorkAddress") || this.haveCardProperty(card, "WorkAddress2") || this.haveCardProperty(card, "WorkCity") || this.haveCardProperty(card, "WorkState") || this.haveCardProperty(card, "WorkZipCode") || this.haveCardProperty(card, "WorkCountry")) {
+ xml += " <adr>\n";
+ xml += " <parameters><type><text>work</text></type></parameters>\n";
+ xml += this.getXmlProperty(card, "WorkAddress", "street");
+ xml += this.getXmlProperty(card, "WorkAddress2", "street2");
+ xml += this.getXmlProperty(card, "WorkCity", "locality");
+ xml += this.getXmlProperty(card, "WorkState", "region");
+ xml += this.getXmlProperty(card, "WorkZipCode", "code");
+ xml += this.getXmlProperty(card, "WorkCountry", "country");
+ xml += " </adr>\n";
+ }
+
+ // TODO photo name = photo - base64-Encoded
+ /*
+ xml += synckolab.tools.text.nodeWithContent("picture", this.getCardProperty(card, "PhotoName"), false);
+
+ // we can probably ignore that
+ var ptype = this.getCardProperty(card, "PhotoType");
+ if (ptype === "web" || ptype === "file") {
+ * kolab:
+ * 1. read the file: FILENAME = this.getCardProperty(card, "PhotoName")
+ * found in ~profil/Photos/FILENAME
+ * 2. create an attachment name FILENAME with the content (base64 encoded)
+ *
+ xml += synckolab.tools.text.nodeWithContent("picture-uri", this.getCardProperty(card, "PhotoURI"), false); // we can distinguish between file: and http: anyways
+ }
+ */
+
+ //xml += synckolab.tools.text.nodeWithContent("preferred-address", this.getCardProperty(card, "DefaultAddress"), false); @deprecated
+
+ if (this.getCardProperty(card, "Custom1")) {
+ xml += " <x-custom><identifier>X-Custom1</identifier><value>"+this.getCardProperty(card, "Custom1")+"</value></x-custom>\n";
+ }
+ if (this.getCardProperty(card, "Custom2")) {
+ xml += " <x-custom><identifier>X-Custom2</identifier><value>"+this.getCardProperty(card, "Custom2")+"</value></x-custom>\n";
+ }
+ if (this.getCardProperty(card, "Custom3")) {
+ xml += " <x-custom><identifier>X-Custom3</identifier><value>"+this.getCardProperty(card, "Custom3")+"</value></x-custom>\n";
+ }
+ if (this.getCardProperty(card, "Custom4")) {
+ xml += " <x-custom><identifier>X-Custom4</identifier><value>"+this.getCardProperty(card, "Custom4")+"</value></x-custom>\n";
+ }
+
+ if (this.getCardProperty(card, "AllowRemoteContent")) {
+ xml += " <x-custom><identifier>X-AllowRemoteContent</identifier><value>true</value></x-custom>\n";
+ } else {
+ xml += " <x-custom><identifier>X-AllowRemoteContent</identifier><value>false</value></x-custom>\n";
+ }
+
+ // add extra/missing fields
+ if (fields) {
+ xml += fields.toXmlString();
+ }
+
+ xml += "</vcard>\n";
+
+ if(!skipHeader) {
+ xml += "</vcards>\n";
+ }
+
+ return xml;
+};
+
/**
* Creates xml (kolab2) out of a given card.
* The return is the xml as string.
@@ -1401,7 +1728,8 @@ synckolab.addressbookTools.card2Xml = function (card, fields) {
xml += " <uid>" + synckolab.tools.text.encode4XML(this.getUID(card)) + "</uid>\n";
xml += synckolab.tools.text.nodeWithContent("categories", this.getCardProperty(card, "Category"), false);
//xml += " <creation-date>"+synckolab.tools.text.date2String(new Date(this.getCardProperty(card, "LastModifiedDate")*1000))+"T"+synckolab.tools.text.time2String(new Date(this.getCardProperty(card, "LastModifiedDate")*1000))+"Z</creation-date>\n";
- xml += " <last-modification-date>" + synckolab.tools.text.date2String(new Date(this.getCardProperty(card, "LastModifiedDate") * 1000)) + "T" + synckolab.tools.text.time2String(new Date(this.getCardProperty(card, "LastModifiedDate") * 1000)) + "Z</last-modification-date>\n";
+ xml += " <last-modification-date>" + synckolab.tools.text.calDateTime2String(new Date(this.getCardProperty(card, "LastModifiedDate")), false, false) + "</last-modification-date>\n";
+
// ??
xml += " <sensitivity>public</sensitivity>\n";
if (this.haveCardProperty(card, "Notes")) {
@@ -2790,13 +3118,20 @@ synckolab.addressbookTools.card2Message = function (card, email, format, fields)
synckolab.tools.logMessage("creating message out of card... ", synckolab.global.LOG_INFO + synckolab.global.LOG_AB);
// for the kolab xml format
- if (format === "Xml") {
+ if (format === "xml-k2") {
// mailing list
if (card.isMailList) {
return synckolab.tools.generateMail(this.getUID(card), email, "", "application/x-vnd.kolab.contact.distlist", true, synckolab.tools.text.utf8.encode(this.list2Xml(card, fields)), this.list2Human(card));
} else {
return synckolab.tools.generateMail(this.getUID(card), email, "", "application/x-vnd.kolab.contact", true, synckolab.tools.text.utf8.encode(this.card2Xml(card, fields)), this.card2Human(card), this.getCardProperty(card, "PhotoName"));
}
+ } else if(format === "xml-k3") {
+ // mailing list
+ if (card.isMailList) {
+ return synckolab.tools.generateMail(this.getUID(card), email, "", "application/x-vcard.list+xml", true, synckolab.tools.text.utf8.encode(this.list2Kolab3(card, fields)), this.list2Human(card));
+ } else {
+ return synckolab.tools.generateMail(this.getUID(card), email, "", "application/vcard+xml", true, synckolab.tools.text.utf8.encode(this.card2Kolab3(card, fields)), this.card2Human(card));
+ }
}
if (card.isMailList) {
diff --git a/src/chrome/content/synckolab/tools/text.js b/src/chrome/content/synckolab/tools/text.js
index 2058c25..018a3ad 100644
--- a/src/chrome/content/synckolab/tools/text.js
+++ b/src/chrome/content/synckolab/tools/text.js
@@ -59,6 +59,14 @@ synckolab.tools.text = {
return " <" + nodeName + ">" + (this.checkExist(nodeValue) ? this.encode4XML(nodeValue) : "") + "</" + nodeName + ">\n";
},
+ nodeContainerWithContent: function (nodeName, containerName, nodeValue, createNonExist) {
+ if (!createNonExist && !this.checkExist(nodeValue)) {
+ return "";
+ }
+
+ return " <" + nodeName + "><" + containerName + ">" + (this.checkExist(nodeValue) ? this.encode4XML(nodeValue) : "") + "</" + containerName + "></" + nodeName + ">\n";
+ },
+
checkExist : function (value) {
return value !== null && typeof value !== 'undefined' && value !== "" && value !== " ";
},
diff --git a/test/suite.js b/test/suite.js
index 832f187..7dd5618 100644
--- a/test/suite.js
+++ b/test/suite.js
@@ -29,7 +29,9 @@ QUnit.log(function(details) {
} else {
testRuns.fail++
}
- print(details.result ? 'PASS' : 'FAIL', (details.module?details.module+" ":"") + details.name + ":", details.message, details.result?"":(" expected '" + details.expected + "' was '" + details.actual + "'"));
+ if(!details.result) {
+ print(details.result ? 'PASS' : 'FAIL', (details.module?details.module+" ":"") + details.name + ":", details.message, details.result?"":(" expected '" + details.expected + "' was '" + details.actual + "'"));
+ }
});
// run the tests
diff --git a/test/synckolab/parser/kolab2/contactTest.js b/test/synckolab/parser/kolab2/contactTest.js
index 3efb20b..739356e 100644
--- a/test/synckolab/parser/kolab2/contactTest.js
+++ b/test/synckolab/parser/kolab2/contactTest.js
@@ -10,7 +10,7 @@ load("src/chrome/content/synckolab/addressbookTools.js");
load("test/lib/testOverride.js");
-test("synckolab.addressbookTools.parseMessageContent", function(){
+test("skolab2 ynckolab.addressbookTools.parseMessageContent", function(){
equal(null, synckolab.addressbookTools.parseMessageContent(null), "parsing a null message");
var testFiles = ["contactMinimalTest", "contactFullTest"];
diff --git a/test/synckolab/parser/kolab3/contactTest.js b/test/synckolab/parser/kolab3/contactTest.js
index 8e05dcb..e268935 100644
--- a/test/synckolab/parser/kolab3/contactTest.js
+++ b/test/synckolab/parser/kolab3/contactTest.js
@@ -10,7 +10,7 @@ load("src/chrome/content/synckolab/addressbookTools.js");
load("test/lib/testOverride.js");
-test("synckolab.addressbookTools.parseMessageContent", function(){
+test("kolab3 synckolab.addressbookTools.parseMessageContent", function(){
equal(null, synckolab.addressbookTools.parseMessageContent(null), "parsing a null message");
var testFiles = ["simple.vcf.mime","complex.vcf.mime"];
@@ -25,10 +25,13 @@ test("synckolab.addressbookTools.parseMessageContent", function(){
content = readFile("test/synckolab/parser/kolab3/json/"+src+".json");
jsonEntry = JSON.parse(content);
equal(synckolab.tools.equalsObject(entry, jsonEntry), true, src);
+
+ // json -> kolab 3 xml
+
}
});
- var testFiles = ["complex.vcf.mime"];
+ var testFiles = ["simple.vcf.mime"];
var content, entry, jsonEntry;
@@ -42,6 +45,9 @@ test("synckolab.addressbookTools.parseMessageContent", function(){
print("==== STARTING PARSE")
entry = synckolab.addressbookTools.parseMessageContent(content);
print(JSON.stringify(entry, null, ' '))
+ // json -> kolab 3 xml
+ content = synckolab.addressbookTools.card2Kolab3(entry);
+ print(content);
/*
content = readFile("test/synckolab/parser/kolab3/json/"+src+".json");
jsonEntry = JSON.parse(content);
diff --git a/test/synckolab/parser/kolab3/json/complex.vcf.mime.json b/test/synckolab/parser/kolab3/json/complex.vcf.mime.json
index e9c7002..b44e602 100644
--- a/test/synckolab/parser/kolab3/json/complex.vcf.mime.json
+++ b/test/synckolab/parser/kolab3/json/complex.vcf.mime.json
@@ -3,12 +3,12 @@
"type": "contact",
"isMailList": false,
"ts": 1349565039427,
- "UUID": "urn:uuid:Huu5X7hfYy",
+ "UUID": "Huu5X7hfYy",
"DisplayName": "Displayname",
"FirstName": "Lastname",
"LastName": "Firstname",
"Notes": "Notes",
- "title": "Title",
+ "JobTitle": "Title",
"WebPage1": "www.homepage.org",
"WebPage2": "www.blog.test",
"HomeAddress": "Home Street",
@@ -26,10 +26,10 @@
"NickName": "Nickname",
"related": "Partner",
"BirthYear": 2009,
- "BirthMonth": 6,
+ "BirthMonth": 7,
"BirthDay": 27,
"AnniversaryYear": 2009,
- "AnniversaryMonth": 6,
+ "AnniversaryMonth": 7,
"AnniversaryDay": 28,
"HomePhone": "+4930-homephone",
"CellularNumber": "+4930-mobile",
@@ -38,5 +38,6 @@
"AimScreenName": "messaging",
"PrimaryEmail": "first@email.org",
"SecondEmail": "second@email.org",
+ "AllowRemoteContent": true,
"sha1": "64d8099d65db9198bcb1bca276d88b7a82ffd0eb"
} \ No newline at end of file
diff --git a/test/synckolab/parser/kolab3/json/simple.vcf.mime.json b/test/synckolab/parser/kolab3/json/simple.vcf.mime.json
index 6e779b9..0b0ba6b 100644
--- a/test/synckolab/parser/kolab3/json/simple.vcf.mime.json
+++ b/test/synckolab/parser/kolab3/json/simple.vcf.mime.json
@@ -3,7 +3,7 @@
"type": "contact",
"isMailList": false,
"ts": 1349536624864,
- "UUID": "urn:uuid:4xuyC0cyjV",
+ "UUID": "4xuyC0cyjV",
"DisplayName": "Volker Krause",
"FirstName": "Krause",
"LastName": "Volker",
diff --git a/test/synckolab/parser/kolab3/raw/complex.vcf.mime b/test/synckolab/parser/kolab3/raw/complex.vcf.mime
index 54fa347..4a3d52a 100644
--- a/test/synckolab/parser/kolab3/raw/complex.vcf.mime
+++ b/test/synckolab/parser/kolab3/raw/complex.vcf.mime
@@ -257,6 +257,7 @@ AhhBBCCPEe8D+b5dDLeP4TXAAAAABJRU5ErkJggg=3D=3D</uri>
<identifier>X-Profession</identifier>
<value>Profession</value>
</x-custom>
+ <x-custom><identifier>X-AllowRemoteContent</identifier><value>true</value></x-custom>
</vcard>
</vcards>
diff --git a/test/synckolab/tools/textTest.js b/test/synckolab/tools/textTest.js
index a866133..a24c32c 100644
--- a/test/synckolab/tools/textTest.js
+++ b/test/synckolab/tools/textTest.js
@@ -43,9 +43,13 @@ test("synckolab.tools.text.string2DateTime", function() {
equal(synckolab.tools.text.string2DateTime("20050330T152852Z", true).getTime(), 1112196532000, "datetime with T/Z (kolab3)");
equal(synckolab.tools.text.string2DateTime("2005-03-30T").getTime(), 1112133600000, "date with - (kolab2)");
equal(synckolab.tools.text.string2DateTime("20050330T").getTime(), 1112133600000, "date (kolab3)");
+
+
+ equal(synckolab.tools.text.string2DateTime("1980-01-22").getTime(), 317343600000, "date with - (kolab2)");
+ equal(synckolab.tools.text.string2DateTime("1980-01-22").getMonth()+1, 1, "month with - (kolab2)");
equal(synckolab.tools.text.string2DateTime("2005-03-30").getTime(), 1112133600000, "date with - (kolab2)");
equal(synckolab.tools.text.string2DateTime("20050330").getTime(), 1112133600000, "date (kolab3)");
- equal(synckolab.tools.text.string2DateTime("2005").getTime(), 1112133600000, "only year");
+ equal(synckolab.tools.text.string2DateTime("2005").getTime(), 1104534000000, "only year");
});
test("synckolab.tools.text.calDateTime2String", function() {