uunconc.c
来自「UUDeview是一个编码解码器」· C语言 代码 · 共 1,686 行 · 第 1/3 页
C
1,686 行
* the next line. Then we try this in our despair */ if (vflag == 0) { if (UUNetscapeCollapse (line)) vflag = UUValidData (line, encoding, bhflag); } /* * If this line looks uuencoded, but the line is one character short * of a valid line, it was probably broken by MS Exchange. According * to my test cases, there is at most one space character missing; * there are never two spaces together. * If adding a space character helps making this line uuencoded, do * it! */ if (vflag == 0) { ptr = line + strlen(line); while (ptr>line && (*(ptr-1)=='\012' || *(ptr-1)=='\015')) { ptr--; } *ptr++ = ' '; *ptr-- = '\0'; if ((vflag = UUValidData (line, encoding, bhflag)) != UU_ENCODED) { *ptr = '\0'; vflag = 0; } } return vflag;}/* * Decode a single encoded line using method */size_tUUDecodeLine (char *s, char *d, int method){ int i, j, c, cc, count=0, z1, z2, z3, z4; static int leftover=0; int *table; /* * for re-initialization */ if (s == NULL || d == NULL) { leftover = 0; return 0; } /* * To shut up gcc -Wall */ z1 = z2 = z3 = z4 = 0; if (method == UU_ENCODED || method == XX_ENCODED) { if (method == UU_ENCODED) table = UUxlat; else table = XXxlat; i = table [ACAST(*s++)]; j = UUxlen[i] - 1; while(j > 0) { c = table[ACAST(*s++)] << 2; cc = table[ACAST(*s++)]; c |= (cc >> 4); if(i-- > 0) d[count++] = c; cc <<= 4; c = table[ACAST(*s++)]; cc |= (c >> 2); if(i-- > 0) d[count++] = cc; c <<= 6; c |= table[ACAST(*s++)]; if(i-- > 0) d[count++] = c; j -= 4; } } else if (method == B64ENCODED) { if (leftover) { strcpy (uuncdl_fulline+leftover, s); leftover = 0; s = uuncdl_fulline; } while ((z1 = B64xlat[ACAST(*s)]) != -1) { if ((z2 = B64xlat[ACAST(*(s+1))]) == -1) break; if ((z3 = B64xlat[ACAST(*(s+2))]) == -1) break; if ((z4 = B64xlat[ACAST(*(s+3))]) == -1) break; d[count++] = (z1 << 2) | (z2 >> 4); d[count++] = (z2 << 4) | (z3 >> 2); d[count++] = (z3 << 6) | (z4); s += 4; } if (z1 != -1 && z2 != -1 && *(s+2) == '=') { d[count++] = (z1 << 2) | (z2 >> 4); s+=2; } else if (z1 != -1 && z2 != -1 && z3 != -1 && *(s+3) == '=') { d[count++] = (z1 << 2) | (z2 >> 4); d[count++] = (z2 << 4) | (z3 >> 2); s+=3; } while (B64xlat[ACAST(*s)] != -1) uuncdl_fulline[leftover++] = *s++; } else if (method == BH_ENCODED) { if (leftover) { strcpy (uuncdl_fulline+leftover, s); leftover = 0; s = uuncdl_fulline; } else if (*s == ':') s++; while ((z1 = BHxlat[ACAST(*s)]) != -1) { if ((z2 = BHxlat[ACAST(*(s+1))]) == -1) break; if ((z3 = BHxlat[ACAST(*(s+2))]) == -1) break; if ((z4 = BHxlat[ACAST(*(s+3))]) == -1) break; d[count++] = (z1 << 2) | (z2 >> 4); d[count++] = (z2 << 4) | (z3 >> 2); d[count++] = (z3 << 6) | (z4); s += 4; } if (z1 != -1 && z2 != -1 && *(s+2) == ':') { d[count++] = (z1 << 2) | (z2 >> 4); s+=2; } else if (z1 != -1 && z2 != -1 && z3 != -1 && *(s+3) == ':') { d[count++] = (z1 << 2) | (z2 >> 4); d[count++] = (z2 << 4) | (z3 >> 2); s+=3; } while (BHxlat[ACAST(*s)] != -1) uuncdl_fulline[leftover++] = *s++; } else if (method == YENC_ENCODED) { while (*s) { if (*s == '=') { if (*++s != '\0') { d[count++] = (char) ((int) *s - 64 - 42); s++; } } else if (*s == '\n' || *s == '\r') { s++; /* ignore */ } else { d[count++] = (char) ((int) *s++ - 42); } } } return count;}/* * ``Decode'' Quoted-Printable text */intUUDecodeQP (FILE *datain, FILE *dataout, int *state, long maxpos, int method, int flags, char *boundary){ char *line=uugen_inbuffer, *p1, *p2; int val; uulboundary = -1; while (!feof (datain) && (ftell(datain)<maxpos || flags&FL_TOEND || (!(flags&FL_PROPER) && uu_fast_scanning))) { if (_FP_fgets (line, 255, datain) == NULL) break; if (ferror (datain)) { UUMessage (uunconc_id, __LINE__, UUMSG_ERROR, uustring (S_SOURCE_READ_ERR), strerror (uu_errno = errno)); return UURET_IOERR; } line[255] = '\0'; if (boundary && line[0]=='-' && line[1]=='-' && strncmp (line+2, boundary, strlen (boundary)) == 0) { if (line[strlen(boundary)+2]=='-') uulboundary = 1; else uulboundary = 0; return UURET_OK; } if (UUBUSYPOLL(ftell(datain)-progress.foffset,progress.fsize)) { UUMessage (uunconc_id, __LINE__, UUMSG_NOTE, uustring (S_DECODE_CANCEL)); return UURET_CANCEL; } p1 = p2 = line; while (*p2) { while (*p2 && *p2 != '=') p2++; if (*p2 == '\0') break; *p2 = '\0'; fprintf (dataout, "%s", p1); p1 = ++p2; if (isxdigit (*p2) && isxdigit (*(p2+1))) { val = ((isdigit(*p2)) ? (*p2-'0') : (tolower(*p2)-'a'+10)) << 4; val |= ((isdigit(*(p2+1)))?(*(p2+1)-'0') : (tolower(*(p2+1))-'a'+10)); fputc (val, dataout); p2 += 2; p1 = p2; } else if (*p2 == '\012' || *(p2+1) == '\015') { /* soft line break */ *p2 = '\0'; break; } else { /* huh? */ fputc ('=', dataout); } } /* * p2 points to a nullbyte right after the CR/LF/CRLF */ val = 0; while (p2>p1 && isspace (*(p2-1))) { if (*(p2-1) == '\012' || *(p2-1) == '\015') val = 1; p2--; } *p2 = '\0'; /* * If the part ends directly after this line, the data does not end * with a linebreak. Or, as the docs put it, "the CRLF preceding the * encapsulation line is conceptually attached to the boundary. * So if the part ends here, don't print a line break" */ if (val && (!feof (datain) && (ftell(datain)<maxpos || flags&FL_TOEND || (!(flags&FL_PROPER) && uu_fast_scanning)))) fprintf (dataout, "%s\n", p1); else fprintf (dataout, "%s", p1); } return UURET_OK;}/* * ``Decode'' plain text. Our job is to properly handle the EOL sequence */intUUDecodePT (FILE *datain, FILE *dataout, int *state, long maxpos, int method, int flags, char *boundary){ char *line=uugen_inbuffer, *ptr; uulboundary = -1; while (!feof (datain) && (ftell(datain)<maxpos || flags&FL_TOEND || (!(flags&FL_PROPER) && uu_fast_scanning))) { if (_FP_fgets (line, 255, datain) == NULL) break; if (ferror (datain)) { UUMessage (uunconc_id, __LINE__, UUMSG_ERROR, uustring (S_SOURCE_READ_ERR), strerror (uu_errno = errno)); return UURET_IOERR; } line[255] = '\0'; if (boundary && line[0]=='-' && line[1]=='-' && strncmp (line+2, boundary, strlen (boundary)) == 0) { if (line[strlen(boundary)+2]=='-') uulboundary = 1; else uulboundary = 0; return UURET_OK; } if (UUBUSYPOLL(ftell(datain)-progress.foffset,progress.fsize)) { UUMessage (uunconc_id, __LINE__, UUMSG_NOTE, uustring (S_DECODE_CANCEL)); return UURET_CANCEL; } ptr = line + strlen (line); while (ptr>line && (*(ptr-1) == '\012' || *(ptr-1) == '\015')) ptr--; /* * If the part ends directly after this line, the data does not end * with a linebreak. Or, as the docs put it, "the CRLF preceding the * encapsulation line is conceptually attached to the boundary. * So if the part ends here, don't print a line break" */ if ((*ptr == '\012' || *ptr == '\015') && (ftell(datain)<maxpos || flags&FL_TOEND || flags&FL_PARTIAL || !boundary || (!(flags&FL_PROPER) && uu_fast_scanning))) { *ptr = '\0'; fprintf (dataout, "%s\n", line); } else { *ptr = '\0'; fprintf (dataout, "%s", line); } } return UURET_OK;}/* * Decode a single field using method. For the moment, this supports * Base64 and Quoted Printable only, to support RFC 1522 header decoding. * Quit when seeing the RFC 1522 ?= end marker. */intUUDecodeField (char *s, char *d, int method){ int z1, z2, z3, z4; int count=0; if (method == B64ENCODED) { while ((z1 = B64xlat[ACAST(*s)]) != -1) { if ((z2 = B64xlat[ACAST(*(s+1))]) == -1) break; if ((z3 = B64xlat[ACAST(*(s+2))]) == -1) break; if ((z4 = B64xlat[ACAST(*(s+3))]) == -1) break; d[count++] = (z1 << 2) | (z2 >> 4); d[count++] = (z2 << 4) | (z3 >> 2); d[count++] = (z3 << 6) | (z4); s+=4; } if (z1 != -1 && z2 != -1 && *(s+2) == '=') { d[count++] = (z1 << 2) | (z2 >> 4); s+=2; } else if (z1 != -1 && z2 != -1 && z3 != -1 && *(s+3) == '=') { d[count++] = (z1 << 2) | (z2 >> 4); d[count++] = (z2 << 4) | (z3 >> 2); s+=3; } } else if (method == QP_ENCODED) { while (*s && (*s != '?' || *(s+1) != '=')) { while (*s && *s != '=' && (*s != '?' || *(s+1) != '=')) { d[count++] = *s++; } if (*s == '=') { if (isxdigit (*(s+1)) && isxdigit (*(s+2))) { d[count] = (isdigit (*(s+1)) ? (*(s+1)-'0') : (tolower (*(s+1))-'a'+10)) << 4; d[count] |= (isdigit (*(s+2)) ? (*(s+2)-'0') : (tolower (*(s+2))-'a'+10)); count++; s+=3; } else if (*(s+1) == '\012' || *(s+1) == '\015') { s+=2; } else { d[count++] = *s++; } } } } else { return -1; } d[count] = '\0'; return count;}intUUDecodePart (FILE *datain, FILE *dataout, int *state, long maxpos, int method, int flags, char *boundary){ char *line=uugen_fnbuffer, *oline=uuncdp_oline; int warning=0, vlc=0, lc[2], hadct=0; int tc=0, tf=0, vflag, haddata=0, haddh=0; long yefilesize=0, yepartends=0; crc32_t yepartcrc=crc32(0L, Z_NULL, 0); static crc32_t yefilecrc=0; static int bhflag=0; size_t count=0; size_t yepartsize=0; char *ptr; if (datain == NULL || dataout == NULL) { yefilecrc = crc32(0L, Z_NULL, 0); bhflag = 0; return UURET_OK; } /* * Use specialized functions for QP_ENCODED and PT_ENCODED plaintext */ if (method == QP_ENCODED) return UUDecodeQP (datain, dataout, state, maxpos, method, flags, boundary); else if (method == PT_ENCODED) return UUDecodePT (datain, dataout, state, maxpos, method, flags, boundary); lc[0] = lc[1] = 0; vflag = 0; uulboundary = -1; if (method == YENC_ENCODED) { *state = BEGIN; } while (!feof (datain) && *state != DONE && (ftell(datain)<maxpos || flags&FL_TOEND || maxpos==-1 || (!(flags&FL_PROPER) && uu_fast_scanning))) { if (_FP_fgets (line, 255, datain) == NULL) break; if (ferror (datain)) { UUMessage (uunconc_id, __LINE__, UUMSG_ERROR, uustring (S_SOURCE_READ_ERR), strerror (uu_errno = errno)); return UURET_IOERR; } if (line[0]=='\015' || line[0]=='\012') { /* Empty line? */ if (*state == DATA && (method == UU_ENCODED || method == XX_ENCODED)) *state = END; /* * if we had a whole block of valid lines before, we reset our * 'valid data' flag, tf. Without this 'if', we'd break decoding * files with interleaved blank lines. The value of 5 is chosen * quite arbitrarly. */ if (vlc > 5) tf = tc = 0; vlc = 0; continue; } /* * Busy Polls */ if (UUBUSYPOLL(ftell(datain)-progress.foffset,progress.fsize)) { UUMessage (uunconc_id, __LINE__, UUMSG_NOTE, uustring (S_DECODE_CANCEL)); return UURET_CANCEL; } /* * try to make sense of data */ line[255] = '\0'; /* For Safety of string functions */ count = 0; if (boundary && line[0]=='-' && line[1]=='-' && strncmp (line+2, boundary, strlen (boundary)) == 0) { if (line[strlen(boundary)+2]=='-') uulboundary = 1; else uulboundary = 0; return UURET_OK; } /* * Use this pseudo-handling only if !FL_PROPER */ if ((flags&FL_PROPER) == 0) { if (strncmp (line, "BEGIN", 5) == 0 && _FP_strstr (line, "CUT HERE") && !tf) { /* I hate these lines */ tc = tf = vlc = 0; continue; } /* MIME body boundary */ if (line[0] == '-' && line[1] == '-' && method == B64ENCODED) { if ((haddata || tc) && (haddh || hadct)) { *state = DONE; vlc = 0; lc[0] = lc[1] = 0; continue; } hadct = 0; haddh = 1; continue; } if (_FP_strnicmp (line, "Content-Type", 12) == 0) hadct = 1; } if (*state == BEGIN) { if ((method == UU_ENCODED || method == XX_ENCODED) && (strncmp (line, "begin ", 6) == 0 || _FP_strnicmp (line, "<pre>begin ", 11) == 0)) { /* for LYNX */ *state = DATA; continue; } else if (method == BH_ENCODED && line[0] == ':') { if (UUValidData (line, BH_ENCODED, &bhflag) == BH_ENCODED) { bhflag = 0; *state = DATA; } else continue; } else if (method == YENC_ENCODED && strncmp (line, "=ybegin ", 8) == 0 && _FP_strstr (line, " name=") != NULL) { *state = DATA; if ((ptr = _FP_strstr (line, " size=")) != NULL) { ptr += 6; yefilesize = atoi (ptr); } else { yefilesize = -1; } if (_FP_strstr (line, " part=") != NULL) { if (_FP_fgets (line, 255, datain) == NULL) { break; } if ((ptr = _FP_strstr (line, " end=")) == NULL) { break; } yepartends = atoi (ptr + 5);
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?