Dialer.c program to read palm address book

Click here for an explanation This has been superseded. Follow the link above for the new version.
// C program to decipher the Palm pilot database format. 
// (c) Andrew Senior 2003
// 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 dialer dialer.c

// Use as: 

// For address book: dialer /cygdrive/c/WorkPad/<username>/address/address.dat
// For address book in vcard format: dialer /cygdrive/c/WorkPad/<username>/address/address.dat -v
// For todolists:  dialer /cygdrive/c/WorkPad/<username>/todo/todo.dat -t
// For todolists (one category #n):  dialer /cygdrive/c/WorkPad/<username>/todo/todo.dat -t <n>

#include "stdio.h"
#include "malloc.h"
#include "stdlib.h"
#include "strings.h"

#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;
char **pcCategories=NULL;
int *piCategories=NULL;
FILE *pOutFile=NULL;
int iVcard=0;

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 ReadInt(FILE *fp)
{
  int iDummy;
  fread(&iDummy, 1, sizeof(int), fp);
  if (pOutFile)
    fwrite(&iDummy, 1, sizeof(int), pOutFile);

//  SwapInt(&iDummy);
  return(iDummy);
}
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<iN; i++)
    {
      int iD=ReadInt(fp);
      printf("%3d", iD);
    }
  printf(">");
  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<iCt; i++)
  {
  unsigned char ch=GETCHAR(fp);
  printf("%2x", ch);
  }
  putchar('>');
  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);
  int i;
  for(i=0; i<iLen; i++)
  {
    if (pc[i]=='\n')
      pc[i]='\\';
    if (pc[i]=='\r')
      pc[i]=' ';
  }
  pc[iLen]='\0';
  return(pc);
}
int PrintShortString(FILE *fp)
{
      char *pc;
      pc=ReadString(fp);
      printf(pc);
      free(pc);
      return(0);
}
int IgnoreShortString(FILE *fp)
{
      char *pc;
      pc=ReadString(fp);
      free(pc);
      return(0);
}
int TwoIntString(FILE *fp, int iPrint=1)
{

if (iVcard) 
iPrint=0;
  ReadInt(fp);
  ReadInt(fp);
  fflush(stdout);
  if (iPrint)
  {
    PrintShortString(fp);
  printf(", ");
  }
  else
    IgnoreShortString(fp);
}

int SkipBytes(FILE *fp, int iLen)
{
  int i;
  for(i=0; i<iLen; i++)
  {
    GETCHAR(fp);
  }
  return(feof(fp));
}
  

int TypeChar(unsigned char ch)
{
  if (iVcard)
 switch (ch)
  {
  case 0x01:
    printf("TEL;HOME:");
    break;
  case 0x0:
    printf("TEL;WORK:");
    break;
  case 0x02:
    printf("TEL;FAX:");
    break;
  case 0x04:
    printf("EMAIL;INTERNET:");
    break;
  case 0x07:
    printf("TEL;CELL:");
    break;
  default:
    printf("[%x]:", ch);
    break;
  }
else
  switch (ch)
  {
  case 0x01:
    printf("[Home]:");
    break;
  case 0x0:
    printf("[Work]:");
    break;
  case 0x02:
    printf("[Fax]:");
    break;
  case 0x04:
    printf("[Email]:");
    break;
  case 0x07:
    printf("[Cell]:");
    break;
  default:
    printf("[%x]:", ch);
    break;
  }
}
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<strlen(pct);j++)
          pct[j]=pct[j+1];
    TypeChar(iType);
    printf("%s\n", pct);
}

int ReadCategories(FILE *fp, int iPrint)
{
  int iLabel=0, iDummy=0, i;
  iNCats=ReadInt(fp);
    if (iPrint)
  printf("Categories: %d\n", iNCats);
  piCategories=(int*)malloc(sizeof(int)*(1+iNCats));
  pcCategories=(char**)malloc(sizeof(char*)*(1+iNCats));
  piCategories[0]=0;  
  pcCategories[0]="Unfiled";
  for (i=0; i<iNCats; i++)
  {
    piCategories[i+1]=iLabel=ReadInt(fp);
    iDummy=ReadInt(fp);
    iDummy=ReadInt(fp);
    char *pc=ReadString(fp);
    if (iPrint)
      printf("Category %d %s ", iLabel, pc);
    pcCategories[i+1]=pc;
    pc=ReadString(fp);
    if (iPrint)
      printf("%s\n", pc);
    free(pc);
  }
}

int PhoneNumber(FILE *fp)
{
  unsigned char ch;
  int iDummy, iType;
  iDummy=ReadInt(fp);
  if (iDummy!=1) printf("EXCEPTION3 %d ", iDummy);
  iType=ReadInt(fp);
  iDummy=ReadInt(fp);
  if (iDummy!=5) printf("EXCEPTION3 %d ", iDummy);
  iDummy=ReadInt(fp); 
  if (iDummy!=0) printf("EXCEPTION3 %d ", iDummy);
  char *pc;
  pc=ReadString(fp);
  if (!iVcard)
{
  if (pc[0]!='\0')
  {
    TypeChar(iType);
    printf(pc);
  }
    printf(", ");
}
  else
    PrintForVcard(iType, pc);
  free(pc);
  fflush(stdout);
}

int ToDoList(FILE *fp, int iCatOnly)
{
  int iDummy=ReadInt(fp);
  char *pc=NULL;
  pc=ReadString(fp);
  free(pc);
  pc=ReadString(fp);
  free(pc);
  if (iCatOnly<0)
    printf("%s\n", pc);
//  SkipBytes(fp, 44);
  ReadInt(fp);
  ReadCategories(fp, (iCatOnly<0)?1:0);
  SkipBytes(fp, 46);
  while(!feof(fp))
  {
   ExpectInt(fp,1);
   if (feof(fp))
     break;
  int iTimeStamp=ReadInt(fp);
   ExpectInt(fp,1);
     ExpectInt(fp,0);
   ExpectInt(fp,1);
  int iIndex=ReadInt(fp);

  ExpectInt(fp,5);
  ExpectInt(fp,0);
  pc=ReadString(fp);
  ExpectInt(fp,3);
  int iTimeStamp2=ReadInt(fp);
  ExpectInt(fp,6); 
  ExpectInt(fp,0);
  ExpectInt(fp,1);
  int iPriority=ReadInt(fp);
  ExpectInt(fp,6);
  ExpectInt(fp,0);
  ExpectInt(fp,1);
  int iCategory=ReadInt(fp);
  ExpectInt(fp,5);
  ExpectInt(fp,0);
  char *pcNote=ReadString(fp);
  if (iCatOnly<0 || iCatOnly==iCategory)
  {
    // printf("Ind: %4d ", iIndex);
  printf("Pri: %1d ", iPriority);
  if (iCatOnly<0) 
    printf("[%s] ", GetCategory(iCategory));
  if (pc!=NULL)
    printf("%s\n", pc);
  if (pcNote!=NULL && pcNote[0]!='\0')
    printf(">> %s\n", pcNote);
  }
  free(pcNote);
  free(pc); 
  }
  fclose(fp);
}

int main (int iArgC, char **ppcArgV)
{
  iNCats=0;
  char ch;
  FILE *fp=stdin;
  if (iArgC!=1)
    fp=fopen(ppcArgV[1], "rb");
  if (fp==NULL)
    exit(1);
  if (iArgC>=3 && strncmp(ppcArgV[2], "-t",2)==0)
    return(ToDoList(fp, (iArgC>=4)?atoi(ppcArgV[3]):-1));
  if (iArgC>=3 && strncmp(ppcArgV[2], "-v",2)==0)
    {
      printf("VCARD\n");
      iVcard=1;
    }
//    SKIP(fp, atoi(ppcArgV[1]));
//  else
    { 
      SkipTo(fp, '\n');
      SkipTo(fp, 0);
      SkipBytes(fp,2);
      ReadCategories(fp,1);
      SkipTo(fp, 255);
      SkipTo(fp, 127);
    }

  while (!feof(fp))
  {
    if (iVcard)
    {
  ReadInt(fp);
  ReadInt(fp);
      char *pcN=ReadString(fp);
  ReadInt(fp);
  ReadInt(fp);
      char *pcF=ReadString(fp);
      printf("BEGIN:VCARD\nVERSION:1.0\nREV:%4d%02d%02dT%02d%02d%02d\n", 2003,8,15,10,0,0);
      printf("FN:%s, %s\nN:%s;%s\n", pcN,pcF, pcN, pcF);
      TwoIntString(fp,0);
      TwoIntString(fp,0);
    }
    else
    {
    TwoIntString(fp);
    TwoIntString(fp);
    TwoIntString(fp);
    TwoIntString(fp);
    fflush(stdout);
    }
    int iRV=0;
    int iC;
//    CodeChar(fp);
    // Print a whole record. 
    for(iC=0; iC<5; iC++)
      PhoneNumber(fp);
if (iVcard)
{
    for(iC=0; iC<5; iC++)
      TwoIntString(fp,0);
    TwoIntString(fp,0); // This is the Note
      int iDummy=ReadInt(fp);
      iDummy=ReadInt(fp);
      iDummy=ReadInt(fp);
//      int iPos=ftell(fp);
      int iCategory=ReadInt(fp);
//      printf("[[%d %d]] ", iPos, iCategory);
      //    printf("<%s>", GetCategory(iCategory));
      TwoIntString(fp,0);
      TwoIntString(fp,0);
      TwoIntString(fp,0);
      TwoIntString(fp,0);
      for(iC=0; iC<8; iC++)
        iDummy=ReadInt(fp);
      printf("END:VCARD\n");
}
else
{
    for(iC=0; iC<5; iC++)
      TwoIntString(fp);
//    printf("GENRECORD\n");
    fflush(stdout);
    TwoIntString(fp); // This is the Note
      int iDummy=ReadInt(fp);
      iDummy=ReadInt(fp);
      iDummy=ReadInt(fp);
//      int iPos=ftell(fp);
      int iCategory=ReadInt(fp);
//      printf("[[%d %d]] ", iPos, iCategory);
      printf("<%s>", GetCategory(iCategory));
      TwoIntString(fp);
      TwoIntString(fp);
      TwoIntString(fp);
      TwoIntString(fp);
      for(iC=0; iC<8; iC++)
        iDummy=ReadInt(fp);
}
/*       if (iDummy!=0x7fffffff)
      {
        printf("EXCEPTION\n");
        return(1);
      }
*/     

    printf("\n");
    fflush(stdout);
  }
  // DELete categories 
  return(0);
}

Andrew Senior
Last modified: Thu Jul 17 00:05:31 EDT 2008