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