diff options
Diffstat (limited to 'transfug_oe.c')
-rw-r--r-- | transfug_oe.c | 484 |
1 files changed, 484 insertions, 0 deletions
diff --git a/transfug_oe.c b/transfug_oe.c new file mode 100644 index 0000000..ee2eaaf --- /dev/null +++ b/transfug_oe.c @@ -0,0 +1,484 @@ +/* transfugdrake + * (c) 2001 Yves DUret <yduret@mandrakesof.com> + */ + +/* based on LIBOE 0.92 - STABLE + Copyright (C) 2000 Stephan B. Nedregård (stephan@micropop.com) */ + +/* 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. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#ifndef WINDOWS +#include <unistd.h> +#endif +#include <sys/stat.h> + +#define OE_CANNOTREAD 1 +#define OE_NOTOEBOX 2 +#define OE_POSITION 3 +#define OE_NOBODY 4 +#define OE_PANIC 5 + +/* #define DEBUG -- uncomment to get some DEBUG output to stdout */ + + +/* TABLE STRUCTURES + -- tables store pointers to message headers and other tables also + containing pointers to message headers and other tables -- */ + +struct oe_table_header { /* At the beginning of each table */ + int self, /* Pointer to self (filepos) */ + unknown1, /* Unknown */ + list, /* Pointer to list */ + next, /* Pointer to next */ + unknown3, /* Unknown */ + unknown4; /* Unknown */ +}; +typedef struct oe_table_header oe_table_header; + +struct oe_table_node { /* Actual table entries */ + int message, /* Pointer to message | 0 */ + list, /* Pointer to another table | 0 */ + unknown; /* Unknown */ +}; +typedef struct oe_table_node oe_table_node; + +struct oe_list { /* Internal use only */ + long pos; + struct oe_list *next; +}; +typedef struct oe_list oe_list; + + + +/* MESSAGE STRUCTURES + -- OE uses 16-byte segment headers inside the actual messages. These + are meaningful, as described below, but were not very easy to hack + correctly -- note that a message may be composed of segments located + anywhere in the mailbox file, some times far from each other. */ + +struct oe_msg_segmentheader { + int self, /* Pointer to self (filepos) */ + increase, /* Increase to next segment header (not in msg, in file!) */ + include, /* Number of bytes to include from this segment */ + next, /* Pointer to next message segment (in msg) (filepos) */ + usenet; /* Only used with usenet posts */ +}; +typedef struct oe_msg_segmentheader oe_msg_segmentheader; + + + + +/* INTERAL STRUCTURES */ +struct oe_internaldata{ + void (*oput)(char*); + FILE *oe; + oe_list *used; + int success, justheaders, failure; + int errcode; + struct stat *stat; +}; +typedef struct oe_internaldata oe_data; + + + +/* LIST OF USED TABLES */ + +void oe_posused(oe_data *data, long pos) { + oe_list *n = malloc(sizeof(oe_list)); + n->pos = pos; + n->next = data->used; + data->used = n; +} + +int oe_isposused(oe_data *data, long pos) { + oe_list *n = data->used; + while (n!=NULL) { + if (pos==n->pos) return 1; + n = n->next; + } + return 0; +} + +void oe_freeposused(oe_data *data) { + oe_list *n; + while (data->used!=NULL) {n=data->used->next; free(data->used); data->used=n;} +} + + +/* ACTUAL MESSAGE PARSER */ + +int oe_readmessage(oe_data *data, + long pos, + int newsarticle) { + int segheadsize = sizeof(oe_msg_segmentheader)-4; /*+(newsarticle<<2);*/ + oe_msg_segmentheader *sgm = malloc(sizeof(oe_msg_segmentheader)); + char buff[16], *ss = malloc(2048), *s = ss; + int nextsegment, endofsegment, i, headerwritten = 0; + fseek(data->oe,pos, SEEK_SET); + while (1) { + fread(sgm,segheadsize,1,data->oe); + if (pos!=sgm->self) { /* No body found*/ +#ifdef DEBUG + printf("- Fail reported at %.8x (%.8x)\n",pos,sgm->self); +#endif + free(sgm); + free(ss); + data->failure++; + return OE_NOBODY; + } + pos+=segheadsize; + nextsegment = pos+sgm->increase; + endofsegment = pos+sgm->include; + if (!headerwritten) { +#ifdef DEBUG + printf("%.8x : \n",pos-segheadsize); +#endif + data->oput("From liboe@linux Sun Jun 11 19:48:24 2000\n"); + headerwritten = 1; + } + while (pos<endofsegment) { + fread(&buff,1,16,data->oe); + for (i=0;i<16;i++,pos++) + if ((pos<endofsegment) && (buff[i]!=0x0d)) { /* rm extra DOS newline */ + *(s++)=buff[i]; + if (buff[i]==0x0a) { *s='\0'; data->oput(ss); s=ss; } + } + } + fseek(data->oe,sgm->next, SEEK_SET); + pos = sgm->next; + if (pos==0) break; + } + if (s!=ss) { + strcpy(s,"\n"); + data->oput(s); + } + data->oput("\n"); + + data->success++; + free(sgm); + free(ss); + return 0; +} + + +/* PARSES MESSAGE HEADERS */ + +int oe_readmessageheader(oe_data *data, long pos) { + int segheadsize = sizeof(oe_msg_segmentheader)-4; + oe_msg_segmentheader *sgm; + int self=1, msgpos = 0, newsarticle = 0; + + if (oe_isposused(data,pos)) return 0; else oe_posused(data,pos); + fseek(data->oe,pos, SEEK_SET); + sgm = malloc(sizeof(oe_msg_segmentheader)); + fread(sgm,segheadsize,1,data->oe); + if (pos!=sgm->self) { free(sgm); return OE_POSITION; /* ERROR */ } + free(sgm); + + fread(&self,4,1,data->oe); self=1; + while ((self & 0x7F)>0) { + fread(&self,4,1,data->oe); + if ((self & 0xFF) == 0x84) /* 0x80 = Set, 04 = Index */ + if (msgpos==0) + msgpos = self >> 8; + if ((self & 0xFF) == 0x83) /* 0x80 = Set, 03 = News */ + newsarticle = 1; + } + if (msgpos) oe_readmessage(data,msgpos,newsarticle); else { + fread(&self,4,1,data->oe); + fread(&msgpos,4,1,data->oe); + if (oe_readmessage(data,msgpos,newsarticle)) { + if (newsarticle) { + data->justheaders++; + data->failure--; + } + } + } + return 0; +} + + +/* PARSES MAILBOX TABLES */ + +int oe_readtable(oe_data *data, long pos) { + oe_table_header thead; + oe_table_node tnode; + int quit = 0; + + if (oe_isposused(data,pos)) return 0; + + fseek(data->oe,pos, SEEK_SET); + + fread(&thead,sizeof(oe_table_header),1,data->oe); + if (thead.self != pos) return OE_POSITION; + oe_posused(data,pos); + pos+=sizeof(oe_table_header); + + oe_readtable(data,thead.next); + oe_readtable(data,thead.list); + fseek(data->oe,pos, SEEK_SET); + + while (!quit) { + fread(&tnode,sizeof(oe_table_node),1,data->oe); + pos+=sizeof(oe_table_node); + if ( (tnode.message > data->stat->st_size) && + (tnode.list > data->stat->st_size) ) + return 0xF0; /* PANIC */ + if ( (tnode.message == tnode.list) && /* Neither message nor list==quit */ + (tnode.message == 0) ) quit = 1; else { + oe_readmessageheader(data,tnode.message); + oe_readtable(data,tnode.list); + } + fseek(data->oe,pos, SEEK_SET); + } + + return 0; +} + +void oe_readdamaged(oe_data *data) { + /* If nothing else works (needed this to get some mailboxes + that even OE couldn't read to work. Should generally not + be needed, but is nice to have in here */ + long pos = 0x7C; + int i,check, lastID; +#ifdef DEBUG + printf(" Trying to construct internal mailbox structure\n"); +#endif + fseek(data->oe,pos, SEEK_SET); + fread(&pos,sizeof(int),1,data->oe); + if (pos==0) return; /* No, sorry, didn't work */ + fseek(data->oe,pos, SEEK_SET); + fread(&i,sizeof(int),1,data->oe); + if (i!=pos) return; /* Sorry */ + fread(&pos,sizeof(int),1,data->oe); + i+=pos+8; + pos = i+4; + fseek(data->oe,pos, SEEK_SET); +#ifdef DEBUG + printf(" Searching for %.8x\n",i); +#endif + lastID=0; + while (pos<data->stat->st_size) { + /* Read through file, notice markers, look for message (gen. 2BD4)*/ + fread(&check,sizeof(int),1,data->oe); + if (check==pos) lastID=pos; + pos+=4; + if ((check==i) && (lastID)) { +#ifdef DEBUG + printf("Trying possible table at %.8x\n",lastID); +#endif + oe_readtable(data,lastID); + fseek(data->oe,pos, SEEK_SET); + } + } +} + +void oe_readbox_oe4(oe_data *data) { + long pos = 0x54, endpos=0, i; + oe_msg_segmentheader *header=malloc(sizeof(oe_msg_segmentheader)); + char *cb = malloc(4), *sfull = malloc(65536), *s = sfull; + fseek(data->oe,pos, SEEK_SET); + while (pos<data->stat->st_size) { + fseek(data->oe,pos, SEEK_SET); + fread(header,16,1,data->oe); + data->oput("From liboe@linux Sat Jun 17 01:08:25 2000\n"); + endpos = pos + header->include; + if (endpos>data->stat->st_size) endpos=data->stat->st_size; + pos+=4; + while (pos<endpos) { + fread(cb,1,4,data->oe); + for (i=0;i<4;i++,pos++) + if (*(cb+i)!=0x0d) { + *s++ = *(cb+i); + if (*(cb+i) == 0x0a) { + *s = '\0'; + data->oput(sfull); + s = sfull; + } + } + } + data->success++; + if (s!=sfull) { *s='\0'; data->oput(sfull); s=sfull; } + data->oput("\n"); + pos=endpos; + } + free(header); + free(sfull); + free(cb); +} + +/* CALL THIS ONE */ + +oe_data* oe_readbox(char* filename,void (*oput)(char*)) { + int signature[4], i; + oe_data *data = malloc(sizeof(oe_data)); + data->success=data->failure=data->justheaders=data->errcode=0; + data->used = NULL; + data->oput = oput; + data->oe = fopen(filename,"rb"); + if (data->oe==NULL) { + fclose(data->oe); + data->errcode = OE_CANNOTREAD; + return data; + } + + /* SECURITY (Yes, we need this, just in case) */ + data->stat = malloc(sizeof(struct stat)); + stat(filename,data->stat); + + /* SIGNATURE */ + fread(&signature,16,1,data->oe); + if ((signature[0]!=0xFE12ADCF) || /* OE 5 & OE 5 BETA SIGNATURE */ + (signature[1]!=0x6F74FDC5) || + (signature[2]!=0x11D1E366) || + (signature[3]!=0xC0004E9A)) { + if ((signature[0]==0x36464D4A) && + (signature[1]==0x00010003)) /* OE4 SIGNATURE */ { + oe_readbox_oe4(data); + fclose(data->oe); + free(data->stat); + return data; + } + fclose(data->oe); + free(data->stat); + data->errcode = OE_NOTOEBOX; + return data; + } + + /* ACTUAL WORK */ + i = 0x30; + fseek(data->oe,i, SEEK_SET); + fread(&i,4,1,data->oe); + if (!i) i=0x1e254; + i = oe_readtable(data,i); /* Reads the box */ + if (i & 0xF0) { + oe_readdamaged(data); + data->errcode=OE_PANIC; + } + oe_freeposused(data); + + /* CLOSE DOWN */ + fclose(data->oe); + free(data->stat); + return data; +} + +#define buffsize 65536 + +/* Just a function to provide the same kind of stream + for ordinary mailboxes. */ +oe_data* oe_readmbox(char* filename,void (*oput)(char*)) { + oe_data *data = malloc(sizeof(oe_data)); + char *s = malloc(buffsize); + data->success=data->failure=data->justheaders=0; + data->used=NULL; + data->oe=fopen(filename,"rb"); + for (;;) { + s=fgets(s,buffsize,data->oe); + if (s==NULL) break; else oput(s); + } + fclose(data->oe); + return data; +} +/* OE2MBX 1.21 + Copyright (C) 2000 Stephan B. Nedregaard (stephan@micropop.com) */ + +/* 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. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#ifdef WINDOWS +#define SLASH '\\' +#else +#define SLASH '/' +#endif + +FILE *mbox = NULL; +char *filename = NULL, *fn; + +void msgandquit(int h) { + if (h==0) + printf("transfug_oe\nSyntax: transfug_oe [oe_mbox] based on OE2MBX 1.21 (c) 2000 Stephan B. Nedregaard - stephan@micropop.com"); + else if (h==1) + printf("OE2MBX cannot run on this platform. Please consult the Web site at http://www.micropop.com/code/"); + exit(h); +} + +void fatal(char *s) { + printf("Fatal error: %s\n\n",s); + exit(1); +} + +void writeit(char *s) { + if (mbox==NULL) { + mbox=fopen(fn,"w"); + if(mbox==NULL) fatal("Cannot create output file"); + } + fprintf(mbox,"%s",s); +} + +int main(int argc, char*argv[]) { + int i; + + /* Handle errors, help and syntax */ + if (argc<2) msgandquit(0); + for (i=1;i<argc;i++) + if ( !strcmp(argv[i],"-h") || !strcmp(argv[i],"--help") ) + msgandquit(0); + + /* Process mailboxes */ + for (i=1;i<argc;i++) { + oe_data *j; + printf("Converting %s...\n",argv[i]); + filename = malloc(strlen(argv[i])+5); + strcpy(filename,argv[i]); + strcpy(filename+strlen(filename),".mbx"); + fn = filename+strlen(filename); + while ((*fn!=SLASH) && (fn!=filename)) fn--; + if (*fn==SLASH) fn++; + printf(" => %s\n",fn); + j = (oe_data*) oe_readbox(argv[i],writeit); + if (j!=NULL) { + if (!j->success) printf(" No messages converted"); else + printf(" %d messages converted",j->success); + if (j->justheaders) printf(" (%d headers w/o bodies)",j->justheaders); + if (j->failure) printf(" (%d messages failed)",j->failure); + printf("\n"); + } else printf(" Empty mailbox\n"); + if (mbox!=NULL) fclose(mbox); + mbox=NULL; + free(filename); + } + return 0; +} |