/*jshint forin:true, noarg:true, noempty:true, eqeqeq:true,
bitwise:true, strict:true, undef:true, curly:true, browser:true,
devel:true, indent:2, maxerr:50, moz:true, newcap:false, moz:true */
/* global mozContact: false,
ContactTelField: false, parseLDIF: false */
(function () {
"use strict";
// Shim for the intersection of two Arrays.
if (!Array.prototype.intersection) {
Array.prototype.intersection = function (anotherArr) {
return this.filter(function(n) {
if (anotherArr.indexOf(n) === -1) { return false; }
return true;
});
};
}
const phoneFields = [
"mobile", "facsimiletelephonenumber", "homePhone", "telephoneNumber"
];
const emailFields = [ "mail" ];
function ValueError(message) {
this.name = "ValueError";
this.message = message || "Unknown Value";
}
ValueError.prototype = new Error();
ValueError.prototype.constructor = ValueError;
/**
* Translate objects created from LDIF files to Contacts
*
* @param Array of LDIF objects
* @return Contact with all fields filled
* @throws ValueError for unknown field in the LDIF object
*
* ContactsAPI:
* @see https://wiki.mozilla.org/WebAPI/ContactsAPI
* @spec http://www.w3.org/TR/contacts-manager-api/
*
* Thunderbid LDAP Schema:
* @see https://developer.mozilla.org/docs/Thunderbird/LDAP_Support
* @see https://tools.ietf.org/html/rfc4519
*/
function translateObjectToContact(inRec) {
var contact = {},
pomStr = "", curRec = null;
/**
* Find the proper record (or create new one) in the multi-value
* attribute
*
* @param idx name of the attribute to which the record belongs
* @param subClass Function constructor of the record if there is
* none
* @param subType String with the type of the record
* @return record of the proper class
*
* Uses global variable contact.
*/
function findSubElement(idx, subType) {
var cAddr = null;
// No contact.adr at all
if (!contact.hasOwnProperty(idx)) {
cAddr = {
'type': [subType]
};
contact[idx] = cAddr;
}
// Single-element property
else if (!Array.isArray(contact[idx])) {
if (contact[idx].type.indexOf(subType) === -1) {
contact[idx] = [contact[idx]];
cAddr = {
'type': [subType]
};
contact[idx].push(cAddr);
}
else {
cAddr = contact[idx];
}
}
// Array
else {
cAddr = contact[idx].filter(function (addr) {
return addr.type.indexOf(subType) !== -1;
});
if (cAddr.length === 0) {
cAddr = {
'type': [subType]
};
contact[idx].push(cAddr);
}
else {
cAddr = cAddr[0];
}
}
return cAddr;
}
for (var key in inRec) {
if (key === "birthyear") {
pomStr = inRec[key];
contact.bday = new Date(pomStr.slice(0,4), pomStr.slice(4,6),
pomStr.slice(6,8));
}
else if (key === "c") {
curRec = findSubElement("adr", "work");
curRec.countryName = inRec[key];
}
else if (key === "cn") {
contact.name = [inRec[key]];
}
else if (key === "description") {
contact.note = [inRec[key]];
}
else if (key === "facsimiletelephonenumber") {
curRec = findSubElement("tel", "fax");
curRec.value = inRec[key];
}
else if (key === "givenName") {
contact.givenName = [inRec[key]];
}
else if (key === "homePhone") {
curRec = findSubElement("tel", "home");
curRec.value = inRec[key];
}
else if (key === "l") {
curRec = findSubElement("adr", "work");
curRec.locality = inRec[key];
}
else if (key === "mail") {
curRec = findSubElement("email", "work");
curRec.value = inRec[key];
}
else if (key === "mobile") {
curRec = findSubElement("tel", "mobile");
curRec.value = inRec[key];
}
else if (key === "mozillaHomeCountryName") {
curRec = findSubElement("adr", "home");
curRec.countryName = inRec[key];
}
else if (key === "mozillaHomeLocalityName") {
curRec = findSubElement("adr", "home");
curRec.locality = inRec[key];
}
else if (key === "mozillaHomePostalCode") {
curRec = findSubElement("adr", "home");
curRec.postalCode = inRec[key];
}
else if (key === "mozillaHomeState") {
curRec = findSubElement("adr", "home");
curRec.region = inRec[key];
}
else if (key === "mozillaHomeStreet") {
curRec = findSubElement("adr", "home");
curRec.streetAddress = inRec[key];
}
else if (key === "mozillaHomeUrl") {
curRec = findSubElement("url", "home");
curRec.value = inRec[key];
}
else if (key === "mozillaNickname") {
contact.nickname = [inRec[key]];
}
else if (key === "o") {
contact.org = [inRec[key]];
}
else if (key === "sn") {
contact.familyName = [inRec[key]];
}
else if (key === "st") {
curRec = findSubElement("adr", "work");
curRec.region = inRec[key];
}
else if (key === "street") {
curRec = findSubElement("adr", "work");
curRec.streetAddress = inRec[key];
}
else if (key === "telephoneNumber") {
curRec = findSubElement("tel", "work");
curRec.value = inRec[key];
}
else if (key === "title") {
contact.jobTitle = [inRec[key]];
}
// Unknown attribute
else {
throw new ValueError("Unknown attribute " + key +
" with value:\n" + inRec[key]);
}
}
// Per RFC 4519 section 3.12 cn and sn attributes are always
// required
if (! contact.hasOwnProperty('name')) {
if (contact.hasOwnProperty('familyName') &&
contact.hasOwnProperty('givenName')) {
contact.name = contact.givenName + " " + contact.familyName;
}
else if (contact.hasOwnProperty("org")) {
contact.name = contact.org;
}
else if (contact.hasOwnProperty("jobTitle")) {
contact.name = contact.jobTitle;
}
}
if (Object.keys(contact).length > 0) {
var outObj = new mozContact();
outObj.init(contact);
return contact;
}
return null;
}
/**
* Not used presently and not debugged.
*/
function whenContactAlreadyPresent(rec, cb_not_found, cb_found) {
var rec_keys = Object.keys(rec);
// Finding whether the contact has email or telephone
var email_fields = rec_keys.intersection(emailFields);
var phone_fields = rec_keys.intersection(phoneFields);
var search_keys = [];
if (email_fields.length > 0) {
search_keys = email_fields;
}
else if (phone_fields.length > 0) {
search_keys = phone_fields;
}
if (search_keys.length > 0) {
var search_opts = {
filterValue : rec(search_keys[0]),
filterBy : search_keys,
filterOp : "contains",
filterLimit : 1
};
var search = navigator.mozContacts.find(search_opts);
// Possible duplicate found ... bail out, rather do nothing!
search.onsuccess = function() {
// search.result is found record (Array of length 1)
cb_found(rec, search.result);
};
// No duplicates, go ahead and create new record
search.onerror = function() {
cb_not_found(rec);
};
}
}
function restoreURLForm(url) {
document.getElementById("progress-div").style.display = "none";
document.getElementById("URL-form").style.display = "block";
if (url !== undefined) {
document.getElementsByName("URL")[0].value = url;
}
}
function insertData(ldifText) {
var progressEl = document.querySelector("#progress-div progress");
var records = parseLDIF(ldifText.split("\n"));
console.log("records.length = " + records.length);
if (records.length > 0) {
if (!window.confirm("THIS WILL ERASE ALL CONTACTS ON YOUR PHONE!\n" +
"Are you cool with that?")) {
return false;
}
}
var cl_req = navigator.mozContacts.clear();
cl_req.onerror = function() {
throw new Error("Cannot clear whole Contacts database?");
};
cl_req.onsuccess = function() {
progressEl.max = records.length;
progressEl.value = 0;
records.forEach(function (rec) {
var add_contact = translateObjectToContact(rec);
var sav_req = navigator.mozContacts.save(add_contact);
sav_req.onsuccess = function() {
progressEl.value += 1;
if (progressEl.value >= records.length) {
window.alert("All contacts have been imported!");
restoreURLForm();
}
};
sav_req.onerror = function() {
console.error("Cannot save record " + add_contact.id +
"\n" + rec.toSource());
};
});
};
}
function submitHandler (evt) {
var URL = document.getElementsByName("URL")[0].value;
var progressForm = document.getElementById("progress-div");
document.getElementById("URL-form").style.display = "none";
progressForm.style.display = "block";
var req = new XMLHttpRequest();
req.open("GET", URL, true);
var progressEl = progressForm.getElementsByTagName("progress")[0];
req.onprogress = function(evt) {
if (evt.lengthComputable) {
progressEl.max = evt.total;
progressEl.value = evt.loaded;
}
};
req.onload = function() {
var inText = req.responseText;
if (inText.length > 0) {
insertData(inText);
if (localStorage) {
localStorage.setItem("lastURL", URL);
}
}
};
req.onerror = function() {
window.alert("Cannot load " + URL + "!");
restoreURLForm(URL);
};
req.send();
evt.stopPropagation();
evt.preventDefault();
}
window.onload = function() {
if (localStorage && localStorage.lastURL) {
var oldURL = localStorage.getItem('lastURL');
document.getElementsByName("URL")[0].value = oldURL;
}
document.body.addEventListener("submit",
submitHandler, false);
};
}());