diff --git a/docs/notework.txt b/docs/notework.txt index e2d9d74..fdbed66 100644 --- a/docs/notework.txt +++ b/docs/notework.txt @@ -12,6 +12,10 @@ ______________________________________________________________________ Notes for GoldED+ 1.1.5, /snapshot/ ______________________________________________________________________ +! Updated uulib to the latest version. Few bugs fixed. Unordered + UU encode now should be processed more accurately than with original + library. + - Fixed improper charset conversion when replying on message without charset between areas with different Xlatimport. diff --git a/goldlib/uulib/Makefile b/goldlib/uulib/Makefile index 41ac2bf..c512042 100644 --- a/goldlib/uulib/Makefile +++ b/goldlib/uulib/Makefile @@ -1,7 +1,7 @@ # -*- makefile -*- VERSION=0.5 -PATCH=13 +PATCH=15 TOP=../.. TARGET=uulib diff --git a/goldlib/uulib/fptools.c b/goldlib/uulib/fptools.c index 2f4dcb7..097304e 100644 --- a/goldlib/uulib/fptools.c +++ b/goldlib/uulib/fptools.c @@ -1,9 +1,8 @@ /* * fptools.c, some helper functions for getcgi.c and uu(en|de)view * - * Distributed by the GNU General Public License. Use and be happy. - * Read http://www.uni-frankfurt.de/~fp/Tools/Getcgi.html for more - * information. fp@informatik.uni-frankfurt.de + * Distributed under the terms of the GNU General Public License. + * Use and be happy. */ #ifdef HAVE_CONFIG_H diff --git a/goldlib/uulib/fptools.h b/goldlib/uulib/fptools.h index aeb49aa..69a10ed 100644 --- a/goldlib/uulib/fptools.h +++ b/goldlib/uulib/fptools.h @@ -1,9 +1,8 @@ /* * fptools.c, some helper functions for getcgi.c and uu(en|de)view * - * Distributed by the GNU General Public License. Use and be happy. - * Read http://www.uni-frankfurt.de/~fp/Tools/Getcgi.html for more - * information. fp@informatik.uni-frankfurt.de + * Distributed under the terms of the GNU General Public License. + * Use and be happy. */ /* diff --git a/goldlib/uulib/uucheck.c b/goldlib/uulib/uucheck.c index f840909..9ead574 100644 --- a/goldlib/uulib/uucheck.c +++ b/goldlib/uulib/uucheck.c @@ -1,7 +1,7 @@ /* * This file is part of uudeview, the simple and friendly multi-part multi- - * file uudecoder program (c) 1994 by Frank Pilhofer. The author may be - * contacted by his email address, fp@informatik.uni-frankfurt.de + * file uudecoder program (c) 1994-2001 by Frank Pilhofer. The author may + * be contacted at fp@fpx.de * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,7 +14,6 @@ * GNU General Public License for more details. */ - #ifdef HAVE_CONFIG_H #include "config.h" #endif @@ -847,7 +846,7 @@ UUPreProcessPart (fileread *data, int *ret) } lastvalid = 0; } - else if (lastvalid && data->uudet == lastenc) { + else if (lastvalid && data->uudet == lastenc && result->partno <= 0) { result->subfname = _FP_strdup (uucheck_lastname); result->partno = ++lastpart; @@ -857,7 +856,10 @@ UUPreProcessPart (fileread *data, int *ret) if (data->end || (data->partno && data->partno == data->maxpno)) lastvalid = 0; } - else { + else if (data->partno != -1 && result->filename) { + result->subfname = _FP_strdup (result->filename); + } + else { /* * it's got no info, it's got no begin, and we don't know anything * about this part. Let's forget all about it. @@ -1460,9 +1462,3 @@ UUCheckGlobalList (void) return UUGlobalFileList; } - -/***************************************************************************** - + Frank Pilhofer fp@informatik.uni-frankfurt.de + - +---------------------------------------------------------------------------+ - | Department of Computer Sciences * University of Frankfurt / Main, Germany | - *****************************************************************************/ diff --git a/goldlib/uulib/uudeview.h b/goldlib/uulib/uudeview.h index 00ff19d..4a1cce9 100644 --- a/goldlib/uulib/uudeview.h +++ b/goldlib/uulib/uudeview.h @@ -1,7 +1,7 @@ /* * This file is part of uudeview, the simple and friendly multi-part multi- - * file uudecoder program (c) 1994 by Frank Pilhofer. The author may be - * contacted by his email address, fp@informatik.uni-frankfurt.de + * file uudecoder program (c) 1994-2001 by Frank Pilhofer. The author may + * be contacted at fp@fpx.de * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -104,6 +104,8 @@ #define UUOPT_PREAMB (17) /* handle Mime preambles/epilogues */ #define UUOPT_TINYB64 (18) /* detect short B64 outside of Mime */ #define UUOPT_ENCEXT (19) /* extension for single-part encoded files */ +#define UUOPT_REMOVE (20) /* remove input files after decoding */ +#define UUOPT_MOREMIME (21) /* strict MIME adherence */ /* * Code for the "action" in the progress structure @@ -239,6 +241,19 @@ int UUEXPORT UUE_PrepPartial _ANSI_ARGS_((FILE *, FILE *, char *, int, int, long, long, char *, char *, char *, int)); + +int UUEXPORT UUE_PrepSingleExt _ANSI_ARGS_((FILE *, FILE *, + char *, int, + char *, int, + char *, char *, + char *, char *, + int)); +int UUEXPORT UUE_PrepPartialExt _ANSI_ARGS_((FILE *, FILE *, + char *, int, + char *, int, + int, long, long, char *, + char *, char *, char *, + int)); #ifdef __cplusplus } #endif diff --git a/goldlib/uulib/uuencode.c b/goldlib/uulib/uuencode.c index cfed11d..2013a93 100644 --- a/goldlib/uulib/uuencode.c +++ b/goldlib/uulib/uuencode.c @@ -1,7 +1,7 @@ /* * This file is part of uudeview, the simple and friendly multi-part multi- - * file uudecoder program (c) 1994 by Frank Pilhofer. The author may be - * contacted by his email address, fp@informatik.uni-frankfurt.de + * file uudecoder program (c) 1994-2001 by Frank Pilhofer. The author may + * be contacted at fp@fpx.de * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -98,9 +98,9 @@ char * uuencode_id = "$Id$"; */ #ifdef EOLSTRING -static unsigned char *eolstring = (unsigned char *) EOLSTRING; +static char *eolstring = (char *) EOLSTRING; #else -static unsigned char *eolstring = (unsigned char *) "\012"; +static char *eolstring = (char *) "\012"; #endif /* @@ -114,6 +114,8 @@ static unsigned char *eolstring = (unsigned char *) "\012"; #define CTE_TYPE(y) (((y)==B64ENCODED) ? "Base64" : \ ((y)==UU_ENCODED) ? CTE_UUENC : \ ((y)==XX_ENCODED) ? CTE_XXENC : \ + ((y)==PT_ENCODED) ? "8bit" : \ + ((y)==QP_ENCODED) ? "quoted-printable" : \ ((y)==BH_ENCODED) ? CTE_BINHEX : "x-oops") /* @@ -163,7 +165,12 @@ unsigned char BHEncodeTable[64] = { 'S', 'T', 'U', 'V', 'X', 'Y', 'Z', '[', '`', 'a', 'b', 'c', 'd', 'e', 'f', 'h', 'i', 'j', 'k', 'l', 'm', 'p', 'q', 'r' -}; +}; + +unsigned char HexEncodeTable[16] = { + '0', '1', '2', '3', '4', '5', '6', '7', + '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' +}; typedef struct { char *extension; @@ -191,7 +198,7 @@ static mimemap mimetable[] = { { "mpeg", "video/mpeg" }, /* Motion Picture Expert Group */ { "mpg", "video/mpeg" }, { "mp2", "video/mpeg" }, /* dito, MPEG-2 encoded files */ - { "mp3", "video/mpeg" }, /* dito, MPEG-3 encoded files */ + { "mp3", "audio/mpeg" }, /* dito, MPEG-3 encoded files */ { "ps", "application/postscript" }, /* Postscript Language */ { "zip", "application/zip" }, /* ZIP archive */ { "doc", "application/msword"},/* assume Microsoft Word */ @@ -243,12 +250,161 @@ UUEncodeStream (FILE *outfile, FILE *infile, int encoding, long linperfile) size_t llen; if (outfile==NULL || infile==NULL || - (encoding!=UU_ENCODED&&encoding!=XX_ENCODED&&encoding!=B64ENCODED)) { + (encoding!=UU_ENCODED&&encoding!=XX_ENCODED&&encoding!=B64ENCODED&& + encoding!=PT_ENCODED&&encoding!=QP_ENCODED)) { UUMessage (uuencode_id, __LINE__, UUMSG_ERROR, uustring (S_PARM_CHECK), "UUEncodeStream()"); return UURET_ILLVAL; } + /* + * Special handling for plain text and quoted printable. Text is + * read line oriented. + */ + + if (encoding == PT_ENCODED || encoding == QP_ENCODED) { + while (!feof (infile) && (linperfile <= 0 || line < linperfile)) { + if (_FP_fgets ((char *)itemp, 255, infile) == NULL) { + break; + } + + itemp[255] = '\0'; + count = strlen ((char *)itemp); + + llen = 0; + optr = otemp; + + /* + * Busy Callback + */ + + if (UUBUSYPOLL(ftell(infile)-progress.foffset,progress.fsize)) { + UUMessage (uuencode_id, __LINE__, UUMSG_NOTE, + uustring (S_ENCODE_CANCEL)); + return UURET_CANCEL; + } + + if (encoding == PT_ENCODED) { + /* + * If there is a line feed, replace by eolstring + */ + if (count > 0 && itemp[count-1] == '\n') { + itemp[--count] = '\0'; + if (fwrite (itemp, 1, count, outfile) != count || + fwrite (eolstring, 1, + strlen(eolstring), outfile) != strlen (eolstring)) { + return UURET_IOERR; + } + } + else { + if (fwrite (itemp, 1, count, outfile) != llen) { + return UURET_IOERR; + } + } + } + else if (encoding == QP_ENCODED) { + for (index=0; index> 4]; + *optr++ = HexEncodeTable[itemp[index] & 0x0f]; + llen += 3; + } + else if ((itemp[index] >= 33 && itemp[index] <= 60) || + (itemp[index] >= 62 && itemp[index] <= 126) || + itemp[index] == 9 || itemp[index] == 32) { + *optr++ = itemp[index]; + llen++; + } + else if (itemp[index] == '\n') { + /* + * If the last character before EOL was a space or tab, + * we must encode it. If llen > 74, there's no space to do + * that, so generate a soft line break instead. + */ + + if (index>0 && (itemp[index-1] == 9 || itemp[index-1] == 32)) { + *(optr-1) = '='; + if (llen <= 74) { + *optr++ = HexEncodeTable[itemp[index-1] >> 4]; + *optr++ = HexEncodeTable[itemp[index-1] & 0x0f]; + llen += 2; + } + } + + if (fwrite (otemp, 1, llen, outfile) != llen || + fwrite (eolstring, 1, + strlen(eolstring), outfile) != strlen (eolstring)) { + return UURET_IOERR; + } + + /* + * Fix the soft line break condition from above + */ + + if (index>0 && (itemp[index-1] == 9 || itemp[index-1] == 32) && + *(optr-1) == '=') { + otemp[0] = '='; + otemp[1] = HexEncodeTable[itemp[index-1] >> 4]; + otemp[2] = HexEncodeTable[itemp[index-1] & 0x0f]; + + if (fwrite (otemp, 1, 3, outfile) != 3 || + fwrite (eolstring, 1, + strlen(eolstring), outfile) != strlen (eolstring)) { + return UURET_IOERR; + } + } + + optr = otemp; + llen = 0; + } + else { + *optr++ = '='; + *optr++ = HexEncodeTable[itemp[index] >> 4]; + *optr++ = HexEncodeTable[itemp[index] & 0x0f]; + llen += 3; + } + + /* + * Lines must be shorter than 76 characters (not counting CRLF). + * If the line grows longer than that, we must include a soft + * line break. + */ + + if (itemp[index+1] != 0 && itemp[index+1] != '\n' && + (llen >= 75 || + (!((itemp[index+1] >= 33 && itemp[index+1] <= 60) || + (itemp[index+1] >= 62 && itemp[index+1] <= 126)) && + llen >= 73))) { + + *optr++ = '='; + llen++; + + if (fwrite (otemp, 1, llen, outfile) != llen || + fwrite (eolstring, 1, + strlen(eolstring), outfile) != strlen (eolstring)) { + return UURET_IOERR; + } + + optr = otemp; + llen = 0; + } + } + } + + line++; + } + + return UURET_OK; + } + + /* + * Handling for binary encodings + */ /* * select charset @@ -258,7 +414,7 @@ UUEncodeStream (FILE *outfile, FILE *infile, int encoding, long linperfile) if (table==NULL || bpl[encoding]==0) { UUMessage (uuencode_id, __LINE__, UUMSG_ERROR, - uustring (S_PARM_CHECK), "UUEncodeStream()"); + uustring (S_PARM_CHECK), "UUEncodeStream()"); return UURET_ILLVAL; } @@ -269,6 +425,7 @@ UUEncodeStream (FILE *outfile, FILE *infile, int encoding, long linperfile) else if (ferror (infile)) return UURET_IOERR; } + optr = otemp; llen = 0; @@ -285,65 +442,76 @@ UUEncodeStream (FILE *outfile, FILE *infile, int encoding, long linperfile) /* * for UU and XX, encode the number of bytes as first character */ + if (encoding == UU_ENCODED || encoding == XX_ENCODED) { *optr++ = table[count]; llen++; } - for (index=0; index<=count-3; index+=3, llen+=4) { - *optr++ = table[itemp[index] >> 2]; - *optr++ = table[((itemp[index ] & 0x03) << 4) | (itemp[index+1] >> 4)]; - *optr++ = table[((itemp[index+1] & 0x0f) << 2) | (itemp[index+2] >> 6)]; - *optr++ = table[ itemp[index+2] & 0x3f]; + /* + * Main encoding + */ + + if (encoding == UU_ENCODED || encoding == XX_ENCODED || + encoding == B64ENCODED) { + for (index=0; index<=count-3; index+=3, llen+=4) { + *optr++ = table[itemp[index] >> 2]; + *optr++ = table[((itemp[index ] & 0x03) << 4)|(itemp[index+1] >> 4)]; + *optr++ = table[((itemp[index+1] & 0x0f) << 2)|(itemp[index+2] >> 6)]; + *optr++ = table[ itemp[index+2] & 0x3f]; + } + + /* + * Special handling for incomplete lines + */ + + if (index != count) { + if (encoding == B64ENCODED) { + if (count - index == 2) { + *optr++ = table[itemp[index] >> 2]; + *optr++ = table[((itemp[index ] & 0x03) << 4) | + ((itemp[index+1] & 0xf0) >> 4)]; + *optr++ = table[((itemp[index+1] & 0x0f) << 2)]; + *optr++ = '='; + } + else if (count - index == 1) { + *optr++ = table[ itemp[index] >> 2]; + *optr++ = table[(itemp[index] & 0x03) << 4]; + *optr++ = '='; + *optr++ = '='; + } + llen += 4; + } + else { + if (count - index == 2) { + *optr++ = table[itemp[index] >> 2]; + *optr++ = table[((itemp[index ] & 0x03) << 4) | + ( itemp[index+1] >> 4)]; + *optr++ = table[((itemp[index+1] & 0x0f) << 2)]; + *optr++ = table[0]; + } + else if (count - index == 1) { + *optr++ = table[ itemp[index] >> 2]; + *optr++ = table[(itemp[index] & 0x03) << 4]; + *optr++ = table[0]; + *optr++ = table[0]; + } + llen += 4; + } + } } - /* - * Special handling for incomplete lines - */ - if (index != count) { - if (encoding == B64ENCODED) { - if (count - index == 2) { - *optr++ = table[itemp[index] >> 2]; - *optr++ = table[((itemp[index ] & 0x03) << 4) | - ((itemp[index+1] & 0xf0) >> 4)]; - *optr++ = table[((itemp[index+1] & 0x0f) << 2)]; - *optr++ = '='; - } - else if (count - index == 1) { - *optr++ = table[ itemp[index] >> 2]; - *optr++ = table[(itemp[index] & 0x03) << 4]; - *optr++ = '='; - *optr++ = '='; - } - llen += 4; - } - else { - if (count - index == 2) { - *optr++ = table[itemp[index] >> 2]; - *optr++ = table[((itemp[index ] & 0x03) << 4) | - ( itemp[index+1] >> 4)]; - *optr++ = table[((itemp[index+1] & 0x0f) << 2)]; - *optr++ = table[0]; - } - else if (count - index == 1) { - *optr++ = table[ itemp[index] >> 2]; - *optr++ = table[(itemp[index] & 0x03) << 4]; - *optr++ = table[0]; - *optr++ = table[0]; - } - llen += 4; - } - } /* * end of line */ - tptr = eolstring; + + tptr = (unsigned char *) eolstring; while (*tptr) *optr++ = *tptr++; *optr++ = '\0'; - llen += strlen ((char *) eolstring); + llen += strlen (eolstring); if (fwrite (otemp, 1, llen, outfile) != llen) return UURET_IOERR; @@ -370,7 +538,8 @@ UUEncodeMulti (FILE *outfile, FILE *infile, char *infname, int encoding, if (outfile==NULL || (infile == NULL && infname==NULL) || (outfname==NULL && infname==NULL) || - (encoding!=UU_ENCODED&&encoding!=XX_ENCODED&&encoding!=B64ENCODED)) { + (encoding!=UU_ENCODED&&encoding!=XX_ENCODED&&encoding!=B64ENCODED&& + encoding!=PT_ENCODED&&encoding!=QP_ENCODED)) { UUMessage (uuencode_id, __LINE__, UUMSG_ERROR, uustring (S_PARM_CHECK), "UUEncodeMulti()"); return UURET_ILLVAL; @@ -430,6 +599,11 @@ UUEncodeMulti (FILE *outfile, FILE *infile, char *infname, int encoding, mimetype = miter->mimetype; } } + + if (mimetype == NULL && (encoding == PT_ENCODED || encoding == QP_ENCODED)) { + mimetype = "text/plain"; + } + /* * print sub-header */ @@ -497,7 +671,8 @@ UUEncodePartial (FILE *outfile, FILE *infile, if ((outfname==NULL&&infname==NULL) || partno<=0 || (infile == NULL&&infname==NULL) || outfile==NULL || - (encoding!=UU_ENCODED&&encoding!=XX_ENCODED&&encoding!=B64ENCODED)) { + (encoding!=UU_ENCODED&&encoding!=XX_ENCODED&&encoding!=B64ENCODED&& + encoding!=PT_ENCODED&&encoding!=QP_ENCODED)) { UUMessage (uuencode_id, __LINE__, UUMSG_ERROR, uustring (S_PARM_CHECK), "UUEncodePartial()"); return UURET_ILLVAL; @@ -574,6 +749,11 @@ UUEncodePartial (FILE *outfile, FILE *infile, mimetype = miter->mimetype; } } + + if (mimetype == NULL && (encoding==PT_ENCODED || encoding==QP_ENCODED)) { + mimetype = "text/plain"; + } + /* * print sub-header */ @@ -639,10 +819,14 @@ UUEncodePartial (FILE *outfile, FILE *infile, eolstring); fprintf (outfile, "end%s", eolstring); } + /* * empty line at end does no harm */ - fprintf (outfile, "%s", eolstring); + + if (encoding != PT_ENCODED && encoding != QP_ENCODED) { + fprintf (outfile, "%s", eolstring); + } if (infile==NULL) { if (res != UURET_OK) { @@ -682,7 +866,8 @@ UUEncodeToStream (FILE *outfile, FILE *infile, if (outfile==NULL || (infile == NULL&&infname==NULL) || (outfname==NULL&&infname==NULL) || - (encoding!=UU_ENCODED&&encoding!=XX_ENCODED&&encoding!=B64ENCODED)) { + (encoding!=UU_ENCODED&&encoding!=XX_ENCODED&&encoding!=B64ENCODED&& + encoding!=PT_ENCODED&&encoding!=QP_ENCODED)) { UUMessage (uuencode_id, __LINE__, UUMSG_ERROR, uustring (S_PARM_CHECK), "UUEncodeToStream()"); return UURET_ILLVAL; @@ -778,7 +963,8 @@ UUEncodeToFile (FILE *infile, char *infname, int encoding, if ((diskname==NULL&&infname==NULL) || (outfname==NULL&&infname==NULL) || (infile==NULL&&infname==NULL) || - (encoding!=UU_ENCODED&&encoding!=XX_ENCODED&&encoding!=B64ENCODED)) { + (encoding!=UU_ENCODED&&encoding!=XX_ENCODED&&encoding!=B64ENCODED&& + encoding!=PT_ENCODED&&encoding!=QP_ENCODED)) { UUMessage (uuencode_id, __LINE__, UUMSG_ERROR, uustring (S_PARM_CHECK), "UUEncodeToFile()"); return UURET_ILLVAL; @@ -1012,6 +1198,22 @@ UUE_PrepSingle (FILE *outfile, FILE *infile, char *outfname, int filemode, char *destination, char *from, char *subject, int isemail) +{ + return UUE_PrepSingleExt (outfile, infile, + infname, encoding, + outfname, filemode, + destination, from, + subject, NULL, + isemail); +} + +int UUEXPORT +UUE_PrepSingleExt (FILE *outfile, FILE *infile, + char *infname, int encoding, + char *outfname, int filemode, + char *destination, char *from, + char *subject, char *replyto, + int isemail) { mimemap *miter=mimetable; char *subline, *oname; @@ -1019,7 +1221,8 @@ UUE_PrepSingle (FILE *outfile, FILE *infile, int res, len; if ((outfname==NULL&&infname==NULL) || (infile==NULL&&infname==NULL) || - (encoding!=UU_ENCODED&&encoding!=XX_ENCODED&&encoding!=B64ENCODED)) { + (encoding!=UU_ENCODED&&encoding!=XX_ENCODED&&encoding!=B64ENCODED&& + encoding!=PT_ENCODED&&encoding!=QP_ENCODED)) { UUMessage (uuencode_id, __LINE__, UUMSG_ERROR, uustring (S_PARM_CHECK), "UUE_PrepSingle()"); return UURET_ILLVAL; @@ -1036,6 +1239,10 @@ UUE_PrepSingle (FILE *outfile, FILE *infile, else mimetype = NULL; + if (mimetype == NULL && (encoding == PT_ENCODED || encoding == QP_ENCODED)) { + mimetype = "text/plain"; + } + if ((subline = (char *) malloc (len)) == NULL) { UUMessage (uuencode_id, __LINE__, UUMSG_ERROR, uustring (S_OUT_OF_MEMORY), len); @@ -1047,8 +1254,6 @@ UUE_PrepSingle (FILE *outfile, FILE *infile, else sprintf (subline, "[ %s ] (001/001)", oname); - fprintf (outfile, "Subject: %s%s", subline, eolstring); - if (from) { fprintf (outfile, "From: %s%s", from, eolstring); } @@ -1057,6 +1262,13 @@ UUE_PrepSingle (FILE *outfile, FILE *infile, (isemail)?"To":"Newsgroups", destination, eolstring); } + + fprintf (outfile, "Subject: %s%s", subline, eolstring); + + if (replyto) { + fprintf (outfile, "Reply-To: %s%s", replyto, eolstring); + } + fprintf (outfile, "MIME-Version: 1.0%s", eolstring); fprintf (outfile, "Content-Type: %s; name=\"%s\"%s", (mimetype)?mimetype:"Application/Octet-Stream", @@ -1080,6 +1292,24 @@ UUE_PrepPartial (FILE *outfile, FILE *infile, int partno, long linperfile, long filesize, char *destination, char *from, char *subject, int isemail) +{ + return UUE_PrepPartialExt (outfile, infile, + infname, encoding, + outfname, filemode, + partno, linperfile, filesize, + destination, + from, subject, NULL, + isemail); +} + +int UUEXPORT +UUE_PrepPartialExt (FILE *outfile, FILE *infile, + char *infname, int encoding, + char *outfname, int filemode, + int partno, long linperfile, long filesize, + char *destination, + char *from, char *subject, char *replyto, + int isemail) { static int numparts, themode; static char mimeid[64]; @@ -1090,7 +1320,8 @@ UUE_PrepPartial (FILE *outfile, FILE *infile, int res, len; if ((outfname==NULL&&infname==NULL) || (infile==NULL&&infname==NULL) || - (encoding!=UU_ENCODED&&encoding!=XX_ENCODED&&encoding!=B64ENCODED)) { + (encoding!=UU_ENCODED&&encoding!=XX_ENCODED&&encoding!=B64ENCODED&& + encoding!=PT_ENCODED&&encoding!=QP_ENCODED)) { UUMessage (uuencode_id, __LINE__, UUMSG_ERROR, uustring (S_PARM_CHECK), "UUE_PrepPartial()"); return UURET_ILLVAL; @@ -1163,9 +1394,9 @@ UUE_PrepPartial (FILE *outfile, FILE *infile, if (numparts == 1) { if (infile==NULL) fclose (theifile); - return UUE_PrepSingle (outfile, infile, infname, encoding, - outfname, filemode, destination, - from, subject, isemail); + return UUE_PrepSingleExt (outfile, infile, infname, encoding, + outfname, filemode, destination, + from, subject, replyto, isemail); } /* @@ -1190,16 +1421,22 @@ UUE_PrepPartial (FILE *outfile, FILE *infile, sprintf (subline, "[ %s ] (%03d/%03d)", oname, partno, numparts); - fprintf (outfile, "Subject: %s%s", subline, eolstring); - if (from) { fprintf (outfile, "From: %s%s", from, eolstring); } + if (destination) { fprintf (outfile, "%s: %s%s", (isemail)?"To":"Newsgroups", destination, eolstring); } + + fprintf (outfile, "Subject: %s%s", subline, eolstring); + + if (replyto) { + fprintf (outfile, "Reply-To: %s%s", replyto, eolstring); + } + fprintf (outfile, "MIME-Version: 1.0%s", eolstring); fprintf (outfile, "Content-Type: Message/Partial; number=%d; total=%d;%s", partno, numparts, eolstring); diff --git a/goldlib/uulib/uuint.h b/goldlib/uulib/uuint.h index 4113d22..4d389aa 100644 --- a/goldlib/uulib/uuint.h +++ b/goldlib/uulib/uuint.h @@ -1,7 +1,7 @@ /* * This file is part of uudeview, the simple and friendly multi-part multi- - * file uudecoder program (c) 1994 by Frank Pilhofer. The author may be - * contacted by his email address, fp@informatik.uni-frankfurt.de + * file uudecoder program (c) 1994-2001 by Frank Pilhofer. The author may + * be contacted at fp@fpx.de * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -204,6 +204,8 @@ extern int uu_headercount; extern int uu_usepreamble; extern int uu_handletext; extern int uu_tinyb64; +extern int uu_remove_input; +extern int uu_more_mime; extern char *uusavepath; extern char *uuencodeext; diff --git a/goldlib/uulib/uulib.c b/goldlib/uulib/uulib.c index 3de38d6..914d732 100644 --- a/goldlib/uulib/uulib.c +++ b/goldlib/uulib/uulib.c @@ -1,7 +1,7 @@ /* * This file is part of uudeview, the simple and friendly multi-part multi- - * file uudecoder program (c) 1994 by Frank Pilhofer. The author may be - * contacted by his email address, fp@informatik.uni-frankfurt.de + * file uudecoder program (c) 1994-2001 by Frank Pilhofer. The author may + * be contacted at fp@fpx.de * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -72,7 +72,7 @@ #endif /* to get open() in Windows */ -#if defined(HAVE_IO_H) && defined(__MINGW32__) +#ifdef HAVE_IO_H #include #endif @@ -141,6 +141,8 @@ int uu_ignmode = 0; /* ignore the original file mode */ int uu_handletext = 0; /* do we want text/plain messages */ int uu_usepreamble = 0; /* do we want Mime preambles/epilogues */ int uu_tinyb64 = 0; /* detect short B64 outside of MIME */ +int uu_remove_input = 0; /* remove input files after decoding */ +int uu_more_mime = 0; /* strictly adhere to MIME headers */ headercount hlcount = { 3, /* restarting after a MIME body */ @@ -229,10 +231,10 @@ static allomap toallocate[] = { { &uucheck_lastname, 256 }, /* from uucheck.c */ { &uucheck_tempname, 256 }, { &uuestr_itemp, 256 }, /* from uuencode.c:UUEncodeStream() */ - { &uuestr_otemp, 256 }, + { &uuestr_otemp, 1024 }, { &uulib_msgstring, 1024 }, /* from uulib.c:UUMessage() */ - { &uuncdl_fulline, 256 }, /* from uunconc.c:UUDecodeLine() */ - { &uuncdp_oline, 512 }, /* from uunconc.c:UUDecodePart() */ + { &uuncdl_fulline, 260 }, /* from uunconc.c:UUDecodeLine() */ + { &uuncdp_oline, 1024 }, /* from uunconc.c:UUDecodePart() */ { &uunconc_UUxlat, 256 * sizeof (int) }, /* from uunconc.c:toplevel */ { &uunconc_UUxlen, 64 * sizeof (int) }, { &uunconc_B64xlat, 256 * sizeof (int) }, @@ -487,6 +489,14 @@ UUGetOption (int option, int *ivalue, char *cvalue, int clength) _FP_strncpy (cvalue, uuencodeext, clength); result = 0; break; + case UUOPT_REMOVE: + if (ivalue) *ivalue = uu_remove_input; + result = uu_remove_input; + break; + case UUOPT_MOREMIME: + if (ivalue) *ivalue = uu_more_mime; + result = uu_more_mime; + break; default: return -1; } @@ -541,6 +551,12 @@ UUSetOption (int option, int ivalue, char *cvalue) _FP_free (uuencodeext); uuencodeext = _FP_strdup (cvalue); break; + case UUOPT_REMOVE: + uu_remove_input = ivalue; + break; + case UUOPT_MOREMIME: + uu_more_mime = ivalue; + break; default: return UURET_ILLVAL; } @@ -733,6 +749,7 @@ UULoadFile (char *filename, char *fileid, int delflag) } if ((loaded->uudet == QP_ENCODED || loaded->uudet == PT_ENCODED) && + (loaded->filename == NULL || *(loaded->filename) == '\0') && !uu_handletext && (loaded->flags&FL_PARTIAL)==0) { /* * Don't want text @@ -1147,14 +1164,14 @@ int UUEXPORT UUCleanUp (void) { itbd *iter=ftodel, *ptr; + uulist *liter; + uufile *fiter; allomap *aiter; - UUkilllist (UUGlobalFileList); - UUGlobalFileList = NULL; - /* - * delete input files + * delete temporary input files (such as the copy of stdin) */ + while (iter) { if (unlink (iter->fname)) { UUMessage (uulib_id, __LINE__, UUMSG_WARNING, @@ -1166,8 +1183,36 @@ UUCleanUp (void) iter = iter->NEXT; _FP_free (ptr); } + ftodel = NULL; + /* + * Delete input files after successful decoding + */ + + if (uu_remove_input) { + liter = UUGlobalFileList; + while (liter) { + if (liter->state & UUFILE_DECODED) { + fiter = liter->thisfile; + while (fiter) { + if (fiter->data && fiter->data->sfname) { + /* + * Error code ignored. We might want to delete a file multiple + * times + */ + unlink (fiter->data->sfname); + } + fiter = fiter->NEXT; + } + } + liter = liter->NEXT; + } + } + + UUkilllist (UUGlobalFileList); + UUGlobalFileList = NULL; + _FP_free (uusavepath); _FP_free (uuencodeext); _FP_free (sstate.source); diff --git a/goldlib/uulib/uunconc.c b/goldlib/uulib/uunconc.c index 7ee6b1f..d70e12e 100644 --- a/goldlib/uulib/uunconc.c +++ b/goldlib/uulib/uunconc.c @@ -1,7 +1,7 @@ /* * This file is part of uudeview, the simple and friendly multi-part multi- - * file uudecoder program (c) 1994 by Frank Pilhofer. The author may be - * contacted by his email address, fp@informatik.uni-frankfurt.de + * file uudecoder program (c) 1994-2001 by Frank Pilhofer. The author may + * be contacted at fp@fpx.de * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -165,7 +165,7 @@ UUInitConc (void) /* prepare line length table */ UUxlen[0] = 1; - for(i = 1, j = 5; i <= 60; i += 3, j += 4) + for(i = 1, j = 5; i <= 61; i += 3, j += 4) UUxlen[i] = UUxlen[i+1] = UUxlen[i+2] = j; /* prepare other tables */ @@ -243,11 +243,10 @@ UUNetscapeCollapse (char *string) */ while (*p1) { if (*p1 == '&') { - if (_FP_strnicmp (p1, "&", 5) == 0) { p1+=5; *p2++='&'; } - else if (_FP_strnicmp (p1, "<", 4) == 0) { p1+=4; *p2++='<'; } - else if (_FP_strnicmp (p1, ">", 4) == 0) { p1+=4; *p2++='>'; } + if (_FP_strnicmp (p1, "&", 5) == 0) { p1+=5; *p2++='&'; res=1; } + else if (_FP_strnicmp (p1, "<", 4) == 0) { p1+=4; *p2++='<'; res=1; } + else if (_FP_strnicmp (p1, ">", 4) == 0) { p1+=4; *p2++='>'; res=1; } else *p2++ = *p1++; - res = 1; } else *p2++ = *p1++; } @@ -298,7 +297,7 @@ UUValidData (char *ptr, int encoding, int *bhflag) int i=0, j, len=0, suspicious=0, flag=0; char *s = ptr; - if ((s == NULL) || (*s & 0x80)) { + if ((s == NULL) || !(iscntrl(ACAST(*s)) || isascii(ACAST(*s)))) { return(0); /* bad string */ } @@ -382,7 +381,8 @@ UUValidData (char *ptr, int encoding, int *bhflag) */ while (len--) { - if ((*s & 0x80) || (B64xlat[ACAST(*s)] == -1 && *s != '=')) { + if (!(iscntrl(ACAST(*s)) || isascii(ACAST(*s))) || + (B64xlat[ACAST(*s)] == -1 && *s != '=')) { /* allow space characters at the end of the line if we are sure */ /* that this is Base64 encoded data or the line was long enough */ if (((i>=60 && len<=10) || encoding) && *s++==' ') { @@ -450,8 +450,10 @@ UUValidData (char *ptr, int encoding, int *bhflag) * evaluated if the first character is lowercase, which really shouldn't * be in uuencoded text. */ - if (len != j && - !(*ptr != 'M' && *ptr != 'h' && len > j && len <= UUxlen[UUxlat['M']])) { + if (len != j && + ((ptr[0] == '-' && ptr[1] == '-' && strstr(ptr,"part")!=NULL) || + !(*ptr != 'M' && *ptr != 'h' && + len > j && len <= UUxlen[UUxlat['M']]))) { if (encoding==UU_ENCODED) return 0; goto _t_XX; /* bad length */ } @@ -472,7 +474,8 @@ UUValidData (char *ptr, int encoding, int *bhflag) } while (len--) { - if ((*s & 0x80) || UUxlat[ACAST(*s++)] < 0) { + if (!(iscntrl(ACAST(*s)) || isascii(ACAST(*s))) || + UUxlat[ACAST(*s++)] < 0) { if (encoding==UU_ENCODED) return 0; goto _t_XX; /* bad code character */ } @@ -512,7 +515,8 @@ UUValidData (char *ptr, int encoding, int *bhflag) return 0; /* bad length */ while(len--) { - if((*s & 0x80) || XXxlat[ACAST(*s++)] < 0) { + if (!(iscntrl(ACAST(*s)) || isascii(ACAST(*s))) || + XXxlat[ACAST(*s++)] < 0) { return 0; /* bad code character */ } } @@ -861,9 +865,8 @@ UUDecodePT (FILE *datain, FILE *dataout, int *state, * So if the part ends here, don't print a line break" */ if ((*ptr == '\012' || *ptr == '\015') && - (!feof (datain) && - (ftell(datain)begin ", 11) == 0) { /* for LYNX */ *state = DATA; continue; @@ -1032,8 +1036,9 @@ UUDecodePart (FILE *datain, FILE *dataout, int *state, } if (vflag == method) { - if (tf) { + if (tf || (method == UU_ENCODED || method == XX_ENCODED)) { count = UUDecodeLine (line, oline, method); + tf = 1; vlc++; lc[1]++; } else if (tc == 3) { @@ -1151,7 +1156,7 @@ UUDecode (uulist *data) if (data->state & UUFILE_NOBEGIN && !uu_desperate) return UURET_NODATA; - if (data->uudet == QP_ENCODED || data->uudet == PT_ENCODED) + if (data->uudet == PT_ENCODED) mode = "wt"; /* open text files in text mode */ else mode = "wb"; /* otherwise in binary */ diff --git a/goldlib/uulib/uuscan.c b/goldlib/uulib/uuscan.c index c770d22..260dd7f 100644 --- a/goldlib/uulib/uuscan.c +++ b/goldlib/uulib/uuscan.c @@ -1,7 +1,7 @@ /* * This file is part of uudeview, the simple and friendly multi-part multi- - * file uudecoder program (c) 1994 by Frank Pilhofer. The author may be - * contacted by his email address, fp@informatik.uni-frankfurt.de + * file uudecoder program (c) 1994-2001 by Frank Pilhofer. The author may + * be contacted at fp@fpx.de * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -126,12 +126,6 @@ char *uuscan_sdbhds1; char *uuscan_sdbhds2; char *uuscan_spline; -/* - * If this is changed to define, some workarounds for broken files are - * disabled - */ -#undef MORE_MIME - /* * Macro: print cancellation message in UUScanPart */ @@ -338,32 +332,35 @@ ParseHeader (headers *theheaders, char *line) if (line == NULL) return theheaders; - value = NULL; delimit = 0; - if (_FP_strnicmp (line, "From:", 5) == 0) { if (theheaders->from) return theheaders; variable = &theheaders->from; value = line+5; + delimit = 0; } else if (_FP_strnicmp (line, "Subject:", 8) == 0) { if (theheaders->subject) return theheaders; variable = &theheaders->subject; value = line+8; + delimit = 0; } else if (_FP_strnicmp (line, "To:", 3) == 0) { if (theheaders->rcpt) return theheaders; variable = &theheaders->rcpt; value = line+3; + delimit = 0; } else if (_FP_strnicmp (line, "Date:", 5) == 0) { if (theheaders->date) return theheaders; variable = &theheaders->date; value = line+5; + delimit = 0; } else if (_FP_strnicmp (line, "Mime-Version:", 13) == 0) { if (theheaders->mimevers) return theheaders; variable = &theheaders->mimevers; value = line+13; + delimit = 0; } else if (_FP_strnicmp (line, "Content-Type:", 13) == 0) { if (theheaders->ctype) return theheaders; @@ -420,12 +417,16 @@ ParseHeader (headers *theheaders, char *line) } } variable = NULL; + value = NULL; + delimit = 0; } else { /* * nothing interesting */ variable = NULL; + value = NULL; + delimit = 0; } /* @@ -519,11 +520,13 @@ ScanData (FILE *datei, char *fname, int *errcode, { char *line=uuscan_sdline, *bhds1=uuscan_sdbhds1, *bhds2=uuscan_sdbhds2; static char *ptr, *p2, *p3=NULL, *bhdsp, bhl; + int isb64[10], isuue[10], isxxe[10], isbhx[10], iscnt; + int cbb64, cbuue, cbxxe, cbbhx; int bhflag=0, vflag, haddh=0, hadct=0; - int bhrpc=0, bhnf=0, c, hcount, lcount, blen; + int bhrpc=0, bhnf=0, c, hcount, lcount, blen=0; int encoding=0, dflag=0, ctline=42; int dontcare=0, hadnl=0; - long preheaders = 0, oldposition; + long preheaders=0, oldposition; size_t dcc, bhopc; *errcode = UURET_OK; @@ -536,7 +539,14 @@ ScanData (FILE *datei, char *fname, int *errcode, result->startpos = ftell (datei); hcount = lcount = 0; - blen = (boundary) ? strlen (boundary) : 0; + for (iscnt=0; iscnt<10; iscnt++) { + isb64[iscnt] = isuue[iscnt] = isxxe[iscnt] = isbhx[iscnt] = 0; + } + + iscnt = 0; + + if (boundary) + blen = strlen (boundary); while (!feof (datei)) { oldposition = ftell (datei); @@ -547,15 +557,10 @@ ScanData (FILE *datei, char *fname, int *errcode, line[255] = '\0'; /* For Safety of string functions */ - if (IsLineEmpty (line)) { /* line empty? */ - hcount = 0; - hadnl = 1; - continue; /* then ignore */ - } - /* * Make Busy Polls */ + if (UUBUSYPOLL(ftell(datei),progress.fsize)) { UUMessage (uuscan_id, __LINE__, UUMSG_NOTE, uustring (S_SCAN_CANCEL)); @@ -563,6 +568,12 @@ ScanData (FILE *datei, char *fname, int *errcode, break; } + if (IsLineEmpty (line)) { /* line empty? */ + hcount = 0; + hadnl = 1; + continue; /* then ignore */ + } + if (checkheaders) { if (IsKnownHeader (line)) { (void) ScanHeaderLine (datei, line); @@ -606,6 +617,7 @@ ScanData (FILE *datei, char *fname, int *errcode, else { dontcare=0; } + if (boundary != NULL && line[0] == '-' && line[1] == '-' && strncmp (line+2, boundary, blen) == 0) { @@ -629,8 +641,9 @@ ScanData (FILE *datei, char *fname, int *errcode, if (strncmp (line, "begin ", 6) == 0 || _FP_strnicmp (line, "
begin ", 11) == 0) {
-      if (result->begin || result->end ||
-	  result->uudet == B64ENCODED || result->uudet == BH_ENCODED) {
+      if ((result->begin || result->end ||
+	   result->uudet == B64ENCODED ||
+	   result->uudet == BH_ENCODED) && !uu_more_mime) {
 	fseek (datei, oldposition, SEEK_SET);
 	break;
       }
@@ -673,15 +686,20 @@ ScanData (FILE *datei, char *fname, int *errcode,
     hadnl = 0;
 
     /*
-     * Detect a UUDeview-Style header
+     * Detect a UUDeview/UUCODE-Style headers
      */
 
-    if (_FP_strnicmp (line, "_=_ Part ", 9) == 0) {
+    if (_FP_strnicmp (line, "_=_ Part ", 9) == 0 ||
+	_FP_strnicmp (line, "section ", 8) == 0) {
       if (result->uudet) {
 	fseek (datei, oldposition, SEEK_SET);
 	break;
       }
       result->partno = atoi (line + 8);
+      if ((ptr = _FP_stristr (line, " of ")) != NULL) {
+        int maxpno = atoi (ptr + 4);
+        if(maxpno != 0) result->maxpno = maxpno;
+      }
       if ((ptr = _FP_stristr (line, "of file ")) != NULL) {
 	ptr += 8;
 	while (isspace (*ptr)) ptr++;
@@ -708,7 +726,7 @@ ScanData (FILE *datei, char *fname, int *errcode,
      * Some reduced MIME handling. Only use if boundary == NULL. Also
      * accept the "X-Orcl-Content-Type" used by some braindead program.
      */
-    if (boundary == NULL && !ismime) {
+    if (boundary == NULL && !ismime && !uu_more_mime) {
       if (_FP_strnicmp (line, "Content-Type", 12) == 0 ||
 	  _FP_strnicmp (line, "X-Orcl-Content-Type", 19) == 0) {
 	/*
@@ -796,7 +814,7 @@ ScanData (FILE *datei, char *fname, int *errcode,
       /* 
        * Handling for very short Base64 files.
        */
-      if (uu_tinyb64) {
+      if (uu_tinyb64 && !ismime && !uu_more_mime) {
 	if (line[0] == '-' && line[1] == '-') {
 	  if (dflag && (encoding==B64ENCODED || result->uudet==B64ENCODED)) {
 	    if (encoding==B64ENCODED && result->uudet==0 && (haddh||hadct)) {
@@ -811,34 +829,76 @@ ScanData (FILE *datei, char *fname, int *errcode,
       }
     } /* end of reduced MIME handling */
 
+    /*
+     * If we're in "freestyle" mode, have not encountered anything
+     * interesting yet, and stumble upon something that looks like
+     * a boundary, followed by a Content-* line, try to use it.
+     */
+
+    if (boundary == NULL && !ismime && !uu_more_mime && dflag <= 1 &&
+	line[0] == '-' && line[1] == '-' && strlen(line+2)>10 &&
+	(((ptr = _FP_strrstr (line+2, "--")) == NULL) ||
+	 (*(ptr+2) != '\012' && *(ptr+2) != '\015')) &&
+	_FP_strstr (line+2, "_=_") != NULL) {
+      if (_FP_fgets (line, 255, datei) == NULL) {
+	break;
+      }
+      if (_FP_strnicmp (line, "Content-", 8) == 0) {
+	/*
+	 * Okay, let's do it. This breaks out of ScanData. ScanPart will
+	 * recognize the boundary on the next call and use it.
+	 */
+	fseek (datei, oldposition, SEEK_SET);
+	break;
+      }
+    }
+
     /*
      * if we haven't yet found anything encoded, try to find something
      */
 
-#if 0
     if (!(result->uudet)) {
-#endif
       /*
        * Netscape-Repair code is the same as in uunconc.c
        */
 
-      if ((vflag = UUValidData (line, 0, &bhflag)) == 0)
+      if ((vflag = UUValidData (line, 0, &bhflag)) == 0 && !ismime)
 	vflag = UURepairData (datei, line, 0, &bhflag);
 
       /*
-       * In a few cases, we might mistake uu or xx-encoded data for
-       * Base64, because their alphabets overlap (XX and Base64 differ
-       * in only one character) and the Base64 check is performed
-       * first. If vflag==B64 and we had a begin line, try to see if
-       * the data is consistent with XX or UU.
+       * Check data against all possible encodings
        */
-      if (vflag == B64ENCODED && result->begin) {
-	if (UUValidData (line, UU_ENCODED, &bhflag) == UU_ENCODED)
-	  vflag = UU_ENCODED;
-	else if (UUValidData (line, XX_ENCODED, &bhflag) == XX_ENCODED)
-	  vflag = XX_ENCODED;
+
+      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
@@ -846,6 +906,10 @@ ScanData (FILE *datei, char *fname, int *errcode,
 	 * 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) {
@@ -882,11 +946,43 @@ ScanData (FILE *datei, char *fname, int *errcode,
 	  else if (bhds2[0] <= 0)
 	    bhnf = 1;
 	}
+
 	/*
-	 * everything is fine after we've found three encoded lines
+	 * We accept an encoding if it has been true for four consecutive
+	 * lines. Check the is 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.
 	 */
-        if (dflag>=3 && (vflag==encoding || vflag==result->uudet)) {
-	  result->uudet = vflag;
+
+	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]);
+	  cbxxe = (isxxe[(iscnt-1)%10] && isxxe[(iscnt-2)%10] &&
+		   isxxe[(iscnt-3)%10] && isxxe[(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;
 
 	  /*
@@ -978,10 +1074,12 @@ ScanData (FILE *datei, char *fname, int *errcode,
 	      /* 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;
 
@@ -998,37 +1096,90 @@ ScanData (FILE *datei, char *fname, int *errcode,
 	       strncmp (line+2, boundary, blen) == 0)) {
 	    break;
 	  }
+
 	  /*
 	   * Otherwise, we wait until finding something more interesting
 	   * in the outer loop
 	   */
+
+	  continue;
 	}
-	else if (encoding == XX_ENCODED && vflag == B64ENCODED) {
-	  dflag++;
+	
+	/*
+	 * 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; dflaguudet) {
-	  if (vflag == result->uudet)
-	    dflag++;
-	  else
-	    dflag=0;
+
+	/*
+	 * 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 (encoding != vflag) {
-          encoding = vflag;
-          dflag = 1;
-        }
-        else {
-          encoding = vflag;
-          dflag++;
-        }
       }
       else if (!dontcare) {
 	encoding = 0;
         dflag = 0;
 	haddh = 0;
       }
-#if 0
     } /* if (!uudet) */
-#endif
     /*
      * End of scanning loop
      */
@@ -1054,6 +1205,29 @@ ScanData (FILE *datei, char *fname, int *errcode,
   if (result->uudet == B64ENCODED || result->uudet == BH_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
@@ -1096,8 +1270,8 @@ 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;
+  int bhflag, begflag, vflag, blen=0, res;
+  long preheaders, prevpos=0, preenc, before;
   char *line=uuscan_spline;
   fileread *result;
   char *ptr1, *ptr2;
@@ -1189,6 +1363,35 @@ ScanPart (FILE *datei, char *fname, int *errcode)
     }
     line[255] = '\0';
 
+    /*
+     * Special handling for AOL folder files, which start off with a boundary.
+     * We recognize them by a valid boundary line as the first line of a file.
+     * Note that the rest of the scanning code becomes suspicious if a boun-
+     * dary does never appear in a file -- this should save us from grave
+     * false detection errors
+     */
+
+    if (!feof (datei) && line[0] == '-' && line[1] == '-' && line[2]) {
+      while (line[strlen(line)-1] == '\012' ||
+	     line[strlen(line)-1] == '\015') {
+	line[strlen(line)-1] = '\0';
+      }
+
+      sstate.ismime            = 1;
+      sstate.envelope.mimevers = _FP_strdup ("1.0");
+      sstate.envelope.boundary = _FP_strdup (line+2);
+      sstate.envelope.ctype    = _FP_strdup ("multipart/mixed");
+      sstate.mimestate         = MS_SUBPART;
+
+      *errcode = UURET_CONT;
+      _FP_free (result);
+      return NULL;
+    }
+
+    /*
+     * Normal behavior: look for a RFC 822 header
+     */
+
     while (!feof (datei) && !IsLineEmpty (line)) {
       if (IsKnownHeader (line))
 	hcount++;
@@ -1228,15 +1431,12 @@ ScanPart (FILE *datei, char *fname, int *errcode)
      * If we don't have all valid MIME headers yet, but the following
      * line is a MIME header, accept it anyway.
      */
-#ifndef MORE_MIME
-    if ((sstate.envelope.mimevers == NULL &&
-	 _FP_strnicmp (line, "Mime-Version:", 13) == 0) ||
-	(sstate.envelope.ctype == NULL &&
-	 _FP_strnicmp (line, "Content-Type:", 13) == 0) ||
-	(sstate.envelope.mimevers == NULL &&
-	 sstate.envelope.ctype    == NULL &&
-	 sstate.envelope.ctenc    == NULL &&
-	 _FP_strnicmp (line, "Content-Transfer-Encoding:", 26) == 0)) {
+
+    if (!uu_more_mime &&
+	sstate.envelope.mimevers == NULL &&
+	sstate.envelope.ctype    == NULL &&
+	sstate.envelope.ctenc    == NULL &&
+	IsKnownHeader (line)) {
       /*
        * see above
        */
@@ -1256,14 +1456,6 @@ ScanPart (FILE *datei, char *fname, int *errcode)
 	  _FP_free (result);
 	  return NULL;
 	}
-	/*
-	 * if we've read too many lines without finding headers, then
-	 * this probably isn't a mail folder after all
-	 */
-	lcount++;
-	if (lcount > WAITHEADER && hcount < hlcount.afternl)
-	  break;
-	
 	if (_FP_fgets (line, 255, datei) == NULL)
 	  break;
 	line[255] = '\0';
@@ -1282,7 +1474,7 @@ ScanPart (FILE *datei, char *fname, int *errcode)
 	prevpos = ftell (datei);
       }
     }
-#endif
+
     /*
      * A partial multipart message probably has only a Content-Type
      * header but nothing else. In this case, at least simulate a
@@ -1552,9 +1744,8 @@ ScanPart (FILE *datei, char *fname, int *errcode)
 	hcount = lcount = 0;
       }
 
-#ifndef MORE_MIME
       /* check for begin and encoded data only at outermost level */
-      if (mssdepth == 0) {
+      if (mssdepth == 0 && !uu_more_mime) {
 	if (strncmp      (line, "begin ",       6) == 0 ||
 	    _FP_strnicmp (line, "
begin ", 11) == 0) {
 	  preenc  = prevpos;
@@ -1586,13 +1777,13 @@ ScanPart (FILE *datei, char *fname, int *errcode)
 	  ecount  = 0;
 	}
       }
-#endif
 
       if (!IsLineEmpty (line))
 	res++;
 
       prevpos = ftell (datei);
     }
+
     if (mssdepth > 0 &&	line[0] == '-' && line[1] == '-' &&
 	strncmp (line+2,
 		 multistack[mssdepth-1].envelope.boundary, blen) == 0) {
@@ -1820,14 +2011,25 @@ ScanPart (FILE *datei, char *fname, int *errcode)
      */
     if (_FP_stristr (localenv.ctenc, "base64") != NULL)
       result->uudet = B64ENCODED;
+    else if (_FP_stristr (localenv.ctenc, "x-uue") != NULL)
+      result->uudet = UU_ENCODED;
     else if (_FP_stristr (localenv.ctenc, "quoted-printable") != NULL)
       result->uudet = QP_ENCODED;
     else if (_FP_stristr (localenv.ctenc, "7bit") != NULL ||
 	     _FP_stristr (localenv.ctenc, "8bit") != NULL)
       result->uudet = PT_ENCODED;
-    else if (_FP_stristr (localenv.ctype, "message") != NULL)
+    else if (_FP_stristr (localenv.ctype, "multipart") != NULL ||
+	     _FP_stristr (localenv.ctype, "message")   != NULL)
       result->uudet = PT_ENCODED;
 
+    /*
+     * If we're switched to MIME-only mode, handle as text
+     */
+
+    if (uu_more_mime >= 2 && !result->uudet) {
+      result->uudet = PT_ENCODED;
+    }
+
     if (result->uudet) {
       /*
        * Oh-kay, go ahead. Just read and wait for the boundary
@@ -1940,16 +2142,15 @@ ScanPart (FILE *datei, char *fname, int *errcode)
 	}
       }
       /* produce result if uu_handletext is set */
-      if ((result->uudet == B64ENCODED || uu_handletext) &&
-	  (result->uudet != QP_ENCODED ||
-	   result->uudet != PT_ENCODED || lcount>0)) {
+      /* or if the file is explicitely named */
+      if (result->uudet == B64ENCODED || lcount) {
 	if (localenv.fname) {
 	  _FP_free (result->filename);
 	  if ((result->filename = _FP_strdup (localenv.fname)) == NULL)
 	    *errcode = UURET_NOMEM;
 	}
 	else if ((result->uudet==QP_ENCODED||result->uudet==PT_ENCODED) &&
-		 result->filename == NULL) {
+		 result->filename == NULL && uu_handletext) {
 	  sprintf (line, "%04d.txt", ++mimseqno);
 	  if ((result->filename = _FP_strdup (line)) == NULL)
 	    *errcode = UURET_NOMEM;
@@ -1984,13 +2185,16 @@ ScanPart (FILE *datei, char *fname, int *errcode)
       UUkillheaders (&localenv);
       return result;
     }
+
     /*
      * we're in a subpart, but the local headers don't give us any
      * clue about what's to find here. So look for encoded data by
      * ourselves.
      */
+
     if ((res = ScanData (datei, fname, errcode,
-			 sstate.envelope.boundary, 1, 0, result)) == -1) {
+			 sstate.envelope.boundary,
+			 1, 0, result)) == -1) {
       /* oops, something went wrong */
       sstate.isfolder = 0;
       sstate.ismime   = 0;
@@ -2090,17 +2294,29 @@ ScanPart (FILE *datei, char *fname, int *errcode)
 	sstate.ismime    = 0;
       }
     }
+
+    /*
+     * If this file has been nicely MIME so far, then be very suspicious
+     * if ScanData reports anything else. So do a double check, and if
+     * it doesn't hold up, handle as plain text instead.
+     */
+
+    if (strcmp (localenv.mimevers, "1.0") == 0 &&
+	_FP_stristr (localenv.ctype, "text") != NULL &&
+	sstate.ismime && sstate.mimestate == MS_SUBPART &&
+	!uu_desperate) {
+      if (result->uudet == UU_ENCODED && !(result->begin || result->end)) {
+	result->uudet = 0;
+      }
+    }
+
     /*
      * produce result
      */
-    if (result->uudet == 0 && uu_handletext) {
+
+    if (result->uudet == 0) {
       result->uudet = PT_ENCODED; /* plain text */
     }
-    else if (result->uudet == 0) {
-      UUkillheaders (&localenv);
-      _FP_free (result);
-      return NULL;
-    }
 
     if (localenv.fname) {
       _FP_free (result->filename);
@@ -2108,7 +2324,7 @@ ScanPart (FILE *datei, char *fname, int *errcode)
 	*errcode = UURET_NOMEM;
     }
     else if ((result->uudet==QP_ENCODED || result->uudet==PT_ENCODED) &&
-	     result->filename==NULL) {
+	     result->filename==NULL && uu_handletext) {
       sprintf (line, "%04d.txt", ++mimseqno);
       if ((result->filename = _FP_strdup (line)) == NULL)
 	*errcode = UURET_NOMEM;
@@ -2234,9 +2450,22 @@ ScanPart (FILE *datei, char *fname, int *errcode)
 	result->uudet = QP_ENCODED;
       else if (_FP_stristr (localenv.ctenc, "base64") != NULL)
 	result->uudet = B64ENCODED;
+      else if (_FP_stristr (localenv.ctenc, "x-uue") != NULL)
+	result->uudet = UU_ENCODED;
+      else if (_FP_stristr (localenv.ctenc, "7bit") != NULL ||
+	       _FP_stristr (localenv.ctenc, "8bit") != NULL)
+	result->uudet = PT_ENCODED;
       else if (_FP_stristr (localenv.ctype, "multipart") != NULL ||
 	       _FP_stristr (localenv.ctype, "message")   != NULL)
 	result->uudet = PT_ENCODED;
+
+      /*
+       * If we're switched to MIME-only mode, handle as text
+       */
+
+      if (uu_more_mime >= 2 && !result->uudet) {
+	result->uudet = PT_ENCODED;
+      }
     }
     else {
       memset (&localenv, 0, sizeof (headers));
@@ -2262,7 +2491,6 @@ ScanPart (FILE *datei, char *fname, int *errcode)
     }
     else if (result->uudet != 0) {
       hcount = lcount = 0;
-
       prevpos = ftell (datei);
 
       if (_FP_stristr (localenv.ctype, "message") != NULL &&
@@ -2274,17 +2502,11 @@ ScanPart (FILE *datei, char *fname, int *errcode)
 	while (!feof (datei)) {
 	  if (_FP_fgets (line, 255, datei) == NULL)
 	    break;
+	  line[255] = '\0';
 	  if (!IsLineEmpty (line)) {
-	    fseek (datei, preheaders, SEEK_SET);
-	    line[255] = '\0';
 	    break;
 	  }
 	}
-	if (_FP_fgets (line, 255, datei) == NULL) {
-	  _FP_free (result);
-	  return NULL;
-	}
-	line[255] = '\0';
 
 	while (!feof (datei) && !IsLineEmpty (line)) { 
 	  if (IsKnownHeader (line))
@@ -2388,6 +2610,8 @@ ScanPart (FILE *datei, char *fname, int *errcode)
 	result->subject = _FP_strdup (sstate.envelope.subject);
     }
     result->partno = sstate.envelope.partno;
+    if (sstate.envelope.partno == 1)
+      result->begin = 1;
     result->maxpno = sstate.envelope.numparts;
     result->flags  = FL_PARTIAL | 
       ((res==1 || uu_fast_scanning) ? FL_PROPER : 0) |
@@ -2435,14 +2659,19 @@ ScanPart (FILE *datei, char *fname, int *errcode)
   }
 
   /*
-   * if this is a MIME body, honor a Content-Type different than
+   * If this is a MIME body, honor a Content-Type different than
    * text/plain or a proper Content-Transfer-Encoding.
+   * We also go in here if we have an assigned filename - this means
+   * that we've had a Content-Disposition field, and we should probably
+   * decode a plain-text segment with a filename.
    */
   if (sstate.isfolder && sstate.ismime &&
       sstate.mimestate == MS_BODY &&
       (_FP_stristr (sstate.envelope.ctenc, "quoted-printable") != NULL ||
        _FP_stristr (sstate.envelope.ctenc, "base64")           != NULL ||
-       _FP_stristr (sstate.envelope.ctype, "message")          != NULL)) {
+       _FP_stristr (sstate.envelope.ctenc, "x-uue")            != NULL ||
+       _FP_stristr (sstate.envelope.ctype, "message")          != NULL ||
+       sstate.envelope.fname != NULL)) {
 
     if (sstate.envelope.subject)
       result->subject = _FP_strdup (sstate.envelope.subject);
@@ -2458,16 +2687,32 @@ ScanPart (FILE *datei, char *fname, int *errcode)
       result->uudet = QP_ENCODED;
     else if (_FP_stristr (sstate.envelope.ctenc, "base64") != NULL)
       result->uudet = B64ENCODED;
+    else if (_FP_stristr (sstate.envelope.ctenc, "x-uue") != NULL)
+      result->uudet = UU_ENCODED;
+    else if (_FP_stristr (sstate.envelope.ctenc, "7bit") != NULL ||
+	     _FP_stristr (sstate.envelope.ctenc, "8bit") != NULL)
+      result->uudet = PT_ENCODED;
     else if (_FP_stristr (sstate.envelope.ctype, "multipart") != NULL ||
-	     _FP_stristr (sstate.envelope.ctype, "message")   != NULL)
+	     _FP_stristr (sstate.envelope.ctype, "message")   != NULL ||
+	     sstate.envelope.fname != NULL)
       result->uudet = PT_ENCODED;
 
-    prevpos = ftell (datei);
+    /*
+     * If we're switched to MIME-only mode, handle as text
+     */
+
+    if (uu_more_mime >= 2 && !result->uudet) {
+      result->uudet = PT_ENCODED;
+    }
+
+    result->startpos = prevpos = ftell (datei);
     
     /*
      * If this is Quoted-Printable or Plain Text, just try looking
      * for the next message header. If uu_fast_scanning, we know
      * there won't be more headers.
+     * If it is a "trivial" (non-embedded) message/rfc822, skip over
+     * the message header and then start looking for the next header.
      */
     if (result->uudet != 0 && uu_fast_scanning) {
       /* do nothing */
@@ -2475,8 +2720,43 @@ ScanPart (FILE *datei, char *fname, int *errcode)
     }
     else if (result->uudet != 0) {
       hcount = lcount = 0;
-
       prevpos = ftell (datei);
+
+      if (_FP_stristr (sstate.envelope.ctype, "message") != NULL &&
+	  _FP_stristr (sstate.envelope.ctype, "rfc822")  != NULL) {
+	/*
+	 * skip over empty lines and local header
+	 */
+	preheaders = ftell (datei);
+	while (!feof (datei)) {
+	  if (_FP_fgets (line, 255, datei) == NULL)
+	    break;
+	  line[255] = '\0';
+	  if (!IsLineEmpty (line)) {
+	    break;
+	  }
+	}
+
+	while (!feof (datei) && !IsLineEmpty (line)) { 
+	  if (IsKnownHeader (line))
+	    hcount++;
+	  lcount++;
+	  if (lcount > WAITHEADER && hcount < hlcount.afternl)
+	    break;
+
+	  if (_FP_fgets (line, 255, datei) == NULL)
+	    break;
+	  line[255] = '\0';
+	}
+	if (hcount < hlcount.afternl)
+	  fseek (datei, preheaders, SEEK_SET);
+	hcount = lcount = 0;
+      }
+
+      /*
+       * look for next header
+       */
+
       while (!feof (datei)) {
 	if (_FP_fgets (line, 255, datei) == NULL)
 	  break;
@@ -2592,7 +2872,6 @@ ScanPart (FILE *datei, char *fname, int *errcode)
     return result;
   }
 
-#ifndef MORE_MIME
   /*
    * Some files have reduced headers, and what should be a multipart
    * message is missing the proper Content-Type. If the first thing
@@ -2604,8 +2883,10 @@ ScanPart (FILE *datei, char *fname, int *errcode)
    * we know that sstate.envelope.boundary is NULL, or we wouldn't
    * be here!
    */
-  if (sstate.envelope.ctype == NULL ||
-      _FP_stristr (sstate.envelope.ctype, "multipart") != NULL) {
+
+  if ((sstate.envelope.ctype == NULL ||
+       _FP_stristr (sstate.envelope.ctype, "multipart") != NULL) &&
+      !uu_more_mime) {
     prevpos = ftell (datei);
     while (!feof (datei)) {
       if (_FP_fgets (line, 255, datei) == NULL) {
@@ -2650,7 +2931,6 @@ ScanPart (FILE *datei, char *fname, int *errcode)
     }
     fseek (datei, prevpos, SEEK_SET);
   }
-#endif
 
   /*
    * Hmm, we're not in a ''special'' state, so it's more or less
diff --git a/goldlib/uulib/uustring.c b/goldlib/uulib/uustring.c
index e854d9b..dd99369 100644
--- a/goldlib/uulib/uustring.c
+++ b/goldlib/uulib/uustring.c
@@ -1,7 +1,7 @@
 /*
  * This file is part of uudeview, the simple and friendly multi-part multi-
- * file uudecoder  program  (c)  1994 by Frank Pilhofer. The author may be
- * contacted by his email address,          fp@informatik.uni-frankfurt.de
+ * file uudecoder  program  (c) 1994-2001 by Frank Pilhofer. The author may
+ * be contacted at fp@fpx.de
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
diff --git a/goldlib/uulib/uustring.h b/goldlib/uulib/uustring.h
index bca363e..1531b7f 100644
--- a/goldlib/uulib/uustring.h
+++ b/goldlib/uulib/uustring.h
@@ -1,4 +1,4 @@
-/* extracted from Id: uustring.c,v 1.1 2000/01/27 18:44:38 asa Exp  */
+/* extracted from Id: uustring.c,v 1.6 2001/06/06 18:21:47 fp Exp  */
 #define S_NOT_OPEN_SOURCE      1
 #define S_NOT_OPEN_TARGET      2
 #define S_NOT_OPEN_FILE        3
diff --git a/goldlib/uulib/uuutil.c b/goldlib/uulib/uuutil.c
index 547cb27..f1779b2 100644
--- a/goldlib/uulib/uuutil.c
+++ b/goldlib/uulib/uuutil.c
@@ -1,7 +1,7 @@
 /*
  * This file is part of uudeview, the simple and friendly multi-part multi-
- * file uudecoder  program  (c)  1994 by Frank Pilhofer. The author may be
- * contacted by his email address,          fp@informatik.uni-frankfurt.de
+ * file uudecoder  program  (c) 1994-2001 by Frank Pilhofer. The author may
+ * be contacted at fp@fpx.de
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -477,9 +477,3 @@ UUSmerge (int pass)
   return flag;
 }
 
-
-/*****************************************************************************
- + Frank Pilhofer                             fp@informatik.uni-frankfurt.de +
- +---------------------------------------------------------------------------+
- | Department of Computer Sciences * University of Frankfurt / Main, Germany |
- *****************************************************************************/