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 + -
显示快捷键?