ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/Convert-UUlib/uulib/uuutil.c
Revision: 1.4
Committed: Sun Mar 31 20:08:43 2002 UTC (22 years, 2 months ago) by root
Content type: text/plain
Branch: MAIN
CVS Tags: rel-1_11, rel-1_10, rel-1_12, rel-0_7, rel-1_06, rel-1_04, rel-1_05, rel-1_08, rel-1_09
Changes since 1.3: +34 -34 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 root 1.4 char * uuutil_id = "$Id: uuutil.c,v 1.3 2002/03/31 20:04:31 root Exp $";
58 root 1.1
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 (char *filename);
77     static uulist * UU_smparts_r (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 root 1.4 _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 root 1.1 }
101     }
102    
103     void
104     UUkillfile (uufile *data)
105     {
106     uufile *next;
107    
108     while (data) {
109 root 1.4 _FP_free (data->filename);
110     _FP_free (data->subfname);
111     _FP_free (data->mimeid);
112     _FP_free (data->mimetype);
113 root 1.1 UUkillfread (data->data);
114    
115     next = data->NEXT;
116 root 1.4 _FP_free (data);
117 root 1.1 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 root 1.4 _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 root 1.1 UUkillfile (data->thisfile);
139 root 1.4 _FP_free (data->haveparts);
140     _FP_free (data->misparts);
141 root 1.1
142     next = data->NEXT;
143 root 1.4 _FP_free (data);
144 root 1.1 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 root 1.4 _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 root 1.1 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 root 1.4 char **eiter = knownexts, *ptr=_FP_strrchr(filename, '.');
179 root 1.1 int count=0, where=0;
180    
181     if (ptr == NULL)
182     return -1;
183     ptr++;
184    
185     while (*eiter) {
186 root 1.4 if (_FP_stricmp (ptr, (**eiter=='@')?*eiter+1:*eiter) == 0)
187 root 1.1 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 root 1.4 iter->filename = _FP_strdup (addit->filename);
387 root 1.1
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