/******************************************************************************/ /* dtmdump.cc */ /* Copyright (C) 2003, S.C. Kremer */ /* */ /* 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; it is available at , */ /* or by writing to the Free Software Foundation, Inc., 59 Temple Place */ /* - Suite 330, Boston, MA 02111-1307, USA. */ /******************************************************************************/ /******************************************************************************/ #include #include #include #include #include #include /******************************************************************************/ /* structure mapping a DTM Parameter ITEMNAME to a function that pretty */ /* prints its contents */ struct PrintMethod { char *name; /* ITEMNAME */ void (*fn_ptr)( unsigned long len, char *data ); /* point to print fn */ }; /******************************************************************************/ /* pretty print function prototypes (need these here to forward refernce */ /* mapping, below) */ void print_unsupported( unsigned long len, char *data ); void print_bit ( unsigned long len, char *data ); void print_time ( unsigned long len, char *data ); void print_ulong ( unsigned long len, char *data ); void print_barray ( unsigned long len, char *data ); void print_uchar ( unsigned long len, char *data ); void print_word ( unsigned long len, char *data ); void print_utf8 ( unsigned long len, char *data ); /******************************************************************************/ /* array of mappings */ /* for efficency this could be sorted alphabetically and then searched using */ /* bsearch, but it seems to run fast enough as is */ struct PrintMethod print_method[] = { { "ATTR", print_bit }, /* common */ { "CTTM", print_time }, /* common */ { "MDTM", print_time }, /* common */ { "SYID", print_ulong }, /* common */ { "CTGR", print_barray }, /* ToDo, Calendar, Addressbook */ { "ETDY", print_time }, /* ToDo */ { "LTDY", print_time }, /* ToDo */ { "FNDY", print_time }, /* ToDo */ { "MARK", print_uchar }, /* ToDo */ { "PRTY", print_uchar }, /* ToDo */ { "TITL", print_utf8 }, /* ToDo */ { "MEM1", print_utf8 }, /* ToDo, Calendar */ { "DSRP", print_utf8 }, /* Calendar */ { "PLCE", print_utf8 }, /* Calendar */ { "TIM1", print_time }, /* Calendar */ { "TIM2", print_time }, /* Calendar */ { "ADAY", print_uchar }, /* Calendar */ { "ARON", print_uchar }, /* Calendar */ { "ARSD", print_uchar }, /* Calendar */ { "ARMN", print_word }, /* Calendar */ { "RTYP", print_uchar }, /* Calendar */ { "RFRQ", print_word }, /* Calendar */ { "RPOS", print_word }, /* Calendar */ { "RDYS", print_uchar }, /* Calendar */ { "REND", print_uchar }, /* Calendar */ { "REDT", print_time }, /* Calendar */ { "ALSD", print_time }, /* Calendar */ { "ALED", print_time }, /* Calendar */ { "MDAY", print_uchar }, /* Calendar */ { "FULL", print_utf8 }, /* Addressbook */ { "NAPR", print_utf8 }, /* Addressbook */ { "TITL", print_utf8 }, /* Addressbook */ { "LNME", print_utf8 }, /* Addressbook */ { "FNME", print_utf8 }, /* Addressbook */ { "MNME", print_utf8 }, /* Addressbook */ { "SUFX", print_utf8 }, /* Addressbook */ { "FLAS", print_utf8 }, /* Addressbook */ { "LNPR", print_utf8 }, /* Addressbook */ { "FNPR", print_utf8 }, /* Addressbook */ { "CPNY", print_utf8 }, /* Addressbook */ { "CPPR", print_utf8 }, /* Addressbook */ { "SCTN", print_utf8 }, /* Addressbook */ { "PSTN", print_utf8 }, /* Addressbook */ { "TEL2", print_utf8 }, /* Addressbook */ { "FAX2", print_utf8 }, /* Addressbook */ { "CPS2", print_utf8 }, /* Addressbook */ { "BSTA", print_utf8 }, /* Addressbook */ { "BCTY", print_utf8 }, /* Addressbook */ { "BSTR", print_utf8 }, /* Addressbook */ { "BZIP", print_utf8 }, /* Addressbook */ { "BCTR", print_utf8 }, /* Addressbook */ { "BWEB", print_utf8 }, /* Addressbook */ { "OFCE", print_utf8 }, /* Addressbook */ { "PRFS", print_utf8 }, /* Addressbook */ { "ASST", print_utf8 }, /* Addressbook */ { "MNGR", print_utf8 }, /* Addressbook */ { "PRFS", print_utf8 }, /* Addressbook */ { "ASST", print_utf8 }, /* Addressbook */ { "MNGR", print_utf8 }, /* Addressbook */ { "BPGR", print_utf8 }, /* Addressbook */ { "CPS1", print_utf8 }, /* Addressbook */ { "TEL1", print_utf8 }, /* Addressbook */ { "FAX1", print_utf8 }, /* Addressbook */ { "HSTA", print_utf8 }, /* Addressbook */ { "HCTY", print_utf8 }, /* Addressbook */ { "HSTR", print_utf8 }, /* Addressbook */ { "HZIP", print_utf8 }, /* Addressbook */ { "HCTR", print_utf8 }, /* Addressbook */ { "HWEB", print_utf8 }, /* Addressbook */ { "DMAL", print_utf8 }, /* Addressbook */ { "MAL1", print_utf8 }, /* Addressbook */ { "SPUS", print_utf8 }, /* Addressbook */ { "GNDR", print_utf8 }, /* Addressbook */ { "BRTH", print_utf8 }, /* Addressbook */ { "ANIV", print_utf8 }, /* Addressbook */ { "NCNM", print_utf8 }, /* Addressbook */ { "CLDR", print_utf8 }, /* Addressbook */ { "MEM1", print_utf8 }, /* Addressbook */ { "GRPS", print_utf8 }, /* Addressbook */ { "SCTG", print_unsupported }, /* Category */ { "TYPE", print_unsupported }, /* Category */ { "COLR", print_unsupported }, /* Category */ { NULL, NULL } }; /******************************************************************************/ /* this function supports the printing of unsupported data, it is used for */ /* development/debugging purposes only */ /* it prints out the data as series of bits (with blanks after every 8) */ void print_unsupported( unsigned long len, char *data ) { unsigned long i; int bit, val; unsigned char x; for (i=0;i=0;bit--) { x = ((unsigned char *)data)[i]; val = (x>>bit) & 1; printf("%d",val); } } } /******************************************************************************/ /* this function is designed to print data of type DATA_ID_BIT *//* it prints the first byte of data as an usigned char */ void print_bit( unsigned long len, char *data ) { printf( "%d", *((unsigned char *)data) ); } /******************************************************************************/ /* this funciton is designed to print data of type DATA_ID_TIME */ /* it uses a bitfield structure to identify all components of time */ /* NOTE: this code is compiler implementation specific - its is only known to */ /* work with the arm-linux-gcc compiler */ /* This is because bitfields are implementation specific. In particulur, on */ /* the arm compiler they seem to be packed tightly, whereas on the x86 */ /* compiler most items are byte aligned. */ void print_time( unsigned long len, char *data ) { static char buffer[256]; /* string to hold ASCII representation of tiem */ struct timestruct { unsigned int junk: 2; /* can anyone tell me what the 2 bits are for? */ unsigned int sec: 6; unsigned int min: 6; unsigned int hour: 5; unsigned int mday: 5; unsigned int mon: 4; unsigned int year: 8; } *ts; static struct tm tm; if (len==0) { printf( "NULL" ); } else { ts = (struct timestruct *)data; /* point to the data */ tm.tm_sec = ts->sec; /* transfer packed data into standard */ tm.tm_min = ts->min; /* unix time structure */ tm.tm_hour = ts->hour; tm.tm_mday = ts->mday; tm.tm_mon = ts->mon-1; tm.tm_year = ts->year; strftime( buffer, 255, "%a %b %e %H:%M:%S %Z %Y", &tm ); printf( buffer ); } } /******************************************************************************/ /* this funciton is designed to print data of type DATA_ID_ULONG */ /* it prints data as an unsigned long int */ void print_ulong( unsigned long len, char *data ) { printf( "%lu", *((unsigned long *)data) ); } /******************************************************************************/ /* this function is designed to print data of type DATA_ID_BARRAY */ /* this feature is currently unsupported, so it just prints the contents */ /* using print_unsupported */ void print_barray( unsigned long len, char *data ) { print_unsupported( len, data ); } /******************************************************************************/ /* this function is designed to print data of type DATA_ID_UCHAR */ /* it prints the data as a single unsigned char */ void print_uchar( unsigned long len, char *data ) { printf( "%d", *((unsigned char *)data) ); } /******************************************************************************/ /* this function is designed to print data of type DATA_ID_WORD */ void print_word( unsigned long len, char *data ) { printf( "%d", *((unsigned int *)data) ); } /******************************************************************************/ /* this function is designed to print data of type DATA_ID_UTF8 */ /* it prints data as an ASCII string, which should be ok for most purposes */ /* should really replace < and > signs here when using XML output! */ void print_utf8( unsigned long len, char *data ) { printf( "%.*s", (int)len, data ); } /******************************************************************************/ /* this function is used to pretty print the given data of type item and */ /* length len. */ /* it selects the appropriate function based on the contents of print_method */ /* This uses a for loop, rather than a binary search which might be */ /* marginally faster if the size of print_method is large enough. */ void pp( char item[4], unsigned long len, UCHAR *data ) { struct PrintMethod *pm; for ( pm = print_method; pm->name!=NULL; pm++ ) { if ( !strncmp( (char *)pm->name, (char *)item, 4 ) ) { printf( " <%.4s>", pm->name ); /* print itemname */ pm->fn_ptr( len, (char *)data ); /* print data using appropriate fn */ printf( "\n", pm->name ); return; } } fprintf( stderr, "Don't know how to print %.4s\n", item ); /* this line should not be reached if print_method is complete */ } /******************************************************************************/ /* This is an incomplete function to print out error messages. The rest */ /* should be added based on the pdf document. */ char *err_name( DTMERR retval ) { switch( retval ) { case 0x00: return "Closed Correctly"; break; case 0x20: return "Cannot write to the designated drive"; break; case 0x42: return "Specified card does not exist"; break; case 0x47: return "Exceeds the stack"; break; default: return "Unknown error code"; break; } } /******************************************************************************/ /* this function prints out the contents of the card given by "card", */ /* assuming that each card contains "itemNum" numbers of items and that */ /* the item names are given in "items". "BoxFHd" is an opened boxhandle, and */ /* "itemname" is the attribute of the outermost XML tag to use. */ DTMERR print_card( int card, UCHAR itemNum, ITEMNAME *items, BOXHANDLE BoxFHd, char *itemname ) { CARD Card; /* data structure holding desired card no, and itemname */ /* for retrieval using _CardRead */ UCHAR item; /* counter over the items */ DATALEN LenMax; /* maximum size of item to retrieve */ DATALEN Len; /* actual size of item retrieved */ UCHAR* Data; /* pointer to item contents */ DTMERR retval; /* return value result */ int first_item; /* flag indicating first item from a given card */ LenMax = 1024; /* allows items upto 1k in length */ Card.CardID = card+1; /* CardID numbered from 1, car from 0 */ first_item = 1; /* assume first item from card */ for (item=0;item\n", itemname, card ); /* wrap it in a tag for the card */ first_item = 0; } pp( (char *)items[item], Len, Data ); /* pretty print it */ } free( Data ); /* free memory */ } printf( "\n", itemname ); /* close tag for card */ return 0; } /******************************************************************************/ /* the program's main function */ int main( int argc, char ** argv ) { BOXHANDLE BoxFHd; /* handle to box file */ ULONG size; /* size in bytes of the box file - not actually used */ USHORT card, /* iterator over cards */ num; /* number of undeleted cards (NOT the actual number */ /* of entries in the box file) */ UCHAR item; /* item iterator */ UCHAR itemNum; /* total number of items on all cards */ ITEMNAME *items; /* names of all the items */ DTMERR retval; /* return value of print_card */ char *BoxFName, /* pointer to name of boxfile */ filename[7]; /* name of boxfile without extension */ char *itemsname, /* outermost XML tag */ *itemname; /* XML tag for a particular card */ /****************************************************************************/ /* process arguments */ if ( (argc!=2) && (argc!=3||(!strcmp(argv[1],"-f")) ) ) { fprintf( stderr, "usage: %s \n", argv[0] ); fprintf( stderr, "usage: %s -f \n", argv[0] ); exit(-1); } if (argc==3) { BoxFName = argv[1]; } else { if (!strcasecmp(argv[1],"ToDo")) BoxFName = "/home/zaurus/Applications/dtm/SLTODO.BOX"; else if (!strcasecmp(argv[1],"Calendar")) BoxFName = "/home/zaurus/Applications/dtm/SLDATE.BOX"; else if (!strcasecmp(argv[1],"Addressbook")) BoxFName = "/home/zaurus/Applications/dtm/SLADRS.BOX"; else if (!strcasecmp(argv[1],"Memo")) BoxFName = "/home/zaurus/Applications/dtm/SLMEMO.BOX"; else if (!strcasecmp(argv[1],"Category")) BoxFName = "/home/zaurus/Applications/dtm/SLFLER.BOX"; else { fprintf( stderr, "%s: Unsupported application \"%s\".", argv[0], argv[2] ); exit(-1); } } /****************************************************************************/ /* figure out appropriate XML tag names */ strncpy( filename, BoxFName + strlen( BoxFName ) - 10, 6 ); filename[6] = '\0'; if ( !strcmp( filename, "SLTODO" ) ) { itemsname = "Tasks"; itemname = "Task"; } else if ( !strcmp( filename, "SLDATE" ) ) { itemsname = "Events"; itemname = "Event"; } else if ( !strcmp( filename, "SLADRS" ) ) { itemsname = "Contacts"; itemname = "Contact"; } else if ( !strcmp( filename, "SLMEMO" ) ) { itemsname = "Memos"; itemname = "Memo"; } else if ( !strcmp( filename, "SLFLER" ) ) { itemsname = "Categories"; itemname = "Category"; } else if ( !strcmp( filename, "slinbox" ) ) { itemsname = "Inbox"; itemname = "Email"; } else if ( !strcmp( filename, "sloutbox" ) ) { itemsname = "Inbox"; itemname = "Email"; } else { fprintf( stderr, "%s: error \"%s\" not supported\n", argv[0], filename ); exit(-1); } /************************************************************************/ /* open file */ BoxFHd = _BoxOpen( (unsigned char *)BoxFName ); if (!BoxFHd) { fprintf( stderr, "%s: BoxOpen(\"%s\") failed\n", argv[0], BoxFName ); exit(-1); } /************************************************************************/ /* compute card number (and box file size) */ _BoxCardTotal( (unsigned char *)BoxFName, &size, &num ); /* compute number of items */ itemNum = _GetItemNum( BoxFHd ); /************************************************************************/ /* get the iten names */ items = (ITEMNAME *)malloc( sizeof(ITEMNAME) * itemNum ); for ( item=0; item\n" ); printf( "\n", filename, filename ); printf( "<%s>\n", itemsname ); retval = 0; for (card=0;retval==0;card++) /* don't loop to num here, it doesn't work */ { retval = print_card( card, itemNum, items, BoxFHd, itemname ); } free( items ); _BoxClose( BoxFHd ); printf( "\n", itemsname ); return 0; }