uuscan.c
来自「UUDeview是一个编码解码器」· C语言 代码 · 共 2,492 行 · 第 1/5 页
C
2,492 行
result->begin = 1; } /* * Don't want auto-detection */ result->uudet = YENC_ENCODED; continue; } if (strncmp (line, "=yend ", 6) == 0 && result->uudet == YENC_ENCODED) { if (yepartends == 0 || yepartends >= yefilesize) { result->end = 1; }#if 0 if (!uu_more_mime) break;#endif continue; } /* * if we haven't yet found anything encoded, try to find something */ if (!(result->uudet)) { /* * Netscape-Repair code is the same as in uunconc.c */ if ((vflag = UUValidData (line, 0, &bhflag)) == 0 && !ismime) vflag = UURepairData (datei, line, 0, &bhflag); /* * Check data against all possible encodings */ islen[iscnt%10] = strlen(line); isb64[iscnt%10] = (UUValidData (line, B64ENCODED, &bhflag)==B64ENCODED); isuue[iscnt%10] = (UUValidData (line, UU_ENCODED, &bhflag)==UU_ENCODED); isxxe[iscnt%10] = (UUValidData (line, XX_ENCODED, &bhflag)==XX_ENCODED); isbhx[iscnt%10] = (UUValidData (line, BH_ENCODED, &bhflag)==BH_ENCODED); /* * If we've got a first valid encoded line, we get suspicious if * it's shorter than, say, 40 characters. */ if (vflag == B64ENCODED && (dflag == 0 || encoding != B64ENCODED) && strlen (line) < 40 && !result->begin && !uu_tinyb64) { isb64[iscnt%10] = 0; vflag = 0; } if ((vflag == UU_ENCODED || vflag == XX_ENCODED) && (dflag == 0 || encoding != vflag) && strlen (line) < 40 && !result->begin) { isuue[iscnt%10] = isxxe[iscnt%10] = 0; vflag = 0; } iscnt++; /* * Ah, so we got an encoded line? How interesting! */ if (vflag) { /* * For BinHex data, we can use the initial colon ':' as begin * and the terminating colon as ':'. * If (vflag && !bhflag), this is the last line, */ if (vflag == BH_ENCODED) { if (line[0] == ':' && result->end) { fseek (datei, oldposition, SEEK_SET); break; } if (line[0] == ':') result->begin = 1; if (bhflag == 0) { result->uudet = BH_ENCODED; result->end = 1; } } /* * For BinHex files, the file name is encoded in the first encoded * data bytes. We try to extract it here */ if (vflag == BH_ENCODED && bhnf == 0 && result->filename == NULL) { if (bhdsp == bhds2 || ((bhdsp-bhds2) <= (int) bhds2[0] && (bhdsp-bhds2) < 256)) { dcc = UUDecodeLine (line, bhds1, BH_ENCODED); UUbhdecomp (bhds1, bhdsp, &bhl, &bhrpc, dcc, 256-(bhdsp-bhds2), &bhopc); bhdsp += bhopc; } if ((bhdsp-bhds2) > (int) bhds2[0] && bhds2[0]>0 && result->filename==NULL) { memcpy (bhds1, bhds2+1, (int) bhds2[0]); bhds1[(int)bhds2[0]]='\0'; result->filename = _FP_strdup (bhds1); bhnf = 1; } else if (bhdsp-bhds2 >= 256 && bhds2[0]>0) { memcpy (bhds1, bhds2+1, 255); bhds1[255] = '\0'; result->filename = _FP_strdup (bhds1); bhnf = 1; } else if (bhds2[0] <= 0) bhnf = 1; } /* * We accept an encoding if it has been true for four consecutive * lines. Check the is<enc> arrays to avoid mistaking one encoding * for the other. Uuencoded data is rather easily mistaken for * Base 64. If the data matches more than one encoding, we need to * scan further. * * Since text can also rather easily be mistaken for UUencoded * data if it just happens to have 4 lines in a row that have the * correct first character for the length of the line, we also add * a check that the first 3 lines must be the same length, and the * 4th line must be less than or equal to that length. (since * uuencoders use the same length for all lines except the last, * this shouldn't increase the minimum size of UUdata we can * detect, as it would if we tested all 4 lines for being the same * length.) - Matthew Mueller, 20030109 */ if (iscnt > 3) { cbb64 = (isb64[(iscnt-1)%10] && isb64[(iscnt-2)%10] && isb64[(iscnt-3)%10] && isb64[(iscnt-4)%10]); cbuue = (isuue[(iscnt-1)%10] && isuue[(iscnt-2)%10] && isuue[(iscnt-3)%10] && isuue[(iscnt-4)%10] && islen[(iscnt-1)%10] <= islen[(iscnt-2)%10] && islen[(iscnt-2)%10] == islen[(iscnt-3)%10] && islen[(iscnt-3)%10] == islen[(iscnt-4)%10]); cbxxe = (isxxe[(iscnt-1)%10] && isxxe[(iscnt-2)%10] && isxxe[(iscnt-3)%10] && isxxe[(iscnt-4)%10] && islen[(iscnt-1)%10] <= islen[(iscnt-2)%10] && islen[(iscnt-2)%10] == islen[(iscnt-3)%10] && islen[(iscnt-3)%10] == islen[(iscnt-4)%10]); cbbhx = (isbhx[(iscnt-1)%10] && isbhx[(iscnt-2)%10] && isbhx[(iscnt-3)%10] && isbhx[(iscnt-4)%10]); } else { cbb64 = cbuue = cbxxe = cbbhx = 0; } if (cbb64 && !cbuue && !cbxxe && !cbbhx) { result->uudet = B64ENCODED; } else if (!cbb64 && cbuue && !cbxxe && !cbbhx) { result->uudet = UU_ENCODED; } else if (!cbb64 && !cbuue && cbxxe && !cbbhx) { result->uudet = XX_ENCODED; } else if (!cbb64 && !cbuue && !cbxxe && cbbhx) { result->uudet = BH_ENCODED; } if (result->uudet) { encoding = dflag = 0; /* * If we're in fast mode, we're told we don't have to look * for anything below, so we can as well break out of every- * thing * We cannot fast-scan if we have a boundary to look after. */ if (uu_fast_scanning && boundary == NULL) break; /* * Skip the encoded data. We simply wait for a boundary, for * a header or for an empty line. But we also try to pick up * an "end" */ hcount = lcount = 0; while (!feof (datei)) { /* * Make Busy Polls */ if (UUBUSYPOLL(ftell(datei),progress.fsize)) { UUMessage (uuscan_id, __LINE__, UUMSG_NOTE, uustring (S_SCAN_CANCEL)); *errcode = UURET_CANCEL; break; } oldposition = ftell (datei); if (_FP_fgets (line, 255, datei) == NULL) break; if (ferror (datei)) break; line[255] = '\0'; /* * Stop scanning at an empty line or a MIME-boundary. */ if (IsLineEmpty (line)) break; if (boundary && line[0] == '-' && line[1] == '-' && strncmp (line+2, boundary, blen) == 0) { fseek (datei, oldposition, SEEK_SET); break; } else if (line[0] == 'e' && (result->uudet == UU_ENCODED || result->uudet == XX_ENCODED)) { if (strncmp (line, "end", 3) == 0) { result->end = 1; break; } } else if (line[0] == 'b') { if (strncmp (line, "begin ", 6) == 0) { fseek (datei, oldposition, SEEK_SET); break; } } if (checkheaders) { if (IsKnownHeader (line)) { (void) ScanHeaderLine (datei, line); if (hcount == 0) preheaders = oldposition; hcount++; lcount++; if ((hcount >= hlcount.restart) || (hcount >= hlcount.afterdata && result->uudet)) { /* * Hey, a new header starts here */ fseek (datei, preheaders, SEEK_SET); break; } } else if (lcount > WAITHEADER) { hcount = 0; lcount = 0; } else if (hcount) { lcount++; } } if (result->uudet == BH_ENCODED) { /* pick up ``EOF'' for BinHex files. Slow :-< */ if (line[0] && strchr (line+1, ':') != NULL) { result->end = 1; bhflag = 0; break; } } } if (ferror (datei) || *errcode == UURET_CANCEL) break; if (line[0] == '-' && line[1] == '-') haddh = 1; /* * Okay, got everything we need. If we had headers or a * boundary, we break out of the outer loop immediately. */ if (IsKnownHeader (line) || (boundary && line[0] == '-' && line[1] == '-' && strncmp (line+2, boundary, blen) == 0)) { break; } /* * Otherwise, we wait until finding something more interesting * in the outer loop */ continue; } /* * Select the encoding with the best "history" */ cbb64 = isb64[(iscnt-1)%10]; cbuue = isuue[(iscnt-1)%10]; cbxxe = isxxe[(iscnt-1)%10]; cbbhx = isbhx[(iscnt-1)%10]; dflag = 0; if (cbb64 || cbuue || cbxxe || cbbhx) { for (dflag=2; dflag<iscnt && dflag<4; dflag++) { if ((!cbb64 || !isb64[(iscnt-dflag)%10]) && (!cbuue || !isuue[(iscnt-dflag)%10]) && (!cbxxe || !isxxe[(iscnt-dflag)%10]) && (!cbbhx || !isbhx[(iscnt-dflag)%10])) { dflag--; break; } cbb64 &= isb64[(iscnt-dflag)%10]; cbuue &= isuue[(iscnt-dflag)%10]; cbxxe &= isxxe[(iscnt-dflag)%10]; cbbhx &= isbhx[(iscnt-dflag)%10]; } } /* * clear-cut cases */ if (cbb64 && !cbuue && !cbxxe && !cbbhx) { encoding = B64ENCODED; } else if (!cbb64 && cbuue && !cbxxe && !cbbhx) { encoding = UU_ENCODED; } else if (!cbb64 && !cbuue && cbxxe && !cbbhx) { encoding = XX_ENCODED; } else if (!cbb64 && !cbuue && !cbxxe && cbbhx) { encoding = BH_ENCODED; } else { encoding = 0; } /* * Check a few common non-clear-cut cases */ if (!encoding && cbuue && result->begin) { encoding = UU_ENCODED; } else if (!encoding && cbxxe && result->begin) { encoding = XX_ENCODED; } else if (!encoding && cbb64) { encoding = B64ENCODED; } else if (!encoding && cbuue) { encoding = UU_ENCODED; } else if (!encoding && cbxxe) { encoding = XX_ENCODED; } else if (!encoding && cbbhx) { encoding = BH_ENCODED; } } else if (!dontcare) { encoding = 0; dflag = 0; haddh = 0; } } /* if (!uudet) */ /* * End of scanning loop */ } /* while (!feof (datei)) */ if (feof (datei)) oldposition = ftell (datei); if (dflag && encoding == B64ENCODED && haddh) result->uudet = B64ENCODED; else if (dflag && encoding == BH_ENCODED) result->uudet = BH_ENCODED; /* Base64 doesn't have begin or end, so it was probably XX */ if (result->uudet == B64ENCODED && result->begin && result->end) result->uudet = XX_ENCODED; /* Base64 doesn't have begin or end */ if (result->uudet == B64ENCODED) result->begin = result->end = 0; /* Base64 and BinHex don't have a file mode */ if (result->uudet == B64ENCODED || result->uudet == BH_ENCODED || result->uudet == YENC_ENCODED) result->mode = 6*64+4*8+4; /* * When strict MIME adherance is set, throw out suspicious attachments */ if (uu_more_mime) { /* * In a MIME message, Base64 should be appropriately tagged */ if (result->uudet == B64ENCODED) { result->uudet = 0; } /* * Do not accept incomplete UU or XX encoded messages */ if ((result->uudet != 0 && result->uudet != B64ENCODED) && (!result->begin || !result->end)) { result->uudet = 0; } } /* * In fast mode, this length will yield a false value. We don't care. * This must be checked for in uunconc(), where we usually stop decoding * after reaching startpos+length */ if (uu_fast_scanning) result->length = progress.fsize-result->startpos; else result->length = ftell(datei)-result->startpos; if (ferror (datei)) { *errcode = UURET_IOERR; uu_errno = errno; return -1; } if (*errcode != UURET_OK) { return -1; } if (boundary && line[0] == '-' && line[1] == '-' && strncmp (line+2, boundary, blen) == 0) return 2; else if (boundary && p3 && line[0] == 'C' && line[1] == 'o' && _FP_strnicmp (line, "Content-Type:", 13) == 0 && strcmp (p3, boundary) == 0) return 2; else if (IsKnownHeader (line)) return 1; return 0;}/* * This is the main scanning function. */fileread *ScanPart (FILE *datei, char *fname, int *errcode){ int ecount, hcount, lcount; int bhflag, begflag, vflag, blen=0, res; long preheaders, prevpos=0, preenc, before; char *line=uuscan_spline; fileread *result; char *ptr1, *ptr2; (void) UUDecodeLine (NULL, NULL, 0); /* init */ if (datei == NULL || feof (datei)) { *errcode = UURET_OK; return NULL; } *errcode = UURET_OK; if ((result = (fileread *) malloc (sizeof (fileread))) == NULL) { *errcode = UURET_NOMEM; return NULL; } memset (result, 0, sizeof (fileread)); result->startpos = ftell (datei); preheaders = result->startpos; before = result->startpos; /* if this is a new file, reset our scanning state */ if (sstate.source == NULL || strcmp (fname, sstate.source) != 0) { sstate.isfolder = 1; /* assume yes */ sstate.ismime = 0; /* wait for MIME-Version */ sstate.mimestate = MS_HEADERS; /* assume headers follow */ /* mimseqno = 1; */ while (mssdepth) { mssdepth--; UUkillheaders (&(multistack[mssdepth].envelope)); _FP_free (multistack[mssdepth].source); } UUkillheaders (&sstate.envelope); memset (&sstate.envelope, 0, sizeof (headers)); _FP_free (sstate.source); if ((sstate.source = _FP_strdup (fname)) == NULL) {
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?