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