/[soft]/transfugdrake/trunk/transfug_oe.c
ViewVC logotype

Contents of /transfugdrake/trunk/transfug_oe.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 479 - (show annotations) (download)
Mon Feb 7 16:39:17 2011 UTC (13 years, 2 months ago) by ennael
File MIME type: text/plain
File size: 12097 byte(s)
import transfugdrake

1 /*
2 * transfugdrake
3 * (c) 2001 Yves Duret <yduret@mandrakesof.com>
4 * $Id: transfug_oe.c 225151 2006-12-09 03:13:01Z pablo $
5 */
6
7 /* This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 */
21
22 /* based on LIBOE 0.92 - STABLE
23 Copyright (C) 2000 Stephan B. NedregÄrd (stephan@micropop.com) */
24
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <string.h>
28 #include <sys/stat.h>
29
30 #define OE_CANNOTREAD 1
31 #define OE_NOTOEBOX 2
32 #define OE_POSITION 3
33 #define OE_NOBODY 4
34 #define OE_PANIC 5
35
36 #define SLASH '/'
37
38
39 /* #define DEBUG -- uncomment to get some DEBUG output to stdout */
40
41
42 /* TABLE STRUCTURES
43 -- tables store pointers to message headers and other tables also
44 containing pointers to message headers and other tables -- */
45
46 struct oe_table_header { /* At the beginning of each table */
47 int self, /* Pointer to self (filepos) */
48 unknown1, /* Unknown */
49 list, /* Pointer to list */
50 next, /* Pointer to next */
51 unknown3, /* Unknown */
52 unknown4; /* Unknown */
53 };
54 typedef struct oe_table_header oe_table_header;
55
56 struct oe_table_node { /* Actual table entries */
57 int message, /* Pointer to message | 0 */
58 list, /* Pointer to another table | 0 */
59 unknown; /* Unknown */
60 };
61 typedef struct oe_table_node oe_table_node;
62
63 struct oe_list { /* Internal use only */
64 long pos;
65 struct oe_list *next;
66 };
67 typedef struct oe_list oe_list;
68
69
70
71 /* MESSAGE STRUCTURES
72 -- OE uses 16-byte segment headers inside the actual messages. These
73 are meaningful, as described below, but were not very easy to hack
74 correctly -- note that a message may be composed of segments located
75 anywhere in the mailbox file, some times far from each other. */
76
77 struct oe_msg_segmentheader {
78 int self, /* Pointer to self (filepos) */
79 increase, /* Increase to next segment header (not in msg, in file!) */
80 include, /* Number of bytes to include from this segment */
81 next, /* Pointer to next message segment (in msg) (filepos) */
82 usenet; /* Only used with usenet posts */
83 };
84 typedef struct oe_msg_segmentheader oe_msg_segmentheader;
85
86
87
88
89 /* INTERAL STRUCTURES */
90 struct oe_internaldata{
91 void (*oput)(char*);
92 FILE *oe;
93 oe_list *used;
94 int success, justheaders, failure;
95 int errcode;
96 struct stat *stat;
97 };
98 typedef struct oe_internaldata oe_data;
99
100
101
102 /* LIST OF USED TABLES */
103
104 void oe_posused(oe_data *data, long pos) {
105 oe_list *n = malloc(sizeof(oe_list));
106 n->pos = pos;
107 n->next = data->used;
108 data->used = n;
109 }
110
111 int oe_isposused(oe_data *data, long pos) {
112 oe_list *n = data->used;
113 while (n!=NULL) {
114 if (pos==n->pos) return 1;
115 n = n->next;
116 }
117 return 0;
118 }
119
120 void oe_freeposused(oe_data *data) {
121 oe_list *n;
122 while (data->used!=NULL) {n=data->used->next; free(data->used); data->used=n;}
123 }
124
125
126 /* ACTUAL MESSAGE PARSER */
127
128 int oe_readmessage(oe_data *data,
129 long pos,
130 int newsarticle) {
131 int segheadsize = sizeof(oe_msg_segmentheader)-4; /*+(newsarticle<<2);*/
132 oe_msg_segmentheader *sgm = malloc(sizeof(oe_msg_segmentheader));
133 char buff[16], *ss = malloc(2048), *s = ss;
134 int nextsegment, endofsegment, i, headerwritten = 0;
135 fseek(data->oe,pos, SEEK_SET);
136 while (1) {
137 fread(sgm,segheadsize,1,data->oe);
138 if (pos!=sgm->self) { /* No body found*/
139 #ifdef DEBUG
140 printf("- Fail reported at %.8x (%.8x)\n",pos,sgm->self);
141 #endif
142 free(sgm);
143 free(ss);
144 data->failure++;
145 return OE_NOBODY;
146 }
147 pos+=segheadsize;
148 nextsegment = pos+sgm->increase;
149 endofsegment = pos+sgm->include;
150 if (!headerwritten) {
151 #ifdef DEBUG
152 printf("%.8x : \n",pos-segheadsize);
153 #endif
154 data->oput("From mandrake@MandrakeLinux Mon Jun 11 10:00:00 2001\n");
155 headerwritten = 1;
156 }
157 while (pos<endofsegment) {
158 fread(&buff,1,16,data->oe);
159 for (i=0;i<16;i++,pos++)
160 if ((pos<endofsegment) && (buff[i]!=0x0d)) { /* rm extra DOS newline */
161 *(s++)=buff[i];
162 if (buff[i]==0x0a) { *s='\0'; data->oput(ss); s=ss; }
163 }
164 }
165 fseek(data->oe,sgm->next, SEEK_SET);
166 pos = sgm->next;
167 if (pos==0) break;
168 }
169 if (s!=ss) {
170 strcpy(s,"\n");
171 data->oput(s);
172 }
173 data->oput("\n");
174
175 data->success++;
176 free(sgm);
177 free(ss);
178 return 0;
179 }
180
181
182 /* PARSES MESSAGE HEADERS */
183
184 int oe_readmessageheader(oe_data *data, long pos) {
185 int segheadsize = sizeof(oe_msg_segmentheader)-4;
186 oe_msg_segmentheader *sgm;
187 int self=1, msgpos = 0, newsarticle = 0;
188
189 if (oe_isposused(data,pos)) return 0; else oe_posused(data,pos);
190 fseek(data->oe,pos, SEEK_SET);
191 sgm = malloc(sizeof(oe_msg_segmentheader));
192 fread(sgm,segheadsize,1,data->oe);
193 if (pos!=sgm->self) { free(sgm); return OE_POSITION; /* ERROR */ }
194 free(sgm);
195
196 fread(&self,4,1,data->oe); self=1;
197 while ((self & 0x7F)>0) {
198 fread(&self,4,1,data->oe);
199 if ((self & 0xFF) == 0x84) /* 0x80 = Set, 04 = Index */
200 if (msgpos==0)
201 msgpos = self >> 8;
202 if ((self & 0xFF) == 0x83) /* 0x80 = Set, 03 = News */
203 newsarticle = 1;
204 }
205 if (msgpos) oe_readmessage(data,msgpos,newsarticle); else {
206 fread(&self,4,1,data->oe);
207 fread(&msgpos,4,1,data->oe);
208 if (oe_readmessage(data,msgpos,newsarticle)) {
209 if (newsarticle) {
210 data->justheaders++;
211 data->failure--;
212 }
213 }
214 }
215 return 0;
216 }
217
218
219 /* PARSES MAILBOX TABLES */
220
221 int oe_readtable(oe_data *data, long pos) {
222 oe_table_header thead;
223 oe_table_node tnode;
224 int quit = 0;
225
226 if (oe_isposused(data,pos)) return 0;
227
228 fseek(data->oe,pos, SEEK_SET);
229
230 fread(&thead,sizeof(oe_table_header),1,data->oe);
231 if (thead.self != pos) return OE_POSITION;
232 oe_posused(data,pos);
233 pos+=sizeof(oe_table_header);
234
235 oe_readtable(data,thead.next);
236 oe_readtable(data,thead.list);
237 fseek(data->oe,pos, SEEK_SET);
238
239 while (!quit) {
240 fread(&tnode,sizeof(oe_table_node),1,data->oe);
241 pos+=sizeof(oe_table_node);
242 if ( (tnode.message > data->stat->st_size) &&
243 (tnode.list > data->stat->st_size) )
244 return 0xF0; /* PANIC */
245 if ( (tnode.message == tnode.list) && /* Neither message nor list==quit */
246 (tnode.message == 0) ) quit = 1; else {
247 oe_readmessageheader(data,tnode.message);
248 oe_readtable(data,tnode.list);
249 }
250 fseek(data->oe,pos, SEEK_SET);
251 }
252
253 return 0;
254 }
255
256 void oe_readdamaged(oe_data *data) {
257 /* If nothing else works (needed this to get some mailboxes
258 that even OE couldn't read to work. Should generally not
259 be needed, but is nice to have in here */
260 long pos = 0x7C;
261 int i,check, lastID;
262 #ifdef DEBUG
263 printf(" Trying to construct internal mailbox structure\n");
264 #endif
265 fseek(data->oe,pos, SEEK_SET);
266 fread(&pos,sizeof(int),1,data->oe);
267 if (pos==0) return; /* No, sorry, didn't work */
268 fseek(data->oe,pos, SEEK_SET);
269 fread(&i,sizeof(int),1,data->oe);
270 if (i!=pos) return; /* Sorry */
271 fread(&pos,sizeof(int),1,data->oe);
272 i+=pos+8;
273 pos = i+4;
274 fseek(data->oe,pos, SEEK_SET);
275 #ifdef DEBUG
276 printf(" Searching for %.8x\n",i);
277 #endif
278 lastID=0;
279 while (pos<data->stat->st_size) {
280 /* Read through file, notice markers, look for message (gen. 2BD4)*/
281 fread(&check,sizeof(int),1,data->oe);
282 if (check==pos) lastID=pos;
283 pos+=4;
284 if ((check==i) && (lastID)) {
285 #ifdef DEBUG
286 printf("Trying possible table at %.8x\n",lastID);
287 #endif
288 oe_readtable(data,lastID);
289 fseek(data->oe,pos, SEEK_SET);
290 }
291 }
292 }
293
294 void oe_readbox_oe4(oe_data *data) {
295 long pos = 0x54, endpos=0, i;
296 oe_msg_segmentheader *header=malloc(sizeof(oe_msg_segmentheader));
297 char *cb = malloc(4), *sfull = malloc(65536), *s = sfull;
298 fseek(data->oe,pos, SEEK_SET);
299 while (pos<data->stat->st_size) {
300 fseek(data->oe,pos, SEEK_SET);
301 fread(header,16,1,data->oe);
302 data->oput("From mandrake@MandrakeLinux Mon Jun 11 10:00:00 2001\n");
303 endpos = pos + header->include;
304 if (endpos>data->stat->st_size) endpos=data->stat->st_size;
305 pos+=4;
306 while (pos<endpos) {
307 fread(cb,1,4,data->oe);
308 for (i=0;i<4;i++,pos++)
309 if (*(cb+i)!=0x0d) {
310 *s++ = *(cb+i);
311 if (*(cb+i) == 0x0a) {
312 *s = '\0';
313 data->oput(sfull);
314 s = sfull;
315 }
316 }
317 }
318 data->success++;
319 if (s!=sfull) { *s='\0'; data->oput(sfull); s=sfull; }
320 data->oput("\n");
321 pos=endpos;
322 }
323 free(header);
324 free(sfull);
325 free(cb);
326 }
327
328 /* CALL THIS ONE */
329
330 oe_data* oe_readbox(char* filename,void (*oput)(char*)) {
331 int signature[4], i;
332 oe_data *data = malloc(sizeof(oe_data));
333 data->success=data->failure=data->justheaders=data->errcode=0;
334 data->used = NULL;
335 data->oput = oput;
336 data->oe = fopen(filename,"rb");
337 if (data->oe==NULL) {
338 fclose(data->oe);
339 data->errcode = OE_CANNOTREAD;
340 return data;
341 }
342
343 /* SECURITY (Yes, we need this, just in case) */
344 data->stat = malloc(sizeof(struct stat));
345 stat(filename,data->stat);
346
347 /* SIGNATURE */
348 fread(&signature,16,1,data->oe);
349 if ((signature[0]!=0xFE12ADCF) || /* OE 5 & OE 5 BETA SIGNATURE */
350 (signature[1]!=0x6F74FDC5) ||
351 (signature[2]!=0x11D1E366) ||
352 (signature[3]!=0xC0004E9A)) {
353 if ((signature[0]==0x36464D4A) &&
354 (signature[1]==0x00010003)) /* OE4 SIGNATURE */ {
355 oe_readbox_oe4(data);
356 fclose(data->oe);
357 free(data->stat);
358 return data;
359 }
360 fclose(data->oe);
361 free(data->stat);
362 data->errcode = OE_NOTOEBOX;
363 return data;
364 }
365
366 /* ACTUAL WORK */
367 i = 0x30;
368 fseek(data->oe,i, SEEK_SET);
369 fread(&i,4,1,data->oe);
370 if (!i) i=0x1e254;
371 i = oe_readtable(data,i); /* Reads the box */
372 if (i & 0xF0) {
373 oe_readdamaged(data);
374 data->errcode=OE_PANIC;
375 }
376 oe_freeposused(data);
377
378 /* CLOSE DOWN */
379 fclose(data->oe);
380 free(data->stat);
381 return data;
382 }
383
384 #define buffsize 65536
385
386 /* Just a function to provide the same kind of stream
387 for ordinary mailboxes. */
388 oe_data* oe_readmbox(char* filename,void (*oput)(char*)) {
389 oe_data *data = malloc(sizeof(oe_data));
390 char *s = malloc(buffsize);
391 data->success=data->failure=data->justheaders=0;
392 data->used=NULL;
393 data->oe=fopen(filename,"rb");
394 for (;;) {
395 s=fgets(s,buffsize,data->oe);
396 if (s==NULL) break; else oput(s);
397 }
398 fclose(data->oe);
399 return data;
400 }
401
402 /****************************************/
403
404 FILE *mbox = NULL;
405 char *filename = NULL, *fn;
406
407 void msgandquit(int h) {
408 if (h==0)
409 printf("transfug_oe\nSyntax: transfug_oe [oe_mbox]*\n"
410 "based on OE2MBX 1.21 (c) 2000 Stephan B. Nedregaard - stephan@micropop.com\n");
411 else if (h==1)
412 printf("OE2MBX cannot run on this platform. Please consult the Web site at http://www.micropop.com/code/\n");
413 exit(h);
414 }
415
416 void fatal(char *s) {
417 printf("Fatal error: %s\n\n",s);
418 exit(1);
419 }
420
421 void writeit(char *s) {
422 if (mbox==NULL) {
423 mbox=fopen(fn,"w");
424 if(mbox==NULL) fatal("Cannot create output file");
425 }
426 fprintf(mbox,"%s",s);
427 }
428
429 int main(int argc, char*argv[]) {
430 int i;
431 oe_data *j;
432
433 /* Handle errors, help and syntax */
434 if (argc<3) msgandquit(0);
435
436 /* Process mailboxes */
437 printf("Converting %s...\n",argv[1]);
438 fn = argv[2];
439 if (*fn==SLASH) fn++;
440 printf(" => %s\n",fn);
441 j = (oe_data*) oe_readbox(argv[1],writeit);
442 if (j!=NULL) {
443 if (!j->success) printf(" No messages converted"); else
444 printf(" %d messages converted",j->success);
445 if (j->justheaders) printf(" (%d headers w/o bodies)",j->justheaders);
446 if (j->failure) printf(" (%d messages failed)",j->failure);
447 printf("\n");
448 } else printf(" Empty mailbox\n");
449 if (mbox!=NULL) fclose(mbox);
450 mbox=NULL;
451 return 0;
452 }

Properties

Name Value
svn:eol-style native

  ViewVC Help
Powered by ViewVC 1.1.30