ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/cvsroot/Convert-UUlib/uulib/uuutil.c
Revision: 1.8
Committed: Sat Sep 24 06:02:04 2022 UTC (4 years ago) by root
Content type: text/plain
Branch: MAIN
Changes since 1.7: +0 -2 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     /*
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 root 1.2 #include <uudeview.h>
53 root 1.1 #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 root 1.7 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 root 1.1 }
99     }
100    
101     void
102     UUkillfile (uufile *data)
103     {
104     uufile *next;
105    
106     while (data) {
107 root 1.7 FP_free (data->filename);
108     FP_free (data->subfname);
109     FP_free (data->mimeid);
110     FP_free (data->mimetype);
111 root 1.1 UUkillfread (data->data);
112    
113     next = data->NEXT;
114 root 1.7 FP_free (data);
115 root 1.1 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 root 1.7 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 root 1.1 UUkillfile (data->thisfile);
137 root 1.7 FP_free (data->haveparts);
138     FP_free (data->misparts);
139 root 1.1
140     next = data->NEXT;
141 root 1.7 FP_free (data);
142 root 1.1 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 root 1.7 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 root 1.1 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 root 1.7 char **eiter = knownexts, *ptr=FP_strrchr(filename, '.');
177 root 1.1 int count=0, where=0;
178    
179     if (ptr == NULL)
180     return -1;
181     ptr++;
182    
183     while (*eiter) {
184 root 1.7 if (FP_stricmp (ptr, (**eiter=='@')?*eiter+1:*eiter) == 0)
185 root 1.1 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 root 1.6 UUbhdecomp (char *in, char *out, char *last, int *rpc,
217 root 1.1 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 root 1.7 iter->filename = FP_strdup (addit->filename);
385 root 1.1
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 root 1.5 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 root 1.6
450 root 1.5 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 root 1.1 }
470     }
471    
472     /*
473     * check again
474     */
475    
476     UUCheckGlobalList ();
477    
478     return flag;
479     }
480