Bug 455797 - "birthday picker doesn't let me enter certain dates, resets day and year", also allow LDAP and LDIF import/export to work correctly. r=Standard8,sr=Neil. a=KaiRo for SM2a1.
authorJosh Geenen <joshgeenen+bugzilla@gmail.com>
Sun, 21 Sep 2008 16:19:37 +0100
changeset 392 4aec6bde0ed8e75c5adf03ae29d9ae90c4e99a72
parent 391 2a274e619bcdc32b95164ee19f6b8aa19df80692
child 393 09db772e30479b7cd03e3bddaaac5e45ed2402fc
push idunknown
push userunknown
push dateunknown
reviewersStandard8, Neil, KaiRo
bugs455797
Bug 455797 - "birthday picker doesn't let me enter certain dates, resets day and year", also allow LDAP and LDIF import/export to work correctly. r=Standard8,sr=Neil. a=KaiRo for SM2a1.
mail/components/addrbook/content/abCardOverlay.js
mail/components/addrbook/content/abCardViewOverlay.js
mailnews/addrbook/resources/content/abCardOverlay.js
mailnews/addrbook/resources/content/abCardViewOverlay.js
mailnews/import/test/resources/AB_README
mailnews/import/test/resources/addressbook.json
mailnews/import/test/resources/basic_ldif_addressbook.ldif
mailnews/import/test/resources/import_helper.js
mailnews/mailnews.js
--- a/mail/components/addrbook/content/abCardOverlay.js
+++ b/mail/components/addrbook/content/abCardOverlay.js
@@ -402,34 +402,34 @@ function GetCardValues(cardproperty, doc
       cardproperty.getProperty(kVcardFields[i][1], "");
   }
 
   var birthday = doc.getElementById("Birthday");
   modifyDatepicker(birthday);
 
   // get the month of the year (1 - 12)
   var month = cardproperty.getProperty("BirthMonth", null);
-  // set the datepicker's month and prepend a zero if necessary
-  if (month) {
-    birthday.month = parseInt(month) - 1;
-    if (month.length < 2)
-      month = "0" + month;
-  }
-  birthday.monthField.value = month;
+  if (month > 0 && month < 13)
+    birthday.month = month - 1;
+  else
+    birthday.monthField.value = null;
 
   // get the date of the month (1 - 31)
   var date = cardproperty.getProperty("BirthDay", null);
-  birthday.dateField.value = date;
+  if (date > 0 && date < 32)
+    birthday.date = date;
+  else
+    birthday.dateField.value = null;
 
   // get the year
   var year = cardproperty.getProperty("BirthYear", null);
   var birthYear = doc.getElementById("BirthYear");
   // set the year in the datepicker to the stored year
   // if the year isn't present, default to 2000 (a leap year)
-  birthday.year = year ? year : kDefaultYear;
+  birthday.year = year && year < 10000 && year > 0 ? year : kDefaultYear;
   birthYear.value = year;
 
   // get the current age
   calculateAge(null, birthYear);
 
   // when the birth year changes, update the datepicker's year to the new value
   // or to kDefaultYear if the value is null
   birthYear.onchange = calculateAge;
@@ -479,29 +479,20 @@ function CheckAndSetCardValues(cardprope
       doc.getElementById(kVcardFields[i][0]).value);
 
   // get the birthday information from the dialog
   var birthdayElem = doc.getElementById("Birthday");
   var birthMonth = birthdayElem.monthField.value;
   var birthDay = birthdayElem.dateField.value;
   var birthYear = doc.getElementById("BirthYear").value;
 
-  // set or delete the birth day, month, and year properties, if necessary
-  if (birthDay)
-    cardproperty.setProperty("BirthDay", birthDay);
-  else if(cardproperty.getProperty("BirthDay", null))
-    cardproperty.deleteProperty("BirthDay");
-  if (birthMonth)
-    cardproperty.setProperty("BirthMonth", birthMonth);
-  else if(cardproperty.getProperty("BirthMonth", null))
-    cardproperty.deleteProperty("BirthMonth");
-  if (birthYear)
-    cardproperty.setProperty("BirthYear", birthYear);
-  else if(cardproperty.getProperty("BirthYear", null))
-    cardproperty.deleteProperty("BirthYear");
+  // set the birth day, month, and year properties
+  cardproperty.setProperty("BirthDay", birthDay);
+  cardproperty.setProperty("BirthMonth", birthMonth);
+  cardproperty.setProperty("BirthYear", birthYear);
 
   var popup = document.getElementById("PreferMailFormatPopup");
   if (popup)
     cardproperty.setProperty("PreferMailFormat", popup.value);
     
   var allowRemoteContentEl = document.getElementById("allowRemoteContent");
   if (allowRemoteContentEl)
     cardproperty.setProperty("AllowRemoteContent", allowRemoteContentEl.checked);
@@ -778,28 +769,28 @@ function modifyDatepicker(aDatepicker) {
     // update the month if the value isn't null
     else if (aField == this.monthField && aValue != null) {
       var oldDate = this.date;
       this._dateValue.setMonth(aValue);
       if (oldDate != this.date)
         this._dateValue.setDate(0);
       this._updateUI(this.dateField, this.date);
       var date = this._dateValue.getDate();
-      this.dateField.value = date < 10 ? "0" + date : date;
+      this.dateField.value = date < 10 && this.dateLeadingZero ? "0" + date : date;
       var month = this._dateValue.getMonth() + 1;
-      this.monthField.value = month < 10 ? "0" + month : month;
+      this.monthField.value = month < 10 && this.monthLeadingZero ? "0" + month : month;
     }
     // update the date if the value isn't null
     else if (aField == this.dateField && aValue != null) {
       this._dateValue.setDate(aValue);
       this._updateUI(this.dateField, this.date);
       var date = this._dateValue.getDate();
-      this.dateField.value = date < 10 ? "0" + date : date;
+      this.dateField.value = date < 10 && this.dateLeadingZero ? "0" + date : date;
       var month = this._dateValue.getMonth() + 1;
-      this.monthField.value = month < 10 ? "0" + month : month;
+      this.monthField.value = month < 10 && this.monthLeadingZero ? "0" + month : month;
     }
     this.setAttribute("value", this.value);
 
     if (this.attachedControl)
       this.attachedControl._setValueNoSync(this._dateValue);
     // if the aField's value is null or 0, set both field's values to null
     if (!aField.value && aField != this.yearField) {
       this.dateField.value = null;
--- a/mail/components/addrbook/content/abCardViewOverlay.js
+++ b/mail/components/addrbook/content/abCardViewOverlay.js
@@ -313,18 +313,18 @@ function DisplayCardViewPane(realCard)
   }
   else {
     // Other section
     // setup the birthday information
     var day = card.getProperty("BirthDay", null);
     var month = card.getProperty("BirthMonth", null);
     var year = card.getProperty("BirthYear", null);
     var dateStr;
-    if (day || month) {
-      var date = (new Date(year, parseInt(month) - 1, day));
+    if (day > 0 && day < 32 && month > 0 && month < 13) {
+      var date = new Date(year, month - 1, day);
       // if the year exists, just use Date.toLocaleString
       if (year)
         dateStr = date.toLocaleDateString();
       // if the year doesn't exist, display Month DD (ex. January 01)
       else
         dateStr = date.toLocaleFormat(gAddressBookBundle.getString("dateformat"));
     }
     else if (year)
--- a/mailnews/addrbook/resources/content/abCardOverlay.js
+++ b/mailnews/addrbook/resources/content/abCardOverlay.js
@@ -400,34 +400,34 @@ function GetCardValues(cardproperty, doc
       cardproperty.getProperty(kVcardFields[i][1], "");
   }
 
   var birthday = doc.getElementById("Birthday");
   modifyDatepicker(birthday);
 
   // get the month of the year (1 - 12)
   var month = cardproperty.getProperty("BirthMonth", null);
-  // set the datepicker's month and prepend a zero if necessary
-  if (month) {
-    birthday.month = parseInt(month) - 1;
-    if (month.length < 2)
-      month = "0" + month;
-  }
-  birthday.monthField.value = month;
+  if (month > 0 && month < 13)
+    birthday.month = month - 1;
+  else
+    birthday.monthField.value = null;
 
   // get the date of the month (1 - 31)
   var date = cardproperty.getProperty("BirthDay", null);
-  birthday.dateField.value = date;
+  if (date > 0 && date < 32)
+    birthday.date = date;
+  else
+    birthday.dateField.value = null;
 
   // get the year
   var year = cardproperty.getProperty("BirthYear", null);
   var birthYear = doc.getElementById("BirthYear");
   // set the year in the datepicker to the stored year
   // if the year isn't present, default to 2000 (a leap year)
-  birthday.year = year ? year : kDefaultYear;
+  birthday.year = year && year < 10000 && year > 0 ? year : kDefaultYear;
   birthYear.value = year;
 
   // get the current age
   calculateAge(null, birthYear);
   // when the birth year changes, update the datepicker's year to the new value
   // or to kDefaultYear if the value is null
   birthYear.onchange = calculateAge;
   birthday.onchange = calculateAge;
@@ -476,29 +476,20 @@ function CheckAndSetCardValues(cardprope
       doc.getElementById(kVcardFields[i][0]).value);
 
   // get the birthday information from the dialog
   var birthdayElem = doc.getElementById("Birthday");
   var birthMonth = birthdayElem.monthField.value;
   var birthDay = birthdayElem.dateField.value;
   var birthYear = doc.getElementById("BirthYear").value;
 
-  // set or delete the birth day, month, and year properties, if necessary
-  if (birthDay)
-    cardproperty.setProperty("BirthDay", birthDay);
-  else if(cardproperty.getProperty("BirthDay", null))
-    cardproperty.deleteProperty("BirthDay");
-  if (birthMonth)
-    cardproperty.setProperty("BirthMonth", birthMonth);
-  else if(cardproperty.getProperty("BirthMonth", null))
-    cardproperty.deleteProperty("BirthMonth");
-  if (birthYear)
-    cardproperty.setProperty("BirthYear", birthYear);
-  else if(cardproperty.getProperty("BirthYear", null))
-    cardproperty.deleteProperty("BirthYear");
+  // set the birth day, month, and year properties
+  cardproperty.setProperty("BirthDay", birthDay);
+  cardproperty.setProperty("BirthMonth", birthMonth);
+  cardproperty.setProperty("BirthYear", birthYear);
 
   var popup = document.getElementById("PreferMailFormatPopup");
   if (popup)
     cardproperty.setProperty("PreferMailFormat", popup.value);
     
   var allowRemoteContentEl = document.getElementById("allowRemoteContent");
   if (allowRemoteContentEl)
     cardproperty.setProperty("AllowRemoteContent", allowRemoteContentEl.checked);
@@ -775,28 +766,28 @@ function modifyDatepicker(aDatepicker) {
     // update the month if the value isn't null
     else if (aField == this.monthField && aValue != null) {
       var oldDate = this.date;
       this._dateValue.setMonth(aValue);
       if (oldDate != this.date)
         this._dateValue.setDate(0);
       this._updateUI(this.dateField, this.date);
       var date = this._dateValue.getDate();
-      this.dateField.value = date < 10 ? "0" + date : date;
+      this.dateField.value = date < 10 && this.dateLeadingZero ? "0" + date : date;
       var month = this._dateValue.getMonth() + 1;
-      this.monthField.value = month < 10 ? "0" + month : month;
+      this.monthField.value = month < 10 && this.monthLeadingZero ? "0" + month : month;
     }
     // update the date if the value isn't null
     else if (aField == this.dateField && aValue != null) {
       this._dateValue.setDate(aValue);
       this._updateUI(this.dateField, this.date);
       var date = this._dateValue.getDate();
-      this.dateField.value = date < 10 ? "0" + date : date;
+      this.dateField.value = date < 10 && this.dateLeadingZero ? "0" + date : date;
       var month = this._dateValue.getMonth() + 1;
-      this.monthField.value = month < 10 ? "0" + month : month;
+      this.monthField.value = month < 10 && this.monthLeadingZero ? "0" + month : month;
     }
     this.setAttribute("value", this.value);
 
     if (this.attachedControl)
       this.attachedControl._setValueNoSync(this._dateValue);
     // if the aField's value is null or 0, set both field's values to null
     if (!aField.value && aField != this.yearField) {
       this.dateField.value = null;
--- a/mailnews/addrbook/resources/content/abCardViewOverlay.js
+++ b/mailnews/addrbook/resources/content/abCardViewOverlay.js
@@ -295,18 +295,18 @@ function DisplayCardViewPane(realCard)
   }
   else {
 	  // Other section
     /// setup the birthday information
     var day = card.getProperty("BirthDay", null);
     var month = card.getProperty("BirthMonth", null);
     var year = card.getProperty("BirthYear", null);
     var dateStr;
-    if (day || month) {
-      var date = (new Date(year, parseInt(month) - 1, day));
+    if (day > 0 && day < 32 && month > 0 && month < 13) {
+      var date = new Date(year, month - 1, day);
       // if the year exists, just use Date.toLocaleString
       if (year)
         dateStr = date.toLocaleDateString();
       // if the year doesn't exist, display Month DD (ex. January 01)
       else
         dateStr = date.toLocaleFormat(gAddressBookBundle.getString("dateformat"));
     }
     else if (year)
--- a/mailnews/import/test/resources/AB_README
+++ b/mailnews/import/test/resources/AB_README
@@ -18,22 +18,22 @@ of the newly-imported card(s) and the ca
 expected order.  If a card to be imported does not have a property, do not
 include it in the JSON card.  Multiple types of imports can be tested with one
 array, as only the supported attributes are checked.
 
 You will also need to give the AbImportHelper constructor two additional
 parameters: the name the imported address book will have (the filename without
 the extension) and the name you chose for the JSON object.
 
-Here is a sample unit test that doesn't check the results:
+Here is a sample LDIF unit test that doesn't check the results:
 function run_test()
 {
   var file = do_get_file("../mailnews/import/test/resources/basic_ldif_addressbook.ldif");
-  new AbImportHelper(file, "ldif").beginImport();
+  new AbImportHelper(file, "LDIF").beginImport();
 }
 
-Here is a sample unit test that checks the results:
+Here is a sample CSV unit test that checks the results:
 function run_test()
 {
-  var file = do_get_file("../mailnews/import/test/resources/basic_ldif_addressbook.ldif");
-  new AbImportHelper(file, "ldif", "basic_ldif_addressbook",
+  var file = do_get_file("../mailnews/import/test/resources/basic_csv_addressbook.csv");
+  new AbImportHelper(file, "CSV", "basic_csv_addressbook",
                      "basic_addressbook").beginImport();
 }
--- a/mailnews/import/test/resources/addressbook.json
+++ b/mailnews/import/test/resources/addressbook.json
@@ -3,17 +3,17 @@
   [
     {
       "DisplayName"      : "Display Name",
       "PrimaryEmail"     : "primaryemail@host.invalid",
       "FirstName"        : "First",
       "LastName"         : "Last",
       "NickName"         : "Nickname",
       "SecondEmail"      : "secondemail@host.invalid",
-      "_AimScreenName"    : "screenname",
+      "_AimScreenName"   : "screenname",
       "PreferMailFormat" : 2,
       "LastModifiedDate" : 1213818826,
       "WorkPhone"        : "123-456-7890",
       "HomePhone"        : "234-567-8901",
       "FaxNumber"        : "345-678-9012",
       "PagerNumber"      : "456-789-0123",
       "CellularNumber"   : "567-890-1234",
       "HomeAddress"      : "Home Address Line 1",
--- a/mailnews/import/test/resources/basic_ldif_addressbook.ldif
+++ b/mailnews/import/test/resources/basic_ldif_addressbook.ldif
@@ -31,13 +31,15 @@ st: Work State
 postalCode: Work Zip
 c: Work Country
 title: Job Title
 ou: Department
 o: Organization Name
 mozillaWorkUrl: http://127.0.0.1
 mozillaHomeUrl: http://localhost
 birthyear: 1900
+birthmonth: 1
+birthday: 2
 mozillaCustom1: Custom Field 1
 mozillaCustom2: Custom Field 2
 mozillaCustom3: Custom Field 3
 mozillaCustom4: Custom Field 4
 description:: Tm90ZXMgbGluZSAxCk5vdGVzIGxpbmUgMgpOb3RlcyBsaW5lIDMKTm90ZXMgbGluZSA0
--- a/mailnews/import/test/resources/import_helper.js
+++ b/mailnews/import/test/resources/import_helper.js
@@ -15,49 +15,46 @@ var gAbImportHelper;
  *                  the extension).
  * @param aJsonName The name of the array in addressbook.json with the cards
  *                  to compare with the imported cards.
  * @constructor
  * @class
  */
 function AbImportHelper(aFile, aType, aAbName, aJsonName)
 {
-  helper = null;
+  gAbImportHelper = null;
   this.mFile = aFile; // checked in the beginImport method
   this.mAbName = aAbName;
 
   /* Attribute notes:  The attributes listed in the declaration below are
-   * supported by all three text export/import types.  AimScreenName &
-   * PreferMailFormat are only supported by LDIF, and BirthMonth and BirthDay
-   * are only supported by CSV and tab-delimited exports/imports.
+   * supported by all three text export/import types.  AimScreenName and
+   * PreferMailFormat are only supported by LDIF.
    * The following are not supported: anniversaryYear, anniversaryMonth,
    * anniversaryDay, popularityIndex, isMailList, mailListURI, lastModifiedDate,
    * and allowRemoteContent
    */
   var supportedAttributes =
     ["FirstName", "LastName", "DisplayName", "NickName", "PrimaryEmail",
      "SecondEmail", "WorkPhone", "HomePhone", "FaxNumber", "PagerNumber",
      "CellularNumber", "HomeAddress", "HomeAddress2", "HomeCity", "HomeState",
      "HomeZipCode", "HomeCountry", "WorkAddress", "WorkAddress2", "WorkCity",
      "WorkState", "WorkZipCode", "WorkCountry", "JobTitle", "Department",
-     "Company", "BirthYear", "WebPage1", "WebPage2", "Custom1", "Custom2",
-     "Custom3", "Custom4", "Notes"];
+     "Company", "BirthYear", "BirthMonth", "BirthDay", "WebPage1", "WebPage2",
+     "Custom1", "Custom2", "Custom3", "Custom4", "Notes"];
   // get the extra attributes supported for the given type of import
   if (aType == "LDIF")
   {
     // LDIF: add AimScreenName and PreferMailFormat
     this.mSupportedAttributes = supportedAttributes.concat(["_AimScreenName",
                                                             "PreferMailFormat"]);
     this.mLdif = true;
   }
   else if (aType == "CSV" || aType == "TAB")
   {
-    // CSV or TAB: add BirthMonth and BirthDay
-    this.mSupportedAttributes = supportedAttributes.concat(["BirthMonth",
-                                                            "BirthDay"]);
+    this.mSupportedAttributes = supportedAttributes;
     this.mLdif = false;
   }
   else
     do_throw("Unexpected type passed to the AbImportHelper constructor");
   // get the "cards" from the JSON file, if necessary
   if (aJsonName)
     this.mJsonCards = this.getJsonCards(aJsonName);
 }
@@ -227,17 +224,17 @@ AbImportHelper.prototype =
    *
    * @param aJsonCard The object decoded from addressbook.json.
    * @param aCard     The imported card to compare with.
    */
   compareCards: function(aJsonCard, aCard)
   {
     for (var i in aJsonCard)
       if (this.mSupportedAttributes.indexOf(i) >= 0)
-          do_check_eq(aJsonCard[i], aCard.getProperty(i, "BAD"));
+        do_check_eq(aJsonCard[i], aCard.getProperty(i, "BAD"));
   },
   /**
    * AbImportHelper.getJsonCards
    * Gets an array of "cards" from the JSON file addressbook.json located in the
    * mailnews/import/test/resources folder.  The array should contain objects
    * with the expected properties and values of the cards in the imported
    * address book.
    * See addressbook.json for an example and AB_README for more details.
--- a/mailnews/mailnews.js
+++ b/mailnews/mailnews.js
@@ -360,16 +360,18 @@ pref("ldap_2.servers.default.attrmap.Wor
 pref("ldap_2.servers.default.attrmap.HomeCountry", "mozillaHomeCountryName");
 pref("ldap_2.servers.default.attrmap.JobTitle", "title");
 pref("ldap_2.servers.default.attrmap.Department", "ou,department,departmentnumber,orgunit");
 pref("ldap_2.servers.default.attrmap.Company", "o,company");
 pref("ldap_2.servers.default.attrmap._AimScreenName", "nsAIMid,nscpaimscreenname");
 pref("ldap_2.servers.default.attrmap.WebPage1", "mozillaWorkUrl,workurl");
 pref("ldap_2.servers.default.attrmap.WebPage2", "mozillaHomeUrl,homeurl");
 pref("ldap_2.servers.default.attrmap.BirthYear", "birthyear");
+pref("ldap_2.servers.default.attrmap.BirthMonth", "birthmonth");
+pref("ldap_2.servers.default.attrmap.BirthDay", "birthday");
 pref("ldap_2.servers.default.attrmap.Custom1", "mozillaCustom1,custom1");
 pref("ldap_2.servers.default.attrmap.Custom2", "mozillaCustom2,custom2");
 pref("ldap_2.servers.default.attrmap.Custom3", "mozillaCustom3,custom3");
 pref("ldap_2.servers.default.attrmap.Custom4", "mozillaCustom4,custom4");
 pref("ldap_2.servers.default.attrmap.Notes", "description,notes");
 pref("ldap_2.servers.default.attrmap.PreferMailFormat", "mozillaUseHtmlMail,xmozillausehtmlmail");
 pref("ldap_2.servers.default.attrmap.LastModifiedDate", "modifytimestamp");