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