// C program to decipher the Palm pilot database format. // (c) Andrew Senior 2003-7 // This code may be used free of charge for non-commercial purposes // and may be redistributed so long as this header is preserved. // I make no representation about its suitability of fitness for any purpose. // You use it at your own risk. // Compile with, for instance: // g++ -o dialerxml dialerxml.c // Use as: // For address book: dialer /cygdrive/c/WorkPad//address/address.dat // For address book in vcard format: dialer /cygdrive/c/WorkPad//address/address.dat -v // For address book in XML format: dialer /cygdrive/c/WorkPad//address/address.dat -x // For todolists: dialer /cygdrive/c/WorkPad//todo/todo.dat -t // For todolists (one category #n): dialer /cygdrive/c/WorkPad//todo/todo.dat -t #include "stdio.h" #include "malloc.h" #include "stdlib.h" #include "strings.h" #include #define NEWFIELD '\05' #define NEWREC 0x7f #define PHONENO 0x01 #define ENDNOTES 0x06 //#define GETCHAR(x) getchar() #define GETCHAR(x) fgetc(x) #define DOINT PrintInt #define SKIP SkipBytes //#define SKIP CodeChars int iNCats=0; int iRecordNumber=0; int iNumberLines=0; char **pcCategories=NULL; int *piCategories=NULL; FILE *pOutFile=NULL; // Global state variables int iVcard=0; int iXML=0; int iDebug=0; 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 *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"}; int ReadInt(FILE *fp) { int iDummy; fread(&iDummy, 1, sizeof(int), fp); if (pOutFile) fwrite(&iDummy, 1, sizeof(int), pOutFile); // SwapInt(&iDummy); return(iDummy); } void OneInt(FILE *fp) { int iDummy=ReadInt(fp); if (iDebug) printf("{%d}", iDummy); } 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); } char * GetCategory(int Cat) { int i; for(i=0; i<=iNCats; i++) if (piCategories[i]==Cat) return(pcCategories[i]); return(""); } int SwapInt(int *pi) { char *pc=(char *)pi; char c=pc[0]; pc[0]=pc[3]; pc[3]=c; c=pc[1]; pc[1]=pc[2]; pc[2]=c; } int ExpectInt(FILE *fp, int iExpect) { int iVal=ReadInt(fp); if (feof(fp)) return(1); if (iVal==iExpect) return(0); // fprintf(stdout,"** Exception expected %d got %d\n", iExpect, iVal); return(1); } int PrintInt(FILE *fp) { int iD=ReadInt(fp); printf("<%d>"); return(iD); } int PrintInts(FILE *fp, int iN) { printf("<"); int i; for(i=0; i"); return(iN); } int CodeChar(FILE *fp) { unsigned char ch=GETCHAR(fp); if (pOutFile) fwrite(&ch, 1, sizeof(char), pOutFile); printf("<%2x>", ch); } int CodeChars(FILE *fp, int iCt) { int i; putchar('<'); for(i=0; i'); return(feof(fp)); } void SkipTo(FILE *fp, int c) { int i=0; while(c!=GETCHAR(fp)) { i++; if (feof(fp)) return; if (pOutFile) fwrite(&c, 1, sizeof(char), pOutFile); } // printf("Skipped %d\n", i); return; } char *ReadString(FILE *fp) { char *pc=NULL; unsigned char iLenc; int iLen=0; fread(&iLenc, 1, 1, fp); iLen=iLenc; // printf("LEN%d \n", iLen); fflush(stdout); if (iLen==255) { unsigned short iLens; fread(&iLens, 1, 2, fp); iLen=iLens; //printf("Extra length %d************\n", iLen); } pc=(char *)malloc(iLen+1); fread(pc, iLen, 1, fp); pc[iLen]='\0'; return(pc); } int PrintShortString(FILE *fp) { char *pc; pc=ReadString(fp); PrintStringNoBreaks(pc); free(pc); return(0); } int IgnoreShortString(FILE *fp) { char *pc; pc=ReadString(fp); free(pc); return(0); } int GetTwoIntString(FILE *fp, int &i1, int &i2, char *&pc) { i1=ReadInt(fp); i2=ReadInt(fp); pc=ReadString(fp); } int TwoIntString(FILE *fp, int iPrint=1) { if (iVcard) iPrint=0; int i1=ReadInt(fp); int i2=ReadInt(fp); fflush(stdout); if (iPrint) { PrintShortString(fp); printf(", "); } else IgnoreShortString(fp); } int SkipBytes(FILE *fp, int iLen) { int i; for(i=0; i7) fprintf(stderr, "Unknown phone type\n"); if (iXML) { if (*pcS=='\0') return(0); PrintXMLTag(pcS, ppczXMLPhoneTypes[ch], 6); } else if (iVcard) { if (*pcS=='\0') return(0); if (ch==4 && strstr(pcS, "ibm.com")!=NULL) printf("EMAIL;TYPE=PREF;TYPE=X-LOTUS-NOTES:%s\n", pcS); else printf("%s:%s\n", ppczVCARDPhoneTypes[ch], pcS); } else { if (*pcS!='\0') printf("[%s]:%s, ", ppczTextPhoneTypes[ch], pcS); else printf(", "); } return(1); } void PrintForVcard(int iType, char *pc) { char pct[100]; if (*pc=='\0') return; strcpy(pct, pc); if (strchr(pct,'@')!=NULL) { char *pca=strchr(pct,' '); if (pca) *pca='\0'; } else for(int i=strlen(pct)-1; i>=0; i--) if (! (( pct[i]>='0' && pct[i]<='9') || ( pct[i]>='A' && pct[i]<='Z'))) for(int j=i; j> %s\n", pcNote); } free(pcNote); free(pc); } fclose(fp); } void PrintRecordHeader() { if (iXML) printf(" \n %d\n", iRecordNumber); 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 (iNumberLines) printf("RECORDNUMBER: %d\n",iRecordNumber); } else if (iNumberLines) printf("<%d>: ",iRecordNumber); } void PrintFileHeader() { if (iXML) { printf("\n"); printf("\n"); } else if (iVcard) ;// printf("VCARD\n"); else ; } void PrintCategory(int iCategory) { if (iXML) PrintXMLTag(GetCategory(iCategory), "category",4); else if (iVcard) ; else printf("<%s>", GetCategory(iCategory)); } void PrintFileFooter() { if (iXML) { printf("\n"); } else if (iVcard) ; else ; fflush(stdout); } void PrintRecordFooter() { if (iXML) printf(" \n"); else if (iVcard) printf("END:VCARD\n"); else printf("\n"); fflush(stdout); } void PrintName(char *pcN, char *pcF) { if (iXML) { PrintXMLTag(pcN, "lastname",4); PrintXMLTag(pcF, "firstname",4); } else if (iVcard) { printf("FN:%s, %s\nN:%s;%s\n", pcN,pcF, pcN, pcF); } else printf("%s, %s, ", pcN, pcF); } int iPrintCompanyAsName=0; void PrintOneItem(FILE *fp, t_TagType iTag, int iXMLIndent) { char *pc; int i1, i2; GetTwoIntString(fp, i1, i2, pc); if (iDebug) printf("<%d, %d>", i1, i2); if (iXML) PrintXMLTag(pc, ppczXMLTags[iTag], 2*iXMLIndent); else if (iVcard) { if (ppczVCARDTags[iTag][0]!='!' && *pc!='\0') { if (iPrintCompanyAsName) printf("N:%s\n", pc); printf("%s:%s\n", ppczVCARDTags[iTag], pc); } } else { PrintStringNoBreaks(pc); printf(", "); // printf("%s, ", pc); } free(pc); } void PrintOneRecord(FILE *fp) { PrintRecordHeader(); int iC; int i1, i2; char *pc, *pcN, *pcF; GetTwoIntString(fp, i1, i2, pcN); GetTwoIntString(fp, i1, i2, pcF); // Don't print null strings here - if it's a company print the company name instead int iPrintCompanyAsNameTemp=0; if (strlen(pcN)!=0 || strlen(pcF)!=0) PrintName(pcN, pcF); else iPrintCompanyAsNameTemp=1; free(pcN); free(pcF); PrintOneItem(fp, Tagtitle, 4); iPrintCompanyAsName=iPrintCompanyAsNameTemp; PrintOneItem(fp, Tagcompany, 4); iPrintCompanyAsName=0; for(iC=0; iC<5; iC++) PhoneNumber(fp); PrintOneItem(fp, Tagaddress, 4); PrintOneItem(fp, Tagcity, 4); PrintOneItem(fp, Tagstate, 4); PrintOneItem(fp, Tagzip, 4); PrintOneItem(fp, Tagcountry, 4); PrintOneItem(fp, Tagnote, 4); OneInt(fp); int iPrivate=ReadInt(fp); OneInt(fp); int iCategory=ReadInt(fp); PrintCategory(iCategory); PrintOneItem(fp, Tagcustom1, 4); PrintOneItem(fp, Tagcustom2, 4); PrintOneItem(fp, Tagcustom3, 4); PrintOneItem(fp, Tagcustom4, 4); OneInt(fp); int iPreferred=ReadInt(fp); for(iC=0; iC<3; iC++) OneInt(fp); int iDeleted=ReadInt(fp); //129 is deleted OneInt(fp); OneInt(fp); PrintRecordFooter(); } void ReadBookHeaderOrig(FILE *fp) { short n; int iRV=fread(&n, 1, sizeof(short), fp); SkipTo(fp, '\n'); SkipTo(fp, 0); SkipBytes(fp,2); ReadCategories(fp,iDebug); SkipTo(fp, 255); SkipTo(fp, 127); } void ReadBookHeader(FILE *fp) { int i; short n; OneInt(fp); char *pczProgName=ReadString(fp); if (iDebug) printf("%s\n", pczProgName); free(pczProgName); char *pczCustom=ReadString(fp); // if (iDebug) // printf("%s\n", pczCustom); free(pczCustom); OneInt(fp); fflush(stdout); ReadCategories(fp,iDebug); fflush(stdout); SkipTo(fp, 255); SkipTo(fp, 127); } int main (int iArgC, char **ppcArgV) { iNCats=0; char ch; FILE *fp=stdin; int iArg=1; if (iArgC>=3 && strncmp(ppcArgV[1], "-t",2)==0) { fp=fopen(ppcArgV[2], "rb"); return(ToDoList(fp, (iArgC>=4)?atoi(ppcArgV[3]):-1)); } while(1) { if (strncmp(ppcArgV[iArg], "-v",2)==0) { iVcard=1; iArg++; } else if (strncmp(ppcArgV[iArg], "-x",2)==0) { iXML=1; iArg++; } else if (strncmp(ppcArgV[iArg], "-n",2)==0) { iNumberLines=true; iArg++; } else if (strncmp(ppcArgV[iArg], "-d",2)==0) { iDebug=1; iArg++; } else break; } if (iArgC>iArg) fp=fopen(ppcArgV[iArg], "rb"); else fp=stdin; if (fp==NULL) { fprintf(stderr, "Couldn't open file\n"); exit(1); } ReadBookHeader(fp); PrintFileHeader(); while (!feof(fp)) { PrintOneRecord(fp); iRecordNumber++; } PrintFileFooter(); // Delete categories return(0); }