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