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