ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/Convert-UUlib/uulib/uucheck.c
Revision: 1.35
Committed: Sat Sep 24 07:01:44 2022 UTC (20 months, 1 week ago) by root
Content type: text/plain
Branch: MAIN
Changes since 1.34: +2 -1 lines
Log Message:
*** empty log message ***

File Contents

# User Rev Content
1 root 1.1 /*
2     * This file is part of uudeview, the simple and friendly multi-part multi-
3 root 1.2 * file uudecoder program (c) 1994-2001 by Frank Pilhofer. The author may
4     * be contacted at fp@fpx.de
5 root 1.1 *
6     * This program is free software; you can redistribute it and/or modify
7     * it under the terms of the GNU General Public License as published by
8     * the Free Software Foundation; either version 2 of the License, or
9     * (at your option) any later version.
10     *
11     * This program is distributed in the hope that it will be useful,
12     * but WITHOUT ANY WARRANTY; without even the implied warranty of
13     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14     * GNU General Public License for more details.
15     */
16    
17     #ifdef HAVE_CONFIG_H
18     #include "config.h"
19     #endif
20    
21     #ifdef SYSTEM_WINDLL
22     #include <windows.h>
23     #endif
24     #ifdef SYSTEM_OS2
25     #include <os2.h>
26     #endif
27    
28     /*
29     * uucheck.c
30     *
31     * Various checking and processing of one input part
32     **/
33    
34     #include <stdio.h>
35     #include <ctype.h>
36     #include <stdlib.h>
37     #include <string.h>
38 root 1.33
39 root 1.1 #ifdef HAVE_UNISTD_H
40     #include <unistd.h>
41     #endif
42    
43 root 1.2 #include <uudeview.h>
44 root 1.1 #include <uuint.h>
45     #include <fptools.h>
46     #include <uustring.h>
47    
48     /*
49     * Arbitrary number. This is the maximum number of part numbers we
50     * store for our have-parts and missing-parts lists
51     */
52    
53     #define MAXPLIST 256
54    
55    
56     /*
57     * forward declarations of local functions
58     */
59    
60     static char * UUGetFileName (char *, char *, char *);
61     static int UUGetPartNo (char *, char **, char **);
62    
63     /*
64     * State of Scanner function and PreProcessPart
65     */
66    
67     int lastvalid, lastenc, nofnum;
68     char *uucheck_lastname;
69     char *uucheck_tempname;
70     static int lastpart = 0;
71     static char *nofname = "UNKNOWN";
72    
73     /*
74     * special characters we allow an unquoted filename to have
75     */
76    
77     static char *fnchars = "._-~!";
78    
79     /*
80     * Policy for extracting a part number from the subject line.
81     * usually, look for part numbers in () brackets first, then in []
82     */
83    
84     static char *brackchr[] = {
85     "()[]", "[]()"
86     };
87    
88     /*
89     * Extract a filename from the subject line. We need anything to identify
90 root 1.20 * the name of the program for sorting. If a nice filename cannot be found,
91 root 1.1 * the subject line itself is used
92     * ptonum is, if not NULL, a pointer to the part number in the subject line,
93     * so that it won't be used as filename.
94     **/
95     static char *
96     UUGetFileName (char *subject, char *ptonum, char *ptonend)
97     {
98     char *ptr = subject, *iter, *result, *part;
99     int count, length=0, alflag=0;
100    
101     /*
102     * If this file has no subject line, assume it is the next part of the
103     * previous file (this is done in UUPreProcessPart)
104     **/
105    
106     if (subject == NULL)
107     return NULL;
108    
109     /*
110     * If the subject starts with 'Re', it is ignored
111     * REPosts or RETries are not ignored!
112     **/
113    
114     if (uu_ignreply &&
115     (subject[0] == 'R' || subject[0] == 'r') &&
116     (subject[1] == 'E' || subject[1] == 'e') &&
117     (subject[2] == ':' || subject[2] == ' ')) {
118 root 1.6 return uu_FileNameCallback ? uu_FileNameCallback(uu_FNCBArg, subject, NULL) : NULL;
119 root 1.1 }
120    
121     /*
122     * Ignore a "Repost" prefix of the subject line. We don't want to get
123     * a file named "Repost" :-)
124     **/
125    
126 root 1.22 if (FP_strnicmp (subject, "repost", 6) == 0)
127 root 1.1 subject += 6;
128 root 1.22 if (FP_strnicmp (subject, "re:", 3) == 0)
129 root 1.1 subject += 3;
130    
131     while (*subject == ' ' || *subject == ':') subject++;
132    
133 root 1.22 part = FP_stristr (subject, "part");
134 root 1.1 if (part == subject) {
135     subject += 4;
136     while (*subject == ' ') subject++;
137     }
138    
139     /*
140     * If the file was encoded by uuenview, then the filename is enclosed
141     * in [brackets]. But check what's inside these bracket's, try not to
142     * fall for something other than a filename
143     */
144    
145     ptr = subject;
146     while ((iter = strchr (ptr, '[')) != NULL) {
147     if (strchr (iter, ']') == NULL) {
148     ptr = iter + 1;
149     continue;
150     }
151     iter++;
152     while (isspace (*iter))
153     iter++;
154     count = length = alflag = 0;
155 root 1.20 while (iter[count] &&
156 root 1.1 (isalnum (iter[count]) || strchr (fnchars, iter[count])!=NULL)) {
157     if (isalpha (iter[count]))
158     alflag++;
159     count++;
160     }
161     if (count<4 || alflag==0) {
162     ptr = iter + 1;
163     continue;
164     }
165     length = count;
166     while (isspace (iter[count]))
167     count++;
168     if (iter[count] == ']') {
169     ptr = iter;
170     break;
171     }
172     length = 0;
173     ptr = iter + 1;
174     }
175    
176     /*
177     * new filename detection routine, fists mostly for files by ftp-by-email
178     * servers that create subject lines with ftp.host.address:/full/path/file
179     * on them. We look for slashes and take the filename from after the last
180     * one ... or at least we try to.
181     */
182    
183     if (length == 0) {
184     ptr = subject;
185     while ((iter = strchr (ptr, '/')) != NULL) {
186     if (iter >= ptonum && iter <= ptonend) {
187     ptr = iter + 1;
188     continue;
189     }
190     count = length = 0;
191     iter++;
192     while (iter[count] &&
193     (isalnum(iter[count])||strchr(fnchars, iter[count])!=NULL))
194     count++;
195     if (iter[count] == ' ' && length > 4) {
196     length = count;
197     break;
198     }
199     ptr = iter + ((count)?count:1);
200     }
201     }
202    
203     /*
204     * Look for two alphanumeric strings separated by a '.'
205     * (That's most likely a filename)
206     **/
207    
208     if (length == 0) {
209     ptr = subject;
210 root 1.3 /* #warning another experimental change */
211     /*while (*ptr && *ptr != 0x0a && *ptr != 0x0d && ptr != part) {*/
212     while (*ptr && *ptr != 0x0a && *ptr != 0x0d) {
213 root 1.1 iter = ptr;
214     count = length = alflag = 0;
215 root 1.20
216 root 1.22 if (FP_strnicmp (ptr, "ftp", 3) == 0) {
217 root 1.1 /* hey, that's an ftp address */
218     while (isalpha (*ptr) || isdigit (*ptr) || *ptr == '.')
219     ptr++;
220     continue;
221     }
222 root 1.20
223 root 1.1 while ((isalnum(*iter)||strchr(fnchars, *iter)!=NULL||
224     *iter=='/') && *iter && iter != ptonum && *iter != '.') {
225     if (isalpha (*iter))
226     alflag = 1;
227 root 1.20
228 root 1.1 count++; iter++;
229     }
230     if (*iter == '\0' || iter == ptonum) {
231     if (iter == ptonum)
232     ptr = ptonend;
233     else
234     ptr = iter;
235    
236     length = 0;
237     continue;
238     }
239 root 1.3
240     /* #warning multi-part change experimental, make pluggable */
241     /* if (*iter++ != '.' || count > 32 || alflag == 0) { */
242     if (*iter++ != '.' || count > 32) {
243 root 1.1 ptr = iter;
244     length = 0;
245     continue;
246     }
247 root 1.3
248 root 1.9 /* a dot followed by sth. unesthetically doesn't look right */
249     if (*iter < '0') {
250 root 1.3 ptr = iter + 1;
251     length = 0;
252     continue;
253     }
254    
255 root 1.22 if (FP_strnicmp (iter, "edu", 3) == 0 ||
256     FP_strnicmp (iter, "gov", 3) == 0) {
257 root 1.1 /* hey, that's an ftp address */
258     while (isalpha (*iter) || isdigit (*iter) || *iter == '.')
259     iter++;
260     ptr = iter;
261     length = 0;
262     continue;
263     }
264 root 1.20
265 root 1.1 length += count + 1;
266     count = 0;
267 root 1.20
268 root 1.1 while ((isalnum(iter[count])||strchr(fnchars, iter[count])!=NULL||
269     iter[count]=='/') && iter[count] && iter[count] != '.')
270     count++;
271 root 1.20
272 root 1.1 if (iter[count]==':' && iter[count+1]=='/') {
273     /* looks like stuff from a mail server */
274     ptr = iter + 1;
275     length = 0;
276     continue;
277     }
278 root 1.20
279 root 1.1 if (count > 8 || iter == ptonum) {
280     ptr = iter;
281     length = 0;
282     continue;
283     }
284    
285     if (iter[count] != '.') {
286     length += count;
287     break;
288     }
289 root 1.20
290 root 1.1 while (iter[count] &&
291     (isalnum(iter[count])||strchr(fnchars, iter[count])!=NULL||
292     iter[count]=='/'))
293     count++;
294 root 1.20
295 root 1.1 if (iter[count]==':' && iter[count+1]=='/') {
296     /* looks like stuff from a mail server */
297     ptr = iter + 1;
298     length = 0;
299     continue;
300     }
301 root 1.20
302 root 1.1 if (count < 12 && iter != ptonum) {
303     length += count;
304     break;
305     }
306    
307     ptr = iter;
308     length = 0;
309     }
310     }
311    
312     if (length == 0) { /* No filename found, use subject line for ident */
313     ptr = subject;
314    
315     while (*ptr && !isalpha (*ptr))
316     ptr++;
317    
318     while ((isalnum(ptr[length])||strchr(fnchars,ptr[length])!=NULL||
319 root 1.20 ptr[length] == '/') &&
320 root 1.1 ptr[length] && ptr+length!=part && ptr+length!=ptonum)
321     length++;
322    
323     if (length) {
324     if (ptr[length] == '\0' || ptr[length] == 0x0a || ptr[length] == 0x0d) {
325     length--;
326    
327     /*
328     * I used to cut off digits from the end of the string, but
329     * let's try to live without. We want to distinguish
330     * DUTCH951 from DUTCH952
331     *
332     * while ((ptr[length] == ' ' || isdigit (ptr[length])) && length > 0)
333     * length--;
334     */
335     }
336     else {
337     length--;
338    
339     while (ptr[length] == ' ' && length > 0)
340     length--;
341     }
342     length++;
343     }
344     }
345    
346     if (length == 0) { /* Still found nothing? We need *something*! */
347     ptr = nofname;
348     length = strlen (nofname);
349     }
350    
351     if ((result = (char *) malloc (length + 1)) == NULL) {
352 root 1.34 UUMessage (UUMSG_ERROR, uustring (S_OUT_OF_MEMORY), length+1);
353 root 1.1 return NULL;
354     }
355 root 1.20
356 root 1.1 memcpy (result, ptr, length);
357     result[length] = '\0';
358 root 1.20
359 root 1.6 return uu_FileNameCallback ? uu_FileNameCallback(uu_FNCBArg, subject, result) : result;
360 root 1.1 }
361    
362     /*
363     * Extract the Part Number from the subject line.
364     * We look first for numbers in (#/#)'s, then for numbers in [#/#]'s
365     * and then for digits that are not part of a string.
366     * If we cannot find anything, assume it is the next part of the
367     * previous file.
368     * If we find a part number, we put a pointer to it in *where. This is
369     * done so that the UUGetFileName function doesn't accidentally use the
370     * part number as the file name. *whend points to the end of this part
371     * number.
372     **/
373    
374     static int
375     UUGetPartNo (char *subject, char **where, char **whend)
376     {
377     char *ptr = subject, *iter, *delim, bdel[2]=" ";
378     int count, length=0, bpc;
379    
380     *where = NULL; bdel[0] = ' ';
381     *whend = NULL; bdel[1] = '\0';
382    
383     iter = NULL;
384     delim = "";
385    
386     if (subject == NULL)
387     return -1;
388    
389     if (uu_ignreply &&
390     (subject[0] == 'R' || subject[0] == 'r') && /* Ignore replies, but not */
391     (subject[1] == 'E' || subject[1] == 'e') && /* reposts */
392     (subject[2] == ':' || subject[2] == ' '))
393     return -2;
394    
395     /*
396     * First try numbers in () or [] (or vice versa, according to bracket
397     * policy)
398 root 1.7 * For multiple occurences, give priority to the bracket with a slash
399     * or the last one, whichever is "found" first.
400 root 1.1 */
401    
402     for (bpc=0, length=0; brackchr[uu_bracket_policy][bpc]; bpc+=2) {
403 root 1.7 iter = subject;
404     length = 0;
405     while ((iter = strchr (iter, brackchr[uu_bracket_policy][bpc])) != NULL) {
406     int plength;
407    
408     count = 0; iter++;
409 root 1.1
410     while (*iter == ' ' || *iter == '#')
411     iter++;
412    
413     if (!isdigit (*iter)) {
414     continue;
415     }
416     while (isdigit (iter[count]))
417     count++;
418 root 1.20
419 root 1.7 if (iter[count] == '\0') {
420     iter += count;
421 root 1.1 break;
422     }
423 root 1.7
424     plength = count;
425    
426 root 1.1 if (iter[count] == brackchr[uu_bracket_policy][bpc+1]) {
427     *where = iter;
428     bdel[0] = brackchr[uu_bracket_policy][bpc+1];
429     delim = bdel;
430 root 1.7 length = plength;
431     continue;
432 root 1.1 }
433 root 1.7
434 root 1.1 while (iter[count] == ' ' || iter[count] == '#' ||
435     iter[count] == '/' || iter[count] == '\\') count++;
436 root 1.20
437 root 1.22 if (FP_strnicmp (iter + count, "of", 2) == 0)
438 root 1.1 count += 2;
439 root 1.20
440 root 1.1 while (iter[count] == ' ') count++;
441     while (isdigit (iter[count])) count++;
442     while (iter[count] == ' ') count++;
443 root 1.20
444 root 1.1 if (iter[count] == brackchr[uu_bracket_policy][bpc+1]) {
445     *where = iter;
446     bdel[0] = brackchr[uu_bracket_policy][bpc+1];
447     delim = bdel;
448 root 1.7 length = plength;
449 root 1.1 break;
450     }
451     }
452     if (length)
453 root 1.7 {
454     iter = *where; /* strange control flow, but less changes == less hassle */
455     break;
456     }
457 root 1.1 }
458    
459     /*
460     * look for the string "part " followed by a number
461     */
462    
463     if (length == 0) {
464 root 1.22 if ((iter = FP_stristr (subject, "part ")) != NULL) {
465 root 1.1 iter += 5;
466    
467     while (isspace (*iter) || *iter == '.' || *iter == '-')
468     iter++;
469    
470     while (isdigit (iter[length]))
471     length++;
472    
473     if (length == 0) {
474 root 1.22 if (FP_strnicmp (iter, "one", 3) == 0) length = 1;
475     else if (FP_strnicmp (iter, "two", 3) == 0) length = 2;
476     else if (FP_strnicmp (iter, "three", 5) == 0) length = 3;
477     else if (FP_strnicmp (iter, "four", 4) == 0) length = 4;
478     else if (FP_strnicmp (iter, "five", 4) == 0) length = 5;
479     else if (FP_strnicmp (iter, "six", 3) == 0) length = 6;
480     else if (FP_strnicmp (iter, "seven", 5) == 0) length = 7;
481     else if (FP_strnicmp (iter, "eight", 5) == 0) length = 8;
482     else if (FP_strnicmp (iter, "nine", 4) == 0) length = 9;
483     else if (FP_strnicmp (iter, "ten", 3) == 0) length = 10;
484 root 1.1
485     if (length && (*whend = strchr (iter, ' '))) {
486     *where = iter;
487     return length;
488     }
489     else
490     length = 0;
491     }
492     else {
493     *where = iter;
494     delim = "of";
495     }
496     }
497     }
498    
499     /*
500     * look for the string "part" followed by a number
501     */
502    
503     if (length == 0) {
504 root 1.22 if ((iter = FP_stristr (subject, "part")) != NULL) {
505 root 1.1 iter += 4;
506    
507     while (isspace (*iter) || *iter == '.' || *iter == '-')
508     iter++;
509    
510     while (isdigit (iter[length]))
511     length++;
512    
513     if (length == 0) {
514 root 1.22 if (FP_strnicmp (iter, "one", 3) == 0) length = 1;
515     else if (FP_strnicmp (iter, "two", 3) == 0) length = 2;
516     else if (FP_strnicmp (iter, "three", 5) == 0) length = 3;
517     else if (FP_strnicmp (iter, "four", 4) == 0) length = 4;
518     else if (FP_strnicmp (iter, "five", 4) == 0) length = 5;
519     else if (FP_strnicmp (iter, "six", 3) == 0) length = 6;
520     else if (FP_strnicmp (iter, "seven", 5) == 0) length = 7;
521     else if (FP_strnicmp (iter, "eight", 5) == 0) length = 8;
522     else if (FP_strnicmp (iter, "nine", 4) == 0) length = 9;
523     else if (FP_strnicmp (iter, "ten", 3) == 0) length = 10;
524 root 1.1
525     if (length && (*whend = strchr (iter, ' '))) {
526     *where = iter;
527     return length;
528     }
529     else
530     length = 0;
531     }
532     else {
533     *where = iter;
534     delim = "of";
535     }
536     }
537     }
538    
539     /*
540     * look for [0-9]* "of" [0-9]*
541     */
542    
543     if (length == 0) {
544 root 1.22 if ((iter = FP_strirstr (subject, "of")) != NULL) {
545 root 1.1 while (iter>subject && isspace (*(iter-1)))
546     iter--;
547     if (isdigit(*(iter-1))) {
548     while (iter>subject && isdigit (*(iter-1)))
549     iter--;
550     if (!isdigit (*iter) && !isalpha (*iter) && *iter != '.')
551     iter++;
552     ptr = iter;
553    
554     while (isdigit (*ptr)) {
555     ptr++; length++;
556     }
557     *where = iter;
558     delim = "of";
559     }
560     }
561     }
562    
563     /*
564     * look for whitespace-separated (or '/'-separated) digits
565     */
566    
567     if (length == 0) {
568     ptr = subject;
569    
570     while (*ptr && length==0) {
571     while (*ptr && !isdigit (*ptr))
572     ptr++;
573     if (isdigit (*ptr) && (ptr==subject || *ptr==' ' || *ptr=='/')) {
574     while (isdigit (ptr[length]))
575     length++;
576     if (ptr[length]!='\0' && ptr[length]!=' ' && ptr[length]!='/') {
577     ptr += length;
578     length = 0;
579     }
580     else {
581     iter = ptr;
582     bdel[0] = ptr[length];
583     delim = bdel;
584     }
585     }
586     else {
587     while (isdigit (*ptr))
588     ptr++;
589     }
590     }
591     }
592    
593     /*
594     * look for _any_ digits -- currently disabled, because it also fell
595     * for "part numbers" in file names
596     */
597    
598     #if 0
599     if (length == 0) {
600     count = strlen(subject) - 1;
601     ptr = subject;
602 root 1.20
603 root 1.1 while (count > 0) {
604     if (!isdigit(ptr[count])||isalpha(ptr[count+1])||ptr[count+1] == '.') {
605     count--;
606     continue;
607     }
608     length = 0;
609    
610     while (count >= 0 && isdigit (ptr[count])) {
611     count--; length++;
612     }
613 root 1.20 if (count>=0 && ((isalpha (ptr[count]) &&
614 root 1.1 (ptr[count] != 's' || ptr[count+1] != 't') &&
615 root 1.20 (ptr[count] != 'n' || ptr[count+1] != 'd')) ||
616     ptr[count] == '/' || ptr[count] == '.' ||
617 root 1.1 ptr[count] == '-' || ptr[count] == '_')) {
618     length = 0;
619     continue;
620     }
621     count++;
622     iter = ptr + count;
623    
624     if (length > 4) {
625     length = 0;
626     continue;
627     }
628     *where = iter;
629     delim = "of";
630     break;
631     }
632     }
633     #endif
634    
635     /*
636     * look for part numbering as string
637     */
638    
639     if (length == 0) {
640     /*
641     * some people use the strangest things, including spelling mistakes :-)
642     */
643 root 1.22 if ((iter = FP_stristr (subject, "first")) != NULL) length = 1;
644     else if ((iter = FP_stristr (subject, "second")) != NULL) length = 2;
645     else if ((iter = FP_stristr (subject, "third")) != NULL) length = 3;
646     else if ((iter = FP_stristr (subject, "forth")) != NULL) length = 4;
647     else if ((iter = FP_stristr (subject, "fourth")) != NULL) length = 4;
648     else if ((iter = FP_stristr (subject, "fifth")) != NULL) length = 5;
649     else if ((iter = FP_stristr (subject, "sixth")) != NULL) length = 6;
650     else if ((iter = FP_stristr (subject, "seventh")) != NULL) length = 7;
651     else if ((iter = FP_stristr (subject, "eigth")) != NULL) length = 8;
652     else if ((iter = FP_stristr (subject, "eighth")) != NULL) length = 8;
653     else if ((iter = FP_stristr (subject, "nineth")) != NULL) length = 9;
654     else if ((iter = FP_stristr (subject, "ninth")) != NULL) length = 9;
655     else if ((iter = FP_stristr (subject, "tenth")) != NULL) length = 10;
656 root 1.1 else iter = NULL;
657    
658     if (length && iter && (*whend = strchr (iter, ' '))) {
659     *where = iter;
660     return length;
661     }
662     else
663     length = 0;
664     }
665    
666     if (iter == NULL || length == 0) /* should be equivalent */
667     return -1;
668    
669     *where = iter;
670    
671     if (delim && delim[0]) {
672 root 1.22 if ((*whend=FP_stristr (iter, delim)) != NULL && (*whend - *where) < 12) {
673 root 1.1 ptr = (*whend += strlen (delim));
674    
675     while (*ptr == ' ')
676     ptr++;
677    
678     if (isdigit (*ptr)) {
679     *whend = ptr;
680     while (isdigit (**whend))
681     *whend += 1;
682     }
683     }
684     else {
685     *whend = iter + length;
686     }
687     }
688     else {
689     *whend = iter + length;
690     }
691    
692     return atoi (iter);
693     }
694    
695     /*
696     * Obtain and process some information about the data.
697     **/
698    
699     uufile *
700     UUPreProcessPart (fileread *data, int *ret)
701     {
702     char *where, *whend, temp[80], *ptr, *p2;
703     uufile *result;
704    
705     if ((result = (uufile *) malloc (sizeof (uufile))) == NULL) {
706 root 1.34 UUMessage (UUMSG_ERROR, uustring (S_OUT_OF_MEMORY), sizeof (uufile));
707 root 1.1 *ret = UURET_NOMEM;
708     return NULL;
709     }
710     memset (result, 0, sizeof (uufile));
711    
712     if (data->partno) {
713     where = whend = NULL;
714     result->partno = data->partno;
715     }
716     else if (uu_dumbness) {
717     result->partno = -1;
718     where = whend = NULL;
719     }
720     else if ((result->partno=UUGetPartNo(data->subject,&where,&whend)) == -2) {
721     *ret = UURET_NODATA;
722     UUkillfile (result);
723     return NULL;
724     }
725    
726     if (data->filename != NULL) {
727 root 1.22 if ((result->filename = FP_strdup (data->filename)) == NULL) {
728 root 1.34 UUMessage (UUMSG_ERROR, uustring (S_OUT_OF_MEMORY), strlen (data->filename)+1);
729 root 1.1 *ret = UURET_NOMEM;
730     UUkillfile (result);
731     return NULL;
732     }
733     }
734     else
735     result->filename = NULL;
736    
737     if (uu_dumbness <= 1)
738 root 1.32 result->subfname = data->uudet == YENC_ENCODED
739     ? FP_strdup (data->filename)
740     : UUGetFileName (data->subject, where, whend);
741 root 1.1 else
742     result->subfname = NULL;
743    
744 root 1.15 result->yefilesize = data->yefilesize;
745 root 1.22 result->mimeid = FP_strdup (data->mimeid);
746     result->mimetype = FP_strdup (data->mimetype);
747 root 1.1
748 root 1.20 if (result->partno == -1 &&
749 root 1.1 (data->uudet == PT_ENCODED || data->uudet == QP_ENCODED))
750     result->partno = 1;
751    
752     if (data->flags & FL_SINGLE) {
753     /*
754     * Don't touch this part. But it should really have a filename
755     */
756     if (result->filename == NULL) {
757     sprintf (temp, "%s.%03d", nofname, ++nofnum);
758 root 1.22 result->filename = FP_strdup (temp);
759 root 1.1 }
760     if (result->subfname == NULL)
761 root 1.22 result->subfname = FP_strdup (result->filename);
762 root 1.1
763 root 1.20 if (result->filename == NULL ||
764 root 1.1 result->subfname == NULL) {
765 root 1.34 UUMessage (UUMSG_ERROR,
766 root 1.1 uustring (S_OUT_OF_MEMORY),
767     (result->filename==NULL)?
768     (strlen(temp)+1):(strlen(result->filename)+1));
769     *ret = UURET_NOMEM;
770     UUkillfile(result);
771     return NULL;
772     }
773     if (result->partno == -1)
774     result->partno = 1;
775     }
776     else if (result->subfname == NULL && data->uudet &&
777 root 1.20 (data->begin || result->partno == 1 ||
778     (!uu_dumbness && result->partno == -1 &&
779 root 1.1 (data->subject != NULL || result->filename != NULL)))) {
780     /*
781     * If it's the first part of something and has some valid data, but
782     * no subject or anything, initialize lastvalid
783     */
784     /*
785     * in this case, it really _should_ have a filename somewhere
786     */
787 root 1.8 if (result->filename != NULL && *result->filename)
788 root 1.22 result->subfname = FP_strdup (result->filename);
789 root 1.1 else { /* if not, escape to UNKNOWN. We need to fill subfname */
790     sprintf (temp, "%s.%03d", nofname, ++nofnum);
791 root 1.22 result->subfname = FP_strdup (temp);
792 root 1.1 }
793     /*
794     * in case the strdup failed
795     */
796     if (result->subfname == NULL) {
797 root 1.34 UUMessage (UUMSG_ERROR,
798 root 1.1 uustring (S_OUT_OF_MEMORY),
799     (result->filename)?
800     (strlen(result->filename)+1):(strlen(temp)+1));
801     *ret = UURET_NOMEM;
802     UUkillfile (result);
803     return NULL;
804     }
805     /*
806     * if it's also got an 'end', or is the last part in a MIME-Mail,
807     * then don't set lastvalid
808     */
809     if (!data->end && (!data->partno || data->partno != data->maxpno)) {
810     /*
811     * initialize lastvalid
812     */
813     lastvalid = 1;
814     lastenc = data->uudet;
815     lastpart = result->partno = 1;
816 root 1.22 FP_strncpy (uucheck_lastname, result->subfname, 256);
817 root 1.1 }
818     else
819     result->partno = 1;
820     }
821     else if (result->subfname == NULL && data->uudet && data->mimeid) {
822     /*
823     * if it's got a file name, use it. Else use the mime-id for identifying
824     * this part, and hope there's no other files encoded in the same message
825     * under the same id.
826     */
827     if (result->filename)
828 root 1.22 result->subfname = FP_strdup (result->filename);
829 root 1.1 else
830 root 1.22 result->subfname = FP_strdup (result->mimeid);
831 root 1.1 }
832     else if (result->subfname == NULL && data->uudet) {
833     /*
834     * ff we have lastvalid, use it. Make an exception for
835     * Base64-encoded files.
836     */
837     if (data->uudet == B64ENCODED) {
838     /*
839     * Assume it's the first part. I wonder why it's got no part number?
840     */
841 root 1.8 if (result->filename != NULL && *result->filename)
842 root 1.22 result->subfname = FP_strdup (result->filename);
843 root 1.1 else { /* if not, escape to UNKNOWN. We need to fill subfname */
844     sprintf (temp, "%s.%03d", nofname, ++nofnum);
845 root 1.22 result->subfname = FP_strdup (temp);
846 root 1.1 }
847     if (result->subfname == NULL) {
848 root 1.34 UUMessage (UUMSG_ERROR,
849 root 1.1 uustring (S_OUT_OF_MEMORY),
850     (result->filename)?
851     (strlen(result->filename)+1):(strlen(temp)+1));
852     *ret = UURET_NOMEM;
853     UUkillfile (result);
854     return NULL;
855     }
856     lastvalid = 0;
857     }
858 root 1.4 else if (lastvalid && data->uudet == lastenc && result->partno == -1) {
859 root 1.22 result->subfname = FP_strdup (uucheck_lastname);
860 root 1.1 result->partno = ++lastpart;
861    
862     /*
863     * if it's the last part, invalidate lastvalid
864     */
865     if (data->end || (data->partno && data->partno == data->maxpno))
866     lastvalid = 0;
867 root 1.4 }
868     else if (data->partno != -1 && result->filename) {
869 root 1.22 result->subfname = FP_strdup (result->filename);
870 root 1.1 }
871 root 1.20 else {
872     /*
873 root 1.1 * it's got no info, it's got no begin, and we don't know anything
874     * about this part. Let's forget all about it.
875     */
876     *ret = UURET_NODATA;
877     UUkillfile (result);
878     return NULL;
879     }
880     }
881     else if (result->subfname == NULL && result->partno == -1) {
882     /*
883     * This, too, is a part without any useful information that we
884     * should forget about.
885     */
886     *ret = UURET_NODATA;
887     UUkillfile (result);
888     return NULL;
889     }
890     else if (result->subfname == NULL) {
891     /*
892     * This is a part without useful subject name, a valid part number
893     * but no encoded data. It *could* be the zeroeth part of something,
894     * but we don't care here. Just forget it.
895     */
896     *ret = UURET_NODATA;
897     UUkillfile (result);
898     return NULL;
899     }
900    
901     /*
902     * now, handle some cases where we have a useful subject but no
903     * useful part number
904     */
905    
906     if (result->partno == -1 && data->begin) {
907     /*
908 root 1.20 * hmm, this is reason enough to initialize lastvalid, at least
909 root 1.1 * if we have no end
910     */
911     if (!data->end) {
912 root 1.22 FP_strncpy (uucheck_lastname, result->subfname, 256);
913 root 1.1 result->partno = lastpart = 1;
914     lastenc = data->uudet;
915     lastvalid = 1;
916     }
917     else
918     result->partno = 1;
919     }
920     else if (result->partno == -1 && data->uudet) {
921 root 1.22 if (lastvalid && FP_stricmp (uucheck_lastname, result->subfname) == 0) {
922 root 1.1 /*
923     * if the subject filename is the same as last time, use part no
924     * of lastvalid. If at end, invalidate lastvalid
925     */
926     result->partno = ++lastpart;
927    
928     if (data->end)
929     lastvalid = 0;
930     }
931     else {
932     /*
933     * data but no part no. It's something UUInsertPartToList() should
934     * handle
935     */
936     goto skipcheck;
937     }
938     }
939     else if (result->partno == -1) {
940     /*
941     * it's got no data, so why should we need this one anyway?
942     */
943     *ret = UURET_NODATA;
944     UUkillfile (result);
945     return NULL;
946     }
947    
948     /*
949     * at this point, the part should have a valid subfname and a valid
950     * part number. If it doesn't, then fail.
951     */
952     if (result->subfname == NULL || result->partno == -1) {
953     *ret = UURET_NODATA;
954     UUkillfile (result);
955     return NULL;
956     }
957    
958     skipcheck:
959    
960     if (result->filename) {
961 root 1.22 if (*(ptr = FP_cutdir (result->filename))) {
962     p2 = FP_strdup (ptr);
963     FP_free (result->filename);
964 root 1.1 result->filename = p2;
965     }
966     }
967    
968     result->data = data;
969     result->NEXT = NULL;
970    
971     *ret = UURET_OK;
972    
973     return result;
974     }
975    
976     /*
977     * Insert one part of a file into the global list
978     **/
979    
980 root 1.29 ecb_hot int
981 root 1.1 UUInsertPartToList (uufile *data)
982     {
983     uulist *iter = UUGlobalFileList, *unew;
984     uufile *fiter, *last;
985    
986 root 1.25 uint32_t mimeid_hash = fnv1a (data->mimeid);
987     uint32_t filename_hash = fnv1a (data->filename);
988    
989     /* cache locally so the compiler has it easier to reason */
990     fileread *data_data = data->data;
991    
992 root 1.1 /*
993 root 1.27 * Part belongs together, if either
994 root 1.25 * (1) The file name received from the subject lines match, and
995 root 1.8 * (a) Not both parts have a begin line
996     * (b) Not both parts have an end line
997     * (c) Both parts don't have different MIME-IDs
998     * (d) Both parts don't encode different files
999     * (e) The other part wants to stay alone (FL_SINGLE)
1000 root 1.15 * (g) The yencode file size matches.
1001 root 1.27 * (2) The MIME-IDs match
1002 root 1.1 */
1003    
1004 root 1.28 /* TODO: use two hash tables, keyed on filename and mimeid */
1005 root 1.31 /* unfortunately, its not so easy, as lots of code inserts in interesting ways, */
1006     /* so I tried to conventionally speed up the search by replacing strcmp with */
1007     /* hash comparisons, reordering and prefetching struct members and so on */
1008 root 1.25
1009 root 1.1 /*
1010     * check if this part wants to be left alone. If so, don't bother
1011     * to do all the checks
1012     */
1013 root 1.25 if (data_data->flags & FL_SINGLE)
1014     goto newpart;
1015 root 1.1
1016     while (iter) {
1017 root 1.30 ecb_prefetch (iter->NEXT, 0, 1);
1018 root 1.25 if (
1019     (
1020     1
1021     && filename_hash == iter->filename_hash
1022     && (data->filename && iter->filename && strcmp (data->filename, iter->filename) == 0)
1023     && !(iter->begin && data_data->begin)
1024     && !(iter->end && data_data->end)
1025     && !(iter->flags & FL_SINGLE)
1026     && !(iter->thisfile && iter->thisfile->yefilesize != data->yefilesize)
1027     && FP_stricmp (data->subfname, iter->subfname) == 0
1028     && mimeid_hash == iter->mimeid_hash
1029     && !(data->mimeid && iter->mimeid && strcmp (data->mimeid, iter->mimeid) != 0)
1030     )
1031     || (mimeid_hash == iter->mimeid_hash && data->mimeid && iter->mimeid && strcmp (data->mimeid, iter->mimeid) == 0)
1032     ) {
1033 root 1.1
1034     /*
1035 root 1.8 * Don't insert a part that is already there.
1036     *
1037     * Also don't add a part beyond the "end" marker (unless we
1038     * have a mimeid, which screws up the marker).
1039 root 1.1 */
1040    
1041 root 1.8 for (fiter=iter->thisfile; fiter; fiter=fiter->NEXT) {
1042     if (data->partno == fiter->partno)
1043     goto goahead;
1044     if (!iter->mimeid) {
1045     if (data->partno > fiter->partno && fiter->data->end) {
1046     goto goahead;
1047     }
1048     }
1049     }
1050 root 1.1
1051     if (iter->filename == NULL && data->filename != NULL) {
1052 root 1.22 if ((iter->filename = FP_strdup (data->filename)) == NULL)
1053 root 1.1 return UURET_NOMEM;
1054     }
1055    
1056     /*
1057     * special case when we might have tagged a part as Base64 when the
1058     * file was really XX
1059     */
1060    
1061 root 1.25 if (data_data->uudet == B64ENCODED &&
1062 root 1.1 iter->uudet == XX_ENCODED && iter->begin) {
1063 root 1.25 data_data->uudet = XX_ENCODED;
1064 root 1.1 }
1065 root 1.25 else if (data_data->uudet == XX_ENCODED && data_data->begin &&
1066 root 1.1 iter->uudet == B64ENCODED) {
1067     iter->uudet = XX_ENCODED;
1068    
1069     fiter = iter->thisfile;
1070     while (fiter) {
1071     fiter->data->uudet = XX_ENCODED;
1072     fiter = fiter->NEXT;
1073     }
1074     }
1075    
1076     /*
1077     * If this is from a Message/Partial, we believe only the
1078     * iter->uudet from the first part
1079     */
1080 root 1.25 if (data_data->flags & FL_PARTIAL) {
1081 root 1.1 if (data->partno == 1) {
1082 root 1.25 iter->uudet = data_data->uudet;
1083     iter->flags = data_data->flags;
1084 root 1.1 }
1085     }
1086     else {
1087 root 1.25 if (data_data->uudet) iter->uudet = data_data->uudet;
1088     if (data_data->flags) iter->flags = data_data->flags;
1089 root 1.1 }
1090    
1091 root 1.25 if (iter->mode == 0 && data_data->mode != 0)
1092     iter->mode = data_data->mode;
1093    
1094     if (data_data->begin) iter->begin = data->partno ? data->partno : 1;
1095     if (data_data->end) iter->end = data->partno ? data->partno : 1;
1096 root 1.1
1097     if (data->mimetype) {
1098 root 1.22 FP_free (iter->mimetype);
1099     iter->mimetype = FP_strdup (data->mimetype);
1100 root 1.1 }
1101    
1102     /*
1103     * insert part at the beginning
1104     */
1105    
1106     if (data->partno != -1 && data->partno < iter->thisfile->partno) {
1107     iter->state = UUFILE_READ;
1108     data->NEXT = iter->thisfile;
1109     iter->thisfile = data;
1110     return UURET_OK;
1111     }
1112    
1113     /*
1114     * insert part somewhere else
1115     */
1116    
1117     iter->state = UUFILE_READ; /* prepare for re-checking */
1118     fiter = iter->thisfile;
1119     last = NULL;
1120    
1121     while (fiter) {
1122     /*
1123     * if we find the same part no again, check which one looks better
1124     */
1125     if (data->partno == fiter->partno) {
1126     if (fiter->data->subject == NULL)
1127     return UURET_NODATA;
1128 root 1.22 else if (FP_stristr (fiter->data->subject, "repost") != NULL &&
1129 root 1.25 FP_stristr (data_data->subject, "repost") == NULL)
1130 root 1.1 return UURET_NODATA;
1131 root 1.25 else if (fiter->data->uudet && !data_data->uudet)
1132 root 1.1 return UURET_NODATA;
1133     else {
1134     /*
1135     * replace
1136     */
1137     data->NEXT = fiter->NEXT;
1138     fiter->NEXT = NULL;
1139     UUkillfile (fiter);
1140    
1141     if (last == NULL)
1142     iter->thisfile = data;
1143     else
1144     last->NEXT = data;
1145    
1146     return UURET_OK;
1147     }
1148     }
1149    
1150     /*
1151     * if at the end of the part list, add it
1152     */
1153    
1154 root 1.20 if (fiter->NEXT == NULL ||
1155 root 1.1 (data->partno != -1 && data->partno < fiter->NEXT->partno)) {
1156     data->NEXT = fiter->NEXT;
1157     fiter->NEXT = data;
1158    
1159     if (data->partno == -1)
1160     data->partno = fiter->partno + 1;
1161    
1162     return UURET_OK;
1163     }
1164 root 1.23
1165 root 1.1 last = fiter;
1166     fiter = fiter->NEXT;
1167     }
1168 root 1.20
1169 root 1.35 /* Shouldn't get here */
1170     abort ();
1171 root 1.1 }
1172 root 1.25
1173 root 1.1 goahead:
1174 root 1.25 iter = iter->NEXT;
1175    
1176     if (!iter)
1177 root 1.1 break;
1178 root 1.25 }
1179 root 1.1
1180 root 1.25 newpart:
1181 root 1.1 /*
1182     * handle new entry
1183     */
1184    
1185     if (data->partno == -1) {
1186     /*
1187     * if it's got no part no, and it's MIME mail, then assume this is
1188     * part no. 1. If it's not MIME, then we can't handle it; if it
1189     * had a 'begin', it'd have got a part number assigned by
1190     * UUPreProcessPart().
1191     */
1192 root 1.25 if (data_data->uudet == B64ENCODED || data_data->uudet == BH_ENCODED)
1193 root 1.1 data->partno = 1;
1194     else
1195     return UURET_NODATA;
1196     }
1197    
1198 root 1.25 if ((unew = (uulist *)malloc (sizeof (uulist))) == NULL) {
1199 root 1.1 return UURET_NOMEM;
1200     }
1201    
1202 root 1.13 {
1203 root 1.21 const uulist uulist_new = { 0 };
1204 root 1.13 *unew = uulist_new; /* zero-initialise the structure */
1205     }
1206    
1207 root 1.22 if ((unew->subfname = FP_strdup (data->subfname)) == NULL) {
1208     FP_free (unew);
1209 root 1.1 return UURET_NOMEM;
1210     }
1211    
1212 root 1.25 unew->filename_hash = filename_hash;
1213 root 1.1 if (data->filename != NULL) {
1214 root 1.22 if ((unew->filename = FP_strdup (data->filename)) == NULL) {
1215     FP_free (unew->subfname);
1216     FP_free (unew);
1217 root 1.1 return UURET_NOMEM;
1218     }
1219     }
1220     else
1221     unew->filename = NULL;
1222    
1223 root 1.25 unew->mimeid_hash = mimeid_hash;
1224 root 1.1 if (data->mimeid != NULL) {
1225 root 1.22 if ((unew->mimeid = FP_strdup (data->mimeid)) == NULL) {
1226     FP_free (unew->subfname);
1227     FP_free (unew->filename);
1228     FP_free (unew);
1229 root 1.1 return UURET_NOMEM;
1230     }
1231     }
1232     else
1233     unew->mimeid = NULL;
1234    
1235     if (data->mimetype != NULL) {
1236 root 1.22 if ((unew->mimetype = FP_strdup (data->mimetype)) == NULL) {
1237     FP_free (unew->mimeid);
1238     FP_free (unew->subfname);
1239     FP_free (unew->filename);
1240     FP_free (unew);
1241 root 1.1 return UURET_NOMEM;
1242     }
1243     }
1244     else
1245     unew->mimetype = NULL;
1246    
1247     unew->state = UUFILE_READ;
1248     unew->thisfile = data;
1249 root 1.25 unew->mode = data_data->mode;
1250     unew->uudet = data_data->uudet;
1251     unew->flags = data_data->flags;
1252     unew->begin = data_data->begin ? (data->partno ? data->partno : 1) : 0;
1253     unew->end = data_data->end ? (data->partno ? data->partno : 1) : 0;
1254 root 1.1
1255 root 1.24 /* insert at the beginning, as parts often show up in bursts */
1256     unew->NEXT = UUGlobalFileList;
1257     UUGlobalFileList = unew;
1258 root 1.1
1259     return UURET_OK;
1260     }
1261    
1262     /*
1263     * At this point, all files are read in and stored in the
1264     * "UUGlobalFileList". Do some checking. All parts there?
1265     **/
1266    
1267 root 1.16 void UUEXPORT
1268 root 1.1 UUCheckGlobalList (void)
1269     {
1270     int misparts[MAXPLIST], haveparts[MAXPLIST];
1271     int miscount, havecount, count, flag, part;
1272     uulist *liter=UUGlobalFileList, *prev;
1273     uufile *fiter;
1274     long thesize;
1275    
1276     while (liter) {
1277     miscount = 0;
1278     thesize = 0;
1279    
1280     if (liter->state & UUFILE_OK) {
1281     liter = liter->NEXT;
1282     continue;
1283     }
1284     else if ((liter->uudet == QP_ENCODED ||
1285 root 1.20 liter->uudet == PT_ENCODED) &&
1286 root 1.1 (liter->flags & FL_SINGLE)) {
1287     if ((liter->flags&FL_PROPER)==0)
1288     liter->size = -1;
1289     else
1290     liter->size = liter->thisfile->data->length;
1291    
1292     liter->state = UUFILE_OK;
1293     continue;
1294     }
1295     else if ((fiter = liter->thisfile) == NULL) {
1296     liter->state = UUFILE_NODATA;
1297     liter = liter->NEXT;
1298     continue;
1299     }
1300    
1301     /*
1302     * Re-Check this file
1303     */
1304    
1305     flag = 0;
1306     miscount = 0;
1307     havecount = 0;
1308     thesize = 0;
1309     liter->state = UUFILE_READ;
1310    
1311     /*
1312     * search encoded data
1313     */
1314    
1315     while (fiter && !fiter->data->uudet) {
1316     if (havecount<MAXPLIST) {
1317     haveparts[havecount++] = fiter->partno;
1318     }
1319     fiter = fiter->NEXT;
1320     }
1321    
1322     if (fiter == NULL) {
1323     liter->state = UUFILE_NODATA;
1324     liter = liter->NEXT;
1325     continue;
1326     }
1327    
1328     if (havecount<MAXPLIST) {
1329     haveparts[havecount++] = fiter->partno;
1330     }
1331    
1332     if ((part = fiter->partno) > 1) {
1333     if (!fiter->data->begin) {
1334     for (count=1; count < part && miscount < MAXPLIST; count++)
1335     misparts[miscount++] = count;
1336     }
1337     }
1338    
1339     /*
1340     * don't care if so many parts are missing
1341     */
1342    
1343     if (miscount >= MAXPLIST) {
1344     liter->state = UUFILE_MISPART;
1345     liter = liter->NEXT;
1346     continue;
1347     }
1348    
1349     if (liter->uudet == B64ENCODED ||
1350     liter->uudet == QP_ENCODED ||
1351     liter->uudet == PT_ENCODED)
1352     flag |= 3; /* Don't need begin or end with Base64 or plain text*/
1353    
1354     if (fiter->data->begin) flag |= 1;
1355     if (fiter->data->end) flag |= 2;
1356 root 1.20 if (fiter->data->uudet) flag |= 4;
1357 root 1.1
1358     /*
1359     * guess size of part
1360     */
1361    
1362     switch (fiter->data->uudet) {
1363     case UU_ENCODED:
1364     case XX_ENCODED:
1365     thesize += 3*fiter->data->length/4;
1366     thesize -= 3*fiter->data->length/124; /* substract 2 of 62 chars */
1367     break;
1368     case B64ENCODED:
1369     thesize += 3*fiter->data->length/4;
1370     thesize -= fiter->data->length/52; /* substract 2 of 78 chars */
1371     break;
1372     case QP_ENCODED:
1373     case PT_ENCODED:
1374     thesize += fiter->data->length;
1375     break;
1376     }
1377 root 1.20
1378 root 1.1 fiter = fiter->NEXT;
1379    
1380     while (fiter != NULL) {
1381 root 1.18 for (count = part+1; count < fiter->partno && miscount < MAXPLIST; count++)
1382 root 1.1 misparts[miscount++] = count;
1383    
1384     part = fiter->partno;
1385 root 1.20
1386 root 1.18 if (havecount < MAXPLIST)
1387     haveparts[havecount++] = part;
1388 root 1.1
1389     if (fiter->data->begin) flag |= 1;
1390     if (fiter->data->end) flag |= 2;
1391     if (fiter->data->uudet) flag |= 4;
1392    
1393     switch (fiter->data->uudet) {
1394     case UU_ENCODED:
1395     case XX_ENCODED:
1396     thesize += 3*fiter->data->length/4;
1397     thesize -= 3*fiter->data->length/124; /* substract 2 of 62 chars */
1398     break;
1399     case B64ENCODED:
1400     thesize += 3*fiter->data->length/4;
1401     thesize -= fiter->data->length/52; /* substract 2 of 78 chars */
1402     break;
1403     case QP_ENCODED:
1404     case PT_ENCODED:
1405     thesize += fiter->data->length;
1406     break;
1407     }
1408    
1409     if (fiter->data->end)
1410     break;
1411 root 1.20
1412 root 1.1 fiter = fiter->NEXT;
1413     }
1414    
1415     /*
1416     * if in fast mode, we don't notice an 'end'. So if its uu or xx
1417     * encoded, there's a begin line and encoded data, assume it's
1418     * there.
1419     */
1420 root 1.20
1421 root 1.1 if (uu_fast_scanning && (flag & 0x01) && (flag & 0x04) &&
1422     (liter->uudet == UU_ENCODED || liter->uudet == XX_ENCODED))
1423     flag |= 2;
1424    
1425     /*
1426     * Set the parts we have and/or missing
1427     */
1428    
1429 root 1.22 FP_free (liter->haveparts);
1430     FP_free (liter->misparts);
1431 root 1.1
1432     liter->haveparts = NULL;
1433     liter->misparts = NULL;
1434 root 1.20
1435 root 1.1 if (havecount) {
1436     if ((liter->haveparts=(int*)malloc((havecount+1)*sizeof(int)))!=NULL) {
1437     memcpy (liter->haveparts, haveparts, havecount*sizeof(int));
1438     liter->haveparts[havecount] = 0;
1439     }
1440     }
1441 root 1.20
1442 root 1.1 if (miscount) {
1443     if ((liter->misparts=(int*)malloc((miscount+1)*sizeof(int)))!=NULL) {
1444     memcpy (liter->misparts, misparts, miscount*sizeof(int));
1445     liter->misparts[miscount] = 0;
1446     }
1447     liter->state |= UUFILE_MISPART;
1448     }
1449    
1450     /*
1451     * Finalize checking
1452     */
1453    
1454     if ((flag & 1) == 0) liter->state |= UUFILE_NOBEGIN;
1455     if ((flag & 2) == 0) liter->state |= UUFILE_NOEND;
1456 root 1.19 if ((flag & 4) == 0) liter->state |= UUFILE_NODATA;
1457 root 1.20
1458 root 1.1 if ((flag & 7) == 7 && miscount==0) {
1459     liter->state = UUFILE_OK;
1460     }
1461    
1462     if ((uu_fast_scanning && (liter->flags&FL_PROPER)==0) || thesize<=0)
1463     liter->size = -1;
1464     else
1465     liter->size = thesize;
1466    
1467 root 1.20 if (liter->state==UUFILE_OK &&
1468 root 1.1 (liter->filename==NULL || liter->filename[0]=='\0')) {
1469     /*
1470     * Emergency backup if the file does not have a filename
1471     */
1472 root 1.22 FP_free (liter->filename);
1473 root 1.1 if (liter->subfname && liter->subfname[0] &&
1474 root 1.22 FP_strpbrk (liter->subfname, "()[];: ") == NULL)
1475     liter->filename = FP_strdup (liter->subfname);
1476 root 1.1 else {
1477     sprintf (uucheck_tempname, "%s.%03d", nofname, ++nofnum);
1478 root 1.22 liter->filename = FP_strdup (uucheck_tempname);
1479 root 1.1 }
1480     }
1481     liter = liter->NEXT;
1482     }
1483    
1484     /*
1485     * Sets back (PREV) links
1486     */
1487    
1488     liter = UUGlobalFileList;
1489     prev = NULL;
1490    
1491     while (liter) {
1492     liter->PREV = prev;
1493     prev = liter;
1494     liter = liter->NEXT;
1495     }
1496     }
1497