ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/Convert-UUlib/uulib/uuscan.c
Revision: 1.3.2.5
Committed: Sun Apr 18 19:55:46 2004 UTC (20 years, 1 month ago) by root
Content type: text/plain
Branch: UUDEVIEW
CVS Tags: UUDEVIEW-0-5-20
Changes since 1.3.2.4: +7 -5 lines
Log Message:
*** empty log message ***

File Contents

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