ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/Convert-UUlib/uulib/uucheck.c
(Generate patch)

Comparing Convert-UUlib/uulib/uucheck.c (file contents):
Revision 1.3.2.5 by root, Sun Apr 18 19:55:46 2004 UTC vs.
Revision 1.36 by root, Tue Nov 29 05:21:02 2022 UTC

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

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines