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