#include #include #include #include #include #include #define FALSE 0 #define TRUE 1 typedef char bool; #define cabName "../btomlin.pfc" #define STRLEN 128 typedef unsigned long UINT32; FILE *cab; enum blocktype { UNKNOWN, INT_LIST, SIMPLE_LIST, PAIR_LIST, INDEX_LIST }; int h1,h2,h3,h4,h5,h6; int ishex(char c) { c = toupper(c); return isdigit(c) || ('A' <= c && c <= 'F'); } int Hex2Dec(c) { c = toupper(c); if (c > '9') return c - 'A' + 10; return c - '0'; } unsigned int EvalHex(char *hexStr) { unsigned int hexVal; int evalErr; int c; evalErr = FALSE; hexVal = 0; while (c = *hexStr++) { if (!ishex(c)) evalErr = TRUE; else hexVal = hexVal * 16 + Hex2Dec(c); } if (evalErr) { hexVal = 0; // Error("Invalid hexadecimal number"); } return hexVal; } // ===================================================================== // Convert an ASCII character to upper case char upcase(char c) { return ('a'<=c) && (c<='z') ? c - ('a'-'A') : c; } // Read a command line and // (optionally) convert to uppercase during input void ReadLine(char *s, int maxlen, int upperonly) { int len=0; char c; while (TRUE) { fflush(stdout); if ((c = getchar()) == EOF) exit(1); if ((c>=' ') && (c<='~')) // valid ASCII characters { if (len < maxlen+1) // if there's still space left { if (upperonly) c=upcase(c); // convert to uppercase s[len++]=c; // store and increment length putchar(c); // echo character } } else { switch (c) // control characters { case 0x7F: // DEL case 0x08: // BS if (len>0) { len--; // remove last character putchar(0x08); // echo destructive backspace putchar(' '); putchar(0x08); } break; case 'U'-0x40: // Ctrl-U = erase line case 0x1B: // ESC = erase line while (len>0) { len--; // remove last character putchar(0x08); // echo destructive backspace putchar(' '); putchar(0x08); } break; case '\n': case '\r': // CR s[len] = 0; // store null terminator putchar('\n'); // echo carriage return fflush(stdout); return; } } } } // Convert a char to its hex digit value int cvthex(char c) { if (c< '0') return -1; if (c<='9') return (c-'0'); if (c< 'A') return -1; if (c<='F') return (c-'A'+10); if (c< 'a') return -1; if (c<='f') return (c-'a'+10); return -1; } // Get next hex number from a command line // 's' is a pointer into the null-terminated command string, passed by reference // flag=0 means okay, flag=1 means end of line, flag=2 means error typedef enum { // Returned flag values from GetHex() GH_good=0, // GetHex "good" status GH_EOL=1, // GetHex "end of line" status GH_bad=2 // GetHex "bad hex character" status } GH_flag; UINT32 GetHex(char **s, GH_flag *flag) { UINT32 n = 0; int digit; // start by eating leading blanks while (**s == ' ') (*s)++; // return an error if at end of line with no hex number if (**s == 0) { *flag = GH_EOL; // set end-of-line flag return 0; // exit if end of line } // return an error if at invalid character with no hex number if (cvthex(**s) == -1) { *flag = GH_bad; // set error flag return 0; // exit if end of line } // now convert as many hex characters as we can find while ((digit=cvthex(**s))>=0) { n = (n << 4) + digit; (*s)++; } *flag = GH_good; // set no-error flag return n; // return hex value } // ===================================================================== void read_cab(void *buf, int len) { int count; count = fread(buf, 1, len, cab); if (count != len) { printf("read_cab: expected %d got %d bytes\n", len, count); exit(1); } } void dump_block(int addr, int type) { unsigned short b1,b2,b3,b4,w; unsigned int i,j,k,n; unsigned char c; if (addr) { fseek(cab, addr, SEEK_SET); read_cab(&b1, 2); read_cab(&b2, 2); read_cab(&b3, 2); read_cab(&b4, 2); if (b2) printf("*** b2 != 0 !!! ***\n"); printf("%.8X: %.4X %.4X %.4X %.4X\n",addr,b1,b2,b3,b4); switch(type) { default: case UNKNOWN: for (i=0; i<16; i++) { read_cab(&n, 4); printf(" %.8X", n); if ((i % 8) == 7) printf("\n"); } break; case INT_LIST: for (i=0; iUnix epoch time = gmtime((time_t *) &n); strftime(s, len, "%a, %d %b %Y %H:%M:%S -0500", time); // your time zone goes here } //#define LONG_MSG void dump_msg_hdr(int addr, int id) { short folder; int subj,subjLen; int body,bodyLen; int from,fromLen; int date; short w,lastRec; int l,i; int n; unsigned char *p,*q,*s,*b,*f,*hdr; unsigned char c; int part; unsigned char t[256]; unsigned char to[16384]; unsigned char cc[16384]; //dump_block(addr,UNKNOWN); fseek(cab, addr+8, SEEK_SET); // skip header read_cab(&folder,2); // folder ID? read_cab(&subj,4); // subject text pointer read_cab(&subjLen,4); // subject text length read_cab(&l,4); // unknown long read_cab(&w,2); // unknown word read_cab(&body,4); // body data pointer read_cab(&bodyLen,4); // body data length read_cab(&from,4); // from text pointer read_cab(&fromLen,4); // from text length read_cab(&date,4); // date (unix-style?) printf(" bodyLen) { printf("\nl is too big (%.8X > %.8X)!\n",l,bodyLen); return; } switch(w) { case 0x04: // Subject: printf("Subject: "); for (i=0; i126) c = '.'; putchar(c); } printf("'\n"); break; */ case 0x0A: if (to[0]) { printf("To: %s\n",to); to[0]=0; } if (cc[0]) { printf("CC: %s\n",cc); cc[0]=0; } q = p + l; while (p < q) { for (i=0; i<4; i++) t[i]=*p++; t[i] = 0; part = EvalHex(t); for (i=0; i<8; i++) t[i]=*p++; t[i]=0; n = EvalHex(t); for (i=0; i<8; i++) t[i]=*p++; t[i]=0; switch(part) { default: p=p+n; break; case 2: printf("\n"); while (n > 0 && *p++ != ',') n--; n--; if (n>1) fwrite(p,1,n-1,stdout); p=p+n; break; } } break; default: if (l) { printf("X-%.4X:",w); for (i=0; i16) printf("\n "); if ((i & 3) == 0) printf(" "); n = *p++; printf("%.2X",n); } printf("\n"); } break; } lastRec = w; } printf("\n"); } else { if (s) printf("Subject = '%s'\n",s); if (f) printf("From = '%s'\n",f); } free(s); free(b); free(f); printf("\n"); //printf("==--==--==--==--==--==--==--==--==\n"); } void dump_msg_index(int addr) { int i,n,id; short b4; //dump_block(addr,PAIR_LIST); fseek(cab, addr+6, SEEK_SET); read_cab(&b4,2); for (i=0; i> 12) { case 0: // indirect block case 4: // list of index lists //dump_block(addr,SIMPLE_LIST); fseek(cab, addr+6, SEEK_SET); read_cab(&b4,2); for(i=0; i0x7e) c='.'; return c; } // ===================================================================== void D_command(char *p) { GH_flag flag; UINT32 addr1,addr2; UINT32 i,j,n; char s[256]; // get (required) first address addr1 = GetHex(&p,&flag); // if no error, get optional second address switch(flag) { case GH_good: addr2 = GetHex(&p,&flag); break; case GH_EOL: flag = GH_bad; default: break; } switch(flag) { case GH_EOL: addr2 = addr1; case GH_good: //HexDump(addr1,addr2+1); addr1 = addr1 & ~3; addr2 = addr2 & ~3; s[0] = 0; for (i=addr1, j=0; i>24); s[j*4+1]=makeascii(n>>16); s[j*4+2]=makeascii(n>>8); s[j*4+3]=makeascii(n); s[j*4+4]=0; } printf(" %s\n",s); break; default: break; } if (flag==GH_bad) printf("Invalid hex value!\n"); } void E_command(char *p) { GH_flag flag; UINT32 addr; // get (required) first address addr = GetHex(&p,&flag); if (flag==GH_good) { dump_messages(addr); } if (flag==GH_bad) printf("Invalid hex value!\n"); } void I_command(char *p) { GH_flag flag; UINT32 addr; // get (required) first address addr = GetHex(&p,&flag); if (flag==GH_good) { dump_block(addr,INT_LIST); } if (flag==GH_bad) printf("Invalid hex value!\n"); } void M_command(char *p) { GH_flag flag; UINT32 addr; char c; c = toupper(*p); if (c == 'X') p++; // get (required) first address addr = GetHex(&p,&flag); if (flag==GH_good) { switch(c) { case 'X': dump_msg_index(addr); break; default: dump_msg_hdr(addr,0); break; } } if (flag==GH_bad) printf("Invalid hex value!\n"); } void P_command(char *p) { GH_flag flag; UINT32 addr; // get (required) first address addr = GetHex(&p,&flag); if (flag==GH_good) { dump_block(addr,PAIR_LIST); } if (flag==GH_bad) printf("Invalid hex value!\n"); } void S_command(char *p) { GH_flag flag; UINT32 addr; // get (required) first address addr = GetHex(&p,&flag); if (flag==GH_good) { dump_block(addr,SIMPLE_LIST); } if (flag==GH_bad) printf("Invalid hex value!\n"); } void U_command(char *p) { GH_flag flag; UINT32 addr; // get (required) first address addr = GetHex(&p,&flag); if (flag==GH_good) { dump_block(addr,UNKNOWN); } if (flag==GH_bad) printf("Invalid hex value!\n"); } void X_command(char *p) { GH_flag flag; UINT32 addr; // get (required) first address addr = GetHex(&p,&flag); if (flag==GH_good) { dump_block(addr,INDEX_LIST); } if (flag==GH_bad) printf("Invalid hex value!\n"); } void do_command(char *p) { if (*p) { switch(toupper(*p++)) { case '!': // ! = dump e-mail dump_email(); break; case 'D': // D = dump raw data D_command(p); break; case 'E': // E = dump e-mail E_command(p); break; case 'I': // I = dump int list record I_command(p); break; case 'M': // M = dump message header record M_command(p); break; case 'P': // X = dump pair pointer record P_command(p); break; case 'S': // S = dump simple pointer record S_command(p); break; case 'U': // U = dump simple pointer record U_command(p); break; case 'X': // X = dump index record X_command(p); break; default: printf("Unknown command!\n"); break; } } } void do_commands(void) { char s[STRLEN]; setvbuf(stdin, NULL, _IONBF, 0); setvbuf(stdout, NULL, _IONBF, 0); while (TRUE) { putchar('>'); ReadLine(s,STRLEN,TRUE); if (s[0] == 'Q') { // Q = quit printf("Exiting...\n"); exit(0); } else do_command(s); } } int main (int argc, char * const argv[]) { cab = fopen(cabName,"rb"); if (cab) { /* printf("AB703EC5 - 24FAD83F = %.8X\n",0xAB703EC5 - 0x24FAD83F); printf("AB71235E - 24FBD4E8 = %.8X\n",(0xAB71235E) - 0x24FBD4E8); printf("AF818782 - 335AA997 = %.8X\n",0xAF818782 - 0x335AA997); printf("AFFF1109 - 33D97237 = %.8X\n",0xAFFF1109 - 0x33D97237); printf("B3BFC2FA - 379A4AD0 = %.8X\n",0xB3BFC2FA - 0x379A4AD0); //printf(" - = %.8X\n",0x-0x); */ read_header(); // dump_h2(); // dump_h3(); dump_email(); // do_commands(); fclose(cab); } else printf("Unable to open %s\n",cabName); return 0; }