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