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