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