Archive for June, 2008

Synchronizing Addresses


Thunderbird stores addresses using 6 fields:  2 lines for the address, the city, the state, the zip code, and the country.  Google stores addresses in one field (supports multiple lines).  Since these two differ so greatly, it is difficult to synchronize addresses properly.

Possible Solution(s):

Splitting the address with newline characters in Google

Address Line 1
Address Line 2

Any empty fields in Thunderbird would mean an empty line in Google.  Google’s mapping feature worked perfectly with the method listed above.

Splitting the address with semicolons

Another possibility is using semicolons instead of newlines to split the address.  Google was also able to map an address formatting in this fashion.  Example:
Address Line 1;Address Line 2;City;State;Zip;Country

Separating using newlines seems to be the most readable (to me), but Google only shows up to 4 lines in the address field and makes you scroll to see beyond that.

Any other ideas or thoughts?

, , ,

1 Comment

E-mail Addresses With Special Characters

I wanted to test some Unicode characters to see if they would sync properly.  So, I made up an e-mail address: üḯǟôÕ  The e-mail address synced without any error messages, but when I tried to edit the contact in Gmail I was given the following error: “Please enter a valid email address.”

So, while gContactSync and Thunderbird fully support Unicode, it appears that Google supports Unicode in every field except for email.

, ,

No Comments

Progress Update

L10n (Localization) Support

I finished adding support for localization to the extension.  It previously used l10n for the XUL files, but I just finished localizing strings in the scripts.  If you or somebody you know would like to help translate this extension please let me know.

Contact Conversion Rewrite

I completely re-wrote the methods that convert contacts from Google Contacts to Thunderbird Address Book cards and vice versa and went from nearly 700 lines of code to just under 275 (with comments).  To do so, I defined an object that stores Thunderbird’s name for the property (like DisplayName), and information on how Google stores the contact data in Atom/XML (the namespace, tag name, whether the data is stored in an attribute or in the child node, and more).

As of now, the supported attributes in Thunderbird include:

DisplayName, Notes, PrimaryEmail, SecondEmail, CellularNumber, HomePhone, WorkPhone, PagerNumber, FaxNumber, HomeAddress, WorkAddress, _AimScreenName, Company, and JobTitle

Possible Name

I finally decided on a possible name that some initial searching on Google tells me is unique: gContactSync.  Any feedback on the name is welcome and I’ll gladly change it if I find a better name.


I removed the need for the “shortDelay” preference.

, , , ,

No Comments

Bug 439819 – LDIF import does not include mozillahomestreet

I have been writing unit tests for importing address books and finally performed my first tests of verifying the imported data. It turns out that LDIF doesn’t import mozillahomestreet (Home Address line 1) even though it worked with mozillahomestreet2.

So I filed Bug 439819. The problem was in mailnews/addrbook/src/nsAbLDIFService.cpp. For whatever reason, the first line of the address isn’t included in all the else ifs. The patch is simple and is included in the bug report.

Status:  Patch waiting for sr.  Test waiting for bug 437556

, , , , , ,

No Comments

Firefox Download Day

Just a reminder, although I’m sure anyone reading this already knows…  Click the image if you want to learn more and/or pledge.

Download Day 2008


No Comments

Extension Update

Name of the extension

I haven’t figured out a name for the extension yet. I initially named it gcontacts, but that name already exists for several programs. gcontactsync is a potential name. Any suggestions are welcome.


While syncing some newly-created cards, I encountered the following error:

org.xml.sax.SAXParseException: The entity name must immediately follow the “&”; in the entity reference.

The cause was an oversight on my part during the conversion from an nsIAbCard to an XML representation of the contact. I had forgotten to replace special characters, such as &, <, >, ‘, and ” with &, <, >, ‘, and “, respectively. I was fortunate to catch this error before it caused any real problems. I also wrote a function to do the opposite when converting from XML to an nsIAbCard.

Code refactoring and reformatting

While browsing through the code, I realized that I had changed many of the functions and their parameter types without changing the name and the contents of some of the global variables had also changed, so I started refactoring the code. I am also reformatting the code.

lastModifiedDate/Address Book Listener

Since I added support for lastModifiedDate, I no longer need the address book listener.

HTTP Request

I didn’t like my previous HTTP Request methods, so made a few slight modifications. I currently have a generic method for sending an XMLHttpRequest with arguments for the type (POST, PUT, GET, DELETE), URL, body, header label(s)/value(s), and arrays of commands, as strings, to be evaluated depending on the response (OK, 0, or offline, and any error) since the XMLHttpRequest used is asynchronous. This flexibility allows me to call the same function for any HTTP Request that the program must send and act on the outcome.

More contacts supported

When a request is sent to Google for contacts, it only sends the first 25 by default. I now use the max-results query parameter to get the first 250 contacts. 250 was arbitrary, but having that many contacts to sync would probably take a long time. There is now a preference for the number of contacts supported by the extension.

Miscellaneous Improvements

I made a few miscellaneous improvements that resulted in a slight performance increase.  More global variables were removed as well.

, , , , , ,

No Comments

Bug 437556

A while ago I mentioned that I accidentally crashed Thunderbird while figuring out how to import an Address Book because I forgot to set the fieldMap before I called BeginImport. So, I filed Bug 437556: Mailnews crashes while importing an address book if a field map is required but not set. After receiving comments on previous patches, I believe the following code should stop the import, log an error, and return false if the field map isn’t set when it needs to be.

  PRBool needsFieldMap = PR_FALSE;

  if (NS_FAILED(m_pInterface->GetNeedsFieldMap(m_pLocation, &needsFieldMap)) ||
      (needsFieldMap && !m_pFieldMap)) {
                                        m_stringBundle, error);
    SetLogs(success, error, successLog, errorLog);
    *_retval = PR_FALSE;
    return NS_OK;

Included in the patch is a simple unit test to check that BeginImport returns false if the fieldMap isn’t set. I am in the process of writing more unit tests for importing address books.

Here is the bug report with the patch and the test.

Update: The patch was checked in, but the original test failed on Windows builds and the new one is waiting for feedback.

, , , ,

No Comments

Progress Update

I finally wrote a bug report for a bug in mailnews relating to importing Address Books.  I was trying to figure out how to import an address book through javascript when I crashed Thunderbird.  I later found out that I forgot to set the field map.  More info on the bug can be found in the report –

Over the last two days I installed Gentoo and compiled my own kernel and all the programs I am using on it.  It is very fast, and I will probably be using it as my main OS instead of Ubuntu.

I did not yet setup NTP, so my clock was about 20 seconds behind, which showed me a new bug in my extension.  It now checks to see if the contact from Google is from the ‘future’ relative to the computer’s clock and avoids making the Thunderbird card from the future, too.  I will probably do more to fix this later.

, ,

No Comments

June 1 – June 2, 2008

I have been busy recently, but I did manage to remove all the custom helper methods from the script that works with Google Contacts and just use one generic method instead.  I also sped up the sync process by removing the need for one of the for loops I had written.  I rewrote the function that updates a Google Contact, but it is still a little rough and will be rewritten again after I figure out the best way to do it.

, ,

No Comments