Convert-UUlib-1.5/0000755000000000000000000000000012550073763012523 5ustar rootrootConvert-UUlib-1.5/typemap0000644000000000000000000000045310211640716014115 0ustar rootrootuulist * T_UULIST INPUT T_UULIST if (sv_derived_from($arg, \"Convert::UUlib::Item\")) { IV tmp = SvIV((SV*)SvRV($arg)); $var = ($type) tmp; } else croak(\"$var is not of type Convert::UUlib::Item\") OUTPUT T_UULIST sv_setref_pv($arg, \"Convert::UUlib::Item\", (void*)$var); Convert-UUlib-1.5/UUlib.xs0000644000000000000000000003427112547616304014126 0ustar rootroot#include "EXTERN.h" #include "perl.h" #include "XSUB.h" #include "uulib/fptools.h" #include "uulib/uudeview.h" #include "uulib/uuint.h" static int not_here (char *s) { croak("%s not implemented", s); return -1; } static int constant (char *name) { errno = 0; switch (*name) { case 'A': if (strEQ(name, "ACT_COPYING")) return UUACT_COPYING; if (strEQ(name, "ACT_DECODING")) return UUACT_DECODING; if (strEQ(name, "ACT_ENCODING")) return UUACT_ENCODING; if (strEQ(name, "ACT_IDLE")) return UUACT_IDLE; if (strEQ(name, "ACT_SCANNING")) return UUACT_SCANNING; case 'F': if (strEQ(name, "FILE_DECODED")) return UUFILE_DECODED; if (strEQ(name, "FILE_ERROR")) return UUFILE_ERROR; if (strEQ(name, "FILE_MISPART")) return UUFILE_MISPART; if (strEQ(name, "FILE_NOBEGIN")) return UUFILE_NOBEGIN; if (strEQ(name, "FILE_NODATA")) return UUFILE_NODATA; if (strEQ(name, "FILE_NOEND")) return UUFILE_NOEND; if (strEQ(name, "FILE_OK")) return UUFILE_OK; if (strEQ(name, "FILE_READ")) return UUFILE_READ; if (strEQ(name, "FILE_TMPFILE")) return UUFILE_TMPFILE; break; case 'M': if (strEQ(name, "MSG_ERROR")) return UUMSG_ERROR; if (strEQ(name, "MSG_FATAL")) return UUMSG_FATAL; if (strEQ(name, "MSG_MESSAGE")) return UUMSG_MESSAGE; if (strEQ(name, "MSG_NOTE")) return UUMSG_NOTE; if (strEQ(name, "MSG_PANIC")) return UUMSG_PANIC; if (strEQ(name, "MSG_WARNING")) return UUMSG_WARNING; case 'O': if (strEQ(name, "OPT_VERSION")) return UUOPT_VERSION; if (strEQ(name, "OPT_FAST")) return UUOPT_FAST; if (strEQ(name, "OPT_DUMBNESS")) return UUOPT_DUMBNESS; if (strEQ(name, "OPT_BRACKPOL")) return UUOPT_BRACKPOL; if (strEQ(name, "OPT_VERBOSE")) return UUOPT_VERBOSE; if (strEQ(name, "OPT_DESPERATE")) return UUOPT_DESPERATE; if (strEQ(name, "OPT_IGNREPLY")) return UUOPT_IGNREPLY; if (strEQ(name, "OPT_OVERWRITE")) return UUOPT_OVERWRITE; if (strEQ(name, "OPT_SAVEPATH")) return UUOPT_SAVEPATH; if (strEQ(name, "OPT_IGNMODE")) return UUOPT_IGNMODE; if (strEQ(name, "OPT_DEBUG")) return UUOPT_DEBUG; if (strEQ(name, "OPT_ERRNO")) return UUOPT_ERRNO; if (strEQ(name, "OPT_PROGRESS")) return UUOPT_PROGRESS; if (strEQ(name, "OPT_USETEXT")) return UUOPT_USETEXT; if (strEQ(name, "OPT_PREAMB")) return UUOPT_PREAMB; if (strEQ(name, "OPT_TINYB64")) return UUOPT_TINYB64; if (strEQ(name, "OPT_ENCEXT")) return UUOPT_ENCEXT; if (strEQ(name, "OPT_REMOVE")) return UUOPT_REMOVE; if (strEQ(name, "OPT_MOREMIME")) return UUOPT_MOREMIME; if (strEQ(name, "OPT_DOTDOT")) return UUOPT_DOTDOT; if (strEQ(name, "OPT_RBUF")) return UUOPT_RBUF; if (strEQ(name, "OPT_WBUF")) return UUOPT_WBUF; if (strEQ(name, "OPT_AUTOCHECK")) return UUOPT_AUTOCHECK; case 'R': if (strEQ(name, "RET_CANCEL")) return UURET_CANCEL; if (strEQ(name, "RET_CONT")) return UURET_CONT; if (strEQ(name, "RET_EXISTS")) return UURET_EXISTS; if (strEQ(name, "RET_ILLVAL")) return UURET_ILLVAL; if (strEQ(name, "RET_IOERR")) return UURET_IOERR; if (strEQ(name, "RET_NODATA")) return UURET_NODATA; if (strEQ(name, "RET_NOEND")) return UURET_NOEND; if (strEQ(name, "RET_NOMEM")) return UURET_NOMEM; if (strEQ(name, "RET_OK")) return UURET_OK; if (strEQ(name, "RET_UNSUP")) return UURET_UNSUP; case 'B': if (strEQ(name, "B64_ENCODED")) return B64ENCODED; if (strEQ(name, "BH_ENCODED")) return BH_ENCODED; case 'P': if (strEQ(name, "PT_ENCODED")) return PT_ENCODED; case 'Q': if (strEQ(name, "QP_ENCODED")) return QP_ENCODED; case 'U': if (strEQ(name, "UU_ENCODED")) return UU_ENCODED; case 'X': if (strEQ(name, "XX_ENCODED")) return XX_ENCODED; case 'Y': if (strEQ(name, "YENC_ENCODED")) return YENC_ENCODED; } errno = EINVAL; return 0; } static void uu_msg_callback (void *cb, char *msg, int level) { dSP; ENTER; SAVETMPS; PUSHMARK (SP); EXTEND (SP, 2); PUSHs (sv_2mortal (newSVpv (msg, 0))); PUSHs (sv_2mortal (newSViv (level))); PUTBACK; (void) perl_call_sv ((SV *)cb, G_VOID|G_DISCARD); SPAGAIN; PUTBACK; FREETMPS; LEAVE; } static int uu_busy_callback (void *cb, uuprogress *uup) { dSP; int count; int retval; ENTER; SAVETMPS; PUSHMARK (SP); EXTEND (SP, 6); PUSHs (sv_2mortal (newSViv (uup->action))); PUSHs (sv_2mortal (newSVpv (uup->curfile, 0))); PUSHs (sv_2mortal (newSViv (uup->partno))); PUSHs (sv_2mortal (newSViv (uup->numparts))); PUSHs (sv_2mortal (newSViv (uup->fsize))); PUSHs (sv_2mortal (newSViv (uup->percent))); PUTBACK; count = perl_call_sv ((SV *)cb, G_SCALAR); SPAGAIN; if (count != 1) croak ("busycallback perl callback returned more than one argument"); retval = POPi; PUTBACK; FREETMPS; LEAVE; return retval; } static char * uu_fnamefilter_callback (void *cb, char *fname) { dSP; int count; static char *str; ENTER; SAVETMPS; PUSHMARK (SP); EXTEND (SP, 1); PUSHs (sv_2mortal (newSVpv (fname, 0))); PUTBACK; count = perl_call_sv ((SV *)cb, G_SCALAR); SPAGAIN; if (count != 1) croak ("fnamefilter perl callback MUST return a single filename exactly"); _FP_free (str); str = _FP_strdup (SvPV_nolen (TOPs)); PUTBACK; FREETMPS; LEAVE; return str; } static int uu_file_callback (void *cb, char *id, char *fname, int retrieve) { dSP; int count; int retval; SV *xfname = newSVpv ("", 0); ENTER; SAVETMPS; PUSHMARK (SP); EXTEND (SP, 3); PUSHs (sv_2mortal (newSVpv (id, 0))); PUSHs (sv_2mortal (xfname)); PUSHs (sv_2mortal (newSViv (retrieve))); PUTBACK; count = perl_call_sv ((SV *)cb, G_SCALAR); SPAGAIN; if (count != 1) croak ("filecallback perl callback must return a single return status"); strcpy (fname, SvPV_nolen (xfname)); retval = POPi; PUTBACK; FREETMPS; LEAVE; return retval; } static char * uu_filename_callback (void *cb, char *subject, char *filename) { dSP; int count; ENTER; SAVETMPS; PUSHMARK (SP); EXTEND (SP, 2); PUSHs (sv_2mortal(newSVpv(subject, 0))); PUSHs (filename ? sv_2mortal(newSVpv(filename, 0)) : &PL_sv_undef); PUTBACK; count = perl_call_sv ((SV *)cb, G_ARRAY); SPAGAIN; if (count > 1) croak ("filenamecallback perl callback must return nothing or a single filename"); if (count) { _FP_free (filename); filename = SvOK (TOPs) ? _FP_strdup (SvPV_nolen (TOPs)) : 0; } PUTBACK; FREETMPS; LEAVE; return filename; } static SV *uu_msg_sv, *uu_busy_sv, *uu_file_sv, *uu_fnamefilter_sv, *uu_filename_sv; #define FUNC_CB(cb) (void *)(sv_setsv (cb ## _sv, func), cb ## _sv), func ? cb ## _callback : NULL static int uu_info_file (void *cb, char *info) { dSP; int count; int retval; ENTER; SAVETMPS; PUSHMARK(SP); EXTEND(SP,1); PUSHs(sv_2mortal(newSVpv(info,0))); PUTBACK; count = perl_call_sv ((SV *)cb, G_SCALAR); SPAGAIN; if (count != 1) croak ("info_file perl callback returned more than one argument"); retval = POPi; PUTBACK; FREETMPS; LEAVE; return retval; } static int uu_opt_isstring (int opt) { switch (opt) { case UUOPT_VERSION: case UUOPT_SAVEPATH: case UUOPT_ENCEXT: return 1; default: return 0; } } static int uu_initialized; MODULE = Convert::UUlib PACKAGE = Convert::UUlib PREFIX = UU PROTOTYPES: ENABLE int constant (name) char * name void UUInitialize () CODE: if (!uu_initialized) { int retval; if ((retval = UUInitialize ()) != UURET_OK) croak ("unable to initialize uudeview library (%s)", UUstrerror (retval)); uu_initialized = 1; } void UUCleanUp () CODE: if (uu_initialized) UUCleanUp (); uu_initialized = 0; SV * UUGetOption (opt) int opt CODE: { if (opt == UUOPT_PROGRESS) croak ("GetOption(UUOPT_PROGRESS) is not yet implemented"); else if (uu_opt_isstring (opt)) { char cval[8192]; UUGetOption (opt, 0, cval, sizeof cval); RETVAL = newSVpv (cval, 0); } else { RETVAL = newSViv (UUGetOption (opt, 0, 0, 0)); } } OUTPUT: RETVAL int UUSetOption (opt, val) int opt SV * val CODE: { STRLEN dc; if (uu_opt_isstring (opt)) RETVAL = UUSetOption (opt, 0, SvPV (val, dc)); else RETVAL = UUSetOption (opt, SvIV (val), (void *)0); } OUTPUT: RETVAL char * UUstrerror (errcode) int errcode void UUSetMsgCallback (func = 0) SV * func CODE: UUSetMsgCallback (FUNC_CB (uu_msg)); void UUSetBusyCallback (func = 0,msecs = 1000) SV * func long msecs CODE: UUSetBusyCallback (FUNC_CB (uu_busy), msecs); void UUSetFileCallback (func = 0) SV * func CODE: UUSetFileCallback (FUNC_CB (uu_file)); void UUSetFNameFilter (func = 0) SV * func CODE: UUSetFNameFilter (FUNC_CB (uu_fnamefilter)); void UUSetFileNameCallback (func = 0) SV * func CODE: UUSetFileNameCallback (FUNC_CB (uu_filename)); char * UUFNameFilter (fname) char * fname void UULoadFile (fname, id = 0, delflag = 0, partno = -1) char * fname char * id int delflag int partno PPCODE: { int count; XPUSHs (sv_2mortal (newSViv (UULoadFileWithPartNo (fname, id, delflag, partno, &count)))); if (GIMME_V == G_ARRAY) XPUSHs (sv_2mortal (newSViv (count))); } int UUSmerge (pass) int pass int UUQuickDecode(datain,dataout,boundary,maxpos) FILE * datain FILE * dataout char * boundary long maxpos int UUEncodeMulti(outfile,infile,infname,encoding,outfname,mimetype,filemode) FILE * outfile FILE * infile char * infname int encoding char * outfname char * mimetype int filemode int UUEncodePartial(outfile,infile,infname,encoding,outfname,mimetype,filemode,partno,linperfile) FILE * outfile FILE * infile char * infname int encoding char * outfname char * mimetype int filemode int partno long linperfile int UUEncodeToStream(outfile,infile,infname,encoding,outfname,filemode) FILE * outfile FILE * infile char * infname int encoding char * outfname int filemode int UUEncodeToFile(infile,infname,encoding,outfname,diskname,linperfile) FILE * infile char * infname int encoding char * outfname char * diskname long linperfile int UUE_PrepSingle(outfile,infile,infname,encoding,outfname,filemode,destination,from,subject,isemail) FILE * outfile FILE * infile char * infname int encoding char * outfname int filemode char * destination char * from char * subject int isemail int UUE_PrepPartial(outfile,infile,infname,encoding,outfname,filemode,partno,linperfile,filesize,destination,from,subject,isemail) FILE * outfile FILE * infile char * infname int encoding char * outfname int filemode int partno long linperfile long filesize char * destination char * from char * subject int isemail uulist * UUGetFileListItem (num) int num MODULE = Convert::UUlib PACKAGE = Convert::UUlib::Item int rename (item, newname) uulist *item char * newname CODE: RETVAL = UURenameFile (item, newname); OUTPUT: RETVAL int decode_temp (item) uulist *item CODE: RETVAL = UUDecodeToTemp (item); OUTPUT: RETVAL int remove_temp (item) uulist *item CODE: RETVAL = UURemoveTemp (item); OUTPUT: RETVAL int decode (item, target = 0) uulist *item char * target CODE: RETVAL = UUDecodeFile (item, target); OUTPUT: RETVAL void info (item, func) uulist *item SV * func CODE: UUInfoFile (item,(void *)func, uu_info_file); short state(li) uulist *li CODE: RETVAL = li->state; OUTPUT: RETVAL short mode(li,newmode=0) uulist *li short newmode CODE: if (newmode) li->mode = newmode; RETVAL = li->mode; OUTPUT: RETVAL short uudet(li) uulist *li CODE: RETVAL = li->uudet; OUTPUT: RETVAL long size(li) uulist *li CODE: RETVAL = li->size; OUTPUT: RETVAL char * filename (li, newfilename = 0) uulist *li char * newfilename CODE: if (newfilename) { _FP_free (li->filename); li->filename = _FP_strdup (newfilename); } RETVAL = li->filename; OUTPUT: RETVAL char * subfname (li) uulist *li CODE: RETVAL = li->subfname; OUTPUT: RETVAL char * mimeid (li) uulist *li CODE: RETVAL = li->mimeid; OUTPUT: RETVAL char * mimetype (li) uulist *li CODE: RETVAL = li->mimetype; OUTPUT: RETVAL char * binfile (li) uulist *li CODE: RETVAL = li->binfile; OUTPUT: RETVAL # methods accessing internal data(!) void parts (li) uulist *li PPCODE: { struct _uufile *p = li->thisfile; while (p) { HV *pi = newHV (); hv_store (pi, "partno" , 6, newSViv (p->partno) , 0); if (p->filename) hv_store (pi, "filename", 8, newSVpv (p->filename, 0) , 0); if(p->subfname) hv_store (pi, "subfname", 8, newSVpv (p->subfname, 0) , 0); if(p->mimeid) hv_store (pi, "mimeid" , 6, newSVpv (p->mimeid , 0) , 0); if(p->mimetype) hv_store (pi, "mimetype", 8, newSVpv (p->mimetype, 0) , 0); if (p->data->subject) hv_store (pi, "subject" , 7, newSVpv (p->data->subject,0), 0); if (p->data->origin) hv_store (pi, "origin" , 6, newSVpv (p->data->origin ,0), 0); if (p->data->sfname) hv_store (pi, "sfname" , 6, newSVpv (p->data->sfname ,0), 0); XPUSHs (sv_2mortal (newRV_noinc ((SV *)pi))); p = p->NEXT; } } BOOT: uu_msg_sv = newSVsv (&PL_sv_undef); uu_busy_sv = newSVsv (&PL_sv_undef); uu_file_sv = newSVsv (&PL_sv_undef); uu_fnamefilter_sv = newSVsv (&PL_sv_undef); uu_filename_sv = newSVsv (&PL_sv_undef); Convert-UUlib-1.5/Makefile.PL0000644000000000000000000000155512550073721014475 0ustar rootrootuse ExtUtils::MakeMaker; use Canary::Stability Convert::UUlib => 1; sub MY::postamble { my $postamble =<<'END'; uulib/Makefile: cd uulib && ./configure --with-cc='$(CC)' --with-cflags='$(OPTIMIZE) $(CFLAGS) $(CCCDLFLAGS)' clean:: -cd uulib && make distclean force: $(MYEXTLIB): uulib/Makefile uulib/uulib.c force cd uulib && $(MAKE) all END } WriteMakefile( 'dist' => { PREOP => 'pod2text UUlib.pm | tee README >$(DISTVNAME)/README; chmod -R u=rwX,go=rX . ; chmod -R u=rwX,go=rX . ;', COMPRESS => 'gzip -9v', SUFFIX => '.gz', }, 'NAME' => 'Convert::UUlib', 'VERSION_FROM' => 'UUlib.pm', 'MYEXTLIB' => 'uulib/libuu$(LIB_EXT)', 'LIBS' => [''], 'DEFINE' => '', 'INC' => '', CONFIGURE_REQUIRES => { "ExtUtils::MakeMaker" => 6.52, "Canary::Stability" => 0, }, ); Convert-UUlib-1.5/META.yml0000644000000000000000000000072012550073763013773 0ustar rootroot--- abstract: unknown author: - unknown build_requires: ExtUtils::MakeMaker: '0' configure_requires: Canary::Stability: '0' ExtUtils::MakeMaker: '6.52' dynamic_config: 1 generated_by: 'ExtUtils::MakeMaker version 7.0401, CPAN::Meta::Converter version 2.150001' license: unknown meta-spec: url: http://module-build.sourceforge.net/META-spec-v1.4.html version: '1.4' name: Convert-UUlib no_index: directory: - t - inc requires: {} version: 1.5 Convert-UUlib-1.5/Changes0000644000000000000000000002265512550073673014030 0ustar rootrootRevision history for Perl extension Convert::UUlib. 1.5 Sat Jul 11 03:56:06 CEST 2015 - fix a heap overflow (testcase by Krzysztof Wojtaƛ). - on systems that support it (posix + mmap + map_anonymous), allocate all dynamic areas via mmap and put four guard pages around them, to catch similar heap overflows safely in the future. - find a safer way to pass in CC/CFLAGS to uulib. - added stability canary support. 1.4 Sun May 29 17:17:01 CEST 2011 - avoid a classical buffer overflow in case a progress message is too long. - this release adds dependencies for snprintf/vsnprintf. - some uuencode encoders do not generate a final "space" line before the "end" marker, so do not rely on the line to be there. 1.34 Tue Dec 14 22:20:00 CET 2010 - fix a one-byte-past-end-write buffer overflow in UURepairData (reported, analysed and testcase provided by Marco Walther). - quoted-printable decoding was completely broken, try a fix. 1.33 Wed Oct 28 09:04:38 CET 2009 - handle yEnc files with part end=0 and total= more gracefully. I wish yEnc had been created by somebody who knows; what he does; but I doubt he even knows; what he did. 1.32 Wed Sep 16 20:07:13 CEST 2009 - Due to a glitch with CVS, configure lacked executable bits. (Quickly reported by Anton Berezin). 1.31 Wed Sep 16 09:04:30 CEST 2009 - do not use system-replacements for case-insensitive string functions when found, as they are broken on too many systems (mostly bsds, as usual, but at least some versions of GNU/Linux disagree with themselves apparently). Analyzed by Anton Berezin. 1.3 Sat Aug 29 01:24:35 CEST 2009 - major changes, new bugs and changes in decoding behaviour are expected (but not intended). - major scanning and decoding speed-up (by a factor of 4), by replacing ultra-slow _FP_gets and improving IsKnownHeader (but fgets is *still* responsible for >50% if the time). - new option OPT_AUTOCHECK to disable O(n) UUCheckGlobalList call after every loadfile, majorly speeds up large decodes (easily by a factor of 10..100). - allow "Smerge -1" to call UUCheckGlobalList. - majorly speed up part insertion (still O(n), but much faster). - allow for 1023 octet headers instead of the standard 255 octet ones. - support strcasestr, strcasecmp, strncasecmp for added speed. 1.12 Mon Oct 13 14:11:01 CEST 2008 - use the yencode filesize as additional matching criterium to avoid false matches. - made the example decoder more verbose w.r.t. error handling. - removed potentially confusing decode_temp calls from example decoder. 1.11 Fri Jun 13 15:32:30 CEST 2008 - don't ask. 1.10 Fri Jun 13 14:22:42 CEST 2008 - fix an infinite-looping problem when scanning in freestyle mode (testcase provided by Pieter Geens and Reinhard Pfau). 1.09 Fri May 25 19:38:11 CEST 2007 - create something sensible, trust a windows program to fuck it up: work around literal "(null)" filenames in yenc-encoded files. - some minor cleanups. 1.08 Sat Dec 16 23:27:13 CET 2006 - URGENT update, the last release did not decode files correctly, usually not at all. - my last patch was, of course, completely bogus. (sorry. looked simple...). 1.07 Sun Dec 10 17:41:46 CET 2006 - fixed an uninitialised variable based on analysis and patch by Mark Martinec. 1.06 Tue Dec 6 00:56:05 CET 2005 - fix a number of int/long format errors in the encoding part and fix some signed/unsigned char problems of unknown relevance, reported by Jonas Smedegaard. - new EXPERIMENTAL options OPT_RBUF and OPT_WBUF to set default stdio buffer size for reading and writing files. 1.051 Thu Mar 3 18:00:52 CET 2005 - change of contact address. - updated perl parts to GPLv2. 1.05 Fri Feb 25 22:50:27 CET 2005 - fix a (likely exploitable) segfault problem, (tracked down and/or reported by Mark Martinec and Robert Lewis). 1.04 Tue Dec 28 15:08:44 CET 2004 - slightly improved subject filename extraction. Also see the filename callback in the example-decoder. 1.03 Sun Apr 18 22:05:43 CEST 2004 - upgrade to uudeview-0.5.20, which supposedly fixes a few buffer overflows. However, judging from the patch these vulnerabilities were not present in the Convert-UUlib version (I might err, though, documentation on the actual exploits is scarce). As every uudeview update usually brings more instability than stability I advise against using this version until it has proven itself to be stable, or 1.02 is proven to contain the same buffer overflows. 1.02 Sun Apr 18 16:47:26 CEST 2004 - renamed crc32 to uulib_crc32, to work around yet another shortcoming in this oh-so-outdated macosx. 1.01 Sun Feb 1 19:49:51 CET 2004 - make it compile with 5.005_03 (reported by Anton Berezin). - very short files might not be detected because the header parsing code might skip them. 1.0 Thu Nov 6 14:32:08 CET 2003 - change bracket policy to give priority to (x/y) over (x), and use the last bracket found otherwise. - part numbers at the end of the subject are now recognized. - updated to uulib-0.5.19. Differences and bugfixes kept. 0.31 Wed Oct 16 01:22:34 CEST 2002 - no internal code changes. - much better documentation, now considered "useful". - removed the procedural interface. - fought the wish to perl-5.8'ify and thus simplify the code :(). - stress-tested version 0.3 against 70000 data postings since sunday. 0.3 Sun Oct 13 15:12:11 CEST 2002 - updated to uulib 0.5.18. As expected, some but not all of my bugfixes have went into uulib, so the number of differences decreased a bit again. - I found out that the library is being sold commercially by Frank Pilhofer, disregarding the GPL and ignoring the rights of the people who sent in patches :( - vastly more useful documentation in the .pm file. - much smaller distribution filesize ;) 0.213 Sat Jul 27 21:16:30 CEST 2002 - fixed another buffer overflow, also added a santity check to fgets. 0.212 Sat Apr 6 03:52:13 CEST 2002 - fix yEnc decoding support. - new option OPT_DOTDOT, that makes uulib unescape dot-escaping. - increased linelength to 1195. 0.211 Fri Apr 5 23:56:46 CEST 2002 - *sigh*. new version of uulib, new braindamaged buffer overflows fixed. Diffs like "line length 256 => 300" should have alerted me... 0.21 Sun Mar 31 22:06:05 CEST 2002 - bumped uulib from 0.5.15 to 0.5.17 (adds some yEnc support, YENC_ENCODED). - source-renamed FP_*-symbols to _FP_* again, but still define them to be FP_* in the object file. - new callback: SetFileNameCallback (actually documented ;) 0.201 Sun Sep 16 03:43:38 CEST 2001 - fixed another segfault-bug in uulib, thanks to Lars Hecking who provides all the test files ;) 0.2 Thu Jun 14 18:42:49 CEST 2001 - Frank Pilhofer is NOT dead! He is alive, kicking, and fixing bugs in uulib now! Since his uulib and mine diverged quite a bit I am still in the process of merging his bugfixes into my version. So be aware that this might introduce new instabilities... - merged uulib-0.5.15 - optimize decode_file to not copy the file contents when a rename succeeds (TMPDIR same disk as destination). - updated documentation. 0.111 Fri May 4 22:29:09 CEST 2001 - heuristic to decode microsoft-rfc822-headers (microsoft uses '\' as path seperator which is also the rfc822 quote character. of course they could have quoted it, but it's microsoft, so only the devil knows how they try to parse mime (they obviously haven't read the standard AGAIN). in case you wonder, this fixes the "c:my_documentssend.doc" "filename" problem. 0.11 Sun Jul 16 22:42:57 CEST 2000 - fixed a bug in the file callback. 0.10 Tue May 2 03:31:09 CEST 2000 - fixed one very longstanding bug that might have been the cause for the many mysterious segmentation faults. Hopefully. - improved documentation to the point that it slowly becomes useful as a (very quick) reference. 0.07 Wed Nov 24 18:45:23 CET 1999 - removed END { CleanUp } from UUlib.pm, perl is too buggy to rely on this in the face of popen etc.. 0.06 Thu Jul 29 22:48:18 CEST 1999 - Thierry Bezecourt had the very reasonable idea to include the example source in the manpage. 0.05 Mon May 24 11:37:25 CEST 1999 - LoadFile returns number of parts loaded. 0.04 Mon May 10 22:02:31 CEST 1999 - fixed a couple of portability problems. - UUEncodeToStream had a wrong definition. - added primitive testsuite. - added README. 0.03 Sat May 8 22:40:01 CEST 1999 - renamed it to Convert::UUlib. 0.02 Fri May 7 01:26:19 CEST 1999 - function names exportable (use :all-tag). - made uulist-related functions methods. - the first fix from cpan-tester. *sigh* you people save the world, continuously. 0.01 Thu May 6 14:30:44 1999 - original version; created by h2xs 1.19 Convert-UUlib-1.5/uulib/0000755000000000000000000000000012550073763013643 5ustar rootrootConvert-UUlib-1.5/uulib/uustring.awk0000644000000000000000000000066610211640773016230 0ustar rootroot#! /usr/bin/awk # # $Id$ # # Extract definitions for string codes from uustring.c into uustring.h # Does this script require GAWK? # BEGIN { i=1; } /\$Id/ { match ($0, "\\$Id.*\\$"); printf ("/* extracted from %s */\n", substr ($0, RSTART+1, RLENGTH-2)); } /^[ ]*\{[ ]*S_[A-Z_]+.*\}[ ]*,[ ]*$/ { match ($0, "S_[A-Z_]+"); printf ("#define %-20s %3d\n", substr ($0, RSTART, RLENGTH), i); i++; } Convert-UUlib-1.5/uulib/Makefile.in0000644000000000000000000000422512547613741015715 0ustar rootroot# # ============================================================================ # # This is the Makefile for the uu library, part of the uudeview package. # The values here were guessed by ./configure and are probably correct. # # Usefull targets # all Compile the package # clean Deletes the binaries and objects and all the # other dirty stuff. # # ============================================================================ # # $Id$ # # your make might need this # SHELL = /bin/sh # # If you don't have the GNU C compiler installed, set CC=cc here # CC = @CC@ # # C Compiler Options # CFLAGS = @CFLAGS@ -I. @CPPFLAGS@ @DEFS@ # # the ranlib program # RANLIB = @RANLIB@ # ############################################################################### # You shouldn't have to change anything below. ############################################################################### # # Programs to compile, Manpages to install and Versions # VERSION = @VERSION@ PATCH = @PATCH@ VDEF = -DVERSION=\"$(VERSION)\" -DPATCH=\"$(PATCH)\" # UULIB_SOURCE = uulib.c uucheck.c uunconc.c uuutil.c uuencode.c \ uuscan.c uustring.c fptools.c crc32.c UULIB_OBJ = ${UULIB_SOURCE:.c=.o} # # make stuff # .SUFFIXES: .SUFFIXES: .c .o all: libuu.a clean: rm -f [Xx]deview gif2gfp rm -f *.o *.a *.so core *~ TAGS distclean: clean rm -f config.status config.cache config.log Makefile config.h rm -f uudeview-*tar* uudeview-sfx realclean: distclean new: clean rm -f libuu.a $(MAKE) all libuu.a: $(UULIB_OBJ) rm -f $@ ar r $@ $(UULIB_OBJ) -$(RANLIB) $@ .c.o: $(CC) -c $(CFLAGS) $(VDEF) $< uuencode.o: uuencode.c uudeview.h uuint.h uustring.h fptools.h config.h uulib.o: uulib.c uudeview.h uuint.h uustring.h fptools.h config.h safealloc.c uunconc.o: uunconc.c uudeview.h uuint.h uustring.h fptools.h config.h uucheck.o: uucheck.c uudeview.h uuint.h uustring.h fptools.h config.h uuutil.o: uuutil.c uudeview.h uuint.h uustring.h fptools.h config.h uuscan.o: uuutil.c uudeview.h uuint.h uustring.h fptools.h config.h uustring.o: uustring.c uudeview.h uuint.h uustring.h config.h fptools.o: fptools.c fptools.h config.h uustring.h: uustring.c awk -f uustring.awk < uustring.c > uustring.h Convert-UUlib-1.5/uulib/crc32.h0000644000000000000000000000156511244412457014733 0ustar rootroot#ifndef __CRC32_H__ #define __CRC32_H__ #ifndef _ANSI_ARGS_ #ifdef PROTOTYPES #define _ANSI_ARGS_(c) c #else #define _ANSI_ARGS_(c) () #endif #endif #ifdef __cplusplus extern "C" { #endif typedef unsigned int crc32_t; #define Z_NULL 0 #define crc32 uulib_crc32 crc32_t crc32 _ANSI_ARGS_((crc32_t crc, const unsigned char *buf, unsigned int len)); /* Update a running crc with the bytes buf[0..len-1] and return the updated crc. If buf is NULL, this function returns the required initial value for the crc. Pre- and post-conditioning (one's complement) is performed within this function so it shouldn't be done by the application. Usage example: uLong crc = crc32(0L, Z_NULL, 0); while (read_buffer(buffer, length) != EOF) { crc = crc32(crc, buffer, length); } if (crc != original_crc) error(); */ #ifdef __cplusplus } #endif #endif Convert-UUlib-1.5/uulib/acconfig.h0000644000000000000000000000270110211640773015556 0ustar rootroot /* * needed for auto configuration * $Id$ */ /* * If your system is kinda special */ #undef SYSTEM_DOS #undef SYSTEM_QUICKWIN #undef SYSTEM_WINDLL #undef SYSTEM_OS2 /* * If your system has stdin/stdout/stderr */ #undef HAVE_STDIO /* * how to declare functions that are exported from the UU library */ #undef UUEXPORT /* * how to declare functions that are exported from the fptools library */ #undef TOOLEXPORT /* * define if your compiler supports function prototypes */ #undef PROTOTYPES /* * define if your system has chmod(2) */ #undef HAVE_CHMOD /* * define if your system has umask(2) */ #undef HAVE_UMASK /* * define if your system has mkstemp */ #undef HAVE_MKSTEMP /* * Replacement functions. * #define strerror _FP_strerror * #define tempnam _FP_tempnam * if you don't have these functions */ #undef strerror #undef tempnam /* * your mailing program. full path and the necessary parameters. * the recepient address is added to the command line (with a leading * space) without any further options */ #undef PROG_MAILER /* * define if the mailer needs to have the subject set on the command * line with -s "Subject". Preferredly, we send the subject as a header. */ #undef MAILER_NEEDS_SUBJECT /* * define if posting is enabled. Do not edit. */ #undef HAVE_NEWS /* * your local news posting program. full path and parameters, so that * the article and all its headers are read from stdin */ #undef PROG_INEWS Convert-UUlib-1.5/uulib/uuencode.c0000644000000000000000000013367611244415717015634 0ustar rootroot/* * This file is part of uudeview, the simple and friendly multi-part multi- * 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 * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #ifdef SYSTEM_WINDLL #include #endif #ifdef SYSTEM_OS2 #include #endif #include #include #include #include #include #ifdef STDC_HEADERS #include #include #endif #ifdef HAVE_UNISTD_H #include #endif #ifdef HAVE_ERRNO_H #include #endif #include #include #include #include #include /* for braindead systems */ #ifndef SEEK_SET #ifdef L_BEGIN #define SEEK_SET L_BEGIN #else #define SEEK_SET 0 #endif #endif char * uuencode_id = "$Id$"; #if 0 /* * the End-Of-Line string. MIME enforces CRLF, so that's what we use. Some * implementations of uudecode will complain about a missing end line, since * they look for "end^J" but find "end^J^M". We don't care - especially be- * cause they still decode the file properly despite this complaint. */ #ifndef EOLSTRING #define EOLSTRING "\015\012" #endif #else /* * Argh. Some delivery software (inews) has problems with the CRLF * line termination. Let's try native EOL and see if we run into * any problems. * This involves opening output files in text mode instead of binary */ #ifndef EOLSTRING #define EOLSTRING "\n" #endif #endif /* * ========================================================================= * User-configurable settings end here. Don't spy below unless you know what * you're doing. * ========================================================================= */ /* * Define End-Of-Line sequence */ #ifdef EOLSTRING static unsigned char *eolstring = (unsigned char *) EOLSTRING; #else static unsigned char *eolstring = (unsigned char *) "\012"; #endif /* * Content-Transfer-Encoding types for non-MIME encodings */ #define CTE_UUENC "x-uuencode" #define CTE_XXENC "x-xxencode" #define CTE_BINHEX "x-binhex" #define CTE_YENC "x-yenc" #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 : \ ((y)==YENC_ENCODED) ? CTE_YENC : "x-oops") /* * encoding tables */ unsigned char UUEncodeTable[64] = { '`', '!', '"', '#', '$', '%', '&', '\'', '(', ')', '*', '+', ',', '-', '.', '/', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', ':', ';', '<', '=', '>', '?', '@', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '[', '\\',']', '^', '_' }; unsigned char B64EncodeTable[64] = { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/' }; unsigned char XXEncodeTable[64] = { '+', '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z' }; unsigned char BHEncodeTable[64] = { '!', '"', '#', '$', '%', '&', '\'', '(', ')', '*', '+', ',', '-', '0', '1', '2', '3', '4', '5', '6', '8', '9', '@', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'P', 'Q', 'R', '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; char *mimetype; } mimemap; /* * This table maps a file's extension into a Content-Type. The current * official list can be downloaded as * ftp://ftp.isi.edu/in-notes/iana/assignments/media-type * I haven't listed any text types since it doesn't make sense to encode * them. Everything not on the list gets mapped to application/octet-stream */ static mimemap mimetable[] = { { "gif", "image/gif" }, /* Grafics Interchange Format */ { "jpg", "image/jpeg" }, /* JFIF encoded files */ { "jpeg", "image/jpeg" }, { "tif", "image/tiff" }, /* Tag Image File Format */ { "tiff", "image/tiff" }, { "cgm", "image/cgm" }, /* Computer Graphics Metafile */ { "au", "audio/basic" }, /* 8kHz ulaw audio data */ { "mov", "video/quicktime" }, /* Apple Quicktime */ { "qt", "video/quicktime" }, /* Also infrequently used */ { "mpeg", "video/mpeg" }, /* Motion Picture Expert Group */ { "mpg", "video/mpeg" }, { "mp2", "video/mpeg" }, /* dito, MPEG-2 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 */ { NULL, NULL } }; /* * the order of the following two tables must match the * Encoding Types definition in uudeview.h */ /* * encoded bytes per line */ static int bpl[8] = { 0, 45, 57, 45, 45, 0, 0, 128 }; /* * tables */ static unsigned char *etables[5] = { NULL, UUEncodeTable, B64EncodeTable, XXEncodeTable, BHEncodeTable }; /* * variables to malloc upon initialization */ char *uuestr_itemp; char *uuestr_otemp; /* * Encode one part of the data stream */ static int UUEncodeStream (FILE *outfile, FILE *infile, int encoding, long linperfile, crc32_t *crc, crc32_t *pcrc) { uchar *itemp = (uchar *) uuestr_itemp; uchar *otemp = (uchar *) uuestr_otemp; unsigned char *optr, *table, *tptr; int index, count; long line=0; size_t llen; if (outfile==NULL || infile==NULL || (encoding!=UU_ENCODED&&encoding!=XX_ENCODED&&encoding!=B64ENCODED&& encoding!=PT_ENCODED&&encoding!=QP_ENCODED&&encoding!=YENC_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 (itemp, 255, infile) == NULL) { break; } itemp[255] = '\0'; count = strlen (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 ((char *) 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 ((char *) 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 ((char *) 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 ((char *) eolstring, 1, strlen(eolstring), outfile) != strlen (eolstring)) { return UURET_IOERR; } optr = otemp; llen = 0; } } } line++; } return UURET_OK; } /* * Special handling for yEnc */ if (encoding == YENC_ENCODED) { llen = 0; optr = otemp; while (!feof (infile) && (linperfile <= 0 || line < linperfile)) { if ((count = fread (itemp, 1, 128, infile)) != 128) { if (count == 0) { break; } else if (ferror (infile)) { return UURET_IOERR; } } if (pcrc) *pcrc = crc32(*pcrc, itemp, count); if (crc) *crc = crc32(*crc, itemp, count); line++; /* * Busy Callback */ if (UUBUSYPOLL(ftell(infile)-progress.foffset,progress.fsize)) { UUMessage (uuencode_id, __LINE__, UUMSG_NOTE, uustring (S_ENCODE_CANCEL)); return UURET_CANCEL; } for (index=0; index 127) { if (fwrite (otemp, 1, llen, outfile) != llen || fwrite ((char *) eolstring, 1, strlen(eolstring), outfile) != strlen (eolstring)) { return UURET_IOERR; } llen = 0; optr = otemp; } switch ((char) ((int) itemp[index] + 42)) { case '\0': case '\t': case '\n': case '\r': case '=': case '\033': *optr++ = '='; *optr++ = (char) ((int) itemp[index] + 42 + 64); llen += 2; break; case '.': if (llen == 0) { *optr++ = '='; *optr++ = (char) ((int) itemp[index] + 42 + 64); llen += 2; } else { *optr++ = (char) ((int) itemp[index] + 42); llen++; } break; default: *optr++ = (char) ((int) itemp[index] + 42); llen++; break; } } } /* * write last line */ if (llen) { if (fwrite (otemp, 1, llen, outfile) != llen || fwrite ((char *) eolstring, 1, strlen(eolstring), outfile) != strlen (eolstring)) { return UURET_IOERR; } } return UURET_OK; } /* * Handling for binary encodings */ /* * select charset */ table = etables[encoding]; if (table==NULL || bpl[encoding]==0) { UUMessage (uuencode_id, __LINE__, UUMSG_ERROR, uustring (S_PARM_CHECK), "UUEncodeStream()"); return UURET_ILLVAL; } while (!feof (infile) && (linperfile <= 0 || line < linperfile)) { if ((count = fread (itemp, 1, bpl[encoding], infile)) != bpl[encoding]) { if (count == 0) break; else if (ferror (infile)) return UURET_IOERR; } optr = otemp; llen = 0; /* * Busy Callback */ if (UUBUSYPOLL(ftell(infile)-progress.foffset,progress.fsize)) { UUMessage (uuencode_id, __LINE__, UUMSG_NOTE, uustring (S_ENCODE_CANCEL)); return UURET_CANCEL; } /* * for UU and XX, encode the number of bytes as first character */ if (encoding == UU_ENCODED || encoding == XX_ENCODED) { *optr++ = table[count]; llen++; } /* * Main encoding */ 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 (encoding == UU_ENCODED || encoding == XX_ENCODED) { 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; while (*tptr) *optr++ = *tptr++; *optr++ = '\0'; llen += strlen ((char *) eolstring); if (fwrite (otemp, 1, llen, outfile) != llen) return UURET_IOERR; line++; } return UURET_OK; } /* * Encode as MIME multipart/mixed sub-message. */ int UUEXPORT UUEncodeMulti (FILE *outfile, FILE *infile, char *infname, int encoding, char *outfname, char *mimetype, int filemode) { mimemap *miter=mimetable; struct stat finfo; int res, themode; FILE *theifile; char *ptr; crc32_t crc; crc32_t *crcptr=NULL; if (outfile==NULL || (infile == NULL && infname==NULL) || (outfname==NULL && infname==NULL) || (encoding!=UU_ENCODED&&encoding!=XX_ENCODED&&encoding!=B64ENCODED&& encoding!=PT_ENCODED&&encoding!=QP_ENCODED&&encoding!=YENC_ENCODED)) { UUMessage (uuencode_id, __LINE__, UUMSG_ERROR, uustring (S_PARM_CHECK), "UUEncodeMulti()"); return UURET_ILLVAL; } progress.action = 0; if (infile==NULL) { if (stat (infname, &finfo) == -1) { UUMessage (uuencode_id, __LINE__, UUMSG_ERROR, uustring (S_NOT_STAT_FILE), infname, strerror (uu_errno=errno)); return UURET_IOERR; } if ((theifile = fopen (infname, "rb")) == NULL) { UUMessage (uuencode_id, __LINE__, UUMSG_ERROR, uustring (S_NOT_OPEN_FILE), infname, strerror (uu_errno=errno)); return UURET_IOERR; } themode = (filemode) ? filemode : ((int) finfo.st_mode & 0777); progress.fsize = (long) finfo.st_size; } else { if (fstat (fileno (infile), &finfo) != 0) { themode = (filemode)?filemode:0644; progress.fsize = -1; } else { themode = (int) finfo.st_mode & 0777; progress.fsize = (long) finfo.st_size; } theifile = infile; } if (progress.fsize < 0) progress.fsize = -1; _FP_strncpy (progress.curfile, (outfname)?outfname:infname, 256); progress.partno = 1; progress.numparts = 1; progress.percent = 0; progress.foffset = 0; progress.action = UUACT_ENCODING; /* * If not given from outside, select an appropriate Content-Type by * looking at the file's extension. If it is unknown, default to * Application/Octet-Stream */ if (mimetype == NULL) { if ((ptr = _FP_strrchr ((outfname)?outfname:infname, '.'))) { while (miter->extension && _FP_stricmp (ptr+1, miter->extension) != 0) miter++; mimetype = miter->mimetype; } } if (mimetype == NULL && (encoding == PT_ENCODED || encoding == QP_ENCODED)) { mimetype = "text/plain"; } /* * print sub-header */ if (encoding != YENC_ENCODED) { fprintf (outfile, "Content-Type: %s%s", (mimetype)?mimetype:"Application/Octet-Stream", eolstring); fprintf (outfile, "Content-Transfer-Encoding: %s%s", CTE_TYPE(encoding), eolstring); fprintf (outfile, "Content-Disposition: attachment; filename=\"%s\"%s", UUFNameFilter ((outfname)?outfname:infname), eolstring); fprintf (outfile, "%s", eolstring); } if (encoding == UU_ENCODED || encoding == XX_ENCODED) { fprintf (outfile, "begin %o %s%s", (themode) ? themode : 0644, UUFNameFilter ((outfname)?outfname:infname), eolstring); } else if (encoding == YENC_ENCODED) { crc = crc32(0L, Z_NULL, 0); crcptr = &crc; if (progress.fsize == -1) { fprintf (outfile, "=ybegin line=128 name=%s%s", UUFNameFilter ((outfname)?outfname:infname), eolstring); } else { fprintf (outfile, "=ybegin line=128 size=%ld name=%s%s", progress.fsize, UUFNameFilter ((outfname)?outfname:infname), eolstring); } } if ((res = UUEncodeStream (outfile, theifile, encoding, 0, crcptr, NULL)) != UURET_OK) { if (res != UURET_CANCEL) { UUMessage (uuencode_id, __LINE__, UUMSG_ERROR, uustring (S_ERR_ENCODING), UUFNameFilter ((infname)?infname:outfname), (res==UURET_IOERR)?strerror(uu_errno):UUstrerror(res)); } progress.action = 0; return res; } if (encoding == UU_ENCODED || encoding == XX_ENCODED) { fprintf (outfile, "%c%s", (encoding==UU_ENCODED) ? UUEncodeTable[0] : XXEncodeTable[0], eolstring); fprintf (outfile, "end%s", eolstring); } else if (encoding == YENC_ENCODED) { if (progress.fsize == -1) { fprintf (outfile, "=yend crc32=%08lx%s", crc, eolstring); } else { fprintf (outfile, "=yend size=%ld crc32=%08lx%s", progress.fsize, crc, eolstring); } } /* * empty line at end does no harm */ fprintf (outfile, "%s", eolstring); if (infile==NULL) fclose (theifile); progress.action = 0; return UURET_OK; } /* * Encode as MIME message/partial */ int UUEXPORT UUEncodePartial (FILE *outfile, FILE *infile, char *infname, int encoding, char *outfname, char *mimetype, int filemode, int partno, long linperfile, crc32_t *crcptr) { mimemap *miter=mimetable; static FILE *theifile; int themode, numparts; struct stat finfo; long thesize; char *ptr; int res; crc32_t pcrc; crc32_t *pcrcptr=NULL; if ((outfname==NULL&&infname==NULL) || partno<=0 || (infile == NULL&&infname==NULL) || outfile==NULL || (encoding!=UU_ENCODED&&encoding!=XX_ENCODED&&encoding!=B64ENCODED&& encoding!=PT_ENCODED&&encoding!=QP_ENCODED&&encoding!=YENC_ENCODED)) { UUMessage (uuencode_id, __LINE__, UUMSG_ERROR, uustring (S_PARM_CHECK), "UUEncodePartial()"); return UURET_ILLVAL; } /* * The first part needs a set of headers */ progress.action = 0; if (partno == 1) { if (infile==NULL) { if (stat (infname, &finfo) == -1) { UUMessage (uuencode_id, __LINE__, UUMSG_ERROR, uustring (S_NOT_STAT_FILE), infname, strerror (uu_errno=errno)); return UURET_IOERR; } if ((theifile = fopen (infname, "rb")) == NULL) { UUMessage (uuencode_id, __LINE__, UUMSG_ERROR, uustring (S_NOT_OPEN_FILE), infname, strerror (uu_errno=errno)); return UURET_IOERR; } if (linperfile <= 0) numparts = 1; else numparts = (int) (((long)finfo.st_size+(linperfile*bpl[encoding]-1))/ (linperfile*bpl[encoding])); themode = (filemode) ? filemode : ((int) finfo.st_mode & 0777); thesize = (long) finfo.st_size; } else { if (fstat (fileno (infile), &finfo) != 0) { UUMessage (uuencode_id, __LINE__, UUMSG_WARNING, uustring (S_STAT_ONE_PART)); numparts = 1; themode = (filemode)?filemode:0644; thesize = -1; } else { if (linperfile <= 0) numparts = 1; else numparts = (int) (((long)finfo.st_size+(linperfile*bpl[encoding]-1))/ (linperfile*bpl[encoding])); themode = (int) finfo.st_mode & 0777; thesize = (long) finfo.st_size; } theifile = infile; } _FP_strncpy (progress.curfile, (outfname)?outfname:infname, 256); progress.totsize = (thesize>=0) ? thesize : -1; progress.partno = 1; progress.numparts = numparts; progress.percent = 0; progress.foffset = 0; /* * If not given from outside, select an appropriate Content-Type by * looking at the file's extension. If it is unknown, default to * Application/Octet-Stream */ if (mimetype == NULL) { if ((ptr = _FP_strrchr ((outfname)?outfname:infname, '.'))) { while (miter->extension && _FP_stricmp (ptr+1, miter->extension) != 0) miter++; mimetype = miter->mimetype; } } if (mimetype == NULL && (encoding==PT_ENCODED || encoding==QP_ENCODED)) { mimetype = "text/plain"; } /* * print sub-header */ if (encoding != YENC_ENCODED) { fprintf (outfile, "MIME-Version: 1.0%s", eolstring); fprintf (outfile, "Content-Type: %s%s", (mimetype)?mimetype:"Application/Octet-Stream", eolstring); fprintf (outfile, "Content-Transfer-Encoding: %s%s", CTE_TYPE(encoding), eolstring); fprintf (outfile, "Content-Disposition: attachment; filename=\"%s\"%s", UUFNameFilter ((outfname)?outfname:infname), eolstring); } fprintf (outfile, "%s", eolstring); /* * for the first part of UU or XX messages, print a begin line */ if (encoding == UU_ENCODED || encoding == XX_ENCODED) { fprintf (outfile, "begin %o %s%s", (themode) ? themode : ((filemode)?filemode:0644), UUFNameFilter ((outfname)?outfname:infname), eolstring); } } if (encoding == YENC_ENCODED) { pcrc = crc32(0L, Z_NULL, 0); pcrcptr = &pcrc; if (numparts != 1) { if (progress.totsize == -1) { fprintf (outfile, "=ybegin part=%d line=128 name=%s%s", partno, UUFNameFilter ((outfname)?outfname:infname), eolstring); } else { fprintf (outfile, "=ybegin part=%d line=128 size=%ld name=%s%s", partno, progress.totsize, UUFNameFilter ((outfname)?outfname:infname), eolstring); } fprintf (outfile, "=ypart begin=%ld end=%ld%s", (partno - 1) * linperfile * 128 + 1, (partno * linperfile * 128) < progress.totsize ? partno * linperfile * 128 : progress.totsize, eolstring); } else { if (progress.totsize == -1) { fprintf (outfile, "=ybegin line=128 name=%s%s", UUFNameFilter ((outfname)?outfname:infname), eolstring); } else { fprintf (outfile, "=ybegin line=128 size=%ld name=%s%s", progress.totsize, UUFNameFilter ((outfname)?outfname:infname), eolstring); } } } /* * update progress information */ progress.partno = partno; progress.percent = 0; progress.foffset = ftell (theifile); if (progress.totsize <= 0) progress.fsize = -1; else if (linperfile <= 0) progress.fsize = progress.totsize; else if (progress.foffset+linperfile*bpl[encoding] > progress.totsize) progress.fsize = progress.totsize - progress.foffset; else progress.fsize = linperfile*bpl[encoding]; progress.action = UUACT_ENCODING; if ((res = UUEncodeStream (outfile, theifile, encoding, linperfile, crcptr, pcrcptr)) != UURET_OK) { if (infile==NULL) fclose (theifile); if (res != UURET_CANCEL) { UUMessage (uuencode_id, __LINE__, UUMSG_ERROR, uustring (S_ERR_ENCODING), UUFNameFilter ((outfname)?outfname:infname), (res==UURET_IOERR)?strerror(uu_errno):UUstrerror (res)); } progress.action = 0; return res; } /* * print end line */ if (feof (theifile) && (encoding == UU_ENCODED || encoding == XX_ENCODED)) { fprintf (outfile, "%c%s", (encoding==UU_ENCODED) ? UUEncodeTable[0] : XXEncodeTable[0], eolstring); fprintf (outfile, "end%s", eolstring); } else if (encoding == YENC_ENCODED) { if (numparts != 1) { fprintf (outfile, "=yend size=%ld part=%d pcrc32=%08lx", (partno * linperfile * 128) < progress.totsize ? linperfile * 128 : (progress.totsize - (partno - 1) * linperfile * 128), partno, pcrc); } else { fprintf (outfile, "=yend size=%ld", progress.totsize); } if (feof (theifile)) fprintf (outfile, " crc32=%08lx", *crcptr); fprintf (outfile, "%s", eolstring); } /* * empty line at end does no harm */ if (encoding != PT_ENCODED && encoding != QP_ENCODED) { fprintf (outfile, "%s", eolstring); } if (infile==NULL) { if (res != UURET_OK) { progress.action = 0; fclose (theifile); return res; } if (feof (theifile)) { progress.action = 0; fclose (theifile); return UURET_OK; } return UURET_CONT; } /* * leave progress.action as-is */ return UURET_OK; } /* * send output to a stream, don't do any headers at all */ int UUEXPORT UUEncodeToStream (FILE *outfile, FILE *infile, char *infname, int encoding, char *outfname, int filemode) { struct stat finfo; FILE *theifile; int themode; int res; crc32_t crc; crc32_t *crcptr=NULL; if (outfile==NULL || (infile == NULL&&infname==NULL) || (outfname==NULL&&infname==NULL) || (encoding!=UU_ENCODED&&encoding!=XX_ENCODED&&encoding!=B64ENCODED&& encoding!=PT_ENCODED&&encoding!=QP_ENCODED&&encoding!=YENC_ENCODED)) { UUMessage (uuencode_id, __LINE__, UUMSG_ERROR, uustring (S_PARM_CHECK), "UUEncodeToStream()"); return UURET_ILLVAL; } progress.action = 0; if (infile==NULL) { if (stat (infname, &finfo) == -1) { UUMessage (uuencode_id, __LINE__, UUMSG_ERROR, uustring (S_NOT_STAT_FILE), infname, strerror (uu_errno=errno)); return UURET_IOERR; } if ((theifile = fopen (infname, "rb")) == NULL) { UUMessage (uuencode_id, __LINE__, UUMSG_ERROR, uustring (S_NOT_OPEN_FILE), infname, strerror (uu_errno=errno)); return UURET_IOERR; } themode = (filemode) ? filemode : ((int) finfo.st_mode & 0777); progress.fsize = (long) finfo.st_size; } else { if (fstat (fileno (infile), &finfo) == -1) { /* gotta live with it */ themode = 0644; progress.fsize = -1; } else { themode = (filemode) ? filemode : ((int) finfo.st_mode & 0777); progress.fsize = (long) finfo.st_size; } theifile = infile; } if (progress.fsize < 0) progress.fsize = -1; _FP_strncpy (progress.curfile, (outfname)?outfname:infname, 256); progress.partno = 1; progress.numparts = 1; progress.percent = 0; progress.foffset = 0; progress.action = UUACT_ENCODING; if (encoding == UU_ENCODED || encoding == XX_ENCODED) { fprintf (outfile, "begin %o %s%s", (themode) ? themode : 0644, UUFNameFilter ((outfname)?outfname:infname), eolstring); } else if (encoding == YENC_ENCODED) { crc = crc32(0L, Z_NULL, 0); crcptr = &crc; if (progress.fsize == -1) { fprintf (outfile, "=ybegin line=128 name=%s%s", UUFNameFilter ((outfname)?outfname:infname), eolstring); } else { fprintf (outfile, "=ybegin line=128 size=%ld name=%s%s", progress.fsize, UUFNameFilter ((outfname)?outfname:infname), eolstring); } } if ((res = UUEncodeStream (outfile, theifile, encoding, 0, crcptr, NULL)) != UURET_OK) { if (res != UURET_CANCEL) { UUMessage (uuencode_id, __LINE__, UUMSG_ERROR, uustring (S_ERR_ENCODING), UUFNameFilter ((infname)?infname:outfname), (res==UURET_IOERR)?strerror(uu_errno):UUstrerror (res)); } progress.action = 0; return res; } if (encoding == UU_ENCODED || encoding == XX_ENCODED) { fprintf (outfile, "%c%s", (encoding==UU_ENCODED) ? UUEncodeTable[0] : XXEncodeTable[0], eolstring); fprintf (outfile, "end%s", eolstring); } else if (encoding == YENC_ENCODED) { if (progress.fsize == -1) { fprintf (outfile, "=yend crc32=%08lx%s", crc, eolstring); } else { fprintf (outfile, "=yend size=%ld crc32=%08lx%s", progress.fsize, crc, eolstring); } } /* * empty line at end does no harm */ fprintf (outfile, "%s", eolstring); if (infile==NULL) fclose (theifile); progress.action = 0; return UURET_OK; } /* * Encode to files on disk, don't generate any headers */ int UUEXPORT UUEncodeToFile (FILE *infile, char *infname, int encoding, char *outfname, char *diskname, long linperfile) { int part, numparts, len, filemode, res; char *oname=NULL, *optr, *ptr; FILE *theifile, *outfile; struct stat finfo; crc32_t pcrc, crc; crc32_t *pcrcptr=NULL, *crcptr=NULL; if ((diskname==NULL&&infname==NULL) || (outfname==NULL&&infname==NULL) || (infile==NULL&&infname==NULL) || (encoding!=UU_ENCODED&&encoding!=XX_ENCODED&&encoding!=B64ENCODED&& encoding!=PT_ENCODED&&encoding!=QP_ENCODED&&encoding!=YENC_ENCODED)) { UUMessage (uuencode_id, __LINE__, UUMSG_ERROR, uustring (S_PARM_CHECK), "UUEncodeToFile()"); return UURET_ILLVAL; } if (diskname) { if ((ptr = strchr (diskname, '/')) == NULL) ptr = strchr (diskname, '\\'); if (ptr) { len = strlen (diskname) + ((uuencodeext)?strlen(uuencodeext):3) + 5; if ((oname = malloc (len)) == NULL) { UUMessage (uuencode_id, __LINE__, UUMSG_ERROR, uustring (S_OUT_OF_MEMORY), len); return UURET_NOMEM; } sprintf (oname, "%s", diskname); } else { len = ((uusavepath)?strlen(uusavepath):0) + strlen (diskname) + ((uuencodeext)?strlen(uuencodeext):0) + 5; if ((oname = malloc (len)) == NULL) { UUMessage (uuencode_id, __LINE__, UUMSG_ERROR, uustring (S_OUT_OF_MEMORY), len); return UURET_NOMEM; } sprintf (oname, "%s%s", (uusavepath)?uusavepath:"", diskname); } } else { len = ((uusavepath) ? strlen (uusavepath) : 0) + strlen(UUFNameFilter(infname)) + ((uuencodeext)?strlen(uuencodeext):0) + 5; if ((oname = malloc (len)) == NULL) { UUMessage (uuencode_id, __LINE__, UUMSG_ERROR, uustring (S_OUT_OF_MEMORY), len); return UURET_NOMEM; } optr = UUFNameFilter (infname); sprintf (oname, "%s%s", (uusavepath)?uusavepath:"", (*optr=='.')?optr+1:optr); } /* * optr points after the last dot, so that we can print the part number * there. */ optr = _FP_strrchr (oname, '.'); if (optr==NULL || strchr (optr, '/')!=NULL || strchr (optr, '\\')!=NULL) { optr = oname + strlen (oname); *optr++ = '.'; } else if (optr==oname || *(optr-1)=='/' || *(optr-1)=='\\') { optr = oname + strlen (oname); *optr++ = '.'; } else optr++; progress.action = 0; if (infile==NULL) { if (stat (infname, &finfo) == -1) { UUMessage (uuencode_id, __LINE__, UUMSG_ERROR, uustring (S_NOT_STAT_FILE), infname, strerror (uu_errno=errno)); _FP_free (oname); return UURET_IOERR; } if ((theifile = fopen (infname, "rb")) == NULL) { UUMessage (uuencode_id, __LINE__, UUMSG_ERROR, uustring (S_NOT_OPEN_FILE), infname, strerror (uu_errno=errno)); _FP_free (oname); return UURET_IOERR; } if (linperfile <= 0) numparts = 1; else numparts = (int) (((long)finfo.st_size + (linperfile*bpl[encoding]-1)) / (linperfile*bpl[encoding])); filemode = (int) finfo.st_mode & 0777; progress.totsize = (long) finfo.st_size; } else { if (fstat (fileno (infile), &finfo) == -1) { /* gotta live with it */ filemode = 0644; numparts = -1; progress.totsize = -1; } else { if (linperfile <= 0) numparts = 1; else numparts = (int) (((long)finfo.st_size+(linperfile*bpl[encoding]-1))/ (linperfile*bpl[encoding])); filemode = (int) finfo.st_mode & 0777; progress.totsize = -1; } theifile = infile; } _FP_strncpy (progress.curfile, (outfname)?outfname:infname, 256); progress.totsize = (progress.totsize<0) ? -1 : progress.totsize; progress.numparts = numparts; for (part=1; !feof (theifile); part++) { /* * Attach extension */ if (progress.numparts==1 && progress.totsize!=-1 && uuencodeext!=NULL) strcpy (optr, uuencodeext); else sprintf (optr, "%03d", part); /* * check if target file exists */ if (!uu_overwrite) { if (stat (oname, &finfo) == 0) { UUMessage (uuencode_id, __LINE__, UUMSG_ERROR, uustring (S_TARGET_EXISTS), oname); if (infile==NULL) fclose (theifile); progress.action = 0; free (oname); return UURET_EXISTS; } } /* * update progress information */ progress.action = 0; progress.partno = part; progress.percent = 0; progress.foffset = ftell (theifile); if (progress.totsize == -1) progress.fsize = -1; else if (linperfile <= 0) progress.fsize = progress.totsize; else if (progress.foffset+linperfile*bpl[encoding] > progress.totsize) progress.fsize = progress.totsize - progress.foffset; else progress.fsize = linperfile*bpl[encoding]; progress.action = UUACT_ENCODING; if ((outfile = fopen (oname, "w")) == NULL) { UUMessage (uuencode_id, __LINE__, UUMSG_ERROR, uustring (S_NOT_OPEN_TARGET), oname, strerror (uu_errno = errno)); if (infile==NULL) fclose (theifile); progress.action = 0; free (oname); return UURET_IOERR; } if (encoding != YENC_ENCODED) { fprintf (outfile, "%s", eolstring); fprintf (outfile, "_=_ %s", eolstring); if (numparts == -1) fprintf (outfile, "_=_ Part %03d of file %s%s", part, UUFNameFilter ((outfname)?outfname:infname), eolstring); else fprintf (outfile, "_=_ Part %03d of %03d of file %s%s", part, numparts, UUFNameFilter ((outfname)?outfname:infname), eolstring); fprintf (outfile, "_=_ %s", eolstring); fprintf (outfile, "%s", eolstring); } if (part==1 && (encoding == UU_ENCODED || encoding == XX_ENCODED)) { fprintf (outfile, "begin %o %s%s", (filemode)?filemode : 0644, UUFNameFilter ((outfname)?outfname:infname), eolstring); } else if (encoding == YENC_ENCODED) { if (!crcptr) { crc = crc32(0L, Z_NULL, 0); crcptr = &crc; } pcrc = crc32(0L, Z_NULL, 0); pcrcptr = &pcrc; if (numparts != 1) { if (progress.totsize == -1) { fprintf (outfile, "=ybegin part=%d line=128 name=%s%s", part, UUFNameFilter ((outfname)?outfname:infname), eolstring); } else { fprintf (outfile, "=ybegin part=%d line=128 size=%ld name=%s%s", part, progress.totsize, UUFNameFilter ((outfname)?outfname:infname), eolstring); } fprintf (outfile, "=ypart begin=%ld end=%ld%s", (part-1)*linperfile*128+1, (part*linperfile*128) < progress.totsize ? (part*linperfile*128) : progress.totsize, eolstring); } else { if (progress.totsize == -1) { fprintf (outfile, "=ybegin line=128 name=%s%s", UUFNameFilter ((outfname)?outfname:infname), eolstring); } else { fprintf (outfile, "=ybegin line=128 size=%ld name=%s%s", progress.totsize, UUFNameFilter ((outfname)?outfname:infname), eolstring); } } } if ((res = UUEncodeStream (outfile, theifile, encoding, linperfile, crcptr, pcrcptr)) != UURET_OK) { if (res != UURET_CANCEL) { UUMessage (uuencode_id, __LINE__, UUMSG_ERROR, uustring (S_ERR_ENCODING), UUFNameFilter ((infname)?infname:outfname), (res==UURET_IOERR)?strerror(uu_errno):UUstrerror (res)); } if (infile==NULL) fclose (theifile); progress.action = 0; fclose (outfile); unlink (oname); _FP_free (oname); return res; } if (feof (theifile) && (encoding == UU_ENCODED || encoding == XX_ENCODED)) { fprintf (outfile, "%c%s", (encoding==UU_ENCODED) ? UUEncodeTable[0] : XXEncodeTable[0], eolstring); fprintf (outfile, "end%s", eolstring); } else if (encoding == YENC_ENCODED) { if (numparts != 1) { fprintf (outfile, "=yend size=%ld part=%d pcrc32=%08lx", (part*linperfile*128) < progress.totsize ? linperfile*128 : (progress.totsize-(part-1)*linperfile*128), part, pcrc); } else { fprintf (outfile, "=yend size=%ld", progress.totsize); } if (feof (theifile)) fprintf (outfile, " crc32=%08lx", crc); fprintf (outfile, "%s", eolstring); } /* * empty line at end does no harm */ fprintf (outfile, "%s", eolstring); fclose (outfile); } if (infile==NULL) fclose (theifile); progress.action = 0; _FP_free (oname); return UURET_OK; } /* * Encode a MIME Mail message or Newsgroup posting and send to a * stream. Still needs a somewhat smart MDA, since we only gene- * rate a minimum set of headers. */ int UUEXPORT UUE_PrepSingle (FILE *outfile, FILE *infile, char *infname, int encoding, 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; char *mimetype, *ptr; int res, len; if ((outfname==NULL&&infname==NULL) || (infile==NULL&&infname==NULL) || (encoding!=UU_ENCODED&&encoding!=XX_ENCODED&&encoding!=B64ENCODED&& encoding!=PT_ENCODED&&encoding!=QP_ENCODED&&encoding!=YENC_ENCODED)) { UUMessage (uuencode_id, __LINE__, UUMSG_ERROR, uustring (S_PARM_CHECK), "UUE_PrepSingle()"); return UURET_ILLVAL; } oname = UUFNameFilter ((outfname)?outfname:infname); len = ((subject)?strlen(subject):0) + strlen(oname) + 40; if ((ptr = _FP_strrchr (oname, '.'))) { while (miter->extension && _FP_stricmp (ptr+1, miter->extension) != 0) miter++; mimetype = miter->mimetype; } 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); return UURET_NOMEM; } if (encoding == YENC_ENCODED) { if (subject) sprintf (subline, "- %s - %s (001/001)", oname, subject); else sprintf (subline, "- %s - (001/001)", oname); } else { if (subject) sprintf (subline, "%s (001/001) - [ %s ]", subject, oname); else sprintf (subline, "[ %s ] (001/001)", oname); } 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); } if (encoding != YENC_ENCODED) { fprintf (outfile, "MIME-Version: 1.0%s", eolstring); fprintf (outfile, "Content-Type: %s; name=\"%s\"%s", (mimetype)?mimetype:"Application/Octet-Stream", UUFNameFilter ((outfname)?outfname:infname), eolstring); fprintf (outfile, "Content-Transfer-Encoding: %s%s", CTE_TYPE(encoding), eolstring); } fprintf (outfile, "%s", eolstring); res = UUEncodeToStream (outfile, infile, infname, encoding, outfname, filemode); _FP_free (subline); return res; } int UUEXPORT UUE_PrepPartial (FILE *outfile, FILE *infile, char *infname, int encoding, char *outfname, int filemode, 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]; static FILE *theifile; struct stat finfo; char *subline, *oname; long thesize; int res, len; static crc32_t crc; crc32_t *crcptr=NULL; if ((outfname==NULL&&infname==NULL) || (infile==NULL&&infname==NULL) || (encoding!=UU_ENCODED&&encoding!=XX_ENCODED&&encoding!=B64ENCODED&& encoding!=PT_ENCODED&&encoding!=QP_ENCODED&&encoding!=YENC_ENCODED)) { UUMessage (uuencode_id, __LINE__, UUMSG_ERROR, uustring (S_PARM_CHECK), "UUE_PrepPartial()"); return UURET_ILLVAL; } oname = UUFNameFilter ((outfname)?outfname:infname); len = ((subject)?strlen(subject):0) + strlen (oname) + 40; /* * if first part, get information about the file */ if (partno == 1) { if (infile==NULL) { if (stat (infname, &finfo) == -1) { UUMessage (uuencode_id, __LINE__, UUMSG_ERROR, uustring (S_NOT_STAT_FILE), infname, strerror (uu_errno=errno)); return UURET_IOERR; } if ((theifile = fopen (infname, "rb")) == NULL) { UUMessage (uuencode_id, __LINE__, UUMSG_ERROR, uustring (S_NOT_OPEN_FILE), infname, strerror (uu_errno=errno)); return UURET_IOERR; } if (linperfile <= 0) numparts = 1; else numparts = (int) (((long)finfo.st_size+(linperfile*bpl[encoding]-1))/ (linperfile*bpl[encoding])); themode = (filemode) ? filemode : ((int) finfo.st_mode & 0777); thesize = (long) finfo.st_size; } else { if (fstat (fileno (infile), &finfo) != 0) { if (filesize <= 0) { UUMessage (uuencode_id, __LINE__, UUMSG_WARNING, uustring (S_STAT_ONE_PART)); numparts = 1; themode = (filemode)?filemode:0644; thesize = -1; } else { if (linperfile <= 0) numparts = 1; else numparts = (int) ((filesize+(linperfile*bpl[encoding]-1))/ (linperfile*bpl[encoding])); themode = (filemode)?filemode:0644; thesize = filesize; } } else { if (linperfile <= 0) numparts = 1; else numparts = (int) (((long)finfo.st_size+(linperfile*bpl[encoding]-1))/ (linperfile*bpl[encoding])); filemode = (int) finfo.st_mode & 0777; thesize = (long) finfo.st_size; } theifile = infile; } /* * if there's one part only, don't use Message/Partial */ if (numparts == 1) { if (infile==NULL) fclose (theifile); return UUE_PrepSingleExt (outfile, infile, infname, encoding, outfname, filemode, destination, from, subject, replyto, isemail); } /* * we also need a unique ID */ sprintf (mimeid, "UUDV-%ld.%ld.%s", (long) time(NULL), thesize, (strlen(oname)>16)?"oops":oname); } if ((subline = (char *) malloc (len)) == NULL) { UUMessage (uuencode_id, __LINE__, UUMSG_ERROR, uustring (S_OUT_OF_MEMORY), len); if (infile==NULL) fclose (theifile); return UURET_NOMEM; } if (encoding == YENC_ENCODED) { if (partno == 1) crc = crc32(0L, Z_NULL, 0); crcptr = &crc; if (subject) sprintf (subline, "- %s - %s (%03d/%03d)", oname, subject, partno, numparts); else sprintf (subline, "- %s - (%03d/%03d)", oname, partno, numparts); } else { if (subject) sprintf (subline, "%s (%03d/%03d) - [ %s ]", subject, partno, numparts, oname); else sprintf (subline, "[ %s ] (%03d/%03d)", oname, partno, numparts); } 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); } if (encoding != YENC_ENCODED) { fprintf (outfile, "MIME-Version: 1.0%s", eolstring); fprintf (outfile, "Content-Type: Message/Partial; number=%d; total=%d;%s", partno, numparts, eolstring); fprintf (outfile, "\tid=\"%s\"%s", mimeid, eolstring); } fprintf (outfile, "%s", eolstring); res = UUEncodePartial (outfile, theifile, infname, encoding, (outfname)?outfname:infname, NULL, themode, partno, linperfile, crcptr); _FP_free (subline); if (infile==NULL) { if (res != UURET_OK) { fclose (theifile); return res; } if (feof (theifile)) { fclose (theifile); return UURET_OK; } return UURET_CONT; } return res; } Convert-UUlib-1.5/uulib/uuscan.c0000644000000000000000000025135112547576206015322 0ustar rootroot/* * This file is part of uudeview, the simple and friendly multi-part multi- * 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 * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. */ /* * These are very central functions of UUDeview. Here, we scan a file * and decide whether it contains encoded data or not. ScanPart() must * be called repeatedly on the same file until feof(file). Each time, * it returns information about the next part found within. */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #ifdef SYSTEM_WINDLL #include #endif #ifdef SYSTEM_OS2 #include #endif #include #include #ifdef STDC_HEADERS #include #include #endif #ifdef HAVE_MALLOC_H #include #endif #ifdef HAVE_UNISTD_H #include #endif #ifdef HAVE_MEMORY_H #include #endif #ifdef HAVE_ERRNO_H #include #endif #include #include #include #include char * uuscan_id = "$Id$"; /* * Header fields we recognize as such. See RFC822. We add "From ", * the usual marker for a beginning of a new message, and a couple * of usual MDA, News and MIME headers. * We make a distinction of MIME headers as we need the difference * to scan the bodies from partial multipart messages. */ #define LSTR(s) { sizeof (s) - 1, s } struct lstr { int len; const char *str; }; #define MAX_KNOWNHEADERLEN 28 /* max. length of a known header */ static struct lstr knownheaders[] = { /* "From " handled in IsKnownHeader */ /* knownmsgheaders */ LSTR ("Return-Path"), LSTR ("Received"), LSTR ("Reply-To"), LSTR ("From"), LSTR ("Sender"), LSTR ("Resent-Reply-To"), LSTR ("Resent-From"), LSTR ("Resent-Sender"), LSTR ("Date"), LSTR ("Resent-Date"), LSTR ("To"), LSTR ("Resent-To"), LSTR ("Cc"), LSTR ("Bcc"), LSTR ("Resent-bcc"), LSTR ("Message-ID"), LSTR ("Resent-Message-Id"), LSTR ("In-Reply-To"), LSTR ("References"), LSTR ("Keywords"), LSTR ("Subject"), LSTR ("Comments"), LSTR ("Delivery-Date"), LSTR ("Posted-Date"), LSTR ("Received-Date"), LSTR ("Precedence"), LSTR ("Path"), LSTR ("Newsgroups"), LSTR ("Organization"), LSTR ("Lines"), LSTR ("NNTP-Posting-Host"), /* knownminehaders */ LSTR ("Mime-Version"), LSTR ("Content-Transfer-Encoding"), LSTR ("Content-Type"), LSTR ("Content-Disposition"), LSTR ("Content-Description"), LSTR ("Content-Length") }; /* * for MIME (plaintext) parts without filename */ int mimseqno; /* * how many lines do we read when checking for headers */ #define WAITHEADER 10 /* * The stack for encapsulated Multipart messages */ #define MSMAXDEPTH 3 int mssdepth = 0; scanstate multistack[MSMAXDEPTH+1]; /* * The state and the local envelope */ headers localenv; scanstate sstate; /* * mallocable areas */ char *uuscan_shlline; char *uuscan_shlline2; char *uuscan_pvvalue; char *uuscan_phtext; char *uuscan_sdline; char *uuscan_sdbhds1; char *uuscan_sdbhds2; char *uuscan_spline; /* * Macro: print cancellation message in UUScanPart */ #define SPCANCEL() {UUMessage(uuscan_id,__LINE__,UUMSG_NOTE,uustring(S_SCAN_CANCEL));*errcode=UURET_CANCEL;goto ScanPartEmergency;} /* * Is line empty? A line is empty if it is composed of whitespace. */ static int IsLineEmpty (char *data) { if (data == NULL) return 0; while (*data && isspace (*data)) data++; return ((*data)?0:1); } /* * Is this a header line? A header line has alphanumeric characters * followed by a colon. */ static int IsHeaderLine (char *data) { if (data == NULL) return 0; if (*data == ':') return 0; while (*data && (isalnum (*data) || *data=='-')) data++; return (*data == ':') ? 1 : 0; } /* * Scans a potentially folded header line from the input file. If * initial is non-NULL, it is the first line of the header, useful * if the calling function just coincidentally noticed that this is * a header. * RFC0822 does not specify a maximum length for headers, but we * truncate everything beyond an insane value of 1024 characters. */ /* (schmorp)every later rfc says 998 octets max */ static char * ScanHeaderLine (FILE *datei, char *initial) { char *ptr=uuscan_shlline; char *ptr2, *p1, *p2, *p3; int llength, c; long curpos; if (initial) { _FP_strncpy (uuscan_shlline, initial, 1024); } else { /* read first line */ if (feof (datei) || ferror (datei)) return NULL; if (_FP_fgets (uuscan_shlline, 1024, datei) == NULL) return NULL; } llength = strlen (uuscan_shlline); /* strip whitespace at end */ ptr = uuscan_shlline + llength; while (llength && isspace(*(ptr-1))) { ptr--; llength--; } if (llength == 0) return uuscan_shlline; while (!feof (datei)) { c = _FP_fgetc (datei); if (c == EOF) break; if (c != ' ' && c != '\t') { ungetc (c, datei); break; } while (!feof (datei) && (c == ' ' || c == '\t')) c = _FP_fgetc (datei); if (!feof (datei)) ungetc (c, datei); /* push back for fgets() */ else break; /* read next line */ curpos = ftell (datei); if (_FP_fgets (uugen_inbuffer, 1024, datei) == NULL) break; if (IsLineEmpty (uugen_inbuffer)) { /* oops */ fseek (datei, curpos, SEEK_SET); break; } _FP_strncpy (ptr, uugen_inbuffer, 1024-llength); c = strlen (ptr); /* * strip whitespace */ ptr += c; llength += c; while (llength && isspace(*(ptr-1))) { ptr--; llength--; } } *ptr = '\0'; if (llength == 0) return NULL; /* * Now that we've read the header line, we can RFC 1522-decode it */ ptr = uuscan_shlline; ptr2 = uuscan_shlline2; while (*ptr) { /* * Look for =? magic */ if (*ptr == '=' && *(ptr+1) == '?') { /* * Let p1 point to the charset, look for next question mark */ p1 = p2 = ptr+2; while (*p2 && *p2 != '?') { p2++; } if (*p2 == '?' && (*(p2+1) == 'q' || *(p2+1) == 'Q' || *(p2+1) == 'b' || *(p2+1) == 'B') && *(p2+2) == '?') { /* * Let p2 point to the encoding, look for ?= magic */ p2++; p3=p2+2; while (*p3 && (*p3 != '?' || *(p3+1) != '=')) { p3++; } if (*p3 == '?' && *(p3+1) == '=') { /* * Alright, we've found an RFC 1522 header field */ if (*p2 == 'q' || *p2 == 'Q') { c = UUDecodeField (p2+2, ptr2, QP_ENCODED); } else if (*p2 == 'b' || *p2 == 'B') { c = UUDecodeField (p2+2, ptr2, B64ENCODED); } if (c >= 0) { ptr2 += c; ptr = p3+2; continue; } } } } *ptr2++ = *ptr++; } *ptr2 = 0; return uuscan_shlline2; } /* * Extract the value from a MIME attribute=value pair. This function * receives a pointer to the attribute. */ static char * ParseValue (char *attribute) { char *ptr=uuscan_pvvalue; int length=0; if (attribute == NULL) return NULL; while ((isalnum(*attribute) || *attribute=='_') && *attribute != '=') attribute++; while (isspace(*attribute)) attribute++; if (*attribute == '=') { attribute++; while (isspace (*attribute)) attribute++; } else return NULL; if (*attribute == '"') { /* quoted-string */ attribute++; while (*attribute && *attribute != '"' && length < 255) { if (*attribute == '\\' && (attribute[1] == '"' || attribute[1] == '\015' || attribute[1] == '\\')) /* we dequote only the three characters that MUST be quoted, since * microsoft is obviously unable to correctly implement even mime headers: * filename="c:\xxx". *sigh* */ *ptr++ = *++attribute; else *ptr++ = *attribute; attribute++; length++; } *ptr = '\0'; } else { /* tspecials from RFC1521 */ /* * Note - exclude '[', ']' and ';' on popular request; these are * used in some Content-Type fields by the Klez virus, and people * who feed their virus scanners with the output of UUDeview would * like to catch it! */ while (*attribute && !isspace (*attribute) && *attribute != '(' && *attribute != ')' && *attribute != '<' && *attribute != '>' && *attribute != '@' && *attribute != ',' && /* *attribute != ';' && */ *attribute != ':' && *attribute != '\\' &&*attribute != '"' && *attribute != '/' && /* *attribute != '[' && *attribute != ']' && */ *attribute != '?' && *attribute != '=' && length < 255) { *ptr++ = *attribute++; length++; } *ptr = '\0'; } return uuscan_pvvalue; } /* * Extract the information we need from header fields */ static headers * ParseHeader (headers *theheaders, char *line) { char **variable=NULL; char *value, *ptr, *thenew; int delimit, length; value = 0; delimit = 0; /* calm down gcc */ if (line == NULL) return theheaders; 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; variable = &theheaders->ctype; value = line+13; delimit = ';'; /* we can probably extract more information */ if ((ptr = _FP_stristr (line, "boundary")) != NULL) { if ((thenew = ParseValue (ptr))) { if (theheaders->boundary) free (theheaders->boundary); theheaders->boundary = _FP_strdup (thenew); } } if ((ptr = _FP_stristr (line, "name")) != NULL) { if ((thenew = ParseValue (ptr))) { if (theheaders->fname) free (theheaders->fname); theheaders->fname = _FP_strdup (thenew); } } if ((ptr = _FP_stristr (line, "id")) != NULL) { if ((thenew = ParseValue (ptr))) { if (theheaders->mimeid) free (theheaders->mimeid); theheaders->mimeid = _FP_strdup (thenew); } } if ((ptr = _FP_stristr (line, "number")) != NULL) { if ((thenew = ParseValue (ptr))) { theheaders->partno = atoi (thenew); } } if ((ptr = _FP_stristr (line, "total")) != NULL) { if ((thenew = ParseValue (ptr))) { theheaders->numparts = atoi (thenew); } } } else if (_FP_strnicmp (line, "Content-Transfer-Encoding:", 26) == 0) { if (theheaders->ctenc) return theheaders; variable = &theheaders->ctenc; value = line+26; delimit = ';'; } else if (_FP_strnicmp (line, "Content-Disposition:", 20) == 0) { /* * Some encoders mention the original filename as parameter to * Content-Type, others as parameter to Content-Disposition. We * do prefer the first solution, but accept this situation, too. * TODO: Read RFC1806 */ if ((ptr = _FP_stristr (line, "name")) != NULL) { if (theheaders->fname == NULL && (thenew=ParseValue(ptr)) != NULL) { theheaders->fname = _FP_strdup (thenew); } } variable = NULL; } else { /* * nothing interesting */ return theheaders; } /* * okay, so extract the actual data */ if (variable) { length = 0; ptr = uuscan_phtext; while (isspace (*value)) value++; while (*value && (delimit==0 || *value!=delimit) && *value && length < 255) { *ptr++ = *value++; length++; } while (length && isspace(*(ptr-1))) { ptr--; length--; } *ptr = '\0'; if ((*variable = _FP_strdup (uuscan_phtext)) == NULL) return NULL; } return theheaders; } /* * is this a header line we know about? */ static int IsKnownHeader (char *line) { const char *sep; int len, i; /* "From " handled specially */ /* we assume the buffer is at least 5 bytes long */ if (line [4] == ' ' && line [1] == 'r' && line [2] == 'o' && line [3] == 'm' && (line [0] == 'f' || line [0] == 'F')) return 1; sep = memchr (line, ':', MAX_KNOWNHEADERLEN); /* fast reject, the majority of calls are simple rejects */ if (!sep) return 0; len = sep - line; /* length of part before ':' */ for (i = 0; i < sizeof (knownheaders) / sizeof (knownheaders [0]); ++i) if (len == knownheaders [i].len && _FP_strnicmp (line, knownheaders [i].str, len) == 0) return 1; return 0; } /* * Scan a header */ int UUScanHeader (FILE *datei, headers *envelope) { char *ptr; while (!feof (datei)) { if ((ptr = ScanHeaderLine (datei, NULL)) == NULL) break; if (*ptr == '\0') break; ParseHeader (envelope, ptr); } return 0; } /* * Scan something for encoded data and fill the fileread* structure. * If boundary is non-NULL, we stop after having read it. If Check- * Headers != 0, we also stop after we've found uu_headercount recog- * nized header lines. * If we have a boundary, then we also don't accept Base64; MIME mails * really should handle this properly. * We return -1 if something went wrong, 0 if everything is normal, * 1 if we found a new header and 2 if we found a boundary. * In MIME message bodies (not multiparts), we also disable our reduced * MIME handling. */ static int ScanData (FILE *datei, char *fname, int *errcode, char *boundary, int ismime, int checkheaders, fileread *result) { char *line=uuscan_sdline, *bhds1=uuscan_sdbhds1, *bhds2=uuscan_sdbhds2; static char *ptr, *p2, *p3=NULL, *bhdsp, bhl; int islen[10], 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=0; int encoding=0, dflag=0, ctline=42; int dontcare=0, hadnl=0; long preheaders=0, oldposition; long yepartends=0; size_t dcc, bhopc; *errcode = UURET_OK; (void) UUDecodeLine (NULL, NULL, 0); /* init */ bhdsp = bhds2; if (datei == NULL || feof (datei)) return -1; result->startpos = ftell (datei); hcount = lcount = 0; for (iscnt=0; iscnt<10; iscnt++) { isb64[iscnt] = isuue[iscnt] = isxxe[iscnt] = isbhx[iscnt] = 0; islen[iscnt] = -1; } iscnt = 0; if (boundary) blen = strlen (boundary); while (!feof (datei)) { oldposition = ftell (datei); if (_FP_fgets (line, 1024, datei) == NULL) break; if (ferror (datei)) break; /* * Make Busy Polls */ if (UUBUSYPOLL(ftell(datei),progress.fsize)) { UUMessage (uuscan_id, __LINE__, UUMSG_NOTE, uustring (S_SCAN_CANCEL)); *errcode = UURET_CANCEL; break; } if (IsLineEmpty (line)) { /* line empty? */ hcount = 0; hadnl = 1; continue; /* then ignore */ } if (checkheaders) { if (IsKnownHeader (line)) { (void) ScanHeaderLine (datei, line); if (hcount == 0) { preheaders = oldposition; lcount = 0; } hcount++; lcount++; /* * check for the various restart counters */ if ((hcount >= hlcount.restart) || (hcount >= hlcount.afterdata && ismime == 0) || (hcount >= hlcount.afterdata && result->uudet) || (hcount >= hlcount.afternl && result->uudet && hadnl)) { /* * Hey, a new header starts here */ fseek (datei, preheaders, SEEK_SET); break; } /* continue; */ } else if (lcount > WAITHEADER) { hcount = 0; lcount = 0; dontcare=0; } else if (hcount) { lcount++; dontcare=1; } else { dontcare=0; } } else { dontcare=0; } if (boundary != NULL && line[0] == '-' && line[1] == '-' && strncmp (line+2, boundary, blen) == 0) { fseek (datei, oldposition, SEEK_SET); break; } if (boundary != NULL && line[0] == 'C' && line[1] == 'o' && _FP_strnicmp (line, "Content-Type:", 13) == 0) { ptr = ScanHeaderLine (datei, line); p2 = (ptr)?_FP_stristr(ptr,"boundary"):NULL; p3 = (p2)?ParseValue(p2):NULL; if (p3 && strcmp (p3, boundary) == 0) { fseek (datei, oldposition, SEEK_SET); break; } else { p3 = NULL; } } if (strncmp (line, "begin ", 6) == 0 || _FP_strnicmp (line, "
begin ", 11) == 0) {
      if ((result->begin || result->end ||
	   result->uudet == B64ENCODED ||
	   result->uudet == BH_ENCODED) && !uu_more_mime) {
	fseek (datei, oldposition, SEEK_SET);
	break;
      }
      
      if (*line == '<')
	ptr = line + 10;
      else
	ptr = line + 5;

      while (*ptr == ' ') ptr++;
      while (isdigit (*ptr)) 
	result->mode = result->mode * 8 + *ptr++ - '0';
      while (*ptr == ' ') ptr++;

      /*
       * We may have picked up a filename from a uuenview-style header
       */
      _FP_free (result->filename);
      result->filename = _FP_strdup (ptr);
      result->begin    = 1;

      while (isspace (result->filename[strlen(result->filename)-1]))
	result->filename[strlen(result->filename)-1] = '\0';

      continue;
    }

    if ((strncmp (line, "end", 3) == 0) &&
	result->uudet != BH_ENCODED &&
	result->uudet != YENC_ENCODED) {
      if (result->uudet == B64ENCODED && result->begin)
	result->uudet = XX_ENCODED;

      if (result->uudet != B64ENCODED) {
	result->end = 1;
	if (dflag && encoding)
	  result->uudet = encoding;
	continue;
      }
    }

    hadnl = 0;

    /*
     * Detect a UUDeview-Style header
     */

    if (_FP_strnicmp (line, "_=_ Part ", 9) == 0 &&
	result->uudet != YENC_ENCODED) {
      if (result->uudet) {
	fseek (datei, oldposition, SEEK_SET);
	break;
      }
      result->partno = atoi (line + 8);
      if ((ptr = _FP_stristr (line, "of file ")) != NULL) {
	ptr += 8;
	while (isspace (*ptr)) ptr++;
	p2 = ptr;
	while (isalnum(*p2) || 
	       *p2 == '.' || *p2=='_' || *p2 == '-' ||
	       *p2 == '!' || *p2=='@' || *p2 == '$')
	  p2++;
	c = *p2; *p2 = '\0';
	if (p2 != ptr && result->filename == NULL)
	  result->filename = _FP_strdup (ptr);
	else if (p2 - ptr > 5 && strchr (ptr, '.') != NULL) {
	  /*
	   * This file name looks good, too. Let's use it
	   */
	  _FP_free (result->filename);
	  result->filename = _FP_strdup (ptr);
	}
	*p2 = c;
      }
    }

    /*
     * 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 && !uu_more_mime &&
	result->uudet != YENC_ENCODED) {
      if (_FP_strnicmp (line, "Content-Type", 12) == 0 ||
	  _FP_strnicmp (line, "X-Orcl-Content-Type", 19) == 0) {
	/*
	 * We use Content-Type to mark a new attachment and split the file.
	 * However, we do not split if we haven't found anything encoded yet.
	 */
	if (result->uudet) {
	  fseek (datei, oldposition, SEEK_SET);
	  break;
	}
	if ((ptr = strchr (line, ':')) != NULL) {
	  ptr++;
	  while (isspace (*ptr)) ptr++; p2 = ptr;
	  while (!isspace (*p2) && *p2 != ';') p2++;
	  c = *p2; *p2 = '\0';
	  if (p2 != ptr) {
	    _FP_free (result->mimetype);
	    result->mimetype = _FP_strdup (ptr);
	  }
	  *p2 = c;
	}
	ctline=0;
	hadct=1;
      }
      if ((ptr = _FP_stristr (line, "number=")) && ctline<4) {
	ptr += 7; if (*ptr == '"') ptr++;
	result->partno = atoi (ptr);
      }
      if ((ptr = _FP_stristr (line, "total=")) && ctline<4) {
	ptr += 6; if (*ptr == '"') ptr++;
	result->maxpno = atoi (ptr);
      }
      if ((ptr = _FP_stristr (line, "name=")) && ctline<4) {
	ptr += 5;
	while (isspace (*ptr)) ptr++;
	if (*ptr == '"' && *(ptr+1) && (p2 = strchr (ptr+2, '"')) != NULL) {
	  c = *p2; *p2 = '\0';
	  _FP_free (result->filename);
	  result->filename = _FP_strdup (ptr+1);
	  *p2 = c;
	}
	else if (*ptr=='\''&&*(ptr+1)&&(p2 = strchr(ptr+2, '\'')) != NULL) {
	  c = *p2; *p2 = '\0';
	  _FP_free (result->filename);
	  result->filename = _FP_strdup (ptr+1);
	  *p2 = c;
	}
	else {
	  p2 = ptr;
	  while (isalnum(*p2) || 
		 *p2 == '.' || *p2=='_' || *p2 == '-' ||
		 *p2 == '!' || *p2=='@' || *p2 == '$')
	    p2++;
	  c = *p2; *p2 = '\0';
	  if (p2 != ptr && result->filename == NULL)
	    result->filename = _FP_strdup (ptr);
	  else if (p2 - ptr > 5 && strchr (ptr, '.') != NULL) {
	    /*
	     * This file name looks good, too. Let's use it
	     */
	    _FP_free (result->filename);
	    result->filename = _FP_strdup (ptr);
	  }
	  *p2 = c;
	}
      }
      if ((ptr = _FP_stristr (line, "id=")) && ctline<4) {
	p2 = ptr += 3;
	if (*p2 == '"') {
	  p2 = strchr (++ptr, '"');
	}
	else {
	  while (*p2 && isprint(*p2) && !isspace(*p2) && *p2 != ';')
	    p2++;
	}
	if (p2 && *p2 && p2!=ptr) {
	  c = *p2; *p2 = '\0';
	  if (result->mimeid)
	    _FP_free (result->mimeid);
	  result->mimeid = _FP_strdup (ptr);
	  *p2 = c;
	}
      }
      
      /* 
       * Handling for very short Base64 files.
       */
      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)) {
	      result->uudet = encoding;
	      encoding = dflag = 0;
	    }
	    haddh = 1;
	    continue;
	  }
	  hadct = 0;
	}
      }
    } /* 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]) &&
	_FP_strstr (line+2, "_=_") != NULL) {

      long oldposition = ftell (datei); /* refresh oldpositition so the comment below becomes true */
     
      if (_FP_fgets (line, 1024, 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;
      }
    }

    /*
     * Detection for yEnc encoding
     */

    if (strncmp (line, "=ybegin ", 8) == 0 &&
	_FP_strstr (line, " name=") != NULL) {
      if ((result->begin || result->end || result->uudet) && !uu_more_mime) {
	fseek (datei, oldposition, SEEK_SET);
	break;
      }

      /*
       * name continues to the end of the line
       */
      
      ptr = _FP_strstr (line, " name=") + 6;

      /* newsbin pro 5.0 (at least) is braindamaged enough to put (null) here */
      /* create something sensible, trust a windows program to fuck it up */
      if (strncmp (ptr, "(null)", 6))
        {
          _FP_free (result->filename);
          result->filename = _FP_strdup (ptr);

          while (isspace (result->filename[strlen(result->filename)-1]))
            result->filename[strlen(result->filename)-1] = '\0';
        }

      /*
       * Determine size
       */

      if ((ptr = _FP_strstr (line, " size=")) != NULL) {
	ptr += 6;
	result->yefilesize = atoi (ptr);
      }
      else {
	result->yefilesize = -1;
      }

      /*
       * check for multipart file and read =ypart line
       */

      if ((ptr = _FP_strstr (line, " part=")) != NULL) {
	result->partno = atoi (ptr + 6);

	if (result->partno == 1) {
	  result->begin = 1;
	}

        if ((ptr = _FP_strstr (line, " total=")))
	  result->maxpno = atoi (ptr + 7);

	if (_FP_fgets (line, 1024, datei) == NULL) {
	  break;
	}

	if (strncmp (line, "=ypart ", 7) != 0) {
	  break;
	}

	if ((ptr = _FP_strstr (line, " end=")) == NULL) {
	  break;
	}
       
	yepartends = atoi (ptr + 5);
      }
      else {
	result->partno = 1;
	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) {
        if (!result->maxpno || result->maxpno == result->partno)
          result->end = 1;
      } else if (yepartends >= result->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 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, 1024, datei) == NULL)
	      break;
	    if (ferror (datei))
	      break;

	    /*
	     * 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; dflagbegin) {
	  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) {
      *errcode = UURET_NOMEM;
      _FP_free (result);
      return NULL;
    }

    /* ignore empty lines at the beginning of a file */
    preheaders = ftell (datei);
    while (!feof (datei)) {
      if (UUBUSYPOLL(preheaders,progress.fsize)) SPCANCEL();
      if (_FP_fgets (line, 1024, datei) == NULL)
	break;
      if (!IsLineEmpty (line)) {
	fseek (datei, preheaders, SEEK_SET);
	break;
      }
      preheaders = ftell (datei);
    }
  }

  if (ferror(datei) || feof(datei)) {
    _FP_free (result);
    return NULL;
  }

  /*
   * If we are confident that this is a mail folder and are at the
   * beginning of the file, expecting to read some headers, scan
   * the envelope.
   */

  if (sstate.isfolder && sstate.mimestate == MS_HEADERS) {
    hcount = 0;
    lcount = 0;
    UUkillheaders (&sstate.envelope);

    /*
     * clean up leftovers from invalid messages
     */

    while (mssdepth) {
      mssdepth--;
      UUkillheaders (&(multistack[mssdepth].envelope));
      _FP_free (multistack[mssdepth].source);
    }

    prevpos = ftell (datei);
    if (_FP_fgets (line, 1024, datei) == NULL) {
      _FP_free (result);
      return NULL;
    }

    /*
     * 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]) {
      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++;
      if (UUBUSYPOLL(ftell(datei),progress.fsize)) SPCANCEL();
      if (IsHeaderLine (line)) {
	ptr1 = ScanHeaderLine (datei, line);
	if (ParseHeader (&sstate.envelope, ptr1) == NULL) {
	  *errcode = UURET_NOMEM;
	  _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) {
	fseek (datei, prevpos, SEEK_SET);
	line[0] = '\0';
	break;
      }

      if (_FP_fgets (line, 1024, datei) == NULL) {
        /* If we are at eof without finding headers, there probably isn't */
        if (hcount < hlcount.afternl)
          fseek (datei, prevpos, SEEK_SET);
        break;
      }
    }

    /* skip empty lines */
    prevpos = ftell (datei);
    if (IsLineEmpty (line)) {
      while (!feof (datei)) {
	if (_FP_fgets (line, 1024, datei) == NULL)
	  break;
	if (UUBUSYPOLL(ftell(datei),progress.fsize)) SPCANCEL();
	if (!IsLineEmpty (line)) {
	  fseek (datei, prevpos, SEEK_SET);
	  break;
	}
	prevpos = ftell (datei);
      }
    }

    /*
     * If we don't have all valid MIME headers yet, but the following
     * line is a MIME header, accept it anyway.
     */

    if (!uu_more_mime &&
	sstate.envelope.mimevers == NULL &&
	sstate.envelope.ctype    == NULL &&
	sstate.envelope.ctenc    == NULL &&
	IsKnownHeader (line)) {
      /*
       * see above
       */
      _FP_fgets (line, 1024, datei);

      while (!feof (datei) && !IsLineEmpty (line)) {
	if (IsKnownHeader (line))
	  hcount++;
	if (UUBUSYPOLL(ftell(datei),progress.fsize)) SPCANCEL();
	ptr1 = ScanHeaderLine (datei, line);
	if (ParseHeader (&sstate.envelope, ptr1) == NULL) {
	  *errcode = UURET_NOMEM;
	  _FP_free (result);
	  return NULL;
	}

	if (_FP_fgets (line, 1024, datei) == NULL)
	  break;
      }
      /* skip empty lines */
      prevpos = ftell (datei);
      while (!feof (datei)) {
	if (_FP_fgets (line, 1024, datei) == NULL)
	  break;
	if (UUBUSYPOLL(ftell(datei),progress.fsize)) SPCANCEL();
	if (!IsLineEmpty (line)) {
	  fseek (datei, prevpos, SEEK_SET);
	  break;
	}
	prevpos = ftell (datei);
      }
    }

    /*
     * A partial multipart message probably has only a Content-Type
     * header but nothing else. In this case, at least simulate a
     * MIME message
     * if mimevers is not set but there are other well-known MIME
     * headers, don't be too picky about it.
     */
    if (sstate.envelope.ctype && sstate.envelope.mimevers==NULL  &&
	_FP_stristr (sstate.envelope.ctype, "multipart") != NULL &&
	sstate.envelope.boundary != NULL) {
      sstate.envelope.mimevers = _FP_strdup ("1.0");
      hcount = hlcount.afternl;
    }
    else if (sstate.envelope.mimevers==NULL && sstate.envelope.ctype &&
	     sstate.envelope.fname && sstate.envelope.ctenc) {
      sstate.envelope.mimevers = _FP_strdup ("1.0");
      hcount = hlcount.afternl;
    }

    if (sstate.envelope.mimevers != NULL) {
      /* this is a MIME file. check the Content-Type */
      sstate.ismime = 1;
      if (_FP_stristr (sstate.envelope.ctype, "multipart") != NULL) {
	if (sstate.envelope.boundary == NULL) {
	  UUMessage (uuscan_id, __LINE__, UUMSG_WARNING,
		     uustring (S_MIME_NO_BOUNDARY));
	  sstate.mimestate = MS_BODY;
	  _FP_free (sstate.envelope.ctype);
	  sstate.envelope.ctype = _FP_strdup ("text/plain");
	}
	else {
	  sstate.mimestate = MS_PREAMBLE;
	}
      }
      else {
	sstate.mimestate = MS_BODY;	/* just a `simple' message */
      }
    }
    else {
      /* not a folder after all */
      fseek (datei, prevpos, SEEK_SET);
      sstate.isfolder = 0;
      sstate.ismime   = 0;
    }
  }

  if (feof (datei) || ferror (datei)) { /* oops */
    _FP_free (result);
    return NULL;
  }

  /*
   * Handle MIME stuff
   */

  /*
   * Read Preamble. This must be ended by a sstate.envelope.boundary line.
   * If uu_usepreamble is set, we produce a result from this one
   */

  if (sstate.ismime && sstate.mimestate == MS_PREAMBLE) {
    result->startpos = ftell (datei);	/* remember start of preamble */
    prevpos          = ftell (datei);
    preheaders       = ftell (datei);

    blen   = strlen (sstate.envelope.boundary);
    lcount = 0;
    
    while (!feof (datei)) {
      if (_FP_fgets (line, 1024, datei) == NULL)
	break;
      if (UUBUSYPOLL(ftell(datei),progress.fsize)) SPCANCEL();
      if (line[0] == '-' && line[1] == '-' &&
	  strncmp (line+2, sstate.envelope.boundary, blen) == 0)
	break;
      if (!IsLineEmpty (line))
	lcount++;

      prevpos = ftell (datei);
    }
    if (feof (datei) || ferror (datei)) {
      UUMessage (uuscan_id, __LINE__, UUMSG_WARNING,
		 uustring (S_MIME_B_NOT_FOUND));
      /*
       * restart and try again; don't restart if uu_fast_scanning
       */
      sstate.isfolder  = 0;
      sstate.ismime    = 0;
      sstate.mimestate = MS_BODY;

      if (!uu_fast_scanning) {
	*errcode = UURET_CONT;
	fseek (datei, preheaders, SEEK_SET);
      }
      _FP_free (result);
      return NULL;
    }
    if (line[0] == '-' && line[1] == '-' &&
	strncmp (line+2, sstate.envelope.boundary, blen) == 0) {
      ptr1 = line + 2 + blen;
      if (*ptr1 == '-' && *(ptr1+1) == '-') {
	/* Empty Multipart Message. Duh. */
	sstate.mimestate = MS_EPILOGUE;
      }
      else {
	sstate.mimestate = MS_SUBPART;
      }
    }
    else { /* shouldn't happen */
      UUMessage (uuscan_id, __LINE__, UUMSG_WARNING,
		 uustring (S_MIME_B_NOT_FOUND));
      /*
       * restart and try again; don't restart if uu_fast_scanning
       */
      sstate.isfolder  = 0;
      sstate.ismime    = 0;
      sstate.mimestate = MS_BODY;

      if (!uu_fast_scanning) {
	*errcode = UURET_CONT;
	fseek (datei, preheaders, SEEK_SET);
      }
      _FP_free (result);
      return NULL;
    }
    /* produce result if uu_usepreamble is set */
    if (uu_usepreamble && lcount) {
      sprintf (line, "%04d.txt", ++mimseqno);
      result->subject  = _FP_strdup (sstate.envelope.subject);
      result->filename = _FP_strdup (line);
      result->origin   = _FP_strdup (sstate.envelope.from);
      result->mimeid   = _FP_strdup (sstate.envelope.mimeid);
      result->mimetype = _FP_strdup ("text/plain");
      result->mode     = 0644;
      result->uudet    = PT_ENCODED;	/* plain text */
      result->sfname   = _FP_strdup (fname);
      result->flags    = FL_SINGLE | FL_PROPER;
      /* result->startpos set from above */
      result->length   = prevpos - result->startpos;
      result->partno   = 1;

      /* MIME message, let's continue */
      *errcode = UURET_CONT;

      if ((sstate.envelope.subject != NULL && result->subject == NULL) ||
	  result->filename == NULL || result->sfname == NULL) {
	*errcode = UURET_NOMEM;
      }

      return result;
    }
    /* MIME message, let's continue */
    if (*errcode == UURET_OK)
      *errcode = UURET_CONT;

    /* otherwise, just return NULL */
    _FP_free (result);
    return NULL;
  }

  /*
   * Read Epilogue, the plain text after the last boundary.
   * This can either end with new headers from the next message of a
   * mail folder or with a `parent' boundary if we are inside an
   * encapsulated Multipart message. Oh yes, and of course the file
   * may also simply end :-)
   * Another possibility is that we might find plain encoded data
   * without encapsulating message. We're not _too_ flexible here,
   * we won't detect Base64, and require a proper `begin' line for
   * uuencoding and xxencoding
   * If uu_usepreamble is set, we produce a result from this one
   */

  if (sstate.ismime && sstate.mimestate == MS_EPILOGUE) {
    result->startpos = ftell (datei);	/* remember start of epilogue */
    prevpos          = ftell (datei);
    preheaders       = ftell (datei);
    preenc           = ftell (datei);
    hcount = lcount  = 0;
    ecount = bhflag  = 0;
    begflag = vflag  = 0;
    res = 0;

    /*
     * If we are in the outermost message and uu_fast_scanning, we
     * know (or assume) that no more messages will follow, so there's
     * no need to scan the rest.
     */
    if (uu_fast_scanning && mssdepth == 0) {
      /*
       * check if the epilogue is empty
       */
      while (!feof (datei) && !ferror (datei) && lcount<10 && res==0) {
	if (_FP_fgets (line, 1024, datei) == NULL)
	  break;
	if (!IsLineEmpty (line))
	  res++;
	lcount++;
      }
      if (uu_usepreamble && res) {
	sprintf (line, "%04d.txt", ++mimseqno);
	result->subject  = _FP_strdup (sstate.envelope.subject);
	result->filename = _FP_strdup (line);
	result->origin   = _FP_strdup (sstate.envelope.from);
	result->mimeid   = _FP_strdup (sstate.envelope.mimeid);
	result->mimetype = _FP_strdup ("text/plain");
	result->mode     = 0644;
	result->uudet    = PT_ENCODED;	/* plain text */
	result->sfname   = _FP_strdup (fname);
	result->flags    = FL_SINGLE | FL_PROPER | FL_TOEND;
	result->partno   = 1;
	/* result->startpos set from above */
	result->length   = progress.fsize - result->startpos;

	if ((sstate.envelope.subject != NULL && result->subject == NULL) ||
	    result->filename == NULL || result->sfname == NULL) {
	  *errcode = UURET_NOMEM;
	}

	return result;
      }
      _FP_free (result);
      return NULL;
    }

    if (mssdepth > 0)
      blen = strlen (multistack[mssdepth-1].envelope.boundary);

    while (!feof (datei)) {
      if (_FP_fgets (line, 1024, datei) == NULL)
	break;
      if (UUBUSYPOLL(ftell(datei),progress.fsize)) SPCANCEL();
      /* check for parent boundary */
      if (mssdepth > 0 && line[0] == '-' && line[1] == '-' &&
	  strncmp (line+2,
		   multistack[mssdepth-1].envelope.boundary, blen) == 0)
	break;

      /* check for next headers only at outermost level */
      if (mssdepth == 0 && IsKnownHeader (line)) {
	(void) ScanHeaderLine (datei, line);
	if (hcount == 0) {
	  preheaders = prevpos;
	  lcount     = 0;
	}
	hcount++; 
	lcount++;

	if (hcount >= hlcount.restart) {
	  /* okay, new headers */
	  break;
	}
      }
      else if (lcount > WAITHEADER) {
	hcount = 0;
	lcount = 0;
      }
      else if (hcount) {
	lcount++;
      }
      else {
	hcount = lcount = 0;
      }

      /* check for begin and encoded data only at outermost level */
      if (mssdepth == 0 && !uu_more_mime) {
	if (strncmp      (line, "begin ",       6) == 0 ||
	    _FP_strnicmp (line, "
begin ", 11) == 0) {
	  preenc  = prevpos;
	  begflag = 1;
	}
	else if (strncmp (line, "end", 3) == 0 && begflag) {
	  ecount = ELC_COUNT;
	  break;
	}
	else if ((vflag = UUValidData (line, 0, &bhflag)) != 0) {
	  if (vflag == BH_ENCODED && bhflag == 0) {
	    /* very short BinHex file follows */
	    preenc = prevpos;
	    break;
	  }
	  /* remember that XX can easily be mistaken as Base64 */
	  if ((vflag == UU_ENCODED || vflag == XX_ENCODED || vflag == B64ENCODED) && begflag) {
	    if (++ecount >= ELC_COUNT)
	      break;
	  }
	  else {
	    begflag = 0;
	    ecount  = 0;
	  }
	}
	else {
	  begflag = 0;
	  ecount  = 0;
	}
      }

      if (!IsLineEmpty (line))
	res++;

      prevpos = ftell (datei);
    }

    if (mssdepth > 0 &&	line[0] == '-' && line[1] == '-' &&
	strncmp (line+2,
		 multistack[mssdepth-1].envelope.boundary, blen) == 0) {
      /* restore previous state */
      mssdepth--;
      UUkillheaders (&sstate.envelope);
      _FP_free  (sstate.source);
      memcpy (&sstate, &(multistack[mssdepth]), sizeof (scanstate));

      ptr1 = line + 2 + strlen (sstate.envelope.boundary);

      if (*ptr1 == '-' && *(ptr1+1) == '-') {
	sstate.mimestate = MS_EPILOGUE;
      }
      else {
	sstate.mimestate = MS_SUBPART;
      }
      result->length = prevpos - result->startpos;
      *errcode = UURET_CONT;
    }
    else if (mssdepth > 0) {
      UUMessage (uuscan_id, __LINE__, UUMSG_WARNING,
		 uustring (S_MIME_B_NOT_FOUND));
      /*
       * restart and try again; don't restart if uu_fast_scanning
       */
      sstate.isfolder  = 0;
      sstate.ismime    = 0;
      sstate.mimestate = MS_BODY;

      while (mssdepth) {
	mssdepth--;
	UUkillheaders (&(multistack[mssdepth].envelope));
	_FP_free (multistack[mssdepth].source);
      }

      if (!uu_fast_scanning) {
	*errcode = UURET_CONT;
	fseek (datei, preheaders, SEEK_SET);
      }
      _FP_free (result);
      return NULL;
    }
    else if (IsKnownHeader (line)) {
      /* new message follows */
      sstate.isfolder  = 1;
      sstate.ismime    = 0;
      sstate.mimestate = MS_HEADERS;
      result->length   = preheaders - result->startpos;
      fseek (datei, preheaders, SEEK_SET);
    }
    else if (ecount >= ELC_COUNT) {
      /* new plain encoding */
      sstate.isfolder  = 0;
      sstate.ismime    = 0;
      sstate.mimestate = MS_BODY;
      result->length   = preenc - result->startpos;
      fseek (datei, preenc, SEEK_SET);
    }

    /* produce result if uu_usepreamble is set */
    if (uu_usepreamble && res) {
      sprintf (line, "%04d.txt", ++mimseqno);
      result->subject  = _FP_strdup (sstate.envelope.subject);
      result->filename = _FP_strdup (line);
      result->origin   = _FP_strdup (sstate.envelope.from);
      result->mimeid   = _FP_strdup (sstate.envelope.mimeid);
      result->mimetype = _FP_strdup ("text/plain");
      result->mode     = 0644;
      result->uudet    = PT_ENCODED;	/* plain text */
      result->sfname   = _FP_strdup (fname);
      result->flags    = FL_SINGLE | FL_PROPER;
      result->partno   = 1;
      /* result->startpos set from above */
      /* result->length set from above */

      if ((sstate.envelope.subject != NULL && result->subject == NULL) ||
	  result->filename == NULL || result->sfname == NULL) {
	*errcode = UURET_NOMEM;
      }

      return result;
    }
    /* otherwise, just return NULL */
    _FP_free (result);
    return NULL;
  }

  /*
   * Scan a new part from a Multipart message. Check for a new local
   * envelope (which defaults to `Content-Type: text/plain') and
   * evaluate its Content-Type and Content-Transfer-Encoding. If this
   * is another Multipart/something, push the current state onto our
   * stack and dive into the new environment, starting with another
   * preamble.
   */
			   
  if (sstate.ismime && sstate.mimestate == MS_SUBPART) {
    memset (&localenv, 0, sizeof (headers));
    result->startpos = ftell (datei);
    prevpos = ftell (datei);
    hcount  = 0;
    lcount  = 0;

    /*
     * Duplicate some data from outer envelope
     */

    localenv.mimevers = _FP_strdup (sstate.envelope.mimevers);
    localenv.from     = _FP_strdup (sstate.envelope.from);
    localenv.subject  = _FP_strdup (sstate.envelope.subject);
    localenv.rcpt     = _FP_strdup (sstate.envelope.rcpt);
    localenv.date     = _FP_strdup (sstate.envelope.date);

    if ((sstate.envelope.mimevers != NULL && localenv.mimevers == NULL) ||
	(sstate.envelope.from     != NULL && localenv.from     == NULL) ||
	(sstate.envelope.subject  != NULL && localenv.subject  == NULL) ||
	(sstate.envelope.rcpt     != NULL && localenv.rcpt     == NULL) ||
	(sstate.envelope.date     != NULL && localenv.date     == NULL)) {

      while (mssdepth) {
	mssdepth--;
	UUkillheaders (&(multistack[mssdepth].envelope));
	_FP_free (multistack[mssdepth].source);
      }
      sstate.isfolder = 0;
      sstate.ismime   = 0;
      
      UUkillheaders (&localenv);
      *errcode = UURET_NOMEM;
      _FP_free (result);
      return NULL;
    }
    
    /* Scan subheader. But what if there is no subheader? */
    hcount = 0;
    lcount = 0;
    preheaders = prevpos;
    
    if (_FP_fgets (line, 1024, datei) == NULL) {
      sstate.isfolder = 0;
      sstate.ismime   = 0;
      while (mssdepth) {
	mssdepth--;
	UUkillheaders (&(multistack[mssdepth].envelope));
	_FP_free (multistack[mssdepth].source);
      }
      UUkillheaders (&localenv);
      _FP_free (result);
      return NULL;
    }

    while (!feof (datei) && !IsLineEmpty (line)) {
      if (IsKnownHeader (line))
	hcount++;
      if (UUBUSYPOLL(ftell(datei),progress.fsize)) SPCANCEL();
      if (lcount > WAITHEADER && hcount == 0) {
	fseek (datei, preheaders, SEEK_SET);
	prevpos = preheaders;
	break;
      }
      ptr1 = ScanHeaderLine (datei, line);
      if (ParseHeader (&localenv, ptr1) == NULL)
	*errcode = UURET_NOMEM;

      if (line[0] == '-' && line[1] == '-')
	break;

      prevpos = ftell (datei);

      if (_FP_fgets (line, 1024, datei) == NULL)
	break;
      lcount++;
    }
    if (line[0] == '-' && line[1] == '-') {
      /*
       * this shouldn't happen, there must always be an empty line,
       * but let's accept it anyway. Just skip back to before the
       * boundary, so that it gets handled below
       */
      fseek (datei, prevpos, SEEK_SET);
    }

    if (_FP_stristr (localenv.ctype, "multipart") != NULL) {
      /* oh no, not again */
      if (mssdepth >= MSMAXDEPTH) {
	/* Argh, what an isane message. Treat as plain text */
	UUMessage (uuscan_id, __LINE__, UUMSG_WARNING,
		   uustring (S_MIME_MULTI_DEPTH));
      }
      else if (localenv.boundary == NULL) {
	UUMessage (uuscan_id, __LINE__, UUMSG_WARNING,
		   uustring (S_MIME_NO_BOUNDARY));
      }
      else {
	memcpy (&multistack[mssdepth], &sstate, sizeof (scanstate));
	memcpy (&sstate.envelope,    &localenv, sizeof (headers));
	memset (&localenv, 0, sizeof (headers));
	sstate.mimestate = MS_PREAMBLE;
	if ((sstate.source = _FP_strdup (sstate.source)) == NULL)
	  *errcode = UURET_NOMEM;

	if (*errcode == UURET_OK)
	  *errcode = UURET_CONT;

	mssdepth++;
	/* need a restart */
	_FP_free (result);
	return NULL;
      }
    }

    /*
     * So this subpart is either plain text or something else. Check
     * the Content-Type and Content-Transfer-Encoding. If the latter
     * is a defined value, we know what to do and just copy everything
     * up to the boundary.
     * If Content-Transfer-Encoding is unknown or missing, look at the
     * Content-Type. If it's "text/plain" or undefined, we subject the
     * message to our encoding detection. Otherwise, treat as plain
     * text.
     * This is done because users might `attach' a uuencoded file, which
     * would then be correctly typed as `text/plain'.
     */

    if (_FP_stristr (localenv.ctenc, "base64") != NULL)
      result->uudet = B64ENCODED;
    else if (_FP_stristr (localenv.ctenc, "x-uue") != NULL) {
      result->uudet = UU_ENCODED;
      result->begin = result->end = 1;
    }
    else if (_FP_stristr (localenv.ctenc, "x-yenc") != NULL) {
      result->uudet = YENC_ENCODED;
      result->begin = result->end = 1;
    }
    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, "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
       */
      result->startpos = ftell (datei);
      prevpos          = ftell (datei);
      blen = strlen (sstate.envelope.boundary);
      lcount = 0;
      
      while (!feof (datei)) {
	if (_FP_fgets (line, 1024, datei) == NULL)
	  break;
	if (UUBUSYPOLL(ftell(datei),progress.fsize)) SPCANCEL();
	line[255] = '\0';
	if (line[0] == '-' && line[1] == '-' &&
	    strncmp (line+2, sstate.envelope.boundary, blen) == 0)
	  break;
	/*
	 * I've had a report of someone who tried to decode a huge file
	 * that had an early truncated multipart message and later another
	 * multipart message with the *same* boundary. Consequently, all
	 * some hundred messages inbetween were ignored ...
	 * This check here doesn't cover folded header lines, but we don't
	 * want to slow down scanning too much. We just check for
	 * Content-Type: multipart/... boundary="same-boundary"
	 */
	if (line[0] == 'C' && line[1] == 'o' &&
	    _FP_strnicmp (line, "Content-Type:", 13) == 0) {
	  ptr1 = ScanHeaderLine (datei, line);
	  ptr2 = (ptr1)?_FP_stristr(ptr1,"boundary"):NULL;
	  ptr1 = (ptr2)?ParseValue(ptr2):NULL;
	  if (ptr1 && strcmp (ptr1, sstate.envelope.boundary) == 0)
	    break;
	  for (res=0; ptr1 && resstartpos, SEEK_SET);

	UUkillfread (result);
	if ((result = (fileread *) malloc (sizeof (fileread))) == NULL) {
	  *errcode = UURET_NOMEM;
	  sstate.isfolder = 0;
	  sstate.ismime   = 0;
	  UUkillheaders (&localenv);
	  return NULL;
	}
	memset (result, 0, sizeof (fileread));

	if ((res = ScanData (datei, fname, errcode, NULL, 1, 1, result))==-1) {
	  /* oops, something went wrong */
	  sstate.isfolder = 0;
	  sstate.ismime   = 0;
	  UUkillfread   (result);
	  UUkillheaders (&localenv);
	  return NULL;
	}
	if (res == 1) {
	  /*
	   * new headers found
	   */
	  sstate.isfolder  = 1;
	  sstate.ismime    = 0;
	  sstate.mimestate = MS_HEADERS;
	}
	else {
	  sstate.isfolder  = 0;
	  sstate.ismime    = 0;
	}
      }
      /* produce result if uu_handletext is set */
      /* 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 && uu_handletext) {
	  sprintf (line, "%04d.txt", ++mimseqno);
	  if ((result->filename = _FP_strdup (line)) == NULL)
	    *errcode = UURET_NOMEM;
	}
	result->subject  = _FP_strdup (localenv.subject);
	result->origin   = _FP_strdup (localenv.from);
	result->mimeid   = _FP_strdup (localenv.mimeid);
	result->mimetype = _FP_strdup (localenv.ctype);
	result->mode     = 0644;
	result->sfname   = _FP_strdup (fname);
	result->flags    = FL_SINGLE | FL_PROPER;
	result->partno   = 1;
	/* result->uudet determined above */
	/* result->startpos set from above */
	result->length   = prevpos - result->startpos;

	if ((localenv.subject != NULL && result->subject == NULL) ||
	    result->filename == NULL  || result->sfname == NULL) {
	  *errcode = UURET_NOMEM;
	}
      }
      else {
	/* don't produce a result */
	_FP_free (result);
	result = NULL;
      }
      if (*errcode == UURET_OK)
	*errcode = UURET_CONT;
      /*
       * destroy local envelope
       */
      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) {
      /* oops, something went wrong */
      sstate.isfolder = 0;
      sstate.ismime   = 0;
      UUkillfread   (result);
      UUkillheaders (&localenv);
      return NULL;
    }
    /*
     * we should really be at a boundary here, but check again
     */
    blen    = strlen (sstate.envelope.boundary);
    prevpos = ftell  (datei);

    while (!feof (datei)) {
      if (_FP_fgets (line, 1024, datei) == NULL)
	break;
      if (UUBUSYPOLL(ftell(datei),progress.fsize)) SPCANCEL();
      if (line[0] == '-' && line[1] == '-' &&
	  strncmp (line+2, sstate.envelope.boundary, blen) == 0)
	break;
      if (line[0] == 'C' && line[1] == 'o' &&
	  _FP_strnicmp (line, "Content-Type:", 13) == 0) {
	ptr1 = ScanHeaderLine (datei, line);
	ptr2 = (ptr1)?_FP_stristr(ptr1,"boundary"):NULL;
	ptr1 = (ptr2)?ParseValue(ptr2):NULL;
	if (ptr1 && strcmp (ptr1, sstate.envelope.boundary) == 0)
	  break;
      }
      prevpos = ftell (datei);
    }
    /*
     * check if this was the last subpart
     */
    if (line[0] == '-' && line[1] == '-' &&
	strncmp (line+2, sstate.envelope.boundary, blen) == 0) {
      ptr1 = line + 2 + blen;
      if (*ptr1 == '-' && *(ptr1+1) == '-')
	sstate.mimestate = MS_EPILOGUE;
      else
	sstate.mimestate = MS_SUBPART;
    }
    else {
      UUMessage (uuscan_id, __LINE__, UUMSG_WARNING,
		 uustring (S_MIME_B_NOT_FOUND));
      
      while (mssdepth) {
	mssdepth--;
	UUkillheaders (&(multistack[mssdepth].envelope));
	_FP_free (multistack[mssdepth].source);
      }

      if (uu_fast_scanning) {
	UUkillheaders (&localenv);
	sstate.isfolder  = 0;
	sstate.ismime    = 0;
	sstate.mimestate = MS_BODY;
	_FP_free (result);
	return NULL;
      }

      /*
       * Retry, listening to headers this time
       */
      fseek (datei, result->startpos, SEEK_SET);
      
      UUkillfread (result);
      if ((result = (fileread *) malloc (sizeof (fileread))) == NULL) {
	*errcode = UURET_NOMEM;
	sstate.isfolder = 0;
	sstate.ismime   = 0;
	UUkillheaders (&localenv);
	return NULL;
      }
      memset (result, 0, sizeof (fileread));

      if ((res = ScanData (datei, fname, errcode, NULL, 1, 1, result))==-1) {
	/* oops, something went wrong */
	sstate.isfolder = 0;
	sstate.ismime   = 0;
	UUkillfread   (result);
	UUkillheaders (&localenv);
	return NULL;
      }
      if (res == 1) {
	/*
	 * new headers found
	 */
	sstate.isfolder  = 1;
	sstate.ismime    = 0;
	sstate.mimestate = MS_HEADERS;
      }
      else {
	sstate.isfolder  = 0;
	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 (sstate.ismime && sstate.mimestate == MS_SUBPART &&
        strcmp (localenv.mimevers, "1.0") == 0 &&
	_FP_stristr (localenv.ctype, "text") != NULL &&
	!uu_desperate) {
      if (result->uudet == UU_ENCODED && !(result->begin || result->end)) {
	result->uudet = 0;
      }
    }

    /*
     * produce result
     */

    if (result->uudet == 0) {
      result->uudet = PT_ENCODED; /* plain text */
    }

    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 && uu_handletext) {
      sprintf (line, "%04d.txt", ++mimseqno);
      if ((result->filename = _FP_strdup (line)) == NULL)
	*errcode = UURET_NOMEM;
    }
    else {
      /* assign a filename lateron */
    }
    if (result->mimetype) _FP_free (result->mimetype);
    if (result->uudet) {
      if (_FP_stristr (localenv.ctype, "text") != NULL &&
	  result->uudet != QP_ENCODED && result->uudet != PT_ENCODED)
	result->mimetype = NULL; /* better don't set it */
      else
	result->mimetype = _FP_strdup (localenv.ctype);
    }
    if (result->origin) _FP_free  (result->origin);
    result->origin  = _FP_strdup  (localenv.from);

    if (result->subject) _FP_free (result->subject);
    result->subject = _FP_strdup  (localenv.subject);

    if (result->sfname == NULL)
      if ((result->sfname = _FP_strdup (fname)) == NULL)
	*errcode = UURET_NOMEM;

    result->length = prevpos - result->startpos;
    result->flags  = FL_SINGLE | FL_PROPER;
    result->partno = 1;

    if (result->mode == 0)
      result->mode = 0644;

    /*
     * the other fields should already be set appropriately
     */

    if (*errcode == UURET_OK)
      *errcode = UURET_CONT;

    /*
     * kill local envelope
     */
    UUkillheaders (&localenv);
    
    return result;
  }

  /*
   * All right, so we're not in a Multipart message. Phew, took quite
   * long to figure this out. But this might still be a MIME message
   * body. And if it's a message/partial, we need more special handling
   */

  if (sstate.isfolder && sstate.ismime && sstate.mimestate == MS_BODY &&
      _FP_stristr (sstate.envelope.ctype, "message") != NULL &&
      _FP_stristr (sstate.envelope.ctype, "partial") != NULL) {

    result->startpos = ftell (datei);

    if (sstate.envelope.partno == 1) {
      /* read local envelope */
      UUkillheaders (&localenv);
      memset (&localenv, 0, sizeof (headers));

      /* skip over blank lines first */
      prevpos = ftell (datei);
      while (!feof (datei)) {
	if (_FP_fgets (line, 1024, datei) == NULL)
	  break;
	if (UUBUSYPOLL(ftell(datei),progress.fsize)) SPCANCEL();
	if (!IsLineEmpty (line))
	  break;
	prevpos = ftell (datei);
      }
      /* Next, read header. But what if there is no subheader? */
      hcount = 0;
      lcount = 0;
      preheaders = prevpos;

      while (!feof (datei) && !IsLineEmpty (line)) {
	if (IsKnownHeader (line))
	  hcount++;
	if (UUBUSYPOLL(ftell(datei),progress.fsize)) SPCANCEL();
	if (lcount > WAITHEADER && hcount == 0) {
	  fseek (datei, preheaders, SEEK_SET);
	  break;
	}
	ptr1 = ScanHeaderLine (datei, line);
	if (ParseHeader (&localenv, ptr1) == NULL)
	  *errcode = UURET_NOMEM;

	if (_FP_fgets (line, 1024, datei) == NULL)
	  break;
	lcount++;
      }
      prevpos = ftell (datei);
      /*
       * Examine local header. We're mostly interested in the Content-Type
       * and the Content-Transfer-Encoding.
       */
      if (_FP_stristr (localenv.ctype, "multipart") != NULL) {
	UUMessage (uuscan_id, __LINE__, UUMSG_WARNING,
		   uustring (S_MIME_PART_MULTI));
      }
      if (localenv.subject)
	result->subject  = _FP_strdup (localenv.subject);
      else
	result->subject  = _FP_strdup (sstate.envelope.subject);

      if (localenv.from)
	result->origin   = _FP_strdup (localenv.from);
      else
	result->origin   = _FP_strdup (sstate.envelope.from);

      if (localenv.ctype)
	result->mimetype = _FP_strdup (localenv.ctype);
      else
	result->mimetype = _FP_strdup ("text/plain");

      if (_FP_stristr (localenv.ctenc, "quoted-printable") != NULL)
	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;
	result->begin = result->end = 1;
      }
      else if (_FP_stristr (localenv.ctenc, "x-yenc") != NULL) {
	result->uudet = YENC_ENCODED;
	result->begin = result->end = 1;
      }
      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));
    }

    /*
     * If this is Quoted-Printable or Plain Text, just try looking
     * for the next message header. If uu_fast_scanning, and the
     * encoding is known, there's no need to look below. Otherwise,
     * we check the type of encoding first.
     * The encoding type is determined on the first part; in all
     * others, we also don't read on.
     * If we have a partial multipart message, scan for headers, but
     * do not react on standard MIME headers, as they are probably
     * from the subparts. However, we're stuck if there's an embedded
     * message/rfc822 :-(
     * If it is a "trivial" (non-embedded) message/rfc822, skip over
     * the message header and then start looking for the next header.
     */
    if (uu_fast_scanning && (result->uudet!=0||sstate.envelope.partno!=1)) {
      /* do nothing */
      res = 0;
    }
    else if (result->uudet != 0) {
      hcount = lcount = 0;
      prevpos = ftell (datei);

      if (_FP_stristr (localenv.ctype, "message") != NULL &&
	  _FP_stristr (localenv.ctype, "rfc822")  != NULL) {
	/*
	 * skip over empty lines and local header
	 */
	preheaders = ftell (datei);
	while (!feof (datei)) {
	  if (_FP_fgets (line, 1024, datei) == NULL)
	    break;
	  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, 1024, datei) == NULL)
	    break;
	}
	if (hcount < hlcount.afternl)
	  fseek (datei, preheaders, SEEK_SET);
	hcount = lcount = 0;
      }

      /*
       * look for next header
       */

      while (!feof (datei)) {
	if (_FP_fgets (line, 1024, datei) == NULL)
	  break;
	if (UUBUSYPOLL(ftell(datei),progress.fsize)) SPCANCEL();
	if (ferror (datei))
	  break;

	if ((vflag = IsKnownHeader (line))) {
	  (void) ScanHeaderLine (datei, line);

	  if (result->uudet != PT_ENCODED || vflag == 1) {
	    if (hcount == 0)
	      preheaders = prevpos;
	    hcount++;
	    lcount++;
	    if (hcount >= hlcount.restart) {
	      /*
	       * Hey, a new header starts here
	       */
	      fseek (datei, preheaders, SEEK_SET);
	      prevpos = preheaders;
	      break;
	    }
	  }
	}
	else if (lcount > WAITHEADER) {
	  hcount = 0;
	  lcount = 0;
	}
	else if (hcount) {
	  lcount++;
	}
	prevpos = ftell (datei);
      }
      res = 1;
    }
    else {
      /*
       * Otherwise, let's see what we can find ourself. No
       * boundary (NULL) but MIME, and respect new headers.
       */
      if ((res = ScanData (datei, fname, errcode, NULL, 1, 1, result)) == -1) {
	/* oops, something went wrong */
	sstate.isfolder = 0;
	sstate.ismime   = 0;
	UUkillfread   (result);
	UUkillheaders (&localenv);
	return NULL;
      }
      if (result->uudet == 0 && uu_handletext)
	result->uudet = PT_ENCODED;

      prevpos = ftell (datei);
    }
    /*
     * produce result
     */
    if (localenv.fname) {
      _FP_free (result->filename);
      if ((result->filename = _FP_strdup (localenv.fname)) == NULL)
	*errcode = UURET_NOMEM;
    }
    else if (sstate.envelope.fname) {
      _FP_free (result->filename);
      if ((result->filename = _FP_strdup (sstate.envelope.fname)) == NULL)
	*errcode = UURET_NOMEM;
    }
    else if ((result->uudet==QP_ENCODED || result->uudet==PT_ENCODED) &&
	     result->filename == NULL) {
      sprintf (line, "%04d.txt", ++mimseqno);
      if ((result->filename = _FP_strdup (line)) == NULL)
	*errcode = UURET_NOMEM;
    }
    else {
      /* assign a filename lateron */
    }
    if (result->subject == NULL) {
      if (sstate.envelope.subject)
	result->subject = _FP_strdup (sstate.envelope.subject);
    }
    result->partno = sstate.envelope.partno;
    result->maxpno = sstate.envelope.numparts;
    result->flags  = FL_PARTIAL | 
      ((res==1 || uu_fast_scanning) ? FL_PROPER : 0) |
	((uu_fast_scanning) ? FL_TOEND : 0);
    result->mimeid = _FP_strdup (sstate.envelope.mimeid);
    if (result->partno == 1)
      result->begin = 1;

    if (uu_fast_scanning)
      result->length = progress.fsize - result->startpos;
    else
      result->length = prevpos - result->startpos;

    if (result->sfname == NULL)
      result->sfname = _FP_strdup (fname);

    if (result->mode == 0)
      result->mode = 0644;

    /*
     * the other fields should already be set appropriately
     */

    if (res == 1) {
      /*
       * new headers found
       */
      sstate.isfolder  = 1;
      sstate.ismime    = 0;
      sstate.mimestate = MS_HEADERS;
      
      UUkillheaders (&sstate.envelope);
      memset (&sstate.envelope, 0, sizeof (headers));
    }
    else {
      /*
       * otherwise, this can't be a mail folder
       */
      sstate.isfolder  = 0;
      sstate.ismime    = 0;
    }
    /*
     * kill local envelope
     */
    UUkillheaders (&localenv);
    return result;
  }

  /*
   * 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.ctenc, "x-uue")            != NULL ||
       _FP_stristr (sstate.envelope.ctenc, "x-yenc")           != NULL ||
       _FP_stristr (sstate.envelope.ctype, "message")          != NULL ||
       sstate.envelope.fname != NULL)) {

    if (sstate.envelope.subject)
      result->subject = _FP_strdup (sstate.envelope.subject);
    if (sstate.envelope.from)
      result->origin  = _FP_strdup (sstate.envelope.from);

    if (sstate.envelope.ctype)
      result->mimetype = _FP_strdup (sstate.envelope.ctype);
    else
      result->mimetype = _FP_strdup ("text/plain");

    if (_FP_stristr (sstate.envelope.ctenc, "quoted-printable") != NULL)
      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;
      result->begin = result->end = 1;
    }
    else if (_FP_stristr (sstate.envelope.ctenc, "x-yenc") != NULL) {
      result->uudet = YENC_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 ||
	     sstate.envelope.fname != 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;
    }

    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 */
      res = 0;
    }
    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, 1024, datei) == NULL)
	    break;
	  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, 1024, datei) == NULL)
	    break;
	}
	if (hcount < hlcount.afternl)
	  fseek (datei, preheaders, SEEK_SET);
	hcount = lcount = 0;
      }

      /*
       * look for next header
       */

      while (!feof (datei)) {
	if (_FP_fgets (line, 1024, datei) == NULL)
	  break;
	if (UUBUSYPOLL(ftell(datei),progress.fsize)) SPCANCEL();
	if (ferror (datei))
	  break;

	if (IsKnownHeader (line)) {
	  (void) ScanHeaderLine (datei, line);
	  if (hcount == 0)
	    preheaders = prevpos;
	  hcount++;
	  lcount++;
	  if (hcount >= hlcount.restart) {
	    /*
	     * Hey, a new header starts here
	     */
	    fseek (datei, preheaders, SEEK_SET);
	    prevpos = preheaders;
	    break;
	  }
	}
	else if (lcount > WAITHEADER) {
	  hcount = 0;
	  lcount = 0;
	}
	else if (hcount) {
	  lcount++;
	}
	prevpos = ftell (datei);
      }
      res = 1;
    }
    else {
      /*
       * Otherwise, let's see what we can find ourself. No
       * boundary (NULL) but MIME, and respect new headers.
       */
      if ((res = ScanData (datei, fname, errcode, NULL, 1, 1, result)) == -1) {
	/* oops, something went wrong */
	sstate.isfolder = 0;
	sstate.ismime   = 0;
	UUkillfread   (result);
	return NULL;
      }
      if (result->uudet == 0 && uu_handletext) {
	result->startpos = before;	/* display headers */
	result->uudet = PT_ENCODED;
      }

      prevpos = ftell (datei);
    }
    /*
     * produce result
     */
    if (sstate.envelope.fname) {
      _FP_free (result->filename);
      if ((result->filename = _FP_strdup (sstate.envelope.fname)) == NULL)
	*errcode = UURET_NOMEM;
    }
    else if ((result->uudet==QP_ENCODED||result->uudet==PT_ENCODED) &&
	     result->filename == NULL) {
      sprintf (line, "%04d.txt", ++mimseqno);
      if ((result->filename = _FP_strdup (line)) == NULL)
	*errcode = UURET_NOMEM;
    }
    else {
      /* assign a filename lateron */
    }
    if (result->subject == NULL) {
      if (sstate.envelope.subject)
	result->subject = _FP_strdup (sstate.envelope.subject);
    }
    result->flags  = ((res==1||uu_fast_scanning)?FL_PROPER:0) |
      ((uu_fast_scanning) ? FL_TOEND : 0);
    result->mimeid = _FP_strdup (sstate.envelope.mimeid);

    if (uu_fast_scanning)
      result->length = progress.fsize - result->startpos;
    else
      result->length = prevpos - result->startpos;

    if (result->sfname == NULL)
      result->sfname = _FP_strdup (fname);

    if (result->mode == 0)
      result->mode = 0644;

    /*
     * the other fields should already be set appropriately
     */

    if (res == 1) {
      /*
       * new headers found
       */
      sstate.isfolder  = 1;
      sstate.ismime    = 0;
      sstate.mimestate = MS_HEADERS;

      UUkillheaders (&sstate.envelope);
      memset (&sstate.envelope, 0, sizeof (headers));
    }
    else {
      /*
       * otherwise, this can't be a mail folder
       */
      sstate.isfolder  = 0;
      sstate.ismime    = 0;
    }

    return result;
  }

  /*
   * Some files have reduced headers, and what should be a multipart
   * message is missing the proper Content-Type. If the first thing
   * we find after a couple of empty lines is a boundary, try it!
   * But make sure that this is indeed intended as being a boundary.
   *
   * Only accept it if there was indeed no Content-Type header line
   * and if the following line is a proper Content-Type header. BTW,
   * we know that sstate.envelope.boundary is NULL, or we wouldn't
   * be here!
   */

  if ((!sstate.envelope.ctype || _FP_stristr (sstate.envelope.ctype, "multipart"))
      && !uu_more_mime) {
    prevpos = ftell (datei);
    while (!feof (datei)) {
      if (_FP_fgets (line, 1024, datei) == NULL)
	break;
      if (UUBUSYPOLL(ftell(datei),progress.fsize)) SPCANCEL();
      if (!IsLineEmpty (line))
	break;
    }
    if (line[0] == '-' && line[1] == '-' &&
	!IsLineEmpty (line+2) && !feof (datei)) {
      ptr1 = _FP_strrstr (line+2, "--");
      ptr2 = ScanHeaderLine (datei, NULL);
      if ((ptr1 == NULL || ptr1[2]) &&
	  ptr2 && _FP_strnicmp (ptr2, "Content-", 8) == 0) {
	/*
	 * hmm, okay, let's do it!
	 */
	sstate.isfolder  = 1;
	sstate.ismime    = 1;
	sstate.mimestate = MS_PREAMBLE;
	/*
	 * get boundary
	 */
	ptr1 = line+2;
	while (*ptr1 && !isspace(*ptr1))
	  ptr1++;
	*ptr1 = '\0';

	sstate.envelope.mimevers = _FP_strdup ("1.0");
	sstate.envelope.boundary = _FP_strdup (line+2);
	
	/*
	 * need restart
	 */
	
	fseek (datei, prevpos, SEEK_SET);
	
	_FP_free (result);
	return NULL;
      }
    }
    fseek (datei, prevpos, SEEK_SET);
  }

  /*
   * Hmm, we're not in a ''special'' state, so it's more or less
   * Freestyle time. Anyway, if this seems to be a Mime message,
   * don't allow the minimal Base64 handling.
   */

  if (sstate.envelope.subject)
    result->subject = _FP_strdup (sstate.envelope.subject);

  if (sstate.envelope.from)
    result->origin  = _FP_strdup (sstate.envelope.from);

  if (sstate.envelope.ctype)
    result->mimetype = _FP_strdup (sstate.envelope.ctype);
  
  if ((res=ScanData (datei, fname, errcode, NULL, 
		     sstate.ismime, 1, result))==-1) {
    /* oops, something went wrong */
    sstate.isfolder = 0;
    sstate.ismime   = 0;
    UUkillfread   (result);
    return NULL;
  }

  /*
   * produce result
   */

  if (result->uudet == 0 && uu_handletext) {
    result->startpos = before;	/* display headers */
    result->uudet  = PT_ENCODED;
    result->partno = 1;
  }

  if (result->uudet == YENC_ENCODED && result->filename != NULL) {
    /*
     * prevent replacing the filename found on the =ybegin line
     */
  }
  else if (sstate.envelope.fname) {
    _FP_free (result->filename);
    if ((result->filename = _FP_strdup (sstate.envelope.fname)) == NULL)
      *errcode = UURET_NOMEM;
  }
  else if ((result->uudet==QP_ENCODED||result->uudet==PT_ENCODED) &&
	   result->filename == NULL) {
    sprintf (line, "%04d.txt", ++mimseqno);
    if ((result->filename = _FP_strdup (line)) == NULL)
      *errcode = UURET_NOMEM;
  }
  else {
    /* assign a filename lateron */
  }

  if (result->subject == NULL) {
    if (sstate.envelope.subject)
      result->subject = _FP_strdup (sstate.envelope.subject);
  }

  result->flags  = (result->uudet==PT_ENCODED)?FL_SINGLE:0;
  result->mimeid = _FP_strdup (sstate.envelope.mimeid);
  result->length = ftell (datei) - result->startpos;

  if (result->mode == 0)
    result->mode = 0644;

  if (result->sfname == NULL)
    result->sfname = _FP_strdup (fname);

  if (res == 1) {
    /*
     * new headers found
     */
    sstate.isfolder  = 1;
    sstate.ismime    = 0;
    sstate.mimestate = MS_HEADERS;

    UUkillheaders (&sstate.envelope);
    memset (&sstate.envelope, 0, sizeof (headers));
  }
  else {
    /*
     * otherwise, this can't be a mail folder
     */
    sstate.isfolder  = 0;
    sstate.ismime    = 0;
  }

  return result;

  /*
   * Emergency handling. Set errcode before jumping here.
   */
 ScanPartEmergency:
  UUkillfread   (result);
  UUkillheaders (&localenv);

  while (mssdepth) {
    mssdepth--;
    UUkillheaders (&(multistack[mssdepth].envelope));
    _FP_free (multistack[mssdepth].source);
  }

  return NULL;
}

Convert-UUlib-1.5/uulib/safealloc.c0000644000000000000000000000337712547615522015753 0ustar  rootroot/* enable the POSIX prototypes of mmap/munmap on Solaris */
#ifdef __sun
# if __STDC_VERSION__ >= 199901L
#  define _XOPEN_SOURCE 600
# else
#  define _XOPEN_SOURCE 500
# endif
#endif

#ifndef _WIN32
  #include 
#endif

#if !defined USE_MMAP \
    && _POSIX_MAPPED_FILES > 0 \
    && (_POSIX_VERSION >= 200809L || _POSIX_MEMORY_PROTECTION > 0)
  #include 
  #if !defined MAP_ANONYMOUS && defined MAP_ANON
    #define MAP_ANONYMOUS MAP_ANON
  #endif
  #ifdef MAP_ANONYMOUS
    #include 
    #if PAGESIZE <= 0
      static long pagesize;
      #define PAGESIZE pagesize ? pagesize : (pagesize = sysconf (_SC_PAGESIZE))
    #endif
    #define USE_MMAP 1
  #endif
#endif

/* we assume natural alignment, uulib only uses ints and chars */
#define ALIGN 1
#define GUARDS 4

static void *
safe_alloc (size_t size)
{
#if USE_MMAP

  size_t rounded = (size + ALIGN - 1) & ~(ALIGN - 1);
  size_t page = PAGESIZE;
  size_t page_rounded = (rounded + page - 1) & ~(page - 1);
  void *base = mmap (0, page_rounded + page * GUARDS * 2, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);

  if (base == (void *)-1)
    return 0;

  mprotect (base, page * GUARDS, PROT_NONE); /* beginning */
  mprotect (page_rounded + page * GUARDS + (char *)base, page * GUARDS, PROT_NONE); /* end */

  return page * GUARDS + (page_rounded - rounded) + (char *)base;

#else
  return malloc (size);
#endif
}

static void
safe_free (void *mem, size_t size)
{
#if USE_MMAP

  size_t rounded = (size + ALIGN - 1) & ~(ALIGN - 1);
  size_t page = PAGESIZE;
  size_t page_rounded = (rounded + page - 1) & ~(page - 1);

  if (!mem)
    return;

  mem = (char *)mem - page * GUARDS - (page_rounded - rounded);

  munmap (mem, page_rounded + page * GUARDS * 2);

#else
  free (size);
#endif
}

Convert-UUlib-1.5/uulib/uunconc.c0000644000000000000000000012552511567725651015502 0ustar  rootroot/*
 * This file is part of uudeview, the simple and friendly multi-part multi-
 * 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
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 */

/*
 * These are the functions that are responsible for decoding. The
 * original idea is from a freeware utility called "uunconc", and
 * few lines of this code may still bear a remote resemblance to
 * its code. If you are the author or know him, contact me.
 * This program could only decode one multi-part, uuencoded file
 * where the parts were in order. Base64, XX and BinHex decoding,
 * support for multi-files and part-ordering covered by myself.
 **/

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#ifdef SYSTEM_WINDLL
#include 
#endif
#ifdef SYSTEM_OS2
#include 
#endif

#include 
#include 

#ifdef STDC_HEADERS
#include 
#include 
#endif
#ifdef HAVE_UNISTD_H
#include 
#endif
#ifdef HAVE_ERRNO_H
#include 
#endif

#include 
#include 
#include 
#include 
#include 

char * uunconc_id = "$Id$";

/* for braindead systems */
#ifndef SEEK_SET
#ifdef L_BEGIN
#define SEEK_SET L_BEGIN
#else
#define SEEK_SET 0
#endif
#endif

/*
 * decoder states
 */

#define BEGIN     (1)
#define DATA      (2)
#define END       (3)
#define DONE      (4)

/*
 * mallocable areas
 */

char *uunconc_UUxlat;
char *uunconc_UUxlen;
char *uunconc_B64xlat;
char *uunconc_XXxlat;
char *uunconc_BHxlat;
char *uunconc_save;

/*
 * decoding translation tables and line length table
 */

static int      * UUxlen;	/* initialized in UUInitConc()    */
static int      * UUxlat;	/* from the malloc'ed areas above */
static int      * B64xlat;
static int      * XXxlat;
static int     	* BHxlat;

/*
 * buffer for decoding
 */

static char *save[3];

/*
 * mallocable areas
 */

char *uuncdl_fulline;
char *uuncdp_oline;

/*
 * Return information for QuickDecode
 */

static int uulboundary;

/*
 * To prevent warnings when using a char as index into an array
 */

#define ACAST(s)	((int)(uchar)(s))

/*
 * Initialize decoding tables
 */

void
UUInitConc (void)
{
  int i, j;

  /*
   * Update pointers
   */
  UUxlen  = (int *) uunconc_UUxlen;
  UUxlat  = (int *) uunconc_UUxlat;
  B64xlat = (int *) uunconc_B64xlat;
  XXxlat  = (int *) uunconc_XXxlat;
  BHxlat  = (int *) uunconc_BHxlat;

  save[0] = uunconc_save;
  save[1] = uunconc_save + 1200;
  save[2] = uunconc_save + 2400;

  /* prepare decoding translation table */
  for(i = 0; i < 256; i++)
    UUxlat[i] = B64xlat[i] = XXxlat[i] = BHxlat[i] = -1;

  /*
   * At some time I received a file which used lowercase characters for
   * uuencoding. This shouldn't be, but let's accept it. Must take special
   * care that this doesn't break xxdecoding. This is giving me quite a
   * headache. If this one file hadn't been a Pocahontas picture, I might
   * have ignored it for good.
   */

  for (i = ' ', j = 0; i < ' ' + 64; i++, j++)
    UUxlat[i] /* = UUxlat[i+64] */ = j;
  for (i = '`', j = 0; i < '`' + 32; i++, j++)
    UUxlat[i] = j;

  /* add special cases */
  UUxlat['`'] = UUxlat[' '];
  UUxlat['~'] = UUxlat['^'];

  /* prepare line length table */
  UUxlen[0] = 1;
  for(i = 1, j = 5; i <= 61; i += 3, j += 4)
    UUxlen[i] = UUxlen[i+1] = UUxlen[i+2] = j;

  /* prepare other tables */
  for (i=0; i<64; i++) {
    B64xlat[ACAST(B64EncodeTable[i])] = i;
    XXxlat [ACAST(XXEncodeTable [i])] = i;
    BHxlat [ACAST(BHEncodeTable [i])] = i;
  }
}

/*
 * Workaround for Netscape
 */

/*
 * Determines whether Netscape may have broken up a data line (by
 * inserting a newline). This only seems to happen after ") > ptr)
      return 2;
  }

  ptr = string + len;

  if (len<3)         return 0;
  if (*--ptr == ' ') ptr--;
  ptr--;

  if (_FP_strnicmp (ptr, "",4)). If the first expression
 * becomes true, the costly function isn't called :-)
 *
 * Since '<', '>', '&' might even be replaced by their html equivalents
 * in href strings, I'm now using two passes, the first one for & + co,
 * the second one for hrefs.
 */

int
UUNetscapeCollapse (char *string)
{
  char *p1=string, *p2=string;
  int res = 0;

  if (string==NULL)
    return 0;

  /*
   * First pass
   */
  while (*p1) {
    if (*p1 == '&') {
      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++;
  }
  *p2 = '\0';
  /*
   * Second pass
   */
  p1 = p2 = string;

  while (*p1) {
    if (*p1 == '<') {
      if ((_FP_strnicmp (p1, "") != 0 || _FP_strstr (p1, "") != 0)) {
	while (*p1 && *p1!='>')        p1++;
	if (*p1=='\0' || *(p1+1)!='<') return 0;
	p1++;
	while (*p1 && (*p1!='<' || _FP_strnicmp(p1,"",4)!=0)) {
	  *p2++ = *p1++;
	}
	if (_FP_strnicmp(p1,"",4) != 0)
	  return 0;
	p1+=4;
	res=1;
      }
      else
	*p2++ = *p1++;
    }
    else
      *p2++ = *p1++;
  }
  *p2 = '\0';

  return res;
}

/*
 * The second parameter is 0 if we are still searching for encoded data,
 * otherwise it indicates the encoding we're using right now. If we're
 * still in the searching stage, we must be a little more strict in
 * deciding for or against encoding; there's too much plain text looking
 * like encoded data :-(
 */

int
UUValidData (char *ptr, int encoding, int *bhflag)
{
  int i=0, j, len=0, suspicious=0, flag=0;
  signed char *s = ptr;

  if ((s == NULL) || (*s == '\0')) {
    return 0;              /* bad string */
  }

  while (*s) {
    s++;
    len++;
    i++;
  }

  if (i == 0)
    return 0;

  switch (encoding) {
  case UU_ENCODED:
    goto _t_UU;
  case XX_ENCODED:
    goto _t_XX;
  case B64ENCODED:
    goto _t_B64;
  case BH_ENCODED:
    goto _t_Binhex;
  case YENC_ENCODED:
    return YENC_ENCODED;
  }

 _t_Binhex:                 /* Binhex Test */
  len = i; s = ptr;

  /*
   * bhflag notes the state we're in. Within the data, it's 1. If we're
   * still looking for the initial :, it's 0
   */
  if (*bhflag == 0 && *s != ':') {
    if (encoding==BH_ENCODED) return 0;
    goto _t_B64;
  }
  else if (*bhflag == 0 /* *s == ':' */) {
    s++; len--;
  }

  while (len && BHxlat[ACAST(*s)] != -1) {
    len--; s++;
  }

  /* allow space characters at the end of the line if we are sure */
  /* that this is Binhex encoded data or the line was long enough */

  flag = (*s == ':') ? 0 : 1;

  if (*s == ':' && len>0) {
    s++; len--;
  }
  if (((i>=60 && len<=10) || encoding) && *s==' ') {
    while (len && *s==' ') {
      s++; len--;
    }
  }

  /*
   * BinHex data shall have exactly 64 characters (except the last
   * line). We ignore everything with less than 40 characters to
   * be flexible
   */

  if (len != 0 || (flag && i < 40)) {
    if (encoding==BH_ENCODED) return 0;
    goto _t_B64;
  }

  *bhflag = flag;

  return BH_ENCODED;

 _t_B64:                    /* Base64 Test */
  len = i; s = ptr;

  /*
   * Face it: there _are_ Base64 lines that are not a multiple of four
   * in length :-(
   *
   * if (len%4)
   *   goto _t_UU;
   */

  while (len--) {
    if (*s < 0 || (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++==' ') {
	while (*s==' ' && len) s++;
	if (len==0) return B64ENCODED;
      }
      if (encoding==B64ENCODED) return 0;
      goto _t_UU;
    }
    else if (*s == '=') {   /* special case at end */
      /* if we know this is B64encoded, allow spaces at end of line */
      s++;
      if (*s=='=' && len>=1) {
	len--; s++;
      }
      if (encoding && len && *s==' ') {
	while (len && *s==' ') {
	  s++; len--;
	}
      }
      if (len != 0) {
	if (encoding==B64ENCODED) return 0;
	goto _t_UU;
      }
      return B64ENCODED;
    }
    s++;
  }
  return B64ENCODED;

 _t_UU:
  len = i; s = ptr;

  if (UUxlat[ACAST(*s)] == -1) {    /* uutest */
    if (encoding==UU_ENCODED) return 0;
    goto _t_XX;
  }

  j = UUxlen[UUxlat[ACAST(*s)]];

  if (len-1 == j)	    /* remove trailing character */
    len--;
  if (len != j) {
    switch (UUxlat[ACAST(*s)]%3) {
    case 1:
      if (j-2 == len) j-=2;
      break;
    case 2:
      if (j-1 == len) j-=1;
      break;
    }
  }

  /*
   * some encoders are broken with respect to encoding the last line of
   * a file and produce extraoneous characters beyond the expected EOL
   * So were not too picky here about the last line, as long as it's longer
   * than necessary and shorter than the maximum
   * this tolerance broke the xxdecoding, because xxencoded data was
   * detected as being uuencoded :( so don't accept 'h' as first character
   * also, if the first character is lowercase, don't accept the line to
   * have space characters. the only encoder I've heard of which uses
   * lowercase characters at least accepts the special case of encoding
   * 0 as `. The strchr() shouldn't be too expensive here as it's only
   * evaluated if the first character is lowercase, which really shouldn't
   * be in uuencoded text.
   */
  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 */
  }

  if (len != j || islower (*ptr)) {
    /*
     * if we are not in a 'uuencoded' state, don't allow the line to have
     * space characters at all. if we know we _are_ decoding uuencoded
     * data, the rest of the line, beyond the length of encoded data, may
     * have spaces.
     */
    if (encoding != UU_ENCODED)
      if (strchr (ptr, ' ') != NULL)
	goto _t_XX;

/*  suspicious = 1;    we're careful here REMOVED 0.4.15 __FP__ */
    len        = j;
  }

  while (len--) {
    if (*s < 0 || UUxlat[ACAST(*s++)] < 0) {
      if (encoding==UU_ENCODED) return 0;
      goto _t_XX;           /* bad code character */
    }
    if (*s == ' ' && suspicious) {
      if (encoding==UU_ENCODED) return 0;
      goto _t_XX;           /* this line looks _too_ suspicious */
    }
  }
  return UU_ENCODED;        /* data is valid */

 _t_XX:                     /* XX Test */
  len = i; s = ptr;

  if (XXxlat[ACAST(*s)] == -1)
    return 0;

  j = UUxlen[XXxlat[ACAST(*s)]];   /* Same line length table as UUencoding */

  if (len-1 == j)	    /* remove trailing character */
    len--;
  if (len != j)
    switch (UUxlat[ACAST(*s)]%3) {
    case 1:
      if (j-2 == len) j-=2;
      break;
    case 2:
      if (j-1 == len) j-=1;
      break;
    }
  /*
   * some encoders are broken with respect to encoding the last line of
   * a file and produce extraoneous characters beyond the expected EOL
   * So were not too picky here about the last line, as long as it's longer
   * than necessary and shorter than the maximum
   */
  if (len != j && !(*ptr != 'h' && len > j && len <= UUxlen[UUxlat['h']]))
    return 0;               /* bad length */

  while(len--) {
    if(*s < 0 || XXxlat[ACAST(*s++)] < 0) {
      return 0;             /* bad code character */
    }
  }
  return XX_ENCODED;        /* data is valid */
}

/*
 * This function may be called upon a line that does not look like
 * valid encoding on first sight, but might be erroneously encoded
 * data from Netscape, Lynx or MS Exchange. We might need to read
 * a new line from the stream, which is why we need the FILE.
 * Returns the type of encoded data if successful or 0 otherwise.
 */

int
UURepairData (FILE *datei, char *line, int encoding, int *bhflag)
{
  int nflag, vflag=0, safety=42;
  char *ptr;

  nflag = UUBrokenByNetscape (line);

  while (vflag == 0 && nflag && safety--) {
    if (nflag == 1) {		/* need next line to repair */
      if (strlen (line) > 250)
	break;
      ptr = line + strlen (line);
      if (_FP_fgets (ptr, 299-(ptr-line), datei) == NULL)
	break;
    }
    else {			/* don't need next line to repair */
    }
    if (UUNetscapeCollapse (line)) {
      if ((vflag = UUValidData (line, encoding, bhflag)) == 0)
	nflag = UUBrokenByNetscape (line);
    }
    else
      nflag = 0;
  }
  /*
   * Sometimes, a line is garbled even without it being split into
   * 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);
    *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_t
UUDecodeLine (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
 */

int
UUDecodeQP (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)> 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]) {
          d[count++] = '\012';
	}
	else {
	  d[count++] = *s++;
	}
      }
    }
  }
  else {
    return -1;
  }

  d[count] = '\0';
  return count;
}

int
UUDecodePart (FILE *datain, FILE *dataout, int *state,
	      long maxpos, int method, int flags,
	      char *boundary)
{
  char *line, *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, yenotlastpart=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) 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[1200 - 1] = '\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, "
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 ((ptr =_FP_strstr (line, " part="))) {
          int partno = atoi (ptr + 6);
       
	  if ((ptr = _FP_strstr (line, " total=")))
            yenotlastpart = atoi (ptr + 7) != partno;

	  if (_FP_fgets (line, 1200 - 5, datain) == NULL) {
	    break;
	  }

	  if ((ptr = _FP_strstr (line, " end=")) == NULL) {
	    break;
	  }

	  yepartends = atoi (ptr + 5);
	}
	tf = 1;
	continue;
      }
      else {
	continue;
      }
      
      tc = tf = vlc = 0;
      lc[0] = lc[1] = 0;
    }
    else if ((*state == END || *state == DATA) &&
	     (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 (!yenotlastpart && (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) {
	    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, 1200);
	}

	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; tfthisfile == 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          */

#ifdef HAVE_MKSTEMP
  if ((getuid()==geteuid()) && (getgid()==getegid())) {
	  tmpdir=getenv("TMPDIR");
  }

  if (!tmpdir) {
	  tmpdir = "/tmp";
  }
  data->binfile = malloc(strlen(tmpdir)+strlen(tmpprefix)+2);

  if (!data->binfile) {
#else
  if ((data->binfile = tempnam (NULL, "uu")) == NULL) {
#endif /* HAVE_MKSTEMP */
    UUMessage (uunconc_id, __LINE__, UUMSG_ERROR,
	       uustring (S_NO_TEMP_NAME));
    return UURET_NOMEM;
  }

#ifdef HAVE_MKSTEMP
  strcpy(data->binfile, tmpdir);
  strcat(data->binfile, "/");
  strcat(data->binfile, tmpprefix);

  if ((tmpfd = mkstemp(data->binfile)) == -1 || 
	  (dataout = fdopen(tmpfd, mode)) == NULL) {
#else
  if ((dataout = fopen (data->binfile, mode)) == NULL) {
#endif /* HAVE_MKSTEMP */
    /*
     * 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));
#ifdef HAVE_MKSTEMP
	if (tmpfd != -1) {
		unlink(data->binfile);
		close(tmpfd);
    }
#endif /* HAVE_MKSTEMP */
    _FP_free (data->binfile);
    data->binfile = NULL;
    uu_errno = errno;
    return UURET_IOERR;
  }
  UUSETBUF (dataout, dataout_buf, uu_wbuf);

  /*
   * 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);
    }
    UUSETBUF (datain, datain_buf, uu_rbuf);

    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);
    UUCLRBUF (uu_rbuf, datain_buf);

    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;
  }
  UUCLRBUF (uu_wbuf, dataout_buf);

  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) {
#ifdef HAVE_MKSTEMP
	  ntmp = malloc(strlen(tmpdir)+strlen(tmpprefix)+2);
	  
	  if (ntmp == NULL) {
#else
    if ((ntmp = tempnam (NULL, "uu")) == NULL) {
#endif /* HAVE_MKSTEMP */
      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;
    }
    UUSETBUF (datain, datain_buf, uu_rbuf);

#ifdef HAVE_MKSTEMP
    strcpy(ntmp, tmpdir);
    strcat(ntmp, "/");
    strcat(ntmp, tmpprefix); 
    if ((tmpfd = mkstemp(ntmp)) == -1 ||
		(dataout = fdopen(tmpfd, "wb")) == NULL) {
#else
    if ((dataout = fopen (ntmp, "wb")) == NULL) {
#endif /* HAVE_MKSTEMP */
      UUMessage (uunconc_id, __LINE__, UUMSG_ERROR,
		 uustring (S_NOT_OPEN_TARGET),
		 ntmp, strerror (uu_errno = errno));
      progress.action = 0;
      fclose (datain);
      UUCLRBUF (uu_rbuf, datain_buf);
#ifdef HAVE_MKSTEMP
	  if (tmpfd != -1) {
		  unlink(ntmp);
		  close(tmpfd);
	  }
#endif /* HAVE_MKSTEMP */
      free   (ntmp);
      return UURET_IOERR;
    }
    UUSETBUF (dataout, dataout_buf, uu_wbuf);

    /*
     * read fork lengths. remember they're in Motorola format
     */
    r[0] = _FP_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);
        UUCLRBUF (uu_rbuf, datain_buf);
	fclose (dataout);
        UUCLRBUF (uu_wbuf, dataout_buf);
	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);
        UUCLRBUF (uu_rbuf, datain_buf);
	fclose (dataout);
        UUCLRBUF (uu_wbuf, dataout_buf);
	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);
        UUCLRBUF (uu_rbuf, datain_buf);
	fclose (dataout);
        UUCLRBUF (uu_wbuf, dataout_buf);
	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);
    UUCLRBUF (uu_rbuf, datain_buf);
    if (fclose (dataout)) {
      UUCLRBUF (uu_wbuf, dataout_buf);
      UUMessage (uunconc_id, __LINE__, UUMSG_ERROR,
		 uustring (S_WR_ERR_TARGET),
		 ntmp, strerror (uu_errno = errno));
      unlink (ntmp);
      free   (ntmp);
      return UURET_IOERR;
    }
    UUCLRBUF (uu_wbuf, dataout_buf);

    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.
 */

int
UUQuickDecode (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);
}
Convert-UUlib-1.5/uulib/config.h.in0000644000000000000000000000425111244424414015660 0ustar  rootroot/* config.h.in.  Generated automatically from configure.in by autoheader 2.13.  */

/* Define to `unsigned' if  doesn't define.  */
#undef size_t

/* Define if you have the ANSI C header files.  */
#undef STDC_HEADERS

/* Define if you can safely include both  and .  */
#undef TIME_WITH_SYS_TIME

/*
 * If your system is kinda special
 */
#undef SYSTEM_DOS
#undef SYSTEM_QUICKWIN
#undef SYSTEM_WINDLL
#undef SYSTEM_OS2

/*
 * If your system has stdin/stdout/stderr
 */
#undef HAVE_STDIO

/*
 * how to declare functions that are exported from the UU library
 */
#undef UUEXPORT

/*
 * how to declare functions that are exported from the fptools library
 */
#undef TOOLEXPORT

/*
 * define if your compiler supports function prototypes
 */
#undef PROTOTYPES

/*
 * define if your system has chmod(2)
 */
#undef HAVE_CHMOD

/*
 * define if your system has umask(2)
 */
#undef HAVE_UMASK

/*
 * define if your system has mkstemp
 */
#undef HAVE_MKSTEMP

/*
 * Replacement functions.
 * #define strerror _FP_strerror
 * #define tempnam  _FP_tempnam
 * if you don't have these functions
 */
#undef strerror
#undef tempnam

/* Define if you have the fgetc_unlocked function.  */
#undef HAVE_FGETC_UNLOCKED

/* Define if you have the gettimeofday function.  */
#undef HAVE_GETTIMEOFDAY

/* Define if you have the strcasecmp function.  */
#undef HAVE_STRCASECMP

/* Define if you have the strcasestr function.  */
#undef HAVE_STRCASESTR

/* Define if you have the strncasecmp function.  */
#undef HAVE_STRNCASECMP

/* Define if you have the  header file.  */
#undef HAVE_ERRNO_H

/* Define if you have the  header file.  */
#undef HAVE_FCNTL_H

/* Define if you have the  header file.  */
#undef HAVE_IO_H

/* Define if you have the  header file.  */
#undef HAVE_MALLOC_H

/* Define if you have the  header file.  */
#undef HAVE_MEMORY_H

/* Define if you have the  header file.  */
#undef HAVE_STDARG_H

/* Define if you have the  header file.  */
#undef HAVE_SYS_TIME_H

/* Define if you have the  header file.  */
#undef HAVE_UNISTD_H

/* Define if you have the  header file.  */
#undef HAVE_VARARGS_H
Convert-UUlib-1.5/uulib/uustring.c0000644000000000000000000001211210626047043015656 0ustar  rootroot/*
 * This file is part of uudeview, the simple and friendly multi-part multi-
 * 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
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 */

/*
 * Strings used in the library for easier translation etc.
 */

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#ifdef SYSTEM_WINDLL
#include 
#endif
#ifdef SYSTEM_OS2
#include 
#endif

#include 
#include 

#ifdef STDC_HEADERS
#include 
#include 
#endif
#ifdef HAVE_MALLOC_H
#include 
#endif
#ifdef HAVE_UNISTD_H
#include 
#endif
#ifdef HAVE_MEMORY_H
#include 
#endif

#include 
#include 
#include 

char * uustring_id = "$Id$";

typedef struct {
  int code;
  char * msg;
} stringmap;

/*
 * Map of messages. This table is not exported, the messages must
 * be retrieved via the below uustring() function.
 */

static stringmap messages[] = {
  /* I/O related errors/messages. Last parameter is strerror() */
  { S_NOT_OPEN_SOURCE,  "Could not open source file %s: %s" },
  { S_NOT_OPEN_TARGET,  "Could not open target file %s for writing: %s" },
  { S_NOT_OPEN_FILE,    "Could not open file %s: %s" },
  { S_NOT_STAT_FILE,    "Could not stat file %s: %s" },
  { S_SOURCE_READ_ERR,  "Read error on source file: %s" },
  { S_READ_ERROR,       "Error reading from %s: %s" },
  { S_IO_ERR_TARGET,    "I/O error on target file %s: %s" },
  { S_WR_ERR_TARGET,    "Write error on target file %s: %s" },
  { S_WR_ERR_TEMP,      "Write error on temp file: %s" },
  { S_TMP_NOT_REMOVED,  "Could not remove temp file %s: %s (ignored)" },

  /* some other problems */
  { S_OUT_OF_MEMORY,    "Out of memory allocating %d bytes" },
  { S_TARGET_EXISTS,    "Target file %s exists and overwriting is not allowed" },
  { S_NOT_RENAME,       "Could not change name of %s to %s" },
  { S_ERR_ENCODING,     "Error while encoding %s: %s" },
  { S_STAT_ONE_PART,    "Could not stat input, encoding to one part only" },
  { S_PARM_CHECK,       "Parameter check failed in %s" },
  { S_SHORT_BINHEX,     "BinHex encoded file %s ended prematurely (%ld bytes left)" },
  { S_DECODE_CANCEL,    "Decode operation canceled" },
  { S_ENCODE_CANCEL,    "Encode operation canceled" },
  { S_SCAN_CANCEL,      "Scanning canceled" },
  { S_SIZE_MISMATCH,    "%s: Decoded size (%ld) does not match expected size (%ld)" },
  { S_PSIZE_MISMATCH,   "%s part %d: Decoded size (%ld) does not match expected size (%ld)" },
  { S_CRC_MISMATCH,     "CRC32 mismatch in %s. Decoded file probably corrupt." },
  { S_PCRC_MISMATCH,    "PCRC32 mismatch in %s part %d. Decoded file probably corrupt." },

  /* informational messages */
  { S_LOADED_PART,      "Loaded from %s: '%s' (%s): %s part %d %s %s %s" },
  { S_NO_DATA_FOUND,    "No encoded data found in %s" },
  { S_NO_BIN_FILE,      "Oops, could not find decoded file?" },
  { S_STRIPPED_SETUID,  "Stripped setuid/setgid bits from target file %s mode %d" },
  { S_DATA_SUSPICIOUS,  "Data looks suspicious. Decoded file might be corrupt." },
  { S_NO_TEMP_NAME,     "Could not get name for temporary file" },
  { S_BINHEX_SIZES,     "BinHex file: data/resource fork sizes %ld/%ld" },
  { S_BINHEX_BOTH,      "BinHex file: both forks non-empty, decoding data fork" },
  { S_SMERGE_MERGED,    "Parts of '%s' merged with parts of '%s' (%d)" },
  
  /* MIME-related messages */
  { S_MIME_NO_BOUNDARY, "Multipart message without boundary ignored" },
  { S_MIME_B_NOT_FOUND, "Boundary expected on Multipart message but found EOF" },
  { S_MIME_MULTI_DEPTH, "Multipart message nested too deep" },
  { S_MIME_PART_MULTI,  "Handling partial multipart message as plain text" },

  { 0, "" }
};

/*
 * description of the return values UURET_*
 */

char *uuretcodes[] = {
  "OK",
  "File I/O Error",
  "Not Enough Memory",
  "Illegal Value",
  "No Data found",
  "Unexpected End of File",
  "Unsupported function",
  "File exists",
  "Continue -- no error",	/* only to be seen internally */
  "Operation Canceled"
};

/*
 * Names of encoding types
 */

char *codenames[8] = {
  "", "UUdata", "Base64", "XXdata", "Binhex", "Text", "Text", "yEnc"
};

/*
 * Message types
 */

char *msgnames[6] = {
  "", "Note: ", "Warning: ", "ERROR: ", "FATAL ERROR: ", "PANIC: "
};

/*
 * Retrieve one of the messages. We never return NULL
 * but instead escape to "oops".
 */

char *
uustring (int codeno)
{
  static char * faileddef = "oops";
  stringmap *ptr = messages;

  while (ptr->code) {
    if (ptr->code == codeno)
      return ptr->msg;
    ptr++;
  }

  UUMessage (uustring_id, __LINE__, UUMSG_ERROR,
	     "Could not retrieve string no %d",
	     codeno);

  return faileddef;
}
Convert-UUlib-1.5/uulib/uuutil.c0000644000000000000000000002344411244421252015332 0ustar  rootroot/*
 * This file is part of uudeview, the simple and friendly multi-part multi-
 * 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
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 */

/*
 * certain utilitarian functions that didn't fit anywhere else
 */

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#ifdef SYSTEM_WINDLL
#include 
#endif
#ifdef SYSTEM_OS2
#include 
#endif

#include 
#include 

#ifdef STDC_HEADERS
#include 
#include 
#endif
#ifdef HAVE_MALLOC_H
#include 
#endif
#ifdef HAVE_UNISTD_H
#include 
#endif
#ifdef HAVE_MEMORY_H
#include 
#endif
#ifdef HAVE_ERRNO_H
#include 
#endif

#include 
#include 
#include 
#include 

char * uuutil_id = "$Id$";

/*
 * Parts with different known extensions will not be merged by SPMS.
 * if first character is '@', it is synonymous to the previous one.
 */

static char *knownexts[] = {
  "mpg", "@mpeg", "avi", "mov",
  "gif", "jpg", "@jpeg", "tif",
  "voc", "wav", "@wave", "au",
  "zip", "arj", "tar",
  NULL
};

/*
 * forward declarations of local functions
 */

static int	UUSMPKnownExt		(char *filename);
static uulist *	UU_smparts_r		(uulist *, int);

/*
 * mallocable areas
 */

char *uuutil_bhwtmp;

/*
 * free some memory
 **/

void
UUkillfread (fileread *data)
{
  if (data != NULL) {
    _FP_free (data->subject);
    _FP_free (data->filename);
    _FP_free (data->origin);
    _FP_free (data->mimeid);
    _FP_free (data->mimetype);
    _FP_free (data->sfname);
    _FP_free (data);
  }
}

void
UUkillfile (uufile *data)
{
  uufile *next;

  while (data) {
    _FP_free    (data->filename);
    _FP_free    (data->subfname);
    _FP_free    (data->mimeid);
    _FP_free    (data->mimetype);
    UUkillfread (data->data);

    next = data->NEXT;
    _FP_free  (data);
    data = next;
  }
}

void
UUkilllist (uulist *data)
{
  uulist *next;

  while (data) {
    if (data->binfile != NULL)
      if (unlink (data->binfile))
	UUMessage (uuutil_id, __LINE__, UUMSG_WARNING,
		   uustring (S_TMP_NOT_REMOVED),
		   data->binfile, strerror (errno));

    _FP_free   (data->filename);
    _FP_free   (data->subfname);
    _FP_free   (data->mimeid);
    _FP_free   (data->mimetype);
    _FP_free   (data->binfile);
    UUkillfile (data->thisfile);
    _FP_free   (data->haveparts);
    _FP_free   (data->misparts);

    next = data->NEXT;
    _FP_free (data);
    data = next;
  }
}

/*
 * this kill function is an exception in that it doesn't kill data itself
 */

void
UUkillheaders (headers *data)
{
  if (data != NULL) {
    _FP_free (data->from);
    _FP_free (data->subject);
    _FP_free (data->rcpt);
    _FP_free (data->date);
    _FP_free (data->mimevers);
    _FP_free (data->ctype);
    _FP_free (data->ctenc);
    _FP_free (data->fname);
    _FP_free (data->boundary);
    _FP_free (data->mimeid);
    memset   (data, 0, sizeof (headers));
  }
}

/*
 * checks for various well-known extensions. if two parts have different
 * known extensions, we won't merge them.
 */

static int
UUSMPKnownExt (char *filename)
{
  char **eiter = knownexts, *ptr=_FP_strrchr(filename, '.');
  int count=0, where=0;

  if (ptr == NULL)
    return -1;
  ptr++;

  while (*eiter) {
    if (_FP_stricmp (ptr, (**eiter=='@')?*eiter+1:*eiter) == 0)
      return where;
    else
      eiter++;

    if (*eiter == NULL)
      break;

    if (**eiter=='@')
      count++;
    else
      where = ++count;
  }
  return -1;
}

/*
 * de-compress a binhex RLE stream
 * the data read from in is uncompressed, and at most maxcount bytes
 * (or octets, as they say) are copied to out. Because an uncompression
 * might not be completed because of this maximum number of bytes. There-
 * for, the leftover character and repetition count is saved. If a marker
 * has been read but not the repetition count, *rpc is set to -256.
 *
 * the function returns the number of bytes eaten from in. If opc is not
 * NULL, the total number of characters stored in out is saved there
 *
 * with repetition counts, remember that we've already transferred *one*
 * occurence
 */

int
UUbhdecomp (char *in, char *out, char *last, int *rpc, 
	    size_t inc, size_t max, size_t *opc)
{
  size_t count, used=0, dummy;
  char marker = '\220' /* '\x90' */;

  if (opc == NULL)
    opc = &dummy;
  else
    *opc = 0;

  if (*rpc == -256) {
    if (inc == 0)
      return 0;
    *rpc = (int) (unsigned char) *in++; used++;

    if (*rpc == 0) {
      *last = *out++ = marker;
      max--; *opc+=1;
    }
    else
      *rpc-=1;
  }

  if (*rpc) {
    count = (max > (size_t) *rpc) ? (size_t) *rpc : max;

    memset (out, *last, count);

    out  += count;
    *opc += count;
    max  -= count;
    *rpc -= count;
  }

  while (used < inc && max) {
    if (*in == marker) {
      used++; in++;
      if (used == inc) {
	*rpc = -256;
	return used;
      }
      *rpc = (int) (unsigned char) *in++; used++;

      if (*rpc == 0) {
	*last = *out++ = marker;
	max--; *opc+=1;
	continue;
      }
      else
	*rpc -= 1;

      count = (max > (size_t) *rpc) ? (size_t) *rpc : max;
      memset (out, *last, count);

      out  += count;
      *opc += count;
      max  -= count;
      *rpc -= count;
    }
    else {
      *last = *out++ = *in++;
      used++; *opc+=1; max--;
    }
  }

  return used;
}

/*
 * write to binhex file
 */

size_t
UUbhwrite (char *ptr, size_t sel, size_t nel, FILE *file)
{
  char *tmpstring=uuutil_bhwtmp;
  static int rpc = 0;
  static char lc;
  int count, tc=0;
  size_t opc;

  if (ptr == NULL) { /* init */
    rpc = 0;
    return 0;
  }

  while (nel || (rpc != 0 && rpc != -256)) {
    count = UUbhdecomp (ptr, tmpstring, &lc, &rpc,
			nel, 256, &opc);
    if (fwrite (tmpstring, 1, opc, file) != opc)
      return 0;
    if (ferror (file))
      return 0;
    nel -= count;
    ptr += count;
    tc  += count;
  }

  return tc;
}

static uulist *
UU_smparts_r (uulist *addit, int pass)
{
  uulist *iter = UUGlobalFileList;
  uufile *fiter, *dest, *temp;
  int count, flag, a, b;

  while (iter) {
    if ((iter->state & UUFILE_OK) || iter->uudet == 0) {
      iter = iter->NEXT;
      continue;
    }
    if (iter == addit) {
      iter = iter->NEXT;
      continue;
    }
    if ((iter->begin && addit->begin) || (iter->end && addit->end) ||
	(iter->uudet != addit->uudet)) {
      iter = iter->NEXT;
      continue;
    }
    if ((a = UUSMPKnownExt (addit->subfname)) != -1 &&
        (b = UUSMPKnownExt (iter->subfname))  != -1)
      if (a != b) {
        iter = iter->NEXT;
        continue;
      }

    flag  = count = 0;
    fiter = iter->thisfile;
    temp  = addit->thisfile;
    dest  = NULL;

    while (temp) {
      if (!(temp->data->uudet)) {
	temp = temp->NEXT;
	continue;
      }

      while (fiter && fiter->partno < temp->partno) {
        dest  = fiter;
        fiter = fiter->NEXT;
      }
      if (fiter && fiter->partno == temp->partno) {
        flag = 0;
        break;
      }
      else {
	flag   = 1;
        count += ((dest)  ? temp->partno - dest->partno - 1 : 0) +
                 ((fiter) ? fiter->partno - temp->partno - 1 : 0);
      }

      temp = temp->NEXT;
    }
    if (flag == 0 ||
        (pass == 0 && count > 0) ||
        (pass == 1 && count > 5)) {
      iter = iter->NEXT;
      continue;
    }

    dest  = iter->thisfile;
    fiter = addit->thisfile;

    if (iter->filename == NULL && addit->filename != NULL)
      iter->filename = _FP_strdup (addit->filename);

    if (addit->begin) iter->begin = 1;
    if (addit->end)   iter->end   = 1;

    if (addit->mode != 0 && iter->mode == 0)
      iter->mode = addit->mode;

    while (fiter) {
      flag = 0;

      if (fiter->partno == iter->thisfile->partno ||
	  (dest->NEXT != NULL && fiter->partno == dest->NEXT->partno)) {
	temp           = fiter->NEXT;
	fiter->NEXT    = NULL;

	UUkillfile (fiter);

	addit->thisfile= temp;
	fiter          = temp;
	continue;
      }
      if (fiter->partno < iter->thisfile->partno) {
	temp           = fiter->NEXT;
	fiter->NEXT    = iter->thisfile;
	iter->thisfile = fiter;
	dest           = fiter;
	addit->thisfile= temp;
	fiter          = temp;
      }
      else if (dest->NEXT == NULL || fiter->partno < dest->NEXT->partno) {
	temp           = fiter->NEXT;
	fiter->NEXT    = dest->NEXT;
	dest->NEXT     = fiter;
	addit->thisfile= temp;
	fiter          = temp;
      }
      else {
	dest = dest->NEXT;
      }
    }
    break;
  }
  return iter;
}

int UUEXPORT
UUSmerge (int pass)
{
  uulist *iter = UUGlobalFileList, *last=NULL, *res, *temp;
  int flag = 0;

  if (pass >= 0)
    {
      while (iter) {
        if ((iter->state & UUFILE_OK) || iter->uudet == 0) {
          last = iter;
          iter = iter->NEXT;
          continue;
        }
        if ((res = UU_smparts_r (iter, pass)) != NULL) {
          UUMessage (uuutil_id, __LINE__, UUMSG_MESSAGE,
		     uustring (S_SMERGE_MERGED),
		     (iter->subfname) ? iter->subfname : "",
		     (res->subfname)  ? res->subfname  : "", pass);
     
          temp       = iter->NEXT;
          iter->NEXT = NULL;
          UUkilllist (iter);

          flag++;

          if (last == NULL) {
	    UUGlobalFileList = temp;
	    iter             = temp;
          }
          else {
	    last->NEXT       = temp;
	    iter             = temp;
          }

          continue;
        }
        last = iter;
        iter = iter->NEXT;
      }
    }

  /*
   * check again
   */

  UUCheckGlobalList ();

  return flag;
}

Convert-UUlib-1.5/uulib/fptools.h0000644000000000000000000000506711253744111015501 0ustar  rootroot/*
 * fptools.c, some helper functions for getcgi.c and uu(en|de)view
 *
 * Distributed under the terms of the GNU General Public License.
 * Use and be happy.
 */

/*
 * Some handy, nonstandard functions. Note that the original may
 * be both faster and better. ``better'', if your compiler allows
 * cleaner use of such functions by proper use of ``const''.
 *
 * $Id$
 */

#ifndef FPTOOLS_H__
#define FPTOOLS_H__

#include 

typedef signed char schar;
typedef unsigned char uchar;

#ifndef TOOLEXPORT
#define TOOLEXPORT
#endif

#ifdef __cplusplus
extern "C" {
#endif

#define _FP_free	FP_free
#define _FP_strdup	FP_strdup
#define _FP_strncpy	FP_strncpy
#define _FP_memdup	FP_memdup
#define _FP_stricmp	FP_stricmp
#define _FP_strnicmp	FP_strnicmp
#define _FP_strrstr	FP_strrstr
#define _FP_stoupper	FP_stoupper
#define _FP_stolower	FP_stolower
#define _FP_strmatch	FP_strmatch
#define _FP_strstr	FP_strstr
#define _FP_stristr	FP_stristr
#define _FP_strirstr	FP_strirstr
#define _FP_strrchr	FP_strrchr
#define _FP_fgets	FP_fgets
#define _FP_strpbrk	FP_strpbrk
#define _FP_strtok	FP_strtok
#define _FP_cutdir	FP_cutdir
#define _FP_strerror	FP_strerror
#define _FP_tempnam	FP_tempnam
#define _FP_fgetc	FP_fgetc

#if HAVE_FGETC_UNLOCKED
# define FP_fgetc(s) fgetc_unlocked (s)
#else
# define FP_fgetc(s) fgetc (s)
#endif

#define FP_strstr(a,b) strstr (a, b)

void	TOOLEXPORT	_FP_free	(void *);
char *	TOOLEXPORT	_FP_strdup	(char *);
char *	TOOLEXPORT	_FP_strncpy	(char *, char *, int);
void *	TOOLEXPORT	_FP_memdup	(void *, int);
int 	TOOLEXPORT	_FP_stricmp	(char *, char *);
int 	TOOLEXPORT	_FP_strnicmp	(char *, char *, int);
char *	TOOLEXPORT	_FP_strrstr	(char *, char *);
char *	TOOLEXPORT	_FP_stoupper	(char *);
char *	TOOLEXPORT	_FP_stolower	(char *);
int 	TOOLEXPORT	_FP_strmatch	(char *, char *);
char *	TOOLEXPORT	_FP_stristr	(char *, char *);
char *	TOOLEXPORT	_FP_strirstr	(char *, char *);
char *	TOOLEXPORT	_FP_strrchr	(char *, int);
char *	TOOLEXPORT	_FP_fgets	(char *, int, FILE *);
char *	TOOLEXPORT	_FP_strpbrk	(char *, char *);
char *	TOOLEXPORT	_FP_strtok	(char *, char *);
char *	TOOLEXPORT	_FP_cutdir	(char *);
char *	TOOLEXPORT	_FP_strerror	(int);
#ifndef HAVE_MKSTEMP
char *	TOOLEXPORT	_FP_tempnam	(char *, char *);
#endif /* HAVE_MKSTEMP */

#if 0 /* API differs too much between systems to make those replacements */
#if HAVE_STRCASECMP
# define FP_stricmp(a,b) strcasecmp (a, b)
#endif

#if HAVE_STRNCASECMP
# define FP_strnicmp(a,b,l) strncasecmp (a, b, l)
#endif

#if HAVE_STRCASESTR
# define FP_stristr(a,b) strcasestr (a, b)
#endif
#endif

#ifdef __cplusplus
}
#endif
#endif

Convert-UUlib-1.5/uulib/configure0000755000000000000000000016404011253744143015553 0ustar  rootroot#! /bin/sh

# Guess values for system-dependent variables and create Makefiles.
# Generated automatically using autoconf version 2.13 
# Copyright (C) 1992, 93, 94, 95, 96 Free Software Foundation, Inc.
#
# This configure script is free software; the Free Software Foundation
# gives unlimited permission to copy, distribute and modify it.

# Defaults:
ac_help=
ac_default_prefix=/usr/local
# Any additions from configure.in:
ac_help="$ac_help
"
ac_help="$ac_help
"

# Initialize some variables set by options.
# The variables have the same names as the options, with
# dashes changed to underlines.
build=NONE
cache_file=./config.cache
exec_prefix=NONE
host=NONE
no_create=
nonopt=NONE
no_recursion=
prefix=NONE
program_prefix=NONE
program_suffix=NONE
program_transform_name=s,x,x,
silent=
site=
srcdir=
target=NONE
verbose=
x_includes=NONE
x_libraries=NONE
bindir='${exec_prefix}/bin'
sbindir='${exec_prefix}/sbin'
libexecdir='${exec_prefix}/libexec'
datadir='${prefix}/share'
sysconfdir='${prefix}/etc'
sharedstatedir='${prefix}/com'
localstatedir='${prefix}/var'
libdir='${exec_prefix}/lib'
includedir='${prefix}/include'
oldincludedir='/usr/include'
infodir='${prefix}/info'
mandir='${prefix}/man'

# Initialize some other variables.
subdirs=
MFLAGS= MAKEFLAGS=
SHELL=${CONFIG_SHELL-/bin/sh}
# Maximum number of lines to put in a shell here document.
ac_max_here_lines=12

ac_prev=
for ac_option
do

  # If the previous option needs an argument, assign it.
  if test -n "$ac_prev"; then
    eval "$ac_prev=\$ac_option"
    ac_prev=
    continue
  fi

  case "$ac_option" in
  -*=*) ac_optarg=`echo "$ac_option" | sed 's/[-_a-zA-Z0-9]*=//'` ;;
  *) ac_optarg= ;;
  esac

  # Accept the important Cygnus configure options, so we can diagnose typos.

  case "$ac_option" in

  -bindir | --bindir | --bindi | --bind | --bin | --bi)
    ac_prev=bindir ;;
  -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*)
    bindir="$ac_optarg" ;;

  -build | --build | --buil | --bui | --bu)
    ac_prev=build ;;
  -build=* | --build=* | --buil=* | --bui=* | --bu=*)
    build="$ac_optarg" ;;

  -cache-file | --cache-file | --cache-fil | --cache-fi \
  | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c)
    ac_prev=cache_file ;;
  -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \
  | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*)
    cache_file="$ac_optarg" ;;

  -datadir | --datadir | --datadi | --datad | --data | --dat | --da)
    ac_prev=datadir ;;
  -datadir=* | --datadir=* | --datadi=* | --datad=* | --data=* | --dat=* \
  | --da=*)
    datadir="$ac_optarg" ;;

  -disable-* | --disable-*)
    ac_feature=`echo $ac_option|sed -e 's/-*disable-//'`
    # Reject names that are not valid shell variable names.
    if test -n "`echo $ac_feature| sed 's/[-a-zA-Z0-9_]//g'`"; then
      { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; }
    fi
    ac_feature=`echo $ac_feature| sed 's/-/_/g'`
    eval "enable_${ac_feature}=no" ;;

  -enable-* | --enable-*)
    ac_feature=`echo $ac_option|sed -e 's/-*enable-//' -e 's/=.*//'`
    # Reject names that are not valid shell variable names.
    if test -n "`echo $ac_feature| sed 's/[-_a-zA-Z0-9]//g'`"; then
      { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; }
    fi
    ac_feature=`echo $ac_feature| sed 's/-/_/g'`
    case "$ac_option" in
      *=*) ;;
      *) ac_optarg=yes ;;
    esac
    eval "enable_${ac_feature}='$ac_optarg'" ;;

  -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \
  | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \
  | --exec | --exe | --ex)
    ac_prev=exec_prefix ;;
  -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \
  | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \
  | --exec=* | --exe=* | --ex=*)
    exec_prefix="$ac_optarg" ;;

  -gas | --gas | --ga | --g)
    # Obsolete; use --with-gas.
    with_gas=yes ;;

  -help | --help | --hel | --he)
    # Omit some internal or obsolete options to make the list less imposing.
    # This message is too long to be a string in the A/UX 3.1 sh.
    cat << EOF
Usage: configure [options] [host]
Options: [defaults in brackets after descriptions]
Configuration:
  --cache-file=FILE       cache test results in FILE
  --help                  print this message
  --no-create             do not create output files
  --quiet, --silent       do not print \`checking...' messages
  --version               print the version of autoconf that created configure
Directory and file names:
  --prefix=PREFIX         install architecture-independent files in PREFIX
                          [$ac_default_prefix]
  --exec-prefix=EPREFIX   install architecture-dependent files in EPREFIX
                          [same as prefix]
  --bindir=DIR            user executables in DIR [EPREFIX/bin]
  --sbindir=DIR           system admin executables in DIR [EPREFIX/sbin]
  --libexecdir=DIR        program executables in DIR [EPREFIX/libexec]
  --datadir=DIR           read-only architecture-independent data in DIR
                          [PREFIX/share]
  --sysconfdir=DIR        read-only single-machine data in DIR [PREFIX/etc]
  --sharedstatedir=DIR    modifiable architecture-independent data in DIR
                          [PREFIX/com]
  --localstatedir=DIR     modifiable single-machine data in DIR [PREFIX/var]
  --libdir=DIR            object code libraries in DIR [EPREFIX/lib]
  --includedir=DIR        C header files in DIR [PREFIX/include]
  --oldincludedir=DIR     C header files for non-gcc in DIR [/usr/include]
  --infodir=DIR           info documentation in DIR [PREFIX/info]
  --mandir=DIR            man documentation in DIR [PREFIX/man]
  --srcdir=DIR            find the sources in DIR [configure dir or ..]
  --program-prefix=PREFIX prepend PREFIX to installed program names
  --program-suffix=SUFFIX append SUFFIX to installed program names
  --program-transform-name=PROGRAM
                          run sed PROGRAM on installed program names
EOF
    cat << EOF
Host type:
  --build=BUILD           configure for building on BUILD [BUILD=HOST]
  --host=HOST             configure for HOST [guessed]
  --target=TARGET         configure for TARGET [TARGET=HOST]
Features and packages:
  --disable-FEATURE       do not include FEATURE (same as --enable-FEATURE=no)
  --enable-FEATURE[=ARG]  include FEATURE [ARG=yes]
  --with-PACKAGE[=ARG]    use PACKAGE [ARG=yes]
  --without-PACKAGE       do not use PACKAGE (same as --with-PACKAGE=no)
  --x-includes=DIR        X include files are in DIR
  --x-libraries=DIR       X library files are in DIR
EOF
    if test -n "$ac_help"; then
      echo "--enable and --with options recognized:$ac_help"
    fi
    exit 0 ;;

  -host | --host | --hos | --ho)
    ac_prev=host ;;
  -host=* | --host=* | --hos=* | --ho=*)
    host="$ac_optarg" ;;

  -includedir | --includedir | --includedi | --included | --include \
  | --includ | --inclu | --incl | --inc)
    ac_prev=includedir ;;
  -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \
  | --includ=* | --inclu=* | --incl=* | --inc=*)
    includedir="$ac_optarg" ;;

  -infodir | --infodir | --infodi | --infod | --info | --inf)
    ac_prev=infodir ;;
  -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*)
    infodir="$ac_optarg" ;;

  -libdir | --libdir | --libdi | --libd)
    ac_prev=libdir ;;
  -libdir=* | --libdir=* | --libdi=* | --libd=*)
    libdir="$ac_optarg" ;;

  -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \
  | --libexe | --libex | --libe)
    ac_prev=libexecdir ;;
  -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \
  | --libexe=* | --libex=* | --libe=*)
    libexecdir="$ac_optarg" ;;

  -localstatedir | --localstatedir | --localstatedi | --localstated \
  | --localstate | --localstat | --localsta | --localst \
  | --locals | --local | --loca | --loc | --lo)
    ac_prev=localstatedir ;;
  -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \
  | --localstate=* | --localstat=* | --localsta=* | --localst=* \
  | --locals=* | --local=* | --loca=* | --loc=* | --lo=*)
    localstatedir="$ac_optarg" ;;

  -mandir | --mandir | --mandi | --mand | --man | --ma | --m)
    ac_prev=mandir ;;
  -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*)
    mandir="$ac_optarg" ;;

  -nfp | --nfp | --nf)
    # Obsolete; use --without-fp.
    with_fp=no ;;

  -no-create | --no-create | --no-creat | --no-crea | --no-cre \
  | --no-cr | --no-c)
    no_create=yes ;;

  -no-recursion | --no-recursion | --no-recursio | --no-recursi \
  | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r)
    no_recursion=yes ;;

  -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \
  | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \
  | --oldin | --oldi | --old | --ol | --o)
    ac_prev=oldincludedir ;;
  -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \
  | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \
  | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*)
    oldincludedir="$ac_optarg" ;;

  -prefix | --prefix | --prefi | --pref | --pre | --pr | --p)
    ac_prev=prefix ;;
  -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*)
    prefix="$ac_optarg" ;;

  -program-prefix | --program-prefix | --program-prefi | --program-pref \
  | --program-pre | --program-pr | --program-p)
    ac_prev=program_prefix ;;
  -program-prefix=* | --program-prefix=* | --program-prefi=* \
  | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*)
    program_prefix="$ac_optarg" ;;

  -program-suffix | --program-suffix | --program-suffi | --program-suff \
  | --program-suf | --program-su | --program-s)
    ac_prev=program_suffix ;;
  -program-suffix=* | --program-suffix=* | --program-suffi=* \
  | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*)
    program_suffix="$ac_optarg" ;;

  -program-transform-name | --program-transform-name \
  | --program-transform-nam | --program-transform-na \
  | --program-transform-n | --program-transform- \
  | --program-transform | --program-transfor \
  | --program-transfo | --program-transf \
  | --program-trans | --program-tran \
  | --progr-tra | --program-tr | --program-t)
    ac_prev=program_transform_name ;;
  -program-transform-name=* | --program-transform-name=* \
  | --program-transform-nam=* | --program-transform-na=* \
  | --program-transform-n=* | --program-transform-=* \
  | --program-transform=* | --program-transfor=* \
  | --program-transfo=* | --program-transf=* \
  | --program-trans=* | --program-tran=* \
  | --progr-tra=* | --program-tr=* | --program-t=*)
    program_transform_name="$ac_optarg" ;;

  -q | -quiet | --quiet | --quie | --qui | --qu | --q \
  | -silent | --silent | --silen | --sile | --sil)
    silent=yes ;;

  -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
    ac_prev=sbindir ;;
  -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
  | --sbi=* | --sb=*)
    sbindir="$ac_optarg" ;;

  -sharedstatedir | --sharedstatedir | --sharedstatedi \
  | --sharedstated | --sharedstate | --sharedstat | --sharedsta \
  | --sharedst | --shareds | --shared | --share | --shar \
  | --sha | --sh)
    ac_prev=sharedstatedir ;;
  -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \
  | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \
  | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \
  | --sha=* | --sh=*)
    sharedstatedir="$ac_optarg" ;;

  -site | --site | --sit)
    ac_prev=site ;;
  -site=* | --site=* | --sit=*)
    site="$ac_optarg" ;;

  -srcdir | --srcdir | --srcdi | --srcd | --src | --sr)
    ac_prev=srcdir ;;
  -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*)
    srcdir="$ac_optarg" ;;

  -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \
  | --syscon | --sysco | --sysc | --sys | --sy)
    ac_prev=sysconfdir ;;
  -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \
  | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*)
    sysconfdir="$ac_optarg" ;;

  -target | --target | --targe | --targ | --tar | --ta | --t)
    ac_prev=target ;;
  -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*)
    target="$ac_optarg" ;;

  -v | -verbose | --verbose | --verbos | --verbo | --verb)
    verbose=yes ;;

  -version | --version | --versio | --versi | --vers)
    echo "configure generated by autoconf version 2.13"
    exit 0 ;;

  -with-* | --with-*)
    ac_package=`echo $ac_option|sed -e 's/-*with-//' -e 's/=.*//'`
    # Reject names that are not valid shell variable names.
    if test -n "`echo $ac_package| sed 's/[-_a-zA-Z0-9]//g'`"; then
      { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; }
    fi
    ac_package=`echo $ac_package| sed 's/-/_/g'`
    case "$ac_option" in
      *=*) ;;
      *) ac_optarg=yes ;;
    esac
    eval "with_${ac_package}='$ac_optarg'" ;;

  -without-* | --without-*)
    ac_package=`echo $ac_option|sed -e 's/-*without-//'`
    # Reject names that are not valid shell variable names.
    if test -n "`echo $ac_package| sed 's/[-a-zA-Z0-9_]//g'`"; then
      { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; }
    fi
    ac_package=`echo $ac_package| sed 's/-/_/g'`
    eval "with_${ac_package}=no" ;;

  --x)
    # Obsolete; use --with-x.
    with_x=yes ;;

  -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \
  | --x-incl | --x-inc | --x-in | --x-i)
    ac_prev=x_includes ;;
  -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \
  | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*)
    x_includes="$ac_optarg" ;;

  -x-libraries | --x-libraries | --x-librarie | --x-librari \
  | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l)
    ac_prev=x_libraries ;;
  -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \
  | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*)
    x_libraries="$ac_optarg" ;;

  -*) { echo "configure: error: $ac_option: invalid option; use --help to show usage" 1>&2; exit 1; }
    ;;

  *)
    if test -n "`echo $ac_option| sed 's/[-a-z0-9.]//g'`"; then
      echo "configure: warning: $ac_option: invalid host type" 1>&2
    fi
    if test "x$nonopt" != xNONE; then
      { echo "configure: error: can only configure for one host and one target at a time" 1>&2; exit 1; }
    fi
    nonopt="$ac_option"
    ;;

  esac
done

if test -n "$ac_prev"; then
  { echo "configure: error: missing argument to --`echo $ac_prev | sed 's/_/-/g'`" 1>&2; exit 1; }
fi

trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15

# File descriptor usage:
# 0 standard input
# 1 file creation
# 2 errors and warnings
# 3 some systems may open it to /dev/tty
# 4 used on the Kubota Titan
# 6 checking for... messages and results
# 5 compiler messages saved in config.log
if test "$silent" = yes; then
  exec 6>/dev/null
else
  exec 6>&1
fi
exec 5>./config.log

echo "\
This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake.
" 1>&5

# Strip out --no-create and --no-recursion so they do not pile up.
# Also quote any args containing shell metacharacters.
ac_configure_args=
for ac_arg
do
  case "$ac_arg" in
  -no-create | --no-create | --no-creat | --no-crea | --no-cre \
  | --no-cr | --no-c) ;;
  -no-recursion | --no-recursion | --no-recursio | --no-recursi \
  | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) ;;
  *" "*|*"	"*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?]*)
  ac_configure_args="$ac_configure_args '$ac_arg'" ;;
  *) ac_configure_args="$ac_configure_args $ac_arg" ;;
  esac
done

# NLS nuisances.
# Only set these to C if already set.  These must not be set unconditionally
# because not all systems understand e.g. LANG=C (notably SCO).
# Fixing LC_MESSAGES prevents Solaris sh from translating var values in `set'!
# Non-C LC_CTYPE values break the ctype check.
if test "${LANG+set}"   = set; then LANG=C;   export LANG;   fi
if test "${LC_ALL+set}" = set; then LC_ALL=C; export LC_ALL; fi
if test "${LC_MESSAGES+set}" = set; then LC_MESSAGES=C; export LC_MESSAGES; fi
if test "${LC_CTYPE+set}"    = set; then LC_CTYPE=C;    export LC_CTYPE;    fi

# confdefs.h avoids OS command line length limits that DEFS can exceed.
rm -rf conftest* confdefs.h
# AIX cpp loses on an empty file, so make sure it contains at least a newline.
echo > confdefs.h

# A filename unique to this package, relative to the directory that
# configure is in, which we can look for to find out if srcdir is correct.
ac_unique_file=uulib.c

# Find the source files, if location was not specified.
if test -z "$srcdir"; then
  ac_srcdir_defaulted=yes
  # Try the directory containing this script, then its parent.
  ac_prog=$0
  ac_confdir=`echo $ac_prog|sed 's%/[^/][^/]*$%%'`
  test "x$ac_confdir" = "x$ac_prog" && ac_confdir=.
  srcdir=$ac_confdir
  if test ! -r $srcdir/$ac_unique_file; then
    srcdir=..
  fi
else
  ac_srcdir_defaulted=no
fi
if test ! -r $srcdir/$ac_unique_file; then
  if test "$ac_srcdir_defaulted" = yes; then
    { echo "configure: error: can not find sources in $ac_confdir or .." 1>&2; exit 1; }
  else
    { echo "configure: error: can not find sources in $srcdir" 1>&2; exit 1; }
  fi
fi
srcdir=`echo "${srcdir}" | sed 's%\([^/]\)/*$%\1%'`

# Prefer explicitly selected file to automatically selected ones.
if test -z "$CONFIG_SITE"; then
  if test "x$prefix" != xNONE; then
    CONFIG_SITE="$prefix/share/config.site $prefix/etc/config.site"
  else
    CONFIG_SITE="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site"
  fi
fi
for ac_site_file in $CONFIG_SITE; do
  if test -r "$ac_site_file"; then
    echo "loading site script $ac_site_file"
    . "$ac_site_file"
  fi
done

if test -r "$cache_file"; then
  echo "loading cache $cache_file"
  . $cache_file
else
  echo "creating cache $cache_file"
  > $cache_file
fi

ac_ext=c
# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
ac_cpp='$CPP $CPPFLAGS'
ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
cross_compiling=$ac_cv_prog_cc_cross

ac_exeext=
ac_objext=o
if (echo "testing\c"; echo 1,2,3) | grep c >/dev/null; then
  # Stardent Vistra SVR4 grep lacks -e, says ghazi@caip.rutgers.edu.
  if (echo -n testing; echo 1,2,3) | sed s/-n/xn/ | grep xn >/dev/null; then
    ac_n= ac_c='
' ac_t='	'
  else
    ac_n=-n ac_c= ac_t=
  fi
else
  ac_n= ac_c='\c' ac_t=
fi





#
# package revision
#
VERSION=0.5
PATCH=20

# Check whether --with-cc or --without-cc was given.
if test "${with_cc+set}" = set; then
  withval="$with_cc"
  CC=$with_cc
fi

# Check whether --with-cflags or --without-cflags was given.
if test "${with_cflags+set}" = set; then
  withval="$with_cflags"
  CFLAGS=$with_cflags
fi


# Extract the first word of "gcc", so it can be a program name with args.
set dummy gcc; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
echo "configure:554: checking for $ac_word" >&5
if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  if test -n "$CC"; then
  ac_cv_prog_CC="$CC" # Let the user override the test.
else
  IFS="${IFS= 	}"; ac_save_ifs="$IFS"; IFS=":"
  ac_dummy="$PATH"
  for ac_dir in $ac_dummy; do
    test -z "$ac_dir" && ac_dir=.
    if test -f $ac_dir/$ac_word; then
      ac_cv_prog_CC="gcc"
      break
    fi
  done
  IFS="$ac_save_ifs"
fi
fi
CC="$ac_cv_prog_CC"
if test -n "$CC"; then
  echo "$ac_t""$CC" 1>&6
else
  echo "$ac_t""no" 1>&6
fi

if test -z "$CC"; then
  # Extract the first word of "cc", so it can be a program name with args.
set dummy cc; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
echo "configure:584: checking for $ac_word" >&5
if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  if test -n "$CC"; then
  ac_cv_prog_CC="$CC" # Let the user override the test.
else
  IFS="${IFS= 	}"; ac_save_ifs="$IFS"; IFS=":"
  ac_prog_rejected=no
  ac_dummy="$PATH"
  for ac_dir in $ac_dummy; do
    test -z "$ac_dir" && ac_dir=.
    if test -f $ac_dir/$ac_word; then
      if test "$ac_dir/$ac_word" = "/usr/ucb/cc"; then
        ac_prog_rejected=yes
	continue
      fi
      ac_cv_prog_CC="cc"
      break
    fi
  done
  IFS="$ac_save_ifs"
if test $ac_prog_rejected = yes; then
  # We found a bogon in the path, so make sure we never use it.
  set dummy $ac_cv_prog_CC
  shift
  if test $# -gt 0; then
    # We chose a different compiler from the bogus one.
    # However, it has the same basename, so the bogon will be chosen
    # first if we set CC to just the basename; use the full file name.
    shift
    set dummy "$ac_dir/$ac_word" "$@"
    shift
    ac_cv_prog_CC="$@"
  fi
fi
fi
fi
CC="$ac_cv_prog_CC"
if test -n "$CC"; then
  echo "$ac_t""$CC" 1>&6
else
  echo "$ac_t""no" 1>&6
fi

  if test -z "$CC"; then
    case "`uname -s`" in
    *win32* | *WIN32*)
      # Extract the first word of "cl", so it can be a program name with args.
set dummy cl; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
echo "configure:635: checking for $ac_word" >&5
if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  if test -n "$CC"; then
  ac_cv_prog_CC="$CC" # Let the user override the test.
else
  IFS="${IFS= 	}"; ac_save_ifs="$IFS"; IFS=":"
  ac_dummy="$PATH"
  for ac_dir in $ac_dummy; do
    test -z "$ac_dir" && ac_dir=.
    if test -f $ac_dir/$ac_word; then
      ac_cv_prog_CC="cl"
      break
    fi
  done
  IFS="$ac_save_ifs"
fi
fi
CC="$ac_cv_prog_CC"
if test -n "$CC"; then
  echo "$ac_t""$CC" 1>&6
else
  echo "$ac_t""no" 1>&6
fi
 ;;
    esac
  fi
  test -z "$CC" && { echo "configure: error: no acceptable cc found in \$PATH" 1>&2; exit 1; }
fi

echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works""... $ac_c" 1>&6
echo "configure:667: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works" >&5

ac_ext=c
# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
ac_cpp='$CPP $CPPFLAGS'
ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
cross_compiling=$ac_cv_prog_cc_cross

cat > conftest.$ac_ext << EOF

#line 678 "configure"
#include "confdefs.h"

main(){return(0);}
EOF
if { (eval echo configure:683: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
  ac_cv_prog_cc_works=yes
  # If we can't run a trivial program, we are probably using a cross compiler.
  if (./conftest; exit) 2>/dev/null; then
    ac_cv_prog_cc_cross=no
  else
    ac_cv_prog_cc_cross=yes
  fi
else
  echo "configure: failed program was:" >&5
  cat conftest.$ac_ext >&5
  ac_cv_prog_cc_works=no
fi
rm -fr conftest*
ac_ext=c
# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
ac_cpp='$CPP $CPPFLAGS'
ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
cross_compiling=$ac_cv_prog_cc_cross

echo "$ac_t""$ac_cv_prog_cc_works" 1>&6
if test $ac_cv_prog_cc_works = no; then
  { echo "configure: error: installation or configuration problem: C compiler cannot create executables." 1>&2; exit 1; }
fi
echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler""... $ac_c" 1>&6
echo "configure:709: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler" >&5
echo "$ac_t""$ac_cv_prog_cc_cross" 1>&6
cross_compiling=$ac_cv_prog_cc_cross

echo $ac_n "checking whether we are using GNU C""... $ac_c" 1>&6
echo "configure:714: checking whether we are using GNU C" >&5
if eval "test \"`echo '$''{'ac_cv_prog_gcc'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  cat > conftest.c <&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then
  ac_cv_prog_gcc=yes
else
  ac_cv_prog_gcc=no
fi
fi

echo "$ac_t""$ac_cv_prog_gcc" 1>&6

if test $ac_cv_prog_gcc = yes; then
  GCC=yes
else
  GCC=
fi

ac_test_CFLAGS="${CFLAGS+set}"
ac_save_CFLAGS="$CFLAGS"
CFLAGS=
echo $ac_n "checking whether ${CC-cc} accepts -g""... $ac_c" 1>&6
echo "configure:742: checking whether ${CC-cc} accepts -g" >&5
if eval "test \"`echo '$''{'ac_cv_prog_cc_g'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  echo 'void f(){}' > conftest.c
if test -z "`${CC-cc} -g -c conftest.c 2>&1`"; then
  ac_cv_prog_cc_g=yes
else
  ac_cv_prog_cc_g=no
fi
rm -f conftest*

fi

echo "$ac_t""$ac_cv_prog_cc_g" 1>&6
if test "$ac_test_CFLAGS" = set; then
  CFLAGS="$ac_save_CFLAGS"
elif test $ac_cv_prog_cc_g = yes; then
  if test "$GCC" = yes; then
    CFLAGS="-g -O2"
  else
    CFLAGS="-g"
  fi
else
  if test "$GCC" = yes; then
    CFLAGS="-O2"
  else
    CFLAGS=
  fi
fi

echo $ac_n "checking how to run the C preprocessor""... $ac_c" 1>&6
echo "configure:774: checking how to run the C preprocessor" >&5
# On Suns, sometimes $CPP names a directory.
if test -n "$CPP" && test -d "$CPP"; then
  CPP=
fi
if test -z "$CPP"; then
if eval "test \"`echo '$''{'ac_cv_prog_CPP'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
    # This must be in double quotes, not single quotes, because CPP may get
  # substituted into the Makefile and "${CC-cc}" will confuse make.
  CPP="${CC-cc} -E"
  # On the NeXT, cc -E runs the code through the compiler's parser,
  # not just through cpp.
  cat > conftest.$ac_ext <
Syntax Error
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
{ (eval echo configure:795: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
if test -z "$ac_err"; then
  :
else
  echo "$ac_err" >&5
  echo "configure: failed program was:" >&5
  cat conftest.$ac_ext >&5
  rm -rf conftest*
  CPP="${CC-cc} -E -traditional-cpp"
  cat > conftest.$ac_ext <
Syntax Error
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
{ (eval echo configure:812: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
if test -z "$ac_err"; then
  :
else
  echo "$ac_err" >&5
  echo "configure: failed program was:" >&5
  cat conftest.$ac_ext >&5
  rm -rf conftest*
  CPP="${CC-cc} -nologo -E"
  cat > conftest.$ac_ext <
Syntax Error
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
{ (eval echo configure:829: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
if test -z "$ac_err"; then
  :
else
  echo "$ac_err" >&5
  echo "configure: failed program was:" >&5
  cat conftest.$ac_ext >&5
  rm -rf conftest*
  CPP=/lib/cpp
fi
rm -f conftest*
fi
rm -f conftest*
fi
rm -f conftest*
  ac_cv_prog_CPP="$CPP"
fi
  CPP="$ac_cv_prog_CPP"
else
  ac_cv_prog_CPP="$CPP"
fi
echo "$ac_t""$CPP" 1>&6


echo $ac_n "checking if the compiler supports function prototypes""... $ac_c" 1>&6
echo "configure:855: checking if the compiler supports function prototypes" >&5
cat > conftest.$ac_ext <&5; (eval $ac_compile) 2>&5; }; then
  rm -rf conftest*
  wi_cv_prototypes=yes
cat >> confdefs.h <<\EOF
#define PROTOTYPES 1
EOF

else
  echo "configure: failed program was:" >&5
  cat conftest.$ac_ext >&5
  rm -rf conftest*
  wi_cv_prototypes=no
fi
rm -f conftest*
echo "$ac_t""$wi_cv_prototypes" 1>&6

echo $ac_n "checking whether ${MAKE-make} sets \${MAKE}""... $ac_c" 1>&6
echo "configure:881: checking whether ${MAKE-make} sets \${MAKE}" >&5
set dummy ${MAKE-make}; ac_make=`echo "$2" | sed 'y%./+-%__p_%'`
if eval "test \"`echo '$''{'ac_cv_prog_make_${ac_make}_set'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  cat > conftestmake <<\EOF
all:
	@echo 'ac_maketemp="${MAKE}"'
EOF
# GNU make sometimes prints "make[1]: Entering...", which would confuse us.
eval `${MAKE-make} -f conftestmake 2>/dev/null | grep temp=`
if test -n "$ac_maketemp"; then
  eval ac_cv_prog_make_${ac_make}_set=yes
else
  eval ac_cv_prog_make_${ac_make}_set=no
fi
rm -f conftestmake
fi
if eval "test \"`echo '$ac_cv_prog_make_'${ac_make}_set`\" = yes"; then
  echo "$ac_t""yes" 1>&6
  SET_MAKE=
else
  echo "$ac_t""no" 1>&6
  SET_MAKE="MAKE=${MAKE-make}"
fi

# Extract the first word of "ranlib", so it can be a program name with args.
set dummy ranlib; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
echo "configure:910: checking for $ac_word" >&5
if eval "test \"`echo '$''{'ac_cv_prog_RANLIB'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  if test -n "$RANLIB"; then
  ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test.
else
  IFS="${IFS= 	}"; ac_save_ifs="$IFS"; IFS=":"
  ac_dummy="$PATH"
  for ac_dir in $ac_dummy; do
    test -z "$ac_dir" && ac_dir=.
    if test -f $ac_dir/$ac_word; then
      ac_cv_prog_RANLIB="ranlib"
      break
    fi
  done
  IFS="$ac_save_ifs"
  test -z "$ac_cv_prog_RANLIB" && ac_cv_prog_RANLIB=":"
fi
fi
RANLIB="$ac_cv_prog_RANLIB"
if test -n "$RANLIB"; then
  echo "$ac_t""$RANLIB" 1>&6
else
  echo "$ac_t""no" 1>&6
fi


if test "$wi_cv_prototypes" = no ; then
	echo "configure: warning: Your compiler does not support function prototyping and" 1>&2
	echo "configure: warning: is not able to properly compile this package. What a pity." 1>&2
        echo "configure: warning: Get gcc, or any compiler that supports function prototypes." 1>&2
	exit 1
fi

#
# Checks for header files and library functions
#

echo $ac_n "checking for ANSI C header files""... $ac_c" 1>&6
echo "configure:950: checking for ANSI C header files" >&5
if eval "test \"`echo '$''{'ac_cv_header_stdc'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  cat > conftest.$ac_ext <
#include 
#include 
#include 
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
{ (eval echo configure:963: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
if test -z "$ac_err"; then
  rm -rf conftest*
  ac_cv_header_stdc=yes
else
  echo "$ac_err" >&5
  echo "configure: failed program was:" >&5
  cat conftest.$ac_ext >&5
  rm -rf conftest*
  ac_cv_header_stdc=no
fi
rm -f conftest*

if test $ac_cv_header_stdc = yes; then
  # SunOS 4.x string.h does not declare mem*, contrary to ANSI.
cat > conftest.$ac_ext <
EOF
if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
  egrep "memchr" >/dev/null 2>&1; then
  :
else
  rm -rf conftest*
  ac_cv_header_stdc=no
fi
rm -f conftest*

fi

if test $ac_cv_header_stdc = yes; then
  # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI.
cat > conftest.$ac_ext <
EOF
if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
  egrep "free" >/dev/null 2>&1; then
  :
else
  rm -rf conftest*
  ac_cv_header_stdc=no
fi
rm -f conftest*

fi

if test $ac_cv_header_stdc = yes; then
  # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi.
if test "$cross_compiling" = yes; then
  :
else
  cat > conftest.$ac_ext <
#define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
#define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c))
#define XOR(e, f) (((e) && !(f)) || (!(e) && (f)))
int main () { int i; for (i = 0; i < 256; i++)
if (XOR (islower (i), ISLOWER (i)) || toupper (i) != TOUPPER (i)) exit(2);
exit (0); }

EOF
if { (eval echo configure:1030: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
then
  :
else
  echo "configure: failed program was:" >&5
  cat conftest.$ac_ext >&5
  rm -fr conftest*
  ac_cv_header_stdc=no
fi
rm -fr conftest*
fi

fi
fi

echo "$ac_t""$ac_cv_header_stdc" 1>&6
if test $ac_cv_header_stdc = yes; then
  cat >> confdefs.h <<\EOF
#define STDC_HEADERS 1
EOF

fi

echo $ac_n "checking for size_t""... $ac_c" 1>&6
echo "configure:1054: checking for size_t" >&5
if eval "test \"`echo '$''{'ac_cv_type_size_t'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  cat > conftest.$ac_ext <
#if STDC_HEADERS
#include 
#include 
#endif
EOF
if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
  egrep "(^|[^a-zA-Z_0-9])size_t[^a-zA-Z_0-9]" >/dev/null 2>&1; then
  rm -rf conftest*
  ac_cv_type_size_t=yes
else
  rm -rf conftest*
  ac_cv_type_size_t=no
fi
rm -f conftest*

fi
echo "$ac_t""$ac_cv_type_size_t" 1>&6
if test $ac_cv_type_size_t = no; then
  cat >> confdefs.h <<\EOF
#define size_t unsigned
EOF

fi

echo $ac_n "checking whether time.h and sys/time.h may both be included""... $ac_c" 1>&6
echo "configure:1087: checking whether time.h and sys/time.h may both be included" >&5
if eval "test \"`echo '$''{'ac_cv_header_time'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  cat > conftest.$ac_ext <
#include 
#include 
int main() {
struct tm *tp;
; return 0; }
EOF
if { (eval echo configure:1101: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
  rm -rf conftest*
  ac_cv_header_time=yes
else
  echo "configure: failed program was:" >&5
  cat conftest.$ac_ext >&5
  rm -rf conftest*
  ac_cv_header_time=no
fi
rm -f conftest*
fi

echo "$ac_t""$ac_cv_header_time" 1>&6
if test $ac_cv_header_time = yes; then
  cat >> confdefs.h <<\EOF
#define TIME_WITH_SYS_TIME 1
EOF

fi

for ac_hdr in fcntl.h unistd.h memory.h malloc.h errno.h
do
ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
echo "configure:1125: checking for $ac_hdr" >&5
if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  cat > conftest.$ac_ext <
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
{ (eval echo configure:1135: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
if test -z "$ac_err"; then
  rm -rf conftest*
  eval "ac_cv_header_$ac_safe=yes"
else
  echo "$ac_err" >&5
  echo "configure: failed program was:" >&5
  cat conftest.$ac_ext >&5
  rm -rf conftest*
  eval "ac_cv_header_$ac_safe=no"
fi
rm -f conftest*
fi
if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then
  echo "$ac_t""yes" 1>&6
    ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'`
  cat >> confdefs.h <&6
fi
done

for ac_hdr in io.h sys/time.h
do
ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
echo "configure:1165: checking for $ac_hdr" >&5
if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  cat > conftest.$ac_ext <
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
{ (eval echo configure:1175: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
if test -z "$ac_err"; then
  rm -rf conftest*
  eval "ac_cv_header_$ac_safe=yes"
else
  echo "$ac_err" >&5
  echo "configure: failed program was:" >&5
  cat conftest.$ac_ext >&5
  rm -rf conftest*
  eval "ac_cv_header_$ac_safe=no"
fi
rm -f conftest*
fi
if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then
  echo "$ac_t""yes" 1>&6
    ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'`
  cat >> confdefs.h <&6
fi
done


CFLAGS="$CFLAGS -D_GNU_SOURCE"
for ac_func in gettimeofday fgetc_unlocked
do
echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
echo "configure:1206: checking for $ac_func" >&5
if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  cat > conftest.$ac_ext <
/* Override any gcc2 internal prototype to avoid an error.  */
/* We use char because int might match the return type of a gcc2
    builtin and then its argument prototype would still apply.  */
char $ac_func();

int main() {

/* The GNU C library defines this for functions which it implements
    to always fail with ENOSYS.  Some functions are actually named
    something starting with __ and the normal name is an alias.  */
#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
choke me
#else
$ac_func();
#endif

; return 0; }
EOF
if { (eval echo configure:1234: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
  rm -rf conftest*
  eval "ac_cv_func_$ac_func=yes"
else
  echo "configure: failed program was:" >&5
  cat conftest.$ac_ext >&5
  rm -rf conftest*
  eval "ac_cv_func_$ac_func=no"
fi
rm -f conftest*
fi

if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then
  echo "$ac_t""yes" 1>&6
    ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'`
  cat >> confdefs.h <&6
fi
done


echo $ac_n "checking for tempnam""... $ac_c" 1>&6
echo "configure:1260: checking for tempnam" >&5
if eval "test \"`echo '$''{'ac_cv_func_tempnam'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  cat > conftest.$ac_ext <
/* Override any gcc2 internal prototype to avoid an error.  */
/* We use char because int might match the return type of a gcc2
    builtin and then its argument prototype would still apply.  */
char tempnam();

int main() {

/* The GNU C library defines this for functions which it implements
    to always fail with ENOSYS.  Some functions are actually named
    something starting with __ and the normal name is an alias.  */
#if defined (__stub_tempnam) || defined (__stub___tempnam)
choke me
#else
tempnam();
#endif

; return 0; }
EOF
if { (eval echo configure:1288: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
  rm -rf conftest*
  eval "ac_cv_func_tempnam=yes"
else
  echo "configure: failed program was:" >&5
  cat conftest.$ac_ext >&5
  rm -rf conftest*
  eval "ac_cv_func_tempnam=no"
fi
rm -f conftest*
fi

if eval "test \"`echo '$ac_cv_func_'tempnam`\" = yes"; then
  echo "$ac_t""yes" 1>&6
  :
else
  echo "$ac_t""no" 1>&6
cat >> confdefs.h <<\EOF
#define tempnam FP_tempnam
EOF

fi


echo $ac_n "checking for chmod""... $ac_c" 1>&6
echo "configure:1313: checking for chmod" >&5
if eval "test \"`echo '$''{'ac_cv_func_chmod'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  cat > conftest.$ac_ext <
/* Override any gcc2 internal prototype to avoid an error.  */
/* We use char because int might match the return type of a gcc2
    builtin and then its argument prototype would still apply.  */
char chmod();

int main() {

/* The GNU C library defines this for functions which it implements
    to always fail with ENOSYS.  Some functions are actually named
    something starting with __ and the normal name is an alias.  */
#if defined (__stub_chmod) || defined (__stub___chmod)
choke me
#else
chmod();
#endif

; return 0; }
EOF
if { (eval echo configure:1341: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
  rm -rf conftest*
  eval "ac_cv_func_chmod=yes"
else
  echo "configure: failed program was:" >&5
  cat conftest.$ac_ext >&5
  rm -rf conftest*
  eval "ac_cv_func_chmod=no"
fi
rm -f conftest*
fi

if eval "test \"`echo '$ac_cv_func_'chmod`\" = yes"; then
  echo "$ac_t""yes" 1>&6
  cat >> confdefs.h <<\EOF
#define HAVE_CHMOD 1
EOF

else
  echo "$ac_t""no" 1>&6
fi

echo $ac_n "checking for umask""... $ac_c" 1>&6
echo "configure:1364: checking for umask" >&5
if eval "test \"`echo '$''{'ac_cv_func_umask'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  cat > conftest.$ac_ext <
/* Override any gcc2 internal prototype to avoid an error.  */
/* We use char because int might match the return type of a gcc2
    builtin and then its argument prototype would still apply.  */
char umask();

int main() {

/* The GNU C library defines this for functions which it implements
    to always fail with ENOSYS.  Some functions are actually named
    something starting with __ and the normal name is an alias.  */
#if defined (__stub_umask) || defined (__stub___umask)
choke me
#else
umask();
#endif

; return 0; }
EOF
if { (eval echo configure:1392: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
  rm -rf conftest*
  eval "ac_cv_func_umask=yes"
else
  echo "configure: failed program was:" >&5
  cat conftest.$ac_ext >&5
  rm -rf conftest*
  eval "ac_cv_func_umask=no"
fi
rm -f conftest*
fi

if eval "test \"`echo '$ac_cv_func_'umask`\" = yes"; then
  echo "$ac_t""yes" 1>&6
  cat >> confdefs.h <<\EOF
#define HAVE_UMASK 1
EOF

else
  echo "$ac_t""no" 1>&6
fi

echo $ac_n "checking for mkstemp""... $ac_c" 1>&6
echo "configure:1415: checking for mkstemp" >&5
if eval "test \"`echo '$''{'ac_cv_func_mkstemp'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  cat > conftest.$ac_ext <
/* Override any gcc2 internal prototype to avoid an error.  */
/* We use char because int might match the return type of a gcc2
    builtin and then its argument prototype would still apply.  */
char mkstemp();

int main() {

/* The GNU C library defines this for functions which it implements
    to always fail with ENOSYS.  Some functions are actually named
    something starting with __ and the normal name is an alias.  */
#if defined (__stub_mkstemp) || defined (__stub___mkstemp)
choke me
#else
mkstemp();
#endif

; return 0; }
EOF
if { (eval echo configure:1443: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
  rm -rf conftest*
  eval "ac_cv_func_mkstemp=yes"
else
  echo "configure: failed program was:" >&5
  cat conftest.$ac_ext >&5
  rm -rf conftest*
  eval "ac_cv_func_mkstemp=no"
fi
rm -f conftest*
fi

if eval "test \"`echo '$ac_cv_func_'mkstemp`\" = yes"; then
  echo "$ac_t""yes" 1>&6
  cat >> confdefs.h <<\EOF
#define HAVE_MKSTEMP 1
EOF

else
  echo "$ac_t""no" 1>&6
fi


#
# strerror might be internally defined. this would cause a
# CHECK_FUNCS(strerror) to fail because it'd be called with
# zero arguments. So use our own code.
#
echo $ac_n "checking for strerror""... $ac_c" 1>&6
echo "configure:1472: checking for strerror" >&5
cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
  rm -rf conftest*
  have_strerror=yes
else
  echo "configure: failed program was:" >&5
  cat conftest.$ac_ext >&5
  rm -rf conftest*
  cat >> confdefs.h <<\EOF
#define strerror FP_strerror
EOF

have_strerror=no
fi
rm -f conftest*
echo "$ac_t""$have_strerror" 1>&6

echo $ac_n "checking for stdin""... $ac_c" 1>&6
echo "configure:1502: checking for stdin" >&5
cat > conftest.$ac_ext <
char *blubb() { FILE *in, *out; in=stdin; out=stdout; return (char*)0; }

int main() {

(void) blubb();

; return 0; }
EOF
if { (eval echo configure:1516: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
  rm -rf conftest*
  have_stdio=yes
else
  echo "configure: failed program was:" >&5
  cat conftest.$ac_ext >&5
  rm -rf conftest*
  cat >> confdefs.h <<\EOF
#define HAVE_STDIO 1
EOF

have_stdio=no
fi
rm -f conftest*
echo "$ac_t""$have_stdio" 1>&6

if test "$ac_cv_header_stdc" = "no" ; then
	for ac_hdr in stdarg.h varargs.h
do
ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
echo "configure:1537: checking for $ac_hdr" >&5
if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  cat > conftest.$ac_ext <
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
{ (eval echo configure:1547: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
if test -z "$ac_err"; then
  rm -rf conftest*
  eval "ac_cv_header_$ac_safe=yes"
else
  echo "$ac_err" >&5
  echo "configure: failed program was:" >&5
  cat conftest.$ac_ext >&5
  rm -rf conftest*
  eval "ac_cv_header_$ac_safe=no"
fi
rm -f conftest*
fi
if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then
  echo "$ac_t""yes" 1>&6
    ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'`
  cat >> confdefs.h <&6
fi
done

	if test "$ac_cv_header_stdarg_h" = "no" ; then
	if test "$ac_cv_header_varargs_h" = "no" ; then
		{ echo "configure: error: neither stdarg.h nor varargs.h present" 1>&2; exit 1; }
	fi
	fi
fi

#
# Check whether this is a DOS-Based system. Another bogus test.
# Don't even bother to print a message. This code is needed so
# that autoheader includes the #undef into the final config.h
# and we can change the definition by hand on a really DOS
# system (where ./configure doesn't work anyway ...)
#

if false ; then
	cat >> confdefs.h <<\EOF
#define SYSTEM_DOS 1
EOF

	cat >> confdefs.h <<\EOF
#define SYSTEM_QUICKWIN 1
EOF

	cat >> confdefs.h <<\EOF
#define SYSTEM_WINDLL 1
EOF

	cat >> confdefs.h <<\EOF
#define SYSTEM_OS2 1
EOF

fi

#
# On some systems (so far, OS2 and WINDOWS), functions that are exported
# from a DLL must be declared specifically.
#

cat >> confdefs.h <> confdefs.h <&6
echo "configure:1625: checking version number" >&5
version_number="$VERSION"pl"$PATCH"
echo "$ac_t""$version_number" 1>&6



#
# done
#

trap '' 1 2 15
cat > confcache <<\EOF
# This file is a shell script that caches the results of configure
# tests run on this system so they can be shared between configure
# scripts and configure runs.  It is not useful on other systems.
# If it contains results you don't want to keep, you may remove or edit it.
#
# By default, configure uses ./config.cache as the cache file,
# creating it if it does not exist already.  You can give configure
# the --cache-file=FILE option to use a different cache file; that is
# what configure does when it calls configure scripts in
# subdirectories, so they share the cache.
# Giving --cache-file=/dev/null disables caching, for debugging configure.
# config.status only pays attention to the cache file if you give it the
# --recheck option to rerun configure.
#
EOF
# The following way of writing the cache mishandles newlines in values,
# but we know of no workaround that is simple, portable, and efficient.
# So, don't put newlines in cache variables' values.
# Ultrix sh set writes to stderr and can't be redirected directly,
# and sets the high bit in the cache file unless we assign to the vars.
(set) 2>&1 |
  case `(ac_space=' '; set | grep ac_space) 2>&1` in
  *ac_space=\ *)
    # `set' does not quote correctly, so add quotes (double-quote substitution
    # turns \\\\ into \\, and sed turns \\ into \).
    sed -n \
      -e "s/'/'\\\\''/g" \
      -e "s/^\\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\\)=\\(.*\\)/\\1=\${\\1='\\2'}/p"
    ;;
  *)
    # `set' quotes correctly as required by POSIX, so do not add quotes.
    sed -n -e 's/^\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\)=\(.*\)/\1=${\1=\2}/p'
    ;;
  esac >> confcache
if cmp -s $cache_file confcache; then
  :
else
  if test -w $cache_file; then
    echo "updating cache $cache_file"
    cat confcache > $cache_file
  else
    echo "not updating unwritable cache $cache_file"
  fi
fi
rm -f confcache

trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15

test "x$prefix" = xNONE && prefix=$ac_default_prefix
# Let make expand exec_prefix.
test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'

# Any assignment to VPATH causes Sun make to only execute
# the first set of double-colon rules, so remove it if not needed.
# If there is a colon in the path, we need to keep it.
if test "x$srcdir" = x.; then
  ac_vpsub='/^[ 	]*VPATH[ 	]*=[^:]*$/d'
fi

trap 'rm -f $CONFIG_STATUS conftest*; exit 1' 1 2 15

DEFS=-DHAVE_CONFIG_H

# Without the "./", some shells look in PATH for config.status.
: ${CONFIG_STATUS=./config.status}

echo creating $CONFIG_STATUS
rm -f $CONFIG_STATUS
cat > $CONFIG_STATUS </dev/null | sed 1q`:
#
# $0 $ac_configure_args
#
# Compiler output produced by configure, useful for debugging
# configure, is in ./config.log if it exists.

ac_cs_usage="Usage: $CONFIG_STATUS [--recheck] [--version] [--help]"
for ac_option
do
  case "\$ac_option" in
  -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
    echo "running \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion"
    exec \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion ;;
  -version | --version | --versio | --versi | --vers | --ver | --ve | --v)
    echo "$CONFIG_STATUS generated by autoconf version 2.13"
    exit 0 ;;
  -help | --help | --hel | --he | --h)
    echo "\$ac_cs_usage"; exit 0 ;;
  *) echo "\$ac_cs_usage"; exit 1 ;;
  esac
done

ac_given_srcdir=$srcdir

trap 'rm -fr `echo "Makefile config.h" | sed "s/:[^ ]*//g"` conftest*; exit 1' 1 2 15
EOF
cat >> $CONFIG_STATUS < conftest.subs <<\\CEOF
$ac_vpsub
$extrasub
s%@SHELL@%$SHELL%g
s%@CFLAGS@%$CFLAGS%g
s%@CPPFLAGS@%$CPPFLAGS%g
s%@CXXFLAGS@%$CXXFLAGS%g
s%@FFLAGS@%$FFLAGS%g
s%@DEFS@%$DEFS%g
s%@LDFLAGS@%$LDFLAGS%g
s%@LIBS@%$LIBS%g
s%@exec_prefix@%$exec_prefix%g
s%@prefix@%$prefix%g
s%@program_transform_name@%$program_transform_name%g
s%@bindir@%$bindir%g
s%@sbindir@%$sbindir%g
s%@libexecdir@%$libexecdir%g
s%@datadir@%$datadir%g
s%@sysconfdir@%$sysconfdir%g
s%@sharedstatedir@%$sharedstatedir%g
s%@localstatedir@%$localstatedir%g
s%@libdir@%$libdir%g
s%@includedir@%$includedir%g
s%@oldincludedir@%$oldincludedir%g
s%@infodir@%$infodir%g
s%@mandir@%$mandir%g
s%@CC@%$CC%g
s%@CPP@%$CPP%g
s%@SET_MAKE@%$SET_MAKE%g
s%@RANLIB@%$RANLIB%g
s%@VERSION@%$VERSION%g
s%@PATCH@%$PATCH%g

CEOF
EOF

cat >> $CONFIG_STATUS <<\EOF

# Split the substitutions into bite-sized pieces for seds with
# small command number limits, like on Digital OSF/1 and HP-UX.
ac_max_sed_cmds=90 # Maximum number of lines to put in a sed script.
ac_file=1 # Number of current file.
ac_beg=1 # First line for current file.
ac_end=$ac_max_sed_cmds # Line after last line for current file.
ac_more_lines=:
ac_sed_cmds=""
while $ac_more_lines; do
  if test $ac_beg -gt 1; then
    sed "1,${ac_beg}d; ${ac_end}q" conftest.subs > conftest.s$ac_file
  else
    sed "${ac_end}q" conftest.subs > conftest.s$ac_file
  fi
  if test ! -s conftest.s$ac_file; then
    ac_more_lines=false
    rm -f conftest.s$ac_file
  else
    if test -z "$ac_sed_cmds"; then
      ac_sed_cmds="sed -f conftest.s$ac_file"
    else
      ac_sed_cmds="$ac_sed_cmds | sed -f conftest.s$ac_file"
    fi
    ac_file=`expr $ac_file + 1`
    ac_beg=$ac_end
    ac_end=`expr $ac_end + $ac_max_sed_cmds`
  fi
done
if test -z "$ac_sed_cmds"; then
  ac_sed_cmds=cat
fi
EOF

cat >> $CONFIG_STATUS <> $CONFIG_STATUS <<\EOF
for ac_file in .. $CONFIG_FILES; do if test "x$ac_file" != x..; then
  # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in".
  case "$ac_file" in
  *:*) ac_file_in=`echo "$ac_file"|sed 's%[^:]*:%%'`
       ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;;
  *) ac_file_in="${ac_file}.in" ;;
  esac

  # Adjust a relative srcdir, top_srcdir, and INSTALL for subdirectories.

  # Remove last slash and all that follows it.  Not all systems have dirname.
  ac_dir=`echo $ac_file|sed 's%/[^/][^/]*$%%'`
  if test "$ac_dir" != "$ac_file" && test "$ac_dir" != .; then
    # The file is in a subdirectory.
    test ! -d "$ac_dir" && mkdir "$ac_dir"
    ac_dir_suffix="/`echo $ac_dir|sed 's%^\./%%'`"
    # A "../" for each directory in $ac_dir_suffix.
    ac_dots=`echo $ac_dir_suffix|sed 's%/[^/]*%../%g'`
  else
    ac_dir_suffix= ac_dots=
  fi

  case "$ac_given_srcdir" in
  .)  srcdir=.
      if test -z "$ac_dots"; then top_srcdir=.
      else top_srcdir=`echo $ac_dots|sed 's%/$%%'`; fi ;;
  /*) srcdir="$ac_given_srcdir$ac_dir_suffix"; top_srcdir="$ac_given_srcdir" ;;
  *) # Relative path.
    srcdir="$ac_dots$ac_given_srcdir$ac_dir_suffix"
    top_srcdir="$ac_dots$ac_given_srcdir" ;;
  esac


  echo creating "$ac_file"
  rm -f "$ac_file"
  configure_input="Generated automatically from `echo $ac_file_in|sed 's%.*/%%'` by configure."
  case "$ac_file" in
  *Makefile*) ac_comsub="1i\\
# $configure_input" ;;
  *) ac_comsub= ;;
  esac

  ac_file_inputs=`echo $ac_file_in|sed -e "s%^%$ac_given_srcdir/%" -e "s%:% $ac_given_srcdir/%g"`
  sed -e "$ac_comsub
s%@configure_input@%$configure_input%g
s%@srcdir@%$srcdir%g
s%@top_srcdir@%$top_srcdir%g
" $ac_file_inputs | (eval "$ac_sed_cmds") > $ac_file
fi; done
rm -f conftest.s*

# These sed commands are passed to sed as "A NAME B NAME C VALUE D", where
# NAME is the cpp macro being defined and VALUE is the value it is being given.
#
# ac_d sets the value in "#define NAME VALUE" lines.
ac_dA='s%^\([ 	]*\)#\([ 	]*define[ 	][ 	]*\)'
ac_dB='\([ 	][ 	]*\)[^ 	]*%\1#\2'
ac_dC='\3'
ac_dD='%g'
# ac_u turns "#undef NAME" with trailing blanks into "#define NAME VALUE".
ac_uA='s%^\([ 	]*\)#\([ 	]*\)undef\([ 	][ 	]*\)'
ac_uB='\([ 	]\)%\1#\2define\3'
ac_uC=' '
ac_uD='\4%g'
# ac_e turns "#undef NAME" without trailing blanks into "#define NAME VALUE".
ac_eA='s%^\([ 	]*\)#\([ 	]*\)undef\([ 	][ 	]*\)'
ac_eB='$%\1#\2define\3'
ac_eC=' '
ac_eD='%g'

if test "${CONFIG_HEADERS+set}" != set; then
EOF
cat >> $CONFIG_STATUS <> $CONFIG_STATUS <<\EOF
fi
for ac_file in .. $CONFIG_HEADERS; do if test "x$ac_file" != x..; then
  # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in".
  case "$ac_file" in
  *:*) ac_file_in=`echo "$ac_file"|sed 's%[^:]*:%%'`
       ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;;
  *) ac_file_in="${ac_file}.in" ;;
  esac

  echo creating $ac_file

  rm -f conftest.frag conftest.in conftest.out
  ac_file_inputs=`echo $ac_file_in|sed -e "s%^%$ac_given_srcdir/%" -e "s%:% $ac_given_srcdir/%g"`
  cat $ac_file_inputs > conftest.in

EOF

# Transform confdefs.h into a sed script conftest.vals that substitutes
# the proper values into config.h.in to produce config.h.  And first:
# Protect against being on the right side of a sed subst in config.status.
# Protect against being in an unquoted here document in config.status.
rm -f conftest.vals
cat > conftest.hdr <<\EOF
s/[\\&%]/\\&/g
s%[\\$`]%\\&%g
s%#define \([A-Za-z_][A-Za-z0-9_]*\) *\(.*\)%${ac_dA}\1${ac_dB}\1${ac_dC}\2${ac_dD}%gp
s%ac_d%ac_u%gp
s%ac_u%ac_e%gp
EOF
sed -n -f conftest.hdr confdefs.h > conftest.vals
rm -f conftest.hdr

# This sed command replaces #undef with comments.  This is necessary, for
# example, in the case of _POSIX_SOURCE, which is predefined and required
# on some systems where configure will not decide to define it.
cat >> conftest.vals <<\EOF
s%^[ 	]*#[ 	]*undef[ 	][ 	]*[a-zA-Z_][a-zA-Z_0-9]*%/* & */%
EOF

# Break up conftest.vals because some shells have a limit on
# the size of here documents, and old seds have small limits too.

rm -f conftest.tail
while :
do
  ac_lines=`grep -c . conftest.vals`
  # grep -c gives empty output for an empty file on some AIX systems.
  if test -z "$ac_lines" || test "$ac_lines" -eq 0; then break; fi
  # Write a limited-size here document to conftest.frag.
  echo '  cat > conftest.frag <> $CONFIG_STATUS
  sed ${ac_max_here_lines}q conftest.vals >> $CONFIG_STATUS
  echo 'CEOF
  sed -f conftest.frag conftest.in > conftest.out
  rm -f conftest.in
  mv conftest.out conftest.in
' >> $CONFIG_STATUS
  sed 1,${ac_max_here_lines}d conftest.vals > conftest.tail
  rm -f conftest.vals
  mv conftest.tail conftest.vals
done
rm -f conftest.vals

cat >> $CONFIG_STATUS <<\EOF
  rm -f conftest.frag conftest.h
  echo "/* $ac_file.  Generated automatically by configure.  */" > conftest.h
  cat conftest.in >> conftest.h
  rm -f conftest.in
  if cmp -s $ac_file conftest.h 2>/dev/null; then
    echo "$ac_file is unchanged"
    rm -f conftest.h
  else
    # Remove last slash and all that follows it.  Not all systems have dirname.
      ac_dir=`echo $ac_file|sed 's%/[^/][^/]*$%%'`
      if test "$ac_dir" != "$ac_file" && test "$ac_dir" != .; then
      # The file is in a subdirectory.
      test ! -d "$ac_dir" && mkdir "$ac_dir"
    fi
    rm -f $ac_file
    mv conftest.h $ac_file
  fi
fi; done

EOF
cat >> $CONFIG_STATUS <> $CONFIG_STATUS <<\EOF

exit 0
EOF
chmod +x $CONFIG_STATUS
rm -fr confdefs* $ac_clean_files
test "$no_create" = yes || ${CONFIG_SHELL-/bin/sh} $CONFIG_STATUS || exit 1


Convert-UUlib-1.5/uulib/uucheck.c0000644000000000000000000011171011567723176015446 0ustar  rootroot/*
 * This file is part of uudeview, the simple and friendly multi-part multi-
 * 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
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 */

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#ifdef SYSTEM_WINDLL
#include 
#endif
#ifdef SYSTEM_OS2
#include 
#endif

/*
 * uucheck.c
 *
 * Various checking and processing of one input part
 **/

#include 
#include 

#ifdef STDC_HEADERS
#include 
#include 
#endif
#ifdef HAVE_MALLOC_H
#include 
#endif
#ifdef HAVE_UNISTD_H
#include 
#endif
#ifdef HAVE_MEMORY_H
#include 
#endif

#include 
#include 
#include 
#include 

char * uucheck_id = "$Id$";

/*
 * Arbitrary number. This is the maximum number of part numbers we
 * store for our have-parts and missing-parts lists
 */

#define MAXPLIST	256


/*
 * forward declarations of local functions
 */

static char *	UUGetFileName	(char *, char *, char *);
static int	UUGetPartNo	(char *, char **, char **);

/*
 * State of Scanner function and PreProcessPart
 */

int lastvalid, lastenc, nofnum;
char *uucheck_lastname;
char *uucheck_tempname;
static int  lastpart = 0;
static char *nofname = "UNKNOWN";

/*
 * special characters we allow an unquoted filename to have
 */

static char *fnchars = "._-~!";

/*
 * Policy for extracting a part number from the subject line.
 * usually, look for part numbers in () brackets first, then in []
 */

static char *brackchr[] = {
  "()[]", "[]()"
};

/*
 * Extract a filename from the subject line. We need anything to identify
 * the name of the program for sorting. If a nice filename cannot be found, 
 * the subject line itself is used
 * ptonum is, if not NULL, a pointer to the part number in the subject line,
 * so that it won't be used as filename.
 **/
static char *
UUGetFileName (char *subject, char *ptonum, char *ptonend)
{
  char *ptr = subject, *iter, *result, *part;
  int count, length=0, alflag=0;

/*
 * If this file has no subject line, assume it is the next part of the
 * previous file (this is done in UUPreProcessPart)
 **/

  if (subject == NULL)
    return NULL;

/*
 * If the subject starts with 'Re', it is ignored
 * REPosts or RETries are not ignored!
 **/

  if (uu_ignreply &&
      (subject[0] == 'R' || subject[0] == 'r') &&
      (subject[1] == 'E' || subject[1] == 'e') &&
      (subject[2] == ':' || subject[2] == ' ')) {
    return uu_FileNameCallback ? uu_FileNameCallback(uu_FNCBArg, subject, NULL) : NULL;
  }

/*
 * Ignore a "Repost" prefix of the subject line. We don't want to get
 * a file named "Repost" :-)
 **/

  if (_FP_strnicmp (subject, "repost", 6) == 0)
    subject += 6;
  if (_FP_strnicmp (subject, "re:", 3) == 0)
    subject += 3;

  while (*subject == ' ' || *subject == ':') subject++;

  part = _FP_stristr (subject, "part");
  if (part == subject) {
    subject += 4;
    while (*subject == ' ') subject++;
  }

  /*
   * If the file was encoded by uuenview, then the filename is enclosed
   * in [brackets]. But check what's inside these bracket's, try not to
   * fall for something other than a filename
   */

  ptr = subject;
  while ((iter = strchr (ptr, '[')) != NULL) {
    if (strchr (iter, ']') == NULL) {
      ptr = iter + 1;
      continue;
    }
    iter++;
    while (isspace (*iter))
      iter++;
    count = length = alflag = 0;
    while (iter[count] && 
	   (isalnum (iter[count]) || strchr (fnchars, iter[count])!=NULL)) {
      if (isalpha (iter[count]))
	alflag++;
      count++;
    }
    if (count<4 || alflag==0) {
      ptr = iter + 1;
      continue;
    }
    length = count;
    while (isspace (iter[count]))
      count++;
    if (iter[count] == ']') {
      ptr = iter;
      break;
    }
    length = 0;
    ptr = iter + 1;
  }

  /*
   * new filename detection routine, fists mostly for files by ftp-by-email
   * servers that create subject lines with ftp.host.address:/full/path/file
   * on them. We look for slashes and take the filename from after the last
   * one ... or at least we try to.
   */

  if (length == 0) {
    ptr = subject;
    while ((iter = strchr (ptr, '/')) != NULL) {
      if (iter >= ptonum && iter <= ptonend) {
	ptr = iter + 1;
	continue;
      }
      count = length = 0;
      iter++;
      while (iter[count] &&
	     (isalnum(iter[count])||strchr(fnchars, iter[count])!=NULL))
	count++;
      if (iter[count] == ' ' && length > 4) {
	length = count;
	break;
      }
      ptr = iter + ((count)?count:1);
    }
  }

  /*
   * Look for two alphanumeric strings separated by a '.'
   * (That's most likely a filename)
   **/

  if (length == 0) {
    ptr = subject;
    /* #warning another experimental change */
    /*while (*ptr && *ptr != 0x0a && *ptr != 0x0d && ptr != part) {*/
    while (*ptr && *ptr != 0x0a && *ptr != 0x0d) {
      iter  = ptr;
      count = length = alflag = 0;
      
      if (_FP_strnicmp (ptr, "ftp", 3) == 0) {
	/* hey, that's an ftp address */
	while (isalpha (*ptr) || isdigit (*ptr) || *ptr == '.')
	  ptr++;
	continue;
      }
      
      while ((isalnum(*iter)||strchr(fnchars, *iter)!=NULL||
	      *iter=='/') && *iter && iter != ptonum && *iter != '.') {
	if (isalpha (*iter))
	  alflag = 1;
	
	count++; iter++;
      }
      if (*iter == '\0' || iter == ptonum) {
	if (iter == ptonum)
	  ptr  = ptonend;
	else
	  ptr  = iter;

	length = 0;
	continue;
      }

      /* #warning multi-part change experimental, make pluggable */
      /* if (*iter++ != '.' || count > 32 || alflag == 0) { */
      if (*iter++ != '.' || count > 32) {
	ptr    = iter;
	length = 0;
	continue;
      }

      /* a dot followed by sth. unesthetically doesn't look right */
      if (*iter < '0') {
	ptr    = iter + 1;
	length = 0;
	continue;
      }

      if (_FP_strnicmp (iter, "edu", 3) == 0 || 
	  _FP_strnicmp (iter, "gov", 3) == 0) {
	/* hey, that's an ftp address */
	while (isalpha (*iter) || isdigit (*iter) || *iter == '.')
	  iter++;
	ptr    = iter;
	length = 0;
	continue;
      }
      
      length += count + 1;
      count   = 0;
      
      while ((isalnum(iter[count])||strchr(fnchars, iter[count])!=NULL||
	      iter[count]=='/') && iter[count] && iter[count] != '.')
	count++;
      
      if (iter[count]==':' && iter[count+1]=='/') {
	/* looks like stuff from a mail server */
	ptr = iter + 1;
	length = 0;
	continue;
      }
      
      if (count > 8 || iter == ptonum) {
	ptr    = iter;
	length = 0;
	continue;
      }

      if (iter[count] != '.') {
	length += count;
	break;
      }
      
      while (iter[count] &&
	     (isalnum(iter[count])||strchr(fnchars, iter[count])!=NULL||
	      iter[count]=='/'))
	count++;
      
      if (iter[count]==':' && iter[count+1]=='/') {
	/* looks like stuff from a mail server */
	ptr = iter + 1;
	length = 0;
	continue;
      }
      
      if (count < 12 && iter != ptonum) {
	length += count;
	break;
      }

      ptr    = iter;
      length = 0;
    }
  }

  if (length == 0) { /* No filename found, use subject line for ident */
    ptr = subject;

    while (*ptr && !isalpha (*ptr))
      ptr++;

    while ((isalnum(ptr[length])||strchr(fnchars,ptr[length])!=NULL||
	    ptr[length] == '/') && 
	   ptr[length] && ptr+length!=part && ptr+length!=ptonum)
      length++;

    if (length) {
      if (ptr[length] == '\0' || ptr[length] == 0x0a || ptr[length] == 0x0d) {
        length--;

	/*
	 * I used to cut off digits from the end of the string, but
	 * let's try to live without. We want to distinguish
	 * DUTCH951 from DUTCH952
	 *
         * while ((ptr[length] == ' ' || isdigit (ptr[length])) && length > 0)
         *   length--;
	 */
      }
      else {
        length--;

        while (ptr[length] == ' ' && length > 0)
          length--;
      }
      length++;
    }
  }

  if (length == 0) { /* Still found nothing? We need *something*! */
    ptr    = nofname;
    length = strlen (nofname);
  }

  if ((result = (char *) malloc (length + 1)) == NULL) {
    UUMessage (uucheck_id, __LINE__, UUMSG_ERROR,
	       uustring (S_OUT_OF_MEMORY), length+1);
    return NULL;
  }
    
  memcpy (result, ptr, length);
  result[length] = '\0';
    
  return uu_FileNameCallback ? uu_FileNameCallback(uu_FNCBArg, subject, result) : result;
}

/*
 * Extract the Part Number from the subject line.
 * We look first for numbers in (#/#)'s, then for numbers in [#/#]'s
 * and then for digits that are not part of a string.
 * If we cannot find anything, assume it is the next part of the
 * previous file.
 * If we find a part number, we put a pointer to it in *where. This is
 * done so that the UUGetFileName function doesn't accidentally use the
 * part number as the file name. *whend points to the end of this part
 * number.
 **/

static int
UUGetPartNo (char *subject, char **where, char **whend)
{
  char *ptr = subject, *iter, *delim, bdel[2]=" ";
  int count, length=0, bpc;

  *where = NULL; bdel[0] = ' ';
  *whend = NULL; bdel[1] = '\0';

  iter  = NULL;
  delim = "";

  if (subject == NULL)
    return -1;

  if (uu_ignreply &&
      (subject[0] == 'R' || subject[0] == 'r') && /* Ignore replies, but not */
      (subject[1] == 'E' || subject[1] == 'e') && /* reposts                 */
      (subject[2] == ':' || subject[2] == ' '))
    return -2;

  /*
   * First try numbers in () or [] (or vice versa, according to bracket
   * policy)
   * For multiple occurences, give priority to the bracket with a slash
   * or the last one, whichever is "found" first.
   */

  for (bpc=0, length=0; brackchr[uu_bracket_policy][bpc]; bpc+=2) {
    iter = subject;
    length = 0;
    while ((iter = strchr (iter, brackchr[uu_bracket_policy][bpc])) != NULL) {
      int plength;

      count = 0; iter++;

      while (*iter == ' ' || *iter == '#')
	iter++;

      if (!isdigit (*iter)) {
	continue;
      }
      while (isdigit (iter[count]))
	count++;
      
      if (iter[count] == '\0') {
	iter += count;
	break;
      }

      plength = count;

      if (iter[count] == brackchr[uu_bracket_policy][bpc+1]) {
	*where  = iter;
	bdel[0] = brackchr[uu_bracket_policy][bpc+1];
	delim   = bdel;
        length  = plength;
	continue;
      }

      while (iter[count] == ' ' || iter[count] == '#' ||
	     iter[count] == '/' || iter[count] == '\\')  count++;
      
      if (_FP_strnicmp (iter + count, "of", 2) == 0)
	count += 2;
      
      while (iter[count] == ' ')    count++;
      while (isdigit (iter[count])) count++;
      while (iter[count] == ' ')    count++;
      
      if (iter[count] == brackchr[uu_bracket_policy][bpc+1]) {
	*where  = iter;
	bdel[0] = brackchr[uu_bracket_policy][bpc+1];
	delim   = bdel;
        length  = plength;
	break;
      }
    }
    if (length)
      {
        iter = *where; /* strange control flow, but less changes == less hassle */
        break;
      }
  }

  /*
   * look for the string "part " followed by a number
   */

  if (length == 0) {
    if ((iter = _FP_stristr (subject, "part ")) != NULL) {
      iter += 5;

      while (isspace (*iter) || *iter == '.' || *iter == '-')
	iter++;

      while (isdigit (iter[length]))
        length++;

      if (length == 0) {
	if (_FP_strnicmp (iter, "one", 3) == 0)        length = 1;
	else if (_FP_strnicmp (iter, "two", 3) == 0)   length = 2;
	else if (_FP_strnicmp (iter, "three", 5) == 0) length = 3;
	else if (_FP_strnicmp (iter, "four",  4) == 0) length = 4;
	else if (_FP_strnicmp (iter, "five",  4) == 0) length = 5;
	else if (_FP_strnicmp (iter, "six",   3) == 0) length = 6;
	else if (_FP_strnicmp (iter, "seven", 5) == 0) length = 7;
	else if (_FP_strnicmp (iter, "eight", 5) == 0) length = 8;
	else if (_FP_strnicmp (iter, "nine",  4) == 0) length = 9;
	else if (_FP_strnicmp (iter, "ten",   3) == 0) length = 10;

	if (length && (*whend = strchr (iter, ' '))) {
	  *where = iter;
	  return length;
	}
	else
	  length = 0;
      }
      else {
	*where = iter;
	delim  = "of";
      }
    }
  }

  /*
   * look for the string "part" followed by a number
   */

  if (length == 0) {
    if ((iter = _FP_stristr (subject, "part")) != NULL) {
      iter += 4;

      while (isspace (*iter) || *iter == '.' || *iter == '-')
	iter++;

      while (isdigit (iter[length]))
        length++;

      if (length == 0) {
	if (_FP_strnicmp (iter, "one", 3) == 0)        length = 1;
	else if (_FP_strnicmp (iter, "two", 3) == 0)   length = 2;
	else if (_FP_strnicmp (iter, "three", 5) == 0) length = 3;
	else if (_FP_strnicmp (iter, "four",  4) == 0) length = 4;
	else if (_FP_strnicmp (iter, "five",  4) == 0) length = 5;
	else if (_FP_strnicmp (iter, "six",   3) == 0) length = 6;
	else if (_FP_strnicmp (iter, "seven", 5) == 0) length = 7;
	else if (_FP_strnicmp (iter, "eight", 5) == 0) length = 8;
	else if (_FP_strnicmp (iter, "nine",  4) == 0) length = 9;
	else if (_FP_strnicmp (iter, "ten",   3) == 0) length = 10;

	if (length && (*whend = strchr (iter, ' '))) {
	  *where = iter;
	  return length;
	}
	else
	  length = 0;
      }
      else {
	*where = iter;
	delim  = "of";
      }
    }
  }

  /*
   * look for [0-9]* "of" [0-9]*
   */

  if (length == 0) {
    if ((iter = _FP_strirstr (subject, "of")) != NULL) {
      while (iter>subject && isspace (*(iter-1)))
	iter--;
      if (isdigit(*(iter-1))) {
	while (iter>subject && isdigit (*(iter-1)))
	  iter--;
	if (!isdigit (*iter) && !isalpha (*iter) && *iter != '.')
	  iter++;
	ptr = iter;

	while (isdigit (*ptr)) {
	  ptr++; length++;
	}
	*where = iter;
	delim  = "of";
      }
    }
  }

  /*
   * look for whitespace-separated (or '/'-separated) digits
   */

  if (length == 0) {
    ptr = subject;

    while (*ptr && length==0) {
      while (*ptr && !isdigit (*ptr))
	ptr++;
      if (isdigit (*ptr) && (ptr==subject || *ptr==' ' || *ptr=='/')) {
	while (isdigit (ptr[length]))
	  length++;
	if (ptr[length]!='\0' && ptr[length]!=' ' && ptr[length]!='/') {
	  ptr   += length;
	  length = 0;
	}
	else {
	  iter    = ptr;
	  bdel[0] = ptr[length];
	  delim   = bdel;
	}
      }
      else {
	while (isdigit (*ptr))
	  ptr++;
      }
    }
  }

  /*
   * look for _any_ digits -- currently disabled, because it also fell
   * for "part numbers" in file names
   */

#if 0
  if (length == 0) {
    count = strlen(subject) - 1;
    ptr   = subject;
 
    while (count > 0) {
      if (!isdigit(ptr[count])||isalpha(ptr[count+1])||ptr[count+1] == '.') {
	count--;
	continue;
      }
      length = 0;

      while (count >= 0 && isdigit (ptr[count])) {
	count--; length++;
      }
      if (count>=0 && ((isalpha (ptr[count]) && 
			(ptr[count] != 's' || ptr[count+1] != 't') &&
			(ptr[count] != 'n' || ptr[count+1] != 'd')) || 
		       ptr[count] == '/' || ptr[count] == '.' || 
		       ptr[count] == '-' || ptr[count] == '_')) {
        length = 0;
        continue;
      }
      count++;
      iter = ptr + count;

      if (length > 4) {
	length = 0;
	continue;
      }
      *where = iter;
      delim  = "of";
      break;
    }
  }
#endif

  /*
   * look for part numbering as string
   */

  if (length == 0) {
    /*
     * some people use the strangest things, including spelling mistakes :-)
     */
    if ((iter = _FP_stristr (subject, "first")) != NULL)        length = 1;
    else if ((iter = _FP_stristr (subject, "second")) != NULL)  length = 2;
    else if ((iter = _FP_stristr (subject, "third")) != NULL)   length = 3;
    else if ((iter = _FP_stristr (subject, "forth")) != NULL)   length = 4;
    else if ((iter = _FP_stristr (subject, "fourth")) != NULL)  length = 4;
    else if ((iter = _FP_stristr (subject, "fifth")) != NULL)   length = 5;
    else if ((iter = _FP_stristr (subject, "sixth")) != NULL)   length = 6;
    else if ((iter = _FP_stristr (subject, "seventh")) != NULL) length = 7;
    else if ((iter = _FP_stristr (subject, "eigth")) != NULL)   length = 8;
    else if ((iter = _FP_stristr (subject, "eighth")) != NULL)  length = 8;
    else if ((iter = _FP_stristr (subject, "nineth")) != NULL)  length = 9;
    else if ((iter = _FP_stristr (subject, "ninth")) != NULL)   length = 9;
    else if ((iter = _FP_stristr (subject, "tenth")) != NULL)   length = 10;
    else iter = NULL;

    if (length && iter && (*whend = strchr (iter, ' '))) {
      *where = iter;
      return length;
    }
    else
      length = 0;
  }

  if (iter == NULL || length == 0)	/* should be equivalent */
    return -1;

  *where = iter;

  if (delim && delim[0]) {
    if ((*whend=_FP_stristr (iter, delim)) != NULL && (*whend - *where) < 12) {
      ptr = (*whend += strlen (delim));

      while (*ptr == ' ')
	ptr++;

      if (isdigit (*ptr)) {
	*whend = ptr;
	while (isdigit (**whend))
	  *whend += 1;
      }
    }
    else {
      *whend = iter + length;
    }
  }
  else {
    *whend = iter + length;
  }

  return atoi (iter);
}

/*
 * Obtain and process some information about the data.
 **/

uufile *
UUPreProcessPart (fileread *data, int *ret)
{
  char *where, *whend, temp[80], *ptr, *p2;
  uufile *result;

  if ((result = (uufile *) malloc (sizeof (uufile))) == NULL) {
    UUMessage (uucheck_id, __LINE__, UUMSG_ERROR,
	       uustring (S_OUT_OF_MEMORY), sizeof (uufile));
    *ret = UURET_NOMEM;
    return NULL;
  }
  memset (result, 0, sizeof (uufile));

  if (data->partno) {
    where = whend  = NULL;
    result->partno = data->partno;
  }
  else if (uu_dumbness) {
    result->partno = -1;
    where = whend  = NULL;
  }
  else if ((result->partno=UUGetPartNo(data->subject,&where,&whend)) == -2) {
    *ret = UURET_NODATA;
    UUkillfile (result);
    return NULL;
  }

  if (data->filename != NULL) {
    if ((result->filename = _FP_strdup (data->filename)) == NULL) {
      UUMessage (uucheck_id, __LINE__, UUMSG_ERROR,
		 uustring (S_OUT_OF_MEMORY),
		 strlen (data->filename)+1);
      *ret = UURET_NOMEM;
      UUkillfile (result);
      return NULL;
    }
  }
  else
    result->filename = NULL;

  if (uu_dumbness <= 1)
    result->subfname = UUGetFileName (data->subject, where, whend);
  else
    result->subfname = NULL;

  result->yefilesize = data->yefilesize;
  result->mimeid     = _FP_strdup (data->mimeid);
  result->mimetype   = _FP_strdup (data->mimetype);

  if (result->partno == -1 && 
      (data->uudet == PT_ENCODED || data->uudet == QP_ENCODED))
    result->partno = 1;

  if (data->flags & FL_SINGLE) {
    /*
     * Don't touch this part. But it should really have a filename
     */
    if (result->filename == NULL) {
      sprintf (temp, "%s.%03d", nofname, ++nofnum);
      result->filename = _FP_strdup (temp);
    }
    if (result->subfname == NULL)
      result->subfname = _FP_strdup (result->filename);

    if (result->filename == NULL || 
	result->subfname == NULL) {
      UUMessage (uucheck_id, __LINE__, UUMSG_ERROR,
		 uustring (S_OUT_OF_MEMORY),
		 (result->filename==NULL)?
		 (strlen(temp)+1):(strlen(result->filename)+1));
      *ret = UURET_NOMEM;
      UUkillfile(result);
      return NULL;
    }
    if (result->partno == -1)
      result->partno = 1;
  }
  else if (result->subfname == NULL && data->uudet &&
      (data->begin || result->partno == 1 || 
       (!uu_dumbness && result->partno == -1 && 
	(data->subject != NULL || result->filename != NULL)))) {
    /*
     * If it's the first part of something and has some valid data, but
     * no subject or anything, initialize lastvalid
     */
    /*
     * in this case, it really _should_ have a filename somewhere
     */
    if (result->filename != NULL && *result->filename)
      result->subfname = _FP_strdup (result->filename);
    else { /* if not, escape to UNKNOWN. We need to fill subfname */
      sprintf (temp, "%s.%03d", nofname, ++nofnum);
      result->subfname = _FP_strdup (temp);
    }
    /*
     * in case the strdup failed
     */
    if (result->subfname == NULL) {
      UUMessage (uucheck_id, __LINE__, UUMSG_ERROR,
		 uustring (S_OUT_OF_MEMORY),
		 (result->filename)?
		 (strlen(result->filename)+1):(strlen(temp)+1));
      *ret = UURET_NOMEM;
      UUkillfile (result);
      return NULL;
    }
    /*
     * if it's also got an 'end', or is the last part in a MIME-Mail,
     * then don't set lastvalid
     */
    if (!data->end && (!data->partno || data->partno != data->maxpno)) {
      /*
       * initialize lastvalid
       */
      lastvalid = 1;
      lastenc   = data->uudet;
      lastpart  = result->partno = 1;
      _FP_strncpy (uucheck_lastname, result->subfname, 256);
    }
    else
      result->partno = 1;
  }
  else if (result->subfname == NULL && data->uudet && data->mimeid) {
    /*
     * if it's got a file name, use it. Else use the mime-id for identifying
     * this part, and hope there's no other files encoded in the same message
     * under the same id.
     */
    if (result->filename)
      result->subfname = _FP_strdup (result->filename);
    else
      result->subfname = _FP_strdup (result->mimeid);
  }
  else if (result->subfname == NULL && data->uudet) {
    /*
     * ff we have lastvalid, use it. Make an exception for
     * Base64-encoded files.
     */
    if (data->uudet == B64ENCODED) {
      /*
       * Assume it's the first part. I wonder why it's got no part number?
       */
      if (result->filename != NULL && *result->filename)
        result->subfname = _FP_strdup (result->filename);
      else { /* if not, escape to UNKNOWN. We need to fill subfname */
        sprintf (temp, "%s.%03d", nofname, ++nofnum);
        result->subfname = _FP_strdup (temp);
      }
      if (result->subfname == NULL) {
	UUMessage (uucheck_id, __LINE__, UUMSG_ERROR,
		   uustring (S_OUT_OF_MEMORY),
		   (result->filename)?
		   (strlen(result->filename)+1):(strlen(temp)+1));
	*ret = UURET_NOMEM;
	UUkillfile (result);
        return NULL;
      }
      lastvalid = 0;
    }
    else if (lastvalid && data->uudet == lastenc && result->partno == -1) {
      result->subfname = _FP_strdup (uucheck_lastname);
      result->partno   = ++lastpart;

      /*
       * if it's the last part, invalidate lastvalid
       */
      if (data->end || (data->partno && data->partno == data->maxpno))
	lastvalid = 0;
    }
    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.
       */
      *ret = UURET_NODATA;
      UUkillfile (result);
      return NULL;
    }
  }
  else if (result->subfname == NULL && result->partno == -1) {
    /*
     * This, too, is a part without any useful information that we
     * should forget about.
     */
    *ret = UURET_NODATA;
    UUkillfile (result);
    return NULL;
  }
  else if (result->subfname == NULL) {
    /*
     * This is a part without useful subject name, a valid part number
     * but no encoded data. It *could* be the zeroeth part of something,
     * but we don't care here. Just forget it.
     */
    *ret = UURET_NODATA;
    UUkillfile (result);
    return NULL;
  }

  /*
   * now, handle some cases where we have a useful subject but no
   * useful part number
   */

  if (result->partno == -1 && data->begin) {
    /*
     * hmm, this is reason enough to initialize lastvalid, at least 
     * if we have no end
     */
    if (!data->end) {
      _FP_strncpy (uucheck_lastname, result->subfname, 256);
      result->partno = lastpart = 1;
      lastenc = data->uudet;
      lastvalid = 1;
    }
    else
      result->partno = 1;
  }
  else if (result->partno == -1 && data->uudet) {
    if (lastvalid && _FP_stricmp (uucheck_lastname, result->subfname) == 0) {
      /*
       * if the subject filename is the same as last time, use part no
       * of lastvalid. If at end, invalidate lastvalid
       */
      result->partno = ++lastpart;

      if (data->end)
	lastvalid = 0;
    }
    else {
      /*
       * data but no part no. It's something UUInsertPartToList() should
       * handle
       */
      goto skipcheck;
    }
  }
  else if (result->partno == -1) {
    /*
     * it's got no data, so why should we need this one anyway?
     */
    *ret = UURET_NODATA;
    UUkillfile (result);
    return NULL;
  }

  /*
   * at this point, the part should have a valid subfname and a valid
   * part number. If it doesn't, then fail.
   */
  if (result->subfname == NULL || result->partno == -1) {
    *ret = UURET_NODATA;
    UUkillfile (result);
    return NULL;
  }

 skipcheck:

  if (result->filename) {
    if (*(ptr = _FP_cutdir (result->filename))) {
      p2 = _FP_strdup (ptr);
      _FP_free (result->filename);
      result->filename = p2;
    }
  }

  result->data = data;
  result->NEXT = NULL;

  *ret = UURET_OK;

  return result;
}

/*
 * Insert one part of a file into the global list
 **/

int
UUInsertPartToList (uufile *data)
{
  uulist *iter = UUGlobalFileList, *unew;
  uufile *fiter, *last;

  /*
   * Part belongs together, if
   * (1) The MIME-IDs match, or
   * (2) The file name received from the subject lines match, and
   *     (a) Not both parts have a begin line
   *     (b) Not both parts have an end line
   *     (c) Both parts don't have different MIME-IDs
   *     (d) Both parts don't encode different files
   *     (e) The other part wants to stay alone (FL_SINGLE)
   *     (g) The yencode file size matches.
   */

  /*
   * check if this part wants to be left alone. If so, don't bother
   * to do all the checks
   */

  while (iter) {
    if (data->data->flags & FL_SINGLE) {
      /* this space intentionally left blank */
    }
    else if ((data->mimeid && iter->mimeid && strcmp (data->mimeid, iter->mimeid) == 0)
             ||
	     (
              1
	      && !(iter->thisfile && iter->thisfile->yefilesize != data->yefilesize)
	      && !(iter->begin && data->data->begin)
	      && !(iter->end   && data->data->end)
	      && !(iter->flags & FL_SINGLE)
	      && !(data->filename && iter->filename && strcmp (data->filename, iter->filename) != 0)
              && _FP_stricmp (data->subfname, iter->subfname) == 0
	      && !(data->mimeid   && iter->mimeid   && strcmp (data->mimeid,   iter->mimeid)   != 0)
             )
            ) {

      /*
       * Don't insert a part that is already there.
       *
       * Also don't add a part beyond the "end" marker (unless we
       * have a mimeid, which screws up the marker).
       */

      for (fiter=iter->thisfile; fiter; fiter=fiter->NEXT) {
	if (data->partno == fiter->partno)
	  goto goahead;
	if (!iter->mimeid) {
	  if (data->partno > fiter->partno && fiter->data->end) {
	    goto goahead;
	  }
	}
      }

      if (iter->filename == NULL && data->filename != NULL) {
        if ((iter->filename = _FP_strdup (data->filename)) == NULL)
	  return UURET_NOMEM;
      }

      /*
       * special case when we might have tagged a part as Base64 when the
       * file was really XX
       */

      if (data->data->uudet == B64ENCODED && 
	  iter->uudet == XX_ENCODED && iter->begin) {
	data->data->uudet = XX_ENCODED;
      }
      else if (data->data->uudet == XX_ENCODED && data->data->begin &&
	       iter->uudet == B64ENCODED) {
	iter->uudet = XX_ENCODED;

	fiter = iter->thisfile;
	while (fiter) {
	  fiter->data->uudet = XX_ENCODED;
	  fiter = fiter->NEXT;
	}
      }

      /*
       * If this is from a Message/Partial, we believe only the
       * iter->uudet from the first part
       */
      if (data->data->flags & FL_PARTIAL) {
	if (data->partno == 1) {
	  iter->uudet = data->data->uudet;
	  iter->flags = data->data->flags;
	}
      }
      else {
	if (data->data->uudet) iter->uudet = data->data->uudet;
	if (data->data->flags) iter->flags = data->data->flags;
      }

      if (iter->mode == 0 && data->data->mode != 0)
        iter->mode = data->data->mode;
      if (data->data->begin) iter->begin = (data->partno)?data->partno:1;
      if (data->data->end)   iter->end   = (data->partno)?data->partno:1;

      if (data->mimetype) {
	_FP_free (iter->mimetype);
	iter->mimetype = _FP_strdup (data->mimetype);
      }

      /*
       * insert part at the beginning
       */

      if (data->partno != -1 && data->partno < iter->thisfile->partno) {
	iter->state    = UUFILE_READ;
	data->NEXT     = iter->thisfile;
	iter->thisfile = data;
	return UURET_OK;
      }

      /*
       * insert part somewhere else
       */

      iter->state = UUFILE_READ;	/* prepare for re-checking */
      fiter       = iter->thisfile;
      last        = NULL;

      while (fiter) {
	/*
	 * if we find the same part no again, check which one looks better
	 */
	if (data->partno == fiter->partno) {
          if (fiter->data->subject == NULL)
            return UURET_NODATA;
	  else if (_FP_stristr (fiter->data->subject, "repost") != NULL &&
		   _FP_stristr (data->data->subject,  "repost") == NULL)
	    return UURET_NODATA;
          else if (fiter->data->uudet && !data->data->uudet)
            return UURET_NODATA;
          else {
	    /*
	     * replace
	     */
            data->NEXT  = fiter->NEXT;
            fiter->NEXT = NULL;
            UUkillfile (fiter);

            if (last == NULL)
              iter->thisfile = data;
            else
              last->NEXT     = data;

            return UURET_OK;
          }
        }

	/*
	 * if at the end of the part list, add it
	 */

	if (fiter->NEXT == NULL || 
	    (data->partno != -1 && data->partno < fiter->NEXT->partno)) {
	  data->NEXT  = fiter->NEXT;
	  fiter->NEXT = data;

	  if (data->partno == -1)
	    data->partno = fiter->partno + 1;

	  return UURET_OK;
	}
        last  = fiter;
	fiter = fiter->NEXT;
      }
      
      return UURET_OK; /* Shouldn't get here */
    }
  goahead:
    /*
     * we need iter below
     */
    if (iter->NEXT == NULL) 
      break;

    iter = iter->NEXT;
  }
  /*
   * handle new entry
   */

  if (data->partno == -1) {
    /*
     * if it's got no part no, and it's MIME mail, then assume this is
     * part no. 1. If it's not MIME, then we can't handle it; if it
     * had a 'begin', it'd have got a part number assigned by
     * UUPreProcessPart().
     */
    if (data->data->uudet == B64ENCODED || data->data->uudet == BH_ENCODED)
      data->partno = 1;
    else
      return UURET_NODATA;
  }

  if ((unew = (uulist *) malloc (sizeof (uulist))) == NULL) {
    return UURET_NOMEM;
  }

  {
    static uulist uulist_new;
    *unew = uulist_new; /* zero-initialise the structure */
  }

  if ((unew->subfname = _FP_strdup (data->subfname)) == NULL) {
    _FP_free (unew);
    return UURET_NOMEM;
  }

  if (data->filename != NULL) {
    if ((unew->filename = _FP_strdup (data->filename)) == NULL) {
      _FP_free (unew->subfname);
      _FP_free (unew);
      return UURET_NOMEM;
    }
  }
  else
    unew->filename = NULL;

  if (data->mimeid != NULL) {
    if ((unew->mimeid = _FP_strdup (data->mimeid)) == NULL) {
      _FP_free (unew->subfname);
      _FP_free (unew->filename);
      _FP_free (unew);
      return UURET_NOMEM;
    }
  }
  else
    unew->mimeid = NULL;

  if (data->mimetype != NULL) {
    if ((unew->mimetype = _FP_strdup (data->mimetype)) == NULL) {
      _FP_free (unew->mimeid);
      _FP_free (unew->subfname);
      _FP_free (unew->filename);
      _FP_free (unew);
      return UURET_NOMEM;
    }
  }
  else
    unew->mimetype = NULL;

  unew->state     = UUFILE_READ;
  unew->thisfile  = data;
  unew->mode      = data->data->mode;
  unew->uudet     = data->data->uudet;
  unew->flags     = data->data->flags;
  unew->begin     = data->data->begin ? (data->partno ? data->partno : 1) : 0;
  unew->end       = data->data->end   ? (data->partno ? data->partno : 1) : 0;

  if (iter == NULL)
    UUGlobalFileList = unew;
  else
    iter->NEXT = unew;

  return UURET_OK;
}

/*
 * At this point, all files are read in and stored in the
 * "UUGlobalFileList". Do some checking. All parts there?
 **/

void UUEXPORT
UUCheckGlobalList (void)
{
  int misparts[MAXPLIST], haveparts[MAXPLIST];
  int miscount, havecount, count, flag, part;
  uulist *liter=UUGlobalFileList, *prev;
  uufile *fiter;
  long thesize;

  while (liter) {
    miscount = 0;
    thesize  = 0;

    if (liter->state & UUFILE_OK) {
      liter = liter->NEXT;
      continue;
    }
    else if ((liter->uudet == QP_ENCODED ||
	      liter->uudet == PT_ENCODED) && 
	     (liter->flags & FL_SINGLE)) {
      if ((liter->flags&FL_PROPER)==0)
	liter->size = -1;
      else
	liter->size = liter->thisfile->data->length;

      liter->state = UUFILE_OK;
      continue;
    }
    else if ((fiter = liter->thisfile) == NULL) {
      liter->state = UUFILE_NODATA;
      liter = liter->NEXT;
      continue;
    }

    /*
     * Re-Check this file
     */

    flag      = 0;
    miscount  = 0;
    havecount = 0;
    thesize   = 0;
    liter->state = UUFILE_READ;

    /*
     * search encoded data
     */

    while (fiter && !fiter->data->uudet) {
      if (havecountpartno;
      }
      fiter = fiter->NEXT;
    }

    if (fiter == NULL) {
      liter->state = UUFILE_NODATA;
      liter = liter->NEXT;
      continue;
    }

    if (havecountpartno;
    }

    if ((part = fiter->partno) > 1) {
      if (!fiter->data->begin) {
	for (count=1; count < part && miscount < MAXPLIST; count++)
	  misparts[miscount++] = count;
      }
    }

    /*
     * don't care if so many parts are missing
     */

    if (miscount >= MAXPLIST) {
      liter->state = UUFILE_MISPART;
      liter        = liter->NEXT;
      continue;
    }

    if (liter->uudet == B64ENCODED ||
	liter->uudet == QP_ENCODED ||
	liter->uudet == PT_ENCODED)
      flag |= 3; /* Don't need begin or end with Base64 or plain text*/

    if (fiter->data->begin) flag |= 1;
    if (fiter->data->end)   flag |= 2;
    if (fiter->data->uudet) flag |= 4; 

    /*
     * guess size of part
     */

    switch (fiter->data->uudet) {
    case UU_ENCODED:
    case XX_ENCODED:
      thesize += 3*fiter->data->length/4;
      thesize -= 3*fiter->data->length/124; /* substract 2 of 62 chars */
      break;
    case B64ENCODED:
      thesize += 3*fiter->data->length/4;
      thesize -=  fiter->data->length/52;   /* substract 2 of 78 chars */
      break;
    case QP_ENCODED:
    case PT_ENCODED:
      thesize += fiter->data->length;
      break;
    }
      
    fiter = fiter->NEXT;

    while (fiter != NULL) {
      for (count = part+1; count < fiter->partno && miscount < MAXPLIST; count++)
	misparts[miscount++] = count;

      part = fiter->partno;
      
      if (havecount < MAXPLIST)
	haveparts[havecount++] = part;

      if (fiter->data->begin) flag |= 1;
      if (fiter->data->end)   flag |= 2;
      if (fiter->data->uudet) flag |= 4;

      switch (fiter->data->uudet) {
      case UU_ENCODED:
      case XX_ENCODED:
	thesize += 3*fiter->data->length/4;
	thesize -= 3*fiter->data->length/124; /* substract 2 of 62 chars */
	break;
      case B64ENCODED:
	thesize += 3*fiter->data->length/4;
	thesize -=  fiter->data->length/52;   /* substract 2 of 78 chars */
	break;
      case QP_ENCODED:
      case PT_ENCODED:
	thesize += fiter->data->length;
	break;
      }

      if (fiter->data->end)
	break;
	
      fiter = fiter->NEXT;
    }

    /*
     * if in fast mode, we don't notice an 'end'. So if its uu or xx
     * encoded, there's a begin line and encoded data, assume it's
     * there.
     */
    
    if (uu_fast_scanning && (flag & 0x01) && (flag & 0x04) &&
	(liter->uudet == UU_ENCODED || liter->uudet == XX_ENCODED))
      flag |= 2;

    /*
     * Set the parts we have and/or missing
     */

    _FP_free (liter->haveparts);
    _FP_free (liter->misparts);

    liter->haveparts = NULL;
    liter->misparts  = NULL;
    
    if (havecount) {
      if ((liter->haveparts=(int*)malloc((havecount+1)*sizeof(int)))!=NULL) {
	memcpy (liter->haveparts, haveparts, havecount*sizeof(int));
	liter->haveparts[havecount] = 0;
      }
    }
    
    if (miscount) {
      if ((liter->misparts=(int*)malloc((miscount+1)*sizeof(int)))!=NULL) {
	memcpy (liter->misparts, misparts, miscount*sizeof(int));
	liter->misparts[miscount] = 0;
      }
      liter->state |= UUFILE_MISPART;
    }

    /*
     * Finalize checking
     */

    if ((flag & 1) == 0) liter->state |= UUFILE_NOBEGIN;
    if ((flag & 2) == 0) liter->state |= UUFILE_NOEND;
    if ((flag & 4) == 0) liter->state |= UUFILE_NODATA;
    
    if ((flag & 7) == 7 && miscount==0) {
      liter->state = UUFILE_OK;
    }

    if ((uu_fast_scanning && (liter->flags&FL_PROPER)==0) || thesize<=0)
      liter->size = -1;
    else
      liter->size = thesize;

    if (liter->state==UUFILE_OK && 
        (liter->filename==NULL || liter->filename[0]=='\0')) {
      /*
       * Emergency backup if the file does not have a filename
       */
      _FP_free (liter->filename);
      if (liter->subfname && liter->subfname[0] &&
          _FP_strpbrk (liter->subfname, "()[];: ") == NULL)
        liter->filename = _FP_strdup (liter->subfname);
      else {
        sprintf (uucheck_tempname, "%s.%03d", nofname, ++nofnum);
        liter->filename = _FP_strdup (uucheck_tempname);
      }
    }
    liter = liter->NEXT;
  }

  /*
   * Sets back (PREV) links
   */

  liter = UUGlobalFileList;
  prev  = NULL;

  while (liter) {
    liter->PREV = prev;
    prev        = liter;
    liter       = liter->NEXT;
  }
}

Convert-UUlib-1.5/uulib/uuint.h0000644000000000000000000002340111244416065015153 0ustar  rootroot/*
 * This file is part of uudeview, the simple and friendly multi-part multi-
 * 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
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 */

#ifndef __UUINT_H__
#define __UUINT_H__

/*
 * This file describes the internal structures, variables and definitions
 * of UUDeview. It should not be included from other packages. Subject to
 * change without notice. Do not depend on anything here.
 *
 * $Id$
 */

/*
 * Busy Polls will be made after processing ... lines
 */

#define BUSY_LINE_TICKS		50

/*
 * States of MIME scanner
 */

#define MS_HEADERS	1	/* still inside of headers      */
#define MS_BODY		2	/* body of `simple' messages    */
#define MS_PREAMBLE	3	/* preamble of Multipart/Mixed  */
#define MS_SUBPART	4	/* within one of the Multiparts */
#define MS_EPILOGUE	5	/* epilogue of Multipart/Mixed  */

/*
 * Number of subsequent encoded lines we require to believe this
 * is valid data.
 */

#define ELC_COUNT	4

/*
 * Flags a part may have. FL_PROPER means that we are sure about the file's
 * encoding, beginning and end, and don't have to use special care when de-
 * coding.
 */

#define FL_NONE		0	/* no flag, just plain normal   */
#define FL_SINGLE	1	/* standalone MSG, do not mix   */
#define FL_PARTIAL	2	/* from Message/Partial         */
#define FL_PROPER	4	/* proper MIME part             */
#define FL_TOEND	8	/* part continues to EOF        */

/*
 * Auxiliary macro: compute the percentage of a against b.
 * The obvious answer is (100*a)/b, but this overflows for large a.
 * a/(b/100) is better; we use a/((b/100)+1) so that we don't divide
 * by zero for b<100 and the result doesn't become larger than 100%
 */

#define UUPERCENT(a,b)	((int) ((unsigned long)(a) / \
				(((unsigned long)(b)/100)+1)))
     
/*
 * Make the Busy Callback easier. The macro returns true if the BusyCallback
 * wants us to terminate.
 */

extern unsigned long uuyctr;
#define UUBUSYPOLL(a,b) (((++uuyctr%BUSY_LINE_TICKS)==0) ? (progress.percent=UUPERCENT((a),(b)),UUBusyPoll()):0)

/*
 * How many lines of headers do we need to believe another mail
 * header is approaching? Use more restrictive values for MIME
 * mails, less restrictive for Freestyle
 */

typedef struct {
  int restart;		/* restarting after a MIME body (not subpart) */
  int afterdata;	/* after we had useful data in freestyle mode */
  int afternl;		/* after an empty line in freestyle mode      */
} headercount;

extern headercount hlcount;

/*
 * Information from the headers of a message. Each instance must
 * have its very own copy of the strings. If `mimevers' is NULL,
 * then this message does not comply to the MIME standard.
 */

typedef struct _headers {
  char *from;		/* From:                                          */
  char *subject;	/* Subject:                                       */
  char *rcpt;		/* To:                                            */
  char *date;		/* Date:                                          */
  char *mimevers;	/* MIME-Version:                                  */
  char *ctype;		/* Content-Type:                                  */
  char *ctenc;		/* Content-Transfer-Encoding:                     */
  char *fname;		/* Potential Filename from Content-Type Parameter */
  char *boundary;	/* MIME-Boundary from Content-Type Parameter      */
  char *mimeid;		/* MIME-Id for Message/Partial                    */
  int partno;		/* part number for Message/Partial                */
  int numparts;		/* number of parts for Message/Partial            */
} headers;

/*
 * Scanner state
 */

typedef struct _scanstate {
  int isfolder;		/* if we think this is a valid email folder       */
  int ismime;		/* if we are within a valid MIME message          */
  int mimestate;	/* state of MIME scanner                          */
  int mimeenc;		/* encoding of this MIME file                     */
  char *source;		/* source filename                                */
  headers envelope;	/* mail envelope headers                          */
} scanstate;

/*
 * Structure that holds the information for a single file / part of
 * a file. If a subject line is encountered, it is copied to subject;
 * if a begin is found, the mode and name of the file is extracted.
 * flags are set if 'begin' or 'end' is detected and 'uudet' if valid
 * uuencoded data is found. If the file contains a 'From:' line with
 * a '@' in it (indicating an origin email address), it is preserved
 * in 'origin'.
 **/

typedef struct _fileread {
  char *subject;	/* Whole subject line */
  char *filename;	/* Only filled in if begin detected */
  char *origin;		/* Whole 'From:' line */
  char *mimeid;		/* the ID for Mime-encoded files */
  char *mimetype;	/* Content-Type */
  int   mode;		/* Mode of File (from 'begin') */
  int   begin;		/* begin detected */
  int   end;		/* end detected */
  int   flags;		/* associated flags */
  long  yefilesize;     /* the yencode file size, or 0 */

  int   uudet;		/* valid encoded data. value indicates encoding */
  int   partno;		/* Mime-files have a part number within */
  int   maxpno;		/* ... plus the total number of parts   */

  char *sfname;		/* Associated source file */
  long startpos;	/* ftell() position where data starts */
  long length;		/* length of data */
} fileread;

/*
 * Structure for holding one part of a file, with some more information
 * about it. The UUPreProcessPart() function takes one a fileread structure
 * and produces this uufile structure.
 * Linked List, ordered by partno.
 **/

typedef struct _uufile {
  char     *filename;
  char     *subfname;
  char     *mimeid;
  char     *mimetype;
  int       partno;
  fileread *data;
  long      yefilesize;
  struct _uufile *NEXT;
} uufile;

extern void *uu_MsgCBArg;
extern void *uu_BusyCBArg;
extern void *uu_FileCBArg;
extern void *uu_FFCBArg;
extern void *uu_FNCBArg;

/*
 * variables
 */

extern int uu_autocheck;
extern int uu_rbuf;
extern int uu_wbuf;
#define UUSETBUF(fp,buff,size) if (size) setvbuf ((fp), ((buff) = malloc (size)), _IOFBF, (size))
#define UUCLRBUF(size,buff) if (size) free (buff)

extern int uu_fast_scanning;
extern int uu_bracket_policy;
extern int uu_verbose;
extern int uu_desperate;
extern int uu_ignreply;
extern int uu_debug;
extern int uu_errno;
extern int uu_dumbness;
extern int uu_overwrite;
extern int uu_ignmode;
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 int uu_dotdot;

extern char *uusavepath;
extern char *uuencodeext;

/*
 * Encoding/Decoding tables
 */

extern unsigned char UUEncodeTable[];
extern unsigned char XXEncodeTable[];
extern unsigned char B64EncodeTable[];
extern unsigned char BHEncodeTable[];

/*
 * String tables from uustring.c
 */

extern char *msgnames[];
extern char *codenames[];
extern char *uuretcodes[];

extern uulist *UUGlobalFileList;

/*
 * State of MIME variables and current progress
 */

extern int nofnum, mssdepth;
extern int mimseqno, lastvalid;
extern int lastenc;
extern scanstate  multistack[];
extern headers    localenv;
extern scanstate  sstate;
extern uuprogress progress;

/*
 * mallocable areas
 */

extern char *uugen_fnbuffer, *uugen_inbuffer;
extern char *uucheck_lastname, *uucheck_tempname;
extern char *uuestr_itemp, *uuestr_otemp;
extern char *uulib_msgstring, *uuncdl_fulline;
extern char *uuncdp_oline, *uuscan_shlline, *uuscan_shlline2;
extern char *uuscan_pvvalue, *uuscan_phtext;
extern char *uuscan_sdline, *uuscan_sdbhds1;
extern char *uuscan_sdbhds2, *uuscan_spline;
extern char *uuutil_bhwtmp;
extern char *uunconc_UUxlat, *uunconc_UUxlen;
extern char *uunconc_B64xlat, *uunconc_XXxlat;
extern char *uunconc_BHxlat, *uunconc_save;

#ifdef __cplusplus
extern "C" {
#endif

extern void   (*uu_MsgCallback)     (void *, char *, int);
extern int    (*uu_BusyCallback)    (void *, uuprogress *);
extern int    (*uu_FileCallback)    (void *, char *, char *, int);
extern char * (*uu_FNameFilter)     (void *, char *);
extern char * (*uu_FileNameCallback)(void *, char *, char *);

/*
 * Functions from uulib.c that aren't defined in 
 * Be careful about the definition with variable arguments.
 */

#if defined(STDC_HEADERS) || defined(HAVE_STDARG_H)
int		UUMessage		(char *, int, int, char *, ...);
#else
int		UUMessage		();
#endif
int		UUBusyPoll		(void);

/*
 * Functions from uucheck.c
 */

uufile *	UUPreProcessPart	(fileread *, int *);
int 		UUInsertPartToList	(uufile *);

/*
 * Functions from uuutil.c
 */

void 		UUkillfread 		(fileread *);
void	 	UUkillfile 		(uufile *);
void 		UUkilllist 		(uulist *);
void 		UUkillheaders 		(headers *);

fileread *	ScanPart 		(FILE *, char *, int *);

int		UUbhdecomp		(char *, char *,
				         char *, int *,
				         size_t, size_t, 
				         size_t *);
size_t		UUbhwrite		(char *, size_t, size_t, FILE *);

/*
 * Functions from uunconc.c
 */

int		UURepairData		(FILE *, char *, int, int *);

void 		UUInitConc		_ANSI_ARGS_((void));
int 		UUValidData		_ANSI_ARGS_((char *, int, int *));
size_t 		UUDecodeLine		_ANSI_ARGS_((char *, char *, int));
int		UUDecodeField		_ANSI_ARGS_((char *, char *, int));
int		UUDecodePart		_ANSI_ARGS_((FILE *, FILE *, int *,
						     long, int, int, char *));
int 		UUDecode 		_ANSI_ARGS_((uulist *));

/*
 * Message retrieval from uustring.c
 */

char *		uustring		(int);

/*
 * From uuscan.c
 */

int		UUScanHeader		(FILE *, headers *);

#ifdef __cplusplus
}
#endif
#endif
Convert-UUlib-1.5/uulib/uudeview.h0000644000000000000000000002323511244415726015654 0ustar  rootroot/*
 * This file is part of uudeview, the simple and friendly multi-part multi-
 * 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
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 */

#ifndef __UUDEVIEW_H__
#define __UUDEVIEW_H__

/*
 * This include file features all the definitions that should
 * be externally visible. This isn't much.
 *
 * $Id$
 */

#ifndef _ANSI_ARGS_
#ifdef PROTOTYPES
#define _ANSI_ARGS_(c)	c
#else
#define _ANSI_ARGS_(c)	()
#endif
#endif

/*
 * Message Types
 */

#define UUMSG_MESSAGE	(0)	/* just a message, nothing important */
#define UUMSG_NOTE	(1)	/* something that should be noticed */
#define UUMSG_WARNING	(2)	/* important msg, processing continues */
#define UUMSG_ERROR	(3)	/* processing has been terminated */
#define UUMSG_FATAL	(4)	/* decoder cannot process further requests */
#define UUMSG_PANIC	(5)	/* recovery impossible, app must terminate */

/*
 * Return Values
 */

#define UURET_OK	(0)	/* everything went fine */
#define UURET_IOERR	(1)	/* I/O Error - examine errno */
#define UURET_NOMEM	(2)	/* not enough memory */
#define UURET_ILLVAL	(3)	/* illegal value for operation */
#define UURET_NODATA	(4)	/* decoder didn't find any data */
#define UURET_NOEND	(5)	/* encoded data wasn't ended properly */
#define UURET_UNSUP	(6)	/* unsupported function (encoding) */
#define UURET_EXISTS	(7)	/* file exists (decoding) */
#define UURET_CONT	(8)	/* continue -- special from ScanPart */
#define UURET_CANCEL	(9)	/* operation canceled */

/*
 * File states, may be OR'ed
 */

#define UUFILE_READ	(0)	/* Read in, but not further processed */
#define UUFILE_MISPART	(1)	/* Missing Part(s) detected */
#define UUFILE_NOBEGIN	(2)	/* No 'begin' found */
#define UUFILE_NOEND	(4)	/* No 'end' found */
#define UUFILE_NODATA	(8)	/* File does not contain valid uudata */
#define UUFILE_OK	(16)	/* All Parts found, ready to decode */
#define UUFILE_ERROR	(32)	/* Error while decoding */
#define UUFILE_DECODED	(64)	/* Successfully decoded */
#define UUFILE_TMPFILE	(128)	/* Temporary decoded file exists */

/*
 * Encoding Types
 */

#define UU_ENCODED	(1)	/* UUencoded data   */
#define B64ENCODED	(2)	/* Mime-Base64 data */
#define XX_ENCODED	(3)	/* XXencoded data   */
#define BH_ENCODED	(4)	/* Binhex encoded   */
#define PT_ENCODED	(5)	/* Plain-Text encoded (MIME) */
#define QP_ENCODED	(6)	/* Quoted-Printable (MIME)   */
#define YENC_ENCODED	(7)	/* yEnc encoded */

/*
 * Option indices for GetOption / SetOption
 */

#define UUOPT_RBUF	(90)    /* file read I/O buffer size */
#define UUOPT_WBUF	(91)    /* file write I/O buffer size */
#define UUOPT_VERSION	(0)	/* version number MAJOR.MINORplPATCH (ro) */
#define UUOPT_FAST	(1)	/* assumes only one part per file */
#define UUOPT_DUMBNESS	(2)	/* switch off the program's intelligence */
#define UUOPT_BRACKPOL	(3)	/* give numbers in [] higher precendence */
#define UUOPT_VERBOSE	(4)	/* generate informative messages */
#define UUOPT_DESPERATE	(5)	/* try to decode incomplete files */
#define UUOPT_IGNREPLY	(6)	/* ignore RE:plies (off by default) */
#define UUOPT_OVERWRITE	(7)	/* whether it's OK to overwrite ex. files */
#define UUOPT_SAVEPATH	(8)	/* prefix to save-files on disk */
#define UUOPT_IGNMODE	(9)	/* ignore the original file mode */
#define UUOPT_DEBUG	(10)	/* print messages with FILE/LINE info */
#define UUOPT_ERRNO	(14)	/* get last error code for UURET_IOERR (ro) */
#define UUOPT_PROGRESS	(15)	/* retrieve progress information */
#define UUOPT_USETEXT	(16)	/* handle text messages */
#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 */
#define UUOPT_DOTDOT	(22)	/* .. unescaping has not yet been done on input files */
#define UUOPT_AUTOCHECK (23)    /* call checkgloballist after every part */

/*
 * Code for the "action" in the progress structure
 */

#define UUACT_IDLE	(0)	/* we don't do anything */
#define UUACT_SCANNING	(1)	/* scanning an input file */
#define UUACT_DECODING	(2)	/* decoding into a temp file */
#define UUACT_COPYING	(3)	/* copying temp to target */
#define UUACT_ENCODING	(4)	/* encoding a file */

/*
 * forward definition
 */

struct _uufile;

/*
 * Structure for holding the list of files that have been found
 * uufile items are inserted into this list with UUInsertPartToList
 * After inserting a bunch of files, UUCheckGlobalList must be called
 * to update the states.
 */

typedef struct _uulist {
  short    state;		/* Status as described by the macros above */
  short    mode;		/* file mode as found on begin line        */

  int      begin;		/* part number where begin was detected    */
  int      end;			/* part number where end was detected      */

  short    uudet;		/* Encoding type (see macros above)        */
  int      flags;		/* flags, especially for single-part files */

  long     size;		/* approximate size of resulting file      */
  char    *filename;		/* malloc'ed file name                     */
  char    *subfname;		/* malloc'ed ID from subject line          */
  char    *mimeid;		/* malloc'ed MIME-ID, if available         */
  char    *mimetype;		/* malloc'ed Content-Type, if available    */

  char    *binfile;		/* name of temp file, if already decoded   */

  struct _uufile *thisfile;	/* linked list of this file's parts        */

  int     *haveparts;		/* the parts we have (max. 256 are listed) */
  int     *misparts;		/* list of missing parts (max. 256)        */

  struct _uulist *NEXT;		/* next item of the list                   */
  struct _uulist *PREV;		/* previous item of the list               */
} uulist;

/*
 * The "progress" structure which is passed to the Busy Callback
 */

typedef struct {
  int  action;			/* see UUACT_* definitions above           */
  char curfile[256];		/* the file we are working on, incl. path  */
  int  partno;			/* part we're currently decoding           */
  int  numparts;		/* total number of parts of this file      */
  long fsize;			/* size of the current file                */
  int  percent;			/* % of _current part_                     */
  long foffset;			/* file offset -- internal use only        */
  long totsize;			/* file total size -- internal use only    */
} uuprogress;
  

/*
 * Externally visible Functions
 */

#ifndef UUEXPORT
#define UUEXPORT
#endif

#ifdef __cplusplus
extern "C" {
#endif

int	UUEXPORT UUInitialize		_ANSI_ARGS_((void));
int	UUEXPORT UUGetOption		_ANSI_ARGS_((int, int *, char *, int));
int	UUEXPORT UUSetOption		_ANSI_ARGS_((int, int, char *));
char *	UUEXPORT UUstrerror		_ANSI_ARGS_((int));
int	UUEXPORT UUSetMsgCallback	_ANSI_ARGS_((void *,
						     void (*) (void *, 
							       char *,
							       int)));
int	UUEXPORT UUSetBusyCallback	_ANSI_ARGS_((void *,
						     int (*) (void *,
							      uuprogress *),
						     long));
int	UUEXPORT UUSetFileCallback	_ANSI_ARGS_((void *,
						     int (*) (void *, char *,
							      char *, int)));
int	UUEXPORT UUSetFNameFilter	_ANSI_ARGS_((void *,
						     char * (*) (void *,
								 char *)));
int	UUEXPORT UUSetFileNameCallback	_ANSI_ARGS_((void *,
						     char * (*) (void *,
								 char *, char *)));
char *	UUEXPORT UUFNameFilter		_ANSI_ARGS_((char *));
int	UUEXPORT UULoadFile		_ANSI_ARGS_((char *, char *, int, int *));
int	UUEXPORT UULoadFileWithPartNo	_ANSI_ARGS_((char *, char *, int, int, int *));
uulist *UUEXPORT UUGetFileListItem	_ANSI_ARGS_((int));
int	UUEXPORT UURenameFile		_ANSI_ARGS_((uulist *, char *));
int	UUEXPORT UUDecodeToTemp		_ANSI_ARGS_((uulist *));
int	UUEXPORT UURemoveTemp		_ANSI_ARGS_((uulist *));
int	UUEXPORT UUDecodeFile		_ANSI_ARGS_((uulist *, char *));
int	UUEXPORT UUInfoFile		_ANSI_ARGS_((uulist *, void *,
						     int (*) (void *, 
							      char *)));
int	UUEXPORT UUSmerge		_ANSI_ARGS_((int));
int	UUEXPORT UUCleanUp		_ANSI_ARGS_((void));

int	UUEXPORT UUQuickDecode		_ANSI_ARGS_((FILE *, FILE *,
						     char *, long));

int	UUEXPORT UUEncodeMulti		_ANSI_ARGS_((FILE *, FILE *,
						     char *, int,
						     char *, char *, int));
int	UUEXPORT UUEncodePartial	_ANSI_ARGS_((FILE *, FILE *,
						     char *, int,
						     char *, char *,
						     int, int, long,
						     unsigned int *));
int	UUEXPORT UUEncodeToStream	_ANSI_ARGS_((FILE *, FILE *,
						     char *, int,
						     char *, int));
int	UUEXPORT UUEncodeToFile		_ANSI_ARGS_((FILE *, char *, int,
						     char *, char *, long));
int	UUEXPORT UUE_PrepSingle		_ANSI_ARGS_((FILE *, FILE *,
						     char *, int,
						     char *, int,
						     char *, char *,
						     char *, int));
int	UUEXPORT UUE_PrepPartial	_ANSI_ARGS_((FILE *, FILE *,
						     char *, int,
						     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));
void	UUEXPORT UUCheckGlobalList	(void);
#ifdef __cplusplus
}
#endif
#endif
Convert-UUlib-1.5/uulib/aclocal.m40000644000000000000000000001463610211640773015506 0ustar  rootrootdnl
dnl originally from ncftp 2.3.0
dnl added wi_EXTRA_PDIR and wi_ANSI_C
dnl $Id$
dnl
AC_DEFUN(wi_EXTRA_IDIR, [
incdir="$1"
if test -r $incdir ; then
	case "$CPPFLAGS" in
		*-I${incdir}*)
			# echo "   + already had $incdir" 1>&6
			;;
		*)
			if test "$CPPFLAGS" = "" ; then
				CPPFLAGS="-I$incdir"
			else
				CPPFLAGS="$CPPFLAGS -I$incdir"
			fi
			echo "   + found $incdir" 1>&6
			;;
	esac
fi
])
dnl
dnl
dnl
dnl
AC_DEFUN(wi_EXTRA_LDIR, [
libdir="$1"
if test -r $libdir ; then
	case "$LDFLAGS" in
		*-L${libdir}*)
			# echo "   + already had $libdir" 1>&6
			;;
		*)
			if test "$LDFLAGS" = "" ; then
				LDFLAGS="-L$libdir"
			else
				LDFLAGS="$LDFLAGS -L$libdir"
			fi
			echo "   + found $libdir" 1>&6
			;;
	esac
fi
])
dnl
dnl __FP__
dnl
dnl
AC_DEFUN(wi_EXTRA_PDIR, [
progdir="$1"
if test -r $progdir ; then
	case "$PATH" in
		*:${progdir}*)
			# echo "   + already had $progdir" 1>&6
			;;
		*${progdir}:*)
			# echo "   + already had $progdir" 1>&6
			;;
		*)
			if test "$PATH" = "" ; then
				PATH="$progdir"
			else
				PATH="$PATH:$progdir"
			fi
			echo "   + found $progdir" 1>&6
			;;
	esac
fi
])
dnl
dnl
dnl If you want to also look for include and lib subdirectories in the
dnl $HOME tree, you supply "yes" as the first argument to this macro.
dnl
dnl If you want to look for subdirectories in include/lib directories,
dnl you pass the names in argument 3, otherwise pass a dash.
dnl
AC_DEFUN(wi_EXTRA_DIRS, [echo "checking for extra include and lib directories..." 1>&6
ifelse([$1], yes, [dnl
b1=`cd .. ; pwd`
b2=`cd ../.. ; pwd`
exdirs="$HOME $j $b1 $b2 $prefix $2"
],[dnl
exdirs="$prefix $2"
])
subexdirs="$3"
if test "$subexdirs" = "" ; then
	subexdirs="-"
fi
for subexdir in $subexdirs ; do
if test "$subexdir" = "-" ; then
	subexdir=""
else
	subexdir="/$subexdir"
fi
for exdir in $exdirs ; do
	if test "$exdir" != "/usr" || test "$subexdir" != ""; then
		incdir="${exdir}/include${subexdir}"
		wi_EXTRA_IDIR($incdir)

		libdir="${exdir}/lib${subexdir}"
		wi_EXTRA_LDIR($libdir)

		progdir="${exdir}/bin${subexdirr}"
		wi_EXTRA_PDIR($progdir)
	fi
done
done
])
dnl
dnl
dnl
AC_DEFUN(wi_PROTOTYPES, [
AC_MSG_CHECKING(if the compiler supports function prototypes)
AC_TRY_COMPILE(,[extern void exit(int status);],[wi_cv_prototypes=yes
AC_DEFINE(PROTOTYPES)],wi_cv_prototypes=no)
AC_MSG_RESULT($wi_cv_prototypes)
])
dnl
dnl
dnl
AC_DEFUN(wi_ANSI_C, [
AC_MSG_CHECKING(ANSI-style function definitions)
AC_TRY_COMPILE(,[int blubb(int x) { return 0; }],[wi_cv_ansi_funcs=yes
AC_DEFINE(ANSI_FUNCS)],wi_cv_ansi_funcs=no)
AC_MSG_RESULT($wi_cv_ansi_funcs)
])
dnl
dnl
dnl
AC_DEFUN(wi_HEADER_SYS_SELECT_H, [
# See if  is includable after 
if test "$ac_cv_header_sys_time_h" = no ; then
AC_CHECK_HEADERS(sys/time.h sys/select.h)
else
AC_CHECK_HEADERS(sys/select.h)
fi
if test "$ac_cv_header_sys_select_h" = yes ; then
	AC_MSG_CHECKING([if  is compatible with ])
	selecth=yes
	if test "$ac_cv_header_sys_time_h" = yes ; then
		AC_TRY_COMPILE([#include 
		#include ],[
		fd_set a;
		struct timeval tmval;

		tmval.tv_sec = 0;],selecth=yes,selecth=no)

		if test "$selecth" = yes ; then
			AC_DEFINE(CAN_USE_SYS_SELECT_H)
		fi
	fi
	AC_MSG_RESULT($selecth)
fi
])
dnl
dnl
dnl
AC_DEFUN(wi_LIB_RESOLV, [
# See if we could access two well-known sites without help of any special
# libraries, like resolv.

AC_TRY_RUN([
#include 
#include 
#include 
#include 
 
main()
{
	struct hostent *hp1, *hp2;
	int result;

	hp1 = gethostbyname("gatekeeper.dec.com");
	hp2 = gethostbyname("ftp.ncsa.uiuc.edu");
	result = ((hp1 != (struct hostent *) 0) && (hp2 != (struct hostent *) 0));
	exit(! result);
}],look_for_resolv=no,look_for_resolv=yes,look_for_resolv=yes)

AC_MSG_CHECKING([if we need to look for -lresolv])
AC_MSG_RESULT($look_for_resolv)
if test "$look_for_resolv" = yes ; then
AC_CHECK_LIB(resolv,main)
else
	ac_cv_lib_resolv=no
fi
])
dnl
dnl
dnl

AC_DEFUN(wi_LIB_NSL, [
AC_MSG_CHECKING(if we can use -lnsl)
ac_save_LIBS="$LIBS";
LIBS="$LIBS -lnsl";
AC_CACHE_VAL(r_cv_use_libnsl, [
AC_TRY_RUN(
main() { if (getpwuid(getuid())) exit(0); exit(-1); },
nc_cv_use_libnsl=yes, nc_cv_use_libnsl=no, nc_cv_use_libnsl=no)
])
if test "$nc_cv_use_libnsl" = "no"; then LIBS="$ac_save_LIBS"; fi
AC_MSG_RESULT($nc_cv_use_libnsl)
])dnl

dnl
dnl
dnl

AC_DEFUN(nc_PATH_PROG_ZCAT, [
AC_PATH_PROG(GZCAT,gzcat)
AC_PATH_PROG(ZCAT,zcat)
if test "x$GZCAT" = x ; then
	if test "x$ZCAT" != x ; then
		# See if zcat is really gzcat.  gzcat has a --version option, regular
		# zcat does not.
		AC_MSG_CHECKING(if zcat is really gzcat in disguise)
		if $ZCAT --version 2> /dev/null ; then
			AC_DEFINE_UNQUOTED(GZCAT, "$ZCAT")
			AC_MSG_RESULT(yes)
		else
			AC_MSG_RESULT(no)
		fi
	fi
else
	AC_DEFINE_UNQUOTED(GZCAT, "$GZCAT")
fi

if test "x$ZCAT" != x ; then
	AC_DEFINE_UNQUOTED(ZCAT, "$ZCAT")
fi
])
dnl
dnl
dnl
AC_DEFUN(wi_SYSV_EXTRA_DIRS, [
# Use System V because their curses extensions are required.  This must
# be done early so we use the -I and -L in the library checks also.
# This is mostly a Solaris/SunOS hack.  Note that doing this will also
# use all of the other System V libraries and headers.

AC_MSG_CHECKING(for alternative System V libraries)
if test -f /usr/5include/curses.h ; then
	CPPFLAGS="$CPPFLAGS -I/usr/5include"
	LDFLAGS="$LDFLAGS -L/usr/5lib"
	AC_MSG_RESULT(yes)
else
	AC_MSG_RESULT(no)
fi
])
dnl
dnl
dnl
AC_DEFUN(wi_DEFINE_UNAME, [
# Get first 127 chars of all uname information.  Some folks have
# way too much stuff there, so grab only the first 127.
unam=`uname -a 2>/dev/null | cut -c1-127`
if test "$unam" != "" ; then
	AC_DEFINE_UNQUOTED(UNAME, "$unam")
fi
])
dnl
dnl
dnl
AC_DEFUN(wi_READLINE_WITH_NCURSES, [
# Readline and Ncurses could both define "backspace".
# Warn about this if we have both things in our definitions list.

if test "$ac_cv_lib_readline" = yes && test "$ac_cv_lib_ncurses" = yes ; then

AC_MSG_CHECKING(if readline and ncurses will link together)
j="$LIBS"
LIBS="-lreadline -lncurses"
AC_TRY_LINK(,[
readline("prompt");
endwin();
],k=yes,k=no)
if test "$k" = no ; then
	AC_MSG_RESULT(no)
	# Remove '-lreadline' from LIBS.
	LIBS=`echo $j | sed s/-lreadline//g`
	ac_cv_lib_readline=no
	AC_WARN([The versions of GNU readline and ncurses you have installed on this system
can't be used together, because they use the same symbol, backspace. If
possible, recompile one of the libraries with -Dbackspace=back_space, then
re-run configure.])

else
	AC_MSG_RESULT(yes)
	LIBS="$j"
fi

fi
])
dnl
dnl
dnl
Convert-UUlib-1.5/uulib/configure.in0000644000000000000000000000556711253744136016167 0ustar  rootrootdnl	This file is an input file used by the GNU "autoconf" program to
dnl	generate the file "configure", which tries to guess your system
dnl	configuration so that no manual editing of the Makefile should be
dnl	necessary
dnl
dnl $Id$
dnl

AC_INIT(uulib.c)
AC_PREREQ(2.9)
AC_CONFIG_HEADER(config.h)

#
# package revision
#
VERSION=0.5
PATCH=20

AC_ARG_WITH(cc,,CC=$with_cc)
AC_ARG_WITH(cflags,,CFLAGS=$with_cflags)

AC_PROG_CC
AC_PROG_CPP
wi_PROTOTYPES
AC_PROG_MAKE_SET
AC_PROG_RANLIB

if test "$wi_cv_prototypes" = no ; then
	AC_WARN([Your compiler does not support function prototyping and])
	AC_WARN([is not able to properly compile this package. What a pity.])
        AC_WARN([Get gcc, or any compiler that supports function prototypes.])
	exit 1
fi

#
# Checks for header files and library functions
#

AC_HEADER_STDC
AC_TYPE_SIZE_T
AC_HEADER_TIME
AC_CHECK_HEADERS(fcntl.h unistd.h memory.h malloc.h errno.h)
AC_CHECK_HEADERS(io.h sys/time.h)

CFLAGS="$CFLAGS -D_GNU_SOURCE"
AC_CHECK_FUNCS(gettimeofday fgetc_unlocked)
dnl AC_CHECK_FUNCS(strcasecmp strncasecmp strcasestr)

AC_CHECK_FUNC(tempnam,,AC_DEFINE(tempnam,FP_tempnam))

AC_CHECK_FUNC(chmod,AC_DEFINE(HAVE_CHMOD))
AC_CHECK_FUNC(umask,AC_DEFINE(HAVE_UMASK))
AC_CHECK_FUNC(mkstemp,AC_DEFINE(HAVE_MKSTEMP))

#
# strerror might be internally defined. this would cause a
# CHECK_FUNCS(strerror) to fail because it'd be called with
# zero arguments. So use our own code.
#
AC_MSG_CHECKING([for strerror])
AC_TRY_LINK([
char *blubb() { return (char *) strerror (42); }
],[
(void) blubb();
],have_strerror=yes,AC_DEFINE(strerror,FP_strerror)
have_strerror=no)
AC_MSG_RESULT($have_strerror)

AC_MSG_CHECKING([for stdin])
AC_TRY_LINK([
#include 
char *blubb() { FILE *in, *out; in=stdin; out=stdout; return (char*)0; }
],[
(void) blubb();
],have_stdio=yes,AC_DEFINE(HAVE_STDIO)
have_stdio=no)
AC_MSG_RESULT($have_stdio)

if test "$ac_cv_header_stdc" = "no" ; then
	AC_CHECK_HEADERS(stdarg.h varargs.h)
	if test "$ac_cv_header_stdarg_h" = "no" ; then
	if test "$ac_cv_header_varargs_h" = "no" ; then
		AC_MSG_ERROR([neither stdarg.h nor varargs.h present])
	fi
	fi
fi

#
# Check whether this is a DOS-Based system. Another bogus test.
# Don't even bother to print a message. This code is needed so
# that autoheader includes the #undef into the final config.h
# and we can change the definition by hand on a really DOS
# system (where ./configure doesn't work anyway ...)
#

if false ; then
	AC_DEFINE(SYSTEM_DOS)
	AC_DEFINE(SYSTEM_QUICKWIN)
	AC_DEFINE(SYSTEM_WINDLL)
	AC_DEFINE(SYSTEM_OS2)
fi

#
# On some systems (so far, OS2 and WINDOWS), functions that are exported
# from a DLL must be declared specifically.
#

AC_DEFINE_UNQUOTED(UUEXPORT,)
AC_DEFINE_UNQUOTED(TOOLEXPORT,)

#
# set version number
#
AC_MSG_CHECKING([version number])
version_number="$VERSION"pl"$PATCH"
AC_MSG_RESULT($version_number)
AC_SUBST(VERSION)
AC_SUBST(PATCH)

#
# done
#

AC_OUTPUT(Makefile)

Convert-UUlib-1.5/uulib/crc32.c0000644000000000000000000001227511244412637014726 0ustar  rootroot/* crc32.c -- compute the CRC-32 of a data stream
  Copyright (C) 1995-1998 Mark Adler

  This software is provided 'as-is', without any express or implied
  warranty.  In no event will the authors be held liable for any damages
  arising from the use of this software.

  Permission is granted to anyone to use this software for any purpose,
  including commercial applications, and to alter it and redistribute it
  freely, subject to the following restrictions:

  1. The origin of this software must not be misrepresented; you must not
     claim that you wrote the original software. If you use this software
     in a product, an acknowledgment in the product documentation would be
     appreciated but is not required.
  2. Altered source versions must be plainly marked as such, and must not be
     misrepresented as being the original software.
  3. This notice may not be removed or altered from any source distribution.

  Jean-loup Gailly        Mark Adler
  jloup@gzip.org          madler@alumni.caltech.edu
*/

#include 

/* ========================================================================
 * Table of CRC-32's of all single-byte values (made by make_crc_table)
 */
static const crc32_t crc_table[256] = {
  0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L,
  0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L,
  0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L,
  0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL,
  0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L,
  0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L,
  0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L,
  0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL,
  0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L,
  0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL,
  0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L,
  0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L,
  0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L,
  0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL,
  0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL,
  0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L,
  0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL,
  0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L,
  0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L,
  0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L,
  0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL,
  0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L,
  0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L,
  0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL,
  0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L,
  0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L,
  0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L,
  0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L,
  0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L,
  0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL,
  0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL,
  0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L,
  0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L,
  0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL,
  0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL,
  0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L,
  0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL,
  0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L,
  0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL,
  0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L,
  0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL,
  0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L,
  0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L,
  0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL,
  0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L,
  0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L,
  0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L,
  0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L,
  0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L,
  0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L,
  0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL,
  0x2d02ef8dL
};

/* ========================================================================= */
#define DO1(buf) crc = crc_table[(crc ^ (*buf++)) & 0xff] ^ (crc >> 8);
#define DO2(buf)  DO1(buf); DO1(buf);
#define DO4(buf)  DO2(buf); DO2(buf);
#define DO8(buf)  DO4(buf); DO4(buf);

/* ========================================================================= */
crc32_t crc32(crc32_t crc, const unsigned char *buf, unsigned int len)
{
    if (buf == Z_NULL) return 0L;
    crc = crc ^ 0xffffffffL;
    while (len >= 8)
    {
      DO8(buf);
      len -= 8;
    }
    if (len) do {
      DO1(buf);
    } while (--len);
    return crc ^ 0xffffffffL;
}
Convert-UUlib-1.5/uulib/fptools.c0000644000000000000000000002065311244426562015501 0ustar  rootroot/*
 * fptools.c, some helper functions for getcgi.c and uu(en|de)view
 *
 * Distributed under the terms of the GNU General Public License.
 * Use and be happy.
 */

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#ifdef SYSTEM_WINDLL
#include 
#endif
#ifdef SYSTEM_OS2
#include 
#endif

/*
 * This file provides replacements for some handy functions that aren't
 * available on all systems, like most of the  functions. They
 * should behave exactly as their counterparts. There are also extensions
 * that aren't portable at all (like strirstr etc.).
 * The proper behaviour in a configure script is as follows:
 *    AC_CHECK_FUNC(strrchr,AC_DEFINE(strrchr,_FP_strrchr))
 * This way, the (probably less efficient) replacements will only be used
 * where it is not provided by the default libraries. Be aware that this
 * does not work with replacements that just shadow wrong behaviour (like
 * _FP_free) or provide extended functionality (FP_gets).
 * The above is not used in the uuenview/uudeview configuration script,
 * since both only use the replacement functions in non-performance-cri-
 * tical sections (except for _FP_tempnam and FP_strerror, where some
 * functionality of the original would be lost).
 */

#include 
#include 

#ifdef STDC_HEADERS
#include 
#include 
#endif
#ifdef HAVE_MALLOC_H
#include 
#endif
#ifdef HAVE_UNISTD_H
#include 
#endif
#ifdef HAVE_MEMORY_H
#include 
#endif

#include 

#if 0
#ifdef SYSTEM_WINDLL
BOOL _export WINAPI
DllEntryPoint (HINSTANCE hInstance, DWORD seginfo,
	       LPVOID lpCmdLine)
{
  /* Don't do anything, so just return true */
  return TRUE;
}
#endif
#endif

char * fptools_id = "$Id$";

/*
 * some versions of free can't handle a NULL pointer properly
 * (ANSI says, free ignores a NULL pointer, but some machines
 * prefer to SIGSEGV on it)
 */

void TOOLEXPORT
_FP_free (void *ptr)
{
  if (ptr) free (ptr);
}

/*
 * This is non-standard, so I'm defining my own
 */

char * TOOLEXPORT
_FP_strdup (char *string)
{
  char *result;

  if (string == NULL)
    return NULL;

  if ((result = (char *) malloc (strlen (string) + 1)) == NULL)
    return NULL;

  strcpy (result, string);
  return result;
}

/*
 * limited-length string copy. this function behaves differently from
 * the original in that the dest string is always terminated with a
 * NULL character.
 */

char * TOOLEXPORT
_FP_strncpy (char *dest, char *src, int length)
{
  char *odest=dest;
  if (src == NULL || dest == NULL || length-- <= 0)
    return dest;

  while (length-- && *src)
    *dest++ = *src++;

  *dest++ = '\0';
  return odest;
}

/*
 * duplicate a memory area
 */

void * TOOLEXPORT
_FP_memdup (void *ptr, int len)
{
  void *result;

  if (ptr == NULL)
    return NULL;

  if ((result = malloc (len)) == NULL)
    return NULL;

  memcpy (result, ptr, len);
  return result;
}

/*
 * case-insensitive compare
 */

#ifndef FP_stricmp
int TOOLEXPORT
_FP_stricmp (char *str1, char *str2)
{
  if (str1==NULL || str2==NULL)
    return -1;

  while (*str1) {
    if (tolower(*str1) != tolower(*str2))
      break;
    str1++;
    str2++;
  }
  return (tolower (*str1) - tolower (*str2));
}
#endif

#ifndef FP_strnicmp
int TOOLEXPORT
_FP_strnicmp (char *str1, char *str2, int count)
{
  if (str1==NULL || str2==NULL)
    return -1;

  while (*str1 && count) {
    if (tolower(*str1) != tolower(*str2))
      break;
    str1++;
    str2++;
    count--;
  }
  return count ? (tolower (*str1) - tolower (*str2)) : 0;
}
#endif

char * TOOLEXPORT
_FP_strpbrk (char *str, char *accept)
{
  char *ptr;

  if (str == NULL)
    return NULL;
  if (accept == NULL || *accept == '\0')
    return str;

  for (; *str; str++)
    for (ptr=accept; *ptr; ptr++)
      if (*str == *ptr)
	return str;

  return NULL;
}

/*
 * autoconf also complains about this one
 */

char * TOOLEXPORT
_FP_strtok (char *str1, char *str2)
{
  static char *optr;
  char *ptr;

  if (str2 == NULL)
    return NULL;

  if (str1) {
    optr = str1;
  }
  else {
    if (*optr == '\0')
      return NULL;
  }

  while (*optr && strchr (str2, *optr))	/* look for beginning of token */
    optr++;

  if (*optr == '\0')			/* no token found */
    return NULL;

  ptr = optr;
  while (*optr && strchr (str2, *optr) == NULL) /* look for end of token */
    optr++;

  if (*optr) {
    *optr++ = '\0';
  }
  return ptr;
}

/*
 * case insensitive strstr.
 */

#ifndef FP_stristr
char * TOOLEXPORT
_FP_stristr (char *str1, char *str2)
{
  char *ptr1, *ptr2;

  if (str1==NULL)
    return NULL;
  if (str2==NULL)
    return str1;

  while (*(ptr1=str1)) {
    for (ptr2=str2;
	 *ptr1 && *ptr2 && tolower(*ptr1)==tolower(*ptr2);
	 ptr1++, ptr2++)
      /* empty loop */ ;

    if (*ptr2 == '\0')
      return str1;
    str1++;
  }
  return NULL;
}
#endif

/*
 * Nice fake of the real (non-standard) one
 */

char * TOOLEXPORT
_FP_strrstr (char *ptr, char *str)
{
  char *found=NULL, *new, *iter=ptr;

  if (ptr==NULL || str==NULL)
    return NULL;

  if (*str == '\0')
    return ptr;

  while ((new = _FP_strstr (iter, str)) != NULL) {
    found = new;
    iter  = new + 1;
  }
  return found;
}

char * TOOLEXPORT
_FP_strirstr (char *ptr, char *str)
{
  char *found=NULL, *iter=ptr, *new;

  if (ptr==NULL || str==NULL)
    return NULL;
  if (*str == '\0')
    return ptr;

  while ((new = _FP_stristr (iter, str)) != NULL) {
    found = new;
    iter  = new + 1;
  }
  return found;
}

/*
 * convert whole string to case
 */

char * TOOLEXPORT
_FP_stoupper (char *input)
{
  char *iter = input;

  if (input == NULL)
    return NULL;

  while (*iter) {
    *iter = toupper (*iter);
    iter++;
  }
  return input;
}

char * TOOLEXPORT
_FP_stolower (char *input)
{
  char *iter = input;

  if (input == NULL)
    return NULL;

  while (*iter) {
    *iter = tolower (*iter);
    iter++;
  }
  return input;
}

/*
 * string matching with wildcards
 */

int TOOLEXPORT
_FP_strmatch (char *string, char *pattern)
{
  char *p1 = string, *p2 = pattern;

  if (pattern==NULL || string==NULL)
    return 0;

  while (*p1 && *p2) {
    if (*p2 == '?') {
      p1++; p2++;
    }
    else if (*p2 == '*') {
      if (*++p2 == '\0')
	return 1;
      while (*p1 && *p1 != *p2)
	p1++;
    }
    else if (*p1 == *p2) {
      p1++; p2++;
    }
    else
      return 0;
  }
  if (*p1 || *p2)
    return 0;

  return 1;
}

char * TOOLEXPORT
_FP_strrchr (char *string, int tc)
{
  char *ptr;

  if (string == NULL || !*string)
    return NULL;

  ptr = string + strlen (string) - 1;

  while (ptr != string && *ptr != tc)
    ptr--;

  if (*ptr == tc)
    return ptr;

  return NULL;
}

/*
 * strip directory information from a filename. Works only on DOS and
 * Unix systems so far ...
 */

char * TOOLEXPORT
_FP_cutdir (char *filename)
{
  char *ptr;

  if (filename == NULL)
    return NULL;

  if ((ptr = _FP_strrchr (filename, '/')) != NULL)
    ptr++;
  else if ((ptr = _FP_strrchr (filename, '\\')) != NULL)
    ptr++;
  else
    ptr = filename;

  return ptr;
}

/*
 * My own fgets function. It handles all kinds of line terminators
 * properly: LF (Unix), CRLF (DOS) and CR (Mac).
 */
/* (schmorp) the buffer is always written to, and no LF is stored at the end */
char * TOOLEXPORT
_FP_fgets (char *buf, int n, FILE *stream)
{
  static char format[64];
  static int format_n = 0;
  char *cp = buf;
  int res;
  int c;

  /* shield against buffer overflows caused by "255 - bytes_left"-kind of bugs when bytes_left > 255 */
  if (n <= 0)
    return NULL;

  if (format_n != n)
    {
      sprintf (format, "%%%d[^\015\012]", n - 1);
      format_n = n;
    }

  *buf = 0; /* fscanf return s0 on empty lines */
  res = fscanf (stream, format, buf);

  if (res == EOF)
    return 0; /* an error occured */

  /* skip line endings */
  for (;;)
    {
      c = _FP_fgetc (stream);

      if (c == '\012') /* LF */
        return buf;
      else if (c == '\015') /* CR */
        {
          c = _FP_fgetc (stream);
          if (c != '\012') /* CR LF? */
            ungetc (c, stream);

          return buf;
        }
      else if (c == EOF)
        return 0; /* error */

      /* skip remaining line */
    }
}

/*
 * A replacement strerror function that just returns the error code
 */

char * TOOLEXPORT
_FP_strerror (int errcode)
{
  static char number[8];

  sprintf (number, "%03d", errcode);

  return number;
}
#ifndef HAVE_MKSTEMP
/*
 * tempnam is not ANSI, but tmpnam is. Ignore the prefix here.
 */

char * TOOLEXPORT
_FP_tempnam (char *dir, char *pfx)
{
  return _FP_strdup (tmpnam (NULL));
}
#endif /* HAVE_MKSTEMP */
Convert-UUlib-1.5/uulib/uulib.c0000644000000000000000000007740012547615545015145 0ustar  rootroot/*
 * This file is part of uudeview, the simple and friendly multi-part multi-
 * 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
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 */

/*
 * This file implements the externally visible functions, as declared
 * in uudeview.h, and some internal interfacing functions
 */

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#ifdef SYSTEM_WINDLL
#include 
#endif
#ifdef SYSTEM_OS2
#include 
#endif

#include 
#include 
#include 

#ifdef HAVE_FCNTL_H
#include 
#endif

#ifdef STDC_HEADERS
#include 
#include 
#include 
#else
#ifdef HAVE_STDARG_H
#include 
#else
#ifdef HAVE_VARARGS_H
#include 
#endif
#endif
#endif

#ifdef HAVE_UNISTD_H
#include 
#endif

#ifdef TIME_WITH_SYS_TIME
# include 
# include 
#else
# ifdef HAVE_SYS_TIME_H
#  include 
# else
#  include 
# endif
#endif

#ifdef HAVE_ERRNO_H
#include 
#endif

/* to get open() in Windows */
#ifdef HAVE_IO_H
#include 
#endif

#include 
#include 
#include 
#include 

#include "safealloc.c"

char * uulib_id = "$Id$";

#ifdef SYSTEM_WINDLL
BOOL _export WINAPI 
DllEntryPoint (HINSTANCE hInstance, DWORD seginfo,
	       LPVOID lpCmdLine)
{
  /* Don't do anything, so just return true */
  return TRUE;
}
#endif

/*
 * In DOS, we must open the file binary, O_BINARY is defined there
 */

#ifndef O_BINARY
#define O_BINARY      0
#endif

/* for braindead systems */
#ifndef SEEK_SET
#ifdef L_BEGIN
#define SEEK_SET L_BEGIN
#else
#define SEEK_SET 0
#endif
#endif

/*
 * Callback functions and their opaque arguments
 */

void   (*uu_MsgCallback)     (void *, char *, int)         = NULL;
int    (*uu_BusyCallback)    (void *, uuprogress *)        = NULL;
int    (*uu_FileCallback)    (void *, char *, char *, int) = NULL;
char * (*uu_FNameFilter)     (void *, char *)              = NULL;
char * (*uu_FileNameCallback)(void *, char *, char *);
;
void *uu_MsgCBArg  = NULL;
void *uu_BusyCBArg = NULL;
void *uu_FileCBArg = NULL;
void *uu_FFCBArg   = NULL;
void *uu_FNCBArg;

int uu_autocheck = 1;           /* call UUCheckGlobaList after every part */

/* I/O buffer sizes */
int uu_rbuf = 0;
int uu_wbuf = 0;

/*
 * Global variables
 */

int uu_fast_scanning = 0;	/* assumes at most 1 part per file          */
int uu_bracket_policy = 0;	/* gives part numbers in [] higher priority */
int uu_verbose = 1;		/* enables/disables messages¬es          */
int uu_desperate = 0;		/* desperate mode                           */
int uu_ignreply = 0;		/* ignore replies                           */
int uu_debug = 0;		/* debugging mode (print __FILE__/__LINE__) */
int uu_errno = 0;		/* the errno that caused this UURET_IOERR   */
int uu_dumbness = 0;		/* switch off the program's intelligence    */
int uu_overwrite = 1;		/* whether it's ok to overwrite ex. files   */
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          */
int uu_dotdot = 0;		/* dot-unescaping has not yet been done     */

headercount hlcount = {
  3,			        /* restarting after a MIME body             */
  2,                            /* after useful data in freestyle mode      */
  1                             /* after useful data and an empty line      */
};

/*
 * version string
 */

char uulibversion[256] = VERSION "pl" PATCH;

/*
 * prefix to the files on disk, usually a path name to save files to
 */

char *uusavepath;

/*
 * extension to use when encoding single-part files
 */

char *uuencodeext;

/*
 * areas to malloc
 */

char *uulib_msgstring;
char *uugen_inbuffer;
char *uugen_fnbuffer;

/*
 * The Global List of Files
 */

uulist *UUGlobalFileList = NULL;

/*
 * time values for BusyCallback. msecs is MILLIsecs here
 */

static long uu_busy_msecs = 0;	/* call callback function each msecs */
static long uu_last_secs  = 0;	/* secs  of last call to callback */
static long uu_last_usecs = 0;	/* usecs of last call to callback */

/*
 * progress information
 */

uuprogress progress;

/*
 * Linked list of files we want to delete after decoding
 */

typedef struct _itbd {
  char *fname;
  struct _itbd *NEXT;
} itbd;
static itbd * ftodel = NULL;

/*
 * for the busy poll
 */

unsigned long uuyctr;

/*
 * Areas to allocate. Instead of using static memory areas, we malloc()
 * the memory in UUInitialize() and release them in UUCleanUp to prevent
 * blowing up of the binary size
 * This is a table with the pointers to allocate and required sizes.
 * They are guaranteed to be never NULL.
 */

typedef struct {
  char **ptr;
  size_t size;
} allomap;

static allomap toallocate[] = {
  { &uugen_fnbuffer,    4096 },  /* generic filename buffer */
  { &uugen_inbuffer,    1024 },  /* generic input data buffer */
  { &uucheck_lastname,   256 },	 /* from uucheck.c */
  { &uucheck_tempname,   256 },
  { &uuestr_itemp,       256 },  /* from uuencode.c:UUEncodeStream() */
  { &uuestr_otemp,      1024 },
  { &uulib_msgstring,   1024 },  /* from uulib.c:UUMessage() */
  { &uuncdl_fulline,    1201 },  /* from uunconc.c:UUDecodeLine() */
  { &uuncdp_oline,      3600 },  /* from uunconc.c:UUDecodePart() */
  { &uunconc_UUxlat,     256 * sizeof (int) },  /* from uunconc.c:toplevel */
  { &uunconc_UUxlen,      64 * sizeof (int) },
  { &uunconc_B64xlat,    256 * sizeof (int) },
  { &uunconc_XXxlat,     256 * sizeof (int) },
  { &uunconc_BHxlat,     256 * sizeof (int) },
  { &uunconc_save,    3*1200 },  /* from uunconc.c:decoding buffer */
  { &uuscan_shlline,    1024 },  /* from uuscan.c:ScanHeaderLine() */
  { &uuscan_shlline2,   1024 },  /* from uuscan.c:ScanHeaderLine() */
  { &uuscan_pvvalue,     300 },  /* from uuscan.c:ParseValue() */
  { &uuscan_phtext,      300 },  /* from uuscan.c:ParseHeader() */
  { &uuscan_sdline,     1025 },  /* from uuscan.c:ScanData(), +1 for UURepairData */
  { &uuscan_sdbhds1,    1300 },  /* 1024 for line in UUScan + 256 potential overhead UUDecodeLine */
  { &uuscan_sdbhds2,    1300 },  /* 1024 for line in UUScan + 256 potential overhead UUDecodeLine */
  { &uuscan_spline,     1024 },  /* from uuscan.c:ScanPart() */
  { &uuutil_bhwtmp,      300 },  /* from uuutil.c:UUbhwrite() */
  { NULL, 0 }
};

/*
 * Handle the printing of messages. Works like printf.
 */

#if defined(STDC_HEADERS) || defined(HAVE_STDARG_H)
int
UUMessage (char *file, int line, int level, char *format, ...)
#else
int
UUMessage (va_alist)
  va_dcl
#endif
{
  int msgofs;
#if defined(STDC_HEADERS) || defined(HAVE_STDARG_H)
  va_list ap;

  va_start (ap, format);
#else
  char *file, *format;
  int   line, level;
  va_list ap;

  va_start (ap);
  file   = va_arg (ap, char *);
  line   = va_arg (ap, int);
  level  = va_arg (ap, int);
  format = va_arg (ap, char *);
#endif

  if (uu_debug) {
    snprintf (uulib_msgstring, 1024,  "%s(%d): %s", file, line, msgnames[level]);
    msgofs = strlen (uulib_msgstring);
  }
  else {
    snprintf (uulib_msgstring, 1024, "%s", msgnames[level]);
    msgofs = strlen (uulib_msgstring);
  }

  if (uu_MsgCallback && (level>UUMSG_NOTE || uu_verbose)) {
    vsnprintf (uulib_msgstring + msgofs, 1024 - msgofs, format, ap);

    (*uu_MsgCallback) (uu_MsgCBArg, uulib_msgstring, level);
  }

  va_end (ap);

  return UURET_OK;
}

/*
 * Call the Busy Callback from time to time. This function must be
 * polled from the Busy loops.
 */

int
UUBusyPoll (void)
{
#ifdef HAVE_GETTIMEOFDAY
  struct timeval tv;
  long msecs;

  if (uu_BusyCallback) {
    (void) gettimeofday (&tv, NULL);

    msecs = 1000*(tv.tv_sec-uu_last_secs)+(tv.tv_usec-uu_last_usecs)/1000;

    if (uu_last_secs==0 || msecs > uu_busy_msecs) {
      uu_last_secs  = tv.tv_sec;
      uu_last_usecs = tv.tv_usec;

      return (*uu_BusyCallback) (uu_BusyCBArg, &progress);
    }
  }
#else
  time_t now;
  long msecs;

  if (uu_BusyCallback) {
    if (uu_busy_msecs <= 0) {
      msecs = 1;
    }
    else {
      now   = time(NULL);
      msecs = 1000 * (now - uu_last_secs);
    }

    if (uu_last_secs==0 || msecs > uu_busy_msecs) {
      uu_last_secs  = now;
      uu_last_usecs = 0;

      return (*uu_BusyCallback) (uu_BusyCBArg, &progress);
    }
  }
#endif

  return 0;
}

/*
 * Initialization function
 */

int UUEXPORT
UUInitialize (void)
{
  allomap *aiter;

  progress.action     = 0;
  progress.curfile[0] = '\0';

  ftodel = NULL;

  uusavepath  = NULL;
  uuencodeext = NULL;

  mssdepth = 0;
  memset (&localenv, 0, sizeof (headers));
  memset (&sstate,   0, sizeof (scanstate));

  nofnum    = 0;
  mimseqno  = 0;
  lastvalid = 0;
  lastenc   = 0;
  uuyctr    = 0;

  /*
   * Allocate areas
   */

  for (aiter=toallocate; aiter->ptr; aiter++)
    *(aiter->ptr) = NULL;

  for (aiter=toallocate; aiter->ptr; aiter++) {
    if ((*(aiter->ptr) = (char *) safe_alloc (aiter->size)) == NULL) {
      /*
       * oops. we may not print a message here, because we need these
       * areas (uulib_msgstring) in UUMessage()
       */
      for (aiter=toallocate; aiter->ptr; aiter++) {
	safe_free (*(aiter->ptr), aiter->size);
      }
      return UURET_NOMEM;
    }
  }

  /*
   * Must be called after areas have been malloced
   */

  UUInitConc ();

  return UURET_OK;
}

/*
 * Set and get Options
 */

int UUEXPORT
UUGetOption (int option, int *ivalue, char *cvalue, int clength)
{
  int result;

  switch (option) {
  case UUOPT_RBUF:
    *ivalue = uu_rbuf;
    result = 0;
    break;
  case UUOPT_WBUF:
    *ivalue = uu_wbuf;
    result = 0;
    break;
  case UUOPT_VERSION:
    _FP_strncpy (cvalue, uulibversion, clength);
    result = 0;
    break;
  case UUOPT_FAST:
    if (ivalue) *ivalue = uu_fast_scanning;
    result = uu_fast_scanning;
    break;
  case UUOPT_DUMBNESS:
    if (ivalue) *ivalue = uu_dumbness;
    result = uu_dumbness;
    break;
  case UUOPT_BRACKPOL:
    if (ivalue) *ivalue = uu_bracket_policy;
    result = uu_bracket_policy;
    break;
  case UUOPT_VERBOSE:
    if (ivalue) *ivalue = uu_verbose;
    result = uu_verbose;
    break;
  case UUOPT_DESPERATE:
    if (ivalue) *ivalue = uu_desperate;
    result = uu_desperate;
    break;
  case UUOPT_IGNREPLY:
    if (ivalue) *ivalue = uu_ignreply;
    result = uu_ignreply;
    break;
  case UUOPT_DEBUG:
    if (ivalue) *ivalue = uu_debug;
    result = uu_debug;
    break;
  case UUOPT_ERRNO:
    if (ivalue) *ivalue = uu_errno;
    result = uu_errno;
    break;
  case UUOPT_OVERWRITE:
    if (ivalue) *ivalue = uu_overwrite;
    result = uu_overwrite;
    break;
  case UUOPT_SAVEPATH:
    _FP_strncpy (cvalue, uusavepath, clength);
    result = 0;
    break;
  case UUOPT_PROGRESS:
    if (clength==sizeof(uuprogress)) {
      memcpy (cvalue, &progress, sizeof (uuprogress));
      result = 0;
    }
    else
      result = -1;
    break;
  case UUOPT_IGNMODE:
    if (ivalue) *ivalue = uu_ignmode;
    result = uu_ignmode;
    break;
  case UUOPT_USETEXT:
    if (ivalue) *ivalue = uu_handletext;
    result = uu_handletext;
    break;
  case UUOPT_PREAMB:
    if (ivalue) *ivalue = uu_usepreamble;
    result = uu_usepreamble;
    break;
  case UUOPT_TINYB64:
    if (ivalue) *ivalue = uu_tinyb64;
    result = uu_tinyb64;
    break;
  case UUOPT_ENCEXT:
    _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;
  case UUOPT_DOTDOT:
    if (ivalue) *ivalue = uu_dotdot;
    result = uu_dotdot;
    break;
  case UUOPT_AUTOCHECK:
    if (ivalue) *ivalue = uu_autocheck;
    result = uu_autocheck;
    break;
  default:
    return -1;
  }
  return result;
}

int UUEXPORT
UUSetOption (int option, int ivalue, char *cvalue)
{
  switch (option) {
  case UUOPT_RBUF:
    uu_rbuf = ivalue;
    break;
  case UUOPT_WBUF:
    uu_wbuf = ivalue;
    break;
  case UUOPT_FAST:
    uu_fast_scanning  = ivalue;
    break;
  case UUOPT_DUMBNESS:
    uu_dumbness       = ivalue;
    break;
  case UUOPT_BRACKPOL:
    uu_bracket_policy = ivalue;
    break;
  case UUOPT_VERBOSE:
    uu_verbose        = ivalue;
    break;
  case UUOPT_DESPERATE:
    uu_desperate      = ivalue;
    break;
  case UUOPT_IGNREPLY:
    uu_ignreply       = ivalue;
    break;
  case UUOPT_DEBUG:
    uu_debug          = ivalue;
    break;
  case UUOPT_OVERWRITE:
    uu_overwrite      = ivalue;
    break;
  case UUOPT_SAVEPATH:
    _FP_free (uusavepath);
    uusavepath = _FP_strdup (cvalue);
    break;
  case UUOPT_IGNMODE:
    uu_ignmode = ivalue;
    break;
  case UUOPT_USETEXT:
    uu_handletext = ivalue;
    break;
  case UUOPT_PREAMB:
    uu_usepreamble = ivalue;
    break;
  case UUOPT_TINYB64:
    uu_tinyb64 = ivalue;
    break;
  case UUOPT_ENCEXT:
    _FP_free (uuencodeext);
    uuencodeext = _FP_strdup (cvalue);
    break;
  case UUOPT_REMOVE:
    uu_remove_input = ivalue;
    break;
  case UUOPT_MOREMIME:
    uu_more_mime = ivalue;
    break;
  case UUOPT_DOTDOT:
    uu_dotdot = ivalue;
    break;
  case UUOPT_AUTOCHECK:
    uu_autocheck = ivalue;
    break;
  default:
    return UURET_ILLVAL;
  }
  return UURET_OK;
}

char * UUEXPORT
UUstrerror (int code)
{
  return uuretcodes[code];
}

/*
 * Set the various Callback functions
 */

int UUEXPORT
UUSetMsgCallback (void *opaque, 
		  void (*func) (void *, char *, int))
{
  uu_MsgCallback = func;
  uu_MsgCBArg    = opaque;

  return UURET_OK;
}

int UUEXPORT
UUSetBusyCallback (void *opaque,
		   int (*func) (void *, uuprogress *),
		   long msecs)
{
  uu_BusyCallback = func;
  uu_BusyCBArg    = opaque;
  uu_busy_msecs   = msecs;

  return UURET_OK;
}

int UUEXPORT
UUSetFileCallback (void *opaque,
		   int (*func) (void *, char *, char *, int))
{
  uu_FileCallback = func;
  uu_FileCBArg    = opaque;

  return UURET_OK;
}

int UUEXPORT
UUSetFNameFilter (void *opaque,
		  char * (*func) (void *, char *))
{
  uu_FNameFilter = func;
  uu_FFCBArg     = opaque;

  return UURET_OK;
}

int UUEXPORT
UUSetFileNameCallback (void *opaque,
		       char * (*func) (void *, char *, char *))
{
  uu_FileNameCallback = func;
  uu_FNCBArg          = opaque;

  return UURET_OK;
}

/*
 * Return a pointer to the nth element of the GlobalFileList
 * zero-based, returns NULL if item is too large.
 */

uulist * UUEXPORT
UUGetFileListItem (int item)
{
  uulist *iter=UUGlobalFileList;

  if (item < 0)
    return NULL;
  while (item && iter) {
    iter = iter->NEXT;
    item--;
  }
  return iter;
}

/*
 * call the current filter
 */

char * UUEXPORT
UUFNameFilter (char *fname)
{
  if (uu_FNameFilter)
    return (*uu_FNameFilter) (uu_FFCBArg, fname);

  return fname;
}

/*
 * Load a File. We call ScanPart repeatedly until at EOF and
 * add the parts to UUGlobalFileList
 */

int UUEXPORT
UULoadFile (char *filename, char *fileid, int delflag, int *partcount)
{
  return UULoadFileWithPartNo(filename, fileid, delflag, -1, partcount);
}

int UUEXPORT
UULoadFileWithPartNo (char *filename, char *fileid, int delflag, int partno, int *partcount)
{
  int res, sr;
  struct stat finfo;
  fileread *loaded;
  uufile *fload;
  itbd *killem;
  FILE *datei;
  void *datei_buf;

  int _count;
  if (!partcount)
    partcount = &_count;
  
  *partcount = 0;

  if ((datei = fopen (filename, "rb")) == NULL) {
    UUMessage (uulib_id, __LINE__, UUMSG_ERROR,
	       uustring (S_NOT_OPEN_SOURCE),
	       filename, strerror (uu_errno = errno));
    return UURET_IOERR;
  }
  UUSETBUF (datei, datei_buf, uu_rbuf);

  if (fstat (fileno(datei), &finfo) == -1) {
    UUMessage (uulib_id, __LINE__, UUMSG_ERROR,
	       uustring (S_NOT_STAT_FILE),
	       filename, strerror (uu_errno = errno));
    fclose (datei);
    UUCLRBUF (uu_rbuf, datei_buf);
    return UURET_IOERR;
  }

  /*
   * schedule for destruction
   */

  if (delflag && fileid==NULL) {
    if ((killem = (itbd *) malloc (sizeof (itbd))) == NULL) {
      UUMessage (uulib_id, __LINE__, UUMSG_WARNING,
		 uustring (S_OUT_OF_MEMORY), sizeof (itbd));
    }
    else if ((killem->fname = _FP_strdup (filename)) == NULL) {
      UUMessage (uulib_id, __LINE__, UUMSG_WARNING,
		 uustring (S_OUT_OF_MEMORY), strlen(filename)+1);
      _FP_free (killem);
    }
    else {
      killem->NEXT = ftodel;
      ftodel = killem;
    }
  }

  progress.action   = 0;
  progress.partno   = 0;
  progress.numparts = 1;
  progress.fsize    = (long) ((finfo.st_size>0)?finfo.st_size:-1);
  progress.percent  = 0;
  progress.foffset  = 0;
  _FP_strncpy (progress.curfile,
	       (strlen(filename)>255)?
	       (filename+strlen(filename)-255):filename,
	       256);
  progress.action   = UUACT_SCANNING;

  if (fileid == NULL)
    fileid = filename;

  while (!feof (datei) && !ferror (datei)) {
    /* 
     * Peek file, or some systems won't detect EOF
     */
    res = _FP_fgetc (datei);
    if (feof (datei) || ferror (datei))
      break;
    else
      ungetc (res, datei);
    
    if ((loaded = ScanPart (datei, fileid, &sr)) == NULL) {
      if (sr != UURET_NODATA && sr != UURET_OK && sr != UURET_CONT) {
	UUkillfread (loaded);
	if (sr != UURET_CANCEL)
	  UUMessage (uulib_id, __LINE__, UUMSG_ERROR,
		     uustring (S_READ_ERROR), filename,
		     strerror (uu_errno));

	if (uu_autocheck) UUCheckGlobalList ();
	progress.action = 0;
	fclose (datei);
        UUCLRBUF (uu_rbuf, datei_buf);
	return sr;
      }
      continue;
    }

    if (ferror (datei)) {
      UUMessage (uulib_id, __LINE__, UUMSG_ERROR,
		 uustring (S_READ_ERROR), filename,
		 strerror (uu_errno = errno));
      if (uu_autocheck) UUCheckGlobalList ();
      progress.action = 0;
      fclose (datei);
      UUCLRBUF (uu_rbuf, datei_buf);
      return UURET_IOERR;
    }

    if (partno != -1)
      loaded->partno = partno;

    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
       */
      UUkillfread (loaded);
      continue;
    }

    if ((loaded->subject == NULL || *(loaded->subject) == '\0') &&
	(loaded->mimeid  == NULL || *(loaded->mimeid)  == '\0') &&
	(loaded->filename== NULL || *(loaded->filename)== '\0') &&
	(loaded->uudet   == 0)) {
      /*
       * no useful data here
       */
      UUkillfread (loaded);
      if (uu_fast_scanning && sr != UURET_CONT) break;
      continue;
    }
    
    if ((fload = UUPreProcessPart (loaded, &res)) == NULL) {
      /*
       * no useful data found
       */
      if (res != UURET_NODATA) {
	UUMessage (uulib_id, __LINE__, UUMSG_ERROR,
		   uustring (S_READ_ERROR), filename,
		   (res==UURET_IOERR)?strerror(uu_errno):UUstrerror(res));
      }
      UUkillfread (loaded);
      if (uu_fast_scanning && sr != UURET_CONT) break;
      continue;
    }

    if ((loaded->subject && *(loaded->subject)) ||
	(loaded->mimeid  && *(loaded->mimeid))  ||
	(loaded->filename&& *(loaded->filename))||
	(loaded->uudet)) {
      UUMessage (uulib_id, __LINE__, UUMSG_MESSAGE,
		 uustring (S_LOADED_PART),
		 filename,
		 (loaded->subject)  ? loaded->subject  : "",
		 (fload->subfname)  ? fload->subfname  : "",
		 (loaded->filename) ? loaded->filename : "",
		 fload->partno,
		 (loaded->begin)    ? "begin" : "",
		 (loaded->end)      ? "end"   : "",
		 codenames[loaded->uudet]);
    }
    
    if ((res = UUInsertPartToList (fload))) {
      /*
       * couldn't use the data
       */
      UUkillfile (fload);

      if (res != UURET_NODATA) {
	if (uu_autocheck) UUCheckGlobalList ();
	progress.action = 0;
	fclose (datei);
        UUCLRBUF (uu_rbuf, datei_buf);
	return res;
      }
      if (uu_fast_scanning && sr != UURET_CONT)
	break;

      continue;
    }

    /*
     * if in fast mode, we don't look any further, because we're told
     * that each source file holds at most one encoded part
     */

    if (loaded->uudet)
      (*partcount)++;

    if (uu_fast_scanning && sr != UURET_CONT)
      break;
  }

  if (ferror (datei)) {
    UUMessage (uulib_id, __LINE__, UUMSG_ERROR,
	       uustring (S_READ_ERROR), filename,
	       strerror (uu_errno = errno));
    if (uu_autocheck) UUCheckGlobalList ();
    progress.action = 0;
    fclose (datei);
    UUCLRBUF (uu_rbuf, datei_buf);
    return UURET_IOERR;
  }

  fclose (datei);
  UUCLRBUF (uu_rbuf, datei_buf);

  if (!uu_fast_scanning && *partcount == 0)
    UUMessage (uulib_id, __LINE__, UUMSG_NOTE,
	       uustring (S_NO_DATA_FOUND), filename);

  progress.action = 0;
  if (uu_autocheck) UUCheckGlobalList ();

  return UURET_OK;
}

/*
 * decode to a temporary file. this is well handled by uudecode()
 */

int UUEXPORT
UUDecodeToTemp (uulist *thefile)
{
  return UUDecode (thefile);
}

/*
 * decode file first to temp file, then copy it to a final location
 */

int UUEXPORT
UUDecodeFile (uulist *thefile, char *destname)
{
  FILE *target, *source;
  void *target_buf, *source_buf;
  struct stat finfo;
  int fildes, res;
  size_t bytes;

  if (thefile == NULL)
    return UURET_ILLVAL;

  if ((res = UUDecode (thefile)) != UURET_OK)
    if (res != UURET_NOEND || !uu_desperate)
      return res;

  if (thefile->binfile == NULL) {
    UUMessage (uulib_id, __LINE__, UUMSG_ERROR,
	       uustring (S_NO_BIN_FILE));
    return UURET_IOERR;
  }

  if ((source = fopen (thefile->binfile, "rb")) == NULL) {
    UUMessage (uulib_id, __LINE__, UUMSG_ERROR,
	       uustring (S_NOT_OPEN_FILE),
	       thefile->binfile, strerror (uu_errno = errno));
    return UURET_IOERR;
  }
  UUSETBUF (source, source_buf, uu_rbuf);

  /*
   * for system security, strip setuid/setgid bits from mode
   */

  if ((thefile->mode & 0777) != thefile->mode) {
    UUMessage (uulib_id, __LINE__, UUMSG_NOTE,
	       uustring (S_STRIPPED_SETUID),
	       destname, (int)thefile->mode);
    thefile->mode &= 0777;
  }

  /*
   * Determine the name of the target file according to the rules:
   * 
   * IF (destname!=NULL) THEN filename=destname;
   * ELSE
   *   filename = thefile->filename
   *   IF (FilenameFilter!=NULL) THEN filename=FilenameFilter(filename);
   *   filename = SaveFilePath + filename
   * END
   */

  if (destname)
    strcpy (uugen_fnbuffer, destname);
  else {
    char *fname = UUFNameFilter (thefile->filename ? thefile->filename : "unknown.xxx");
    sprintf (uugen_fnbuffer, "%.1024s%.3071s",
	     uusavepath ? uusavepath : "",
             fname ? fname : "unknown.xxx");
  }

  /*
   * if we don't want to overwrite existing files, check if it's there
   */

  if (!uu_overwrite) {
    if (stat (uugen_fnbuffer, &finfo) == 0) {
      UUMessage (uulib_id, __LINE__, UUMSG_ERROR,
		 uustring (S_TARGET_EXISTS), uugen_fnbuffer);
      fclose (source);
      UUCLRBUF (uu_rbuf, source_buf);
      return UURET_EXISTS;
    }
  }

  if (fstat (fileno(source), &finfo) == -1) {
    UUMessage (uulib_id, __LINE__, UUMSG_ERROR,
	       uustring (S_NOT_STAT_FILE),
	       thefile->binfile, strerror (uu_errno = errno));
    fclose (source);
    UUCLRBUF (uu_rbuf, source_buf);
    return UURET_IOERR;
  }

  /* try rename() shortcut first */
  if (!rename (thefile->binfile, uugen_fnbuffer))
    {
      mode_t mask = 0000; /* there is a slight window here anyway */
#if HAVE_UMASK
      mask = umask (0022); umask (mask);
#endif
      fclose (source);
      UUCLRBUF (uu_rbuf, source_buf);
#if HAVE_CHMOD
      chmod (uugen_fnbuffer, thefile->mode & ~mask);
#endif
      goto skip_copy;
    }

  progress.action   = 0;
  _FP_strncpy (progress.curfile,
	       (strlen(uugen_fnbuffer)>255)?
	       (uugen_fnbuffer+strlen(uugen_fnbuffer)-255):uugen_fnbuffer,
	       256);
  progress.partno   = 0;
  progress.numparts = 1;
  progress.fsize    = (long) ((finfo.st_size)?finfo.st_size:-1);
  progress.foffset  = 0;
  progress.percent  = 0;
  progress.action   = UUACT_COPYING;

  if ((fildes = open (uugen_fnbuffer,
                      O_WRONLY | O_CREAT | O_BINARY | O_TRUNC,
                      (uu_ignmode)?0666:thefile->mode)) == -1) {
    progress.action = 0;
    UUMessage (uulib_id, __LINE__, UUMSG_ERROR,
	       uustring (S_NOT_OPEN_TARGET),
	       uugen_fnbuffer, strerror (uu_errno = errno));
    fclose (source);
    UUCLRBUF (uu_rbuf, source_buf);
    return UURET_IOERR;
  }

  if ((target = fdopen (fildes, "wb")) == NULL) {
    progress.action = 0;
    UUMessage (uulib_id, __LINE__, UUMSG_ERROR,
	       uustring (S_IO_ERR_TARGET),
	       uugen_fnbuffer, strerror (uu_errno = errno));
    fclose (source);
    UUCLRBUF (uu_rbuf, source_buf);
    close  (fildes);
    return UURET_IOERR;
  }
  UUSETBUF (target, target_buf, uu_wbuf);

  while (!feof (source)) {

    if (UUBUSYPOLL(ftell(source),progress.fsize)) {
      UUMessage (uulib_id, __LINE__, UUMSG_NOTE,
		 uustring (S_DECODE_CANCEL));
      fclose (source);
      UUCLRBUF (uu_rbuf, source_buf);
      fclose (target);
      UUCLRBUF (uu_wbuf, target_buf);
      unlink (uugen_fnbuffer);
      return UURET_CANCEL;
    }

    bytes = fread (uugen_inbuffer, 1, 1024, source);

    if (ferror (source) || (bytes == 0 && !feof (source))) {
      progress.action = 0;
      UUMessage (uulib_id, __LINE__, UUMSG_ERROR,
		 uustring (S_READ_ERROR),
		 thefile->binfile, strerror (uu_errno = errno));
      fclose (source);
      UUCLRBUF (uu_rbuf, source_buf);
      fclose (target);
      UUCLRBUF (uu_wbuf, target_buf);
      unlink (uugen_fnbuffer);
      return UURET_IOERR;
    }
    if (fwrite (uugen_inbuffer, 1, bytes, target) != bytes) {
      progress.action = 0;
      UUMessage (uulib_id, __LINE__, UUMSG_ERROR,
		 uustring (S_WR_ERR_TARGET),
		 uugen_fnbuffer, strerror (uu_errno = errno));
      fclose (source);
      UUCLRBUF (uu_rbuf, source_buf);
      fclose (target);
      UUCLRBUF (uu_wbuf, target_buf);
      unlink (uugen_fnbuffer);
      return UURET_IOERR;
    }
  }

  fclose (source);
  UUCLRBUF (uu_rbuf, source_buf);
  if (fclose (target)) {
    UUCLRBUF (uu_wbuf, target_buf);
    UUMessage (uulib_id, __LINE__, UUMSG_ERROR,
	       uustring (S_WR_ERR_TARGET),
	       uugen_fnbuffer, strerror (uu_errno = errno));
    unlink (uugen_fnbuffer);
    return UURET_IOERR;
  }
  UUCLRBUF (uu_wbuf, target_buf);

  /*
   * after a successful decoding run, we delete the temporary file
   */

  if (unlink (thefile->binfile)) {
    UUMessage (uulib_id, __LINE__, UUMSG_WARNING,
	       uustring (S_TMP_NOT_REMOVED),
	       thefile->binfile,
	       strerror (uu_errno = errno));
  }

skip_copy:
  _FP_free (thefile->binfile);
  thefile->binfile = NULL;
  thefile->state  &= ~UUFILE_TMPFILE;
  thefile->state  |=  UUFILE_DECODED;
  progress.action  = 0;

  return UURET_OK;
}

/*
 * Calls a function repeatedly with all the info we have for a file
 * If the function returns non-zero, we break and don't send any more
 */

int UUEXPORT
UUInfoFile (uulist *thefile, void *opaque,
	    int (*func) (void *, char *))
{
  int errflag=0, res, bhflag=0, dd;
  long maxpos;
  FILE *inpfile;

  /*
   * We might need to ask our callback function to download the file
   */

  if (uu_FileCallback) {
    if ((res = (*uu_FileCallback) (uu_FileCBArg, 
				   thefile->thisfile->data->sfname,
				   uugen_fnbuffer,
				   1)) != UURET_OK)
      return res;
    if ((inpfile = fopen (uugen_fnbuffer, "rb")) == NULL) {
      (*uu_FileCallback) (uu_FileCBArg, thefile->thisfile->data->sfname,
			  uugen_fnbuffer, 0);
      UUMessage (uulib_id, __LINE__, UUMSG_ERROR,
		 uustring (S_NOT_OPEN_FILE), uugen_fnbuffer,
		 strerror (uu_errno = errno));
      return UURET_IOERR;
    }
  }
  else {
    if ((inpfile = fopen (thefile->thisfile->data->sfname, "rb")) == NULL) {
      UUMessage (uulib_id, __LINE__, UUMSG_ERROR,
		 uustring (S_NOT_OPEN_FILE), 
		 thefile->thisfile->data->sfname,
		 strerror (uu_errno=errno));
      return UURET_IOERR;
    }
    _FP_strncpy (uugen_fnbuffer, thefile->thisfile->data->sfname, 1024);
  }

  /*
   * seek to beginning of info
   */

  fseek (inpfile, thefile->thisfile->data->startpos, SEEK_SET);
  maxpos = thefile->thisfile->data->startpos + thefile->thisfile->data->length;

  while (!feof (inpfile) && 
	 (uu_fast_scanning || ftell(inpfile) < maxpos)) {
    if (_FP_fgets (uugen_inbuffer, 511, inpfile) == NULL)
      break;
    uugen_inbuffer[511] = '\0';

    if (ferror (inpfile))
      break;

    dd = UUValidData (uugen_inbuffer, 0, &bhflag);

    if (thefile->uudet == B64ENCODED && dd == B64ENCODED)
      break;
    else if (thefile->uudet == BH_ENCODED && bhflag)
      break;
    else if ((thefile->uudet == UU_ENCODED || thefile->uudet == XX_ENCODED) &&
	     strncmp (uugen_inbuffer, "begin ", 6) == 0)
      break;
    else if (thefile->uudet == YENC_ENCODED &&
	     strncmp (uugen_inbuffer, "=ybegin ", 8) == 0)
      break;

    if ((*func) (opaque, uugen_inbuffer))
      break;
  }

  if (ferror (inpfile)) {
    UUMessage (uulib_id, __LINE__, UUMSG_ERROR,
	       uustring (S_READ_ERROR),
	       uugen_fnbuffer, strerror (uu_errno = errno));
    errflag = 1;
  }

  fclose (inpfile);

  if (uu_FileCallback)
    (*uu_FileCallback) (uu_FileCBArg, 
			thefile->thisfile->data->sfname,
			uugen_fnbuffer, 0);

  if (errflag)
    return UURET_IOERR;

  return UURET_OK;
}
	    
int UUEXPORT
UURenameFile (uulist *thefile, char *newname)
{
  char *oldname;

  if (thefile == NULL)
    return UURET_ILLVAL;

  oldname = thefile->filename;

  if ((thefile->filename = _FP_strdup (newname)) == NULL) {
    UUMessage (uulib_id, __LINE__, UUMSG_ERROR,
	       uustring (S_NOT_RENAME),
	       oldname, newname);
    thefile->filename = oldname;
    return UURET_NOMEM;
  }
  _FP_free (oldname);
  return UURET_OK;
}

int UUEXPORT
UURemoveTemp (uulist *thefile)
{
  if (thefile == NULL)
    return UURET_ILLVAL;

  if (thefile->binfile) {
    if (unlink (thefile->binfile)) {
      UUMessage (uulib_id, __LINE__, UUMSG_WARNING,
		 uustring (S_TMP_NOT_REMOVED),
		 thefile->binfile,
		 strerror (uu_errno = errno));
    }
    _FP_free (thefile->binfile);
    thefile->binfile = NULL;
    thefile->state  &= ~UUFILE_TMPFILE;
  }
  return UURET_OK;
}

int UUEXPORT
UUCleanUp (void)
{
  itbd *iter=ftodel, *ptr;
  uulist *liter;
  uufile *fiter;
  allomap *aiter;

  /*
   * delete temporary input files (such as the copy of stdin)
   */

  while (iter) {
    if (unlink (iter->fname)) {
      UUMessage (uulib_id, __LINE__, UUMSG_WARNING,
		 uustring (S_TMP_NOT_REMOVED),
		 iter->fname, strerror (uu_errno = errno));
    }
    _FP_free (iter->fname);
    ptr  = iter;
    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);

  uusavepath  = NULL;
  uuencodeext = NULL;

  UUkillheaders (&localenv);
  UUkillheaders (&sstate.envelope);
  memset (&localenv, 0, sizeof (headers));
  memset (&sstate,   0, sizeof (scanstate));

  while (mssdepth) {
    mssdepth--;
    UUkillheaders (&(multistack[mssdepth].envelope));
    _FP_free (multistack[mssdepth].source);
  }

  /*
   * clean up the malloc'ed stuff
   */

  for (aiter=toallocate; aiter->ptr; aiter++) {
    safe_free (*(aiter->ptr), aiter->size);
    *(aiter->ptr) = NULL;
  }

  return UURET_OK;
}

Convert-UUlib-1.5/uulib/uustring.h0000644000000000000000000000233510626047510015670 0ustar  rootroot/* extracted from Id */
#define S_NOT_OPEN_SOURCE      1
#define S_NOT_OPEN_TARGET      2
#define S_NOT_OPEN_FILE        3
#define S_NOT_STAT_FILE        4
#define S_SOURCE_READ_ERR      5
#define S_READ_ERROR           6
#define S_IO_ERR_TARGET        7
#define S_WR_ERR_TARGET        8
#define S_WR_ERR_TEMP          9
#define S_TMP_NOT_REMOVED     10
#define S_OUT_OF_MEMORY       11
#define S_TARGET_EXISTS       12
#define S_NOT_RENAME          13
#define S_ERR_ENCODING        14
#define S_STAT_ONE_PART       15
#define S_PARM_CHECK          16
#define S_SHORT_BINHEX        17
#define S_DECODE_CANCEL       18
#define S_ENCODE_CANCEL       19
#define S_SCAN_CANCEL         20
#define S_SIZE_MISMATCH       21
#define S_PSIZE_MISMATCH      22
#define S_CRC_MISMATCH        23
#define S_PCRC_MISMATCH       24
#define S_LOADED_PART         25
#define S_NO_DATA_FOUND       26
#define S_NO_BIN_FILE         27
#define S_STRIPPED_SETUID     28
#define S_DATA_SUSPICIOUS     29
#define S_NO_TEMP_NAME        30
#define S_BINHEX_SIZES        31
#define S_BINHEX_BOTH         32
#define S_SMERGE_MERGED       33
#define S_MIME_NO_BOUNDARY    34
#define S_MIME_B_NOT_FOUND    35
#define S_MIME_MULTI_DEPTH    36
#define S_MIME_PART_MULTI     37
Convert-UUlib-1.5/COPYING.Artistic0000644000000000000000000001373710211640716015340 0ustar  rootroot



			 The "Artistic License"

				Preamble

The intent of this document is to state the conditions under which a
Package may be copied, such that the Copyright Holder maintains some
semblance of artistic control over the development of the package,
while giving the users of the package the right to use and distribute
the Package in a more-or-less customary fashion, plus the right to make
reasonable modifications.

Definitions:

	"Package" refers to the collection of files distributed by the
	Copyright Holder, and derivatives of that collection of files
	created through textual modification.

	"Standard Version" refers to such a Package if it has not been
	modified, or has been modified in accordance with the wishes
	of the Copyright Holder as specified below.

	"Copyright Holder" is whoever is named in the copyright or
	copyrights for the package.

	"You" is you, if you're thinking about copying or distributing
	this Package.

	"Reasonable copying fee" is whatever you can justify on the
	basis of media cost, duplication charges, time of people involved,
	and so on.  (You will not be required to justify it to the
	Copyright Holder, but only to the computing community at large
	as a market that must bear the fee.)

	"Freely Available" means that no fee is charged for the item
	itself, though there may be fees involved in handling the item.
	It also means that recipients of the item may redistribute it
	under the same conditions they received it.

1. You may make and give away verbatim copies of the source form of the
Standard Version of this Package without restriction, provided that you
duplicate all of the original copyright notices and associated disclaimers.

2. You may apply bug fixes, portability fixes and other modifications
derived from the Public Domain or from the Copyright Holder.  A Package
modified in such a way shall still be considered the Standard Version.

3. You may otherwise modify your copy of this Package in any way, provided
that you insert a prominent notice in each changed file stating how and
when you changed that file, and provided that you do at least ONE of the
following:

    a) place your modifications in the Public Domain or otherwise make them
    Freely Available, such as by posting said modifications to Usenet or
    an equivalent medium, or placing the modifications on a major archive
    site such as uunet.uu.net, or by allowing the Copyright Holder to include
    your modifications in the Standard Version of the Package.

    b) use the modified Package only within your corporation or organization.

    c) rename any non-standard executables so the names do not conflict
    with standard executables, which must also be provided, and provide
    a separate manual page for each non-standard executable that clearly
    documents how it differs from the Standard Version.

    d) make other distribution arrangements with the Copyright Holder.

4. You may distribute the programs of this Package in object code or
executable form, provided that you do at least ONE of the following:

    a) distribute a Standard Version of the executables and library files,
    together with instructions (in the manual page or equivalent) on where
    to get the Standard Version.

    b) accompany the distribution with the machine-readable source of
    the Package with your modifications.

    c) give non-standard executables non-standard names, and clearly
    document the differences in manual pages (or equivalent), together
    with instructions on where to get the Standard Version.

    d) make other distribution arrangements with the Copyright Holder.

5. You may charge a reasonable copying fee for any distribution of this
Package.  You may charge any fee you choose for support of this
Package.  You may not charge a fee for this Package itself.  However,
you may distribute this Package in aggregate with other (possibly
commercial) programs as part of a larger (possibly commercial) software
distribution provided that you do not advertise this Package as a
product of your own.  You may embed this Package's interpreter within
an executable of yours (by linking); this shall be construed as a mere
form of aggregation, provided that the complete Standard Version of the
interpreter is so embedded.

6. The scripts and library files supplied as input to or produced as
output from the programs of this Package do not automatically fall
under the copyright of this Package, but belong to whoever generated
them, and may be sold commercially, and may be aggregated with this
Package.  If such scripts or library files are aggregated with this
Package via the so-called "undump" or "unexec" methods of producing a
binary executable image, then distribution of such an image shall
neither be construed as a distribution of this Package nor shall it
fall under the restrictions of Paragraphs 3 and 4, provided that you do
not represent such an executable image as a Standard Version of this
Package.

7. C subroutines (or comparably compiled subroutines in other
languages) supplied by you and linked into this Package in order to
emulate subroutines and variables of the language defined by this
Package shall not be considered part of this Package, but are the
equivalent of input as in Paragraph 6, provided these subroutines do
not change the language in any way that would cause it to fail the
regression tests for the language.

8. Aggregation of this Package with a commercial distribution is always
permitted provided that the use of this Package is embedded; that is,
when no overt attempt is made to make this Package's interfaces visible
to the end user of the commercial distribution.  Such use shall not be
construed as a distribution of this Package.

9. The name of the Copyright Holder may not be used to endorse or promote
products derived from this software without specific prior written permission.

10. THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.

				The End
Convert-UUlib-1.5/META.json0000644000000000000000000000150012550073763014140 0ustar  rootroot{
   "abstract" : "unknown",
   "author" : [
      "unknown"
   ],
   "dynamic_config" : 1,
   "generated_by" : "ExtUtils::MakeMaker version 7.0401, CPAN::Meta::Converter version 2.150001",
   "license" : [
      "unknown"
   ],
   "meta-spec" : {
      "url" : "http://search.cpan.org/perldoc?CPAN::Meta::Spec",
      "version" : "2"
   },
   "name" : "Convert-UUlib",
   "no_index" : {
      "directory" : [
         "t",
         "inc"
      ]
   },
   "prereqs" : {
      "build" : {
         "requires" : {
            "ExtUtils::MakeMaker" : "0"
         }
      },
      "configure" : {
         "requires" : {
            "Canary::Stability" : "0",
            "ExtUtils::MakeMaker" : "6.52"
         }
      },
      "runtime" : {
         "requires" : {}
      }
   },
   "release_status" : "stable",
   "version" : 1.5
}
Convert-UUlib-1.5/doc/0000755000000000000000000000000012550073763013270 5ustar  rootrootConvert-UUlib-1.5/doc/HISTORY0000644000000000000000000005221210211640772014346 0ustar  rootroot#
# $Id: HISTORY,v 1.2 2002/10/13 13:51:00 root Exp $
#

PROGRAM HISTORY
---------------

(remember that all _dates_ are dd.mm.yyyy)

 0.1  (15.06.1994)
-----
First release. Took less than a week of coding. Most features should work now.
All files I encountered can be decoded properly. Some special cases, however,
are still untested. This version was updated two or three times without
upgrading the version number because that were just minor changes.

 0.2  (23.06.1994)
-----
DOS support! After getting some requests for a DOS version, many portions of 
the code have been completely rewritten so that the file data is not loaded 
into memory. Instead, just an index is saved. Added +e option to select file
extensions. Added +i option to disable user questioning.
Some special cases to evaluate the part no. of the subject line added
Automatic uncompress / gunzip (need to have them installed)
Tar file handling - extract files right out of a tar archive. This is done
from uudeview itself, so you won't need an external tar.

 0.3  (30.06.1994)
-----
Getting smarter every day. After I found some postings with spelling mistakes
in the subject line (namely "something.zip" instead of "something.arj"), I
began to program "Smart Part Merging System" (SPMS (R)). It detects that the
parts of "something.zip" are just the missing parts of "something.arj" and
merges both files. This feature will still need a lot of maintenance, since
there are a lot of special cases.
Added a ton of features. Now you can list the files or enter commands to do
anything with them (you can enter "xv $") to watch the file.
Installed a signal handler for SIGINT (Ctrl-C). If the program was interrupted
by the user, it left LOTS of temporary files in /usr/tmp. They will now be
cleaned.
Again, the user interface was changed. I did that in 0.2, so why not again
in 0.3. I hope you'll agree it's a bit better now.
The program now checks if gunzip has failed (it tests if the resulting file
has less than 2 bytes).
Fixed a bug with filenames that contained spaces at the end.
Linked files in tar archives are now ignored.
In 0.2 each file was decoded before the user was prompted what to do. This
was quite slow on some machines. Now the files are only decoded on request.

 0.3.42
--------
 I'm quite lazy with documenting all the changes I made to the source code.
I hope I will keep online this time. To do this, I have invented the patch-
level number. Since I have made a lot of changes to the original 0.3 release,
I start with patchlevel 42.

 0.3.43
--------
- gets suspicious if it finds multiple begins/ends within the same post
  and opens up a new file record
- Treats "BEGIN -- CUT HERE" line exceptionally, because it frequently looks
  like valid uuencoded data and fooled the program. The 4-line-safety barrier
  didn't catch because the real data followed immediately.

 0.3.44  (25.01.1995)
--------
- added lots of patches to allow for Mime Base64 decoding ... mostly because
  I want to decode this Lion King MPEG from alt.binaries.multimedia

 0.3.45  (29.01.1995)
--------
- added XX decoding scheme. Was really simple after having to change every-
  thing for the above MIME stuff anyway. Just another decoding table. Hope
  it works.

 0.3.46  (01.02.1995)
--------
- included groundworks for desperate mode. I don't know -- should I leave
  the '-d' command line option out?

 0.3.47  (03.02.1995)
--------
- written my own more function. previously, I just called system(), but this
  was (a) unstable and (b) didn't work in QuickWin
- included '(i)' action to show file info; either part 0, or part 1 up to the
  begin line
- desperate mode finished. Moved the original '-d' (decompress) option to
  '-x' (didn't use it anyway, and needs major rewriting) and replaced it
  with new desperate option

 0.3.48  (04.02.1995)
--------
- wrote an case-insensitive string compare function. Have migrated the
  extension detection to case-insensitivity
- added some code to detect some common file suffixes (jpg, gif etc.)
  added SPMS check: parts of files will not be merged if they have different
  but correct suffixes (if one of the files' suffix is not recognized, it
  might just be spelled wrong, so this doesn't prevent merging). This should
  stop SMPS from merging together complete junk.
- generalized Unix Makefile. Now I only have to change a version number in
  one place (well in three places if I consider DOS&Windows with other make
  files).
- added multiple passes to SMPS. In first pass, only "exact fits" are merged,
  in second pass only files with minimal differences, in third pass, everything
- stripping some boring headers in file (i)nfo
- now it should also accept files with less than 4 lines of data
- finally found the 'bug' that declared some final lines as invalid -- the
  encoder has stripped unnecessary chars. Added more checks ...

 0.4    (06.02.1995)
-----
- After getting no bugreports for a few weeks (either nobody uses the program
  or it does work after all), I renamed 0.3.48 to 0.4. There is so much dif-
  ferent from the original 0.3 that I simply need to indicate these changes
  to users. And besides, it's my birthday :-)
- Deleted "ALPHA" indication from the windows version. Now fully integrated.
- moved MIME check in front of UUdata check. Strongest semantics first.

 0.4.1  (08.02.1995)
-------
- Added additional check for a part number on the subject line:
  "test.gif 3 of 4" was detected to be 4, now done correctly.

 0.4.2  (10.02.1995)
-------
- bugfixed uudeview.c:IsKnownExtension() which would core dump on some
  systems due to NULL read access. Thanks to J. Wilkinson,
   for pointing out the problem.
  This isn't fatal for DOS, and also shouldn't be fatal in Windows.

 0.4.3  (14.02.1995)
-------
- some people couldn't compile the Unix version because I used two
  non-standard string functions, strrstr() and strdup(). Thought they
  were defined everywhere. Now I've written them on my own.
- moved _FP_strnicmp() to uuutil.c

 0.4.4  (24.02.1995)
-------
- trimmed comments in header files because some compilers warned about
  "nested comments"
- fixed annoying bug in CheckGlobalList() that caused infinite loops
  and may also have caused core dumps if more than 98 parts were missing
  from a posting
- added another clause to the detection of a part number on the subject
  line after getting a file by the name of abc-1019.gif, where a part num-
  ber of 1019 was detected

 0.4.5  (02.03.1995)
-------
- Added workaround for Netscape, which completely messes up encoded data
  on some setups. It replaces &,<,> by their html equivalents and occasio-
  nally inserts some junk HREF links. Now whenever an invalid line is found,
  it is NetscapeCollapse()d, in the hope it's decodeable afterwards.

 0.4.6  (11.04.1995)
-------
- wow, I just see that it's been a long time since the last bugfix. I guess
  it is indeed getting better :-)
- UUdeview would ignore files with double-spacing (one line of data followed
  by an empty line). Now, all empty lines are ignored. I just hope this
  doesn't add problems elsewhere. Thanks to Gary for this one.
- a slight bug in the Base64 detection made the program fail to pick up the
  destination filename when quoted

 0.4.7  (07.05.1995)
-------
- the mime detection was looking for the "Content-Type" message. Now, this
  tag is accepted case-insensitive.
- if no trailing lines were at the end of a Base64-encoded file, some data
  was written twice, resulting in trailing garbage data.

 0.4.8  (22.05.1995)
-------
- all string compares are now case insensitive, especially because I
  found mime headers in all kinds of variations
- small bug fixed that caused uudeview to ignore some files where the
  first part didn't have encoded data
- included checking if files exist, prompting the user whether it shall
  be overwritten. suggested and coded by Kevin B. York
- new: the encoding engine! incorprorated into the launcher in Windows,
  for Dos/Unix, it's in the external 'uuenview' program.

 0.4.9  (07.06.1995)
-------
- allows an 'end' after the encoded data with only an _empty_ line
  inbetween. Previously, I expected a valid encoded line with zero
  data, meaning that the single character on that line is '`' (UUE)
  or '+' (XXE)

 0.4.10 (14.06.1995)
--------
- funny bug fixed: if the decoder found a valid UUencoded line in a
  supposed MIME-data file, it decoded the single line and exited. In
  my case, a MIME header triggered this.
- fixed bug with more than one MIME-encoded file in a single message.
- serious bug fixed when overwriting an existing file: I had forgot-
  ten O_TRUNC when opening the file, causing some undefined behavior.

 0.4.11 (16.06.1995)
--------
- renamed all variables 'this' and 'new', as some C++ compilers don't
  like using these keywords as names
- renamed the variable 'inpfile' in uudeview.c:more(); I had a type
  of the same name (ec@matufia.sp.TRW.COM)

 0.4.12 ()
--------
- more smartness (although I now can't remember where, probably everywhere)
- fixed problem with multiple MIME attachments in a single mail
- can now decode news articles from lynx, which were messed up similar
  to Netscape news files, only worse.
- one appearance of strdup() in uuio.c slipped through. Now replaced
  by _FP_strdup()
- Instead of having to choose to rename or overwrite existing files each
  time, you can now enter 'a' once to overwrite them all.
- The Ultrix C compiler ignored hex escape sequences, which were used in
  uuenview.c for CRLF. Now they're in octal.
- not so picky if the last line is longer than expected. some encoders
  (more than one!) failed to let the last line end where it was supposed
  to end.
- complete rewrite of uuenview. It can now email and post files direcly.
  For the purpose of posting, a mini inews program, written by Steven Grady, 
  , is included in the distribution
- finally: manual pages! And make install works as well as make install.man!
  Thanks to all the people who have been bothering me for months :)
- uudeview and uuenview can now behave similar to uudecode and uuencode
  if called like that (ln -s uudeview uudecode). Of course, you don't
  loose any smartness. My ultimate goal is to replace these outdated tools.
- attempt to enforce stronger subject-line semantics. uuenview prints the
  part numbers in brackets (partno/numparts) and the file name in hard
  brackets [ filename.tar.gz ], and this is what the decoder looks for first.

 0.4.13 (20.10.1995)
--------
- after sending out so many 'beta' versions of 0.4.12 and being asked
  whether there's a new one available, I've decided to skip an official
  0.4.12.
- Scan speed greatly improved. And if you're sure you only have one article
  per file, you can use the undocumented "-f" option for even more speed.
  But then everything becomes quite unsafe, as incomplete files are only
  detected when decoding.
- don't ignore RETries
- reworked most documentation, and rearranged the rest. All packages now
  only include the documentation the reader really needs
- Win version includes a new version of the Launcher, compiled with the
  new encoding routines, and also remembering its screen position and size
- Oops, the Netscape repair code was partially broken and needed some repair
  itself.
- xxdecoding was broken because of over-tolerant uudecoding
- uudecoding was broken because of over-tolerant uudecoding :(

 0.4.15 (20.01.1996)
--------
- Implemented my own version of fgets() that allows to transparently read
  lines terminated either with LF (Unix), CRLF (DOS) or CR (Mac). Sadly,
  it's slower than the original.
- in previous versions, I have very much relaxed the checking for uudecoded
  lines (valid_data()). Now I only allow the less strong code (meaning,
  allow the data look more weird, more off the specs) if I'm sure it actually
  _is_ uuencoded data. This should work in all cases because it was usually
  only the last line with was "erroneous"
- included option '-b' to let part numbers in [] take precedence over ()
  this only affects the kind of brackets uudeview looks to find a part
  number _first_
- fixed problems with multiple MIME attachments
- got rid of the 'Ignore Replies' switch. It caused lots of confusion and
  didn't really help anything.
- included option '-f' for fast scanning. Only works if each input file
  contains at most one article. Many sanity checks cannot be performed
  because much less data is gathered, thus many invalid files may get
  processed.
- added e(x)tract command; but (d)ecode stays default.

 0.4.16 (21.01.1996)
--------
- a tiny typo, which was introduced for debugging purposes but not removed,
  broke 0.4.15. This was especially problematic for the Windows version.

 0.4.17 (09.02.1996)
--------
- once again a stupid 16 bit problem introduced in 0.4.15. In uunconc.c:
  uunconc(), the variable pppos, used to remember the file position, was
  declared as int. Because of this, on 16 bit systems, it looped over and
  over, but the file pointer never reached maxpos :-(
  This patchlevel was only released as uudv[dw]04h but not as Unix version
  because 32 or 64 bit systems weren't affected.

 0.4.18 (not publicly released)
--------
- this is an intermediate beta test version. With all the changes going
  on, I expect everything to settle into a 0.5 release sooner or later.
- got rid of some bugs
- Base64-encoded lines can now have arbitrary length (not limited to
  multiples of four)
- support for BinHex decoding added. No encoder yet.
- complete re-layout of the code. All the encoding/decoding stuff has
  been moved into a seperate, system-independent library, while the
  enveloping standalone programs uuencode and uudecode are just front-
  ends to this library.
- another front-end has been added, uutcl, which makes the library
  functions available to Tcl/Tk programs
- A Tcl/Tk script, xdeview, uses these functions and provides a graphical
  frontend
- support for decompressing and tar files has been removed. They didn't
  work reliably, and aren't the job of a decoder anyway.
- BinHex and Base64 lines may have space characters at the end of the
  line

 0.4.19 (not publicly released)
--------
- More changes everywhere. Fixed another problem with Base64 files.
- Improvements everywhere :)
- Added progress meter to the decoder

 0.5.0 (07.06.1996)
-------
- Well, thought I have to release the stuff sooner or later.
- Fed the code into CVS for better revision control.

 0.5.1 (10.06.1996)
-------
- Fixed problem with multiple tiny Base64 files in a single message.

 0.5.2 (15.06.1996)
-------
- Cleaned up some code; now using size_t parameters for fread() and
  fwrite() and such.
- Fixed problem with short BinHex files.
- Use the initial and trailing colon `:' of BinHex files as
  `begin' and `end' markers.
- Only encode to message/partial embedded messages if we really
  have more than one part; otherwise encode directly to toplevel
  MIME body.

 0.5.3 (23.06.1996)
-------
- Complete rewrite of the scanning routines, which have been moved
  to uuscan.c and grown into the largest chunks of code.
- Mime files are properly treated with a pretty complete Mime par-
  ser. Outside of Mime messages, the scanner falls back to the old
  behaviour.
- Offers to `decode' plain text (and quoted-printable text) files
  with -t option.
- Intermediate preview release.

 0.5.4 (21.07.1996)
-------
- Rewrote encoding functions. The system-dependent stuff has moved
  to the outside of the library.
- Minor changes not affecting the frontend.

 0.5.5 (21.08.1996)
-------
- Bugfixes:
- Sometimes, the file pointer wasn't properly rewound to the beginning
  of the headers after bumping into them.
- The Binhex RLE decompressor produced garbage with repetition counts
  greater than 127 (which were expanded into negative integers)
- Stripping the last CRLF of a plain-text message was fatal if the
  piece was really an unhandled message/multipart part.

 0.5.6 (28.08.1996)
-------
- The Mime-Id buffer in uuencode.c:UUE_PrepPartial() was too small,
  causing it to be partially overwritten
- Added code to read part number and file name from UUEnview-Style
  headers. Especially important for filename detection with pure
  Base64. I consider this an ugly hack, but users call for it.

 0.5.7 (04.09.1996)
-------
- Added "attach" option to uuenview: read a msg from stdin and attach
  one or more files using proper MIME multipart/mixed style.
- Fixed configure script: we might need $x_includes for 
- Fixed rules for "make install"

 0.5.8 (13.09.1996)
-------
- Fixed output filename when encoding dotfiles
- Fixed uudecode compatibilty mode (would crash when reading stdin)
- Fixed bug with long header lines (was actually a bug in _FP_strncpy)
- Fixed bug when mailing directly from uuenview. The recipient address
  length must be added when composing the command.
- Added configure options --enable-sendmail and --enable-inews

 0.5.9 (29.09.1996)
-------
- Fixed percentage display for >20Meg files on 32bit systems, where
  100*fsize becomes > MAXINT ...
- Fixed problem with "--- cut here ---" lines that were misinterpreted
  as MIME boundaries.
- A user tried to decode a file with an early truncated MIME message
  and another message later with the same boundary. Consequently, all
  data inbetween was ignored. Added check for a Content-Type with the
  same boundary when scanning a subpart.
- Allow to specify more dumbness on UUDeview's command line to ignore
  subjects as well as part numbers. Fixed a problem with dumb mode as
  well.

 0.5.10 (01.10.1996)
--------
- Plugged memory leak in uucheck.c:PreProcessPart()

 0.5.11 (03.10.1996)
--------
- Added workaround for broken uuencoded files sent from MS Exchange.

 0.5.12 (23.12.1996)
--------
- Fixed bug with aborted decoding runs that the tempfile was deleted,
  but UUFILE_TMPFILE was still set.
- Make uudeview return a more or less sensible return value: 0 if all
  files were decoded successfully, 99 for miscellaneous errors, 2 if
  all files failed to decode, or 3 if some files were decoded okay
  and others failed.
- Added -n option to uudeview to not print progress bars.
- You can now set global options for UUDeview in the UUDEVIEW environ-
  ment variable. Options set there may be overrridden on the command
  line.
- Some tweaking to make some troublesome input files (for example with
  interleaved blank lines) decode.
- Fixed bug that caused erroneously decoded data when UUencoded data
  looked like Base64 (because of the overlapping alphabet)

 0.5.13 (09.01.1997)
--------
- Fixed bug in uuscan.c.
- Fixed another bug in uuscan.c which happened when a filename
  on the Content-Type line happened to contain a header keyword.
- Fixed infinite loop when trying to descramble Netscape data;
  in one place we were looking for  8.0
- Do not use "dangerous" gets in minews, replace by fgets
- If the file looks like MIME, be more strict when scanning "text/*"
  parts for encoded data.
- Add +o option to never overwrite files (useful in non-interactive
  mode)
- Add -c option to autoclear input files from which anything was decoded.
  Use with care - UUDeview does not care about anything else in that file.
- Add -z option for improved MIME compliance on MIME messages.
- Improved encoding detection, it should now be less sensitive to data
  that looks both like uu and Base 64.
- Add -r (Reply-To:) and -f (From:) options to uuenview
- Support encoding as quoted-printable
- Support "encoding" as plain text
- Add -t and -q options to uuenview for that
- Make the encoding to be used depend on the last -ubxtq option, so that
  you can send plain text and binary attachments on the same command line.
- Make uuenview read the $UUENVIEW command line option
- Tag attachments as "text/plain" if plain text or quoted printable is
  used and no other mime type is appropriate.
- Recognize a boundary when scanning a file in "freestyle" mode. This is
  similar to the AOL handling above.

 0.5.16 (26.08.2001)
--------
- fix handling of "x-uue" encoded MIME attachments
- bug fix for file renaming

 0.5.17 (06.03.2002)
--------
- fix handling of quoted parameters
- some support for yEnc encoding

 0.5.18 (02.04.2002)
--------
- fix for yEnc files in UUInfoFile
- patch by Matthew Mueller:
  - add CRC generation and checks for yEnc
  - accept yEnc files where the tab character is not escaped
  - improved error checking for yEnc files

Convert-UUlib-1.5/COPYING0000644000000000000000000000072710541071137013553 0ustar  rootrootThis interface is distributed under the same license as perl itself, i.e.
either the Artistic License (COPYING.Artistic) or the GPL (COPYING.GNU).

However, the uulib library itself (see the subdirectory uulib) is ONLY
distributed under the GENERAL PUBLIC LICENSE (COPYING.GNU). Depending on
how you use and distribute it, this makes the whole package fall under the
GPL.

If you make modifications, please consider sending them to me,
Marc Lehmann 

Convert-UUlib-1.5/README0000644000000000000000000003303612550073763013410 0ustar  rootrootNAME
    Convert::UUlib - Perl interface to the uulib library (a.k.a.
    uudeview/uuenview).

SYNOPSIS
     use Convert::UUlib ':all';
 
     # read all the files named on the commandline and decode them
     # into the CURRENT directory. See below for a longer example.
     LoadFile $_ for @ARGV;
     for (my $i = 0; my $uu = GetFileListItem $i; $i++) {
        if ($uu->state & FILE_OK) {
          $uu->decode;
          print $uu->filename, "\n";
        }
     }

DESCRIPTION
    Read the file doc/library.pdf from the distribution for in-depth
    information about the C-library used in this interface, and the rest of
    this document and especially the non-trivial decoder program at the end.

EXPORTED CONSTANTS
  Action code constants
      ACT_IDLE      we don't do anything
      ACT_SCANNING  scanning an input file
      ACT_DECODING  decoding into a temp file
      ACT_COPYING   copying temp to target
      ACT_ENCODING  encoding a file

  Message severity levels
      MSG_MESSAGE   just a message, nothing important
      MSG_NOTE      something that should be noticed
      MSG_WARNING   important msg, processing continues
      MSG_ERROR     processing has been terminated
      MSG_FATAL     decoder cannot process further requests
      MSG_PANIC     recovery impossible, app must terminate

  Options
      OPT_VERSION   version number MAJOR.MINORplPATCH (ro)
      OPT_FAST      assumes only one part per file
      OPT_DUMBNESS  switch off the program's intelligence
      OPT_BRACKPOL  give numbers in [] higher precendence
      OPT_VERBOSE   generate informative messages
      OPT_DESPERATE try to decode incomplete files
      OPT_IGNREPLY  ignore RE:plies (off by default)
      OPT_OVERWRITE whether it's OK to overwrite ex. files
      OPT_SAVEPATH  prefix to save-files on disk
      OPT_IGNMODE   ignore the original file mode
      OPT_DEBUG     print messages with FILE/LINE info
      OPT_ERRNO     get last error code for RET_IOERR (ro)
      OPT_PROGRESS  retrieve progress information
      OPT_USETEXT   handle text messages
      OPT_PREAMB    handle Mime preambles/epilogues
      OPT_TINYB64   detect short B64 outside of Mime
      OPT_ENCEXT    extension for single-part encoded files
      OPT_REMOVE    remove input files after decoding (dangerous)
      OPT_MOREMIME  strict MIME adherence
      OPT_DOTDOT    ".."-unescaping has not yet been done on input files
      OPT_RBUF      set default read I/O buffer size in bytes
      OPT_WBUF      set default write I/O buffer size in bytes
      OPT_AUTOCHECK automatically check file list after every loadfile

  Result/Error codes
      RET_OK        everything went fine
      RET_IOERR     I/O Error - examine errno
      RET_NOMEM     not enough memory
      RET_ILLVAL    illegal value for operation
      RET_NODATA    decoder didn't find any data
      RET_NOEND     encoded data wasn't ended properly
      RET_UNSUP     unsupported function (encoding)
      RET_EXISTS    file exists (decoding)
      RET_CONT      continue -- special from ScanPart
      RET_CANCEL    operation canceled

  File States
     This code is zero, i.e. "false":

      UUFILE_READ   Read in, but not further processed

     The following state codes are or'ed together:

      FILE_MISPART  Missing Part(s) detected
      FILE_NOBEGIN  No 'begin' found
      FILE_NOEND    No 'end' found
      FILE_NODATA   File does not contain valid uudata
      FILE_OK       All Parts found, ready to decode
      FILE_ERROR    Error while decoding
      FILE_DECODED  Successfully decoded
      FILE_TMPFILE  Temporary decoded file exists

  Encoding types
      UU_ENCODED    UUencoded data
      B64_ENCODED   Mime-Base64 data
      XX_ENCODED    XXencoded data
      BH_ENCODED    Binhex encoded
      PT_ENCODED    Plain-Text encoded (MIME)
      QP_ENCODED    Quoted-Printable (MIME)
      YENC_ENCODED  yEnc encoded (non-MIME)

EXPORTED FUNCTIONS
  Initializing and cleanup
    Initialize is automatically called when the module is loaded and
    allocates quite a small amount of memory for todays machines ;) CleanUp
    releases that again.

    On my machine, a fairly complete decode with DBI backend needs about
    10MB RSS to decode 20000 files.

    Initialize
        Not normally necessary, (re-)initializes the library.

    CleanUp
        Not normally necessary, could be called at the end to release memory
        before starting a new decoding round.

  Setting and querying options
    $option = GetOption OPT_xxx
    SetOption OPT_xxx, opt-value

    See the "OPT_xxx" constants above to see which options exist.

  Setting various callbacks
    SetMsgCallback [callback-function]
    SetBusyCallback [callback-function]
    SetFileCallback [callback-function]
    SetFNameFilter [callback-function]

  Call the currently selected FNameFilter
    $file = FNameFilter $file

  Loading sourcefiles, optionally fuzzy merge and start decoding
    ($retval, $count) = LoadFile $fname, [$id, [$delflag, [$partno]]]
        Load the given file and scan it for encoded contents. Optionally tag
        it with the given id, and if $delflag is true, delete the file after
        it is no longer necessary. If you are certain of the part number,
        you can specify it as the last argument.

        A better (usually faster) way of doing this is using the
        "SetFNameFilter" functionality.

    $retval = Smerge $pass
        If you are desperate, try to call "Smerge" with increasing $pass
        values, beginning at 0, to try to merge parts that usually would not
        have been merged.

        Most probably this will result in garbled files, so never do this by
        default, except:

        If the "OPT_AUTOCHECK" option has been disabled (by default it is
        enabled) to speed up file loading, then you *have* to call "Smerge
        -1" after loading all files as an additional pre-pass (which is
        normally done by "LoadFile").

    $item = GetFileListItem $item_number
        Return the $item structure for the $item_number'th found file, or
        "undef" of no file with that number exists.

        The first file has number 0, and the series has no holes, so you can
        iterate over all files by starting with zero and incrementing until
        you hit "undef".

  Decoding files
    $retval = $item->rename($newname)
        Change the ondisk filename where the decoded file will be saved.

    $retval = $item->decode_temp
        Decode the file into a temporary location, use "$item->infile" to
        retrieve the temporary filename.

    $retval = $item->remove_temp
        Remove the temporarily decoded file again.

    $retval = $item->decode([$target_path])
        Decode the file to it's destination, or the given target path.

    $retval = $item->info(callback-function)

  Querying (and setting) item attributes
    $state = $item->state
    $mode = $item->mode([newmode])
    $uudet = $item->uudet
    $size = $item->size
    $filename = $item->filename([newfilename})
    $subfname = $item->subfname
    $mimeid = $item->mimeid
    $mimetype = $item->mimetype
    $binfile = $item->binfile

  Information about source parts
    $parts = $item->parts
        Return information about all parts (source files) used to decode the
        file as a list of hashrefs with the following structure:

         {
           partno   => ,
           # the following member sonly exist when they contain useful information
           sfname   => ,
           filename => ,
           subfname => ,
           subject  => ,
           origin   => ,
           mimetype => ,
           mimeid   => ,
         }

        Usually you are interested mostly the "sfname" and possibly the
        "partno" and "filename" members.

  Functions below not documented and not very well tested
      QuickDecode
      EncodeMulti
      EncodePartial
      EncodeToStream
      EncodeToFile
      E_PrepSingle
      E_PrepPartial

  EXTENSION FUNCTIONS
    Functions found in this module but not documented in the uulib
    documentation:

    $msg = straction ACT_xxx
        Return a human readable string representing the given action code.

    $msg = strerror RET_xxx
        Return a human readable string representing the given error code.

    $str = strencoding xxx_ENCODED
        Return the name of the encoding type as a string.

    $str = strmsglevel MSG_xxx
        Returns the message level as a string.

    SetFileNameCallback $cb
        Sets (or queries) the FileNameCallback, which is called whenever the
        decoding library can't find a filename and wants to extract a
        filename from the subject line of a posting. The callback will be
        called with two arguments, the subject line and the current
        candidate for the filename. The latter argument can be "undef",
        which means that no filename could be found (and likely no one
        exists, so it is safe to also return "undef" in this case). If it
        doesn't return anything (not even "undef"!), then nothing happens,
        so this is a no-op callback:

           sub cb {
              return ();
           }

        If it returns "undef", then this indicates that no filename could be
        found. In all other cases, the return value is taken to be the
        filename.

        This is a slightly more useful callback:

          sub cb {
             return unless $_[1]; # skip "Re:"-plies et al.
             my ($subject, $filename) = @_;
             # if we find some *.rar, take it
             return $1 if $subject =~ /(\w+\.rar)/;
             # otherwise just pass what we have
             return ();
          }

LARGE EXAMPLE DECODER
    This is the file "example-decoder" from the distribution, put here
    instead of more thorough documentation.

       #!/usr/bin/perl

       # decode all the files in the directory uusrc/ and copy
       # the resulting files to uudst/

       use Convert::UUlib ':all';

       sub namefilter {
          my ($path) = @_;

          $path=~s/^.*[\/\\]//;

          $path
       }

       sub busycb {
          my ($action, $curfile, $partno, $numparts, $percent, $fsize) = @_;
          $_[0]=straction($action);
          print "busy_callback(", (join ",",@_), ")\n";
          0
       }

       SetOption OPT_RBUF, 128*1024;
       SetOption OPT_WBUF, 1024*1024;
       SetOption OPT_IGNMODE, 1;
       SetOption OPT_IGNMODE, 1;
       SetOption OPT_VERBOSE, 1;

       # show the three ways you can set callback functions. I normally
       # prefer the one with the sub inplace.
       SetFNameFilter \&namefilter;

       SetBusyCallback "busycb", 333;

       SetMsgCallback sub {
          my ($msg, $level) = @_;
          print uc strmsglevel $_[1], ": $msg\n";
       };

       # the following non-trivial FileNameCallback takes care
       # of some subject lines not detected properly by uulib:
       SetFileNameCallback sub {
          return unless $_[1]; # skip "Re:"-plies et al.
          local $_ = $_[0];

          # the following rules are rather effective on some newsgroups,
          # like alt.binaries.games.anime, where non-mime, uuencoded data
          # is very common

          # if we find some *.rar, take it as the filename
          return $1 if /(\S{3,}\.(?:[rstuvwxyz]\d\d|rar))\s/i;

          # one common subject format
          return $1 if /- "(.{2,}?\..+?)" (?:yenc )?\(\d+\/\d+\)/i;

          # - filename.par (04/55)
          return $1 if /- "?(\S{3,}\.\S+?)"? (?:yenc )?\(\d+\/\d+\)/i;

          # - (xxx) No. 1 sayuri81.jpg 756565 bytes
          # - (20 files) No.17 Roseanne.jpg [2/2]
          return $1 if /No\.[ 0-9]+ (\S+\....) (?:\d+ bytes )?\[/;

          # try to detect some common forms of filenames
          return $1 if /([a-z0-9_\-+.]{3,}\.[a-z]{3,4}(?:.\d+))/i;

          # otherwise just pass what we have
          ()
       };

       # now read all files in the directory uusrc/*
       for() {
          my ($retval, $count) = LoadFile ($_, $_, 1);
          print "file($_), status(", strerror $retval, ") parts($count)\n";
       }

       SetOption OPT_SAVEPATH, "uudst/";

       # now wade through all files and their source parts
       $i = 0;
       while ($uu = GetFileListItem $i) {
          $i++;
          print "file nr. $i";
          print " state ", $uu->state;
          print " mode ", $uu->mode;
          print " uudet ", strencoding $uu->uudet;
          print " size ", $uu->size;
          print " filename ", $uu->filename;
          print " subfname ", $uu->subfname;
          print " mimeid ", $uu->mimeid;
          print " mimetype ", $uu->mimetype;
          print "\n";

          # print additional info about all parts
          for ($uu->parts) {
             while (my ($k, $v) = each %$_) {
                print "$k > $v, ";
             }
             print "\n";
          }

          print $uu->filename;

          $uu->remove_temp;

          if (my $err = $uu->decode ()) {
             print ", ", strerror $err, "\n";
          } else {
             print ", saved as uudst/", $uu->filename, "\n";
          }
       }

       print "cleanup...\n";

       CleanUp;

AUTHOR
    Marc Lehmann , the original uulib library was
    written by Frank Pilhofer , and later
    heavily bugfixed by Marc Lehmann.

SEE ALSO
    perl(1), uudeview homepage at http://www.uni-frankfurt.de/~fp/uudeview/.

Convert-UUlib-1.5/UUlib.pm0000644000000000000000000003637512547615721014121 0ustar  rootrootpackage Convert::UUlib;

no warnings;
use strict;

use Carp;

require Exporter;
require DynaLoader;

our $VERSION = 1.5;

our @ISA = qw(Exporter DynaLoader);

our @_consts = qw(
	ACT_COPYING ACT_DECODING ACT_ENCODING ACT_IDLE ACT_SCANNING

	FILE_DECODED FILE_ERROR FILE_MISPART FILE_NOBEGIN FILE_NODATA
	FILE_NOEND FILE_OK FILE_READ FILE_TMPFILE

	MSG_ERROR MSG_FATAL MSG_MESSAGE MSG_NOTE MSG_PANIC MSG_WARNING

        OPT_RBUF OPT_WBUF
	OPT_BRACKPOL OPT_DEBUG OPT_DESPERATE OPT_DUMBNESS OPT_ENCEXT
	OPT_ERRNO OPT_FAST OPT_IGNMODE OPT_IGNREPLY OPT_OVERWRITE OPT_PREAMB
	OPT_PROGRESS OPT_SAVEPATH OPT_TINYB64 OPT_USETEXT OPT_VERBOSE
	OPT_VERSION OPT_REMOVE OPT_MOREMIME OPT_DOTDOT OPT_AUTOCHECK

	RET_CANCEL RET_CONT RET_EXISTS RET_ILLVAL RET_IOERR RET_NODATA
	RET_NOEND RET_NOMEM RET_OK RET_UNSUP

	B64_ENCODED BH_ENCODED PT_ENCODED QP_ENCODED
	XX_ENCODED UU_ENCODED YENC_ENCODED
);

our @_funcs = qw(
        Initialize CleanUp GetOption SetOption strerror SetMsgCallback
        SetBusyCallback SetFileCallback SetFNameFilter SetFileNameCallback
        FNameFilter LoadFile GetFileListItem RenameFile DecodeToTemp
        RemoveTemp DecodeFile InfoFile Smerge QuickDecode EncodeMulti
        EncodePartial EncodeToStream EncodeToFile E_PrepSingle
        E_PrepPartial

        straction strencoding strmsglevel
);

our @EXPORT = @_consts;
our @EXPORT_OK = @_funcs;
our %EXPORT_TAGS = (all => [@_consts,@_funcs], constants => \@_consts);

bootstrap Convert::UUlib $VERSION;

Initialize();

# not when < 5.005_6x
# END { CleanUp() }

for (@_consts) {
   my $constant = constant($_);
   no strict 'refs';
   *$_ = sub () { $constant };
}

# action code -> string mapping
sub straction($) {
   return 'copying'	if $_[0] == &ACT_COPYING;
   return 'decoding'	if $_[0] == &ACT_DECODING;
   return 'encoding'	if $_[0] == &ACT_ENCODING;
   return 'idle'	if $_[0] == &ACT_IDLE;
   return 'scanning'	if $_[0] == &ACT_SCANNING;
   'unknown';
}

# encoding type -> string mapping
sub strencoding($) {
   return 'uuencode'		if $_[0] == &UU_ENCODED;
   return 'base64'		if $_[0] == &B64_ENCODED;
   return 'yenc'		if $_[0] == &YENC_ENCODED;
   return 'binhex'		if $_[0] == &BH_ENCODED;
   return 'plaintext'		if $_[0] == &PT_ENCODED;
   return 'quoted-printable'	if $_[0] == &QP_ENCODED;
   return 'xxencode'		if $_[0] == &XX_ENCODED;
   'unknown';
}

sub strmsglevel($) {
   return 'message'	if $_[0] == &MSG_MESSAGE;
   return 'note'	if $_[0] == &MSG_NOTE;
   return 'warning'	if $_[0] == &MSG_WARNING;
   return 'error'	if $_[0] == &MSG_ERROR;
   return 'panic'	if $_[0] == &MSG_PANIC;
   return 'fatal'	if $_[0] == &MSG_FATAL;
   'unknown';
}

1;
__END__

=head1 NAME

Convert::UUlib - Perl interface to the uulib library (a.k.a. uudeview/uuenview).

=head1 SYNOPSIS

 use Convert::UUlib ':all';
 
 # read all the files named on the commandline and decode them
 # into the CURRENT directory. See below for a longer example.
 LoadFile $_ for @ARGV;
 for (my $i = 0; my $uu = GetFileListItem $i; $i++) {
    if ($uu->state & FILE_OK) {
      $uu->decode;
      print $uu->filename, "\n";
    }
 }

=head1 DESCRIPTION

Read the file doc/library.pdf from the distribution for in-depth
information about the C-library used in this interface, and the rest of
this document and especially the non-trivial decoder program at the end.

=head1 EXPORTED CONSTANTS

=head2 Action code constants

  ACT_IDLE      we don't do anything
  ACT_SCANNING  scanning an input file
  ACT_DECODING  decoding into a temp file
  ACT_COPYING   copying temp to target
  ACT_ENCODING  encoding a file

=head2 Message severity levels

  MSG_MESSAGE   just a message, nothing important
  MSG_NOTE      something that should be noticed
  MSG_WARNING   important msg, processing continues
  MSG_ERROR     processing has been terminated
  MSG_FATAL     decoder cannot process further requests
  MSG_PANIC     recovery impossible, app must terminate

=head2 Options

  OPT_VERSION	version number MAJOR.MINORplPATCH (ro)
  OPT_FAST	assumes only one part per file
  OPT_DUMBNESS	switch off the program's intelligence
  OPT_BRACKPOL	give numbers in [] higher precendence
  OPT_VERBOSE	generate informative messages
  OPT_DESPERATE	try to decode incomplete files
  OPT_IGNREPLY	ignore RE:plies (off by default)
  OPT_OVERWRITE	whether it's OK to overwrite ex. files
  OPT_SAVEPATH	prefix to save-files on disk
  OPT_IGNMODE	ignore the original file mode
  OPT_DEBUG	print messages with FILE/LINE info
  OPT_ERRNO	get last error code for RET_IOERR (ro)
  OPT_PROGRESS	retrieve progress information
  OPT_USETEXT	handle text messages
  OPT_PREAMB	handle Mime preambles/epilogues
  OPT_TINYB64	detect short B64 outside of Mime
  OPT_ENCEXT	extension for single-part encoded files
  OPT_REMOVE	remove input files after decoding (dangerous)
  OPT_MOREMIME	strict MIME adherence
  OPT_DOTDOT	".."-unescaping has not yet been done on input files
  OPT_RBUF      set default read I/O buffer size in bytes
  OPT_WBUF      set default write I/O buffer size in bytes
  OPT_AUTOCHECK automatically check file list after every loadfile

=head2 Result/Error codes

  RET_OK        everything went fine
  RET_IOERR     I/O Error - examine errno
  RET_NOMEM     not enough memory
  RET_ILLVAL    illegal value for operation
  RET_NODATA    decoder didn't find any data
  RET_NOEND     encoded data wasn't ended properly
  RET_UNSUP     unsupported function (encoding)
  RET_EXISTS    file exists (decoding)
  RET_CONT      continue -- special from ScanPart
  RET_CANCEL    operation canceled

=head2 File States

 This code is zero, i.e. "false":

  UUFILE_READ   Read in, but not further processed

 The following state codes are or'ed together:

  FILE_MISPART  Missing Part(s) detected
  FILE_NOBEGIN  No 'begin' found
  FILE_NOEND    No 'end' found
  FILE_NODATA   File does not contain valid uudata
  FILE_OK       All Parts found, ready to decode
  FILE_ERROR    Error while decoding
  FILE_DECODED  Successfully decoded
  FILE_TMPFILE  Temporary decoded file exists

=head2 Encoding types

  UU_ENCODED    UUencoded data
  B64_ENCODED   Mime-Base64 data
  XX_ENCODED    XXencoded data
  BH_ENCODED    Binhex encoded
  PT_ENCODED    Plain-Text encoded (MIME)
  QP_ENCODED    Quoted-Printable (MIME)
  YENC_ENCODED  yEnc encoded (non-MIME)

=head1 EXPORTED FUNCTIONS

=head2 Initializing and cleanup

Initialize is automatically called when the module is loaded and allocates
quite a small amount of memory for todays machines ;) CleanUp releases that
again.

On my machine, a fairly complete decode with DBI backend needs about 10MB
RSS to decode 20000 files.

=over 4

=item Initialize

Not normally necessary, (re-)initializes the library.

=item CleanUp

Not normally necessary, could be called at the end to release memory
before starting a new decoding round.

=back

=head2 Setting and querying options

=over 4

=item $option = GetOption OPT_xxx

=item SetOption OPT_xxx, opt-value

=back

See the C constants above to see which options exist.

=head2 Setting various callbacks

=over 4

=item SetMsgCallback [callback-function]

=item SetBusyCallback [callback-function]

=item SetFileCallback [callback-function]

=item SetFNameFilter [callback-function]

=back

=head2 Call the currently selected FNameFilter

=over 4

=item $file = FNameFilter $file

=back

=head2 Loading sourcefiles, optionally fuzzy merge and start decoding

=over 4

=item ($retval, $count) = LoadFile $fname, [$id, [$delflag, [$partno]]]

Load the given file and scan it for encoded contents. Optionally tag it
with the given id, and if C<$delflag> is true, delete the file after it
is no longer necessary. If you are certain of the part number, you can
specify it as the last argument.

A better (usually faster) way of doing this is using the C
functionality.

=item $retval = Smerge $pass

If you are desperate, try to call C with increasing C<$pass>
values, beginning at C<0>, to try to merge parts that usually would not
have been merged.

Most probably this will result in garbled files, so never do this by
default, except:

If the C option has been disabled (by default it is
enabled) to speed up file loading, then you I to call C
after loading all files as an additional pre-pass (which is normally done
by C).

=item $item = GetFileListItem $item_number

Return the C<$item> structure for the C<$item_number>'th found file, or
C of no file with that number exists.

The first file has number C<0>, and the series has no holes, so you can
iterate over all files by starting with zero and incrementing until you
hit C.

=back

=head2 Decoding files

=over 4

=item $retval = $item->rename($newname)

Change the ondisk filename where the decoded file will be saved.

=item $retval = $item->decode_temp

Decode the file into a temporary location, use C<< $item->infile >> to
retrieve the temporary filename.

=item $retval = $item->remove_temp

Remove the temporarily decoded file again.

=item $retval = $item->decode([$target_path])

Decode the file to it's destination, or the given target path.

=item $retval = $item->info(callback-function)

=back

=head2 Querying (and setting) item attributes

=over 4

=item $state    = $item->state

=item $mode     = $item->mode([newmode])

=item $uudet    = $item->uudet

=item $size     = $item->size

=item $filename = $item->filename([newfilename})

=item $subfname = $item->subfname

=item $mimeid   = $item->mimeid

=item $mimetype = $item->mimetype

=item $binfile  = $item->binfile

=back

=head2 Information about source parts

=over 4

=item $parts = $item->parts

Return information about all parts (source files) used to decode the file
as a list of hashrefs with the following structure:

 {
   partno   => ,
   # the following member sonly exist when they contain useful information
   sfname   => ,
   filename => ,
   subfname => ,
   subject  => ,
   origin   => ,
   mimetype => ,
   mimeid   => ,
 }

Usually you are interested mostly the C and possibly the C
and C members.

=back

=head2 Functions below not documented and not very well tested

  QuickDecode
  EncodeMulti
  EncodePartial
  EncodeToStream
  EncodeToFile
  E_PrepSingle
  E_PrepPartial

=head2 EXTENSION FUNCTIONS

Functions found in this module but not documented in the uulib documentation:

=over 4

=item $msg = straction ACT_xxx

Return a human readable string representing the given action code.

=item $msg = strerror RET_xxx

Return a human readable string representing the given error code.

=item $str = strencoding xxx_ENCODED

Return the name of the encoding type as a string.

=item $str = strmsglevel MSG_xxx

Returns the message level as a string.

=item SetFileNameCallback $cb

Sets (or queries) the FileNameCallback, which is called whenever the
decoding library can't find a filename and wants to extract a filename
from the subject line of a posting. The callback will be called with
two arguments, the subject line and the current candidate for the
filename. The latter argument can be C, which means that no
filename could be found (and likely no one exists, so it is safe to also
return C in this case). If it doesn't return anything (not even
C!), then nothing happens, so this is a no-op callback:

   sub cb {
      return ();
   }

If it returns C, then this indicates that no filename could be
found. In all other cases, the return value is taken to be the filename.

This is a slightly more useful callback:

  sub cb {
     return unless $_[1]; # skip "Re:"-plies et al.
     my ($subject, $filename) = @_;
     # if we find some *.rar, take it
     return $1 if $subject =~ /(\w+\.rar)/;
     # otherwise just pass what we have
     return ();
  }

=back

=head1 LARGE EXAMPLE DECODER

This is the file C from the distribution, put here
instead of more thorough documentation.

   #!/usr/bin/perl

   # decode all the files in the directory uusrc/ and copy
   # the resulting files to uudst/

   use Convert::UUlib ':all';

   sub namefilter {
      my ($path) = @_;

      $path=~s/^.*[\/\\]//;

      $path
   }

   sub busycb {
      my ($action, $curfile, $partno, $numparts, $percent, $fsize) = @_;
      $_[0]=straction($action);
      print "busy_callback(", (join ",",@_), ")\n";
      0
   }

   SetOption OPT_RBUF, 128*1024;
   SetOption OPT_WBUF, 1024*1024;
   SetOption OPT_IGNMODE, 1;
   SetOption OPT_IGNMODE, 1;
   SetOption OPT_VERBOSE, 1;

   # show the three ways you can set callback functions. I normally
   # prefer the one with the sub inplace.
   SetFNameFilter \&namefilter;

   SetBusyCallback "busycb", 333;

   SetMsgCallback sub {
      my ($msg, $level) = @_;
      print uc strmsglevel $_[1], ": $msg\n";
   };

   # the following non-trivial FileNameCallback takes care
   # of some subject lines not detected properly by uulib:
   SetFileNameCallback sub {
      return unless $_[1]; # skip "Re:"-plies et al.
      local $_ = $_[0];

      # the following rules are rather effective on some newsgroups,
      # like alt.binaries.games.anime, where non-mime, uuencoded data
      # is very common

      # if we find some *.rar, take it as the filename
      return $1 if /(\S{3,}\.(?:[rstuvwxyz]\d\d|rar))\s/i;

      # one common subject format
      return $1 if /- "(.{2,}?\..+?)" (?:yenc )?\(\d+\/\d+\)/i;

      # - filename.par (04/55)
      return $1 if /- "?(\S{3,}\.\S+?)"? (?:yenc )?\(\d+\/\d+\)/i;

      # - (xxx) No. 1 sayuri81.jpg 756565 bytes
      # - (20 files) No.17 Roseanne.jpg [2/2]
      return $1 if /No\.[ 0-9]+ (\S+\....) (?:\d+ bytes )?\[/;

      # try to detect some common forms of filenames
      return $1 if /([a-z0-9_\-+.]{3,}\.[a-z]{3,4}(?:.\d+))/i;

      # otherwise just pass what we have
      ()
   };

   # now read all files in the directory uusrc/*
   for() {
      my ($retval, $count) = LoadFile ($_, $_, 1);
      print "file($_), status(", strerror $retval, ") parts($count)\n";
   }

   SetOption OPT_SAVEPATH, "uudst/";

   # now wade through all files and their source parts
   $i = 0;
   while ($uu = GetFileListItem $i) {
      $i++;
      print "file nr. $i";
      print " state ", $uu->state;
      print " mode ", $uu->mode;
      print " uudet ", strencoding $uu->uudet;
      print " size ", $uu->size;
      print " filename ", $uu->filename;
      print " subfname ", $uu->subfname;
      print " mimeid ", $uu->mimeid;
      print " mimetype ", $uu->mimetype;
      print "\n";

      # print additional info about all parts
      for ($uu->parts) {
         while (my ($k, $v) = each %$_) {
            print "$k > $v, ";
         }
         print "\n";
      }

      print $uu->filename;

      $uu->remove_temp;

      if (my $err = $uu->decode ()) {
         print ", ", strerror $err, "\n";
      } else {
         print ", saved as uudst/", $uu->filename, "\n";
      }
   }

   print "cleanup...\n";

   CleanUp;

=head1 AUTHOR

Marc Lehmann , the original uulib library was written
by Frank Pilhofer , and later heavily
bugfixed by Marc Lehmann.

=head1 SEE ALSO

perl(1), uudeview homepage at http://www.uni-frankfurt.de/~fp/uudeview/.

=cut
Convert-UUlib-1.5/t/0000755000000000000000000000000012550073763012766 5ustar  rootrootConvert-UUlib-1.5/t/cb.t0000644000000000000000000000043410211640772013530 0ustar  rootrootBEGIN { $| = 1; print "1..3\n"; }
END {print "not ok 1\n" unless $loaded;}
use Convert::UUlib ':all';
$loaded = 1;
print "ok 1\n";

SetFNameFilter(sub { $_[0]+1 });
print FNameFilter(5) == 6 ? "" : "not ","ok 2\n";
SetFNameFilter();
print FNameFilter(5) == 5 ? "" : "not ","ok 3\n";

Convert-UUlib-1.5/COPYING.GNU0000644000000000000000000004311010211642617014175 0ustar  rootroot		    GNU GENERAL PUBLIC LICENSE
		       Version 2, June 1991

 Copyright (C) 1989, 1991 Free Software Foundation, Inc.
     59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 Everyone is permitted to copy and distribute verbatim copies
 of this license document, but changing it is not allowed.

			    Preamble

  The licenses for most software are designed to take away your
freedom to share and change it.  By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users.  This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it.  (Some other Free Software Foundation software is covered by
the GNU Library General Public License instead.)  You can apply it to
your programs, too.

  When we speak of free software, we are referring to freedom, not
price.  Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.

  To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.

  For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have.  You must make sure that they, too, receive or can get the
source code.  And you must show them these terms so they know their
rights.

  We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.

  Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software.  If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.

  Finally, any free program is threatened constantly by software
patents.  We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary.  To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.

  The precise terms and conditions for copying, distribution and
modification follow.

		    GNU GENERAL PUBLIC LICENSE
   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION

  0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License.  The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language.  (Hereinafter, translation is included without limitation in
the term "modification".)  Each licensee is addressed as "you".

Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope.  The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.

  1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.

You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.

  2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:

    a) You must cause the modified files to carry prominent notices
    stating that you changed the files and the date of any change.

    b) You must cause any work that you distribute or publish, that in
    whole or in part contains or is derived from the Program or any
    part thereof, to be licensed as a whole at no charge to all third
    parties under the terms of this License.

    c) If the modified program normally reads commands interactively
    when run, you must cause it, when started running for such
    interactive use in the most ordinary way, to print or display an
    announcement including an appropriate copyright notice and a
    notice that there is no warranty (or else, saying that you provide
    a warranty) and that users may redistribute the program under
    these conditions, and telling the user how to view a copy of this
    License.  (Exception: if the Program itself is interactive but
    does not normally print such an announcement, your work based on
    the Program is not required to print an announcement.)

These requirements apply to the modified work as a whole.  If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works.  But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.

Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.

In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.

  3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:

    a) Accompany it with the complete corresponding machine-readable
    source code, which must be distributed under the terms of Sections
    1 and 2 above on a medium customarily used for software interchange; or,

    b) Accompany it with a written offer, valid for at least three
    years, to give any third party, for a charge no more than your
    cost of physically performing source distribution, a complete
    machine-readable copy of the corresponding source code, to be
    distributed under the terms of Sections 1 and 2 above on a medium
    customarily used for software interchange; or,

    c) Accompany it with the information you received as to the offer
    to distribute corresponding source code.  (This alternative is
    allowed only for noncommercial distribution and only if you
    received the program in object code or executable form with such
    an offer, in accord with Subsection b above.)

The source code for a work means the preferred form of the work for
making modifications to it.  For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable.  However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.

If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.

  4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License.  Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.

  5. You are not required to accept this License, since you have not
signed it.  However, nothing else grants you permission to modify or
distribute the Program or its derivative works.  These actions are
prohibited by law if you do not accept this License.  Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.

  6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions.  You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.

  7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License.  If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all.  For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.

If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.

It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices.  Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.

This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.

  8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded.  In such case, this License incorporates
the limitation as if written in the body of this License.

  9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time.  Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.

Each version is given a distinguishing version number.  If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation.  If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.

  10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission.  For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this.  Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.

			    NO WARRANTY

  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.

  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.

		     END OF TERMS AND CONDITIONS

	    How to Apply These Terms to Your New Programs

  If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.

  To do so, attach the following notices to the program.  It is safest
to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.

    
    Copyright (C)   

    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
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA


Also add information on how to contact you by electronic and paper mail.

If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:

    Gnomovision version 69, Copyright (C) year  name of author
    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
    This is free software, and you are welcome to redistribute it
    under certain conditions; type `show c' for details.

The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License.  Of course, the commands you use may
be called something other than `show w' and `show c'; they could even be
mouse-clicks or menu items--whatever suits your program.

You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary.  Here is a sample; alter the names:

  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
  `Gnomovision' (which makes passes at compilers) written by James Hacker.

  , 1 April 1989
  Ty Coon, President of Vice

This General Public License does not permit incorporating your program into
proprietary programs.  If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library.  If this is what you want to do, use the GNU Library General
Public License instead of this License.
Convert-UUlib-1.5/example-decoder0000644000000000000000000000600111501754725015500 0ustar  rootroot#!/usr/bin/perl

# decode all the files in the directory uusrc/ and copy
# the resulting files to uudst/

use Convert::UUlib ':all';

sub namefilter {
   my ($path) = @_;

   $path=~s/^.*[\/\\]//;

   $path
}

sub busycb {
   my ($action, $curfile, $partno, $numparts, $percent, $fsize) = @_;
   $_[0]=straction($action);
   print "busy_callback(", (join ",",@_), ")\n";
   0
}

SetOption OPT_RBUF, 128*1024;
SetOption OPT_WBUF, 1024*1024;
SetOption OPT_IGNMODE, 1;
SetOption OPT_VERBOSE, 1;
SetOption OPT_DOTDOT, 1;
SetOption OPT_AUTOCHECK, 0;

# show the three ways you can set callback functions. I normally
# prefer the one with the sub inplace.
SetFNameFilter \&namefilter;

SetBusyCallback "busycb", 333;

SetMsgCallback sub {
   my ($msg, $level) = @_;
   print uc strmsglevel $_[1], ": $msg\n";
};

# the following non-trivial FileNameCallback takes care
# of some subject lines not detected properly by uulib:
SetFileNameCallback sub {
   return unless $_[1]; # skip "Re:"-plies et al.
   local $_ = $_[0];

   if ($_[1] =~ /^(img_?\d+|\d+\w?)\./) {
      return "$1 $_[1]"
         if /^\s*\(([^)]+)\) \[\d+/;
   }

   # the following rules are rather effective on some newsgroups,
   # like alt.binaries.games.anime, where non-mime, uuencoded data
   # is very common

   # File 06 of 33 - Kendo - Final - 0001.jpg (2/3)
   return $1 if /File \d+ of \d+ - (.*) \(\d+\/\d+\)/i;

   # if we find some *.rar, take it as the filename
   return $1 if /(\S{3,}\.(?:[rstuvwxyz]\d\d|rar))\s/i;

   # one common subject format
   return $1 if /- "(.{2,}?\..+?)" (?:yenc )?\(\d+\/\d+\)/i;

   # - filename.par (04/55)
   return $1 if /- "?(\S{3,}\.\S+?)"? (?:yenc )?\(\d+\/\d+\)/i;

   # - (xxx) No. 1 sayuri81.jpg 756565 bytes
   # - (20 files) No.17 Roseanne.jpg [2/2]
   return $1 if /No\.[ 0-9]+ (\S+\....) (?:\d+ bytes )?\[/;

   # try to detect some common forms of filenames
   return $1 if /([a-z0-9_\-+.]{3,}\.[a-z]{3,4}(?:.\d+))/i;

   # otherwise just pass what we have
   ()
};

# now read all files in the directory uusrc/*
for() {
   my ($retval, $count) = LoadFile ($_, $_, 1);
   print "file($_), status(", strerror $retval, ") parts($count)\n";
}

Smerge -1;

SetOption OPT_SAVEPATH, "uudst/";

# now wade through all files and their source parts
$i = 0;
while ($uu = GetFileListItem $i) {
   $i++;
   print "file nr. $i";
   print " state ", $uu->state;
   print " mode ", $uu->mode;
   print " uudet ", strencoding $uu->uudet;
   print " size ", $uu->size;
   print " filename ", $uu->filename;
   print " subfname ", $uu->subfname;
   print " mimeid ", $uu->mimeid;
   print " mimetype ", $uu->mimetype;
   print "\n";

   # print additional info about all parts
   for ($uu->parts) {
      while (my ($k, $v) = each %$_) {
         print "$k > $v, ";
      }
      print "\n";
   }

   print $uu->filename;

   $uu->remove_temp;

   print "state, ">";#d#
   if (my $err = $uu->decode) {
      print ", ", strerror $err, "\n";
   } else {
      print ", saved as uudst/", $uu->filename, "\n";
   }
}

print "cleanup...\n";

CleanUp;
Convert-UUlib-1.5/MANIFEST0000644000000000000000000000124712550073763013660 0ustar  rootrootREADME
Changes
MANIFEST
COPYING.Artistic
COPYING.GNU
COPYING
Makefile.PL
UUlib.pm
UUlib.xs
typemap
example-decoder
t/cb.t
doc/library.pdf
doc/HISTORY
uulib/safealloc.c
uulib/Makefile.in
uulib/acconfig.h
uulib/aclocal.m4
uulib/config.h.in
uulib/configure
uulib/configure.in
uulib/crc32.c
uulib/crc32.h
uulib/fptools.c
uulib/fptools.h
uulib/uucheck.c
uulib/uudeview.h
uulib/uuencode.c
uulib/uuint.h
uulib/uulib.c
uulib/uunconc.c
uulib/uuscan.c
uulib/uustring.awk
uulib/uustring.c
uulib/uustring.h
uulib/uuutil.c

META.yml                                 Module YAML meta-data (added by MakeMaker)
META.json                                Module JSON meta-data (added by MakeMaker)