ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/Convert-UUlib/uulib/uuutil.c
Revision: 1.8
Committed: Sat Sep 24 06:02:04 2022 UTC (20 months, 1 week ago) by root
Content type: text/plain
Branch: MAIN
Changes since 1.7: +0 -2 lines
Log Message:
*** empty log message ***

File Contents

# Content
1 /*
2 * This file is part of uudeview, the simple and friendly multi-part multi-
3 * file uudecoder program (c) 1994-2001 by Frank Pilhofer. The author may
4 * be contacted at fp@fpx.de
5 *
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 /*
18 * certain utilitarian functions that didn't fit anywhere else
19 */
20
21 #ifdef HAVE_CONFIG_H
22 #include "config.h"
23 #endif
24
25 #ifdef SYSTEM_WINDLL
26 #include <windows.h>
27 #endif
28 #ifdef SYSTEM_OS2
29 #include <os2.h>
30 #endif
31
32 #include <stdio.h>
33 #include <ctype.h>
34
35 #ifdef STDC_HEADERS
36 #include <stdlib.h>
37 #include <string.h>
38 #endif
39 #ifdef HAVE_MALLOC_H
40 #include <malloc.h>
41 #endif
42 #ifdef HAVE_UNISTD_H
43 #include <unistd.h>
44 #endif
45 #ifdef HAVE_MEMORY_H
46 #include <memory.h>
47 #endif
48 #ifdef HAVE_ERRNO_H
49 #include <errno.h>
50 #endif
51
52 #include <uudeview.h>
53 #include <uuint.h>
54 #include <fptools.h>
55 #include <uustring.h>
56
57 /*
58 * Parts with different known extensions will not be merged by SPMS.
59 * if first character is '@', it is synonymous to the previous one.
60 */
61
62 static char *knownexts[] = {
63 "mpg", "@mpeg", "avi", "mov",
64 "gif", "jpg", "@jpeg", "tif",
65 "voc", "wav", "@wave", "au",
66 "zip", "arj", "tar",
67 NULL
68 };
69
70 /*
71 * forward declarations of local functions
72 */
73
74 static int UUSMPKnownExt (char *filename);
75 static uulist * UU_smparts_r (uulist *, int);
76
77 /*
78 * mallocable areas
79 */
80
81 char *uuutil_bhwtmp;
82
83 /*
84 * free some memory
85 **/
86
87 void
88 UUkillfread (fileread *data)
89 {
90 if (data != NULL) {
91 FP_free (data->subject);
92 FP_free (data->filename);
93 FP_free (data->origin);
94 FP_free (data->mimeid);
95 FP_free (data->mimetype);
96 FP_free (data->sfname);
97 FP_free (data);
98 }
99 }
100
101 void
102 UUkillfile (uufile *data)
103 {
104 uufile *next;
105
106 while (data) {
107 FP_free (data->filename);
108 FP_free (data->subfname);
109 FP_free (data->mimeid);
110 FP_free (data->mimetype);
111 UUkillfread (data->data);
112
113 next = data->NEXT;
114 FP_free (data);
115 data = next;
116 }
117 }
118
119 void
120 UUkilllist (uulist *data)
121 {
122 uulist *next;
123
124 while (data) {
125 if (data->binfile != NULL)
126 if (unlink (data->binfile))
127 UUMessage (uuutil_id, __LINE__, UUMSG_WARNING,
128 uustring (S_TMP_NOT_REMOVED),
129 data->binfile, strerror (errno));
130
131 FP_free (data->filename);
132 FP_free (data->subfname);
133 FP_free (data->mimeid);
134 FP_free (data->mimetype);
135 FP_free (data->binfile);
136 UUkillfile (data->thisfile);
137 FP_free (data->haveparts);
138 FP_free (data->misparts);
139
140 next = data->NEXT;
141 FP_free (data);
142 data = next;
143 }
144 }
145
146 /*
147 * this kill function is an exception in that it doesn't kill data itself
148 */
149
150 void
151 UUkillheaders (headers *data)
152 {
153 if (data != NULL) {
154 FP_free (data->from);
155 FP_free (data->subject);
156 FP_free (data->rcpt);
157 FP_free (data->date);
158 FP_free (data->mimevers);
159 FP_free (data->ctype);
160 FP_free (data->ctenc);
161 FP_free (data->fname);
162 FP_free (data->boundary);
163 FP_free (data->mimeid);
164 memset (data, 0, sizeof (headers));
165 }
166 }
167
168 /*
169 * checks for various well-known extensions. if two parts have different
170 * known extensions, we won't merge them.
171 */
172
173 static int
174 UUSMPKnownExt (char *filename)
175 {
176 char **eiter = knownexts, *ptr=FP_strrchr(filename, '.');
177 int count=0, where=0;
178
179 if (ptr == NULL)
180 return -1;
181 ptr++;
182
183 while (*eiter) {
184 if (FP_stricmp (ptr, (**eiter=='@')?*eiter+1:*eiter) == 0)
185 return where;
186 else
187 eiter++;
188
189 if (*eiter == NULL)
190 break;
191
192 if (**eiter=='@')
193 count++;
194 else
195 where = ++count;
196 }
197 return -1;
198 }
199
200 /*
201 * de-compress a binhex RLE stream
202 * the data read from in is uncompressed, and at most maxcount bytes
203 * (or octets, as they say) are copied to out. Because an uncompression
204 * might not be completed because of this maximum number of bytes. There-
205 * for, the leftover character and repetition count is saved. If a marker
206 * has been read but not the repetition count, *rpc is set to -256.
207 *
208 * the function returns the number of bytes eaten from in. If opc is not
209 * NULL, the total number of characters stored in out is saved there
210 *
211 * with repetition counts, remember that we've already transferred *one*
212 * occurence
213 */
214
215 int
216 UUbhdecomp (char *in, char *out, char *last, int *rpc,
217 size_t inc, size_t max, size_t *opc)
218 {
219 size_t count, used=0, dummy;
220 char marker = '\220' /* '\x90' */;
221
222 if (opc == NULL)
223 opc = &dummy;
224 else
225 *opc = 0;
226
227 if (*rpc == -256) {
228 if (inc == 0)
229 return 0;
230 *rpc = (int) (unsigned char) *in++; used++;
231
232 if (*rpc == 0) {
233 *last = *out++ = marker;
234 max--; *opc+=1;
235 }
236 else
237 *rpc-=1;
238 }
239
240 if (*rpc) {
241 count = (max > (size_t) *rpc) ? (size_t) *rpc : max;
242
243 memset (out, *last, count);
244
245 out += count;
246 *opc += count;
247 max -= count;
248 *rpc -= count;
249 }
250
251 while (used < inc && max) {
252 if (*in == marker) {
253 used++; in++;
254 if (used == inc) {
255 *rpc = -256;
256 return used;
257 }
258 *rpc = (int) (unsigned char) *in++; used++;
259
260 if (*rpc == 0) {
261 *last = *out++ = marker;
262 max--; *opc+=1;
263 continue;
264 }
265 else
266 *rpc -= 1;
267
268 count = (max > (size_t) *rpc) ? (size_t) *rpc : max;
269 memset (out, *last, count);
270
271 out += count;
272 *opc += count;
273 max -= count;
274 *rpc -= count;
275 }
276 else {
277 *last = *out++ = *in++;
278 used++; *opc+=1; max--;
279 }
280 }
281
282 return used;
283 }
284
285 /*
286 * write to binhex file
287 */
288
289 size_t
290 UUbhwrite (char *ptr, size_t sel, size_t nel, FILE *file)
291 {
292 char *tmpstring=uuutil_bhwtmp;
293 static int rpc = 0;
294 static char lc;
295 int count, tc=0;
296 size_t opc;
297
298 if (ptr == NULL) { /* init */
299 rpc = 0;
300 return 0;
301 }
302
303 while (nel || (rpc != 0 && rpc != -256)) {
304 count = UUbhdecomp (ptr, tmpstring, &lc, &rpc,
305 nel, 256, &opc);
306 if (fwrite (tmpstring, 1, opc, file) != opc)
307 return 0;
308 if (ferror (file))
309 return 0;
310 nel -= count;
311 ptr += count;
312 tc += count;
313 }
314
315 return tc;
316 }
317
318 static uulist *
319 UU_smparts_r (uulist *addit, int pass)
320 {
321 uulist *iter = UUGlobalFileList;
322 uufile *fiter, *dest, *temp;
323 int count, flag, a, b;
324
325 while (iter) {
326 if ((iter->state & UUFILE_OK) || iter->uudet == 0) {
327 iter = iter->NEXT;
328 continue;
329 }
330 if (iter == addit) {
331 iter = iter->NEXT;
332 continue;
333 }
334 if ((iter->begin && addit->begin) || (iter->end && addit->end) ||
335 (iter->uudet != addit->uudet)) {
336 iter = iter->NEXT;
337 continue;
338 }
339 if ((a = UUSMPKnownExt (addit->subfname)) != -1 &&
340 (b = UUSMPKnownExt (iter->subfname)) != -1)
341 if (a != b) {
342 iter = iter->NEXT;
343 continue;
344 }
345
346 flag = count = 0;
347 fiter = iter->thisfile;
348 temp = addit->thisfile;
349 dest = NULL;
350
351 while (temp) {
352 if (!(temp->data->uudet)) {
353 temp = temp->NEXT;
354 continue;
355 }
356
357 while (fiter && fiter->partno < temp->partno) {
358 dest = fiter;
359 fiter = fiter->NEXT;
360 }
361 if (fiter && fiter->partno == temp->partno) {
362 flag = 0;
363 break;
364 }
365 else {
366 flag = 1;
367 count += ((dest) ? temp->partno - dest->partno - 1 : 0) +
368 ((fiter) ? fiter->partno - temp->partno - 1 : 0);
369 }
370
371 temp = temp->NEXT;
372 }
373 if (flag == 0 ||
374 (pass == 0 && count > 0) ||
375 (pass == 1 && count > 5)) {
376 iter = iter->NEXT;
377 continue;
378 }
379
380 dest = iter->thisfile;
381 fiter = addit->thisfile;
382
383 if (iter->filename == NULL && addit->filename != NULL)
384 iter->filename = FP_strdup (addit->filename);
385
386 if (addit->begin) iter->begin = 1;
387 if (addit->end) iter->end = 1;
388
389 if (addit->mode != 0 && iter->mode == 0)
390 iter->mode = addit->mode;
391
392 while (fiter) {
393 flag = 0;
394
395 if (fiter->partno == iter->thisfile->partno ||
396 (dest->NEXT != NULL && fiter->partno == dest->NEXT->partno)) {
397 temp = fiter->NEXT;
398 fiter->NEXT = NULL;
399
400 UUkillfile (fiter);
401
402 addit->thisfile= temp;
403 fiter = temp;
404 continue;
405 }
406 if (fiter->partno < iter->thisfile->partno) {
407 temp = fiter->NEXT;
408 fiter->NEXT = iter->thisfile;
409 iter->thisfile = fiter;
410 dest = fiter;
411 addit->thisfile= temp;
412 fiter = temp;
413 }
414 else if (dest->NEXT == NULL || fiter->partno < dest->NEXT->partno) {
415 temp = fiter->NEXT;
416 fiter->NEXT = dest->NEXT;
417 dest->NEXT = fiter;
418 addit->thisfile= temp;
419 fiter = temp;
420 }
421 else {
422 dest = dest->NEXT;
423 }
424 }
425 break;
426 }
427 return iter;
428 }
429
430 int UUEXPORT
431 UUSmerge (int pass)
432 {
433 uulist *iter = UUGlobalFileList, *last=NULL, *res, *temp;
434 int flag = 0;
435
436 if (pass >= 0)
437 {
438 while (iter) {
439 if ((iter->state & UUFILE_OK) || iter->uudet == 0) {
440 last = iter;
441 iter = iter->NEXT;
442 continue;
443 }
444 if ((res = UU_smparts_r (iter, pass)) != NULL) {
445 UUMessage (uuutil_id, __LINE__, UUMSG_MESSAGE,
446 uustring (S_SMERGE_MERGED),
447 (iter->subfname) ? iter->subfname : "",
448 (res->subfname) ? res->subfname : "", pass);
449
450 temp = iter->NEXT;
451 iter->NEXT = NULL;
452 UUkilllist (iter);
453
454 flag++;
455
456 if (last == NULL) {
457 UUGlobalFileList = temp;
458 iter = temp;
459 }
460 else {
461 last->NEXT = temp;
462 iter = temp;
463 }
464
465 continue;
466 }
467 last = iter;
468 iter = iter->NEXT;
469 }
470 }
471
472 /*
473 * check again
474 */
475
476 UUCheckGlobalList ();
477
478 return flag;
479 }
480