1 | /* |
1 | /* |
2 | * This file is part of uudeview, the simple and friendly multi-part multi- |
2 | * This file is part of uudeview, the simple and friendly multi-part multi- |
3 | * file uudecoder program (c) 1994 by Frank Pilhofer. The author may be |
3 | * file uudecoder program (c) 1994-2001 by Frank Pilhofer. The author may |
4 | * contacted by his email address, fp@informatik.uni-frankfurt.de |
4 | * be contacted at fp@fpx.de |
5 | * |
5 | * |
6 | * This program is free software; you can redistribute it and/or modify |
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 |
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 |
8 | * the Free Software Foundation; either version 2 of the License, or |
9 | * (at your option) any later version. |
9 | * (at your option) any later version. |
… | |
… | |
47 | #endif |
47 | #endif |
48 | #ifdef HAVE_ERRNO_H |
48 | #ifdef HAVE_ERRNO_H |
49 | #include <errno.h> |
49 | #include <errno.h> |
50 | #endif |
50 | #endif |
51 | |
51 | |
52 | #include <uulib.h> |
52 | #include <uudeview.h> |
53 | #include <uuint.h> |
53 | #include <uuint.h> |
54 | #include <fptools.h> |
54 | #include <fptools.h> |
55 | #include <uustring.h> |
55 | #include <uustring.h> |
56 | |
56 | |
57 | char * uunconc_id = "$Id: uunconc.c,v 1.1 2001/06/11 19:49:00 root Exp $"; |
57 | char * uunconc_id = "$Id: uunconc.c,v 1.3 2002/02/10 22:47:18 root Exp $"; |
58 | |
58 | |
59 | /* for braindead systems */ |
59 | /* for braindead systems */ |
60 | #ifndef SEEK_SET |
60 | #ifndef SEEK_SET |
61 | #ifdef L_BEGIN |
61 | #ifdef L_BEGIN |
62 | #define SEEK_SET L_BEGIN |
62 | #define SEEK_SET L_BEGIN |
… | |
… | |
163 | UUxlat['`'] = UUxlat[' ']; |
163 | UUxlat['`'] = UUxlat[' ']; |
164 | UUxlat['~'] = UUxlat['^']; |
164 | UUxlat['~'] = UUxlat['^']; |
165 | |
165 | |
166 | /* prepare line length table */ |
166 | /* prepare line length table */ |
167 | UUxlen[0] = 1; |
167 | UUxlen[0] = 1; |
168 | for(i = 1, j = 5; i <= 60; i += 3, j += 4) |
168 | for(i = 1, j = 5; i <= 61; i += 3, j += 4) |
169 | UUxlen[i] = UUxlen[i+1] = UUxlen[i+2] = j; |
169 | UUxlen[i] = UUxlen[i+1] = UUxlen[i+2] = j; |
170 | |
170 | |
171 | /* prepare other tables */ |
171 | /* prepare other tables */ |
172 | for (i=0; i<64; i++) { |
172 | for (i=0; i<64; i++) { |
173 | B64xlat[ACAST(B64EncodeTable[i])] = i; |
173 | B64xlat[ACAST(B64EncodeTable[i])] = i; |
… | |
… | |
241 | /* |
241 | /* |
242 | * First pass |
242 | * First pass |
243 | */ |
243 | */ |
244 | while (*p1) { |
244 | while (*p1) { |
245 | if (*p1 == '&') { |
245 | if (*p1 == '&') { |
246 | if (FP_strnicmp (p1, "&", 5) == 0) { p1+=5; *p2++='&'; } |
246 | if (FP_strnicmp (p1, "&", 5) == 0) { p1+=5; *p2++='&'; res=1; } |
247 | else if (FP_strnicmp (p1, "<", 4) == 0) { p1+=4; *p2++='<'; } |
247 | else if (FP_strnicmp (p1, "<", 4) == 0) { p1+=4; *p2++='<'; res=1; } |
248 | else if (FP_strnicmp (p1, ">", 4) == 0) { p1+=4; *p2++='>'; } |
248 | else if (FP_strnicmp (p1, ">", 4) == 0) { p1+=4; *p2++='>'; res=1; } |
249 | else *p2++ = *p1++; |
249 | else *p2++ = *p1++; |
250 | res = 1; |
250 | res = 1; |
251 | } |
251 | } |
252 | else *p2++ = *p1++; |
252 | else *p2++ = *p1++; |
253 | } |
253 | } |
… | |
… | |
448 | * lowercase characters at least accepts the special case of encoding |
448 | * lowercase characters at least accepts the special case of encoding |
449 | * 0 as `. The strchr() shouldn't be too expensive here as it's only |
449 | * 0 as `. The strchr() shouldn't be too expensive here as it's only |
450 | * evaluated if the first character is lowercase, which really shouldn't |
450 | * evaluated if the first character is lowercase, which really shouldn't |
451 | * be in uuencoded text. |
451 | * be in uuencoded text. |
452 | */ |
452 | */ |
453 | if (len != j && |
453 | if (len != j && |
454 | !(*ptr != 'M' && *ptr != 'h' && len > j && len <= UUxlen[UUxlat['M']])) { |
454 | ((ptr[0] == '-' && ptr[1] == '-' && strstr(ptr,"part")!=NULL) || |
|
|
455 | !(*ptr != 'M' && *ptr != 'h' && |
|
|
456 | len > j && len <= UUxlen[UUxlat['M']]))) { |
455 | if (encoding==UU_ENCODED) return 0; |
457 | if (encoding==UU_ENCODED) return 0; |
456 | goto _t_XX; /* bad length */ |
458 | goto _t_XX; /* bad length */ |
457 | } |
459 | } |
458 | |
460 | |
459 | if (len != j || islower (*ptr)) { |
461 | if (len != j || islower (*ptr)) { |
… | |
… | |
859 | * with a linebreak. Or, as the docs put it, "the CRLF preceding the |
861 | * with a linebreak. Or, as the docs put it, "the CRLF preceding the |
860 | * encapsulation line is conceptually attached to the boundary. |
862 | * encapsulation line is conceptually attached to the boundary. |
861 | * So if the part ends here, don't print a line break" |
863 | * So if the part ends here, don't print a line break" |
862 | */ |
864 | */ |
863 | if ((*ptr == '\012' || *ptr == '\015') && |
865 | if ((*ptr == '\012' || *ptr == '\015') && |
864 | (!feof (datain) && |
|
|
865 | (ftell(datain)<maxpos || flags&FL_TOEND || flags&FL_PARTIAL || |
866 | (ftell(datain)<maxpos || flags&FL_TOEND || flags&FL_PARTIAL || |
866 | (!(flags&FL_PROPER) && uu_fast_scanning)))) { |
867 | !boundary || (!(flags&FL_PROPER) && uu_fast_scanning))) { |
867 | *ptr = '\0'; |
868 | *ptr = '\0'; |
868 | fprintf (dataout, "%s\n", line); |
869 | fprintf (dataout, "%s\n", line); |
869 | } |
870 | } |
870 | else { |
871 | else { |
871 | *ptr = '\0'; |
872 | *ptr = '\0'; |
… | |
… | |
1136 | FILE *datain, *dataout; |
1137 | FILE *datain, *dataout; |
1137 | unsigned char r[8]; |
1138 | unsigned char r[8]; |
1138 | char *mode, *ntmp; |
1139 | char *mode, *ntmp; |
1139 | uufile *iter; |
1140 | uufile *iter; |
1140 | size_t bytes; |
1141 | size_t bytes; |
|
|
1142 | #ifdef HAVE_MKSTEMP |
|
|
1143 | int tmpfd; |
|
|
1144 | const char *tmpprefix = "uuXXXXXX"; |
|
|
1145 | char *tmpdir = NULL; |
|
|
1146 | #endif /* HAVE_MKSTEMP */ |
1141 | |
1147 | |
1142 | if (data == NULL || data->thisfile == NULL) |
1148 | if (data == NULL || data->thisfile == NULL) |
1143 | return UURET_ILLVAL; |
1149 | return UURET_ILLVAL; |
1144 | |
1150 | |
1145 | if (data->state & UUFILE_TMPFILE) |
1151 | if (data->state & UUFILE_TMPFILE) |
… | |
… | |
1149 | return UURET_NODATA; |
1155 | return UURET_NODATA; |
1150 | |
1156 | |
1151 | if (data->state & UUFILE_NOBEGIN && !uu_desperate) |
1157 | if (data->state & UUFILE_NOBEGIN && !uu_desperate) |
1152 | return UURET_NODATA; |
1158 | return UURET_NODATA; |
1153 | |
1159 | |
1154 | if (data->uudet == QP_ENCODED || data->uudet == PT_ENCODED) |
1160 | if (data->uudet == PT_ENCODED) |
1155 | mode = "wt"; /* open text files in text mode */ |
1161 | mode = "wt"; /* open text files in text mode */ |
1156 | else |
1162 | else |
1157 | mode = "wb"; /* otherwise in binary */ |
1163 | mode = "wb"; /* otherwise in binary */ |
1158 | |
1164 | |
|
|
1165 | #ifdef HAVE_MKSTEMP |
|
|
1166 | if ((getuid()==geteuid()) && (getgid()==getegid())) { |
|
|
1167 | tmpdir=getenv("TMPDIR"); |
|
|
1168 | } |
|
|
1169 | |
|
|
1170 | if (!tmpdir) { |
|
|
1171 | tmpdir = "/tmp"; |
|
|
1172 | } |
|
|
1173 | data->binfile = malloc(strlen(tmpdir)+strlen(tmpprefix)+2); |
|
|
1174 | |
|
|
1175 | if (!data->binfile) { |
|
|
1176 | #else |
1159 | if ((data->binfile = tempnam (NULL, "uu")) == NULL) { |
1177 | if ((data->binfile = tempnam (NULL, "uu")) == NULL) { |
|
|
1178 | #endif /* HAVE_MKSTEMP */ |
1160 | UUMessage (uunconc_id, __LINE__, UUMSG_ERROR, |
1179 | UUMessage (uunconc_id, __LINE__, UUMSG_ERROR, |
1161 | uustring (S_NO_TEMP_NAME)); |
1180 | uustring (S_NO_TEMP_NAME)); |
1162 | return UURET_NOMEM; |
1181 | return UURET_NOMEM; |
1163 | } |
1182 | } |
1164 | |
1183 | |
|
|
1184 | #ifdef HAVE_MKSTEMP |
|
|
1185 | strcpy(data->binfile, tmpdir); |
|
|
1186 | strcat(data->binfile, "/"); |
|
|
1187 | strcat(data->binfile, tmpprefix); |
|
|
1188 | |
|
|
1189 | if ((tmpfd = mkstemp(data->binfile)) == -1 || |
|
|
1190 | (dataout = fdopen(tmpfd, mode)) == NULL) { |
|
|
1191 | #else |
1165 | if ((dataout = fopen (data->binfile, mode)) == NULL) { |
1192 | if ((dataout = fopen (data->binfile, mode)) == NULL) { |
|
|
1193 | #endif /* HAVE_MKSTEMP */ |
1166 | /* |
1194 | /* |
1167 | * we couldn't create a temporary file. Usually this means that TMP |
1195 | * we couldn't create a temporary file. Usually this means that TMP |
1168 | * and TEMP aren't set |
1196 | * and TEMP aren't set |
1169 | */ |
1197 | */ |
1170 | UUMessage (uunconc_id, __LINE__, UUMSG_ERROR, |
1198 | UUMessage (uunconc_id, __LINE__, UUMSG_ERROR, |
1171 | uustring (S_WR_ERR_TARGET), |
1199 | uustring (S_WR_ERR_TARGET), |
1172 | data->binfile, strerror (uu_errno = errno)); |
1200 | data->binfile, strerror (uu_errno = errno)); |
|
|
1201 | #ifdef HAVE_MKSTEMP |
|
|
1202 | if (tmpfd != -1) { |
|
|
1203 | unlink(data->binfile); |
|
|
1204 | close(tmpfd); |
|
|
1205 | } |
|
|
1206 | #endif /* HAVE_MKSTEMP */ |
1173 | FP_free (data->binfile); |
1207 | FP_free (data->binfile); |
1174 | data->binfile = NULL; |
1208 | data->binfile = NULL; |
1175 | uu_errno = errno; |
1209 | uu_errno = errno; |
1176 | return UURET_IOERR; |
1210 | return UURET_IOERR; |
1177 | } |
1211 | } |
|
|
1212 | |
1178 | /* |
1213 | /* |
1179 | * we don't have begin lines in Base64 or plain text files. |
1214 | * we don't have begin lines in Base64 or plain text files. |
1180 | */ |
1215 | */ |
1181 | if (data->uudet == B64ENCODED || data->uudet == QP_ENCODED || |
1216 | if (data->uudet == B64ENCODED || data->uudet == QP_ENCODED || |
1182 | data->uudet == PT_ENCODED) |
1217 | data->uudet == PT_ENCODED) |
… | |
… | |
1316 | /* |
1351 | /* |
1317 | * If this was a BinHex file, we must extract its data or resource fork |
1352 | * If this was a BinHex file, we must extract its data or resource fork |
1318 | */ |
1353 | */ |
1319 | |
1354 | |
1320 | if (data->uudet == BH_ENCODED && data->binfile) { |
1355 | if (data->uudet == BH_ENCODED && data->binfile) { |
|
|
1356 | #ifdef HAVE_MKSTEMP |
|
|
1357 | ntmp = malloc(strlen(tmpdir)+strlen(tmpprefix)+2); |
|
|
1358 | |
|
|
1359 | if (ntmp == NULL) { |
|
|
1360 | #else |
1321 | if ((ntmp = tempnam (NULL, "uu")) == NULL) { |
1361 | if ((ntmp = tempnam (NULL, "uu")) == NULL) { |
|
|
1362 | #endif /* HAVE_MKSTEMP */ |
1322 | UUMessage (uunconc_id, __LINE__, UUMSG_ERROR, |
1363 | UUMessage (uunconc_id, __LINE__, UUMSG_ERROR, |
1323 | uustring (S_NO_TEMP_NAME)); |
1364 | uustring (S_NO_TEMP_NAME)); |
1324 | progress.action = 0; |
1365 | progress.action = 0; |
1325 | return UURET_NOMEM; |
1366 | return UURET_NOMEM; |
1326 | } |
1367 | } |
… | |
… | |
1330 | data->binfile, strerror (uu_errno = errno)); |
1371 | data->binfile, strerror (uu_errno = errno)); |
1331 | progress.action = 0; |
1372 | progress.action = 0; |
1332 | free (ntmp); |
1373 | free (ntmp); |
1333 | return UURET_IOERR; |
1374 | return UURET_IOERR; |
1334 | } |
1375 | } |
|
|
1376 | #ifdef HAVE_MKSTEMP |
|
|
1377 | strcpy(ntmp, tmpdir); |
|
|
1378 | strcat(ntmp, "/"); |
|
|
1379 | strcat(ntmp, tmpprefix); |
|
|
1380 | if ((tmpfd = mkstemp(ntmp)) == -1 || |
|
|
1381 | (dataout = fdopen(tmpfd, "wb")) == NULL) { |
|
|
1382 | #else |
1335 | if ((dataout = fopen (ntmp, "wb")) == NULL) { |
1383 | if ((dataout = fopen (ntmp, "wb")) == NULL) { |
|
|
1384 | #endif /* HAVE_MKSTEMP */ |
1336 | UUMessage (uunconc_id, __LINE__, UUMSG_ERROR, |
1385 | UUMessage (uunconc_id, __LINE__, UUMSG_ERROR, |
1337 | uustring (S_NOT_OPEN_TARGET), |
1386 | uustring (S_NOT_OPEN_TARGET), |
1338 | ntmp, strerror (uu_errno = errno)); |
1387 | ntmp, strerror (uu_errno = errno)); |
1339 | progress.action = 0; |
1388 | progress.action = 0; |
1340 | fclose (datain); |
1389 | fclose (datain); |
|
|
1390 | #ifdef HAVE_MKSTEMP |
|
|
1391 | if (tmpfd != -1) { |
|
|
1392 | unlink(ntmp); |
|
|
1393 | close(tmpfd); |
|
|
1394 | } |
|
|
1395 | #endif /* HAVE_MKSTEMP */ |
1341 | free (ntmp); |
1396 | free (ntmp); |
1342 | return UURET_IOERR; |
1397 | return UURET_IOERR; |
1343 | } |
1398 | } |
|
|
1399 | |
1344 | /* |
1400 | /* |
1345 | * read fork lengths. remember they're in Motorola format |
1401 | * read fork lengths. remember they're in Motorola format |
1346 | */ |
1402 | */ |
1347 | r[0] = fgetc (datain); |
1403 | r[0] = fgetc (datain); |
1348 | hb = (int) r[0] + 22; |
1404 | hb = (int) r[0] + 22; |