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