Reitwiessner.de
Contact Database Name Breaker

What Is It?

Have you imported your contact database from your old phone, and noticed that Symbian has two fields for the name: Forename and Surname? Then perhaps this application can help you converting the contact database. Unfortunately, the current source code only works for german phones, since it scans for "Vorname" and "Nachname" (I don't know how these fields are callen in english exactly.). But you can modify the source and recompile it. If you know how the fields are called, but cannot compile it, please tell me.

Requirements

A mobile phone running Symbian OS series 60 will do it, like the Nokia 7650, Nokia 3650, Nokia N-Gage, Nokia 6600, Siemens SX1, Nokia 3660, Nokia 7610, Nokia N-Gage QD and the Sendo X. Perhaps other Symbian versions will work to. It should work best on a Siemens SX1, though I will not guarantee that it works at all. It is best if you backed up your contact database before you run the program. THE PROGRAM WILL NOT ASK FOR CONFIRMATION BEFORE MODIFYING THE CONTACT DATABASE.

Download

You can download Name Breaker directly here:
breaknames.exe (2.6 KB)
Source: breaknames.tar.gz (9.2 KB)
Name Breaker is released under the terms of the GPL.

Installation Of The Program

Copy the file "breaknames.exe" to you phone and start it in the file manager. Copying can be done via Bluetooth or a removable memory card. The program will start to convert the whole contact database right away and does not ask for confirmation.

Source Code

The source code is available here on this page so that the libraries used here can be found by search engines. You should nevertheless download the .tar.gz package above if you want to compile it.

breaknames.cpp:

/*
 *  Name Breaker - Symbian OS tool
 *  Author: Christian Reitwiessner <christian@reitwiessner.de>
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 */

#include <eikenv.h>
#include <e32base.h>
#include <e32cons.h>
#include <e32std.h>
#include <cntdb.h>
#include <cntfilt.h>
#include <cntitem.h>
#include <cntfield.h>
#include <cntfldst.h>

class CNameBreaker : public CBase {
private:
	CContactDatabase *iDatabase;
	
public:
	static CNameBreaker* NewLC() {
		CNameBreaker* result = new (ELeave) CNameBreaker();
		CleanupStack::PushL(result);
		result->ConstructL();
		return result;
	}
	
	CNameBreaker() {
	}
	
	void ConstructL() {
		iDatabase = CContactDatabase::OpenL();
	}
	
	~CNameBreaker() {
		delete iDatabase;
		iDatabase = NULL;
	}
	
	void BreakNamesL(CConsoleBase *console) {
		TContactIter *iter = new TContactIter(*iDatabase);

		while (1) {
			TContactItemId itemid = iter->NextL();
			if (itemid == KNullContactId) {
				break;
			}

			CContactItem *item;
			
			item = iDatabase->OpenContactLX(itemid);
			/* LX means that the lock object is kept on the cleanup
			 * stack, we have to push the contact item onto the
			 * stack nevertheless. */
			CleanupStack::PushL(item);
			
			if (item->Type() == KUidContactCard) {
				BreakContactL(item, console);
			}
				
			iDatabase->CommitContactL(*item);
			/*iDatabase->CloseContactL(itemid);*/
			/* use CloseContactL to not save the changes */
			
			CleanupStack::PopAndDestroy(2); /* item, lock object */
		}
	}

private:
	void BreakContactL(CContactItem *item, CConsoleBase *console) {
		TInt vornameId = -1, nachnameId = -1;
		CContactItemFieldSet *fields = &item->CardFields();

		for (TInt i = 0; i < fields->Count(); i ++) {
			/* strange construct, but other methods provoke a
			 * compiler error. suggestions? */
			CContactItemField *field = &((*fields)[i]);
			/* Vorname is german for forename, change this if your
			 * fileds are named differently */
			if (field->Label() == _L("Vorname") &&
					field->StorageType() == KStorageTypeText) {
				vornameId = i;
			/* Nachname is german for surname, same here */
			} else if (field->Label() == _L("Nachname") &&
					field->StorageType() == KStorageTypeText) {
				nachnameId = i;
			}
		}

		if (vornameId == -1 || nachnameId == -1) {
			/* At least one of the fields is not available, don't
			 * change anything */
			return;
		}
		
		CContactTextField *vornameField = ((*fields)[vornameId]).TextStorage();
		CContactTextField *nachnameField = ((*fields)[nachnameId]).TextStorage();
		TPtrC vorname = vornameField->Text();
		TPtrC nachname = nachnameField->Text();
		
		if (vorname == _L(" ")) {
			/* empty forename */
			TInt space = nachname.Locate(' ');
			if (space != KErrNotFound) {
				/* ok, suranme consists of two parts */
				console->Printf(nachname);
				console->Printf(_L("\r\n-> "));
				
				vornameField->SetTextL(nachname.Left(space));
				nachnameField->SetTextL(nachname.Right(
							nachname.Length() - 1 - space));
				
				/* these printfs are normally bad because of
				 * format string exploits, but if i use _L("%s")
				 * and voranmeField->Text().Ptr(), there is no
				 * terminating null byte that is needed by the
				 * %s. */
				console->Printf(vornameField->Text());
				console->Printf(_L(" --- "));
				console->Printf(nachnameField->Text());
				console->Printf(_L("\r\n"));
			}
		}
	}
};


LOCAL_C void startL()
{
	/* the scheduler is needed for communicating with the contact databes.
	 * It is used internally by the library, but there must be one
	 * installed. .app programs have one installed automatically, but this
	 * must be manually done for .exe programs. */
	CActiveScheduler *sched = new (ELeave) CActiveScheduler();
	CleanupStack::PushL(sched);
	CActiveScheduler::Install(sched);

	CConsoleBase *console;
	console = Console::NewL(_L("InsertAdresses"),
			TSize(KConsFullScreen, KConsFullScreen));
	CleanupStack::PushL(console);

	console->Printf(_L("Breaking names...\n"));
	
	CNameBreaker *breaker = CNameBreaker::NewLC();
	breaker->BreakNamesL(console);
	
	console->Printf(_L("\ndone\n[Press any key]"));
	console->Getch();
	
	CleanupStack::PopAndDestroy(3); /* scheduler, console, breaker */
}


GLDEF_C TInt E32Main()
{
	__UHEAP_MARK;
	CTrapCleanup* cleanup = CTrapCleanup::New();
	TRAPD(error, startL());
	__ASSERT_ALWAYS(!error, User::Panic(_L("Panic"), error));
	delete cleanup;
	__UHEAP_MARKEND;
	return 0;
}