/* This is ugly, copy&pasted, never cleaned up code. * Original code is (C) 2005 Matias Alejo Garcia * but blame me (Kosta) if anything is ugly, broken or whatever :) * GPL Licenced * * usage: console_contacts * * You need berkeley database 4.2 to compile this. * Get it from http://dev.sleepycat.com/downloads/optreg.html?fname=db-4.2.52.NC.tar.gz&prod=core * configure it: * cd build_unix * ../dist/configure --host=arm-linux * and copy the db.h and .libs/libdb-4.2.so to the build directory * now build this file using * arm-linux-gcc console_contacts.cpp -o console_contacts -L. -ldb-4.2 * and copy it to the phone, together with libdb-4.2.so * you'll propably need to adjust LD_LIBRATY_PATH to the location of libdb-4.2.so * * WARNING: * This piece of code works "fine" on a native.db copied to an x86 pc, * but fails on my Motorola a780, saying -30988: DB_PAGE_NOTFOUND: Requested page not found * * any help is appreciated :) */ #include #include #include #include #include #include #include "db.h" #define BTM_SUBDB 0x020 /* Subdatabases. */ #define DB_HASH_SUBDB 0x02 /* Subdatabases. */ //keep this in sync! static char* fieldname[]={ "index", "display", //display name "nick", "first name", "middle name", "last name", "birthday", "anniversary", "home address", "home city", "home state", "home zip ", "home_country", "work address", "work city", "work state", "work zip ", "work country", "tel home", "tel work", "tel home2", "tel work2", "tel cel1", "tel cel2", "fax", "email1", "email2", "company", "department", "title", "manager", "assistant", "spouse", "children", "notes", "user1", "user2", "url", "category", "photopath", "ringtone", 0 }; class PhoneContact { //QString *field[FieldSize]; public: enum FieldType { f_index=0, f_display, f_nick, f_fn, f_mn, f_ln, f_bday, f_aniv, //7 f_home_addr, f_home_city, f_home_state, f_home_zip, f_home_coun, //12 f_work_addr, f_work_city, f_work_state, f_work_zip, f_work_coun, //17 f_tel_home, f_tel_work, f_tel_home2, f_tel_work2, //21 f_cel1, f_cel2, f_fax, f_email1, f_email2, f_company, f_dtment, //28 f_title, f_manager, f_assistant, f_spouse, f_children, f_notes, //34 f_user1, f_user2, f_url, f_category, f_photograph, f_ringtone, FieldSize //41 }; }; class PhoneContactList { public: PhoneContactList(char* arg = "/ezxlocal/sysDatabase/native.db") { printf("infile: %s\n", arg); infile = arg; //contacts.setAutoDelete( TRUE ); }; int import(); private: char* infile; //QList contacts; int is_sub(DB *dbp, int *yesno); int db_init(DB_ENV *dbenv, char* home, int is_salvage, u_int32_t cache, int *is_privatep); int dump_sub(DB_ENV *dbenv, char* file_name, DB* parent, char* subdb, int e680old); int get_buffer(wchar_t buffer[][255], DBT* key, DBT* data); int get_buffer_old(wchar_t buffer[][255], DBT* key, DBT* data); void phone_invert (wchar_t *field); void record_map(wchar_t buffer[][255]); int readheader (DBT* dbt, unsigned int * out); int readseparator(DBT* data, int pos); static const int DBFIELDS = 37; }; void err_handle (const char *pre, char*msg) { fprintf (stderr, msg); } int PhoneContactList::readheader (DBT* dbt, unsigned int * out){ unsigned int *in; int i=0; in=(unsigned int*)dbt->data; for (i=0;iopen(dbenv, home, DB_USE_ENVIRON | (is_salvage ? DB_INIT_MPOOL : DB_JOINENV), 0) == 0) return (0); printf("db_init: second\n"); /* * An environment is required because we may be trying to look at * databases in directories other than the current one. We could * avoid using an environment iff the -h option wasn't specified, * but that seems like more work than it's worth. * * No environment exists (or, at least no environment that includes * an mpool region exists). Create one, but make it private so that * no files are actually created. */ *is_privatep = 1; if ((ret = dbenv->set_cachesize(dbenv, 0, cache, 1)) == 0 && (ret = dbenv->open(dbenv, home, DB_CREATE | DB_INIT_MPOOL | DB_PRIVATE | DB_USE_ENVIRON, 0)) == 0) return (0); /* An environment is required. */ printf("error creating envrionment %i: %s\n", ret, db_strerror(ret)); dbenv->err(dbenv, ret, "open"); return (1); }; int PhoneContactList::is_sub(DB *dbp, int *yesno) { DB_BTREE_STAT *btsp; DB_HASH_STAT *hsp; int ret; switch (dbp->type) { case DB_BTREE: case DB_RECNO: if ((ret = dbp->stat(dbp, &btsp, DB_FAST_STAT)) != 0) { dbp->err(dbp, ret, "DB->stat"); return (ret); } *yesno = btsp->bt_metaflags & BTM_SUBDB ? 1 : 0; free(btsp); break; case DB_HASH: if ((ret = dbp->stat(dbp, &hsp, DB_FAST_STAT)) != 0) { dbp->err(dbp, ret, "DB->stat"); return (ret); } *yesno = hsp->hash_metaflags & DB_HASH_SUBDB ? 1 : 0; free(hsp); break; case DB_QUEUE: break; case DB_UNKNOWN: default: dbp->errx(dbp, "unknown database type"); return (1); } return (0); }; /* returns: 0 on success, -1 on failure */ int PhoneContactList::import() { DB* dbp; DBC* cursorp; u_int32_t flags; int ret; DBT key,data; int sub,nr=0; char subdb[100]; int subdbfound=0; DB_ENV *dbenv=NULL; int isprivate=0; char* homepath = NULL; //"/ezxlocal"; db_env_create(&dbenv, 0); dbenv->set_errfile(dbenv, stderr); dbenv->set_errpfx(dbenv, __FILE__); if (db_init(dbenv, homepath, 0, 1<<16, &isprivate)) { printf("Could not set db envrionment.\n"); return -1; }; ret=db_create(&dbp,dbenv,0); if (ret==0){ flags=DB_RDONLY; printf("opening db %s\n", infile); ret=dbp->open(dbp,NULL,infile,NULL,DB_BTREE,flags,0); if (ret==0){ printf("Database opened.\n"); DBTYPE dbtype; ret = dbp->get_type(dbp, &dbtype); printf("get_type %i: %s\n", ret, db_strerror(ret)); dbp->set_errcall(dbp,err_handle); dbp->set_errpfx(dbp,__FILE__); ret = dbp->cursor(dbp,NULL,&cursorp,0); printf("cursor %i: %s\n", ret, db_strerror(ret)); /* Initialize our DBTs. */ memset(&key, 0, sizeof(DBT)); memset(&data, 0, sizeof(DBT)); ret = cursorp->c_get(cursorp, &key, &data, DB_FIRST); printf("db ret %i: %s\n", ret, db_strerror(ret)); while (ret == 0) { printf("import() while"); memcpy(subdb, key.data, key.size); subdb[key.size] = '\0'; is_sub(dbp,&sub); if (sub){ if (strcmp("780_contact_table",subdb)==0) { subdbfound=1; nr=dump_sub(dbenv,infile,dbp,subdb, 0); } else if (strcmp("contact_table",subdb)==0) { subdbfound=1; //us_debug(US_CRIT,"**** WARNING. E680 (not i) db file detected...import filter is higly experimental!\n"); nr=dump_sub(dbenv,infile,dbp,subdb, 1); } } ret = cursorp->c_get(cursorp, &key, &data, DB_NEXT); printf("db ret %i: %s\n", ret, db_strerror(ret)); } if(!subdbfound) { //us_debug (US_CRIT,"Couldn't find the right subdatabase. Is this file from a e680i?\n"); } //nr = dump_sub(dbenv, infile, dbp, "780_contact_table", 0); dbp->close(dbp,0); } else { //us_debug (US_CRIT,"db_open: %d failed\n",ret); perror(""); } } else { //us_debug(US_WARN,"db_create: %d\n",ret); } return 0; //TODO }; int PhoneContactList::dump_sub(DB_ENV *dbenv, char* file_name, DB* parent, char* subdb, int e680old) { DB* dbp; DBC* cursorp; int ret; DBT key,data; wchar_t buffer[DBFIELDS+1][255]; int nr=0; printf("subdb: %s\n", subdb); db_create(&dbp,dbenv,0); ret= dbp->open(dbp, NULL, file_name, subdb, DB_UNKNOWN, DB_RDONLY, 0); if (ret==0){ //us_debug (US_DBG, "subdabase: [%s] opened. \n",subdb); dbp->cursor(dbp,NULL,&cursorp,0); memset(&key, 0, sizeof(DBT)); memset(&data, 0, sizeof(DBT)); while ((ret = cursorp->c_get(cursorp, &key, &data, DB_NEXT)) == 0) { if (e680old) get_buffer_old(buffer, &key,&data); else get_buffer(buffer, &key,&data); record_map(buffer); nr++; } dbp->close(dbp,0); } else { //us_debug (US_CRIT, "dbsub: db_open: %d failed\n",ret); perror(""); } return nr; } int PhoneContactList::get_buffer(wchar_t buffer[][255], DBT* key, DBT* data){ unsigned int headoff[DBFIELDS]; char* datastart=(char*)data->data; int i,nf=0,pos; char reversed_fields[]={ 0,0,0,1,1,1,1,1,1,1, 0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0 }; //We temporaly store the key at end swprintf (buffer[DBFIELDS],255,L"%u",*(unsigned int*)(key->data)); //us_debug(US_DBG,"Read key %ls\n",buffer[DBFIELDS]); /*for (i=0; isize; i++) printf ("%c",*(datastart+i));*/ //us_debug(US_DBG,"Reading buffer header\n"); pos=readheader(data,headoff); pos=readseparator(data,pos); //us_debug(US_DBG,"Reading buffer data\n"); nf=0; while ( (*(headoff+nf)) && (nfsize)){ //us_debug(US_HDBG,"Reading field: %3d, pos:%x end:%x size:%x \n", //nf,pos,*(headoff+nf),data->size); for (i=0; ((pos<*(headoff+nf))&&(possize)); i++, pos+=2) buffer[nf][i]=*(datastart+pos)+ (*(datastart+ pos+1 )<<8); buffer[nf][i]=L'\0'; if (reversed_fields[nf]) phone_invert(buffer[nf]); nf++; } if (nf>DBFIELDS){ //us_debug(US_CRIT, "**WARNING**: More fields than expected! Ignoring...\n"); } return 0; } //this should work for e680 (not i) int PhoneContactList::get_buffer_old(wchar_t buffer[][255], DBT* key, DBT* data){ unsigned int low,high,word; char* pdata=(char*)data->data; int i=0,nf=0,pos=0, first=1; swprintf (buffer[DBFIELDS],255,L"%u",*(unsigned int*)(key->data)); //us_debug(US_DBG,"Read key %ls\n",buffer[DBFIELDS]); //pos++; //skip first char //us_debug(US_DBG,"Reading buffer data\n"); nf=0; //number of field, in db while ( (nfsize) && (i< 255)){ /*us_debug(US_HDBG,"Reading field: %3d, pos:%x size:%x *pos: %c \n", nf,pos,data->size,*(pdata+pos));*/ low=*(pdata+pos); pos++; high=*(pdata+pos); pos++; //us_debug(US_HDBG,"L:%u H:%u\n",low,high); word=low+(high<<8); if ( ((!word) && (first!=2)) || ((first==2) &&(word))) { if (first==2) { first++;} if (first==1) { first++; continue;} if (i<2) i=0; buffer[nf][i]=L'\0'; //us_debug(US_HDBG,"Read field [%2d]: %ls\n",nf,buffer[nf]); nf++; i=0; continue; } buffer[nf][i]=word; i++; } if (nf>DBFIELDS){ //us_debug(US_CRIT,"**WARNING**: More fields than expected! Ignoring...\n"); } return 0; } void PhoneContactList::phone_invert (wchar_t *field) { int i, n=wcslen(field); wchar_t t; //printf ("[r]"); for (i=0; i=0)&&(wcslen(buffer[map[i]])>0)) { //FIXME wcscpy (pi_getfield(pi_record,i), buffer[map[i]]); printf("%s: %ls\n", fieldname[i], buffer[map[i]]); /*printf ("NF:%3d %10ls COFF:%10x [src:%3d] %ls:%ls\n", i,contact_fieldname10[i], offset, map[i], c+offset,rec[map[i]]);*/ } } printf("---\n"); //pi_record->type=PI_CONTACT; //pi_data_print(pi_record); //us_debug(US_DBG,"Adding record [%ls]\n",buffer[0]); } int main(int *argc, char **argv) { PhoneContactList l(argv[1]); l.import(); return 0; };