ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/Convert-UUlib/uulib/uuscan.c
Revision: 1.25
Committed: Sun Dec 13 02:55:12 2020 UTC (3 years, 5 months ago) by root
Content type: text/plain
Branch: MAIN
Changes since 1.24: +3 -3 lines
Log Message:
*** empty log message ***

File Contents

# User Rev Content
1 root 1.1 /*
2     * This file is part of uudeview, the simple and friendly multi-part multi-
3 root 1.2 * file uudecoder program (c) 1994-2001 by Frank Pilhofer. The author may
4     * be contacted at fp@fpx.de
5 root 1.1 *
6     * This program is free software; you can redistribute it and/or modify
7     * it under the terms of the GNU General Public License as published by
8     * the Free Software Foundation; either version 2 of the License, or
9     * (at your option) any later version.
10     *
11     * This program is distributed in the hope that it will be useful,
12     * but WITHOUT ANY WARRANTY; without even the implied warranty of
13     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14     * GNU General Public License for more details.
15     */
16    
17     /*
18     * These are very central functions of UUDeview. Here, we scan a file
19     * and decide whether it contains encoded data or not. ScanPart() must
20 root 1.23 * be called repeatedly on the same file until FP_feof(file). Each time,
21 root 1.1 * it returns information about the next part found within.
22     */
23    
24     #ifdef HAVE_CONFIG_H
25     #include "config.h"
26     #endif
27    
28     #ifdef SYSTEM_WINDLL
29     #include <windows.h>
30     #endif
31     #ifdef SYSTEM_OS2
32     #include <os2.h>
33     #endif
34    
35     #include <stdio.h>
36     #include <ctype.h>
37    
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.25 #define LSTR(s) { (s), sizeof (s) - 1 }
71 root 1.17
72     struct lstr {
73 root 1.25 const char *str;
74 root 1.17 int len;
75     };
76    
77     #define MAX_KNOWNHEADERLEN 28 /* max. length of a known header */
78    
79 root 1.25 static const struct lstr knownheaders[] = {
80 root 1.17 /* "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.22
90 root 1.17 LSTR ("Delivery-Date"), LSTR ("Posted-Date"), LSTR ("Received-Date"),
91 root 1.22 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 root 1.22 LSTR ("Content-Type"), LSTR ("Content-Disposition"),
99 root 1.17 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.21 char *ptr2, *p2, *p3;
186 root 1.1 int llength, c;
187     long curpos;
188    
189     if (initial) {
190 root 1.23 FP_strncpy (uuscan_shlline, initial, 1024);
191 root 1.15 } else {
192 root 1.1 /* read first line */
193 root 1.23 if (FP_feof (datei) || ferror (datei))
194 root 1.1 return NULL;
195 root 1.23 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 root 1.23 while (!FP_feof (datei)) {
210     c = FP_getc (datei);
211 root 1.16 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 root 1.23 while (!FP_feof (datei) && (c == ' ' || c == '\t'))
221     c = FP_getc (datei);
222 root 1.1
223 root 1.23 if (!FP_feof (datei))
224 root 1.1 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.23 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.23 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 root 1.21 * Let p2 point to the charset, look for next question mark
273 root 1.7 */
274    
275 root 1.21 p2 = ptr+2;
276 root 1.7
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.24 if (FP_strnicmp_fast (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.24 else if (FP_strnicmp_fast (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.24 else if (FP_strnicmp_fast (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.24 else if (FP_strnicmp_fast (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.24 else if (FP_strnicmp_fast (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.24 else if (FP_strnicmp_fast (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.23 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.23 theheaders->boundary = FP_strdup (thenew);
454 root 1.1 }
455     }
456 root 1.23 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.23 theheaders->fname = FP_strdup (thenew);
460 root 1.1 }
461     }
462 root 1.23 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.23 theheaders->mimeid = FP_strdup (thenew);
466 root 1.1 }
467     }
468 root 1.23 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.23 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.24 else if (FP_strnicmp_fast (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.24 else if (FP_strnicmp_fast (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.23 if ((ptr = FP_stristr (line, "name")) != NULL) {
493 root 1.1 if (theheaders->fname == NULL && (thenew=ParseValue(ptr)) != NULL) {
494 root 1.23 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.23 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 root 1.24 if (len == knownheaders [i].len && FP_strnicmp_fast (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 root 1.23 while (!FP_feof (datei)) {
573 root 1.1 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 root 1.23 if (datei == NULL || FP_feof (datei))
617 root 1.1 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 root 1.23 while (!FP_feof (datei)) {
633 root 1.1 oldposition = ftell (datei);
634 root 1.23 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.22 if (boundary != NULL &&
701 root 1.1 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.24 FP_strnicmp_fast (line, "Content-Type:", 13) == 0) {
708 root 1.1 ptr = ScanHeaderLine (datei, line);
709 root 1.23 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 root 1.24 if (strncmp (line, "begin ", 6) == 0 ||
722     FP_strnicmp_fast (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 root 1.22
730 root 1.1 if (*line == '<')
731     ptr = line + 10;
732     else
733     ptr = line + 5;
734    
735     while (*ptr == ' ') ptr++;
736 root 1.22 while (isdigit (*ptr))
737 root 1.1 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.23 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.24 if (FP_strnicmp_fast (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.23 if ((ptr = FP_stristr (line, "of file ")) != NULL) {
781 root 1.1 ptr += 8;
782     while (isspace (*ptr)) ptr++;
783     p2 = ptr;
784 root 1.22 while (isalnum(*p2) ||
785 root 1.1 *p2 == '.' || *p2=='_' || *p2 == '-' ||
786     *p2 == '!' || *p2=='@' || *p2 == '$')
787     p2++;
788     c = *p2; *p2 = '\0';
789     if (p2 != ptr && result->filename == NULL)
790 root 1.23 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.23 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.24 if (FP_strnicmp_fast (line, "Content-Type", 12) == 0 ||
809     FP_strnicmp_fast (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 root 1.21 while (isspace (*ptr)) ptr++;
821     p2 = ptr;
822 root 1.20 while (*p2 && !isspace (*p2) && *p2 != ';') p2++;
823 root 1.1 c = *p2; *p2 = '\0';
824     if (p2 != ptr) {
825 root 1.23 FP_free (result->mimetype);
826     result->mimetype = FP_strdup (ptr);
827 root 1.1 }
828     *p2 = c;
829     }
830     ctline=0;
831     hadct=1;
832     }
833 root 1.23 if ((ptr = FP_stristr (line, "number=")) && ctline<4) {
834 root 1.1 ptr += 7; if (*ptr == '"') ptr++;
835     result->partno = atoi (ptr);
836     }
837 root 1.23 if ((ptr = FP_stristr (line, "total=")) && ctline<4) {
838 root 1.1 ptr += 6; if (*ptr == '"') ptr++;
839     result->maxpno = atoi (ptr);
840     }
841 root 1.23 if ((ptr = FP_stristr (line, "name=")) && ctline<4) {
842 root 1.1 ptr += 5;
843     while (isspace (*ptr)) ptr++;
844     if (*ptr == '"' && *(ptr+1) && (p2 = strchr (ptr+2, '"')) != NULL) {
845     c = *p2; *p2 = '\0';
846 root 1.23 FP_free (result->filename);
847     result->filename = FP_strdup (ptr+1);
848 root 1.1 *p2 = c;
849     }
850     else if (*ptr=='\''&&*(ptr+1)&&(p2 = strchr(ptr+2, '\'')) != NULL) {
851     c = *p2; *p2 = '\0';
852 root 1.23 FP_free (result->filename);
853     result->filename = FP_strdup (ptr+1);
854 root 1.1 *p2 = c;
855     }
856     else {
857     p2 = ptr;
858 root 1.22 while (isalnum(*p2) ||
859 root 1.1 *p2 == '.' || *p2=='_' || *p2 == '-' ||
860     *p2 == '!' || *p2=='@' || *p2 == '$')
861     p2++;
862     c = *p2; *p2 = '\0';
863     if (p2 != ptr && result->filename == NULL)
864 root 1.23 result->filename = FP_strdup (ptr);
865 root 1.1 else if (p2 - ptr > 5 && strchr (ptr, '.') != NULL) {
866     /*
867     * This file name looks good, too. Let's use it
868     */
869 root 1.23 FP_free (result->filename);
870     result->filename = FP_strdup (ptr);
871 root 1.1 }
872     *p2 = c;
873     }
874     }
875 root 1.23 if ((ptr = FP_stristr (line, "id=")) && ctline<4) {
876 root 1.1 p2 = ptr += 3;
877     if (*p2 == '"') {
878     p2 = strchr (++ptr, '"');
879     }
880     else {
881     while (*p2 && isprint(*p2) && !isspace(*p2) && *p2 != ';')
882     p2++;
883     }
884     if (p2 && *p2 && p2!=ptr) {
885     c = *p2; *p2 = '\0';
886     if (result->mimeid)
887 root 1.23 FP_free (result->mimeid);
888     result->mimeid = FP_strdup (ptr);
889 root 1.1 *p2 = c;
890     }
891     }
892 root 1.22
893     /*
894 root 1.1 * Handling for very short Base64 files.
895     */
896 root 1.2 if (uu_tinyb64 && !ismime && !uu_more_mime) {
897 root 1.1 if (line[0] == '-' && line[1] == '-') {
898     if (dflag && (encoding==B64ENCODED || result->uudet==B64ENCODED)) {
899     if (encoding==B64ENCODED && result->uudet==0 && (haddh||hadct)) {
900     result->uudet = encoding;
901     encoding = dflag = 0;
902     }
903     haddh = 1;
904     continue;
905     }
906     hadct = 0;
907     }
908     }
909     } /* end of reduced MIME handling */
910    
911     /*
912 root 1.2 * If we're in "freestyle" mode, have not encountered anything
913     * interesting yet, and stumble upon something that looks like
914     * a boundary, followed by a Content-* line, try to use it.
915     */
916    
917     if (boundary == NULL && !ismime && !uu_more_mime && dflag <= 1 &&
918     line[0] == '-' && line[1] == '-' && strlen(line+2)>10 &&
919 root 1.23 (((ptr = FP_strrstr (line+2, "--")) == NULL) ||
920 root 1.16 ptr[2]) &&
921 root 1.23 FP_strstr (line+2, "_=_") != NULL) {
922 root 1.12
923     long oldposition = ftell (datei); /* refresh oldpositition so the comment below becomes true */
924 root 1.22
925 root 1.23 if (FP_fgets (line, 1024, datei) == NULL) {
926 root 1.2 break;
927     }
928 root 1.24 if (FP_strnicmp_fast (line, "Content-", 8) == 0) {
929 root 1.2 /*
930     * Okay, let's do it. This breaks out of ScanData. ScanPart will
931     * recognize the boundary on the next call and use it.
932     */
933     fseek (datei, oldposition, SEEK_SET);
934     break;
935     }
936     }
937    
938     /*
939 root 1.4 * Detection for yEnc encoding
940     */
941    
942     if (strncmp (line, "=ybegin ", 8) == 0 &&
943 root 1.23 FP_strstr (line, " name=") != NULL) {
944 root 1.7 if ((result->begin || result->end || result->uudet) && !uu_more_mime) {
945 root 1.4 fseek (datei, oldposition, SEEK_SET);
946     break;
947     }
948    
949     /*
950     * name continues to the end of the line
951     */
952 root 1.22
953 root 1.23 ptr = FP_strstr (line, " name=") + 6;
954 root 1.4
955 root 1.11 /* newsbin pro 5.0 (at least) is braindamaged enough to put (null) here */
956     /* create something sensible, trust a windows program to fuck it up */
957     if (strncmp (ptr, "(null)", 6))
958     {
959 root 1.23 FP_free (result->filename);
960     result->filename = FP_strdup (ptr);
961 root 1.11
962     while (isspace (result->filename[strlen(result->filename)-1]))
963     result->filename[strlen(result->filename)-1] = '\0';
964     }
965 root 1.4
966     /*
967     * Determine size
968     */
969    
970 root 1.23 if ((ptr = FP_strstr (line, " size=")) != NULL) {
971 root 1.6 ptr += 6;
972 root 1.14 result->yefilesize = atoi (ptr);
973 root 1.6 }
974     else {
975 root 1.14 result->yefilesize = -1;
976 root 1.6 }
977 root 1.4
978     /*
979     * check for multipart file and read =ypart line
980     */
981    
982 root 1.23 if ((ptr = FP_strstr (line, " part=")) != NULL) {
983 root 1.4 result->partno = atoi (ptr + 6);
984    
985     if (result->partno == 1) {
986     result->begin = 1;
987     }
988    
989 root 1.23 if ((ptr = FP_strstr (line, " total=")))
990 root 1.18 result->maxpno = atoi (ptr + 7);
991    
992 root 1.23 if (FP_fgets (line, 1024, datei) == NULL) {
993 root 1.4 break;
994     }
995    
996     if (strncmp (line, "=ypart ", 7) != 0) {
997     break;
998     }
999    
1000 root 1.23 if ((ptr = FP_strstr (line, " end=")) == NULL) {
1001 root 1.4 break;
1002     }
1003 root 1.22
1004 root 1.4 yepartends = atoi (ptr + 5);
1005     }
1006     else {
1007     result->partno = 1;
1008     result->begin = 1;
1009     }
1010    
1011     /*
1012     * Don't want auto-detection
1013     */
1014    
1015     result->uudet = YENC_ENCODED;
1016     continue;
1017     }
1018    
1019     if (strncmp (line, "=yend ", 6) == 0 &&
1020     result->uudet == YENC_ENCODED) {
1021 root 1.18 if (yepartends == 0) {
1022     if (!result->maxpno || result->maxpno == result->partno)
1023     result->end = 1;
1024     } else if (yepartends >= result->yefilesize) {
1025 root 1.4 result->end = 1;
1026     }
1027 root 1.7 #if 0
1028 root 1.4 if (!uu_more_mime)
1029     break;
1030 root 1.7 #endif
1031     continue;
1032 root 1.4 }
1033    
1034     /*
1035 root 1.1 * if we haven't yet found anything encoded, try to find something
1036     */
1037    
1038     if (!(result->uudet)) {
1039     /*
1040     * Netscape-Repair code is the same as in uunconc.c
1041     */
1042    
1043 root 1.2 if ((vflag = UUValidData (line, 0, &bhflag)) == 0 && !ismime)
1044 root 1.1 vflag = UURepairData (datei, line, 0, &bhflag);
1045    
1046     /*
1047 root 1.2 * Check data against all possible encodings
1048     */
1049    
1050 root 1.7 islen[iscnt%10] = strlen(line);
1051 root 1.2 isb64[iscnt%10] = (UUValidData (line, B64ENCODED, &bhflag)==B64ENCODED);
1052     isuue[iscnt%10] = (UUValidData (line, UU_ENCODED, &bhflag)==UU_ENCODED);
1053     isxxe[iscnt%10] = (UUValidData (line, XX_ENCODED, &bhflag)==XX_ENCODED);
1054     isbhx[iscnt%10] = (UUValidData (line, BH_ENCODED, &bhflag)==BH_ENCODED);
1055    
1056     /*
1057     * If we've got a first valid encoded line, we get suspicious if
1058     * it's shorter than, say, 40 characters.
1059     */
1060    
1061     if (vflag == B64ENCODED &&
1062     (dflag == 0 || encoding != B64ENCODED) &&
1063     strlen (line) < 40 && !result->begin && !uu_tinyb64) {
1064     isb64[iscnt%10] = 0;
1065     vflag = 0;
1066 root 1.1 }
1067    
1068 root 1.2 if ((vflag == UU_ENCODED || vflag == XX_ENCODED) &&
1069     (dflag == 0 || encoding != vflag) &&
1070     strlen (line) < 40 && !result->begin) {
1071     isuue[iscnt%10] = isxxe[iscnt%10] = 0;
1072     vflag = 0;
1073     }
1074    
1075     iscnt++;
1076    
1077     /*
1078     * Ah, so we got an encoded line? How interesting!
1079     */
1080    
1081 root 1.1 if (vflag) {
1082     /*
1083     * For BinHex data, we can use the initial colon ':' as begin
1084     * and the terminating colon as ':'.
1085     * If (vflag && !bhflag), this is the last line,
1086     */
1087     if (vflag == BH_ENCODED) {
1088 root 1.2 if (line[0] == ':' && result->end) {
1089     fseek (datei, oldposition, SEEK_SET);
1090     break;
1091     }
1092 root 1.1 if (line[0] == ':')
1093     result->begin = 1;
1094     if (bhflag == 0) {
1095     result->uudet = BH_ENCODED;
1096     result->end = 1;
1097     }
1098     }
1099     /*
1100     * For BinHex files, the file name is encoded in the first encoded
1101     * data bytes. We try to extract it here
1102     */
1103     if (vflag == BH_ENCODED && bhnf == 0 && result->filename == NULL) {
1104     if (bhdsp == bhds2 ||
1105     ((bhdsp-bhds2) <= (int) bhds2[0] &&
1106 root 1.19 (bhdsp-bhds2) < 256)) {
1107 root 1.1 dcc = UUDecodeLine (line, bhds1, BH_ENCODED);
1108     UUbhdecomp (bhds1, bhdsp, &bhl, &bhrpc,
1109     dcc, 256-(bhdsp-bhds2), &bhopc);
1110     bhdsp += bhopc;
1111     }
1112     if ((bhdsp-bhds2) > (int) bhds2[0] && bhds2[0]>0 &&
1113     result->filename==NULL) {
1114     memcpy (bhds1, bhds2+1, (int) bhds2[0]);
1115     bhds1[(int)bhds2[0]]='\0';
1116 root 1.23 result->filename = FP_strdup (bhds1);
1117 root 1.1 bhnf = 1;
1118     }
1119     else if (bhdsp-bhds2 >= 256 && bhds2[0]>0) {
1120     memcpy (bhds1, bhds2+1, 255);
1121     bhds1[255] = '\0';
1122 root 1.23 result->filename = FP_strdup (bhds1);
1123 root 1.1 bhnf = 1;
1124     }
1125     else if (bhds2[0] <= 0)
1126     bhnf = 1;
1127     }
1128 root 1.2
1129 root 1.1 /*
1130 root 1.2 * We accept an encoding if it has been true for four consecutive
1131     * lines. Check the is<enc> arrays to avoid mistaking one encoding
1132     * for the other. Uuencoded data is rather easily mistaken for
1133     * Base 64. If the data matches more than one encoding, we need to
1134     * scan further.
1135 root 1.7 *
1136     * Since text can also rather easily be mistaken for UUencoded
1137     * data if it just happens to have 4 lines in a row that have the
1138     * correct first character for the length of the line, we also add
1139     * a check that the first 3 lines must be the same length, and the
1140     * 4th line must be less than or equal to that length. (since
1141     * uuencoders use the same length for all lines except the last,
1142     * this shouldn't increase the minimum size of UUdata we can
1143     * detect, as it would if we tested all 4 lines for being the same
1144     * length.) - Matthew Mueller, 20030109
1145 root 1.1 */
1146 root 1.2
1147     if (iscnt > 3) {
1148     cbb64 = (isb64[(iscnt-1)%10] && isb64[(iscnt-2)%10] &&
1149     isb64[(iscnt-3)%10] && isb64[(iscnt-4)%10]);
1150     cbuue = (isuue[(iscnt-1)%10] && isuue[(iscnt-2)%10] &&
1151 root 1.7 isuue[(iscnt-3)%10] && isuue[(iscnt-4)%10] &&
1152     islen[(iscnt-1)%10] <= islen[(iscnt-2)%10] &&
1153     islen[(iscnt-2)%10] == islen[(iscnt-3)%10] &&
1154     islen[(iscnt-3)%10] == islen[(iscnt-4)%10]);
1155 root 1.2 cbxxe = (isxxe[(iscnt-1)%10] && isxxe[(iscnt-2)%10] &&
1156 root 1.7 isxxe[(iscnt-3)%10] && isxxe[(iscnt-4)%10] &&
1157     islen[(iscnt-1)%10] <= islen[(iscnt-2)%10] &&
1158     islen[(iscnt-2)%10] == islen[(iscnt-3)%10] &&
1159     islen[(iscnt-3)%10] == islen[(iscnt-4)%10]);
1160 root 1.2 cbbhx = (isbhx[(iscnt-1)%10] && isbhx[(iscnt-2)%10] &&
1161     isbhx[(iscnt-3)%10] && isbhx[(iscnt-4)%10]);
1162     }
1163     else {
1164     cbb64 = cbuue = cbxxe = cbbhx = 0;
1165     }
1166    
1167     if (cbb64 && !cbuue && !cbxxe && !cbbhx) {
1168     result->uudet = B64ENCODED;
1169     }
1170     else if (!cbb64 && cbuue && !cbxxe && !cbbhx) {
1171     result->uudet = UU_ENCODED;
1172     }
1173     else if (!cbb64 && !cbuue && cbxxe && !cbbhx) {
1174     result->uudet = XX_ENCODED;
1175     }
1176     else if (!cbb64 && !cbuue && !cbxxe && cbbhx) {
1177     result->uudet = BH_ENCODED;
1178     }
1179    
1180     if (result->uudet) {
1181 root 1.1 encoding = dflag = 0;
1182    
1183     /*
1184     * If we're in fast mode, we're told we don't have to look
1185     * for anything below, so we can as well break out of every-
1186     * thing
1187     * We cannot fast-scan if we have a boundary to look after.
1188     */
1189    
1190     if (uu_fast_scanning && boundary == NULL)
1191     break;
1192    
1193     /*
1194     * Skip the encoded data. We simply wait for a boundary, for
1195     * a header or for an empty line. But we also try to pick up
1196     * an "end"
1197     */
1198    
1199     hcount = lcount = 0;
1200    
1201 root 1.23 while (!FP_feof (datei)) {
1202 root 1.1 /*
1203     * Make Busy Polls
1204     */
1205     if (UUBUSYPOLL(ftell(datei),progress.fsize)) {
1206     UUMessage (uuscan_id, __LINE__, UUMSG_NOTE,
1207     uustring (S_SCAN_CANCEL));
1208     *errcode = UURET_CANCEL;
1209     break;
1210     }
1211    
1212     oldposition = ftell (datei);
1213 root 1.23 if (FP_fgets (line, 1024, datei) == NULL)
1214 root 1.1 break;
1215     if (ferror (datei))
1216     break;
1217    
1218     /*
1219     * Stop scanning at an empty line or a MIME-boundary.
1220     */
1221     if (IsLineEmpty (line))
1222     break;
1223     if (boundary && line[0] == '-' && line[1] == '-' &&
1224     strncmp (line+2, boundary, blen) == 0) {
1225     fseek (datei, oldposition, SEEK_SET);
1226     break;
1227     }
1228     else if (line[0] == 'e' && (result->uudet == UU_ENCODED ||
1229     result->uudet == XX_ENCODED)) {
1230     if (strncmp (line, "end", 3) == 0) {
1231     result->end = 1;
1232     break;
1233     }
1234     }
1235     else if (line[0] == 'b') {
1236     if (strncmp (line, "begin ", 6) == 0) {
1237     fseek (datei, oldposition, SEEK_SET);
1238     break;
1239     }
1240     }
1241    
1242     if (checkheaders) {
1243     if (IsKnownHeader (line)) {
1244     (void) ScanHeaderLine (datei, line);
1245     if (hcount == 0)
1246     preheaders = oldposition;
1247     hcount++;
1248     lcount++;
1249     if ((hcount >= hlcount.restart) ||
1250     (hcount >= hlcount.afterdata && result->uudet)) {
1251     /*
1252     * Hey, a new header starts here
1253     */
1254     fseek (datei, preheaders, SEEK_SET);
1255     break;
1256     }
1257     }
1258     else if (lcount > WAITHEADER) {
1259     hcount = 0;
1260     lcount = 0;
1261     }
1262     else if (hcount) {
1263     lcount++;
1264     }
1265     }
1266     if (result->uudet == BH_ENCODED) {
1267     /* pick up ``EOF'' for BinHex files. Slow :-< */
1268     if (line[0] && strchr (line+1, ':') != NULL) {
1269     result->end = 1;
1270 root 1.2 bhflag = 0;
1271 root 1.1 break;
1272     }
1273     }
1274     }
1275 root 1.2
1276 root 1.1 if (ferror (datei) || *errcode == UURET_CANCEL)
1277     break;
1278    
1279     if (line[0] == '-' && line[1] == '-')
1280     haddh = 1;
1281    
1282     /*
1283     * Okay, got everything we need. If we had headers or a
1284     * boundary, we break out of the outer loop immediately.
1285     */
1286    
1287     if (IsKnownHeader (line) ||
1288     (boundary && line[0] == '-' && line[1] == '-' &&
1289     strncmp (line+2, boundary, blen) == 0)) {
1290     break;
1291     }
1292 root 1.2
1293 root 1.1 /*
1294     * Otherwise, we wait until finding something more interesting
1295     * in the outer loop
1296     */
1297 root 1.2
1298     continue;
1299 root 1.1 }
1300 root 1.22
1301 root 1.2 /*
1302     * Select the encoding with the best "history"
1303     */
1304    
1305     cbb64 = isb64[(iscnt-1)%10];
1306     cbuue = isuue[(iscnt-1)%10];
1307     cbxxe = isxxe[(iscnt-1)%10];
1308     cbbhx = isbhx[(iscnt-1)%10];
1309     dflag = 0;
1310    
1311     if (cbb64 || cbuue || cbxxe || cbbhx) {
1312     for (dflag=2; dflag<iscnt && dflag<4; dflag++) {
1313     if ((!cbb64 || !isb64[(iscnt-dflag)%10]) &&
1314     (!cbuue || !isuue[(iscnt-dflag)%10]) &&
1315     (!cbxxe || !isxxe[(iscnt-dflag)%10]) &&
1316     (!cbbhx || !isbhx[(iscnt-dflag)%10])) {
1317     dflag--;
1318     break;
1319     }
1320     cbb64 &= isb64[(iscnt-dflag)%10];
1321     cbuue &= isuue[(iscnt-dflag)%10];
1322     cbxxe &= isxxe[(iscnt-dflag)%10];
1323     cbbhx &= isbhx[(iscnt-dflag)%10];
1324     }
1325     }
1326    
1327     /*
1328     * clear-cut cases
1329     */
1330    
1331     if (cbb64 && !cbuue && !cbxxe && !cbbhx) {
1332     encoding = B64ENCODED;
1333     }
1334     else if (!cbb64 && cbuue && !cbxxe && !cbbhx) {
1335     encoding = UU_ENCODED;
1336     }
1337     else if (!cbb64 && !cbuue && cbxxe && !cbbhx) {
1338     encoding = XX_ENCODED;
1339     }
1340     else if (!cbb64 && !cbuue && !cbxxe && cbbhx) {
1341     encoding = BH_ENCODED;
1342     }
1343     else {
1344     encoding = 0;
1345     }
1346    
1347     /*
1348     * Check a few common non-clear-cut cases
1349     */
1350    
1351     if (!encoding && cbuue && result->begin) {
1352     encoding = UU_ENCODED;
1353     }
1354     else if (!encoding && cbxxe && result->begin) {
1355     encoding = XX_ENCODED;
1356     }
1357     else if (!encoding && cbb64) {
1358     encoding = B64ENCODED;
1359     }
1360     else if (!encoding && cbuue) {
1361     encoding = UU_ENCODED;
1362     }
1363     else if (!encoding && cbxxe) {
1364     encoding = XX_ENCODED;
1365     }
1366     else if (!encoding && cbbhx) {
1367     encoding = BH_ENCODED;
1368 root 1.1 }
1369     }
1370     else if (!dontcare) {
1371     encoding = 0;
1372     dflag = 0;
1373     haddh = 0;
1374     }
1375     } /* if (!uudet) */
1376     /*
1377     * End of scanning loop
1378     */
1379 root 1.23 } /* while (!FP_feof (datei)) */
1380 root 1.1
1381 root 1.23 if (FP_feof (datei))
1382 root 1.1 oldposition = ftell (datei);
1383    
1384     if (dflag && encoding == B64ENCODED && haddh)
1385     result->uudet = B64ENCODED;
1386     else if (dflag && encoding == BH_ENCODED)
1387     result->uudet = BH_ENCODED;
1388    
1389     /* Base64 doesn't have begin or end, so it was probably XX */
1390     if (result->uudet == B64ENCODED && result->begin && result->end)
1391     result->uudet = XX_ENCODED;
1392    
1393     /* Base64 doesn't have begin or end */
1394     if (result->uudet == B64ENCODED)
1395     result->begin = result->end = 0;
1396    
1397     /* Base64 and BinHex don't have a file mode */
1398 root 1.4 if (result->uudet == B64ENCODED || result->uudet == BH_ENCODED ||
1399     result->uudet == YENC_ENCODED)
1400 root 1.1 result->mode = 6*64+4*8+4;
1401    
1402     /*
1403 root 1.2 * When strict MIME adherance is set, throw out suspicious attachments
1404     */
1405    
1406     if (uu_more_mime) {
1407     /*
1408     * In a MIME message, Base64 should be appropriately tagged
1409     */
1410    
1411     if (result->uudet == B64ENCODED) {
1412     result->uudet = 0;
1413     }
1414    
1415     /*
1416     * Do not accept incomplete UU or XX encoded messages
1417     */
1418    
1419     if ((result->uudet != 0 && result->uudet != B64ENCODED) &&
1420     (!result->begin || !result->end)) {
1421     result->uudet = 0;
1422     }
1423     }
1424    
1425     /*
1426 root 1.1 * In fast mode, this length will yield a false value. We don't care.
1427     * This must be checked for in uunconc(), where we usually stop decoding
1428     * after reaching startpos+length
1429     */
1430    
1431     if (uu_fast_scanning)
1432     result->length = progress.fsize-result->startpos;
1433     else
1434     result->length = ftell(datei)-result->startpos;
1435    
1436     if (ferror (datei)) {
1437     *errcode = UURET_IOERR;
1438     uu_errno = errno;
1439     return -1;
1440     }
1441     if (*errcode != UURET_OK) {
1442     return -1;
1443     }
1444    
1445     if (boundary && line[0] == '-' && line[1] == '-' &&
1446     strncmp (line+2, boundary, blen) == 0)
1447     return 2;
1448     else if (boundary && p3 &&
1449     line[0] == 'C' && line[1] == 'o' &&
1450 root 1.24 FP_strnicmp_fast (line, "Content-Type:", 13) == 0 &&
1451 root 1.1 strcmp (p3, boundary) == 0)
1452     return 2;
1453     else if (IsKnownHeader (line))
1454     return 1;
1455    
1456     return 0;
1457     }
1458    
1459     /*
1460     * This is the main scanning function.
1461     */
1462    
1463     fileread *
1464     ScanPart (FILE *datei, char *fname, int *errcode)
1465     {
1466     int ecount, hcount, lcount;
1467 root 1.4 int bhflag, begflag, vflag, blen=0, res;
1468     long preheaders, prevpos=0, preenc, before;
1469 root 1.1 char *line=uuscan_spline;
1470     fileread *result;
1471     char *ptr1, *ptr2;
1472    
1473     (void) UUDecodeLine (NULL, NULL, 0); /* init */
1474 root 1.23 if (datei == NULL || FP_feof (datei)) {
1475 root 1.1 *errcode = UURET_OK;
1476     return NULL;
1477     }
1478    
1479     *errcode = UURET_OK;
1480    
1481     if ((result = (fileread *) malloc (sizeof (fileread))) == NULL) {
1482     *errcode = UURET_NOMEM;
1483     return NULL;
1484     }
1485     memset (result, 0, sizeof (fileread));
1486     result->startpos = ftell (datei);
1487     preheaders = result->startpos;
1488     before = result->startpos;
1489    
1490     /* if this is a new file, reset our scanning state */
1491     if (sstate.source == NULL || strcmp (fname, sstate.source) != 0) {
1492     sstate.isfolder = 1; /* assume yes */
1493     sstate.ismime = 0; /* wait for MIME-Version */
1494     sstate.mimestate = MS_HEADERS; /* assume headers follow */
1495     /* mimseqno = 1; */
1496    
1497     while (mssdepth) {
1498     mssdepth--;
1499     UUkillheaders (&(multistack[mssdepth].envelope));
1500 root 1.23 FP_free (multistack[mssdepth].source);
1501 root 1.1 }
1502    
1503     UUkillheaders (&sstate.envelope);
1504     memset (&sstate.envelope, 0, sizeof (headers));
1505    
1506 root 1.23 FP_free (sstate.source);
1507     if ((sstate.source = FP_strdup (fname)) == NULL) {
1508 root 1.1 *errcode = UURET_NOMEM;
1509 root 1.23 FP_free (result);
1510 root 1.1 return NULL;
1511     }
1512    
1513     /* ignore empty lines at the beginning of a file */
1514     preheaders = ftell (datei);
1515 root 1.23 while (!FP_feof (datei)) {
1516 root 1.12 if (UUBUSYPOLL(preheaders,progress.fsize)) SPCANCEL();
1517 root 1.23 if (FP_fgets (line, 1024, datei) == NULL)
1518 root 1.1 break;
1519     if (!IsLineEmpty (line)) {
1520     fseek (datei, preheaders, SEEK_SET);
1521     break;
1522     }
1523     preheaders = ftell (datei);
1524     }
1525     }
1526    
1527 root 1.23 if (ferror(datei) || FP_feof(datei)) {
1528     FP_free (result);
1529 root 1.1 return NULL;
1530     }
1531    
1532     /*
1533     * If we are confident that this is a mail folder and are at the
1534     * beginning of the file, expecting to read some headers, scan
1535     * the envelope.
1536     */
1537    
1538     if (sstate.isfolder && sstate.mimestate == MS_HEADERS) {
1539     hcount = 0;
1540     lcount = 0;
1541     UUkillheaders (&sstate.envelope);
1542    
1543     /*
1544     * clean up leftovers from invalid messages
1545     */
1546    
1547     while (mssdepth) {
1548     mssdepth--;
1549     UUkillheaders (&(multistack[mssdepth].envelope));
1550 root 1.23 FP_free (multistack[mssdepth].source);
1551 root 1.1 }
1552    
1553 root 1.7 prevpos = ftell (datei);
1554 root 1.23 if (FP_fgets (line, 1024, datei) == NULL) {
1555     FP_free (result);
1556 root 1.1 return NULL;
1557     }
1558    
1559 root 1.2 /*
1560     * Special handling for AOL folder files, which start off with a boundary.
1561     * We recognize them by a valid boundary line as the first line of a file.
1562     * Note that the rest of the scanning code becomes suspicious if a boun-
1563     * dary does never appear in a file -- this should save us from grave
1564     * false detection errors
1565     */
1566    
1567 root 1.23 if (!FP_feof (datei) && line[0] == '-' && line[1] == '-' && line[2]) {
1568 root 1.2 sstate.ismime = 1;
1569 root 1.23 sstate.envelope.mimevers = FP_strdup ("1.0");
1570     sstate.envelope.boundary = FP_strdup (line+2);
1571     sstate.envelope.ctype = FP_strdup ("multipart/mixed");
1572 root 1.2 sstate.mimestate = MS_SUBPART;
1573    
1574     *errcode = UURET_CONT;
1575 root 1.23 FP_free (result);
1576 root 1.2 return NULL;
1577     }
1578    
1579     /*
1580     * Normal behavior: look for a RFC 822 header
1581     */
1582    
1583 root 1.23 while (!FP_feof (datei) && !IsLineEmpty (line)) {
1584 root 1.1 if (IsKnownHeader (line))
1585     hcount++;
1586     if (UUBUSYPOLL(ftell(datei),progress.fsize)) SPCANCEL();
1587 root 1.7 if (IsHeaderLine (line)) {
1588     ptr1 = ScanHeaderLine (datei, line);
1589     if (ParseHeader (&sstate.envelope, ptr1) == NULL) {
1590     *errcode = UURET_NOMEM;
1591 root 1.23 FP_free (result);
1592 root 1.7 return NULL;
1593     }
1594 root 1.1 }
1595     /*
1596     * if we've read too many lines without finding headers, then
1597     * this probably isn't a mail folder after all
1598     */
1599     lcount++;
1600 root 1.7 if (lcount > WAITHEADER && hcount < hlcount.afternl) {
1601     fseek (datei, prevpos, SEEK_SET);
1602     line[0] = '\0';
1603 root 1.1 break;
1604 root 1.7 }
1605 root 1.1
1606 root 1.23 if (FP_fgets (line, 1024, datei) == NULL) {
1607 root 1.8 /* If we are at eof without finding headers, there probably isn't */
1608 root 1.15 if (hcount < hlcount.afternl)
1609 root 1.8 fseek (datei, prevpos, SEEK_SET);
1610     break;
1611     }
1612 root 1.1 }
1613 root 1.7
1614 root 1.1 /* skip empty lines */
1615     prevpos = ftell (datei);
1616 root 1.7 if (IsLineEmpty (line)) {
1617 root 1.23 while (!FP_feof (datei)) {
1618     if (FP_fgets (line, 1024, datei) == NULL)
1619 root 1.7 break;
1620     if (UUBUSYPOLL(ftell(datei),progress.fsize)) SPCANCEL();
1621     if (!IsLineEmpty (line)) {
1622     fseek (datei, prevpos, SEEK_SET);
1623     break;
1624     }
1625     prevpos = ftell (datei);
1626 root 1.1 }
1627     }
1628 root 1.7
1629 root 1.1 /*
1630     * If we don't have all valid MIME headers yet, but the following
1631     * line is a MIME header, accept it anyway.
1632     */
1633 root 1.2
1634     if (!uu_more_mime &&
1635     sstate.envelope.mimevers == NULL &&
1636     sstate.envelope.ctype == NULL &&
1637     sstate.envelope.ctenc == NULL &&
1638     IsKnownHeader (line)) {
1639 root 1.1 /*
1640     * see above
1641     */
1642 root 1.23 FP_fgets (line, 1024, datei);
1643 root 1.1
1644 root 1.23 while (!FP_feof (datei) && !IsLineEmpty (line)) {
1645 root 1.1 if (IsKnownHeader (line))
1646     hcount++;
1647     if (UUBUSYPOLL(ftell(datei),progress.fsize)) SPCANCEL();
1648     ptr1 = ScanHeaderLine (datei, line);
1649     if (ParseHeader (&sstate.envelope, ptr1) == NULL) {
1650     *errcode = UURET_NOMEM;
1651 root 1.23 FP_free (result);
1652 root 1.1 return NULL;
1653     }
1654 root 1.2
1655 root 1.23 if (FP_fgets (line, 1024, datei) == NULL)
1656 root 1.1 break;
1657     }
1658     /* skip empty lines */
1659     prevpos = ftell (datei);
1660 root 1.23 while (!FP_feof (datei)) {
1661     if (FP_fgets (line, 1024, datei) == NULL)
1662 root 1.1 break;
1663     if (UUBUSYPOLL(ftell(datei),progress.fsize)) SPCANCEL();
1664     if (!IsLineEmpty (line)) {
1665     fseek (datei, prevpos, SEEK_SET);
1666     break;
1667     }
1668     prevpos = ftell (datei);
1669     }
1670     }
1671 root 1.2
1672 root 1.1 /*
1673     * A partial multipart message probably has only a Content-Type
1674     * header but nothing else. In this case, at least simulate a
1675     * MIME message
1676     * if mimevers is not set but there are other well-known MIME
1677     * headers, don't be too picky about it.
1678     */
1679     if (sstate.envelope.ctype && sstate.envelope.mimevers==NULL &&
1680 root 1.23 FP_stristr (sstate.envelope.ctype, "multipart") != NULL &&
1681 root 1.1 sstate.envelope.boundary != NULL) {
1682 root 1.23 sstate.envelope.mimevers = FP_strdup ("1.0");
1683 root 1.1 hcount = hlcount.afternl;
1684     }
1685     else if (sstate.envelope.mimevers==NULL && sstate.envelope.ctype &&
1686     sstate.envelope.fname && sstate.envelope.ctenc) {
1687 root 1.23 sstate.envelope.mimevers = FP_strdup ("1.0");
1688 root 1.1 hcount = hlcount.afternl;
1689     }
1690    
1691 root 1.7 if (sstate.envelope.mimevers != NULL) {
1692 root 1.1 /* this is a MIME file. check the Content-Type */
1693     sstate.ismime = 1;
1694 root 1.23 if (FP_stristr (sstate.envelope.ctype, "multipart") != NULL) {
1695 root 1.1 if (sstate.envelope.boundary == NULL) {
1696     UUMessage (uuscan_id, __LINE__, UUMSG_WARNING,
1697     uustring (S_MIME_NO_BOUNDARY));
1698     sstate.mimestate = MS_BODY;
1699 root 1.23 FP_free (sstate.envelope.ctype);
1700     sstate.envelope.ctype = FP_strdup ("text/plain");
1701 root 1.1 }
1702     else {
1703     sstate.mimestate = MS_PREAMBLE;
1704     }
1705     }
1706     else {
1707     sstate.mimestate = MS_BODY; /* just a `simple' message */
1708     }
1709 root 1.7 }
1710     else {
1711     /* not a folder after all */
1712     fseek (datei, prevpos, SEEK_SET);
1713     sstate.isfolder = 0;
1714     sstate.ismime = 0;
1715 root 1.1 }
1716     }
1717    
1718 root 1.23 if (FP_feof (datei) || ferror (datei)) { /* oops */
1719     FP_free (result);
1720 root 1.1 return NULL;
1721     }
1722    
1723     /*
1724     * Handle MIME stuff
1725     */
1726    
1727     /*
1728     * Read Preamble. This must be ended by a sstate.envelope.boundary line.
1729     * If uu_usepreamble is set, we produce a result from this one
1730     */
1731    
1732     if (sstate.ismime && sstate.mimestate == MS_PREAMBLE) {
1733     result->startpos = ftell (datei); /* remember start of preamble */
1734     prevpos = ftell (datei);
1735     preheaders = ftell (datei);
1736    
1737     blen = strlen (sstate.envelope.boundary);
1738     lcount = 0;
1739 root 1.22
1740 root 1.23 while (!FP_feof (datei)) {
1741     if (FP_fgets (line, 1024, datei) == NULL)
1742 root 1.1 break;
1743     if (UUBUSYPOLL(ftell(datei),progress.fsize)) SPCANCEL();
1744     if (line[0] == '-' && line[1] == '-' &&
1745     strncmp (line+2, sstate.envelope.boundary, blen) == 0)
1746     break;
1747     if (!IsLineEmpty (line))
1748     lcount++;
1749    
1750     prevpos = ftell (datei);
1751     }
1752 root 1.23 if (FP_feof (datei) || ferror (datei)) {
1753 root 1.1 UUMessage (uuscan_id, __LINE__, UUMSG_WARNING,
1754     uustring (S_MIME_B_NOT_FOUND));
1755     /*
1756     * restart and try again; don't restart if uu_fast_scanning
1757     */
1758     sstate.isfolder = 0;
1759     sstate.ismime = 0;
1760     sstate.mimestate = MS_BODY;
1761    
1762     if (!uu_fast_scanning) {
1763     *errcode = UURET_CONT;
1764     fseek (datei, preheaders, SEEK_SET);
1765     }
1766 root 1.23 FP_free (result);
1767 root 1.1 return NULL;
1768     }
1769     if (line[0] == '-' && line[1] == '-' &&
1770     strncmp (line+2, sstate.envelope.boundary, blen) == 0) {
1771     ptr1 = line + 2 + blen;
1772     if (*ptr1 == '-' && *(ptr1+1) == '-') {
1773     /* Empty Multipart Message. Duh. */
1774     sstate.mimestate = MS_EPILOGUE;
1775     }
1776     else {
1777     sstate.mimestate = MS_SUBPART;
1778     }
1779     }
1780     else { /* shouldn't happen */
1781     UUMessage (uuscan_id, __LINE__, UUMSG_WARNING,
1782     uustring (S_MIME_B_NOT_FOUND));
1783     /*
1784     * restart and try again; don't restart if uu_fast_scanning
1785     */
1786     sstate.isfolder = 0;
1787     sstate.ismime = 0;
1788     sstate.mimestate = MS_BODY;
1789    
1790     if (!uu_fast_scanning) {
1791     *errcode = UURET_CONT;
1792     fseek (datei, preheaders, SEEK_SET);
1793     }
1794 root 1.23 FP_free (result);
1795 root 1.1 return NULL;
1796     }
1797     /* produce result if uu_usepreamble is set */
1798     if (uu_usepreamble && lcount) {
1799     sprintf (line, "%04d.txt", ++mimseqno);
1800 root 1.23 result->subject = FP_strdup (sstate.envelope.subject);
1801     result->filename = FP_strdup (line);
1802     result->origin = FP_strdup (sstate.envelope.from);
1803     result->mimeid = FP_strdup (sstate.envelope.mimeid);
1804     result->mimetype = FP_strdup ("text/plain");
1805 root 1.1 result->mode = 0644;
1806     result->uudet = PT_ENCODED; /* plain text */
1807 root 1.23 result->sfname = FP_strdup (fname);
1808 root 1.1 result->flags = FL_SINGLE | FL_PROPER;
1809     /* result->startpos set from above */
1810     result->length = prevpos - result->startpos;
1811     result->partno = 1;
1812    
1813     /* MIME message, let's continue */
1814     *errcode = UURET_CONT;
1815    
1816     if ((sstate.envelope.subject != NULL && result->subject == NULL) ||
1817     result->filename == NULL || result->sfname == NULL) {
1818     *errcode = UURET_NOMEM;
1819     }
1820    
1821     return result;
1822     }
1823     /* MIME message, let's continue */
1824     if (*errcode == UURET_OK)
1825     *errcode = UURET_CONT;
1826    
1827     /* otherwise, just return NULL */
1828 root 1.23 FP_free (result);
1829 root 1.1 return NULL;
1830     }
1831    
1832     /*
1833     * Read Epilogue, the plain text after the last boundary.
1834     * This can either end with new headers from the next message of a
1835     * mail folder or with a `parent' boundary if we are inside an
1836     * encapsulated Multipart message. Oh yes, and of course the file
1837     * may also simply end :-)
1838     * Another possibility is that we might find plain encoded data
1839     * without encapsulating message. We're not _too_ flexible here,
1840     * we won't detect Base64, and require a proper `begin' line for
1841     * uuencoding and xxencoding
1842     * If uu_usepreamble is set, we produce a result from this one
1843     */
1844    
1845     if (sstate.ismime && sstate.mimestate == MS_EPILOGUE) {
1846     result->startpos = ftell (datei); /* remember start of epilogue */
1847     prevpos = ftell (datei);
1848     preheaders = ftell (datei);
1849     preenc = ftell (datei);
1850     hcount = lcount = 0;
1851     ecount = bhflag = 0;
1852     begflag = vflag = 0;
1853     res = 0;
1854    
1855     /*
1856     * If we are in the outermost message and uu_fast_scanning, we
1857     * know (or assume) that no more messages will follow, so there's
1858     * no need to scan the rest.
1859     */
1860     if (uu_fast_scanning && mssdepth == 0) {
1861     /*
1862     * check if the epilogue is empty
1863     */
1864 root 1.23 while (!FP_feof (datei) && !ferror (datei) && lcount<10 && res==0) {
1865     if (FP_fgets (line, 1024, datei) == NULL)
1866 root 1.1 break;
1867     if (!IsLineEmpty (line))
1868     res++;
1869     lcount++;
1870     }
1871     if (uu_usepreamble && res) {
1872     sprintf (line, "%04d.txt", ++mimseqno);
1873 root 1.23 result->subject = FP_strdup (sstate.envelope.subject);
1874     result->filename = FP_strdup (line);
1875     result->origin = FP_strdup (sstate.envelope.from);
1876     result->mimeid = FP_strdup (sstate.envelope.mimeid);
1877     result->mimetype = FP_strdup ("text/plain");
1878 root 1.1 result->mode = 0644;
1879     result->uudet = PT_ENCODED; /* plain text */
1880 root 1.23 result->sfname = FP_strdup (fname);
1881 root 1.1 result->flags = FL_SINGLE | FL_PROPER | FL_TOEND;
1882     result->partno = 1;
1883     /* result->startpos set from above */
1884     result->length = progress.fsize - result->startpos;
1885    
1886     if ((sstate.envelope.subject != NULL && result->subject == NULL) ||
1887     result->filename == NULL || result->sfname == NULL) {
1888     *errcode = UURET_NOMEM;
1889     }
1890    
1891     return result;
1892     }
1893 root 1.23 FP_free (result);
1894 root 1.1 return NULL;
1895     }
1896    
1897     if (mssdepth > 0)
1898     blen = strlen (multistack[mssdepth-1].envelope.boundary);
1899    
1900 root 1.23 while (!FP_feof (datei)) {
1901     if (FP_fgets (line, 1024, datei) == NULL)
1902 root 1.1 break;
1903     if (UUBUSYPOLL(ftell(datei),progress.fsize)) SPCANCEL();
1904     /* check for parent boundary */
1905     if (mssdepth > 0 && line[0] == '-' && line[1] == '-' &&
1906     strncmp (line+2,
1907     multistack[mssdepth-1].envelope.boundary, blen) == 0)
1908     break;
1909    
1910     /* check for next headers only at outermost level */
1911     if (mssdepth == 0 && IsKnownHeader (line)) {
1912     (void) ScanHeaderLine (datei, line);
1913     if (hcount == 0) {
1914     preheaders = prevpos;
1915     lcount = 0;
1916     }
1917 root 1.22 hcount++;
1918 root 1.1 lcount++;
1919    
1920     if (hcount >= hlcount.restart) {
1921     /* okay, new headers */
1922     break;
1923     }
1924     }
1925     else if (lcount > WAITHEADER) {
1926     hcount = 0;
1927     lcount = 0;
1928     }
1929     else if (hcount) {
1930     lcount++;
1931     }
1932     else {
1933     hcount = lcount = 0;
1934     }
1935    
1936     /* check for begin and encoded data only at outermost level */
1937 root 1.2 if (mssdepth == 0 && !uu_more_mime) {
1938 root 1.24 if (strncmp (line, "begin ", 6) == 0 ||
1939     FP_strnicmp_fast (line, "<pre>begin ", 11) == 0) {
1940 root 1.1 preenc = prevpos;
1941     begflag = 1;
1942     }
1943     else if (strncmp (line, "end", 3) == 0 && begflag) {
1944     ecount = ELC_COUNT;
1945     break;
1946     }
1947     else if ((vflag = UUValidData (line, 0, &bhflag)) != 0) {
1948     if (vflag == BH_ENCODED && bhflag == 0) {
1949     /* very short BinHex file follows */
1950     preenc = prevpos;
1951     break;
1952     }
1953     /* remember that XX can easily be mistaken as Base64 */
1954 root 1.10 if ((vflag == UU_ENCODED || vflag == XX_ENCODED || vflag == B64ENCODED) && begflag) {
1955 root 1.1 if (++ecount >= ELC_COUNT)
1956     break;
1957     }
1958     else {
1959     begflag = 0;
1960     ecount = 0;
1961     }
1962     }
1963     else {
1964     begflag = 0;
1965     ecount = 0;
1966     }
1967     }
1968    
1969     if (!IsLineEmpty (line))
1970     res++;
1971    
1972     prevpos = ftell (datei);
1973     }
1974 root 1.2
1975 root 1.1 if (mssdepth > 0 && line[0] == '-' && line[1] == '-' &&
1976     strncmp (line+2,
1977     multistack[mssdepth-1].envelope.boundary, blen) == 0) {
1978     /* restore previous state */
1979     mssdepth--;
1980     UUkillheaders (&sstate.envelope);
1981 root 1.23 FP_free (sstate.source);
1982 root 1.1 memcpy (&sstate, &(multistack[mssdepth]), sizeof (scanstate));
1983    
1984     ptr1 = line + 2 + strlen (sstate.envelope.boundary);
1985    
1986     if (*ptr1 == '-' && *(ptr1+1) == '-') {
1987     sstate.mimestate = MS_EPILOGUE;
1988     }
1989     else {
1990     sstate.mimestate = MS_SUBPART;
1991     }
1992     result->length = prevpos - result->startpos;
1993     *errcode = UURET_CONT;
1994     }
1995     else if (mssdepth > 0) {
1996     UUMessage (uuscan_id, __LINE__, UUMSG_WARNING,
1997     uustring (S_MIME_B_NOT_FOUND));
1998     /*
1999     * restart and try again; don't restart if uu_fast_scanning
2000     */
2001     sstate.isfolder = 0;
2002     sstate.ismime = 0;
2003     sstate.mimestate = MS_BODY;
2004    
2005     while (mssdepth) {
2006     mssdepth--;
2007     UUkillheaders (&(multistack[mssdepth].envelope));
2008 root 1.23 FP_free (multistack[mssdepth].source);
2009 root 1.1 }
2010    
2011     if (!uu_fast_scanning) {
2012     *errcode = UURET_CONT;
2013     fseek (datei, preheaders, SEEK_SET);
2014     }
2015 root 1.23 FP_free (result);
2016 root 1.1 return NULL;
2017     }
2018     else if (IsKnownHeader (line)) {
2019     /* new message follows */
2020     sstate.isfolder = 1;
2021     sstate.ismime = 0;
2022     sstate.mimestate = MS_HEADERS;
2023     result->length = preheaders - result->startpos;
2024     fseek (datei, preheaders, SEEK_SET);
2025     }
2026     else if (ecount >= ELC_COUNT) {
2027     /* new plain encoding */
2028     sstate.isfolder = 0;
2029     sstate.ismime = 0;
2030     sstate.mimestate = MS_BODY;
2031     result->length = preenc - result->startpos;
2032     fseek (datei, preenc, SEEK_SET);
2033     }
2034    
2035     /* produce result if uu_usepreamble is set */
2036     if (uu_usepreamble && res) {
2037     sprintf (line, "%04d.txt", ++mimseqno);
2038 root 1.23 result->subject = FP_strdup (sstate.envelope.subject);
2039     result->filename = FP_strdup (line);
2040     result->origin = FP_strdup (sstate.envelope.from);
2041     result->mimeid = FP_strdup (sstate.envelope.mimeid);
2042     result->mimetype = FP_strdup ("text/plain");
2043 root 1.1 result->mode = 0644;
2044     result->uudet = PT_ENCODED; /* plain text */
2045 root 1.23 result->sfname = FP_strdup (fname);
2046 root 1.1 result->flags = FL_SINGLE | FL_PROPER;
2047     result->partno = 1;
2048     /* result->startpos set from above */
2049     /* result->length set from above */
2050    
2051     if ((sstate.envelope.subject != NULL && result->subject == NULL) ||
2052     result->filename == NULL || result->sfname == NULL) {
2053     *errcode = UURET_NOMEM;
2054     }
2055    
2056     return result;
2057     }
2058     /* otherwise, just return NULL */
2059 root 1.23 FP_free (result);
2060 root 1.1 return NULL;
2061     }
2062    
2063     /*
2064     * Scan a new part from a Multipart message. Check for a new local
2065     * envelope (which defaults to `Content-Type: text/plain') and
2066     * evaluate its Content-Type and Content-Transfer-Encoding. If this
2067     * is another Multipart/something, push the current state onto our
2068     * stack and dive into the new environment, starting with another
2069     * preamble.
2070     */
2071 root 1.22
2072 root 1.1 if (sstate.ismime && sstate.mimestate == MS_SUBPART) {
2073     memset (&localenv, 0, sizeof (headers));
2074     result->startpos = ftell (datei);
2075     prevpos = ftell (datei);
2076     hcount = 0;
2077     lcount = 0;
2078    
2079     /*
2080     * Duplicate some data from outer envelope
2081     */
2082    
2083 root 1.23 localenv.mimevers = FP_strdup (sstate.envelope.mimevers);
2084     localenv.from = FP_strdup (sstate.envelope.from);
2085     localenv.subject = FP_strdup (sstate.envelope.subject);
2086     localenv.rcpt = FP_strdup (sstate.envelope.rcpt);
2087     localenv.date = FP_strdup (sstate.envelope.date);
2088 root 1.1
2089     if ((sstate.envelope.mimevers != NULL && localenv.mimevers == NULL) ||
2090     (sstate.envelope.from != NULL && localenv.from == NULL) ||
2091     (sstate.envelope.subject != NULL && localenv.subject == NULL) ||
2092     (sstate.envelope.rcpt != NULL && localenv.rcpt == NULL) ||
2093     (sstate.envelope.date != NULL && localenv.date == NULL)) {
2094    
2095     while (mssdepth) {
2096     mssdepth--;
2097     UUkillheaders (&(multistack[mssdepth].envelope));
2098 root 1.23 FP_free (multistack[mssdepth].source);
2099 root 1.1 }
2100     sstate.isfolder = 0;
2101     sstate.ismime = 0;
2102 root 1.22
2103 root 1.1 UUkillheaders (&localenv);
2104     *errcode = UURET_NOMEM;
2105 root 1.23 FP_free (result);
2106 root 1.1 return NULL;
2107     }
2108 root 1.22
2109 root 1.1 /* Scan subheader. But what if there is no subheader? */
2110     hcount = 0;
2111     lcount = 0;
2112     preheaders = prevpos;
2113 root 1.22
2114 root 1.23 if (FP_fgets (line, 1024, datei) == NULL) {
2115 root 1.1 sstate.isfolder = 0;
2116     sstate.ismime = 0;
2117     while (mssdepth) {
2118     mssdepth--;
2119     UUkillheaders (&(multistack[mssdepth].envelope));
2120 root 1.23 FP_free (multistack[mssdepth].source);
2121 root 1.1 }
2122     UUkillheaders (&localenv);
2123 root 1.23 FP_free (result);
2124 root 1.1 return NULL;
2125     }
2126    
2127 root 1.23 while (!FP_feof (datei) && !IsLineEmpty (line)) {
2128 root 1.1 if (IsKnownHeader (line))
2129     hcount++;
2130     if (UUBUSYPOLL(ftell(datei),progress.fsize)) SPCANCEL();
2131     if (lcount > WAITHEADER && hcount == 0) {
2132     fseek (datei, preheaders, SEEK_SET);
2133     prevpos = preheaders;
2134     break;
2135     }
2136     ptr1 = ScanHeaderLine (datei, line);
2137     if (ParseHeader (&localenv, ptr1) == NULL)
2138     *errcode = UURET_NOMEM;
2139    
2140     if (line[0] == '-' && line[1] == '-')
2141     break;
2142    
2143     prevpos = ftell (datei);
2144    
2145 root 1.23 if (FP_fgets (line, 1024, datei) == NULL)
2146 root 1.1 break;
2147     lcount++;
2148     }
2149     if (line[0] == '-' && line[1] == '-') {
2150     /*
2151     * this shouldn't happen, there must always be an empty line,
2152     * but let's accept it anyway. Just skip back to before the
2153     * boundary, so that it gets handled below
2154     */
2155     fseek (datei, prevpos, SEEK_SET);
2156     }
2157    
2158 root 1.23 if (FP_stristr (localenv.ctype, "multipart") != NULL) {
2159 root 1.1 /* oh no, not again */
2160     if (mssdepth >= MSMAXDEPTH) {
2161     /* Argh, what an isane message. Treat as plain text */
2162     UUMessage (uuscan_id, __LINE__, UUMSG_WARNING,
2163     uustring (S_MIME_MULTI_DEPTH));
2164     }
2165     else if (localenv.boundary == NULL) {
2166     UUMessage (uuscan_id, __LINE__, UUMSG_WARNING,
2167     uustring (S_MIME_NO_BOUNDARY));
2168     }
2169     else {
2170     memcpy (&multistack[mssdepth], &sstate, sizeof (scanstate));
2171     memcpy (&sstate.envelope, &localenv, sizeof (headers));
2172     memset (&localenv, 0, sizeof (headers));
2173     sstate.mimestate = MS_PREAMBLE;
2174 root 1.23 if ((sstate.source = FP_strdup (sstate.source)) == NULL)
2175 root 1.1 *errcode = UURET_NOMEM;
2176    
2177     if (*errcode == UURET_OK)
2178     *errcode = UURET_CONT;
2179    
2180     mssdepth++;
2181     /* need a restart */
2182 root 1.23 FP_free (result);
2183 root 1.1 return NULL;
2184     }
2185     }
2186 root 1.4
2187 root 1.1 /*
2188     * So this subpart is either plain text or something else. Check
2189     * the Content-Type and Content-Transfer-Encoding. If the latter
2190     * is a defined value, we know what to do and just copy everything
2191     * up to the boundary.
2192     * If Content-Transfer-Encoding is unknown or missing, look at the
2193     * Content-Type. If it's "text/plain" or undefined, we subject the
2194     * message to our encoding detection. Otherwise, treat as plain
2195     * text.
2196     * This is done because users might `attach' a uuencoded file, which
2197     * would then be correctly typed as `text/plain'.
2198     */
2199 root 1.4
2200 root 1.23 if (FP_stristr (localenv.ctenc, "base64") != NULL)
2201 root 1.1 result->uudet = B64ENCODED;
2202 root 1.23 else if (FP_stristr (localenv.ctenc, "x-uue") != NULL) {
2203 root 1.2 result->uudet = UU_ENCODED;
2204 root 1.4 result->begin = result->end = 1;
2205     }
2206 root 1.23 else if (FP_stristr (localenv.ctenc, "x-yenc") != NULL) {
2207 root 1.4 result->uudet = YENC_ENCODED;
2208     result->begin = result->end = 1;
2209     }
2210 root 1.23 else if (FP_stristr (localenv.ctenc, "quoted-printable") != NULL)
2211 root 1.1 result->uudet = QP_ENCODED;
2212 root 1.23 else if (FP_stristr (localenv.ctenc, "7bit") != NULL ||
2213     FP_stristr (localenv.ctenc, "8bit") != NULL)
2214 root 1.1 result->uudet = PT_ENCODED;
2215 root 1.23 else if (FP_stristr (localenv.ctype, "multipart") != NULL ||
2216     FP_stristr (localenv.ctype, "message") != NULL)
2217 root 1.2 result->uudet = PT_ENCODED;
2218    
2219     /*
2220     * If we're switched to MIME-only mode, handle as text
2221     */
2222    
2223     if (uu_more_mime >= 2 && !result->uudet) {
2224 root 1.1 result->uudet = PT_ENCODED;
2225 root 1.2 }
2226 root 1.1
2227     if (result->uudet) {
2228     /*
2229     * Oh-kay, go ahead. Just read and wait for the boundary
2230     */
2231     result->startpos = ftell (datei);
2232     prevpos = ftell (datei);
2233     blen = strlen (sstate.envelope.boundary);
2234     lcount = 0;
2235 root 1.22
2236 root 1.23 while (!FP_feof (datei)) {
2237     if (FP_fgets (line, 1024, datei) == NULL)
2238 root 1.1 break;
2239     if (UUBUSYPOLL(ftell(datei),progress.fsize)) SPCANCEL();
2240     line[255] = '\0';
2241     if (line[0] == '-' && line[1] == '-' &&
2242     strncmp (line+2, sstate.envelope.boundary, blen) == 0)
2243     break;
2244     /*
2245     * I've had a report of someone who tried to decode a huge file
2246     * that had an early truncated multipart message and later another
2247     * multipart message with the *same* boundary. Consequently, all
2248     * some hundred messages inbetween were ignored ...
2249     * This check here doesn't cover folded header lines, but we don't
2250     * want to slow down scanning too much. We just check for
2251     * Content-Type: multipart/... boundary="same-boundary"
2252     */
2253     if (line[0] == 'C' && line[1] == 'o' &&
2254 root 1.24 FP_strnicmp_fast (line, "Content-Type:", 13) == 0) {
2255 root 1.1 ptr1 = ScanHeaderLine (datei, line);
2256 root 1.23 ptr2 = (ptr1)?FP_stristr(ptr1,"boundary"):NULL;
2257 root 1.1 ptr1 = (ptr2)?ParseValue(ptr2):NULL;
2258     if (ptr1 && strcmp (ptr1, sstate.envelope.boundary) == 0)
2259     break;
2260     for (res=0; ptr1 && res<mssdepth; res++)
2261     if (strcmp (ptr1, multistack[res].envelope.boundary) == 0)
2262     break;
2263     if (res<mssdepth)
2264     break;
2265     }
2266     if (!IsLineEmpty (line))
2267     lcount++;
2268     prevpos = ftell (datei);
2269     }
2270     if (line[0] == '-' && line[1] == '-' &&
2271     strncmp (line+2, sstate.envelope.boundary, blen) == 0) {
2272     ptr1 = line + 2 + blen;
2273     if (*ptr1 == '-' && *(ptr1+1) == '-')
2274     sstate.mimestate = MS_EPILOGUE;
2275     else
2276     sstate.mimestate = MS_SUBPART;
2277     }
2278     else {
2279     UUMessage (uuscan_id, __LINE__, UUMSG_WARNING,
2280     uustring (S_MIME_B_NOT_FOUND));
2281    
2282     while (mssdepth) {
2283     mssdepth--;
2284     UUkillheaders (&(multistack[mssdepth].envelope));
2285 root 1.23 FP_free (multistack[mssdepth].source);
2286 root 1.1 }
2287     /*
2288     * Don't retry if uu_fast_scanning
2289     */
2290    
2291     if (uu_fast_scanning) {
2292     UUkillheaders (&localenv);
2293     sstate.isfolder = 0;
2294     sstate.ismime = 0;
2295     sstate.mimestate = MS_BODY;
2296 root 1.23 FP_free (result);
2297 root 1.1 return NULL;
2298     }
2299    
2300     /*
2301     * Retry, but listening to headers this time
2302     */
2303     fseek (datei, result->startpos, SEEK_SET);
2304    
2305     UUkillfread (result);
2306     if ((result = (fileread *) malloc (sizeof (fileread))) == NULL) {
2307     *errcode = UURET_NOMEM;
2308     sstate.isfolder = 0;
2309     sstate.ismime = 0;
2310     UUkillheaders (&localenv);
2311     return NULL;
2312     }
2313     memset (result, 0, sizeof (fileread));
2314    
2315     if ((res = ScanData (datei, fname, errcode, NULL, 1, 1, result))==-1) {
2316     /* oops, something went wrong */
2317     sstate.isfolder = 0;
2318     sstate.ismime = 0;
2319     UUkillfread (result);
2320     UUkillheaders (&localenv);
2321     return NULL;
2322     }
2323     if (res == 1) {
2324     /*
2325     * new headers found
2326     */
2327     sstate.isfolder = 1;
2328     sstate.ismime = 0;
2329     sstate.mimestate = MS_HEADERS;
2330     }
2331     else {
2332     sstate.isfolder = 0;
2333     sstate.ismime = 0;
2334     }
2335     }
2336     /* produce result if uu_handletext is set */
2337 root 1.2 /* or if the file is explicitely named */
2338     if (result->uudet == B64ENCODED || lcount) {
2339 root 1.1 if (localenv.fname) {
2340 root 1.23 FP_free (result->filename);
2341     if ((result->filename = FP_strdup (localenv.fname)) == NULL)
2342 root 1.1 *errcode = UURET_NOMEM;
2343     }
2344     else if ((result->uudet==QP_ENCODED||result->uudet==PT_ENCODED) &&
2345 root 1.2 result->filename == NULL && uu_handletext) {
2346 root 1.1 sprintf (line, "%04d.txt", ++mimseqno);
2347 root 1.23 if ((result->filename = FP_strdup (line)) == NULL)
2348 root 1.1 *errcode = UURET_NOMEM;
2349     }
2350 root 1.23 result->subject = FP_strdup (localenv.subject);
2351     result->origin = FP_strdup (localenv.from);
2352     result->mimeid = FP_strdup (localenv.mimeid);
2353     result->mimetype = FP_strdup (localenv.ctype);
2354 root 1.1 result->mode = 0644;
2355 root 1.23 result->sfname = FP_strdup (fname);
2356 root 1.1 result->flags = FL_SINGLE | FL_PROPER;
2357     result->partno = 1;
2358     /* result->uudet determined above */
2359     /* result->startpos set from above */
2360     result->length = prevpos - result->startpos;
2361    
2362     if ((localenv.subject != NULL && result->subject == NULL) ||
2363     result->filename == NULL || result->sfname == NULL) {
2364     *errcode = UURET_NOMEM;
2365     }
2366     }
2367     else {
2368     /* don't produce a result */
2369 root 1.23 FP_free (result);
2370 root 1.1 result = NULL;
2371     }
2372     if (*errcode == UURET_OK)
2373     *errcode = UURET_CONT;
2374     /*
2375     * destroy local envelope
2376     */
2377     UUkillheaders (&localenv);
2378     return result;
2379     }
2380 root 1.2
2381 root 1.1 /*
2382     * we're in a subpart, but the local headers don't give us any
2383     * clue about what's to find here. So look for encoded data by
2384     * ourselves.
2385     */
2386 root 1.2
2387 root 1.1 if ((res = ScanData (datei, fname, errcode,
2388 root 1.2 sstate.envelope.boundary,
2389     1, 0, result)) == -1) {
2390 root 1.1 /* oops, something went wrong */
2391     sstate.isfolder = 0;
2392     sstate.ismime = 0;
2393     UUkillfread (result);
2394     UUkillheaders (&localenv);
2395     return NULL;
2396     }
2397     /*
2398     * we should really be at a boundary here, but check again
2399     */
2400     blen = strlen (sstate.envelope.boundary);
2401     prevpos = ftell (datei);
2402    
2403 root 1.23 while (!FP_feof (datei)) {
2404     if (FP_fgets (line, 1024, datei) == NULL)
2405 root 1.1 break;
2406     if (UUBUSYPOLL(ftell(datei),progress.fsize)) SPCANCEL();
2407     if (line[0] == '-' && line[1] == '-' &&
2408     strncmp (line+2, sstate.envelope.boundary, blen) == 0)
2409     break;
2410     if (line[0] == 'C' && line[1] == 'o' &&
2411 root 1.24 FP_strnicmp_fast (line, "Content-Type:", 13) == 0) {
2412 root 1.1 ptr1 = ScanHeaderLine (datei, line);
2413 root 1.23 ptr2 = (ptr1)?FP_stristr(ptr1,"boundary"):NULL;
2414 root 1.1 ptr1 = (ptr2)?ParseValue(ptr2):NULL;
2415     if (ptr1 && strcmp (ptr1, sstate.envelope.boundary) == 0)
2416     break;
2417     }
2418     prevpos = ftell (datei);
2419     }
2420     /*
2421     * check if this was the last subpart
2422     */
2423     if (line[0] == '-' && line[1] == '-' &&
2424     strncmp (line+2, sstate.envelope.boundary, blen) == 0) {
2425     ptr1 = line + 2 + blen;
2426     if (*ptr1 == '-' && *(ptr1+1) == '-')
2427     sstate.mimestate = MS_EPILOGUE;
2428     else
2429     sstate.mimestate = MS_SUBPART;
2430     }
2431     else {
2432     UUMessage (uuscan_id, __LINE__, UUMSG_WARNING,
2433     uustring (S_MIME_B_NOT_FOUND));
2434 root 1.22
2435 root 1.1 while (mssdepth) {
2436     mssdepth--;
2437     UUkillheaders (&(multistack[mssdepth].envelope));
2438 root 1.23 FP_free (multistack[mssdepth].source);
2439 root 1.1 }
2440    
2441     if (uu_fast_scanning) {
2442     UUkillheaders (&localenv);
2443     sstate.isfolder = 0;
2444     sstate.ismime = 0;
2445     sstate.mimestate = MS_BODY;
2446 root 1.23 FP_free (result);
2447 root 1.1 return NULL;
2448     }
2449    
2450     /*
2451     * Retry, listening to headers this time
2452     */
2453     fseek (datei, result->startpos, SEEK_SET);
2454 root 1.22
2455 root 1.1 UUkillfread (result);
2456     if ((result = (fileread *) malloc (sizeof (fileread))) == NULL) {
2457     *errcode = UURET_NOMEM;
2458     sstate.isfolder = 0;
2459     sstate.ismime = 0;
2460     UUkillheaders (&localenv);
2461     return NULL;
2462     }
2463     memset (result, 0, sizeof (fileread));
2464    
2465     if ((res = ScanData (datei, fname, errcode, NULL, 1, 1, result))==-1) {
2466     /* oops, something went wrong */
2467     sstate.isfolder = 0;
2468     sstate.ismime = 0;
2469     UUkillfread (result);
2470     UUkillheaders (&localenv);
2471     return NULL;
2472     }
2473     if (res == 1) {
2474     /*
2475     * new headers found
2476     */
2477     sstate.isfolder = 1;
2478     sstate.ismime = 0;
2479     sstate.mimestate = MS_HEADERS;
2480     }
2481     else {
2482     sstate.isfolder = 0;
2483     sstate.ismime = 0;
2484     }
2485     }
2486 root 1.2
2487     /*
2488     * If this file has been nicely MIME so far, then be very suspicious
2489     * if ScanData reports anything else. So do a double check, and if
2490     * it doesn't hold up, handle as plain text instead.
2491     */
2492    
2493 root 1.3 if (sstate.ismime && sstate.mimestate == MS_SUBPART &&
2494     strcmp (localenv.mimevers, "1.0") == 0 &&
2495 root 1.23 FP_stristr (localenv.ctype, "text") != NULL &&
2496 root 1.2 !uu_desperate) {
2497     if (result->uudet == UU_ENCODED && !(result->begin || result->end)) {
2498     result->uudet = 0;
2499     }
2500     }
2501    
2502 root 1.1 /*
2503     * produce result
2504     */
2505 root 1.2
2506     if (result->uudet == 0) {
2507 root 1.1 result->uudet = PT_ENCODED; /* plain text */
2508     }
2509    
2510     if (localenv.fname) {
2511 root 1.23 FP_free (result->filename);
2512     if ((result->filename = FP_strdup (localenv.fname)) == NULL)
2513 root 1.1 *errcode = UURET_NOMEM;
2514     }
2515     else if ((result->uudet==QP_ENCODED || result->uudet==PT_ENCODED) &&
2516 root 1.2 result->filename==NULL && uu_handletext) {
2517 root 1.1 sprintf (line, "%04d.txt", ++mimseqno);
2518 root 1.23 if ((result->filename = FP_strdup (line)) == NULL)
2519 root 1.1 *errcode = UURET_NOMEM;
2520     }
2521     else {
2522     /* assign a filename lateron */
2523     }
2524 root 1.23 if (result->mimetype) FP_free (result->mimetype);
2525 root 1.1 if (result->uudet) {
2526 root 1.23 if (FP_stristr (localenv.ctype, "text") != NULL &&
2527 root 1.1 result->uudet != QP_ENCODED && result->uudet != PT_ENCODED)
2528     result->mimetype = NULL; /* better don't set it */
2529     else
2530 root 1.23 result->mimetype = FP_strdup (localenv.ctype);
2531 root 1.1 }
2532 root 1.23 if (result->origin) FP_free (result->origin);
2533     result->origin = FP_strdup (localenv.from);
2534 root 1.1
2535 root 1.23 if (result->subject) FP_free (result->subject);
2536     result->subject = FP_strdup (localenv.subject);
2537 root 1.1
2538     if (result->sfname == NULL)
2539 root 1.23 if ((result->sfname = FP_strdup (fname)) == NULL)
2540 root 1.1 *errcode = UURET_NOMEM;
2541    
2542     result->length = prevpos - result->startpos;
2543     result->flags = FL_SINGLE | FL_PROPER;
2544     result->partno = 1;
2545    
2546     if (result->mode == 0)
2547     result->mode = 0644;
2548    
2549     /*
2550     * the other fields should already be set appropriately
2551     */
2552    
2553     if (*errcode == UURET_OK)
2554     *errcode = UURET_CONT;
2555    
2556     /*
2557     * kill local envelope
2558     */
2559     UUkillheaders (&localenv);
2560 root 1.22
2561 root 1.1 return result;
2562     }
2563    
2564     /*
2565     * All right, so we're not in a Multipart message. Phew, took quite
2566     * long to figure this out. But this might still be a MIME message
2567     * body. And if it's a message/partial, we need more special handling
2568     */
2569    
2570     if (sstate.isfolder && sstate.ismime && sstate.mimestate == MS_BODY &&
2571 root 1.23 FP_stristr (sstate.envelope.ctype, "message") != NULL &&
2572     FP_stristr (sstate.envelope.ctype, "partial") != NULL) {
2573 root 1.1
2574     result->startpos = ftell (datei);
2575    
2576     if (sstate.envelope.partno == 1) {
2577     /* read local envelope */
2578     UUkillheaders (&localenv);
2579     memset (&localenv, 0, sizeof (headers));
2580    
2581     /* skip over blank lines first */
2582     prevpos = ftell (datei);
2583 root 1.23 while (!FP_feof (datei)) {
2584     if (FP_fgets (line, 1024, datei) == NULL)
2585 root 1.1 break;
2586     if (UUBUSYPOLL(ftell(datei),progress.fsize)) SPCANCEL();
2587     if (!IsLineEmpty (line))
2588     break;
2589     prevpos = ftell (datei);
2590     }
2591     /* Next, read header. But what if there is no subheader? */
2592     hcount = 0;
2593     lcount = 0;
2594     preheaders = prevpos;
2595    
2596 root 1.23 while (!FP_feof (datei) && !IsLineEmpty (line)) {
2597 root 1.1 if (IsKnownHeader (line))
2598     hcount++;
2599     if (UUBUSYPOLL(ftell(datei),progress.fsize)) SPCANCEL();
2600     if (lcount > WAITHEADER && hcount == 0) {
2601     fseek (datei, preheaders, SEEK_SET);
2602     break;
2603     }
2604     ptr1 = ScanHeaderLine (datei, line);
2605     if (ParseHeader (&localenv, ptr1) == NULL)
2606     *errcode = UURET_NOMEM;
2607    
2608 root 1.23 if (FP_fgets (line, 1024, datei) == NULL)
2609 root 1.1 break;
2610     lcount++;
2611     }
2612     prevpos = ftell (datei);
2613     /*
2614     * Examine local header. We're mostly interested in the Content-Type
2615     * and the Content-Transfer-Encoding.
2616     */
2617 root 1.23 if (FP_stristr (localenv.ctype, "multipart") != NULL) {
2618 root 1.1 UUMessage (uuscan_id, __LINE__, UUMSG_WARNING,
2619     uustring (S_MIME_PART_MULTI));
2620     }
2621     if (localenv.subject)
2622 root 1.23 result->subject = FP_strdup (localenv.subject);
2623 root 1.1 else
2624 root 1.23 result->subject = FP_strdup (sstate.envelope.subject);
2625 root 1.1
2626     if (localenv.from)
2627 root 1.23 result->origin = FP_strdup (localenv.from);
2628 root 1.1 else
2629 root 1.23 result->origin = FP_strdup (sstate.envelope.from);
2630 root 1.1
2631     if (localenv.ctype)
2632 root 1.23 result->mimetype = FP_strdup (localenv.ctype);
2633 root 1.1 else
2634 root 1.23 result->mimetype = FP_strdup ("text/plain");
2635 root 1.1
2636 root 1.23 if (FP_stristr (localenv.ctenc, "quoted-printable") != NULL)
2637 root 1.1 result->uudet = QP_ENCODED;
2638 root 1.23 else if (FP_stristr (localenv.ctenc, "base64") != NULL)
2639 root 1.1 result->uudet = B64ENCODED;
2640 root 1.23 else if (FP_stristr (localenv.ctenc, "x-uue") != NULL) {
2641 root 1.2 result->uudet = UU_ENCODED;
2642 root 1.4 result->begin = result->end = 1;
2643     }
2644 root 1.23 else if (FP_stristr (localenv.ctenc, "x-yenc") != NULL) {
2645 root 1.4 result->uudet = YENC_ENCODED;
2646     result->begin = result->end = 1;
2647     }
2648 root 1.23 else if (FP_stristr (localenv.ctenc, "7bit") != NULL ||
2649     FP_stristr (localenv.ctenc, "8bit") != NULL)
2650 root 1.2 result->uudet = PT_ENCODED;
2651 root 1.23 else if (FP_stristr (localenv.ctype, "multipart") != NULL ||
2652     FP_stristr (localenv.ctype, "message") != NULL)
2653 root 1.1 result->uudet = PT_ENCODED;
2654 root 1.2
2655     /*
2656     * If we're switched to MIME-only mode, handle as text
2657     */
2658    
2659     if (uu_more_mime >= 2 && !result->uudet) {
2660     result->uudet = PT_ENCODED;
2661     }
2662 root 1.1 }
2663     else {
2664     memset (&localenv, 0, sizeof (headers));
2665     }
2666    
2667     /*
2668     * If this is Quoted-Printable or Plain Text, just try looking
2669     * for the next message header. If uu_fast_scanning, and the
2670     * encoding is known, there's no need to look below. Otherwise,
2671     * we check the type of encoding first.
2672     * The encoding type is determined on the first part; in all
2673     * others, we also don't read on.
2674     * If we have a partial multipart message, scan for headers, but
2675     * do not react on standard MIME headers, as they are probably
2676     * from the subparts. However, we're stuck if there's an embedded
2677     * message/rfc822 :-(
2678     * If it is a "trivial" (non-embedded) message/rfc822, skip over
2679     * the message header and then start looking for the next header.
2680     */
2681     if (uu_fast_scanning && (result->uudet!=0||sstate.envelope.partno!=1)) {
2682     /* do nothing */
2683     res = 0;
2684     }
2685     else if (result->uudet != 0) {
2686     hcount = lcount = 0;
2687     prevpos = ftell (datei);
2688    
2689 root 1.23 if (FP_stristr (localenv.ctype, "message") != NULL &&
2690     FP_stristr (localenv.ctype, "rfc822") != NULL) {
2691 root 1.1 /*
2692     * skip over empty lines and local header
2693     */
2694     preheaders = ftell (datei);
2695 root 1.23 while (!FP_feof (datei)) {
2696     if (FP_fgets (line, 1024, datei) == NULL)
2697 root 1.1 break;
2698     if (!IsLineEmpty (line)) {
2699     break;
2700     }
2701     }
2702    
2703 root 1.23 while (!FP_feof (datei) && !IsLineEmpty (line)) {
2704 root 1.1 if (IsKnownHeader (line))
2705     hcount++;
2706     lcount++;
2707     if (lcount > WAITHEADER && hcount < hlcount.afternl)
2708     break;
2709    
2710 root 1.23 if (FP_fgets (line, 1024, datei) == NULL)
2711 root 1.1 break;
2712     }
2713     if (hcount < hlcount.afternl)
2714     fseek (datei, preheaders, SEEK_SET);
2715     hcount = lcount = 0;
2716     }
2717    
2718     /*
2719     * look for next header
2720     */
2721    
2722 root 1.23 while (!FP_feof (datei)) {
2723     if (FP_fgets (line, 1024, datei) == NULL)
2724 root 1.1 break;
2725     if (UUBUSYPOLL(ftell(datei),progress.fsize)) SPCANCEL();
2726     if (ferror (datei))
2727     break;
2728    
2729     if ((vflag = IsKnownHeader (line))) {
2730     (void) ScanHeaderLine (datei, line);
2731    
2732     if (result->uudet != PT_ENCODED || vflag == 1) {
2733     if (hcount == 0)
2734     preheaders = prevpos;
2735     hcount++;
2736     lcount++;
2737     if (hcount >= hlcount.restart) {
2738     /*
2739     * Hey, a new header starts here
2740     */
2741     fseek (datei, preheaders, SEEK_SET);
2742     prevpos = preheaders;
2743     break;
2744     }
2745     }
2746     }
2747     else if (lcount > WAITHEADER) {
2748     hcount = 0;
2749     lcount = 0;
2750     }
2751     else if (hcount) {
2752     lcount++;
2753     }
2754     prevpos = ftell (datei);
2755     }
2756     res = 1;
2757     }
2758     else {
2759     /*
2760     * Otherwise, let's see what we can find ourself. No
2761     * boundary (NULL) but MIME, and respect new headers.
2762     */
2763     if ((res = ScanData (datei, fname, errcode, NULL, 1, 1, result)) == -1) {
2764     /* oops, something went wrong */
2765     sstate.isfolder = 0;
2766     sstate.ismime = 0;
2767     UUkillfread (result);
2768     UUkillheaders (&localenv);
2769     return NULL;
2770     }
2771     if (result->uudet == 0 && uu_handletext)
2772     result->uudet = PT_ENCODED;
2773    
2774     prevpos = ftell (datei);
2775     }
2776     /*
2777     * produce result
2778     */
2779     if (localenv.fname) {
2780 root 1.23 FP_free (result->filename);
2781     if ((result->filename = FP_strdup (localenv.fname)) == NULL)
2782 root 1.1 *errcode = UURET_NOMEM;
2783     }
2784     else if (sstate.envelope.fname) {
2785 root 1.23 FP_free (result->filename);
2786     if ((result->filename = FP_strdup (sstate.envelope.fname)) == NULL)
2787 root 1.1 *errcode = UURET_NOMEM;
2788     }
2789     else if ((result->uudet==QP_ENCODED || result->uudet==PT_ENCODED) &&
2790     result->filename == NULL) {
2791     sprintf (line, "%04d.txt", ++mimseqno);
2792 root 1.23 if ((result->filename = FP_strdup (line)) == NULL)
2793 root 1.1 *errcode = UURET_NOMEM;
2794     }
2795     else {
2796     /* assign a filename lateron */
2797     }
2798     if (result->subject == NULL) {
2799     if (sstate.envelope.subject)
2800 root 1.23 result->subject = FP_strdup (sstate.envelope.subject);
2801 root 1.1 }
2802     result->partno = sstate.envelope.partno;
2803     result->maxpno = sstate.envelope.numparts;
2804 root 1.22 result->flags = FL_PARTIAL |
2805 root 1.1 ((res==1 || uu_fast_scanning) ? FL_PROPER : 0) |
2806     ((uu_fast_scanning) ? FL_TOEND : 0);
2807 root 1.23 result->mimeid = FP_strdup (sstate.envelope.mimeid);
2808 root 1.4 if (result->partno == 1)
2809     result->begin = 1;
2810 root 1.1
2811     if (uu_fast_scanning)
2812     result->length = progress.fsize - result->startpos;
2813     else
2814     result->length = prevpos - result->startpos;
2815    
2816     if (result->sfname == NULL)
2817 root 1.23 result->sfname = FP_strdup (fname);
2818 root 1.1
2819     if (result->mode == 0)
2820     result->mode = 0644;
2821    
2822     /*
2823     * the other fields should already be set appropriately
2824     */
2825    
2826     if (res == 1) {
2827     /*
2828     * new headers found
2829     */
2830     sstate.isfolder = 1;
2831     sstate.ismime = 0;
2832     sstate.mimestate = MS_HEADERS;
2833 root 1.22
2834 root 1.1 UUkillheaders (&sstate.envelope);
2835     memset (&sstate.envelope, 0, sizeof (headers));
2836     }
2837     else {
2838     /*
2839     * otherwise, this can't be a mail folder
2840     */
2841     sstate.isfolder = 0;
2842     sstate.ismime = 0;
2843     }
2844     /*
2845     * kill local envelope
2846     */
2847     UUkillheaders (&localenv);
2848     return result;
2849     }
2850    
2851     /*
2852 root 1.2 * If this is a MIME body, honor a Content-Type different than
2853 root 1.1 * text/plain or a proper Content-Transfer-Encoding.
2854 root 1.2 * We also go in here if we have an assigned filename - this means
2855     * that we've had a Content-Disposition field, and we should probably
2856     * decode a plain-text segment with a filename.
2857 root 1.1 */
2858 root 1.4
2859 root 1.1 if (sstate.isfolder && sstate.ismime &&
2860     sstate.mimestate == MS_BODY &&
2861 root 1.23 (FP_stristr (sstate.envelope.ctenc, "quoted-printable") != NULL ||
2862     FP_stristr (sstate.envelope.ctenc, "base64") != NULL ||
2863     FP_stristr (sstate.envelope.ctenc, "x-uue") != NULL ||
2864     FP_stristr (sstate.envelope.ctenc, "x-yenc") != NULL ||
2865     FP_stristr (sstate.envelope.ctype, "message") != NULL ||
2866 root 1.2 sstate.envelope.fname != NULL)) {
2867 root 1.1
2868     if (sstate.envelope.subject)
2869 root 1.23 result->subject = FP_strdup (sstate.envelope.subject);
2870 root 1.1 if (sstate.envelope.from)
2871 root 1.23 result->origin = FP_strdup (sstate.envelope.from);
2872 root 1.1
2873     if (sstate.envelope.ctype)
2874 root 1.23 result->mimetype = FP_strdup (sstate.envelope.ctype);
2875 root 1.1 else
2876 root 1.23 result->mimetype = FP_strdup ("text/plain");
2877 root 1.1
2878 root 1.23 if (FP_stristr (sstate.envelope.ctenc, "quoted-printable") != NULL)
2879 root 1.1 result->uudet = QP_ENCODED;
2880 root 1.23 else if (FP_stristr (sstate.envelope.ctenc, "base64") != NULL)
2881 root 1.1 result->uudet = B64ENCODED;
2882 root 1.23 else if (FP_stristr (sstate.envelope.ctenc, "x-uue") != NULL) {
2883 root 1.2 result->uudet = UU_ENCODED;
2884 root 1.4 result->begin = result->end = 1;
2885     }
2886 root 1.23 else if (FP_stristr (sstate.envelope.ctenc, "x-yenc") != NULL) {
2887 root 1.4 result->uudet = YENC_ENCODED;
2888     }
2889 root 1.23 else if (FP_stristr (sstate.envelope.ctenc, "7bit") != NULL ||
2890     FP_stristr (sstate.envelope.ctenc, "8bit") != NULL)
2891 root 1.2 result->uudet = PT_ENCODED;
2892 root 1.23 else if (FP_stristr (sstate.envelope.ctype, "multipart") != NULL ||
2893     FP_stristr (sstate.envelope.ctype, "message") != NULL ||
2894 root 1.2 sstate.envelope.fname != NULL)
2895     result->uudet = PT_ENCODED;
2896    
2897     /*
2898     * If we're switched to MIME-only mode, handle as text
2899     */
2900    
2901     if (uu_more_mime >= 2 && !result->uudet) {
2902 root 1.1 result->uudet = PT_ENCODED;
2903 root 1.2 }
2904    
2905     result->startpos = prevpos = ftell (datei);
2906 root 1.1
2907     /*
2908     * If this is Quoted-Printable or Plain Text, just try looking
2909     * for the next message header. If uu_fast_scanning, we know
2910     * there won't be more headers.
2911 root 1.2 * If it is a "trivial" (non-embedded) message/rfc822, skip over
2912     * the message header and then start looking for the next header.
2913 root 1.1 */
2914     if (result->uudet != 0 && uu_fast_scanning) {
2915     /* do nothing */
2916     res = 0;
2917     }
2918     else if (result->uudet != 0) {
2919     hcount = lcount = 0;
2920 root 1.2 prevpos = ftell (datei);
2921    
2922 root 1.23 if (FP_stristr (sstate.envelope.ctype, "message") != NULL &&
2923     FP_stristr (sstate.envelope.ctype, "rfc822") != NULL) {
2924 root 1.2 /*
2925     * skip over empty lines and local header
2926     */
2927     preheaders = ftell (datei);
2928 root 1.23 while (!FP_feof (datei)) {
2929     if (FP_fgets (line, 1024, datei) == NULL)
2930 root 1.2 break;
2931     if (!IsLineEmpty (line)) {
2932     break;
2933     }
2934     }
2935    
2936 root 1.23 while (!FP_feof (datei) && !IsLineEmpty (line)) {
2937 root 1.2 if (IsKnownHeader (line))
2938     hcount++;
2939     lcount++;
2940     if (lcount > WAITHEADER && hcount < hlcount.afternl)
2941     break;
2942    
2943 root 1.23 if (FP_fgets (line, 1024, datei) == NULL)
2944 root 1.2 break;
2945     }
2946     if (hcount < hlcount.afternl)
2947     fseek (datei, preheaders, SEEK_SET);
2948     hcount = lcount = 0;
2949     }
2950    
2951     /*
2952     * look for next header
2953     */
2954 root 1.1
2955 root 1.23 while (!FP_feof (datei)) {
2956     if (FP_fgets (line, 1024, datei) == NULL)
2957 root 1.1 break;
2958     if (UUBUSYPOLL(ftell(datei),progress.fsize)) SPCANCEL();
2959     if (ferror (datei))
2960     break;
2961    
2962     if (IsKnownHeader (line)) {
2963     (void) ScanHeaderLine (datei, line);
2964     if (hcount == 0)
2965     preheaders = prevpos;
2966     hcount++;
2967     lcount++;
2968     if (hcount >= hlcount.restart) {
2969     /*
2970     * Hey, a new header starts here
2971     */
2972     fseek (datei, preheaders, SEEK_SET);
2973     prevpos = preheaders;
2974     break;
2975     }
2976     }
2977     else if (lcount > WAITHEADER) {
2978     hcount = 0;
2979     lcount = 0;
2980     }
2981     else if (hcount) {
2982     lcount++;
2983     }
2984     prevpos = ftell (datei);
2985     }
2986     res = 1;
2987     }
2988     else {
2989     /*
2990     * Otherwise, let's see what we can find ourself. No
2991     * boundary (NULL) but MIME, and respect new headers.
2992     */
2993     if ((res = ScanData (datei, fname, errcode, NULL, 1, 1, result)) == -1) {
2994     /* oops, something went wrong */
2995     sstate.isfolder = 0;
2996     sstate.ismime = 0;
2997     UUkillfread (result);
2998     return NULL;
2999     }
3000     if (result->uudet == 0 && uu_handletext) {
3001     result->startpos = before; /* display headers */
3002     result->uudet = PT_ENCODED;
3003     }
3004    
3005     prevpos = ftell (datei);
3006     }
3007     /*
3008     * produce result
3009     */
3010     if (sstate.envelope.fname) {
3011 root 1.23 FP_free (result->filename);
3012     if ((result->filename = FP_strdup (sstate.envelope.fname)) == NULL)
3013 root 1.1 *errcode = UURET_NOMEM;
3014     }
3015     else if ((result->uudet==QP_ENCODED||result->uudet==PT_ENCODED) &&
3016     result->filename == NULL) {
3017     sprintf (line, "%04d.txt", ++mimseqno);
3018 root 1.23 if ((result->filename = FP_strdup (line)) == NULL)
3019 root 1.1 *errcode = UURET_NOMEM;
3020     }
3021     else {
3022     /* assign a filename lateron */
3023     }
3024     if (result->subject == NULL) {
3025     if (sstate.envelope.subject)
3026 root 1.23 result->subject = FP_strdup (sstate.envelope.subject);
3027 root 1.1 }
3028     result->flags = ((res==1||uu_fast_scanning)?FL_PROPER:0) |
3029     ((uu_fast_scanning) ? FL_TOEND : 0);
3030 root 1.23 result->mimeid = FP_strdup (sstate.envelope.mimeid);
3031 root 1.1
3032     if (uu_fast_scanning)
3033     result->length = progress.fsize - result->startpos;
3034     else
3035     result->length = prevpos - result->startpos;
3036    
3037     if (result->sfname == NULL)
3038 root 1.23 result->sfname = FP_strdup (fname);
3039 root 1.1
3040     if (result->mode == 0)
3041     result->mode = 0644;
3042    
3043     /*
3044     * the other fields should already be set appropriately
3045     */
3046    
3047     if (res == 1) {
3048     /*
3049     * new headers found
3050     */
3051     sstate.isfolder = 1;
3052     sstate.ismime = 0;
3053     sstate.mimestate = MS_HEADERS;
3054    
3055     UUkillheaders (&sstate.envelope);
3056     memset (&sstate.envelope, 0, sizeof (headers));
3057     }
3058     else {
3059     /*
3060     * otherwise, this can't be a mail folder
3061     */
3062     sstate.isfolder = 0;
3063     sstate.ismime = 0;
3064     }
3065    
3066     return result;
3067     }
3068    
3069     /*
3070     * Some files have reduced headers, and what should be a multipart
3071     * message is missing the proper Content-Type. If the first thing
3072     * we find after a couple of empty lines is a boundary, try it!
3073     * But make sure that this is indeed intended as being a boundary.
3074     *
3075     * Only accept it if there was indeed no Content-Type header line
3076     * and if the following line is a proper Content-Type header. BTW,
3077     * we know that sstate.envelope.boundary is NULL, or we wouldn't
3078     * be here!
3079     */
3080 root 1.2
3081 root 1.23 if ((!sstate.envelope.ctype || FP_stristr (sstate.envelope.ctype, "multipart"))
3082 root 1.12 && !uu_more_mime) {
3083 root 1.1 prevpos = ftell (datei);
3084 root 1.23 while (!FP_feof (datei)) {
3085     if (FP_fgets (line, 1024, datei) == NULL)
3086 root 1.1 break;
3087     if (UUBUSYPOLL(ftell(datei),progress.fsize)) SPCANCEL();
3088     if (!IsLineEmpty (line))
3089     break;
3090     }
3091     if (line[0] == '-' && line[1] == '-' &&
3092 root 1.23 !IsLineEmpty (line+2) && !FP_feof (datei)) {
3093     ptr1 = FP_strrstr (line+2, "--");
3094 root 1.1 ptr2 = ScanHeaderLine (datei, NULL);
3095 root 1.16 if ((ptr1 == NULL || ptr1[2]) &&
3096 root 1.24 ptr2 && FP_strnicmp_fast (ptr2, "Content-", 8) == 0) {
3097 root 1.1 /*
3098     * hmm, okay, let's do it!
3099     */
3100     sstate.isfolder = 1;
3101     sstate.ismime = 1;
3102     sstate.mimestate = MS_PREAMBLE;
3103     /*
3104     * get boundary
3105     */
3106     ptr1 = line+2;
3107     while (*ptr1 && !isspace(*ptr1))
3108     ptr1++;
3109     *ptr1 = '\0';
3110 root 1.4
3111 root 1.23 sstate.envelope.mimevers = FP_strdup ("1.0");
3112     sstate.envelope.boundary = FP_strdup (line+2);
3113 root 1.22
3114 root 1.1 /*
3115     * need restart
3116     */
3117 root 1.22
3118 root 1.1 fseek (datei, prevpos, SEEK_SET);
3119 root 1.22
3120 root 1.23 FP_free (result);
3121 root 1.1 return NULL;
3122     }
3123     }
3124     fseek (datei, prevpos, SEEK_SET);
3125     }
3126    
3127     /*
3128     * Hmm, we're not in a ''special'' state, so it's more or less
3129     * Freestyle time. Anyway, if this seems to be a Mime message,
3130     * don't allow the minimal Base64 handling.
3131     */
3132    
3133     if (sstate.envelope.subject)
3134 root 1.23 result->subject = FP_strdup (sstate.envelope.subject);
3135 root 1.12
3136 root 1.1 if (sstate.envelope.from)
3137 root 1.23 result->origin = FP_strdup (sstate.envelope.from);
3138 root 1.1
3139     if (sstate.envelope.ctype)
3140 root 1.23 result->mimetype = FP_strdup (sstate.envelope.ctype);
3141 root 1.22
3142     if ((res=ScanData (datei, fname, errcode, NULL,
3143 root 1.1 sstate.ismime, 1, result))==-1) {
3144     /* oops, something went wrong */
3145     sstate.isfolder = 0;
3146     sstate.ismime = 0;
3147     UUkillfread (result);
3148     return NULL;
3149     }
3150 root 1.4
3151 root 1.1 /*
3152     * produce result
3153     */
3154 root 1.4
3155 root 1.1 if (result->uudet == 0 && uu_handletext) {
3156     result->startpos = before; /* display headers */
3157     result->uudet = PT_ENCODED;
3158     result->partno = 1;
3159     }
3160    
3161 root 1.4 if (result->uudet == YENC_ENCODED && result->filename != NULL) {
3162     /*
3163     * prevent replacing the filename found on the =ybegin line
3164     */
3165     }
3166     else if (sstate.envelope.fname) {
3167 root 1.23 FP_free (result->filename);
3168     if ((result->filename = FP_strdup (sstate.envelope.fname)) == NULL)
3169 root 1.1 *errcode = UURET_NOMEM;
3170     }
3171     else if ((result->uudet==QP_ENCODED||result->uudet==PT_ENCODED) &&
3172     result->filename == NULL) {
3173     sprintf (line, "%04d.txt", ++mimseqno);
3174 root 1.23 if ((result->filename = FP_strdup (line)) == NULL)
3175 root 1.1 *errcode = UURET_NOMEM;
3176     }
3177     else {
3178     /* assign a filename lateron */
3179     }
3180 root 1.4
3181 root 1.1 if (result->subject == NULL) {
3182     if (sstate.envelope.subject)
3183 root 1.23 result->subject = FP_strdup (sstate.envelope.subject);
3184 root 1.1 }
3185    
3186     result->flags = (result->uudet==PT_ENCODED)?FL_SINGLE:0;
3187 root 1.23 result->mimeid = FP_strdup (sstate.envelope.mimeid);
3188 root 1.1 result->length = ftell (datei) - result->startpos;
3189    
3190     if (result->mode == 0)
3191     result->mode = 0644;
3192    
3193     if (result->sfname == NULL)
3194 root 1.23 result->sfname = FP_strdup (fname);
3195 root 1.1
3196     if (res == 1) {
3197     /*
3198     * new headers found
3199     */
3200     sstate.isfolder = 1;
3201     sstate.ismime = 0;
3202     sstate.mimestate = MS_HEADERS;
3203    
3204     UUkillheaders (&sstate.envelope);
3205     memset (&sstate.envelope, 0, sizeof (headers));
3206     }
3207     else {
3208     /*
3209     * otherwise, this can't be a mail folder
3210     */
3211     sstate.isfolder = 0;
3212     sstate.ismime = 0;
3213     }
3214    
3215     return result;
3216    
3217     /*
3218     * Emergency handling. Set errcode before jumping here.
3219     */
3220     ScanPartEmergency:
3221     UUkillfread (result);
3222     UUkillheaders (&localenv);
3223    
3224     while (mssdepth) {
3225     mssdepth--;
3226     UUkillheaders (&(multistack[mssdepth].envelope));
3227 root 1.23 FP_free (multistack[mssdepth].source);
3228 root 1.1 }
3229    
3230     return NULL;
3231     }
3232