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 (20 months, 1 week 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

# 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     #include <stdlib.h>
35     #include <string.h>
36 root 1.10 #include <errno.h>
37 root 1.9
38 root 1.1 #ifdef HAVE_UNISTD_H
39     #include <unistd.h>
40     #endif
41    
42 root 1.2 #include <uudeview.h>
43 root 1.1 #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 root 1.7 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 root 1.1 }
89     }
90    
91     void
92     UUkillfile (uufile *data)
93     {
94     uufile *next;
95    
96     while (data) {
97 root 1.7 FP_free (data->filename);
98     FP_free (data->subfname);
99     FP_free (data->mimeid);
100     FP_free (data->mimetype);
101 root 1.1 UUkillfread (data->data);
102    
103     next = data->NEXT;
104 root 1.7 FP_free (data);
105 root 1.1 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 root 1.10 UUMessage (UUMSG_WARNING,
118 root 1.1 uustring (S_TMP_NOT_REMOVED),
119     data->binfile, strerror (errno));
120    
121 root 1.7 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 root 1.1 UUkillfile (data->thisfile);
127 root 1.7 FP_free (data->haveparts);
128     FP_free (data->misparts);
129 root 1.1
130     next = data->NEXT;
131 root 1.7 FP_free (data);
132 root 1.1 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 root 1.7 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 root 1.1 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 root 1.7 char **eiter = knownexts, *ptr=FP_strrchr(filename, '.');
167 root 1.1 int count=0, where=0;
168    
169     if (ptr == NULL)
170     return -1;
171     ptr++;
172    
173     while (*eiter) {
174 root 1.7 if (FP_stricmp (ptr, (**eiter=='@')?*eiter+1:*eiter) == 0)
175 root 1.1 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 root 1.6 UUbhdecomp (char *in, char *out, char *last, int *rpc,
207 root 1.1 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 root 1.7 iter->filename = FP_strdup (addit->filename);
375 root 1.1
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 root 1.5 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 root 1.10 UUMessage (UUMSG_MESSAGE,
436 root 1.5 uustring (S_SMERGE_MERGED),
437     (iter->subfname) ? iter->subfname : "",
438     (res->subfname) ? res->subfname : "", pass);
439 root 1.6
440 root 1.5 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 root 1.1 }
460     }
461    
462     /*
463     * check again
464     */
465    
466     UUCheckGlobalList ();
467    
468     return flag;
469     }
470