ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/Convert-UUlib/uulib/uuscan.c
Revision: 1.27
Committed: Sat Sep 24 06:02:04 2022 UTC (20 months, 1 week ago) by root
Content type: text/plain
Branch: MAIN
Changes since 1.26: +0 -2 lines
Log Message:
*** empty log message ***

File Contents

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