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