ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/Convert-UUlib/uulib/uuscan.c
Revision: 1.20
Committed: Thu Oct 24 15:18:26 2019 UTC (4 years, 7 months ago) by root
Content type: text/plain
Branch: MAIN
CVS Tags: rel-1_6
Changes since 1.19: +1 -1 lines
Log Message:
1.6

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