/* newdialer.c palmpilot address book decoder/printer (c) 2000-2008 Andrew Senior see http://www.andrewsenior.com/linux/addressbook.html Distributed with no warranty express or implied. */ #include #include #include #include /* Compile with g++ ~/various/codesamples/source/dialer/newdialer.c -o ~/bin/windows/dialer.exe */ #define MAGICNEW 0xcafebabe int iMagic=0; int iFieldsPerRow=0; class Phone { public: int iLabel; char *pczString; Phone(); void Set(int iL, char *pc) {delete [] pczString; iLabel=iL; pczString=pc;} void Set(int iL) { iLabel=iL;} void Read(FILE *pFile); void Print(); ~Phone() { delete [] pczString;} }; class Address { public: int iType; char *pczAddress; char *pczCity; char *pczState; char *pczZip; char *pczCountry; Address(); void Read(FILE *pFile); void Print(); ~Address() { delete [] pczAddress ;delete [] pczCity;delete [] pczState;delete [] pczZip;delete [] pczCountry;} }; class Category { public: int iIndex; int iID; int iDirty; char *pczCategoryName; char *pczCategoryNameShort; Category(FILE *pFile); Category(int iID, char *pczName, char *pczShortName); virtual ~Category() { delete [] pczCategoryName; delete [] pczCategoryNameShort; } void Print(); void LongPrint(); }; class Entry { public: int iID; int iStatus; int iPosition; int iRecordNumber; // char *pczType; char *pczName; char *pczFirst; char *pczTitle; char *pczCompany; char *pczNickname; Phone P1; Phone P2; Phone P3; Phone P4; Phone P5; Phone P6; Phone P7; #ifdef OLD char *pczAddress; char *pczCity; char *pczState; char *pczZip; char *pczCountry; #else Address A1, A2, A3; #endif char *pczNote; bool bPrivate; int iCategory; char *pczCustom1; char *pczCustom2; char *pczCustom3; char *pczCustom4; int iDisplayPhone; Entry(FILE *pFile); void Print(); virtual ~Entry() { // delete [] pczType; delete [] pczName; delete [] pczFirst; delete [] pczTitle; delete [] pczCompany; delete [] pczNickname; #ifdef OLD delete [] pczAddress; delete [] pczCity; delete [] pczState; delete [] pczZip; delete [] pczCountry; #endif delete [] pczNote; delete [] pczCustom1; delete [] pczCustom2; delete [] pczCustom3; delete [] pczCustom4; } }; Category **ppCats=NULL; int iNCategories=0; int iNRecords; // Global state variables int iVcard=0; int iXML=0; int iDebug=false; bool bNumberLines=false; int iPrintCompanyAsName=0; bool bPrintDeleted=false; typedef enum e_TagType {Tagunknown, Tagtitle, Tagcompany, Tagaddress, Tagcity, Tagstate, Tagzip, Tagcountry, Tagnote, Tagcustom1, Tagcustom2, Tagcustom3, Tagcustom4} t_TagType; char *ppczXMLTags[]={"unknown", "title", "company", "address", "city", "state", "zip", "country", "note", "custom1", "custom2", "custom3", "custom4"} ; char *ppczRecordType[]={"none", "integer", "float", "date", "alpha", "CString", "Boolean", "BitFlag", "RepeatEvent", "Unknown"} ; char *ppczVCARDTags[]={"UNKNOWN", "TITLE", "ORG", "ADDRESS", "CITY", "STATE", "ZIP", "COUNTRY", "NOTE", "!CUSTOM1", "!CUSTOM2", "!CUSTOM3", "!CUSTOM4"} ; // Used to use COMPANY not ORG. Changed for Lotus Notes. typedef enum e_PhoneTypes {Phwork, Phhome, Phfax, Phother, Phemail, Phmain, Phpager, Phcell} t_PhoneTypes; char *ppczXMLPhoneTypes[]={"Work", "Home", "Fax", "Other", "Email", "Main", "Pager", "Cell"}; char *ppczVCARDPhoneTypes[]={"TEL;WORK", "TEL;HOME", "TEL;FAX", "TEL;OTHER", "EMAIL;INTERNET", "TEL;MAIN", "TEL;PAGER", "TEL;CELL"}; char *ppczTextPhoneTypes[]={"work", "home", "fax", "other", "email", "main", "pager", "cell"}; void FlagError(FILE *pFile, char *pczMessage=NULL) { int i=ftell(pFile); fflush(stdout); fprintf(stderr, "Error %s at %d\n", pczMessage, i); exit(1); } int ReadInt(FILE *pFile) { int i; if (pFile==NULL) return(0); fread(&i, 1, sizeof(int), pFile); return(i); } int ReadShort(FILE *pFile) { short i; if (pFile==NULL) return(0); fread(&i, 1, sizeof(short), pFile); return(i); } char *ReadString(FILE *pFile) { char *pc=NULL; unsigned char iLenc; int iLen=0; fread(&iLenc, 1, 1, pFile); iLen=iLenc; // printf("LEN%d \n", iLen); fflush(stdout); if (iLen==255) { unsigned short iLens; fread(&iLens, 1, 2, pFile); iLen=iLens; //if (iDebug) printf("Extra length %d************\n", iLen); } pc=new char [iLen+1]; fread(pc, iLen, 1, pFile); pc[iLen]='\0'; return(pc); } char *ReadStringRecord(FILE *pFile) { int iType=ReadInt(pFile); int iPadding=ReadInt(pFile); if (iType!=5 || iPadding !=0) FlagError(pFile, "String Type wrong"); char *pc=ReadString(pFile); return(pc); } int iValOtherHalf=0; // iType returns the type. if iType >=0 it is what we expect to see int ReadRecord(FILE *pFile, int &iType) { int iInType=ReadInt(pFile); // Not the expected type if (iType>=0 && iType!=iInType) FlagError(pFile, "Record type unexpected"); iType=iInType; int iVal=0; switch (iType) { case 1: iVal=ReadInt(pFile); return(iVal); case 64: case 65: case 66: case 6: case 7: iVal=ReadInt(pFile); return(iVal); case 68: iVal=ReadInt(pFile); iValOtherHalf=ReadInt(pFile); return(iVal); case 5: int iPadding=ReadInt(pFile); if (iPadding !=0) FlagError(pFile, "Padding not zero"); char *pc=ReadString(pFile); // delete [] pc; return((int)pc); case 0: default: fprintf(stderr, "Type %d\n", iType); FlagError(pFile,"Don't know how to deal with a record of type %d\n"); } } void PrintXMLString(char *pc) { for(int i=0; i') printf(">"); else if (pc[i]=='&') printf("&"); else if (pc[i]=='\n') printf("
\n"); else if (pc[i]=='\r') printf(""); else if ((unsigned char)pc[i]>=127 || (unsigned char)pc[i]<32) printf("&%d;", (unsigned char)pc[i]); else printf("%c", pc[i]); } void PrintStringNoBreaks(char *pc) { for(int i=0; i", pcTag); PrintXMLString(pc); printf("\n", pcTag); } Phone::Phone() { iLabel=0; pczString=NULL; } void Phone::Print() { if (iLabel>7) fprintf(stderr, "Unknown phone type\n"); if (iXML) { if (pczString==NULL || *pczString=='\0') return; PrintXMLTag(pczString, ppczXMLPhoneTypes[iLabel], 6); } else if (iVcard) { char pczNoNickname[500]; if (pczString==NULL || *pczString=='\0') return; strcpy(pczNoNickname, pczString); char *pcAtPos=strchr(pczNoNickname,'@'); if (iLabel==4 && pcAtPos!=NULL) do { char *pcSpace=strrchr(pczNoNickname, ' '); if (pcSpace!=NULL && pcSpace>pcAtPos) *pcSpace='\0'; else break; } while (true); if (iLabel==4 && strstr(pczNoNickname, "ibm.com")!=NULL) printf("EMAIL;TYPE=PREF;TYPE=X-LOTUS-NOTES:%s\n", pczNoNickname); else printf("%s:%s\n", ppczVCARDPhoneTypes[iLabel], pczNoNickname); } else { if (pczString!=NULL && *pczString!='\0') printf("[%s]:%s, ", ppczTextPhoneTypes[iLabel], pczString); else printf(", "); } } void Phone::Read(FILE *pFile) { int iType=ReadInt(pFile); if (iType!=1) FlagError(pFile, "Phone type not 1\n"); iLabel=ReadInt(pFile); delete [] pczString; pczString=ReadStringRecord(pFile); if (iDebug) printf("Phone %d %s\n", iLabel, pczString); } Category::Category(FILE *pFile) { iIndex=ReadInt(pFile); iID=ReadInt(pFile); iDirty=ReadInt(pFile); pczCategoryName=ReadString(pFile); pczCategoryNameShort=ReadString(pFile); } Category::Category(int iID, char *pczN, char *pczShort) { iIndex=iID; iID=iID; iDirty=0; pczCategoryName=pczN; pczCategoryNameShort=pczShort; } void Category::LongPrint() { printf("Cat: %3d %3d %s\n", iIndex, iID, pczCategoryName); } void Category::Print() { printf("<%s>", pczCategoryName); } void PrintOneItem(char *pczItem, int iTag, int iXMLIndent) { if (iXML) PrintXMLTag(pczItem, ppczXMLTags[iTag], 2*iXMLIndent); else if (iVcard) { if (ppczVCARDTags[iTag][0]!='!' && *pczItem!='\0') { if (iPrintCompanyAsName) printf("N:%s\n", pczItem); printf("%s:%s\n", ppczVCARDTags[iTag], pczItem); } } else { if (pczItem!=NULL && strlen(pczItem)!=0) PrintStringNoBreaks(pczItem); printf(", "); // printf("%s, ", pczItem); } } void PrintName(char *pcN, char *pcF) { if (iXML) { PrintXMLTag(pcN, "lastname",4); PrintXMLTag(pcF, "firstname",4); } else if (iVcard) { if (pcN!=NULL && strlen(pcN)!=0) { if (pcF!=NULL && strlen(pcF)!=0) printf("FN:%s, %s\nN:%s;%s\n", pcN,pcF, pcN, pcF); else printf("FN:%s\nN:%s\n", pcN, pcN); } else printf("FN:%s\nN:%s\n", pcF, pcF); } else printf("%s, %s, ", pcN, pcF); } void PrintRecordHeader(int iPosition) { if (iXML) printf(" \n %d\n", iPosition); else if (iVcard) { time_t TNow=time(NULL); struct tm *pTMNow=localtime(&TNow); printf("BEGIN:VCARD\nVERSION:2.1\nREV:%4d%02d%02dT%02d%02d%02d\n", pTMNow->tm_year+1900, pTMNow->tm_mon+1, pTMNow->tm_mday, pTMNow->tm_hour, pTMNow->tm_min, pTMNow->tm_sec); if (bNumberLines) printf("RECORDNUMBER: %d\n",iPosition); } else if (bNumberLines) printf("<%d>: ",iPosition); } Address::Address() { iType=1; pczAddress=NULL; pczCity=NULL; pczState=NULL; pczZip=NULL; pczCountry=NULL; } void Address::Print() { PrintOneItem(pczAddress, Tagaddress, 4); PrintOneItem(pczCity, Tagcity, 4); PrintOneItem(pczState, Tagstate, 4); PrintOneItem(pczZip, Tagzip, 4); PrintOneItem(pczCountry, Tagcountry, 4); } void Address::Read(FILE *pFile) { pczAddress=ReadStringRecord(pFile); pczCity=ReadStringRecord(pFile); pczState=ReadStringRecord(pFile); pczZip=ReadStringRecord(pFile); pczCountry=ReadStringRecord(pFile); } void Entry::Print() { int iPrintCompanyAsNameTemp=0; PrintRecordHeader(iRecordNumber); if (strlen(pczName)!=0 || strlen(pczFirst)!=0) PrintName(pczName, pczFirst); else iPrintCompanyAsNameTemp=1; // printf("%s %s\n", pczName, pczFirst); PrintOneItem(pczTitle, Tagtitle, 4); iPrintCompanyAsName=iPrintCompanyAsNameTemp; PrintOneItem(pczCompany, Tagcompany, 4); iPrintCompanyAsName=0; P1.Print(); P2.Print(); P3.Print(); P4.Print(); P5.Print(); P6.Print(); P7.Print(); if (pczNickname && iVcard) printf("NICKNAME:%s\n", pczNickname); #ifdef OLD PrintOneItem(pczAddress, Tagaddress, 4); PrintOneItem(pczCity, Tagcity, 4); PrintOneItem(pczState, Tagstate, 4); PrintOneItem(pczZip, Tagzip, 4); PrintOneItem(pczCountry, Tagcountry, 4); #else A1.Print(); A2.Print(); A3.Print(); #endif PrintOneItem(pczNote, Tagnote, 4); PrintOneItem(pczCustom1, Tagcustom1, 4); PrintOneItem(pczCustom2, Tagcustom2, 4); PrintOneItem(pczCustom3, Tagcustom3, 4); PrintOneItem(pczCustom4, Tagcustom4, 4); if (iXML) printf(" \n"); else if (iVcard) printf("END:VCARD\n"); else { if (iCategory>=0 && iCategory<=iNCategories) printf("<%s>", ppCats[iCategory]->pczCategoryName); printf("\n"); } fflush(stdout); } // Constructor for Entry Entry::Entry(FILE *pFile) { pczFirst=NULL; pczName=NULL; pczTitle=NULL; pczCompany=NULL; pczNickname=NULL; #ifdef OLD pczAddress=NULL; pczCity=NULL; pczState=NULL; pczZip=NULL; pczCountry=NULL; #endif pczNote=NULL; pczCustom1=NULL; pczCustom2=NULL; pczCustom3=NULL; pczCustom4=NULL; int iType=1; if (iMagic==MAGICNEW) { for(int i=0;i< iFieldsPerRow; i++) { iType=-1; int iRec=ReadRecord(pFile, iType); if (iType==5) { char *pc=(char*)iRec; if (iDebug) printf("%d/ %d %s\n", i, iType, pc); switch (i) { case 13: pczFirst=pc; break; case 14: pczName=pc; break; case 16: pczTitle=pc; break; case 18: pczNote=pc; break; case 19: P1.Set(0, pc); break; case 20: P2.Set(0, pc); break; case 21: P3.Set(0, pc); break; case 22: P4.Set(0, pc); break; case 23: P5.Set(0, pc); break; case 24: P6.Set(0, pc); break; case 25: P7.Set(0, pc); break; #ifdef OLD case 43: pczAddress=pc; break; case 44: pczCity=pc; break; case 45: pczState=pc; break; case 46: pczZip=pc; break; case 47: pczCountry=pc; break; #else case 43: A1.pczAddress=pc; break; case 44: A1.pczCity=pc; break; case 45: A1.pczState=pc; break; case 46: A1.pczZip=pc; break; case 47: A1.pczCountry=pc; break; case 49: A2.pczAddress=pc; break; case 50: A2.pczCity=pc; break; case 51: A2.pczState=pc; break; case 52: A2.pczZip=pc; break; case 53: A2.pczCountry=pc; break; case 55: A3.pczAddress=pc; break; case 56: A3.pczCity=pc; break; case 57: A3.pczState=pc; break; case 58: A3.pczZip=pc; break; case 59: A3.pczCountry=pc; break; #endif // case 14: pcz=pc; break; // case 14: pcz=pc; break; default: delete [] pc; } } else { int iAddressType=0; switch (i) { case 2: iStatus=iRec; break; case 5: iCategory=iRec; break; case 26: P1.Set(iRec); break; case 27: P2.Set(iRec); break; case 28: P3.Set(iRec); break; case 29: P4.Set(iRec); break; case 30: P5.Set(iRec); break; case 31: P6.Set(iRec); break; case 32: P7.Set(iRec); break; #ifdef OLD case 42: iAddressType=iRec; break; // 1=Home 0=work #else case 42: A1.iType=iRec; break; // 1=Home 0=work case 48: A2.iType=iRec; break; // 1=Home 0=work case 54: A3.iType=iRec; break; // 1=Home 0=work #endif default: if (iDebug) if (iType==68) printf("%d/ %d (%d:%d),", i, iType, iRec, iValOtherHalf); else printf("%d/ %d (%d),", i, iType, iRec); } } } if (iDebug) printf("Return\n"); fflush(stdout); return; } iID=ReadRecord(pFile, iType); iStatus=ReadRecord(pFile, iType); iPosition=ReadRecord(pFile, iType); pczName=ReadStringRecord(pFile); if (iDebug) printf("Name %s\n", pczName); pczFirst=ReadStringRecord(pFile); if (iDebug) printf("First %s\n", pczFirst); pczTitle=ReadStringRecord(pFile); pczCompany=ReadStringRecord(pFile); if (iDebug) printf("Company %s\n", pczCompany); P1.Read(pFile); P2.Read(pFile); P3.Read(pFile); P4.Read(pFile); P5.Read(pFile); #ifdef OLD pczAddress=ReadStringRecord(pFile); pczCity=ReadStringRecord(pFile); pczState=ReadStringRecord(pFile); pczZip=ReadStringRecord(pFile); pczCountry=ReadStringRecord(pFile); #else A1.Read(pFile); #endif pczNote=ReadStringRecord(pFile); int iDummy=ReadInt(pFile); bPrivate=ReadInt(pFile); iDummy=ReadInt(pFile); iCategory=ReadInt(pFile); pczCustom1=ReadStringRecord(pFile); pczCustom2=ReadStringRecord(pFile); pczCustom3=ReadStringRecord(pFile); pczCustom4=ReadStringRecord(pFile); iDummy=ReadInt(pFile); iDisplayPhone=ReadInt(pFile); } void ReadHeader(FILE *pFile) { iMagic=ReadInt(pFile); if (iDebug) printf("Magic 0x%04x\n", iMagic); if (iMagic==MAGICNEW) { char *pczIntro=ReadString(pFile); if (iDebug) printf("Intro %s**\n", pczIntro); char c='a'; int iSkipped=0; while(c!='\0') { c=fgetc(pFile); iSkipped++; printf("%02x", c); } char *pczBA=ReadString(pFile); if (iDebug) printf("Skipped %d BA %s\n", iSkipped, pczBA); int iDummy=ReadInt(pFile); iDummy=ReadInt(pFile); iDummy=ReadInt(pFile); iDummy=ReadInt(pFile); iDummy=ReadInt(pFile); iDummy=ReadInt(pFile); // c=fgetc(pFile); delete [] pczIntro; delete [] pczBA; } char *pczFilename=ReadString(pFile); if (iDebug) printf("Filename %s\n", pczFilename); char *pczTableString=ReadString(pFile); if (iDebug) printf("TableString %s\n", pczTableString); if (iMagic==MAGICNEW) { char c='\0'; int iSkipped=0; for(int k=0; k<10; k++) c=fgetc(pFile); if (iDebug) printf("Skipped %d\n", iSkipped); for(int j=0; j<9; j++) { char *pczBAS=ReadString(pFile); if (iDebug) printf("Cust: %s\n", pczBAS); int iT=ReadInt(pFile); delete [] pczBAS; } c='\0'; for(int k=0; k<42; k++) c=fgetc(pFile); } int iNextFree=ReadInt(pFile); if (iDebug) printf("%d is next Free\n", iNextFree); iNCategories=ReadInt(pFile); if (iDebug) printf("%d Categories\n", iNCategories); ppCats=new Category *[iNCategories]; ppCats[0]=new Category(0, "Unfiled", "Unfiled"); for (int i=1; i<=iNCategories; i++) { ppCats[i]=new Category(pFile); if (iDebug) printf("%d <%s>\n", i, ppCats[i]->pczCategoryName); } int iResource=ReadInt(pFile); iFieldsPerRow=ReadInt(pFile); int iIDPos=ReadInt(pFile); int iStatusPos=ReadInt(pFile); int iSchemaPlacementPos=ReadInt(pFile); int iSchemaFieldCount=ReadShort(pFile); for (int iS=0; iS %s\n", iS, iField, ppczRecordType[(iField<9)?iField:9]); } int iNEntries=ReadInt(pFile); iNRecords=iNEntries/iFieldsPerRow; if (iDebug) printf("Resource %d iIDPos %d StatusPos %d SSPos %d SchemaFieldCount %d\n", iResource, iIDPos, iStatusPos, iSchemaPlacementPos, iSchemaFieldCount); if (iDebug) printf("%d records %d fields / %d FPR \n", iNRecords, iNEntries, iFieldsPerRow); if (iMagic==MAGICNEW) { for(int k=0; k<0; k++) int iT=ReadInt(pFile); } } void PrintFileHeader() { if (iXML) { printf("\n"); printf("\n"); } else if (iVcard) ;// printf("VCARD\n"); else ; } void PrintFileFooter() { if (iXML) { printf("\n"); } else if (iVcard) ; else ; fflush(stdout); } main (int iArgC, char **ppcArgV) { char ch; FILE *pFile=stdin; int iArg=1; if (iArgC>=3 && strncmp(ppcArgV[1], "-t",2)==0) { pFile=fopen(ppcArgV[2], "rb"); // return(ToDoList(pFile, (iArgC>=4)?atoi(ppcArgV[3]):-1)); } while(iArgiArg) pFile=fopen(ppcArgV[iArg], "rb"); else pFile=stdin; if (pFile==NULL) { fprintf(stderr, "Couldn't open file\n"); exit(1); } ReadHeader(pFile); PrintFileHeader(); for(int iR=0; iR