uunconc.c
来自「UUDeview是一个编码解码器」· C语言 代码 · 共 1,686 行 · 第 1/3 页
C
1,686 行
} tf = 1; continue; } else { continue; } tc = tf = vlc = 0; lc[0] = lc[1] = 0; } else if ((*state == END) && (method == UU_ENCODED || method == XX_ENCODED)) { if (strncmp (line, "end", 3) == 0) { *state = DONE; break; } } if (*state == DATA && method == YENC_ENCODED && strncmp (line, "=yend ", 6) == 0) { if ((ptr = _FP_strstr (line, " pcrc32=")) != NULL) { crc32_t pcrc32 = strtoul (ptr + 8, NULL, 16); if (pcrc32 != yepartcrc) { UUMessage (uunconc_id, __LINE__, UUMSG_WARNING, uustring (S_PCRC_MISMATCH), progress.curfile, progress.partno); } } if ((ptr = _FP_strstr (line, " crc32=")) != NULL) { crc32_t fcrc32 = strtoul (ptr + 7, NULL, 16); if (fcrc32 != yefilecrc) { UUMessage (uunconc_id, __LINE__, UUMSG_WARNING, uustring (S_CRC_MISMATCH), progress.curfile); } } if ((ptr = _FP_strstr (line, " size=")) != NULL) { size_t size = atol(ptr + 6); if (size != yepartsize && yefilesize != -1) { if (size != yefilesize) UUMessage (uunconc_id, __LINE__, UUMSG_WARNING, uustring (S_PSIZE_MISMATCH), progress.curfile, progress.partno, yepartsize, size); else UUMessage (uunconc_id, __LINE__, UUMSG_WARNING, uustring (S_SIZE_MISMATCH), progress.curfile, yepartsize, size); } } if (yepartends == 0 || yepartends >= yefilesize) { *state = DONE; } break; } if (*state == DATA || *state == END) { if (method==B64ENCODED && line[0]=='-' && line[1]=='-' && tc) { break; } if ((vflag = UUValidData (line, (tf)?method:0, &bhflag)) == 0) vflag = UURepairData (datain, line, (tf)?method:0, &bhflag); /* * correct XX/UUencoded lines that were declared Base64 */ if ((method == XX_ENCODED || method == UU_ENCODED) && vflag == B64ENCODED) { if (UUValidData (line, method, &bhflag) == method) vflag = method; } if (vflag == method) { if (tf) { count = UUDecodeLine (line, oline, method); if (method == YENC_ENCODED) { if (yepartends) yepartcrc = crc32(yepartcrc, oline, count); yefilecrc = crc32(yefilecrc, oline, count); yepartsize += count; } vlc++; lc[1]++; } else if (tc == 3) { count = UUDecodeLine (save[0], oline, method); count += UUDecodeLine (save[1], oline + count, method); count += UUDecodeLine (save[2], oline + count, method); count += UUDecodeLine (line, oline + count, method); tf = 1; tc = 0; /* * complain if we had one or two invalid lines amidst of * correctly encoded data. This usually means that the * file is in error */ if (lc[1] > 10 && (lc[0] >= 1 && lc[0] <= 2) && !warning) { UUMessage (uunconc_id, __LINE__, UUMSG_WARNING, uustring (S_DATA_SUSPICIOUS)); warning=1; } lc[0] = 0; lc[1] = 3; } else { _FP_strncpy (save[tc++], line, 256); } if (method == UU_ENCODED) *state = (line[0] == 'M') ? DATA : END; else if (method == XX_ENCODED) *state = (line[0] == 'h') ? DATA : END; else if (method == B64ENCODED) *state = (strchr (line, '=') == NULL) ? DATA : DONE; else if (method == BH_ENCODED) *state = (!line[0] || strchr(line+1,':')==NULL)?DATA:DONE; } else { vlc = tf = tc = 0; haddh = 0; lc[0]++; } } else if (*state != DONE) { return UURET_NOEND; } if (count) { if (method == BH_ENCODED) { if (UUbhwrite (oline, 1, count, dataout) != count) { UUMessage (uunconc_id, __LINE__, UUMSG_ERROR, uustring (S_WR_ERR_TEMP), strerror (uu_errno = errno)); return UURET_IOERR; } } else if (fwrite (oline, 1, count, dataout) != count) { UUMessage (uunconc_id, __LINE__, UUMSG_ERROR, uustring (S_WR_ERR_TEMP), strerror (uu_errno = errno)); return UURET_IOERR; } haddata++; count = 0; } } if (*state == DONE || (*state == DATA && method == B64ENCODED && vflag == B64ENCODED && (flags&FL_PROPER || haddh))) { for (tf=0; tf<tc; tf++) count += UUDecodeLine (save[tf], oline + count, method); if (count) { if (method == BH_ENCODED) { if (UUbhwrite (oline, 1, count, dataout) != count) { UUMessage (uunconc_id, __LINE__, UUMSG_ERROR, uustring (S_WR_ERR_TEMP), strerror (uu_errno = errno)); return UURET_IOERR; } } else if (fwrite (oline, 1, count, dataout) != count) { UUMessage (uunconc_id, __LINE__, UUMSG_ERROR, uustring (S_WR_ERR_TEMP), strerror (uu_errno = errno)); return UURET_IOERR; } } } return UURET_OK;}/* * this function decodes the file into a temporary file */intUUDecode (uulist *data){ int state=BEGIN, part=-1, res=0, hb; long rsize, dsize, numbytes; FILE *datain, *dataout; unsigned char r[8]; char *mode, *ntmp; uufile *iter; size_t bytes; if (data == NULL || data->thisfile == NULL) return UURET_ILLVAL; if (data->state & UUFILE_TMPFILE) return UURET_OK; if (data->state & UUFILE_NODATA) return UURET_NODATA; if (data->state & UUFILE_NOBEGIN && !uu_desperate) return UURET_NODATA; if (data->uudet == PT_ENCODED) mode = "wt"; /* open text files in text mode */ else mode = "wb"; /* otherwise in binary */ if ((data->binfile = tempnam (NULL, "uu")) == NULL) { UUMessage (uunconc_id, __LINE__, UUMSG_ERROR, uustring (S_NO_TEMP_NAME)); return UURET_NOMEM; } if ((dataout = fopen (data->binfile, mode)) == NULL) { /* * we couldn't create a temporary file. Usually this means that TMP * and TEMP aren't set */ UUMessage (uunconc_id, __LINE__, UUMSG_ERROR, uustring (S_WR_ERR_TARGET), data->binfile, strerror (uu_errno = errno)); _FP_free (data->binfile); data->binfile = NULL; uu_errno = errno; return UURET_IOERR; } /* * we don't have begin lines in Base64 or plain text files. */ if (data->uudet == B64ENCODED || data->uudet == QP_ENCODED || data->uudet == PT_ENCODED) state = DATA; /* * If we know that the file does not have a begin, we simulate * it in desperate mode */ if ((data->state & UUFILE_NOBEGIN) && uu_desperate) state = DATA; (void) UUDecodeLine (NULL, NULL, 0); /* init */ (void) UUbhwrite (NULL, 0, 0, NULL); /* dito */ (void) UUDecodePart (NULL, NULL, NULL, 0, 0, 0, NULL); /* yep */ /* * initialize progress information */ progress.action = 0; if (data->filename != NULL) { _FP_strncpy (progress.curfile, (strlen(data->filename)>255)? (data->filename+strlen(data->filename)-255):data->filename, 256); } else { _FP_strncpy (progress.curfile, (strlen(data->binfile)>255)? (data->binfile+strlen(data->binfile)-255):data->binfile, 256); } progress.partno = 0; progress.numparts = 0; progress.fsize = -1; progress.percent = 0; progress.action = UUACT_DECODING; iter = data->thisfile; while (iter) { progress.numparts = (iter->partno)?iter->partno:1; iter = iter->NEXT; } /* * let's rock! */ iter = data->thisfile; while (iter) { if (part != -1 && iter->partno != part+1 && !uu_desperate) break; else part = iter->partno; if (iter->data->sfname == NULL) { iter = iter->NEXT; continue; } /* * call our FileCallback to retrieve the file */ if (uu_FileCallback) { if ((res = (*uu_FileCallback) (uu_FileCBArg, iter->data->sfname, uugen_fnbuffer, 1)) != UURET_OK) break; if ((datain = fopen (uugen_fnbuffer, "rb")) == NULL) { (*uu_FileCallback) (uu_FileCBArg, iter->data->sfname, uugen_fnbuffer, 0); UUMessage (uunconc_id, __LINE__, UUMSG_ERROR, uustring (S_NOT_OPEN_FILE), uugen_fnbuffer, strerror (uu_errno = errno)); res = UURET_IOERR; break; } } else { if ((datain = fopen (iter->data->sfname, "rb")) == NULL) { UUMessage (uunconc_id, __LINE__, UUMSG_ERROR, uustring (S_NOT_OPEN_FILE), iter->data->sfname, strerror (uu_errno = errno)); res = UURET_IOERR; break; } _FP_strncpy (uugen_fnbuffer, iter->data->sfname, 1024); } progress.partno = part; progress.fsize = (iter->data->length)?iter->data->length:-1; progress.percent = 0; progress.foffset = iter->data->startpos; fseek (datain, iter->data->startpos, SEEK_SET); res = UUDecodePart (datain, dataout, &state, iter->data->startpos+iter->data->length, data->uudet, iter->data->flags, NULL); fclose (datain); if (uu_FileCallback) (*uu_FileCallback) (uu_FileCBArg, iter->data->sfname, uugen_fnbuffer, 0); if (state == DONE || res != UURET_OK) break; iter = iter->NEXT; } if (state == DATA && (data->uudet == B64ENCODED || data->uudet == QP_ENCODED || data->uudet == PT_ENCODED)) state = DONE; /* assume we're done */ if (fclose (dataout)) { UUMessage (uunconc_id, __LINE__, UUMSG_ERROR, uustring (S_WR_ERR_TEMP), strerror (uu_errno = errno)); res = UURET_IOERR; } if (res != UURET_OK || (state != DONE && !uu_desperate)) { unlink (data->binfile); _FP_free (data->binfile); data->binfile = NULL; data->state &= ~UUFILE_TMPFILE; data->state |= UUFILE_ERROR; if (res == UURET_OK && state != DONE) res = UURET_NOEND; } else if (res != UURET_OK) { data->state &= ~UUFILE_DECODED; data->state |= UUFILE_ERROR | UUFILE_TMPFILE; } else { data->state &= ~UUFILE_ERROR; data->state |= UUFILE_TMPFILE; } /* * If this was a BinHex file, we must extract its data or resource fork */ if (data->uudet == BH_ENCODED && data->binfile) { if ((ntmp = tempnam (NULL, "uu")) == NULL) { UUMessage (uunconc_id, __LINE__, UUMSG_ERROR, uustring (S_NO_TEMP_NAME)); progress.action = 0; return UURET_NOMEM; } if ((datain = fopen (data->binfile, "rb")) == NULL) { UUMessage (uunconc_id, __LINE__, UUMSG_ERROR, uustring (S_NOT_OPEN_FILE), data->binfile, strerror (uu_errno = errno)); progress.action = 0; free (ntmp); return UURET_IOERR; } if ((dataout = fopen (ntmp, "wb")) == NULL) { UUMessage (uunconc_id, __LINE__, UUMSG_ERROR, uustring (S_NOT_OPEN_TARGET), ntmp, strerror (uu_errno = errno)); progress.action = 0; fclose (datain); free (ntmp); return UURET_IOERR; } /* * read fork lengths. remember they're in Motorola format */ r[0] = fgetc (datain); hb = (int) r[0] + 22; fseek (datain, (int) r[0] + 12, SEEK_SET); fread (r, 1, 8, datain); dsize = (((long) 1 << 24) * (long) r[0]) + (((long) 1 << 16) * (long) r[1]) + (((long) 1 << 8) * (long) r[2]) + ( (long) r[3]); rsize = (((long) 1 << 24) * (long) r[4]) + (((long) 1 << 16) * (long) r[5]) + (((long) 1 << 8) * (long) r[6]) + ( (long) r[7]); UUMessage (uunconc_id, __LINE__, UUMSG_MESSAGE, uustring (S_BINHEX_SIZES), dsize, rsize); if (dsize == 0) { fseek (datain, dsize + hb + 2, SEEK_SET); numbytes = rsize; } else if (rsize == 0) { fseek (datain, hb, SEEK_SET); numbytes = dsize; } else { /* we should let the user have the choice here */ UUMessage (uunconc_id, __LINE__, UUMSG_NOTE, uustring (S_BINHEX_BOTH)); fseek (datain, hb, SEEK_SET); numbytes = dsize; } progress.action = 0; progress.partno = 0; progress.numparts = 1; progress.fsize = (numbytes)?numbytes:-1; progress.foffset = hb; progress.percent = 0; progress.action = UUACT_COPYING; /* * copy the chosen fork */ while (!feof (datain) && numbytes) { if (UUBUSYPOLL(ftell(datain)-progress.foffset,progress.fsize)) { UUMessage (uunconc_id, __LINE__, UUMSG_NOTE, uustring (S_DECODE_CANCEL)); fclose (datain); fclose (dataout); unlink (ntmp); free (ntmp); return UURET_CANCEL; } bytes = fread (uugen_inbuffer, 1, (size_t) ((numbytes>1024)?1024:numbytes), datain); if (ferror (datain) || (bytes == 0 && !feof (datain))) { progress.action = 0; UUMessage (uunconc_id, __LINE__, UUMSG_ERROR, uustring (S_SOURCE_READ_ERR), data->binfile, strerror (uu_errno = errno)); fclose (datain); fclose (dataout); unlink (ntmp); free (ntmp); return UURET_IOERR; } if (fwrite (uugen_inbuffer, 1, bytes, dataout) != bytes) { progress.action = 0; UUMessage (uunconc_id, __LINE__, UUMSG_ERROR, uustring (S_WR_ERR_TARGET), ntmp, strerror (uu_errno = errno)); fclose (datain); fclose (dataout); unlink (ntmp); free (ntmp); return UURET_IOERR; } numbytes -= bytes; } if (numbytes) { UUMessage (uunconc_id, __LINE__, UUMSG_WARNING, uustring (S_SHORT_BINHEX), (data->filename)?data->filename: (data->subfname)?data->subfname:"???", numbytes); } /* * replace temp file */ fclose (datain); if (fclose (dataout)) { UUMessage (uunconc_id, __LINE__, UUMSG_ERROR, uustring (S_WR_ERR_TARGET), ntmp, strerror (uu_errno = errno)); unlink (ntmp); free (ntmp); return UURET_IOERR; } if (unlink (data->binfile)) { UUMessage (uunconc_id, __LINE__, UUMSG_WARNING, uustring (S_TMP_NOT_REMOVED), data->binfile, strerror (uu_errno = errno)); } free (data->binfile); data->binfile = ntmp; } progress.action = 0; return res;}/* * QuickDecode for proper MIME attachments. We expect the pointer to * be on the first header line. */intUUQuickDecode (FILE *datain, FILE *dataout, char *boundary, long maxpos){ int state=BEGIN, encoding=-1; headers myenv; /* * Read header and find out about encoding. */ memset (&myenv, 0, sizeof (headers)); UUScanHeader (datain, &myenv); if (_FP_stristr (myenv.ctenc, "uu") != NULL) encoding = UU_ENCODED; else if (_FP_stristr (myenv.ctenc, "xx") != NULL) encoding = XX_ENCODED; else if (_FP_stricmp (myenv.ctenc, "base64") == 0) encoding = B64ENCODED; else if (_FP_stricmp (myenv.ctenc, "quoted-printable") == 0) encoding = QP_ENCODED; else encoding = PT_ENCODED; UUkillheaders (&myenv); /* * okay, so decode this one */ (void) UUDecodePart (NULL, NULL, NULL, 0, 0, 0, NULL); /* init */ return UUDecodePart (datain, dataout, &state, maxpos, encoding, FL_PROPER|FL_TOEND, boundary);}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?