ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/Convert-UUlib/uulib/uuscan.c
Revision: 1.31
Committed: Sat Sep 24 10:55:43 2022 UTC (20 months, 1 week ago) by root
Content type: text/plain
Branch: MAIN
CVS Tags: HEAD
Changes since 1.30: +1 -1 lines
Log Message:
*** empty log message ***

File Contents

# User Rev Content
1 root 1.1 /*
2     * This file is part of uudeview, the simple and friendly multi-part multi-
3 root 1.2 * file uudecoder program (c) 1994-2001 by Frank Pilhofer. The author may
4     * be contacted at fp@fpx.de
5 root 1.1 *
6     * This program is free software; you can redistribute it and/or modify
7     * it under the terms of the GNU General Public License as published by
8     * the Free Software Foundation; either version 2 of the License, or
9     * (at your option) any later version.
10     *
11     * This program is distributed in the hope that it will be useful,
12     * but WITHOUT ANY WARRANTY; without even the implied warranty of
13     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14     * GNU General Public License for more details.
15     */
16    
17     /*
18     * These are very central functions of UUDeview. Here, we scan a file
19     * and decide whether it contains encoded data or not. ScanPart() must
20 root 1.23 * be called repeatedly on the same file until FP_feof(file). Each time,
21 root 1.1 * it returns information about the next part found within.
22     */
23    
24     #ifdef HAVE_CONFIG_H
25     #include "config.h"
26     #endif
27    
28     #ifdef SYSTEM_WINDLL
29     #include <windows.h>
30     #endif
31     #ifdef SYSTEM_OS2
32     #include <os2.h>
33     #endif
34    
35     #include <stdio.h>
36     #include <ctype.h>
37     #include <stdlib.h>
38     #include <string.h>
39 root 1.29 #include <errno.h>
40 root 1.28
41 root 1.1 #ifdef HAVE_UNISTD_H
42     #include <unistd.h>
43     #endif
44    
45 root 1.2 #include <uudeview.h>
46 root 1.1 #include <uuint.h>
47     #include <fptools.h>
48     #include <uustring.h>
49    
50     /*
51     * Header fields we recognize as such. See RFC822. We add "From ",
52     * the usual marker for a beginning of a new message, and a couple
53     * of usual MDA, News and MIME headers.
54     * We make a distinction of MIME headers as we need the difference
55     * to scan the bodies from partial multipart messages.
56     */
57    
58 root 1.25 #define LSTR(s) { (s), sizeof (s) - 1 }
59 root 1.17
60     struct lstr {
61 root 1.25 const char *str;
62 root 1.17 int len;
63     };
64    
65     #define MAX_KNOWNHEADERLEN 28 /* max. length of a known header */
66    
67 root 1.25 static const struct lstr knownheaders[] = {
68 root 1.17 /* "From " handled in IsKnownHeader */
69    
70     /* knownmsgheaders */
71     LSTR ("Return-Path"), LSTR ("Received"), LSTR ("Reply-To"),
72     LSTR ("From"), LSTR ("Sender"), LSTR ("Resent-Reply-To"), LSTR ("Resent-From"),
73     LSTR ("Resent-Sender"), LSTR ("Date"), LSTR ("Resent-Date"), LSTR ("To"),
74     LSTR ("Resent-To"), LSTR ("Cc"), LSTR ("Bcc"), LSTR ("Resent-bcc"),
75     LSTR ("Message-ID"), LSTR ("Resent-Message-Id"), LSTR ("In-Reply-To"),
76     LSTR ("References"), LSTR ("Keywords"), LSTR ("Subject"), LSTR ("Comments"),
77 root 1.22
78 root 1.17 LSTR ("Delivery-Date"), LSTR ("Posted-Date"), LSTR ("Received-Date"),
79 root 1.22 LSTR ("Precedence"),
80 root 1.1
81 root 1.17 LSTR ("Path"), LSTR ("Newsgroups"), LSTR ("Organization"), LSTR ("Lines"),
82     LSTR ("NNTP-Posting-Host"),
83 root 1.1
84 root 1.17 /* knownminehaders */
85     LSTR ("Mime-Version"), LSTR ("Content-Transfer-Encoding"),
86 root 1.22 LSTR ("Content-Type"), LSTR ("Content-Disposition"),
87 root 1.17 LSTR ("Content-Description"), LSTR ("Content-Length")
88 root 1.1 };
89    
90     /*
91     * for MIME (plaintext) parts without filename
92     */
93     int mimseqno;
94    
95     /*
96     * how many lines do we read when checking for headers
97     */
98     #define WAITHEADER 10
99    
100     /*
101     * The stack for encapsulated Multipart messages
102     */
103     #define MSMAXDEPTH 3
104    
105     int mssdepth = 0;
106     scanstate multistack[MSMAXDEPTH+1];
107    
108     /*
109     * The state and the local envelope
110     */
111     headers localenv;
112     scanstate sstate;
113    
114     /*
115     * mallocable areas
116     */
117    
118     char *uuscan_shlline;
119 root 1.7 char *uuscan_shlline2;
120 root 1.1 char *uuscan_pvvalue;
121     char *uuscan_phtext;
122     char *uuscan_sdline;
123     char *uuscan_sdbhds1;
124     char *uuscan_sdbhds2;
125     char *uuscan_spline;
126    
127     /*
128     * Macro: print cancellation message in UUScanPart
129     */
130    
131 root 1.29 #define SPCANCEL() { UUMessage (UUMSG_NOTE, uustring(S_SCAN_CANCEL)); *errcode = UURET_CANCEL; goto ScanPartEmergency; }
132 root 1.1
133     /*
134     * Is line empty? A line is empty if it is composed of whitespace.
135     */
136    
137     static int
138     IsLineEmpty (char *data)
139     {
140     if (data == NULL) return 0;
141     while (*data && isspace (*data)) data++;
142     return ((*data)?0:1);
143     }
144    
145     /*
146 root 1.7 * Is this a header line? A header line has alphanumeric characters
147     * followed by a colon.
148     */
149    
150     static int
151     IsHeaderLine (char *data)
152     {
153     if (data == NULL) return 0;
154     if (*data == ':') return 0;
155 root 1.9 while (*data && (isalnum (*data) || *data=='-')) data++;
156 root 1.7 return (*data == ':') ? 1 : 0;
157     }
158    
159     /*
160 root 1.1 * Scans a potentially folded header line from the input file. If
161     * initial is non-NULL, it is the first line of the header, useful
162     * if the calling function just coincidentally noticed that this is
163     * a header.
164     * RFC0822 does not specify a maximum length for headers, but we
165     * truncate everything beyond an insane value of 1024 characters.
166     */
167 root 1.16 /* (schmorp)every later rfc says 998 octets max */
168 root 1.1
169     static char *
170     ScanHeaderLine (FILE *datei, char *initial)
171     {
172     char *ptr=uuscan_shlline;
173 root 1.21 char *ptr2, *p2, *p3;
174 root 1.1 int llength, c;
175     long curpos;
176    
177     if (initial) {
178 root 1.23 FP_strncpy (uuscan_shlline, initial, 1024);
179 root 1.15 } else {
180 root 1.1 /* read first line */
181 root 1.23 if (FP_feof (datei) || ferror (datei))
182 root 1.1 return NULL;
183 root 1.23 if (FP_fgets (uuscan_shlline, 1024, datei) == NULL)
184 root 1.1 return NULL;
185     }
186    
187     llength = strlen (uuscan_shlline);
188    
189     /* strip whitespace at end */
190     ptr = uuscan_shlline + llength;
191     while (llength && isspace(*(ptr-1))) {
192     ptr--; llength--;
193     }
194 root 1.16 if (llength == 0)
195 root 1.1 return uuscan_shlline;
196    
197 root 1.23 while (!FP_feof (datei)) {
198     c = FP_getc (datei);
199 root 1.16 if (c == EOF)
200 root 1.1 break;
201    
202 root 1.16 if (c != ' ' && c != '\t')
203     {
204     ungetc (c, datei);
205     break;
206     }
207 root 1.1
208 root 1.23 while (!FP_feof (datei) && (c == ' ' || c == '\t'))
209     c = FP_getc (datei);
210 root 1.1
211 root 1.23 if (!FP_feof (datei))
212 root 1.1 ungetc (c, datei); /* push back for fgets() */
213 root 1.16 else
214 root 1.1 break;
215    
216     /* read next line */
217     curpos = ftell (datei);
218 root 1.23 if (FP_fgets (uugen_inbuffer, 1024, datei) == NULL)
219 root 1.1 break;
220    
221     if (IsLineEmpty (uugen_inbuffer)) { /* oops */
222     fseek (datei, curpos, SEEK_SET);
223     break;
224     }
225    
226 root 1.23 FP_strncpy (ptr, uugen_inbuffer, 1024-llength);
227 root 1.1
228     c = strlen (ptr);
229    
230     /*
231     * strip whitespace
232     */
233    
234     ptr += c;
235     llength += c;
236     while (llength && isspace(*(ptr-1))) {
237     ptr--; llength--;
238     }
239     }
240 root 1.7
241 root 1.1 *ptr = '\0';
242    
243     if (llength == 0)
244     return NULL;
245    
246 root 1.7 /*
247     * Now that we've read the header line, we can RFC 1522-decode it
248     */
249    
250     ptr = uuscan_shlline;
251     ptr2 = uuscan_shlline2;
252    
253     while (*ptr) {
254     /*
255     * Look for =? magic
256     */
257    
258     if (*ptr == '=' && *(ptr+1) == '?') {
259     /*
260 root 1.21 * Let p2 point to the charset, look for next question mark
261 root 1.7 */
262    
263 root 1.21 p2 = ptr+2;
264 root 1.7
265     while (*p2 && *p2 != '?') {
266     p2++;
267     }
268    
269     if (*p2 == '?' &&
270     (*(p2+1) == 'q' || *(p2+1) == 'Q' ||
271     *(p2+1) == 'b' || *(p2+1) == 'B') &&
272     *(p2+2) == '?') {
273     /*
274     * Let p2 point to the encoding, look for ?= magic
275     */
276    
277     p2++;
278     p3=p2+2;
279    
280     while (*p3 && (*p3 != '?' || *(p3+1) != '=')) {
281     p3++;
282     }
283    
284     if (*p3 == '?' && *(p3+1) == '=') {
285     /*
286     * Alright, we've found an RFC 1522 header field
287     */
288     if (*p2 == 'q' || *p2 == 'Q') {
289     c = UUDecodeField (p2+2, ptr2, QP_ENCODED);
290     }
291     else if (*p2 == 'b' || *p2 == 'B') {
292     c = UUDecodeField (p2+2, ptr2, B64ENCODED);
293     }
294     if (c >= 0) {
295     ptr2 += c;
296     ptr = p3+2;
297     continue;
298     }
299     }
300     }
301     }
302    
303     *ptr2++ = *ptr++;
304     }
305    
306     *ptr2 = 0;
307    
308     return uuscan_shlline2;
309 root 1.1 }
310    
311     /*
312     * Extract the value from a MIME attribute=value pair. This function
313     * receives a pointer to the attribute.
314     */
315     static char *
316     ParseValue (char *attribute)
317     {
318     char *ptr=uuscan_pvvalue;
319     int length=0;
320    
321     if (attribute == NULL)
322     return NULL;
323    
324     while ((isalnum(*attribute) || *attribute=='_') && *attribute != '=')
325     attribute++;
326    
327     while (isspace(*attribute))
328     attribute++;
329    
330     if (*attribute == '=') {
331     attribute++;
332     while (isspace (*attribute))
333     attribute++;
334     }
335     else
336     return NULL;
337    
338     if (*attribute == '"') {
339     /* quoted-string */
340     attribute++;
341     while (*attribute && *attribute != '"' && length < 255) {
342     if (*attribute == '\\'
343     && (attribute[1] == '"'
344     || attribute[1] == '\015'
345     || attribute[1] == '\\'))
346     /* we dequote only the three characters that MUST be quoted, since
347     * microsoft is obviously unable to correctly implement even mime headers:
348     * filename="c:\xxx". *sigh*
349     */
350     *ptr++ = *++attribute;
351     else
352     *ptr++ = *attribute;
353     attribute++;
354     length++;
355     }
356     *ptr = '\0';
357     }
358     else {
359     /* tspecials from RFC1521 */
360 root 1.7 /*
361     * Note - exclude '[', ']' and ';' on popular request; these are
362     * used in some Content-Type fields by the Klez virus, and people
363     * who feed their virus scanners with the output of UUDeview would
364     * like to catch it!
365     */
366 root 1.1
367     while (*attribute && !isspace (*attribute) &&
368     *attribute != '(' && *attribute != ')' &&
369     *attribute != '<' && *attribute != '>' &&
370     *attribute != '@' && *attribute != ',' &&
371 root 1.7 /* *attribute != ';' && */ *attribute != ':' &&
372 root 1.1 *attribute != '\\' &&*attribute != '"' &&
373 root 1.7 *attribute != '/' && /* *attribute != '[' &&
374     *attribute != ']' && */ *attribute != '?' &&
375 root 1.9 *attribute != '=' && length < 255) {
376 root 1.1 *ptr++ = *attribute++;
377 root 1.9 length++;
378     }
379 root 1.1
380     *ptr = '\0';
381     }
382     return uuscan_pvvalue;
383     }
384    
385     /*
386     * Extract the information we need from header fields
387     */
388    
389     static headers *
390     ParseHeader (headers *theheaders, char *line)
391     {
392     char **variable=NULL;
393     char *value, *ptr, *thenew;
394     int delimit, length;
395    
396 root 1.2 value = 0; delimit = 0; /* calm down gcc */
397 root 1.1
398     if (line == NULL)
399     return theheaders;
400    
401 root 1.24 if (FP_strnicmp_fast (line, "From:", 5) == 0) {
402 root 1.1 if (theheaders->from) return theheaders;
403     variable = &theheaders->from;
404     value = line+5;
405     delimit = 0;
406     }
407 root 1.24 else if (FP_strnicmp_fast (line, "Subject:", 8) == 0) {
408 root 1.1 if (theheaders->subject) return theheaders;
409     variable = &theheaders->subject;
410     value = line+8;
411     delimit = 0;
412     }
413 root 1.24 else if (FP_strnicmp_fast (line, "To:", 3) == 0) {
414 root 1.1 if (theheaders->rcpt) return theheaders;
415     variable = &theheaders->rcpt;
416     value = line+3;
417     delimit = 0;
418     }
419 root 1.24 else if (FP_strnicmp_fast (line, "Date:", 5) == 0) {
420 root 1.1 if (theheaders->date) return theheaders;
421     variable = &theheaders->date;
422     value = line+5;
423     delimit = 0;
424     }
425 root 1.24 else if (FP_strnicmp_fast (line, "Mime-Version:", 13) == 0) {
426 root 1.1 if (theheaders->mimevers) return theheaders;
427     variable = &theheaders->mimevers;
428     value = line+13;
429     delimit = 0;
430     }
431 root 1.24 else if (FP_strnicmp_fast (line, "Content-Type:", 13) == 0) {
432 root 1.1 if (theheaders->ctype) return theheaders;
433     variable = &theheaders->ctype;
434     value = line+13;
435     delimit = ';';
436    
437     /* we can probably extract more information */
438 root 1.23 if ((ptr = FP_stristr (line, "boundary")) != NULL) {
439 root 1.1 if ((thenew = ParseValue (ptr))) {
440     if (theheaders->boundary) free (theheaders->boundary);
441 root 1.23 theheaders->boundary = FP_strdup (thenew);
442 root 1.1 }
443     }
444 root 1.23 if ((ptr = FP_stristr (line, "name")) != NULL) {
445 root 1.1 if ((thenew = ParseValue (ptr))) {
446     if (theheaders->fname) free (theheaders->fname);
447 root 1.23 theheaders->fname = FP_strdup (thenew);
448 root 1.1 }
449     }
450 root 1.23 if ((ptr = FP_stristr (line, "id")) != NULL) {
451 root 1.1 if ((thenew = ParseValue (ptr))) {
452     if (theheaders->mimeid) free (theheaders->mimeid);
453 root 1.23 theheaders->mimeid = FP_strdup (thenew);
454 root 1.1 }
455     }
456 root 1.23 if ((ptr = FP_stristr (line, "number")) != NULL) {
457 root 1.1 if ((thenew = ParseValue (ptr))) {
458     theheaders->partno = atoi (thenew);
459     }
460     }
461 root 1.23 if ((ptr = FP_stristr (line, "total")) != NULL) {
462 root 1.1 if ((thenew = ParseValue (ptr))) {
463     theheaders->numparts = atoi (thenew);
464     }
465     }
466     }
467 root 1.24 else if (FP_strnicmp_fast (line, "Content-Transfer-Encoding:", 26) == 0) {
468 root 1.1 if (theheaders->ctenc) return theheaders;
469     variable = &theheaders->ctenc;
470     value = line+26;
471     delimit = ';';
472     }
473 root 1.24 else if (FP_strnicmp_fast (line, "Content-Disposition:", 20) == 0) {
474 root 1.1 /*
475     * Some encoders mention the original filename as parameter to
476     * Content-Type, others as parameter to Content-Disposition. We
477     * do prefer the first solution, but accept this situation, too.
478     * TODO: Read RFC1806
479     */
480 root 1.23 if ((ptr = FP_stristr (line, "name")) != NULL) {
481 root 1.1 if (theheaders->fname == NULL && (thenew=ParseValue(ptr)) != NULL) {
482 root 1.23 theheaders->fname = FP_strdup (thenew);
483 root 1.1 }
484     }
485     variable = NULL;
486     }
487     else {
488     /*
489     * nothing interesting
490     */
491 root 1.4 return theheaders;
492 root 1.1 }
493    
494     /*
495     * okay, so extract the actual data
496     */
497     if (variable) {
498     length = 0;
499     ptr = uuscan_phtext;
500    
501     while (isspace (*value))
502     value++;
503     while (*value && (delimit==0 || *value!=delimit) &&
504 root 1.16 *value && length < 255) {
505 root 1.1 *ptr++ = *value++;
506     length++;
507     }
508     while (length && isspace(*(ptr-1))) {
509     ptr--; length--;
510     }
511     *ptr = '\0';
512    
513 root 1.23 if ((*variable = FP_strdup (uuscan_phtext)) == NULL)
514 root 1.1 return NULL;
515     }
516    
517     return theheaders;
518     }
519    
520     /*
521     * is this a header line we know about?
522     */
523    
524     static int
525     IsKnownHeader (char *line)
526     {
527 root 1.17 const char *sep;
528     int len, i;
529    
530     /* "From " handled specially */
531     /* we assume the buffer is at least 5 bytes long */
532     if (line [4] == ' ' && line [1] == 'r' && line [2] == 'o' && line [3] == 'm'
533     && (line [0] == 'f' || line [0] == 'F'))
534     return 1;
535    
536     sep = memchr (line, ':', MAX_KNOWNHEADERLEN);
537 root 1.1
538 root 1.15 /* fast reject, the majority of calls are simple rejects */
539 root 1.17 if (!sep)
540 root 1.15 return 0;
541    
542 root 1.17 len = sep - line; /* length of part before ':' */
543    
544     for (i = 0; i < sizeof (knownheaders) / sizeof (knownheaders [0]); ++i)
545 root 1.24 if (len == knownheaders [i].len && FP_strnicmp_fast (line, knownheaders [i].str, len) == 0)
546 root 1.1 return 1;
547    
548     return 0;
549     }
550    
551     /*
552     * Scan a header
553     */
554    
555     int
556     UUScanHeader (FILE *datei, headers *envelope)
557     {
558     char *ptr;
559    
560 root 1.23 while (!FP_feof (datei)) {
561 root 1.1 if ((ptr = ScanHeaderLine (datei, NULL)) == NULL)
562     break;
563 root 1.16 if (*ptr == '\0')
564 root 1.1 break;
565     ParseHeader (envelope, ptr);
566     }
567     return 0;
568     }
569    
570     /*
571     * Scan something for encoded data and fill the fileread* structure.
572     * If boundary is non-NULL, we stop after having read it. If Check-
573     * Headers != 0, we also stop after we've found uu_headercount recog-
574     * nized header lines.
575     * If we have a boundary, then we also don't accept Base64; MIME mails
576     * really should handle this properly.
577     * We return -1 if something went wrong, 0 if everything is normal,
578     * 1 if we found a new header and 2 if we found a boundary.
579     * In MIME message bodies (not multiparts), we also disable our reduced
580     * MIME handling.
581     */
582    
583 root 1.26 ecb_hot static int
584 root 1.1 ScanData (FILE *datei, char *fname, int *errcode,
585     char *boundary, int ismime, int checkheaders,
586     fileread *result)
587     {
588     char *line=uuscan_sdline, *bhds1=uuscan_sdbhds1, *bhds2=uuscan_sdbhds2;
589     static char *ptr, *p2, *p3=NULL, *bhdsp, bhl;
590 root 1.7 int islen[10], isb64[10], isuue[10], isxxe[10], isbhx[10], iscnt;
591 root 1.2 int cbb64, cbuue, cbxxe, cbbhx;
592 root 1.1 int bhflag=0, vflag, haddh=0, hadct=0;
593 root 1.4 int bhrpc=0, bhnf=0, c, hcount, lcount, blen=0;
594 root 1.1 int encoding=0, dflag=0, ctline=42;
595     int dontcare=0, hadnl=0;
596 root 1.4 long preheaders=0, oldposition;
597 root 1.14 long yepartends=0;
598 root 1.1 size_t dcc, bhopc;
599    
600     *errcode = UURET_OK;
601     (void) UUDecodeLine (NULL, NULL, 0); /* init */
602     bhdsp = bhds2;
603    
604 root 1.23 if (datei == NULL || FP_feof (datei))
605 root 1.1 return -1;
606    
607     result->startpos = ftell (datei);
608     hcount = lcount = 0;
609    
610 root 1.2 for (iscnt=0; iscnt<10; iscnt++) {
611     isb64[iscnt] = isuue[iscnt] = isxxe[iscnt] = isbhx[iscnt] = 0;
612 root 1.7 islen[iscnt] = -1;
613 root 1.2 }
614    
615     iscnt = 0;
616    
617 root 1.1 if (boundary)
618     blen = strlen (boundary);
619    
620 root 1.23 while (!FP_feof (datei)) {
621 root 1.1 oldposition = ftell (datei);
622 root 1.23 if (FP_fgets (line, 1024, datei) == NULL)
623 root 1.1 break;
624     if (ferror (datei))
625     break;
626    
627     /*
628     * Make Busy Polls
629     */
630 root 1.2
631 root 1.1 if (UUBUSYPOLL(ftell(datei),progress.fsize)) {
632 root 1.29 UUMessage (UUMSG_NOTE, uustring (S_SCAN_CANCEL));
633 root 1.1 *errcode = UURET_CANCEL;
634     break;
635     }
636    
637 root 1.2 if (IsLineEmpty (line)) { /* line empty? */
638     hcount = 0;
639     hadnl = 1;
640     continue; /* then ignore */
641     }
642    
643 root 1.1 if (checkheaders) {
644     if (IsKnownHeader (line)) {
645     (void) ScanHeaderLine (datei, line);
646    
647     if (hcount == 0) {
648     preheaders = oldposition;
649     lcount = 0;
650     }
651     hcount++;
652     lcount++;
653    
654     /*
655     * check for the various restart counters
656     */
657    
658     if ((hcount >= hlcount.restart) ||
659     (hcount >= hlcount.afterdata && ismime == 0) ||
660     (hcount >= hlcount.afterdata && result->uudet) ||
661     (hcount >= hlcount.afternl && result->uudet && hadnl)) {
662     /*
663     * Hey, a new header starts here
664     */
665     fseek (datei, preheaders, SEEK_SET);
666     break;
667     }
668     /* continue; */
669     }
670     else if (lcount > WAITHEADER) {
671     hcount = 0;
672     lcount = 0;
673     dontcare=0;
674     }
675     else if (hcount) {
676     lcount++;
677     dontcare=1;
678     }
679     else {
680     dontcare=0;
681     }
682     }
683     else {
684     dontcare=0;
685     }
686 root 1.2
687 root 1.22 if (boundary != NULL &&
688 root 1.1 line[0] == '-' && line[1] == '-' &&
689     strncmp (line+2, boundary, blen) == 0) {
690     fseek (datei, oldposition, SEEK_SET);
691     break;
692     }
693     if (boundary != NULL && line[0] == 'C' && line[1] == 'o' &&
694 root 1.24 FP_strnicmp_fast (line, "Content-Type:", 13) == 0) {
695 root 1.1 ptr = ScanHeaderLine (datei, line);
696 root 1.23 p2 = (ptr)?FP_stristr(ptr,"boundary"):NULL;
697 root 1.1 p3 = (p2)?ParseValue(p2):NULL;
698    
699     if (p3 && strcmp (p3, boundary) == 0) {
700     fseek (datei, oldposition, SEEK_SET);
701     break;
702     }
703     else {
704     p3 = NULL;
705     }
706     }
707    
708 root 1.24 if (strncmp (line, "begin ", 6) == 0 ||
709     FP_strnicmp_fast (line, "<pre>begin ", 11) == 0) {
710 root 1.2 if ((result->begin || result->end ||
711     result->uudet == B64ENCODED ||
712     result->uudet == BH_ENCODED) && !uu_more_mime) {
713 root 1.1 fseek (datei, oldposition, SEEK_SET);
714     break;
715     }
716 root 1.22
717 root 1.1 if (*line == '<')
718     ptr = line + 10;
719     else
720     ptr = line + 5;
721    
722     while (*ptr == ' ') ptr++;
723 root 1.22 while (isdigit (*ptr))
724 root 1.1 result->mode = result->mode * 8 + *ptr++ - '0';
725     while (*ptr == ' ') ptr++;
726    
727     /*
728     * We may have picked up a filename from a uuenview-style header
729     */
730 root 1.23 FP_free (result->filename);
731     result->filename = FP_strdup (ptr);
732 root 1.1 result->begin = 1;
733    
734     while (isspace (result->filename[strlen(result->filename)-1]))
735     result->filename[strlen(result->filename)-1] = '\0';
736    
737     continue;
738     }
739    
740 root 1.4 if ((strncmp (line, "end", 3) == 0) &&
741     result->uudet != BH_ENCODED &&
742     result->uudet != YENC_ENCODED) {
743 root 1.1 if (result->uudet == B64ENCODED && result->begin)
744     result->uudet = XX_ENCODED;
745    
746     if (result->uudet != B64ENCODED) {
747     result->end = 1;
748     if (dflag && encoding)
749     result->uudet = encoding;
750     continue;
751     }
752     }
753    
754     hadnl = 0;
755    
756     /*
757     * Detect a UUDeview-Style header
758     */
759    
760 root 1.24 if (FP_strnicmp_fast (line, "_=_ Part ", 9) == 0 &&
761 root 1.4 result->uudet != YENC_ENCODED) {
762 root 1.1 if (result->uudet) {
763     fseek (datei, oldposition, SEEK_SET);
764     break;
765     }
766     result->partno = atoi (line + 8);
767 root 1.23 if ((ptr = FP_stristr (line, "of file ")) != NULL) {
768 root 1.1 ptr += 8;
769     while (isspace (*ptr)) ptr++;
770     p2 = ptr;
771 root 1.22 while (isalnum(*p2) ||
772 root 1.1 *p2 == '.' || *p2=='_' || *p2 == '-' ||
773     *p2 == '!' || *p2=='@' || *p2 == '$')
774     p2++;
775     c = *p2; *p2 = '\0';
776     if (p2 != ptr && result->filename == NULL)
777 root 1.23 result->filename = FP_strdup (ptr);
778 root 1.1 else if (p2 - ptr > 5 && strchr (ptr, '.') != NULL) {
779     /*
780     * This file name looks good, too. Let's use it
781     */
782 root 1.23 FP_free (result->filename);
783     result->filename = FP_strdup (ptr);
784 root 1.1 }
785     *p2 = c;
786     }
787     }
788    
789     /*
790     * Some reduced MIME handling. Only use if boundary == NULL. Also
791     * accept the "X-Orcl-Content-Type" used by some braindead program.
792     */
793 root 1.4 if (boundary == NULL && !ismime && !uu_more_mime &&
794     result->uudet != YENC_ENCODED) {
795 root 1.24 if (FP_strnicmp_fast (line, "Content-Type", 12) == 0 ||
796     FP_strnicmp_fast (line, "X-Orcl-Content-Type", 19) == 0) {
797 root 1.1 /*
798     * We use Content-Type to mark a new attachment and split the file.
799     * However, we do not split if we haven't found anything encoded yet.
800     */
801     if (result->uudet) {
802     fseek (datei, oldposition, SEEK_SET);
803     break;
804     }
805     if ((ptr = strchr (line, ':')) != NULL) {
806     ptr++;
807 root 1.21 while (isspace (*ptr)) ptr++;
808     p2 = ptr;
809 root 1.20 while (*p2 && !isspace (*p2) && *p2 != ';') p2++;
810 root 1.1 c = *p2; *p2 = '\0';
811     if (p2 != ptr) {
812 root 1.23 FP_free (result->mimetype);
813     result->mimetype = FP_strdup (ptr);
814 root 1.1 }
815     *p2 = c;
816     }
817     ctline=0;
818     hadct=1;
819     }
820 root 1.23 if ((ptr = FP_stristr (line, "number=")) && ctline<4) {
821 root 1.1 ptr += 7; if (*ptr == '"') ptr++;
822     result->partno = atoi (ptr);
823     }
824 root 1.23 if ((ptr = FP_stristr (line, "total=")) && ctline<4) {
825 root 1.1 ptr += 6; if (*ptr == '"') ptr++;
826     result->maxpno = atoi (ptr);
827     }
828 root 1.23 if ((ptr = FP_stristr (line, "name=")) && ctline<4) {
829 root 1.1 ptr += 5;
830     while (isspace (*ptr)) ptr++;
831     if (*ptr == '"' && *(ptr+1) && (p2 = strchr (ptr+2, '"')) != NULL) {
832     c = *p2; *p2 = '\0';
833 root 1.23 FP_free (result->filename);
834     result->filename = FP_strdup (ptr+1);
835 root 1.1 *p2 = c;
836     }
837     else if (*ptr=='\''&&*(ptr+1)&&(p2 = strchr(ptr+2, '\'')) != NULL) {
838     c = *p2; *p2 = '\0';
839 root 1.23 FP_free (result->filename);
840     result->filename = FP_strdup (ptr+1);
841 root 1.1 *p2 = c;
842     }
843     else {
844     p2 = ptr;
845 root 1.22 while (isalnum(*p2) ||
846 root 1.1 *p2 == '.' || *p2=='_' || *p2 == '-' ||
847     *p2 == '!' || *p2=='@' || *p2 == '$')
848     p2++;
849     c = *p2; *p2 = '\0';
850     if (p2 != ptr && result->filename == NULL)
851 root 1.23 result->filename = FP_strdup (ptr);
852 root 1.1 else if (p2 - ptr > 5 && strchr (ptr, '.') != NULL) {
853     /*
854     * This file name looks good, too. Let's use it
855     */
856 root 1.23 FP_free (result->filename);
857     result->filename = FP_strdup (ptr);
858 root 1.1 }
859     *p2 = c;
860     }
861     }
862 root 1.23 if ((ptr = FP_stristr (line, "id=")) && ctline<4) {
863 root 1.1 p2 = ptr += 3;
864     if (*p2 == '"') {
865     p2 = strchr (++ptr, '"');
866     }
867     else {
868     while (*p2 && isprint(*p2) && !isspace(*p2) && *p2 != ';')
869     p2++;
870     }
871     if (p2 && *p2 && p2!=ptr) {
872     c = *p2; *p2 = '\0';
873     if (result->mimeid)
874 root 1.23 FP_free (result->mimeid);
875     result->mimeid = FP_strdup (ptr);
876 root 1.1 *p2 = c;
877     }
878     }
879 root 1.22
880     /*
881 root 1.1 * Handling for very short Base64 files.
882     */
883 root 1.2 if (uu_tinyb64 && !ismime && !uu_more_mime) {
884 root 1.1 if (line[0] == '-' && line[1] == '-') {
885     if (dflag && (encoding==B64ENCODED || result->uudet==B64ENCODED)) {
886     if (encoding==B64ENCODED && result->uudet==0 && (haddh||hadct)) {
887     result->uudet = encoding;
888     encoding = dflag = 0;
889     }
890     haddh = 1;
891     continue;
892     }
893     hadct = 0;
894     }
895     }
896     } /* end of reduced MIME handling */
897    
898     /*
899 root 1.2 * If we're in "freestyle" mode, have not encountered anything
900     * interesting yet, and stumble upon something that looks like
901     * a boundary, followed by a Content-* line, try to use it.
902     */
903    
904     if (boundary == NULL && !ismime && !uu_more_mime && dflag <= 1 &&
905     line[0] == '-' && line[1] == '-' && strlen(line+2)>10 &&
906 root 1.23 (((ptr = FP_strrstr (line+2, "--")) == NULL) ||
907 root 1.16 ptr[2]) &&
908 root 1.23 FP_strstr (line+2, "_=_") != NULL) {
909 root 1.12
910     long oldposition = ftell (datei); /* refresh oldpositition so the comment below becomes true */
911 root 1.22
912 root 1.23 if (FP_fgets (line, 1024, datei) == NULL) {
913 root 1.2 break;
914     }
915 root 1.24 if (FP_strnicmp_fast (line, "Content-", 8) == 0) {
916 root 1.2 /*
917     * Okay, let's do it. This breaks out of ScanData. ScanPart will
918     * recognize the boundary on the next call and use it.
919     */
920     fseek (datei, oldposition, SEEK_SET);
921     break;
922     }
923     }
924    
925     /*
926 root 1.4 * Detection for yEnc encoding
927     */
928    
929     if (strncmp (line, "=ybegin ", 8) == 0 &&
930 root 1.23 FP_strstr (line, " name=") != NULL) {
931 root 1.7 if ((result->begin || result->end || result->uudet) && !uu_more_mime) {
932 root 1.4 fseek (datei, oldposition, SEEK_SET);
933     break;
934     }
935    
936     /*
937     * name continues to the end of the line
938     */
939 root 1.22
940 root 1.23 ptr = FP_strstr (line, " name=") + 6;
941 root 1.4
942 root 1.11 /* newsbin pro 5.0 (at least) is braindamaged enough to put (null) here */
943     /* create something sensible, trust a windows program to fuck it up */
944     if (strncmp (ptr, "(null)", 6))
945     {
946 root 1.23 FP_free (result->filename);
947     result->filename = FP_strdup (ptr);
948 root 1.11
949     while (isspace (result->filename[strlen(result->filename)-1]))
950     result->filename[strlen(result->filename)-1] = '\0';
951     }
952 root 1.4
953     /*
954     * Determine size
955     */
956    
957 root 1.23 if ((ptr = FP_strstr (line, " size=")) != NULL) {
958 root 1.6 ptr += 6;
959 root 1.30 result->yefilesize = atol (ptr);
960 root 1.6 }
961     else {
962 root 1.14 result->yefilesize = -1;
963 root 1.6 }
964 root 1.4
965     /*
966     * check for multipart file and read =ypart line
967     */
968    
969 root 1.23 if ((ptr = FP_strstr (line, " part=")) != NULL) {
970 root 1.4 result->partno = atoi (ptr + 6);
971    
972     if (result->partno == 1) {
973     result->begin = 1;
974     }
975    
976 root 1.23 if ((ptr = FP_strstr (line, " total=")))
977 root 1.18 result->maxpno = atoi (ptr + 7);
978    
979 root 1.23 if (FP_fgets (line, 1024, datei) == NULL) {
980 root 1.4 break;
981     }
982    
983     if (strncmp (line, "=ypart ", 7) != 0) {
984     break;
985     }
986    
987 root 1.23 if ((ptr = FP_strstr (line, " end=")) == NULL) {
988 root 1.4 break;
989     }
990 root 1.22
991 root 1.30 yepartends = atol (ptr + 5);
992 root 1.4 }
993     else {
994     result->partno = 1;
995     result->begin = 1;
996     }
997    
998     /*
999     * Don't want auto-detection
1000     */
1001    
1002     result->uudet = YENC_ENCODED;
1003     continue;
1004     }
1005    
1006 root 1.30 if (strncmp (line, "=yend ", 6) == 0 && result->uudet == YENC_ENCODED) {
1007 root 1.18 if (yepartends == 0) {
1008     if (!result->maxpno || result->maxpno == result->partno)
1009     result->end = 1;
1010     } else if (yepartends >= result->yefilesize) {
1011 root 1.4 result->end = 1;
1012     }
1013 root 1.7 #if 0
1014 root 1.4 if (!uu_more_mime)
1015     break;
1016 root 1.7 #endif
1017     continue;
1018 root 1.4 }
1019    
1020     /*
1021 root 1.1 * if we haven't yet found anything encoded, try to find something
1022     */
1023    
1024     if (!(result->uudet)) {
1025     /*
1026     * Netscape-Repair code is the same as in uunconc.c
1027     */
1028    
1029 root 1.2 if ((vflag = UUValidData (line, 0, &bhflag)) == 0 && !ismime)
1030 root 1.1 vflag = UURepairData (datei, line, 0, &bhflag);
1031    
1032     /*
1033 root 1.2 * Check data against all possible encodings
1034     */
1035    
1036 root 1.7 islen[iscnt%10] = strlen(line);
1037 root 1.2 isb64[iscnt%10] = (UUValidData (line, B64ENCODED, &bhflag)==B64ENCODED);
1038     isuue[iscnt%10] = (UUValidData (line, UU_ENCODED, &bhflag)==UU_ENCODED);
1039     isxxe[iscnt%10] = (UUValidData (line, XX_ENCODED, &bhflag)==XX_ENCODED);
1040     isbhx[iscnt%10] = (UUValidData (line, BH_ENCODED, &bhflag)==BH_ENCODED);
1041    
1042     /*
1043     * If we've got a first valid encoded line, we get suspicious if
1044     * it's shorter than, say, 40 characters.
1045     */
1046    
1047     if (vflag == B64ENCODED &&
1048     (dflag == 0 || encoding != B64ENCODED) &&
1049     strlen (line) < 40 && !result->begin && !uu_tinyb64) {
1050     isb64[iscnt%10] = 0;
1051     vflag = 0;
1052 root 1.1 }
1053    
1054 root 1.2 if ((vflag == UU_ENCODED || vflag == XX_ENCODED) &&
1055     (dflag == 0 || encoding != vflag) &&
1056     strlen (line) < 40 && !result->begin) {
1057     isuue[iscnt%10] = isxxe[iscnt%10] = 0;
1058     vflag = 0;
1059     }
1060    
1061     iscnt++;
1062    
1063     /*
1064     * Ah, so we got an encoded line? How interesting!
1065     */
1066    
1067 root 1.1 if (vflag) {
1068     /*
1069     * For BinHex data, we can use the initial colon ':' as begin
1070     * and the terminating colon as ':'.
1071     * If (vflag && !bhflag), this is the last line,
1072     */
1073     if (vflag == BH_ENCODED) {
1074 root 1.2 if (line[0] == ':' && result->end) {
1075     fseek (datei, oldposition, SEEK_SET);
1076     break;
1077     }
1078 root 1.1 if (line[0] == ':')
1079     result->begin = 1;
1080     if (bhflag == 0) {
1081     result->uudet = BH_ENCODED;
1082     result->end = 1;
1083     }
1084     }
1085     /*
1086     * For BinHex files, the file name is encoded in the first encoded
1087     * data bytes. We try to extract it here
1088     */
1089     if (vflag == BH_ENCODED && bhnf == 0 && result->filename == NULL) {
1090     if (bhdsp == bhds2 ||
1091     ((bhdsp-bhds2) <= (int) bhds2[0] &&
1092 root 1.19 (bhdsp-bhds2) < 256)) {
1093 root 1.1 dcc = UUDecodeLine (line, bhds1, BH_ENCODED);
1094     UUbhdecomp (bhds1, bhdsp, &bhl, &bhrpc,
1095     dcc, 256-(bhdsp-bhds2), &bhopc);
1096     bhdsp += bhopc;
1097     }
1098     if ((bhdsp-bhds2) > (int) bhds2[0] && bhds2[0]>0 &&
1099     result->filename==NULL) {
1100     memcpy (bhds1, bhds2+1, (int) bhds2[0]);
1101     bhds1[(int)bhds2[0]]='\0';
1102 root 1.23 result->filename = FP_strdup (bhds1);
1103 root 1.1 bhnf = 1;
1104     }
1105     else if (bhdsp-bhds2 >= 256 && bhds2[0]>0) {
1106     memcpy (bhds1, bhds2+1, 255);
1107     bhds1[255] = '\0';
1108 root 1.23 result->filename = FP_strdup (bhds1);
1109 root 1.1 bhnf = 1;
1110     }
1111     else if (bhds2[0] <= 0)
1112     bhnf = 1;
1113     }
1114 root 1.2
1115 root 1.1 /*
1116 root 1.2 * We accept an encoding if it has been true for four consecutive
1117     * lines. Check the is<enc> arrays to avoid mistaking one encoding
1118     * for the other. Uuencoded data is rather easily mistaken for
1119     * Base 64. If the data matches more than one encoding, we need to
1120     * scan further.
1121 root 1.7 *
1122     * Since text can also rather easily be mistaken for UUencoded
1123     * data if it just happens to have 4 lines in a row that have the
1124     * correct first character for the length of the line, we also add
1125     * a check that the first 3 lines must be the same length, and the
1126     * 4th line must be less than or equal to that length. (since
1127     * uuencoders use the same length for all lines except the last,
1128     * this shouldn't increase the minimum size of UUdata we can
1129     * detect, as it would if we tested all 4 lines for being the same
1130     * length.) - Matthew Mueller, 20030109
1131 root 1.1 */
1132 root 1.2
1133     if (iscnt > 3) {
1134     cbb64 = (isb64[(iscnt-1)%10] && isb64[(iscnt-2)%10] &&
1135     isb64[(iscnt-3)%10] && isb64[(iscnt-4)%10]);
1136     cbuue = (isuue[(iscnt-1)%10] && isuue[(iscnt-2)%10] &&
1137 root 1.7 isuue[(iscnt-3)%10] && isuue[(iscnt-4)%10] &&
1138     islen[(iscnt-1)%10] <= islen[(iscnt-2)%10] &&
1139     islen[(iscnt-2)%10] == islen[(iscnt-3)%10] &&
1140     islen[(iscnt-3)%10] == islen[(iscnt-4)%10]);
1141 root 1.2 cbxxe = (isxxe[(iscnt-1)%10] && isxxe[(iscnt-2)%10] &&
1142 root 1.7 isxxe[(iscnt-3)%10] && isxxe[(iscnt-4)%10] &&
1143     islen[(iscnt-1)%10] <= islen[(iscnt-2)%10] &&
1144     islen[(iscnt-2)%10] == islen[(iscnt-3)%10] &&
1145     islen[(iscnt-3)%10] == islen[(iscnt-4)%10]);
1146 root 1.2 cbbhx = (isbhx[(iscnt-1)%10] && isbhx[(iscnt-2)%10] &&
1147     isbhx[(iscnt-3)%10] && isbhx[(iscnt-4)%10]);
1148     }
1149     else {
1150     cbb64 = cbuue = cbxxe = cbbhx = 0;
1151     }
1152    
1153     if (cbb64 && !cbuue && !cbxxe && !cbbhx) {
1154     result->uudet = B64ENCODED;
1155     }
1156     else if (!cbb64 && cbuue && !cbxxe && !cbbhx) {
1157     result->uudet = UU_ENCODED;
1158     }
1159     else if (!cbb64 && !cbuue && cbxxe && !cbbhx) {
1160     result->uudet = XX_ENCODED;
1161     }
1162     else if (!cbb64 && !cbuue && !cbxxe && cbbhx) {
1163     result->uudet = BH_ENCODED;
1164     }
1165    
1166     if (result->uudet) {
1167 root 1.1 encoding = dflag = 0;
1168    
1169     /*
1170     * If we're in fast mode, we're told we don't have to look
1171     * for anything below, so we can as well break out of every-
1172     * thing
1173     * We cannot fast-scan if we have a boundary to look after.
1174     */
1175    
1176     if (uu_fast_scanning && boundary == NULL)
1177     break;
1178    
1179     /*
1180     * Skip the encoded data. We simply wait for a boundary, for
1181     * a header or for an empty line. But we also try to pick up
1182     * an "end"
1183     */
1184    
1185     hcount = lcount = 0;
1186    
1187 root 1.23 while (!FP_feof (datei)) {
1188 root 1.1 /*
1189     * Make Busy Polls
1190     */
1191     if (UUBUSYPOLL(ftell(datei),progress.fsize)) {
1192 root 1.29 UUMessage (UUMSG_NOTE, uustring (S_SCAN_CANCEL));
1193 root 1.1 *errcode = UURET_CANCEL;
1194     break;
1195     }
1196    
1197     oldposition = ftell (datei);
1198 root 1.23 if (FP_fgets (line, 1024, datei) == NULL)
1199 root 1.1 break;
1200     if (ferror (datei))
1201     break;
1202    
1203     /*
1204     * Stop scanning at an empty line or a MIME-boundary.
1205     */
1206     if (IsLineEmpty (line))
1207     break;
1208     if (boundary && line[0] == '-' && line[1] == '-' &&
1209     strncmp (line+2, boundary, blen) == 0) {
1210     fseek (datei, oldposition, SEEK_SET);
1211     break;
1212     }
1213     else if (line[0] == 'e' && (result->uudet == UU_ENCODED ||
1214     result->uudet == XX_ENCODED)) {
1215     if (strncmp (line, "end", 3) == 0) {
1216     result->end = 1;
1217     break;
1218     }
1219     }
1220     else if (line[0] == 'b') {
1221     if (strncmp (line, "begin ", 6) == 0) {
1222     fseek (datei, oldposition, SEEK_SET);
1223     break;
1224     }
1225     }
1226    
1227     if (checkheaders) {
1228     if (IsKnownHeader (line)) {
1229     (void) ScanHeaderLine (datei, line);
1230     if (hcount == 0)
1231     preheaders = oldposition;
1232     hcount++;
1233     lcount++;
1234     if ((hcount >= hlcount.restart) ||
1235     (hcount >= hlcount.afterdata && result->uudet)) {
1236     /*
1237     * Hey, a new header starts here
1238     */
1239     fseek (datei, preheaders, SEEK_SET);
1240     break;
1241     }
1242     }
1243     else if (lcount > WAITHEADER) {
1244     hcount = 0;
1245     lcount = 0;
1246     }
1247     else if (hcount) {
1248     lcount++;
1249     }
1250     }
1251     if (result->uudet == BH_ENCODED) {
1252     /* pick up ``EOF'' for BinHex files. Slow :-< */
1253     if (line[0] && strchr (line+1, ':') != NULL) {
1254     result->end = 1;
1255 root 1.2 bhflag = 0;
1256 root 1.1 break;
1257     }
1258     }
1259     }
1260 root 1.2
1261 root 1.1 if (ferror (datei) || *errcode == UURET_CANCEL)
1262     break;
1263    
1264     if (line[0] == '-' && line[1] == '-')
1265     haddh = 1;
1266    
1267     /*
1268     * Okay, got everything we need. If we had headers or a
1269     * boundary, we break out of the outer loop immediately.
1270     */
1271    
1272     if (IsKnownHeader (line) ||
1273     (boundary && line[0] == '-' && line[1] == '-' &&
1274     strncmp (line+2, boundary, blen) == 0)) {
1275     break;
1276     }
1277 root 1.2
1278 root 1.1 /*
1279     * Otherwise, we wait until finding something more interesting
1280     * in the outer loop
1281     */
1282 root 1.2
1283     continue;
1284 root 1.1 }
1285 root 1.22
1286 root 1.2 /*
1287     * Select the encoding with the best "history"
1288     */
1289    
1290     cbb64 = isb64[(iscnt-1)%10];
1291     cbuue = isuue[(iscnt-1)%10];
1292     cbxxe = isxxe[(iscnt-1)%10];
1293     cbbhx = isbhx[(iscnt-1)%10];
1294     dflag = 0;
1295    
1296     if (cbb64 || cbuue || cbxxe || cbbhx) {
1297     for (dflag=2; dflag<iscnt && dflag<4; dflag++) {
1298     if ((!cbb64 || !isb64[(iscnt-dflag)%10]) &&
1299     (!cbuue || !isuue[(iscnt-dflag)%10]) &&
1300     (!cbxxe || !isxxe[(iscnt-dflag)%10]) &&
1301     (!cbbhx || !isbhx[(iscnt-dflag)%10])) {
1302     dflag--;
1303     break;
1304     }
1305     cbb64 &= isb64[(iscnt-dflag)%10];
1306     cbuue &= isuue[(iscnt-dflag)%10];
1307     cbxxe &= isxxe[(iscnt-dflag)%10];
1308     cbbhx &= isbhx[(iscnt-dflag)%10];
1309     }
1310     }
1311    
1312     /*
1313     * clear-cut cases
1314     */
1315    
1316     if (cbb64 && !cbuue && !cbxxe && !cbbhx) {
1317     encoding = B64ENCODED;
1318     }
1319     else if (!cbb64 && cbuue && !cbxxe && !cbbhx) {
1320     encoding = UU_ENCODED;
1321     }
1322     else if (!cbb64 && !cbuue && cbxxe && !cbbhx) {
1323     encoding = XX_ENCODED;
1324     }
1325     else if (!cbb64 && !cbuue && !cbxxe && cbbhx) {
1326     encoding = BH_ENCODED;
1327     }
1328     else {
1329     encoding = 0;
1330     }
1331    
1332     /*
1333     * Check a few common non-clear-cut cases
1334     */
1335    
1336     if (!encoding && cbuue && result->begin) {
1337     encoding = UU_ENCODED;
1338     }
1339     else if (!encoding && cbxxe && result->begin) {
1340     encoding = XX_ENCODED;
1341     }
1342     else if (!encoding && cbb64) {
1343     encoding = B64ENCODED;
1344     }
1345     else if (!encoding && cbuue) {
1346     encoding = UU_ENCODED;
1347     }
1348     else if (!encoding && cbxxe) {
1349     encoding = XX_ENCODED;
1350     }
1351     else if (!encoding && cbbhx) {
1352     encoding = BH_ENCODED;
1353 root 1.1 }
1354     }
1355     else if (!dontcare) {
1356     encoding = 0;
1357     dflag = 0;
1358     haddh = 0;
1359     }
1360     } /* if (!uudet) */
1361     /*
1362     * End of scanning loop
1363     */
1364 root 1.23 } /* while (!FP_feof (datei)) */
1365 root 1.1
1366 root 1.23 if (FP_feof (datei))
1367 root 1.1 oldposition = ftell (datei);
1368    
1369     if (dflag && encoding == B64ENCODED && haddh)
1370     result->uudet = B64ENCODED;
1371     else if (dflag && encoding == BH_ENCODED)
1372     result->uudet = BH_ENCODED;
1373    
1374     /* Base64 doesn't have begin or end, so it was probably XX */
1375     if (result->uudet == B64ENCODED && result->begin && result->end)
1376     result->uudet = XX_ENCODED;
1377    
1378     /* Base64 doesn't have begin or end */
1379     if (result->uudet == B64ENCODED)
1380     result->begin = result->end = 0;
1381    
1382     /* Base64 and BinHex don't have a file mode */
1383 root 1.4 if (result->uudet == B64ENCODED || result->uudet == BH_ENCODED ||
1384     result->uudet == YENC_ENCODED)
1385 root 1.1 result->mode = 6*64+4*8+4;
1386    
1387     /*
1388 root 1.2 * When strict MIME adherance is set, throw out suspicious attachments
1389     */
1390    
1391     if (uu_more_mime) {
1392     /*
1393     * In a MIME message, Base64 should be appropriately tagged
1394     */
1395    
1396     if (result->uudet == B64ENCODED) {
1397     result->uudet = 0;
1398     }
1399    
1400     /*
1401     * Do not accept incomplete UU or XX encoded messages
1402     */
1403    
1404     if ((result->uudet != 0 && result->uudet != B64ENCODED) &&
1405     (!result->begin || !result->end)) {
1406     result->uudet = 0;
1407     }
1408     }
1409    
1410     /*
1411 root 1.1 * In fast mode, this length will yield a false value. We don't care.
1412     * This must be checked for in uunconc(), where we usually stop decoding
1413     * after reaching startpos+length
1414     */
1415    
1416     if (uu_fast_scanning)
1417     result->length = progress.fsize-result->startpos;
1418     else
1419     result->length = ftell(datei)-result->startpos;
1420    
1421     if (ferror (datei)) {
1422     *errcode = UURET_IOERR;
1423     uu_errno = errno;
1424     return -1;
1425     }
1426     if (*errcode != UURET_OK) {
1427     return -1;
1428     }
1429    
1430     if (boundary && line[0] == '-' && line[1] == '-' &&
1431     strncmp (line+2, boundary, blen) == 0)
1432     return 2;
1433     else if (boundary && p3 &&
1434     line[0] == 'C' && line[1] == 'o' &&
1435 root 1.24 FP_strnicmp_fast (line, "Content-Type:", 13) == 0 &&
1436 root 1.1 strcmp (p3, boundary) == 0)
1437     return 2;
1438     else if (IsKnownHeader (line))
1439     return 1;
1440    
1441     return 0;
1442     }
1443    
1444     /*
1445     * This is the main scanning function.
1446     */
1447    
1448     fileread *
1449 root 1.31 UUScanPart (FILE *datei, char *fname, int *errcode)
1450 root 1.1 {
1451     int ecount, hcount, lcount;
1452 root 1.4 int bhflag, begflag, vflag, blen=0, res;
1453     long preheaders, prevpos=0, preenc, before;
1454 root 1.1 char *line=uuscan_spline;
1455     fileread *result;
1456     char *ptr1, *ptr2;
1457    
1458     (void) UUDecodeLine (NULL, NULL, 0); /* init */
1459 root 1.23 if (datei == NULL || FP_feof (datei)) {
1460 root 1.1 *errcode = UURET_OK;
1461     return NULL;
1462     }
1463    
1464     *errcode = UURET_OK;
1465    
1466     if ((result = (fileread *) malloc (sizeof (fileread))) == NULL) {
1467     *errcode = UURET_NOMEM;
1468     return NULL;
1469     }
1470     memset (result, 0, sizeof (fileread));
1471     result->startpos = ftell (datei);
1472     preheaders = result->startpos;
1473     before = result->startpos;
1474    
1475     /* if this is a new file, reset our scanning state */
1476     if (sstate.source == NULL || strcmp (fname, sstate.source) != 0) {
1477     sstate.isfolder = 1; /* assume yes */
1478     sstate.ismime = 0; /* wait for MIME-Version */
1479     sstate.mimestate = MS_HEADERS; /* assume headers follow */
1480     /* mimseqno = 1; */
1481    
1482     while (mssdepth) {
1483     mssdepth--;
1484     UUkillheaders (&(multistack[mssdepth].envelope));
1485 root 1.23 FP_free (multistack[mssdepth].source);
1486 root 1.1 }
1487    
1488     UUkillheaders (&sstate.envelope);
1489     memset (&sstate.envelope, 0, sizeof (headers));
1490    
1491 root 1.23 FP_free (sstate.source);
1492     if ((sstate.source = FP_strdup (fname)) == NULL) {
1493 root 1.1 *errcode = UURET_NOMEM;
1494 root 1.23 FP_free (result);
1495 root 1.1 return NULL;
1496     }
1497    
1498     /* ignore empty lines at the beginning of a file */
1499     preheaders = ftell (datei);
1500 root 1.23 while (!FP_feof (datei)) {
1501 root 1.12 if (UUBUSYPOLL(preheaders,progress.fsize)) SPCANCEL();
1502 root 1.23 if (FP_fgets (line, 1024, datei) == NULL)
1503 root 1.1 break;
1504     if (!IsLineEmpty (line)) {
1505     fseek (datei, preheaders, SEEK_SET);
1506     break;
1507     }
1508     preheaders = ftell (datei);
1509     }
1510     }
1511    
1512 root 1.23 if (ferror(datei) || FP_feof(datei)) {
1513     FP_free (result);
1514 root 1.1 return NULL;
1515     }
1516    
1517     /*
1518     * If we are confident that this is a mail folder and are at the
1519     * beginning of the file, expecting to read some headers, scan
1520     * the envelope.
1521     */
1522    
1523     if (sstate.isfolder && sstate.mimestate == MS_HEADERS) {
1524     hcount = 0;
1525     lcount = 0;
1526     UUkillheaders (&sstate.envelope);
1527    
1528     /*
1529     * clean up leftovers from invalid messages
1530     */
1531    
1532     while (mssdepth) {
1533     mssdepth--;
1534     UUkillheaders (&(multistack[mssdepth].envelope));
1535 root 1.23 FP_free (multistack[mssdepth].source);
1536 root 1.1 }
1537    
1538 root 1.7 prevpos = ftell (datei);
1539 root 1.23 if (FP_fgets (line, 1024, datei) == NULL) {
1540     FP_free (result);
1541 root 1.1 return NULL;
1542     }
1543    
1544 root 1.2 /*
1545     * Special handling for AOL folder files, which start off with a boundary.
1546     * We recognize them by a valid boundary line as the first line of a file.
1547     * Note that the rest of the scanning code becomes suspicious if a boun-
1548     * dary does never appear in a file -- this should save us from grave
1549     * false detection errors
1550     */
1551    
1552 root 1.23 if (!FP_feof (datei) && line[0] == '-' && line[1] == '-' && line[2]) {
1553 root 1.2 sstate.ismime = 1;
1554 root 1.23 sstate.envelope.mimevers = FP_strdup ("1.0");
1555     sstate.envelope.boundary = FP_strdup (line+2);
1556     sstate.envelope.ctype = FP_strdup ("multipart/mixed");
1557 root 1.2 sstate.mimestate = MS_SUBPART;
1558    
1559     *errcode = UURET_CONT;
1560 root 1.23 FP_free (result);
1561 root 1.2 return NULL;
1562     }
1563    
1564     /*
1565     * Normal behavior: look for a RFC 822 header
1566     */
1567    
1568 root 1.23 while (!FP_feof (datei) && !IsLineEmpty (line)) {
1569 root 1.1 if (IsKnownHeader (line))
1570     hcount++;
1571     if (UUBUSYPOLL(ftell(datei),progress.fsize)) SPCANCEL();
1572 root 1.7 if (IsHeaderLine (line)) {
1573     ptr1 = ScanHeaderLine (datei, line);
1574     if (ParseHeader (&sstate.envelope, ptr1) == NULL) {
1575     *errcode = UURET_NOMEM;
1576 root 1.23 FP_free (result);
1577 root 1.7 return NULL;
1578     }
1579 root 1.1 }
1580     /*
1581     * if we've read too many lines without finding headers, then
1582     * this probably isn't a mail folder after all
1583     */
1584     lcount++;
1585 root 1.7 if (lcount > WAITHEADER && hcount < hlcount.afternl) {
1586     fseek (datei, prevpos, SEEK_SET);
1587     line[0] = '\0';
1588 root 1.1 break;
1589 root 1.7 }
1590 root 1.1
1591 root 1.23 if (FP_fgets (line, 1024, datei) == NULL) {
1592 root 1.8 /* If we are at eof without finding headers, there probably isn't */
1593 root 1.15 if (hcount < hlcount.afternl)
1594 root 1.8 fseek (datei, prevpos, SEEK_SET);
1595     break;
1596     }
1597 root 1.1 }
1598 root 1.7
1599 root 1.1 /* skip empty lines */
1600     prevpos = ftell (datei);
1601 root 1.7 if (IsLineEmpty (line)) {
1602 root 1.23 while (!FP_feof (datei)) {
1603     if (FP_fgets (line, 1024, datei) == NULL)
1604 root 1.7 break;
1605     if (UUBUSYPOLL(ftell(datei),progress.fsize)) SPCANCEL();
1606     if (!IsLineEmpty (line)) {
1607     fseek (datei, prevpos, SEEK_SET);
1608     break;
1609     }
1610     prevpos = ftell (datei);
1611 root 1.1 }
1612     }
1613 root 1.7
1614 root 1.1 /*
1615     * If we don't have all valid MIME headers yet, but the following
1616     * line is a MIME header, accept it anyway.
1617     */
1618 root 1.2
1619     if (!uu_more_mime &&
1620     sstate.envelope.mimevers == NULL &&
1621     sstate.envelope.ctype == NULL &&
1622     sstate.envelope.ctenc == NULL &&
1623     IsKnownHeader (line)) {
1624 root 1.1 /*
1625     * see above
1626     */
1627 root 1.23 FP_fgets (line, 1024, datei);
1628 root 1.1
1629 root 1.23 while (!FP_feof (datei) && !IsLineEmpty (line)) {
1630 root 1.1 if (IsKnownHeader (line))
1631     hcount++;
1632     if (UUBUSYPOLL(ftell(datei),progress.fsize)) SPCANCEL();
1633     ptr1 = ScanHeaderLine (datei, line);
1634     if (ParseHeader (&sstate.envelope, ptr1) == NULL) {
1635     *errcode = UURET_NOMEM;
1636 root 1.23 FP_free (result);
1637 root 1.1 return NULL;
1638     }
1639 root 1.2
1640 root 1.23 if (FP_fgets (line, 1024, datei) == NULL)
1641 root 1.1 break;
1642     }
1643     /* skip empty lines */
1644     prevpos = ftell (datei);
1645 root 1.23 while (!FP_feof (datei)) {
1646     if (FP_fgets (line, 1024, datei) == NULL)
1647 root 1.1 break;
1648     if (UUBUSYPOLL(ftell(datei),progress.fsize)) SPCANCEL();
1649     if (!IsLineEmpty (line)) {
1650     fseek (datei, prevpos, SEEK_SET);
1651     break;
1652     }
1653     prevpos = ftell (datei);
1654     }
1655     }
1656 root 1.2
1657 root 1.1 /*
1658     * A partial multipart message probably has only a Content-Type
1659     * header but nothing else. In this case, at least simulate a
1660     * MIME message
1661     * if mimevers is not set but there are other well-known MIME
1662     * headers, don't be too picky about it.
1663     */
1664     if (sstate.envelope.ctype && sstate.envelope.mimevers==NULL &&
1665 root 1.23 FP_stristr (sstate.envelope.ctype, "multipart") != NULL &&
1666 root 1.1 sstate.envelope.boundary != NULL) {
1667 root 1.23 sstate.envelope.mimevers = FP_strdup ("1.0");
1668 root 1.1 hcount = hlcount.afternl;
1669     }
1670     else if (sstate.envelope.mimevers==NULL && sstate.envelope.ctype &&
1671     sstate.envelope.fname && sstate.envelope.ctenc) {
1672 root 1.23 sstate.envelope.mimevers = FP_strdup ("1.0");
1673 root 1.1 hcount = hlcount.afternl;
1674     }
1675    
1676 root 1.7 if (sstate.envelope.mimevers != NULL) {
1677 root 1.1 /* this is a MIME file. check the Content-Type */
1678     sstate.ismime = 1;
1679 root 1.23 if (FP_stristr (sstate.envelope.ctype, "multipart") != NULL) {
1680 root 1.1 if (sstate.envelope.boundary == NULL) {
1681 root 1.29 UUMessage (UUMSG_WARNING, uustring (S_MIME_NO_BOUNDARY));
1682 root 1.1 sstate.mimestate = MS_BODY;
1683 root 1.23 FP_free (sstate.envelope.ctype);
1684     sstate.envelope.ctype = FP_strdup ("text/plain");
1685 root 1.1 }
1686     else {
1687     sstate.mimestate = MS_PREAMBLE;
1688     }
1689     }
1690     else {
1691     sstate.mimestate = MS_BODY; /* just a `simple' message */
1692     }
1693 root 1.7 }
1694     else {
1695     /* not a folder after all */
1696     fseek (datei, prevpos, SEEK_SET);
1697     sstate.isfolder = 0;
1698     sstate.ismime = 0;
1699 root 1.1 }
1700     }
1701    
1702 root 1.23 if (FP_feof (datei) || ferror (datei)) { /* oops */
1703     FP_free (result);
1704 root 1.1 return NULL;
1705     }
1706    
1707     /*
1708     * Handle MIME stuff
1709     */
1710    
1711     /*
1712     * Read Preamble. This must be ended by a sstate.envelope.boundary line.
1713     * If uu_usepreamble is set, we produce a result from this one
1714     */
1715    
1716     if (sstate.ismime && sstate.mimestate == MS_PREAMBLE) {
1717     result->startpos = ftell (datei); /* remember start of preamble */
1718     prevpos = ftell (datei);
1719     preheaders = ftell (datei);
1720    
1721     blen = strlen (sstate.envelope.boundary);
1722     lcount = 0;
1723 root 1.22
1724 root 1.23 while (!FP_feof (datei)) {
1725     if (FP_fgets (line, 1024, datei) == NULL)
1726 root 1.1 break;
1727     if (UUBUSYPOLL(ftell(datei),progress.fsize)) SPCANCEL();
1728     if (line[0] == '-' && line[1] == '-' &&
1729     strncmp (line+2, sstate.envelope.boundary, blen) == 0)
1730     break;
1731     if (!IsLineEmpty (line))
1732     lcount++;
1733    
1734     prevpos = ftell (datei);
1735     }
1736 root 1.23 if (FP_feof (datei) || ferror (datei)) {
1737 root 1.29 UUMessage (UUMSG_WARNING, uustring (S_MIME_B_NOT_FOUND));
1738 root 1.1 /*
1739     * restart and try again; don't restart if uu_fast_scanning
1740     */
1741     sstate.isfolder = 0;
1742     sstate.ismime = 0;
1743     sstate.mimestate = MS_BODY;
1744    
1745     if (!uu_fast_scanning) {
1746     *errcode = UURET_CONT;
1747     fseek (datei, preheaders, SEEK_SET);
1748     }
1749 root 1.23 FP_free (result);
1750 root 1.1 return NULL;
1751     }
1752     if (line[0] == '-' && line[1] == '-' &&
1753     strncmp (line+2, sstate.envelope.boundary, blen) == 0) {
1754     ptr1 = line + 2 + blen;
1755     if (*ptr1 == '-' && *(ptr1+1) == '-') {
1756     /* Empty Multipart Message. Duh. */
1757     sstate.mimestate = MS_EPILOGUE;
1758     }
1759     else {
1760     sstate.mimestate = MS_SUBPART;
1761     }
1762     }
1763     else { /* shouldn't happen */
1764 root 1.29 UUMessage (UUMSG_WARNING, uustring (S_MIME_B_NOT_FOUND));
1765 root 1.1 /*
1766     * restart and try again; don't restart if uu_fast_scanning
1767     */
1768     sstate.isfolder = 0;
1769     sstate.ismime = 0;
1770     sstate.mimestate = MS_BODY;
1771    
1772     if (!uu_fast_scanning) {
1773     *errcode = UURET_CONT;
1774     fseek (datei, preheaders, SEEK_SET);
1775     }
1776 root 1.23 FP_free (result);
1777 root 1.1 return NULL;
1778     }
1779     /* produce result if uu_usepreamble is set */
1780     if (uu_usepreamble && lcount) {
1781     sprintf (line, "%04d.txt", ++mimseqno);
1782 root 1.23 result->subject = FP_strdup (sstate.envelope.subject);
1783     result->filename = FP_strdup (line);
1784     result->origin = FP_strdup (sstate.envelope.from);
1785     result->mimeid = FP_strdup (sstate.envelope.mimeid);
1786     result->mimetype = FP_strdup ("text/plain");
1787 root 1.1 result->mode = 0644;
1788     result->uudet = PT_ENCODED; /* plain text */
1789 root 1.23 result->sfname = FP_strdup (fname);
1790 root 1.1 result->flags = FL_SINGLE | FL_PROPER;
1791     /* result->startpos set from above */
1792     result->length = prevpos - result->startpos;
1793     result->partno = 1;
1794    
1795     /* MIME message, let's continue */
1796     *errcode = UURET_CONT;
1797    
1798     if ((sstate.envelope.subject != NULL && result->subject == NULL) ||
1799     result->filename == NULL || result->sfname == NULL) {
1800     *errcode = UURET_NOMEM;
1801     }
1802    
1803     return result;
1804     }
1805     /* MIME message, let's continue */
1806     if (*errcode == UURET_OK)
1807     *errcode = UURET_CONT;
1808    
1809     /* otherwise, just return NULL */
1810 root 1.23 FP_free (result);
1811 root 1.1 return NULL;
1812     }
1813    
1814     /*
1815     * Read Epilogue, the plain text after the last boundary.
1816     * This can either end with new headers from the next message of a
1817     * mail folder or with a `parent' boundary if we are inside an
1818     * encapsulated Multipart message. Oh yes, and of course the file
1819     * may also simply end :-)
1820     * Another possibility is that we might find plain encoded data
1821     * without encapsulating message. We're not _too_ flexible here,
1822     * we won't detect Base64, and require a proper `begin' line for
1823     * uuencoding and xxencoding
1824     * If uu_usepreamble is set, we produce a result from this one
1825     */
1826    
1827     if (sstate.ismime && sstate.mimestate == MS_EPILOGUE) {
1828     result->startpos = ftell (datei); /* remember start of epilogue */
1829     prevpos = ftell (datei);
1830     preheaders = ftell (datei);
1831     preenc = ftell (datei);
1832     hcount = lcount = 0;
1833     ecount = bhflag = 0;
1834     begflag = vflag = 0;
1835     res = 0;
1836    
1837     /*
1838     * If we are in the outermost message and uu_fast_scanning, we
1839     * know (or assume) that no more messages will follow, so there's
1840     * no need to scan the rest.
1841     */
1842     if (uu_fast_scanning && mssdepth == 0) {
1843     /*
1844     * check if the epilogue is empty
1845     */
1846 root 1.23 while (!FP_feof (datei) && !ferror (datei) && lcount<10 && res==0) {
1847     if (FP_fgets (line, 1024, datei) == NULL)
1848 root 1.1 break;
1849     if (!IsLineEmpty (line))
1850     res++;
1851     lcount++;
1852     }
1853     if (uu_usepreamble && res) {
1854     sprintf (line, "%04d.txt", ++mimseqno);
1855 root 1.23 result->subject = FP_strdup (sstate.envelope.subject);
1856     result->filename = FP_strdup (line);
1857     result->origin = FP_strdup (sstate.envelope.from);
1858     result->mimeid = FP_strdup (sstate.envelope.mimeid);
1859     result->mimetype = FP_strdup ("text/plain");
1860 root 1.1 result->mode = 0644;
1861     result->uudet = PT_ENCODED; /* plain text */
1862 root 1.23 result->sfname = FP_strdup (fname);
1863 root 1.1 result->flags = FL_SINGLE | FL_PROPER | FL_TOEND;
1864     result->partno = 1;
1865     /* result->startpos set from above */
1866     result->length = progress.fsize - result->startpos;
1867    
1868     if ((sstate.envelope.subject != NULL && result->subject == NULL) ||
1869     result->filename == NULL || result->sfname == NULL) {
1870     *errcode = UURET_NOMEM;
1871     }
1872    
1873     return result;
1874     }
1875 root 1.23 FP_free (result);
1876 root 1.1 return NULL;
1877     }
1878    
1879     if (mssdepth > 0)
1880     blen = strlen (multistack[mssdepth-1].envelope.boundary);
1881    
1882 root 1.23 while (!FP_feof (datei)) {
1883     if (FP_fgets (line, 1024, datei) == NULL)
1884 root 1.1 break;
1885     if (UUBUSYPOLL(ftell(datei),progress.fsize)) SPCANCEL();
1886     /* check for parent boundary */
1887     if (mssdepth > 0 && line[0] == '-' && line[1] == '-' &&
1888     strncmp (line+2,
1889     multistack[mssdepth-1].envelope.boundary, blen) == 0)
1890     break;
1891    
1892     /* check for next headers only at outermost level */
1893     if (mssdepth == 0 && IsKnownHeader (line)) {
1894     (void) ScanHeaderLine (datei, line);
1895     if (hcount == 0) {
1896     preheaders = prevpos;
1897     lcount = 0;
1898     }
1899 root 1.22 hcount++;
1900 root 1.1 lcount++;
1901    
1902     if (hcount >= hlcount.restart) {
1903     /* okay, new headers */
1904     break;
1905     }
1906     }
1907     else if (lcount > WAITHEADER) {
1908     hcount = 0;
1909     lcount = 0;
1910     }
1911     else if (hcount) {
1912     lcount++;
1913     }
1914     else {
1915     hcount = lcount = 0;
1916     }
1917    
1918     /* check for begin and encoded data only at outermost level */
1919 root 1.2 if (mssdepth == 0 && !uu_more_mime) {
1920 root 1.24 if (strncmp (line, "begin ", 6) == 0 ||
1921     FP_strnicmp_fast (line, "<pre>begin ", 11) == 0) {
1922 root 1.1 preenc = prevpos;
1923     begflag = 1;
1924     }
1925     else if (strncmp (line, "end", 3) == 0 && begflag) {
1926     ecount = ELC_COUNT;
1927     break;
1928     }
1929     else if ((vflag = UUValidData (line, 0, &bhflag)) != 0) {
1930     if (vflag == BH_ENCODED && bhflag == 0) {
1931     /* very short BinHex file follows */
1932     preenc = prevpos;
1933     break;
1934     }
1935     /* remember that XX can easily be mistaken as Base64 */
1936 root 1.10 if ((vflag == UU_ENCODED || vflag == XX_ENCODED || vflag == B64ENCODED) && begflag) {
1937 root 1.1 if (++ecount >= ELC_COUNT)
1938     break;
1939     }
1940     else {
1941     begflag = 0;
1942     ecount = 0;
1943     }
1944     }
1945     else {
1946     begflag = 0;
1947     ecount = 0;
1948     }
1949     }
1950    
1951     if (!IsLineEmpty (line))
1952     res++;
1953    
1954     prevpos = ftell (datei);
1955     }
1956 root 1.2
1957 root 1.1 if (mssdepth > 0 && line[0] == '-' && line[1] == '-' &&
1958     strncmp (line+2,
1959     multistack[mssdepth-1].envelope.boundary, blen) == 0) {
1960     /* restore previous state */
1961     mssdepth--;
1962     UUkillheaders (&sstate.envelope);
1963 root 1.23 FP_free (sstate.source);
1964 root 1.1 memcpy (&sstate, &(multistack[mssdepth]), sizeof (scanstate));
1965    
1966     ptr1 = line + 2 + strlen (sstate.envelope.boundary);
1967    
1968     if (*ptr1 == '-' && *(ptr1+1) == '-') {
1969     sstate.mimestate = MS_EPILOGUE;
1970     }
1971     else {
1972     sstate.mimestate = MS_SUBPART;
1973     }
1974     result->length = prevpos - result->startpos;
1975     *errcode = UURET_CONT;
1976     }
1977     else if (mssdepth > 0) {
1978 root 1.29 UUMessage (UUMSG_WARNING, uustring (S_MIME_B_NOT_FOUND));
1979 root 1.1 /*
1980     * restart and try again; don't restart if uu_fast_scanning
1981     */
1982     sstate.isfolder = 0;
1983     sstate.ismime = 0;
1984     sstate.mimestate = MS_BODY;
1985    
1986     while (mssdepth) {
1987     mssdepth--;
1988     UUkillheaders (&(multistack[mssdepth].envelope));
1989 root 1.23 FP_free (multistack[mssdepth].source);
1990 root 1.1 }
1991    
1992     if (!uu_fast_scanning) {
1993     *errcode = UURET_CONT;
1994     fseek (datei, preheaders, SEEK_SET);
1995     }
1996 root 1.23 FP_free (result);
1997 root 1.1 return NULL;
1998     }
1999     else if (IsKnownHeader (line)) {
2000     /* new message follows */
2001     sstate.isfolder = 1;
2002     sstate.ismime = 0;
2003     sstate.mimestate = MS_HEADERS;
2004     result->length = preheaders - result->startpos;
2005     fseek (datei, preheaders, SEEK_SET);
2006     }
2007     else if (ecount >= ELC_COUNT) {
2008     /* new plain encoding */
2009     sstate.isfolder = 0;
2010     sstate.ismime = 0;
2011     sstate.mimestate = MS_BODY;
2012     result->length = preenc - result->startpos;
2013     fseek (datei, preenc, SEEK_SET);
2014     }
2015    
2016     /* produce result if uu_usepreamble is set */
2017     if (uu_usepreamble && res) {
2018     sprintf (line, "%04d.txt", ++mimseqno);
2019 root 1.23 result->subject = FP_strdup (sstate.envelope.subject);
2020     result->filename = FP_strdup (line);
2021     result->origin = FP_strdup (sstate.envelope.from);
2022     result->mimeid = FP_strdup (sstate.envelope.mimeid);
2023     result->mimetype = FP_strdup ("text/plain");
2024 root 1.1 result->mode = 0644;
2025     result->uudet = PT_ENCODED; /* plain text */
2026 root 1.23 result->sfname = FP_strdup (fname);
2027 root 1.1 result->flags = FL_SINGLE | FL_PROPER;
2028     result->partno = 1;
2029     /* result->startpos set from above */
2030     /* result->length set from above */
2031    
2032     if ((sstate.envelope.subject != NULL && result->subject == NULL) ||
2033     result->filename == NULL || result->sfname == NULL) {
2034     *errcode = UURET_NOMEM;
2035     }
2036    
2037     return result;
2038     }
2039     /* otherwise, just return NULL */
2040 root 1.23 FP_free (result);
2041 root 1.1 return NULL;
2042     }
2043    
2044     /*
2045     * Scan a new part from a Multipart message. Check for a new local
2046     * envelope (which defaults to `Content-Type: text/plain') and
2047     * evaluate its Content-Type and Content-Transfer-Encoding. If this
2048     * is another Multipart/something, push the current state onto our
2049     * stack and dive into the new environment, starting with another
2050     * preamble.
2051     */
2052 root 1.22
2053 root 1.1 if (sstate.ismime && sstate.mimestate == MS_SUBPART) {
2054     memset (&localenv, 0, sizeof (headers));
2055     result->startpos = ftell (datei);
2056     prevpos = ftell (datei);
2057     hcount = 0;
2058     lcount = 0;
2059    
2060     /*
2061     * Duplicate some data from outer envelope
2062     */
2063    
2064 root 1.23 localenv.mimevers = FP_strdup (sstate.envelope.mimevers);
2065     localenv.from = FP_strdup (sstate.envelope.from);
2066     localenv.subject = FP_strdup (sstate.envelope.subject);
2067     localenv.rcpt = FP_strdup (sstate.envelope.rcpt);
2068     localenv.date = FP_strdup (sstate.envelope.date);
2069 root 1.1
2070     if ((sstate.envelope.mimevers != NULL && localenv.mimevers == NULL) ||
2071     (sstate.envelope.from != NULL && localenv.from == NULL) ||
2072     (sstate.envelope.subject != NULL && localenv.subject == NULL) ||
2073     (sstate.envelope.rcpt != NULL && localenv.rcpt == NULL) ||
2074     (sstate.envelope.date != NULL && localenv.date == NULL)) {
2075    
2076     while (mssdepth) {
2077     mssdepth--;
2078     UUkillheaders (&(multistack[mssdepth].envelope));
2079 root 1.23 FP_free (multistack[mssdepth].source);
2080 root 1.1 }
2081     sstate.isfolder = 0;
2082     sstate.ismime = 0;
2083 root 1.22
2084 root 1.1 UUkillheaders (&localenv);
2085     *errcode = UURET_NOMEM;
2086 root 1.23 FP_free (result);
2087 root 1.1 return NULL;
2088     }
2089 root 1.22
2090 root 1.1 /* Scan subheader. But what if there is no subheader? */
2091     hcount = 0;
2092     lcount = 0;
2093     preheaders = prevpos;
2094 root 1.22
2095 root 1.23 if (FP_fgets (line, 1024, datei) == NULL) {
2096 root 1.1 sstate.isfolder = 0;
2097     sstate.ismime = 0;
2098     while (mssdepth) {
2099     mssdepth--;
2100     UUkillheaders (&(multistack[mssdepth].envelope));
2101 root 1.23 FP_free (multistack[mssdepth].source);
2102 root 1.1 }
2103     UUkillheaders (&localenv);
2104 root 1.23 FP_free (result);
2105 root 1.1 return NULL;
2106     }
2107    
2108 root 1.23 while (!FP_feof (datei) && !IsLineEmpty (line)) {
2109 root 1.1 if (IsKnownHeader (line))
2110     hcount++;
2111     if (UUBUSYPOLL(ftell(datei),progress.fsize)) SPCANCEL();
2112     if (lcount > WAITHEADER && hcount == 0) {
2113     fseek (datei, preheaders, SEEK_SET);
2114     prevpos = preheaders;
2115     break;
2116     }
2117     ptr1 = ScanHeaderLine (datei, line);
2118     if (ParseHeader (&localenv, ptr1) == NULL)
2119     *errcode = UURET_NOMEM;
2120    
2121     if (line[0] == '-' && line[1] == '-')
2122     break;
2123    
2124     prevpos = ftell (datei);
2125    
2126 root 1.23 if (FP_fgets (line, 1024, datei) == NULL)
2127 root 1.1 break;
2128     lcount++;
2129     }
2130     if (line[0] == '-' && line[1] == '-') {
2131     /*
2132     * this shouldn't happen, there must always be an empty line,
2133     * but let's accept it anyway. Just skip back to before the
2134     * boundary, so that it gets handled below
2135     */
2136     fseek (datei, prevpos, SEEK_SET);
2137     }
2138    
2139 root 1.23 if (FP_stristr (localenv.ctype, "multipart") != NULL) {
2140 root 1.1 /* oh no, not again */
2141     if (mssdepth >= MSMAXDEPTH) {
2142     /* Argh, what an isane message. Treat as plain text */
2143 root 1.29 UUMessage (UUMSG_WARNING, uustring (S_MIME_MULTI_DEPTH));
2144 root 1.1 }
2145     else if (localenv.boundary == NULL) {
2146 root 1.29 UUMessage (UUMSG_WARNING, uustring (S_MIME_NO_BOUNDARY));
2147 root 1.1 }
2148     else {
2149     memcpy (&multistack[mssdepth], &sstate, sizeof (scanstate));
2150     memcpy (&sstate.envelope, &localenv, sizeof (headers));
2151     memset (&localenv, 0, sizeof (headers));
2152     sstate.mimestate = MS_PREAMBLE;
2153 root 1.23 if ((sstate.source = FP_strdup (sstate.source)) == NULL)
2154 root 1.1 *errcode = UURET_NOMEM;
2155    
2156     if (*errcode == UURET_OK)
2157     *errcode = UURET_CONT;
2158    
2159     mssdepth++;
2160     /* need a restart */
2161 root 1.23 FP_free (result);
2162 root 1.1 return NULL;
2163     }
2164     }
2165 root 1.4
2166 root 1.1 /*
2167     * So this subpart is either plain text or something else. Check
2168     * the Content-Type and Content-Transfer-Encoding. If the latter
2169     * is a defined value, we know what to do and just copy everything
2170     * up to the boundary.
2171     * If Content-Transfer-Encoding is unknown or missing, look at the
2172     * Content-Type. If it's "text/plain" or undefined, we subject the
2173     * message to our encoding detection. Otherwise, treat as plain
2174     * text.
2175     * This is done because users might `attach' a uuencoded file, which
2176     * would then be correctly typed as `text/plain'.
2177     */
2178 root 1.4
2179 root 1.23 if (FP_stristr (localenv.ctenc, "base64") != NULL)
2180 root 1.1 result->uudet = B64ENCODED;
2181 root 1.23 else if (FP_stristr (localenv.ctenc, "x-uue") != NULL) {
2182 root 1.2 result->uudet = UU_ENCODED;
2183 root 1.4 result->begin = result->end = 1;
2184     }
2185 root 1.23 else if (FP_stristr (localenv.ctenc, "x-yenc") != NULL) {
2186 root 1.4 result->uudet = YENC_ENCODED;
2187     result->begin = result->end = 1;
2188     }
2189 root 1.23 else if (FP_stristr (localenv.ctenc, "quoted-printable") != NULL)
2190 root 1.1 result->uudet = QP_ENCODED;
2191 root 1.23 else if (FP_stristr (localenv.ctenc, "7bit") != NULL ||
2192     FP_stristr (localenv.ctenc, "8bit") != NULL)
2193 root 1.1 result->uudet = PT_ENCODED;
2194 root 1.23 else if (FP_stristr (localenv.ctype, "multipart") != NULL ||
2195     FP_stristr (localenv.ctype, "message") != NULL)
2196 root 1.2 result->uudet = PT_ENCODED;
2197    
2198     /*
2199     * If we're switched to MIME-only mode, handle as text
2200     */
2201    
2202     if (uu_more_mime >= 2 && !result->uudet) {
2203 root 1.1 result->uudet = PT_ENCODED;
2204 root 1.2 }
2205 root 1.1
2206     if (result->uudet) {
2207     /*
2208     * Oh-kay, go ahead. Just read and wait for the boundary
2209     */
2210     result->startpos = ftell (datei);
2211     prevpos = ftell (datei);
2212     blen = strlen (sstate.envelope.boundary);
2213     lcount = 0;
2214 root 1.22
2215 root 1.23 while (!FP_feof (datei)) {
2216     if (FP_fgets (line, 1024, datei) == NULL)
2217 root 1.1 break;
2218     if (UUBUSYPOLL(ftell(datei),progress.fsize)) SPCANCEL();
2219     line[255] = '\0';
2220     if (line[0] == '-' && line[1] == '-' &&
2221     strncmp (line+2, sstate.envelope.boundary, blen) == 0)
2222     break;
2223     /*
2224     * I've had a report of someone who tried to decode a huge file
2225     * that had an early truncated multipart message and later another
2226     * multipart message with the *same* boundary. Consequently, all
2227     * some hundred messages inbetween were ignored ...
2228     * This check here doesn't cover folded header lines, but we don't
2229     * want to slow down scanning too much. We just check for
2230     * Content-Type: multipart/... boundary="same-boundary"
2231     */
2232     if (line[0] == 'C' && line[1] == 'o' &&
2233 root 1.24 FP_strnicmp_fast (line, "Content-Type:", 13) == 0) {
2234 root 1.1 ptr1 = ScanHeaderLine (datei, line);
2235 root 1.23 ptr2 = (ptr1)?FP_stristr(ptr1,"boundary"):NULL;
2236 root 1.1 ptr1 = (ptr2)?ParseValue(ptr2):NULL;
2237     if (ptr1 && strcmp (ptr1, sstate.envelope.boundary) == 0)
2238     break;
2239     for (res=0; ptr1 && res<mssdepth; res++)
2240     if (strcmp (ptr1, multistack[res].envelope.boundary) == 0)
2241     break;
2242     if (res<mssdepth)
2243     break;
2244     }
2245     if (!IsLineEmpty (line))
2246     lcount++;
2247     prevpos = ftell (datei);
2248     }
2249     if (line[0] == '-' && line[1] == '-' &&
2250     strncmp (line+2, sstate.envelope.boundary, blen) == 0) {
2251     ptr1 = line + 2 + blen;
2252     if (*ptr1 == '-' && *(ptr1+1) == '-')
2253     sstate.mimestate = MS_EPILOGUE;
2254     else
2255     sstate.mimestate = MS_SUBPART;
2256     }
2257     else {
2258 root 1.29 UUMessage (UUMSG_WARNING, uustring (S_MIME_B_NOT_FOUND));
2259 root 1.1
2260     while (mssdepth) {
2261     mssdepth--;
2262     UUkillheaders (&(multistack[mssdepth].envelope));
2263 root 1.23 FP_free (multistack[mssdepth].source);
2264 root 1.1 }
2265     /*
2266     * Don't retry if uu_fast_scanning
2267     */
2268    
2269     if (uu_fast_scanning) {
2270     UUkillheaders (&localenv);
2271     sstate.isfolder = 0;
2272     sstate.ismime = 0;
2273     sstate.mimestate = MS_BODY;
2274 root 1.23 FP_free (result);
2275 root 1.1 return NULL;
2276     }
2277    
2278     /*
2279     * Retry, but listening to headers this time
2280     */
2281     fseek (datei, result->startpos, SEEK_SET);
2282    
2283     UUkillfread (result);
2284     if ((result = (fileread *) malloc (sizeof (fileread))) == NULL) {
2285     *errcode = UURET_NOMEM;
2286     sstate.isfolder = 0;
2287     sstate.ismime = 0;
2288     UUkillheaders (&localenv);
2289     return NULL;
2290     }
2291     memset (result, 0, sizeof (fileread));
2292    
2293     if ((res = ScanData (datei, fname, errcode, NULL, 1, 1, result))==-1) {
2294     /* oops, something went wrong */
2295     sstate.isfolder = 0;
2296     sstate.ismime = 0;
2297     UUkillfread (result);
2298     UUkillheaders (&localenv);
2299     return NULL;
2300     }
2301     if (res == 1) {
2302     /*
2303     * new headers found
2304     */
2305     sstate.isfolder = 1;
2306     sstate.ismime = 0;
2307     sstate.mimestate = MS_HEADERS;
2308     }
2309     else {
2310     sstate.isfolder = 0;
2311     sstate.ismime = 0;
2312     }
2313     }
2314     /* produce result if uu_handletext is set */
2315 root 1.2 /* or if the file is explicitely named */
2316     if (result->uudet == B64ENCODED || lcount) {
2317 root 1.1 if (localenv.fname) {
2318 root 1.23 FP_free (result->filename);
2319     if ((result->filename = FP_strdup (localenv.fname)) == NULL)
2320 root 1.1 *errcode = UURET_NOMEM;
2321     }
2322     else if ((result->uudet==QP_ENCODED||result->uudet==PT_ENCODED) &&
2323 root 1.2 result->filename == NULL && uu_handletext) {
2324 root 1.1 sprintf (line, "%04d.txt", ++mimseqno);
2325 root 1.23 if ((result->filename = FP_strdup (line)) == NULL)
2326 root 1.1 *errcode = UURET_NOMEM;
2327     }
2328 root 1.23 result->subject = FP_strdup (localenv.subject);
2329     result->origin = FP_strdup (localenv.from);
2330     result->mimeid = FP_strdup (localenv.mimeid);
2331     result->mimetype = FP_strdup (localenv.ctype);
2332 root 1.1 result->mode = 0644;
2333 root 1.23 result->sfname = FP_strdup (fname);
2334 root 1.1 result->flags = FL_SINGLE | FL_PROPER;
2335     result->partno = 1;
2336     /* result->uudet determined above */
2337     /* result->startpos set from above */
2338     result->length = prevpos - result->startpos;
2339    
2340     if ((localenv.subject != NULL && result->subject == NULL) ||
2341     result->filename == NULL || result->sfname == NULL) {
2342     *errcode = UURET_NOMEM;
2343     }
2344     }
2345     else {
2346     /* don't produce a result */
2347 root 1.23 FP_free (result);
2348 root 1.1 result = NULL;
2349     }
2350     if (*errcode == UURET_OK)
2351     *errcode = UURET_CONT;
2352     /*
2353     * destroy local envelope
2354     */
2355     UUkillheaders (&localenv);
2356     return result;
2357     }
2358 root 1.2
2359 root 1.1 /*
2360     * we're in a subpart, but the local headers don't give us any
2361     * clue about what's to find here. So look for encoded data by
2362     * ourselves.
2363     */
2364 root 1.2
2365 root 1.1 if ((res = ScanData (datei, fname, errcode,
2366 root 1.2 sstate.envelope.boundary,
2367     1, 0, result)) == -1) {
2368 root 1.1 /* oops, something went wrong */
2369     sstate.isfolder = 0;
2370     sstate.ismime = 0;
2371     UUkillfread (result);
2372     UUkillheaders (&localenv);
2373     return NULL;
2374     }
2375     /*
2376     * we should really be at a boundary here, but check again
2377     */
2378     blen = strlen (sstate.envelope.boundary);
2379     prevpos = ftell (datei);
2380    
2381 root 1.23 while (!FP_feof (datei)) {
2382     if (FP_fgets (line, 1024, datei) == NULL)
2383 root 1.1 break;
2384     if (UUBUSYPOLL(ftell(datei),progress.fsize)) SPCANCEL();
2385     if (line[0] == '-' && line[1] == '-' &&
2386     strncmp (line+2, sstate.envelope.boundary, blen) == 0)
2387     break;
2388     if (line[0] == 'C' && line[1] == 'o' &&
2389 root 1.24 FP_strnicmp_fast (line, "Content-Type:", 13) == 0) {
2390 root 1.1 ptr1 = ScanHeaderLine (datei, line);
2391 root 1.23 ptr2 = (ptr1)?FP_stristr(ptr1,"boundary"):NULL;
2392 root 1.1 ptr1 = (ptr2)?ParseValue(ptr2):NULL;
2393     if (ptr1 && strcmp (ptr1, sstate.envelope.boundary) == 0)
2394     break;
2395     }
2396     prevpos = ftell (datei);
2397     }
2398     /*
2399     * check if this was the last subpart
2400     */
2401     if (line[0] == '-' && line[1] == '-' &&
2402     strncmp (line+2, sstate.envelope.boundary, blen) == 0) {
2403     ptr1 = line + 2 + blen;
2404     if (*ptr1 == '-' && *(ptr1+1) == '-')
2405     sstate.mimestate = MS_EPILOGUE;
2406     else
2407     sstate.mimestate = MS_SUBPART;
2408     }
2409     else {
2410 root 1.29 UUMessage (UUMSG_WARNING, uustring (S_MIME_B_NOT_FOUND));
2411 root 1.22
2412 root 1.1 while (mssdepth) {
2413     mssdepth--;
2414     UUkillheaders (&(multistack[mssdepth].envelope));
2415 root 1.23 FP_free (multistack[mssdepth].source);
2416 root 1.1 }
2417    
2418     if (uu_fast_scanning) {
2419     UUkillheaders (&localenv);
2420     sstate.isfolder = 0;
2421     sstate.ismime = 0;
2422     sstate.mimestate = MS_BODY;
2423 root 1.23 FP_free (result);
2424 root 1.1 return NULL;
2425     }
2426    
2427     /*
2428     * Retry, listening to headers this time
2429     */
2430     fseek (datei, result->startpos, SEEK_SET);
2431 root 1.22
2432 root 1.1 UUkillfread (result);
2433     if ((result = (fileread *) malloc (sizeof (fileread))) == NULL) {
2434     *errcode = UURET_NOMEM;
2435     sstate.isfolder = 0;
2436     sstate.ismime = 0;
2437     UUkillheaders (&localenv);
2438     return NULL;
2439     }
2440     memset (result, 0, sizeof (fileread));
2441    
2442     if ((res = ScanData (datei, fname, errcode, NULL, 1, 1, result))==-1) {
2443     /* oops, something went wrong */
2444     sstate.isfolder = 0;
2445     sstate.ismime = 0;
2446     UUkillfread (result);
2447     UUkillheaders (&localenv);
2448     return NULL;
2449     }
2450     if (res == 1) {
2451     /*
2452     * new headers found
2453     */
2454     sstate.isfolder = 1;
2455     sstate.ismime = 0;
2456     sstate.mimestate = MS_HEADERS;
2457     }
2458     else {
2459     sstate.isfolder = 0;
2460     sstate.ismime = 0;
2461     }
2462     }
2463 root 1.2
2464     /*
2465     * If this file has been nicely MIME so far, then be very suspicious
2466     * if ScanData reports anything else. So do a double check, and if
2467     * it doesn't hold up, handle as plain text instead.
2468     */
2469    
2470 root 1.3 if (sstate.ismime && sstate.mimestate == MS_SUBPART &&
2471     strcmp (localenv.mimevers, "1.0") == 0 &&
2472 root 1.23 FP_stristr (localenv.ctype, "text") != NULL &&
2473 root 1.2 !uu_desperate) {
2474     if (result->uudet == UU_ENCODED && !(result->begin || result->end)) {
2475     result->uudet = 0;
2476     }
2477     }
2478    
2479 root 1.1 /*
2480     * produce result
2481     */
2482 root 1.2
2483     if (result->uudet == 0) {
2484 root 1.1 result->uudet = PT_ENCODED; /* plain text */
2485     }
2486    
2487     if (localenv.fname) {
2488 root 1.23 FP_free (result->filename);
2489     if ((result->filename = FP_strdup (localenv.fname)) == NULL)
2490 root 1.1 *errcode = UURET_NOMEM;
2491     }
2492     else if ((result->uudet==QP_ENCODED || result->uudet==PT_ENCODED) &&
2493 root 1.2 result->filename==NULL && uu_handletext) {
2494 root 1.1 sprintf (line, "%04d.txt", ++mimseqno);
2495 root 1.23 if ((result->filename = FP_strdup (line)) == NULL)
2496 root 1.1 *errcode = UURET_NOMEM;
2497     }
2498     else {
2499     /* assign a filename lateron */
2500     }
2501 root 1.23 if (result->mimetype) FP_free (result->mimetype);
2502 root 1.1 if (result->uudet) {
2503 root 1.23 if (FP_stristr (localenv.ctype, "text") != NULL &&
2504 root 1.1 result->uudet != QP_ENCODED && result->uudet != PT_ENCODED)
2505     result->mimetype = NULL; /* better don't set it */
2506     else
2507 root 1.23 result->mimetype = FP_strdup (localenv.ctype);
2508 root 1.1 }
2509 root 1.23 if (result->origin) FP_free (result->origin);
2510     result->origin = FP_strdup (localenv.from);
2511 root 1.1
2512 root 1.23 if (result->subject) FP_free (result->subject);
2513     result->subject = FP_strdup (localenv.subject);
2514 root 1.1
2515     if (result->sfname == NULL)
2516 root 1.23 if ((result->sfname = FP_strdup (fname)) == NULL)
2517 root 1.1 *errcode = UURET_NOMEM;
2518    
2519     result->length = prevpos - result->startpos;
2520     result->flags = FL_SINGLE | FL_PROPER;
2521     result->partno = 1;
2522    
2523     if (result->mode == 0)
2524     result->mode = 0644;
2525    
2526     /*
2527     * the other fields should already be set appropriately
2528     */
2529    
2530     if (*errcode == UURET_OK)
2531     *errcode = UURET_CONT;
2532    
2533     /*
2534     * kill local envelope
2535     */
2536     UUkillheaders (&localenv);
2537 root 1.22
2538 root 1.1 return result;
2539     }
2540    
2541     /*
2542     * All right, so we're not in a Multipart message. Phew, took quite
2543     * long to figure this out. But this might still be a MIME message
2544     * body. And if it's a message/partial, we need more special handling
2545     */
2546    
2547     if (sstate.isfolder && sstate.ismime && sstate.mimestate == MS_BODY &&
2548 root 1.23 FP_stristr (sstate.envelope.ctype, "message") != NULL &&
2549     FP_stristr (sstate.envelope.ctype, "partial") != NULL) {
2550 root 1.1
2551     result->startpos = ftell (datei);
2552    
2553     if (sstate.envelope.partno == 1) {
2554     /* read local envelope */
2555     UUkillheaders (&localenv);
2556     memset (&localenv, 0, sizeof (headers));
2557    
2558     /* skip over blank lines first */
2559     prevpos = ftell (datei);
2560 root 1.23 while (!FP_feof (datei)) {
2561     if (FP_fgets (line, 1024, datei) == NULL)
2562 root 1.1 break;
2563     if (UUBUSYPOLL(ftell(datei),progress.fsize)) SPCANCEL();
2564     if (!IsLineEmpty (line))
2565     break;
2566     prevpos = ftell (datei);
2567     }
2568     /* Next, read header. But what if there is no subheader? */
2569     hcount = 0;
2570     lcount = 0;
2571     preheaders = prevpos;
2572    
2573 root 1.23 while (!FP_feof (datei) && !IsLineEmpty (line)) {
2574 root 1.1 if (IsKnownHeader (line))
2575     hcount++;
2576     if (UUBUSYPOLL(ftell(datei),progress.fsize)) SPCANCEL();
2577     if (lcount > WAITHEADER && hcount == 0) {
2578     fseek (datei, preheaders, SEEK_SET);
2579     break;
2580     }
2581     ptr1 = ScanHeaderLine (datei, line);
2582     if (ParseHeader (&localenv, ptr1) == NULL)
2583     *errcode = UURET_NOMEM;
2584    
2585 root 1.23 if (FP_fgets (line, 1024, datei) == NULL)
2586 root 1.1 break;
2587     lcount++;
2588     }
2589     prevpos = ftell (datei);
2590     /*
2591     * Examine local header. We're mostly interested in the Content-Type
2592     * and the Content-Transfer-Encoding.
2593     */
2594 root 1.23 if (FP_stristr (localenv.ctype, "multipart") != NULL) {
2595 root 1.29 UUMessage (UUMSG_WARNING, uustring (S_MIME_PART_MULTI));
2596 root 1.1 }
2597     if (localenv.subject)
2598 root 1.23 result->subject = FP_strdup (localenv.subject);
2599 root 1.1 else
2600 root 1.23 result->subject = FP_strdup (sstate.envelope.subject);
2601 root 1.1
2602     if (localenv.from)
2603 root 1.23 result->origin = FP_strdup (localenv.from);
2604 root 1.1 else
2605 root 1.23 result->origin = FP_strdup (sstate.envelope.from);
2606 root 1.1
2607     if (localenv.ctype)
2608 root 1.23 result->mimetype = FP_strdup (localenv.ctype);
2609 root 1.1 else
2610 root 1.23 result->mimetype = FP_strdup ("text/plain");
2611 root 1.1
2612 root 1.23 if (FP_stristr (localenv.ctenc, "quoted-printable") != NULL)
2613 root 1.1 result->uudet = QP_ENCODED;
2614 root 1.23 else if (FP_stristr (localenv.ctenc, "base64") != NULL)
2615 root 1.1 result->uudet = B64ENCODED;
2616 root 1.23 else if (FP_stristr (localenv.ctenc, "x-uue") != NULL) {
2617 root 1.2 result->uudet = UU_ENCODED;
2618 root 1.4 result->begin = result->end = 1;
2619     }
2620 root 1.23 else if (FP_stristr (localenv.ctenc, "x-yenc") != NULL) {
2621 root 1.4 result->uudet = YENC_ENCODED;
2622     result->begin = result->end = 1;
2623     }
2624 root 1.23 else if (FP_stristr (localenv.ctenc, "7bit") != NULL ||
2625     FP_stristr (localenv.ctenc, "8bit") != NULL)
2626 root 1.2 result->uudet = PT_ENCODED;
2627 root 1.23 else if (FP_stristr (localenv.ctype, "multipart") != NULL ||
2628     FP_stristr (localenv.ctype, "message") != NULL)
2629 root 1.1 result->uudet = PT_ENCODED;
2630 root 1.2
2631     /*
2632     * If we're switched to MIME-only mode, handle as text
2633     */
2634    
2635     if (uu_more_mime >= 2 && !result->uudet) {
2636     result->uudet = PT_ENCODED;
2637     }
2638 root 1.1 }
2639     else {
2640     memset (&localenv, 0, sizeof (headers));
2641     }
2642    
2643     /*
2644     * If this is Quoted-Printable or Plain Text, just try looking
2645     * for the next message header. If uu_fast_scanning, and the
2646     * encoding is known, there's no need to look below. Otherwise,
2647     * we check the type of encoding first.
2648     * The encoding type is determined on the first part; in all
2649     * others, we also don't read on.
2650     * If we have a partial multipart message, scan for headers, but
2651     * do not react on standard MIME headers, as they are probably
2652     * from the subparts. However, we're stuck if there's an embedded
2653     * message/rfc822 :-(
2654     * If it is a "trivial" (non-embedded) message/rfc822, skip over
2655     * the message header and then start looking for the next header.
2656     */
2657     if (uu_fast_scanning && (result->uudet!=0||sstate.envelope.partno!=1)) {
2658     /* do nothing */
2659     res = 0;
2660     }
2661     else if (result->uudet != 0) {
2662     hcount = lcount = 0;
2663     prevpos = ftell (datei);
2664    
2665 root 1.23 if (FP_stristr (localenv.ctype, "message") != NULL &&
2666     FP_stristr (localenv.ctype, "rfc822") != NULL) {
2667 root 1.1 /*
2668     * skip over empty lines and local header
2669     */
2670     preheaders = ftell (datei);
2671 root 1.23 while (!FP_feof (datei)) {
2672     if (FP_fgets (line, 1024, datei) == NULL)
2673 root 1.1 break;
2674     if (!IsLineEmpty (line)) {
2675     break;
2676     }
2677     }
2678    
2679 root 1.23 while (!FP_feof (datei) && !IsLineEmpty (line)) {
2680 root 1.1 if (IsKnownHeader (line))
2681     hcount++;
2682     lcount++;
2683     if (lcount > WAITHEADER && hcount < hlcount.afternl)
2684     break;
2685    
2686 root 1.23 if (FP_fgets (line, 1024, datei) == NULL)
2687 root 1.1 break;
2688     }
2689     if (hcount < hlcount.afternl)
2690     fseek (datei, preheaders, SEEK_SET);
2691     hcount = lcount = 0;
2692     }
2693    
2694     /*
2695     * look for next header
2696     */
2697    
2698 root 1.23 while (!FP_feof (datei)) {
2699     if (FP_fgets (line, 1024, datei) == NULL)
2700 root 1.1 break;
2701     if (UUBUSYPOLL(ftell(datei),progress.fsize)) SPCANCEL();
2702     if (ferror (datei))
2703     break;
2704    
2705     if ((vflag = IsKnownHeader (line))) {
2706     (void) ScanHeaderLine (datei, line);
2707    
2708     if (result->uudet != PT_ENCODED || vflag == 1) {
2709     if (hcount == 0)
2710     preheaders = prevpos;
2711     hcount++;
2712     lcount++;
2713     if (hcount >= hlcount.restart) {
2714     /*
2715     * Hey, a new header starts here
2716     */
2717     fseek (datei, preheaders, SEEK_SET);
2718     prevpos = preheaders;
2719     break;
2720     }
2721     }
2722     }
2723     else if (lcount > WAITHEADER) {
2724     hcount = 0;
2725     lcount = 0;
2726     }
2727     else if (hcount) {
2728     lcount++;
2729     }
2730     prevpos = ftell (datei);
2731     }
2732     res = 1;
2733     }
2734     else {
2735     /*
2736     * Otherwise, let's see what we can find ourself. No
2737     * boundary (NULL) but MIME, and respect new headers.
2738     */
2739     if ((res = ScanData (datei, fname, errcode, NULL, 1, 1, result)) == -1) {
2740     /* oops, something went wrong */
2741     sstate.isfolder = 0;
2742     sstate.ismime = 0;
2743     UUkillfread (result);
2744     UUkillheaders (&localenv);
2745     return NULL;
2746     }
2747     if (result->uudet == 0 && uu_handletext)
2748     result->uudet = PT_ENCODED;
2749    
2750     prevpos = ftell (datei);
2751     }
2752     /*
2753     * produce result
2754     */
2755     if (localenv.fname) {
2756 root 1.23 FP_free (result->filename);
2757     if ((result->filename = FP_strdup (localenv.fname)) == NULL)
2758 root 1.1 *errcode = UURET_NOMEM;
2759     }
2760     else if (sstate.envelope.fname) {
2761 root 1.23 FP_free (result->filename);
2762     if ((result->filename = FP_strdup (sstate.envelope.fname)) == NULL)
2763 root 1.1 *errcode = UURET_NOMEM;
2764     }
2765     else if ((result->uudet==QP_ENCODED || result->uudet==PT_ENCODED) &&
2766     result->filename == NULL) {
2767     sprintf (line, "%04d.txt", ++mimseqno);
2768 root 1.23 if ((result->filename = FP_strdup (line)) == NULL)
2769 root 1.1 *errcode = UURET_NOMEM;
2770     }
2771     else {
2772     /* assign a filename lateron */
2773     }
2774     if (result->subject == NULL) {
2775     if (sstate.envelope.subject)
2776 root 1.23 result->subject = FP_strdup (sstate.envelope.subject);
2777 root 1.1 }
2778     result->partno = sstate.envelope.partno;
2779     result->maxpno = sstate.envelope.numparts;
2780 root 1.22 result->flags = FL_PARTIAL |
2781 root 1.1 ((res==1 || uu_fast_scanning) ? FL_PROPER : 0) |
2782     ((uu_fast_scanning) ? FL_TOEND : 0);
2783 root 1.23 result->mimeid = FP_strdup (sstate.envelope.mimeid);
2784 root 1.4 if (result->partno == 1)
2785     result->begin = 1;
2786 root 1.1
2787     if (uu_fast_scanning)
2788     result->length = progress.fsize - result->startpos;
2789     else
2790     result->length = prevpos - result->startpos;
2791    
2792     if (result->sfname == NULL)
2793 root 1.23 result->sfname = FP_strdup (fname);
2794 root 1.1
2795     if (result->mode == 0)
2796     result->mode = 0644;
2797    
2798     /*
2799     * the other fields should already be set appropriately
2800     */
2801    
2802     if (res == 1) {
2803     /*
2804     * new headers found
2805     */
2806     sstate.isfolder = 1;
2807     sstate.ismime = 0;
2808     sstate.mimestate = MS_HEADERS;
2809 root 1.22
2810 root 1.1 UUkillheaders (&sstate.envelope);
2811     memset (&sstate.envelope, 0, sizeof (headers));
2812     }
2813     else {
2814     /*
2815     * otherwise, this can't be a mail folder
2816     */
2817     sstate.isfolder = 0;
2818     sstate.ismime = 0;
2819     }
2820     /*
2821     * kill local envelope
2822     */
2823     UUkillheaders (&localenv);
2824     return result;
2825     }
2826    
2827     /*
2828 root 1.2 * If this is a MIME body, honor a Content-Type different than
2829 root 1.1 * text/plain or a proper Content-Transfer-Encoding.
2830 root 1.2 * We also go in here if we have an assigned filename - this means
2831     * that we've had a Content-Disposition field, and we should probably
2832     * decode a plain-text segment with a filename.
2833 root 1.1 */
2834 root 1.4
2835 root 1.1 if (sstate.isfolder && sstate.ismime &&
2836     sstate.mimestate == MS_BODY &&
2837 root 1.23 (FP_stristr (sstate.envelope.ctenc, "quoted-printable") != NULL ||
2838     FP_stristr (sstate.envelope.ctenc, "base64") != NULL ||
2839     FP_stristr (sstate.envelope.ctenc, "x-uue") != NULL ||
2840     FP_stristr (sstate.envelope.ctenc, "x-yenc") != NULL ||
2841     FP_stristr (sstate.envelope.ctype, "message") != NULL ||
2842 root 1.2 sstate.envelope.fname != NULL)) {
2843 root 1.1
2844     if (sstate.envelope.subject)
2845 root 1.23 result->subject = FP_strdup (sstate.envelope.subject);
2846 root 1.1 if (sstate.envelope.from)
2847 root 1.23 result->origin = FP_strdup (sstate.envelope.from);
2848 root 1.1
2849     if (sstate.envelope.ctype)
2850 root 1.23 result->mimetype = FP_strdup (sstate.envelope.ctype);
2851 root 1.1 else
2852 root 1.23 result->mimetype = FP_strdup ("text/plain");
2853 root 1.1
2854 root 1.23 if (FP_stristr (sstate.envelope.ctenc, "quoted-printable") != NULL)
2855 root 1.1 result->uudet = QP_ENCODED;
2856 root 1.23 else if (FP_stristr (sstate.envelope.ctenc, "base64") != NULL)
2857 root 1.1 result->uudet = B64ENCODED;
2858 root 1.23 else if (FP_stristr (sstate.envelope.ctenc, "x-uue") != NULL) {
2859 root 1.2 result->uudet = UU_ENCODED;
2860 root 1.4 result->begin = result->end = 1;
2861     }
2862 root 1.23 else if (FP_stristr (sstate.envelope.ctenc, "x-yenc") != NULL) {
2863 root 1.4 result->uudet = YENC_ENCODED;
2864     }
2865 root 1.23 else if (FP_stristr (sstate.envelope.ctenc, "7bit") != NULL ||
2866     FP_stristr (sstate.envelope.ctenc, "8bit") != NULL)
2867 root 1.2 result->uudet = PT_ENCODED;
2868 root 1.23 else if (FP_stristr (sstate.envelope.ctype, "multipart") != NULL ||
2869     FP_stristr (sstate.envelope.ctype, "message") != NULL ||
2870 root 1.2 sstate.envelope.fname != NULL)
2871     result->uudet = PT_ENCODED;
2872    
2873     /*
2874     * If we're switched to MIME-only mode, handle as text
2875     */
2876    
2877     if (uu_more_mime >= 2 && !result->uudet) {
2878 root 1.1 result->uudet = PT_ENCODED;
2879 root 1.2 }
2880    
2881     result->startpos = prevpos = ftell (datei);
2882 root 1.1
2883     /*
2884     * If this is Quoted-Printable or Plain Text, just try looking
2885     * for the next message header. If uu_fast_scanning, we know
2886     * there won't be more headers.
2887 root 1.2 * If it is a "trivial" (non-embedded) message/rfc822, skip over
2888     * the message header and then start looking for the next header.
2889 root 1.1 */
2890     if (result->uudet != 0 && uu_fast_scanning) {
2891     /* do nothing */
2892     res = 0;
2893     }
2894     else if (result->uudet != 0) {
2895     hcount = lcount = 0;
2896 root 1.2 prevpos = ftell (datei);
2897    
2898 root 1.23 if (FP_stristr (sstate.envelope.ctype, "message") != NULL &&
2899     FP_stristr (sstate.envelope.ctype, "rfc822") != NULL) {
2900 root 1.2 /*
2901     * skip over empty lines and local header
2902     */
2903     preheaders = ftell (datei);
2904 root 1.23 while (!FP_feof (datei)) {
2905     if (FP_fgets (line, 1024, datei) == NULL)
2906 root 1.2 break;
2907     if (!IsLineEmpty (line)) {
2908     break;
2909     }
2910     }
2911    
2912 root 1.23 while (!FP_feof (datei) && !IsLineEmpty (line)) {
2913 root 1.2 if (IsKnownHeader (line))
2914     hcount++;
2915     lcount++;
2916     if (lcount > WAITHEADER && hcount < hlcount.afternl)
2917     break;
2918    
2919 root 1.23 if (FP_fgets (line, 1024, datei) == NULL)
2920 root 1.2 break;
2921     }
2922     if (hcount < hlcount.afternl)
2923     fseek (datei, preheaders, SEEK_SET);
2924     hcount = lcount = 0;
2925     }
2926    
2927     /*
2928     * look for next header
2929     */
2930 root 1.1
2931 root 1.23 while (!FP_feof (datei)) {
2932     if (FP_fgets (line, 1024, datei) == NULL)
2933 root 1.1 break;
2934     if (UUBUSYPOLL(ftell(datei),progress.fsize)) SPCANCEL();
2935     if (ferror (datei))
2936     break;
2937    
2938     if (IsKnownHeader (line)) {
2939     (void) ScanHeaderLine (datei, line);
2940     if (hcount == 0)
2941     preheaders = prevpos;
2942     hcount++;
2943     lcount++;
2944     if (hcount >= hlcount.restart) {
2945     /*
2946     * Hey, a new header starts here
2947     */
2948     fseek (datei, preheaders, SEEK_SET);
2949     prevpos = preheaders;
2950     break;
2951     }
2952     }
2953     else if (lcount > WAITHEADER) {
2954     hcount = 0;
2955     lcount = 0;
2956     }
2957     else if (hcount) {
2958     lcount++;
2959     }
2960     prevpos = ftell (datei);
2961     }
2962     res = 1;
2963     }
2964     else {
2965     /*
2966     * Otherwise, let's see what we can find ourself. No
2967     * boundary (NULL) but MIME, and respect new headers.
2968     */
2969     if ((res = ScanData (datei, fname, errcode, NULL, 1, 1, result)) == -1) {
2970     /* oops, something went wrong */
2971     sstate.isfolder = 0;
2972     sstate.ismime = 0;
2973     UUkillfread (result);
2974     return NULL;
2975     }
2976     if (result->uudet == 0 && uu_handletext) {
2977     result->startpos = before; /* display headers */
2978     result->uudet = PT_ENCODED;
2979     }
2980    
2981     prevpos = ftell (datei);
2982     }
2983     /*
2984     * produce result
2985     */
2986     if (sstate.envelope.fname) {
2987 root 1.23 FP_free (result->filename);
2988     if ((result->filename = FP_strdup (sstate.envelope.fname)) == NULL)
2989 root 1.1 *errcode = UURET_NOMEM;
2990     }
2991     else if ((result->uudet==QP_ENCODED||result->uudet==PT_ENCODED) &&
2992     result->filename == NULL) {
2993     sprintf (line, "%04d.txt", ++mimseqno);
2994 root 1.23 if ((result->filename = FP_strdup (line)) == NULL)
2995 root 1.1 *errcode = UURET_NOMEM;
2996     }
2997     else {
2998     /* assign a filename lateron */
2999     }
3000     if (result->subject == NULL) {
3001     if (sstate.envelope.subject)
3002 root 1.23 result->subject = FP_strdup (sstate.envelope.subject);
3003 root 1.1 }
3004     result->flags = ((res==1||uu_fast_scanning)?FL_PROPER:0) |
3005     ((uu_fast_scanning) ? FL_TOEND : 0);
3006 root 1.23 result->mimeid = FP_strdup (sstate.envelope.mimeid);
3007 root 1.1
3008     if (uu_fast_scanning)
3009     result->length = progress.fsize - result->startpos;
3010     else
3011     result->length = prevpos - result->startpos;
3012    
3013     if (result->sfname == NULL)
3014 root 1.23 result->sfname = FP_strdup (fname);
3015 root 1.1
3016     if (result->mode == 0)
3017     result->mode = 0644;
3018    
3019     /*
3020     * the other fields should already be set appropriately
3021     */
3022    
3023     if (res == 1) {
3024     /*
3025     * new headers found
3026     */
3027     sstate.isfolder = 1;
3028     sstate.ismime = 0;
3029     sstate.mimestate = MS_HEADERS;
3030    
3031     UUkillheaders (&sstate.envelope);
3032     memset (&sstate.envelope, 0, sizeof (headers));
3033     }
3034     else {
3035     /*
3036     * otherwise, this can't be a mail folder
3037     */
3038     sstate.isfolder = 0;
3039     sstate.ismime = 0;
3040     }
3041    
3042     return result;
3043     }
3044    
3045     /*
3046     * Some files have reduced headers, and what should be a multipart
3047     * message is missing the proper Content-Type. If the first thing
3048     * we find after a couple of empty lines is a boundary, try it!
3049     * But make sure that this is indeed intended as being a boundary.
3050     *
3051     * Only accept it if there was indeed no Content-Type header line
3052     * and if the following line is a proper Content-Type header. BTW,
3053     * we know that sstate.envelope.boundary is NULL, or we wouldn't
3054     * be here!
3055     */
3056 root 1.2
3057 root 1.23 if ((!sstate.envelope.ctype || FP_stristr (sstate.envelope.ctype, "multipart"))
3058 root 1.12 && !uu_more_mime) {
3059 root 1.1 prevpos = ftell (datei);
3060 root 1.23 while (!FP_feof (datei)) {
3061     if (FP_fgets (line, 1024, datei) == NULL)
3062 root 1.1 break;
3063     if (UUBUSYPOLL(ftell(datei),progress.fsize)) SPCANCEL();
3064     if (!IsLineEmpty (line))
3065     break;
3066     }
3067     if (line[0] == '-' && line[1] == '-' &&
3068 root 1.23 !IsLineEmpty (line+2) && !FP_feof (datei)) {
3069     ptr1 = FP_strrstr (line+2, "--");
3070 root 1.1 ptr2 = ScanHeaderLine (datei, NULL);
3071 root 1.16 if ((ptr1 == NULL || ptr1[2]) &&
3072 root 1.24 ptr2 && FP_strnicmp_fast (ptr2, "Content-", 8) == 0) {
3073 root 1.1 /*
3074     * hmm, okay, let's do it!
3075     */
3076     sstate.isfolder = 1;
3077     sstate.ismime = 1;
3078     sstate.mimestate = MS_PREAMBLE;
3079     /*
3080     * get boundary
3081     */
3082     ptr1 = line+2;
3083     while (*ptr1 && !isspace(*ptr1))
3084     ptr1++;
3085     *ptr1 = '\0';
3086 root 1.4
3087 root 1.23 sstate.envelope.mimevers = FP_strdup ("1.0");
3088     sstate.envelope.boundary = FP_strdup (line+2);
3089 root 1.22
3090 root 1.1 /*
3091     * need restart
3092     */
3093 root 1.22
3094 root 1.1 fseek (datei, prevpos, SEEK_SET);
3095 root 1.22
3096 root 1.23 FP_free (result);
3097 root 1.1 return NULL;
3098     }
3099     }
3100     fseek (datei, prevpos, SEEK_SET);
3101     }
3102    
3103     /*
3104     * Hmm, we're not in a ''special'' state, so it's more or less
3105     * Freestyle time. Anyway, if this seems to be a Mime message,
3106     * don't allow the minimal Base64 handling.
3107     */
3108    
3109     if (sstate.envelope.subject)
3110 root 1.23 result->subject = FP_strdup (sstate.envelope.subject);
3111 root 1.12
3112 root 1.1 if (sstate.envelope.from)
3113 root 1.23 result->origin = FP_strdup (sstate.envelope.from);
3114 root 1.1
3115     if (sstate.envelope.ctype)
3116 root 1.23 result->mimetype = FP_strdup (sstate.envelope.ctype);
3117 root 1.22
3118     if ((res=ScanData (datei, fname, errcode, NULL,
3119 root 1.1 sstate.ismime, 1, result))==-1) {
3120     /* oops, something went wrong */
3121     sstate.isfolder = 0;
3122     sstate.ismime = 0;
3123     UUkillfread (result);
3124     return NULL;
3125     }
3126 root 1.4
3127 root 1.1 /*
3128     * produce result
3129     */
3130 root 1.4
3131 root 1.1 if (result->uudet == 0 && uu_handletext) {
3132     result->startpos = before; /* display headers */
3133     result->uudet = PT_ENCODED;
3134     result->partno = 1;
3135     }
3136    
3137 root 1.4 if (result->uudet == YENC_ENCODED && result->filename != NULL) {
3138     /*
3139     * prevent replacing the filename found on the =ybegin line
3140     */
3141     }
3142     else if (sstate.envelope.fname) {
3143 root 1.23 FP_free (result->filename);
3144     if ((result->filename = FP_strdup (sstate.envelope.fname)) == NULL)
3145 root 1.1 *errcode = UURET_NOMEM;
3146     }
3147     else if ((result->uudet==QP_ENCODED||result->uudet==PT_ENCODED) &&
3148     result->filename == NULL) {
3149     sprintf (line, "%04d.txt", ++mimseqno);
3150 root 1.23 if ((result->filename = FP_strdup (line)) == NULL)
3151 root 1.1 *errcode = UURET_NOMEM;
3152     }
3153     else {
3154     /* assign a filename lateron */
3155     }
3156 root 1.4
3157 root 1.1 if (result->subject == NULL) {
3158     if (sstate.envelope.subject)
3159 root 1.23 result->subject = FP_strdup (sstate.envelope.subject);
3160 root 1.1 }
3161    
3162     result->flags = (result->uudet==PT_ENCODED)?FL_SINGLE:0;
3163 root 1.23 result->mimeid = FP_strdup (sstate.envelope.mimeid);
3164 root 1.1 result->length = ftell (datei) - result->startpos;
3165    
3166     if (result->mode == 0)
3167     result->mode = 0644;
3168    
3169     if (result->sfname == NULL)
3170 root 1.23 result->sfname = FP_strdup (fname);
3171 root 1.1
3172     if (res == 1) {
3173     /*
3174     * new headers found
3175     */
3176     sstate.isfolder = 1;
3177     sstate.ismime = 0;
3178     sstate.mimestate = MS_HEADERS;
3179    
3180     UUkillheaders (&sstate.envelope);
3181     memset (&sstate.envelope, 0, sizeof (headers));
3182     }
3183     else {
3184     /*
3185     * otherwise, this can't be a mail folder
3186     */
3187     sstate.isfolder = 0;
3188     sstate.ismime = 0;
3189     }
3190    
3191     return result;
3192    
3193     /*
3194     * Emergency handling. Set errcode before jumping here.
3195     */
3196     ScanPartEmergency:
3197     UUkillfread (result);
3198     UUkillheaders (&localenv);
3199    
3200     while (mssdepth) {
3201     mssdepth--;
3202     UUkillheaders (&(multistack[mssdepth].envelope));
3203 root 1.23 FP_free (multistack[mssdepth].source);
3204 root 1.1 }
3205    
3206     return NULL;
3207     }
3208