Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | File List | Namespace Members | Class Members | File Members | Related Pages

basestrm.cpp

Go to the documentation of this file.
00001 
00005 /*
00006     This file is part of Advanced Strategic Command; http://www.asc-hq.de
00007     Copyright (C) 1994-2005  Martin Bickel  and  Marc Schellenberger
00008 
00009     This program is free software; you can redistribute it and/or modify
00010     it under the terms of the GNU General Public License as published by
00011     the Free Software Foundation; either version 2 of the License, or
00012     (at your option) any later version.
00013 
00014     This program is distributed in the hope that it will be useful,
00015     but WITHOUT ANY WARRANTY; without even the implied warranty of
00016     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00017     GNU General Public License for more details.
00018 
00019     You should have received a copy of the GNU General Public License
00020     along with this program; see the file COPYING. If not, write to the 
00021     Free Software Foundation, Inc., 59 Temple Place, Suite 330, 
00022     Boston, MA  02111-1307  USA
00023 */
00024 
00025 #include <stdio.h> 
00026 #include <ctype.h>
00027 #include <cstdlib>
00028 #include <stdlib.h>
00029 #include <string>
00030 #include <list>
00031 
00032 #include "global.h"
00033 
00034 #ifdef HAVE_LIMITS
00035  #include <limits> 
00036 #endif
00037 
00038 
00039 #include <sys/stat.h>
00040 
00041 #include "global.h"
00042 #include "basestrm.h"
00043 
00044 #ifdef _DOS_
00045   #include "dos/fileio.h"
00046 #else
00047  #ifdef _WIN32_
00048    #include "win32/fileio.h"
00049  #else
00050   #ifdef _UNIX_
00051     #include "unix/fileio.h"
00052   #endif
00053  #endif
00054 #endif
00055 
00056 //#include sdlheader
00057 #include <SDL_endian.h>
00058 
00059 
00060 #include "messaginghub.h"
00061 
00062 
00063  const int maxSearchDirNum = 30;
00064  int searchDirNum = 0;
00065  char* ascDirectory[maxSearchDirNum] = { NULL, NULL, NULL, NULL, NULL,
00066                                          NULL, NULL, NULL, NULL, NULL };
00067 
00068 
00069 
00070 
00071 #pragma pack(1)
00072 struct trleheader {
00073    unsigned short int id;
00074    unsigned short int size;
00075    char rle;
00076    unsigned short int x;
00077    unsigned short int y;
00078 };
00079 
00080 #pragma pack()
00081 
00082 #define bzip_xor_byte 'M'
00083 
00084 const char* containermagic = "NCBM";
00085 
00086 const char* LZ_SIGNATURE  =  "MBLZW16";
00087 const char* RLE_SIGNATURE =  "MBRLE1";
00088 const char* BZIP_SIGNATURE = "MBZLB2X!";
00089 
00090 
00091 
00092 
00093 
00097 
00098 CharBuf :: CharBuf ( void )
00099          {
00100             size = 0;
00101             buf = NULL;
00102          }
00103 
00104 CharBuf :: CharBuf ( int _size )
00105 
00106          {
00107             size = _size;
00108             buf = new char[ size ];
00109          }
00110 
00111 void CharBuf :: resize ( int newsize )
00112          {
00113             char* nb = new char[newsize];
00114             for ( int i = 0; i < size; i++ )
00115                nb[i] = buf[i];
00116 
00117             delete[] buf;
00118             buf = nb;
00119          }
00120 
00121 CharBuf :: ~CharBuf()
00122          {
00123             if ( buf )
00124                delete[] buf;
00125             buf = NULL;
00126          }
00127 
00131 
00132 
00133 
00134 toutofmem::toutofmem ( int m )
00135 {
00136   required = m; 
00137 }
00138 
00139 tfileerror::tfileerror ( const ASCString& fileName )
00140 {
00141    _filename = fileName ;
00142 }
00143 
00144 
00145 /*
00146 tfileerror::~tfileerror()
00147 {
00148    if ( filename ) {
00149       delete filename;
00150       filename = NULL;
00151    }
00152 }
00153 */
00154 
00155 tinvalidmode :: tinvalidmode ( const ASCString& _fileName, tnstream::IOMode org_mode, tnstream::IOMode requested_mode )
00156               : tfileerror ( _fileName )
00157 {
00158    orgmode = org_mode;
00159    requestmode = requested_mode;
00160 }
00161 
00162 
00163 
00164 treadafterend :: treadafterend ( const ASCString& _fileName )
00165                : tfileerror ( _fileName )
00166 {
00167 
00168 }
00169 
00170 
00171 tinternalerror::tinternalerror (  const char* filename, int l )
00172 {
00173    linenum = l;
00174    sourcefilename = filename;
00175 }
00176 
00177 
00178 
00179 tinvalidversion :: tinvalidversion ( const ASCString& _fileName, int ex, int fnd )
00180                  : tfileerror ( _fileName ), expected ( ex ), found ( fnd )
00181 {
00182 }
00183 
00184 ASCString tinvalidversion :: getMessage() const
00185 {
00186    ASCString s;
00187    if ( expected < found )
00188       s.format( "File/module %s has invalid version.\nExpected file version %d\nFound file version %d\nThe file/module is newer than your application\nPlease install the latest version of ASC from www.asc-hq.org", getFileName().c_str(), expected, found );
00189    else
00190       s.format ( "File/module %s has invalid version.\nExpected file version %d\nFound file version %d\nThis is a bug, please report it!", getFileName().c_str(), expected, found );
00191 
00192    return s;
00193 }
00194 
00195 
00196 
00200 
00201 
00202 tnstream :: tnstream ( void ) 
00203           : devicename ( "-abstract tnstream-" ) {}
00204 
00205 void tnstream::seek ( int pos )
00206 {
00207    throw tfileerror ( "Seeking not supported for stream " + getDeviceName() );
00208 }
00209 
00210 void         tnstream::readrlepict( void** pnter, bool allocated, int* size)
00211 { 
00212   trleheader   hd; 
00213   int          w;
00214   char*        q;
00215 
00216   hd.id = readWord();
00217   hd.size = readWord();
00218   hd.rle = readChar();
00219   hd.x = readWord();
00220   hd.y = readWord();
00221 
00222    if (hd.id == 16973) {
00223       if (!allocated)
00224         *pnter = new char [ hd.size + sizeof(hd) ];
00225       memcpy( *pnter, &hd, sizeof(hd));
00226       q = (char*) (*pnter) + sizeof(hd);
00227 
00228       readdata( q, hd.size);  // endian ok ?
00229       *size = hd.size + sizeof(hd);
00230    }
00231    else {
00232       w =  (hd.id + 1) * (hd.size + 1) + 4 ;
00233       if (!allocated)
00234         *pnter = new char [ w ];
00235       memcpy ( *pnter, &hd, sizeof ( hd ));
00236       q = (char*) (*pnter) + sizeof(hd);
00237       readdata ( q, w - sizeof(hd) ); // endian ok ?
00238       *size = w;
00239    }
00240 }
00241 
00242 
00243 
00244 void tnstream :: writerlepict ( const void* buf )
00245 {
00246    writeImage( buf, true );
00247 }
00248 
00249 void tnstream :: writeImage ( const void* buf, bool compress )
00250 {
00251    if ( compress ) {
00252       char* tempbuf = new char [ 0xffff ];
00253       if ( tempbuf ) {
00254          int   size    = compressrle ( buf, tempbuf );
00255          trleheader* hd = (trleheader*) tempbuf;
00256          writeWord( hd->id );
00257          writeWord( hd->size );
00258          writeChar( hd->rle );
00259          writeWord( hd->x );
00260          writeWord( hd->y );
00261          
00262          writedata ( hd+1, size - sizeof(*hd) );
00263          delete[] tempbuf;
00264       } else
00265          compress = false;
00266    }
00267 
00268    if ( !compress )  {
00269       Uint16* pw = (Uint16*) buf;
00270       writeWord(pw[0] );
00271       writeWord(pw[1] );
00272       writedata ( pw+2, ( pw[0] + 1 ) * ( pw[1] + 1 ) );
00273    }
00274 }
00275 
00276 
00277 ASCString tnstream::getDeviceName ( void )
00278 {
00279    return devicename;
00280 }
00281 
00282 ASCString tnstream::getLocation ( void )
00283 {
00284    return devicename;
00285 }
00286 
00287 int  tnstream::readInt  ( void )
00288 {
00289    int i;
00290    readdata2 ( i );
00291    return SDL_SwapLE32( i );
00292 }
00293 
00294 int tnstream::readWord ( void )
00295 {
00296    Uint16 w;
00297    readdata2 ( w );
00298    return SDL_SwapLE16( w );
00299 }
00300 
00301 char tnstream::readChar ( void )
00302 {
00303    char c;
00304    readdata2 ( c );
00305    return c;
00306 }
00307 
00308 float SwapFloat( float f )
00309 {
00310   union
00311   {
00312     float f;
00313     unsigned char b[4];
00314   } dat1, dat2;
00315 
00316   dat1.f = f;
00317   dat2.b[0] = dat1.b[3];
00318   dat2.b[1] = dat1.b[2];
00319   dat2.b[2] = dat1.b[1];
00320   dat2.b[3] = dat1.b[0];
00321   return dat2.f;
00322 }
00323 
00324 float tnstream::readFloat ( void )
00325 {
00326    float c;
00327    readdata2 ( c );
00328 #if SDL_BYTEORDER == SDL_BIG_ENDIAN
00329    c = SwapFloat(c);
00330 #endif
00331    return c;
00332 }
00333 
00334 #if SIZE_T_not_identical_to_INT
00335 
00336 void tnstream::writeInt  ( size_t i )
00337 {
00338 #ifdef HAVE_LIMITS
00339    // assert( i <=  numeric_limits<int>::max());
00340 #endif
00341    writeInt( int(i) );
00342 }
00343 
00344 #endif
00345 
00346 void tnstream::writeInt  ( unsigned int i )
00347 {
00348    i = SDL_SwapLE32(i);
00349    writedata2 ( i );
00350 }
00351 
00352 void tnstream::writeInt  ( bool b )
00353 {
00354    int i = b;
00355    i = SDL_SwapLE32(i);
00356    writedata2 ( i );
00357 }
00358 
00359 void tnstream::writeInt  ( int i )
00360 {
00361    i = SDL_SwapLE32(i);
00362    writedata2 ( i );
00363 }
00364 
00365 void tnstream::writeWord ( int w )
00366 {
00367    Uint16 w2 = SDL_SwapLE16( Uint16(w) );
00368    writedata2 ( w2 );
00369 }
00370 
00371 void tnstream::writeChar ( char c )
00372 {
00373    writedata2 ( c );
00374 }
00375 
00376 void tnstream::writeFloat ( float f )
00377 {
00378    writedata2 ( f );
00379 }
00380 
00381 void         tnstream::readpchar(char** pc, int maxlength )
00382 { 
00383    int actpos2 = 0; 
00384 
00385    int maxav = 100000;
00386                             
00387    if ( maxlength )
00388       if ( maxav > maxlength )
00389          maxav = maxlength;
00390 
00391    CharBuf charbuf ( maxav );
00392 
00393    maxav--;
00394 
00395 
00396    char* pch2 = charbuf.buf;
00397 
00398    int loop = 0;
00399 
00400    do {
00401      actpos2++;
00402      if ( loop )
00403         pch2++;
00404         
00405      loop++;
00406 
00407      readdata( pch2, 1 ); // endian ok !
00408 
00409    } while (*pch2 != 0   &&   actpos2 < maxav ); /* enddo */
00410 
00411    if ( actpos2 >= maxav ) {
00412       pch2[1] = 0;
00413       actpos2++;
00414 
00415       if ( pch2[0] ) {
00416          char temp;
00417          do {
00418             readdata( &temp, 1 ); // endian ok !
00419          } while ( temp ); /* enddo */
00420       }
00421    }
00422                       
00423    pch2 = new char [ actpos2 ];
00424 
00425    memcpy ( pch2, charbuf.buf, actpos2 );
00426 
00427    *pc = pch2;
00428 } 
00429 
00430 
00431 void         tnstream::readpnchar(char** pc, int maxlength )
00432 { 
00433    int actpos2 = 0; 
00434 
00435    int maxav = 10000;
00436                             
00437    if ( maxlength )
00438       if ( maxav > maxlength )
00439          maxav = maxlength;
00440 
00441 
00442    CharBuf charbuf ( maxav );
00443 
00444    maxav--;
00445 
00446 
00447    char* pch2 = charbuf.buf;
00448 
00449    int ende = 0;
00450 
00451    do {
00452      char bt;
00453 
00454      int red = readdata( &bt, 1, 0 );
00455 
00456      if ( red < 1 ) {
00457         ende = 2;
00458         *pch2 = 0;
00459      } else
00460        if ( bt == '\n' || bt == 0 ) {
00461           *pch2 = 0;
00462           ende = 1;
00463        } else
00464           if ( bt != '\r' ) {
00465             *pch2 = bt;
00466             pch2++;
00467             actpos2++;
00468           }
00469 
00470    } while ( !ende  && actpos2 < maxav ); /* enddo */
00471 
00472 
00473    if ( !ende ) {
00474       if ( actpos2 >= maxav ) {
00475          *pch2 = 0;
00476 
00477          if ( pch2[0] ) {
00478             char temp;
00479             do {
00480 
00481                int red = readdata( &temp, 1, 0 );
00482                if ( red < 1 )  {
00483                   temp = 0;
00484                }  else
00485                  if ( temp == '\n' )
00486                     temp = 0;
00487 
00488             } while ( temp ); /* enddo */
00489          }
00490       }
00491    }
00492    if ( ende == 2 ) {
00493       if ( !actpos2 )
00494          *pc = NULL;
00495       else
00496          *pc = strdup ( charbuf.buf );
00497    } else
00498       *pc = strdup ( charbuf.buf );
00499 }
00500 
00501 
00502 bool  tnstream::readTextString ( ASCString& s, bool includeCR  )
00503 {
00504   s = "";
00505   char c;
00506   int red;
00507   int end = 0;
00508   do {
00509      red = readdata( &c, 1, 0 ); // endian ok !
00510      if ( red < 1 ) {
00511         end = 2;
00512      } else
00513        if ( (c == '\n' && !includeCR) || c == 0 ) {
00514           end = 1;
00515        } else
00516           if ( c != '\r' )
00517              s += c;
00518   } while ( red && !end );
00519   if ( end == 2)
00520      return false;
00521   else
00522      return true;
00523 }
00524 
00525 
00526 ASCString  tnstream::readString ( bool includeCR )
00527 {
00528   ASCString s;
00529   bool data = readTextString ( s, includeCR );
00530   if ( !data && s.empty() )
00531      throw treadafterend ( getLocation() );
00532   return s;
00533 }
00534 
00535 
00536 void         tnstream::writeString(const string& pc, bool binary )
00537 {
00538    if ( binary )
00539       writepchar ( pc.c_str() );
00540    else
00541       writedata ( pc.data(), pc.length() );
00542 }
00543 
00544 
00545 void         tnstream::writepchar(const char* pc)
00546 { 
00547    if ( pc ) {
00548       const char *pch1 = pc;
00549       int loop = 0;
00550 
00551       do {
00552          if ( loop )
00553             pch1++;
00554          writedata( pch1, 1 );
00555          loop++;
00556       } while ( *pch1 > 0  ); /* enddo */
00557    } else {
00558        char         pch1 = 0;
00559        writedata ( &pch1, 1 );
00560    }
00561 
00562 } 
00563 
00565 
00566 
00567 
00568 
00569 MemoryStreamCopy :: MemoryStreamCopy ( pnstream stream )
00570 {
00571   buf = NULL;
00572   int bufused = 0;
00573   int memreserved = 0;
00574   int blocksize = 500000;
00575   int red;
00576   do {
00577     if ( bufused + blocksize > memreserved ) {
00578        int newsize = memreserved + blocksize;
00579        void* newbuf = malloc (newsize);
00580        if ( buf ) {
00581           memcpy ( newbuf, buf, bufused );
00582           free ( buf );
00583        }
00584        buf = newbuf;
00585        memreserved = newsize;
00586     }
00587     char* cp = (char*) buf;
00588     red = stream->readdata ( cp + bufused, blocksize, 0 ); // endian ok !
00589     bufused += red;
00590 
00591   } while ( red == blocksize );
00592   size = bufused;
00593   pos = 0;
00594 
00595   devicename = stream->getDeviceName();
00596 }
00597 
00598 ASCString MemoryStreamCopy::getLocation()
00599 {
00600   return devicename + " (memory bufferd)";
00601 }
00602 
00603 MemoryStreamCopy :: ~MemoryStreamCopy ( )
00604 {
00605    if ( buf )
00606       free ( buf );
00607 }
00608 
00609 
00610 void MemoryStreamCopy :: writedata ( const void* buf, int size )
00611 {
00612    throw  tinvalidmode ( getDeviceName(), reading, writing );
00613 }
00614 
00615 int MemoryStreamCopy :: readdata  ( void* buffer, int _size, bool excpt )
00616 {
00617    char* cp = (char*) buf;
00618    if ( pos + _size > size ) {
00619       if ( excpt )
00620           throw treadafterend ( getDeviceName() );
00621       else {
00622          int tr = size-pos;
00623          memcpy ( buffer, cp+pos, tr );
00624          pos += tr;
00625          return tr;
00626       }
00627 
00628    } else {
00629       memcpy ( buffer, cp+pos, _size );
00630       pos += _size;
00631       return _size;
00632    }
00633 }
00634 
00635 void MemoryStreamCopy :: seek ( int newpos )
00636 {
00637    if ( newpos > size || newpos < 0 )
00638      throw treadafterend ( getDeviceName() );
00639 
00640    pos = newpos;
00641 }
00642 
00643 
00645 
00646 #ifdef _SDL_
00647 
00648 static int stream_seek( struct SDL_RWops *context, int offset, int whence)
00649 {
00650         MemoryStreamCopy* stream = (MemoryStreamCopy*) context->hidden.unknown.data1;
00651         if ( whence == SEEK_SET )
00652            stream->seek ( offset );
00653         else
00654         if ( whence == SEEK_CUR )
00655               stream->seek ( offset + stream->getPosition() );
00656            else
00657          if ( whence == SEEK_END )
00658             stream->seek ( offset + stream->getSize() );
00659   return stream->getPosition();
00660 }
00661 
00662 
00663 static int stream_read(SDL_RWops *context, void *ptr, int size, int maxnum)
00664 
00665 {
00666         MemoryStreamCopy* stream = (MemoryStreamCopy*) context->hidden.unknown.data1;
00667         size_t nread = stream->readdata ( ptr, size * maxnum, 0 );
00668 
00669         return(nread / size);
00670 }
00671 
00672 static int stream_close(SDL_RWops *context)
00673 {
00674         if ( context ) {
00675                 if ( context->hidden.unknown.data1 ) {
00676                         MemoryStreamCopy* stream = (MemoryStreamCopy*) context->hidden.unknown.data1;
00677                         delete stream;
00678                 }
00679                 SDL_FreeRW(context);
00680         }
00681         return(0);
00682 }
00683 
00684 
00685 SDL_RWops *SDL_RWFromStream( pnstream stream )
00686 {
00687    MemoryStreamCopy* msb = new MemoryStreamCopy ( stream );
00688 
00689         SDL_RWops *rwops;
00690 
00691         rwops = SDL_AllocRW();
00692         if ( rwops != NULL ) {
00693            rwops->seek = stream_seek;
00694            rwops->read = stream_read;
00695            rwops->write = NULL;
00696            rwops->close = stream_close;
00697            rwops->hidden.unknown.data1 = msb;
00698         }
00699         return(rwops);
00700 }
00701 
00702 #endif
00703 
00704 
00705 
00706 
00707 
00708 tncontainerstream :: tncontainerstream ( const char* containerfilename, ContainerIndexer* indexer, int dirLevel )
00709         : tn_file_buf_stream ( containerfilename, reading ), index(NULL)
00710 {
00711    num = 0;
00712    char magic[4];
00713    readdata ( &magic, 4 ); // endian ok !
00714    if ( strncmp ( magic, containermagic, 4 ) == 0) {
00715       int pos = readInt();
00716       seek ( pos );
00717       num = readInt();
00718       index = new tcontainerindex[num];
00719       for ( int i = 0; i < num; i++ ) {
00720 
00721          bool __loadName = readInt();
00722          index[i].start = readInt();
00723          index[i].end = readInt();
00724          if ( __loadName ) {
00725             readpchar ( &index[i].name );
00726 
00727            #if CASE_SENSITIVE_FILE_NAMES == 1
00728             // quick hack to be able to use existing CON files.
00729             char *c = index[i].name;
00730             while ( *c ) {
00731                *c = tolower( *c );
00732                c++;
00733             }
00734            #endif
00735 
00736             indexer->addfile ( index[i].name, this, dirLevel );
00737          } else
00738             index[i].name = NULL;
00739       }
00740    }
00741    actfile = NULL;
00742    containerfilepos = 0;
00743 }
00744 
00745 
00746 int  tncontainerstream :: getcontainerfilesize ( const char* name )
00747 {
00748    int i = 0;
00749    while ( i < num  &&  stricmp ( index[i].name, name ) )
00750       i++;
00751 
00752    if ( i >= num )
00753       return -1;
00754    else
00755       return index[i].end - index[i].start + 1;
00756 
00757 }
00758 
00759 
00760 void tncontainerstream :: opencontainerfile ( const char* name )
00761 {
00762    if ( actfile ) {
00763       ASCString err = ASCString("two files simultaneously: ") + actfile->name + " and " + name;
00764       throw tfileerror (  err );
00765    }
00766 
00767    containerfilepos = 0;
00768    int i = 0;
00769    while ( i < num  && stricmp ( index[i].name, name ) )
00770       i++;
00771 
00772    if ( i >= num )
00773       throw tfileerror ( name );
00774 
00775    actfile = &index[i];
00776    containerfilepos = 0;
00777    seek ( actfile->start );
00778 }
00779 
00780 int tncontainerstream :: readcontainerdata ( void* buf, int size, bool excpt  )
00781 {
00782    if ( actfile->start + containerfilepos + size > actfile->end+1 ) {
00783       if ( excpt ) 
00784          throw treadafterend ( actfile->name );
00785       else {
00786          int got = readdata ( buf, (actfile->end+1 - actfile->start) - containerfilepos  , excpt );
00787          containerfilepos+=got;
00788          return got;
00789 
00790       }
00791    }
00792 
00793    readdata ( buf, size );
00794    containerfilepos+=size;
00795    return size;
00796 }
00797 
00798 void tncontainerstream :: closecontainerfile ( void )
00799 {
00800    actfile = NULL;
00801 }
00802 
00803 char* tncontainerstream :: getfirstname ( void )
00804 {
00805    actname = 0;
00806    return getnextname();
00807 }
00808 
00809 char* tncontainerstream :: getnextname ( void )
00810 {
00811    if ( actname < num )
00812       return index[actname++].name;
00813    else
00814       return NULL;
00815 
00816 }
00817 
00818 
00819 
00820 tncontainerstream  :: ~tncontainerstream  ()
00821 {
00822    for ( int i = 0; i < num; i++ ) 
00823       if ( index[i].name )
00824          delete[] index[i].name;
00825    delete[] index;
00826 }
00827 
00828 
00829 
00830 
00832 
00833 class ContainerCollector : public ContainerIndexer {
00834    public:
00835       struct FileIndex {
00836          ASCString name;
00837          pncontainerstream container;
00838          int directoryLevel;
00839       };
00840    protected:
00841 
00842       dynamic_array<FileIndex> index[256];    // not very efficient, but who cares :-)
00843 
00844       dynamic_array<pncontainerstream> container;
00845       int containernum;
00846       struct {
00847          int alpha;
00848          int index;
00849       } namesearch;       // next entry to return
00850    public:
00851       ContainerCollector ( void );
00852       void init ( const char* wildcard );
00853       void addfile ( const char* filename, const pncontainerstream stream, int directoryLevel );
00854            // pncontainerstream getfile ( const char* filename );
00855       FileIndex* getfile ( const ASCString& filename );
00856       FileIndex* getfirstname ( void );
00857       FileIndex* getnextname ( void );
00858       ASCString listContainer();
00859       virtual ~ContainerCollector();
00860 };
00861 
00862 
00863 ContainerCollector containercollector;
00864 
00865 char* constructFileName( char* buf, int directoryLevel, const char* path, const char* filename )
00866 {
00867   if ( buf ) {
00868 
00869      const char* filename2 = filename;
00870      buf[0] = 0;
00871 
00872      // filenames beginning with / or ~/ have an absolute path ; ignore variable path for them
00873      if ( ! (filename && (filename[0] == pathdelimitter || (filename[0]=='~' && filename[1] == pathdelimitter)) )) {
00874         if ( path )
00875            strcpy ( buf, path);
00876         else
00877            if ( directoryLevel >= 0 && ascDirectory[ directoryLevel ] )
00878               strcpy ( buf, ascDirectory[ directoryLevel ]);
00879      }
00880 
00881      appendbackslash ( buf );
00882 
00883      if ( filename && strchr ( filename, pathdelimitter )) {
00884      
00885         char name2[ maxFileStringSize ];
00886         // filename contains directories
00887         strcpy ( name2, filename );
00888         int i = strlen ( name2 )-1;
00889         while ( name2[i] != pathdelimitter )
00890            i--;
00891 
00892         name2[i+1] = 0;
00893 
00894         filename2 = &filename[i+1];
00895 
00896         // filename2 is now the pure filename without directory
00897         // name2 is the directory
00898         
00899         if ( buf[0] && name2[0]==pathdelimitter )
00900            strcpy ( buf, name2+1);
00901         else
00902            strcpy ( buf, name2);
00903      }
00904 
00905      if ( buf[0] == '~' && buf[1] == pathdelimitter ) {
00906         char* home = getenv ( "HOME" );
00907         if ( home ) {
00908            char temp[ maxFileStringSize ];
00909            strcpy ( temp, buf );
00910            strcpy ( buf, home );
00911            appendbackslash ( buf );
00912            strcat ( buf, &temp[2]);
00913         }
00914      }
00915 
00916 
00917      appendbackslash ( buf );
00918 
00919      if ( filename2 )
00920         strcat ( buf, filename2 );
00921   }
00922 
00923   return buf;
00924 }
00925 
00926 bool isPathRelative( const ASCString& path )
00927 {
00928   if ( path.length() < 2 )
00929      return true;
00930      
00931   if ( path[0] == '~' && path[1] == pathdelimitter )
00932      return false;
00933 
00934 #ifdef WIN32
00935   if ( path[1] == ':' && path[2] == pathdelimitter )
00936      return false;
00937 
00938 #endif
00939      
00940   if ( path[0] == pathdelimitter )
00941      return false;
00942 
00943   return true;     
00944 }
00945 
00946 ASCString constructFileName( int directoryLevel, const ASCString& path, ASCString filename )
00947 {
00948      ASCString result;
00949    
00950      // filenames beginning with / or ~/ have an absolute path ; ignore variable path for them
00951      if ( isPathRelative( filename )) {
00952         if ( !path.empty() )
00953            result += path;
00954         else
00955            if ( directoryLevel >= 0 && ascDirectory[ directoryLevel ] )
00956               result += ascDirectory[ directoryLevel ];
00957      }
00958 
00959      appendbackslash ( result );
00960 
00961      if ( !filename.empty() && filename.find( pathdelimitter )!= ASCString::npos ) {
00962         ASCString dir = filename;
00963         
00964         dir.erase( dir.rfind( pathdelimitter ) + 1);
00965 
00966         filename.erase( 0, filename.find( pathdelimitter ) + 1 );
00967         
00968         if ( dir.find( pathdelimitter ) == 0 )
00969            dir.erase( 0, 1 );
00970            
00971         result = dir;   
00972      }
00973 
00974      if ( result.length() > 2 && result[0] == '~' && result[1] == pathdelimitter ) {
00975         char* home = getenv ( "HOME" );
00976         if ( home ) {
00977            ASCString temp = result;
00978            result = home;
00979            appendbackslash ( result );
00980            result += temp.substr( 2 );
00981         }
00982      }
00983 
00984 
00985      appendbackslash ( result );
00986 
00987      result += filename;
00988 
00989      return result;
00990 }
00991 
00992 
00993 
00994 struct FileLocation {
00995         int directoryLevel;
00996         pncontainerstream container;
00997         int found;
00998      };
00999 
01000 void locateFile ( const ASCString& filename, FileLocation* loc )
01001 {
01002    loc->found = 0;
01003    ContainerCollector::FileIndex* idx = containercollector.getfile ( filename );
01004    int maxnum;
01005    if ( idx ) {
01006       maxnum = idx->directoryLevel+1;
01007       loc->directoryLevel = idx->directoryLevel;
01008       loc->found = 1;
01009       loc->container = idx->container;
01010    } else {
01011       maxnum = searchDirNum;
01012       loc->container = NULL;
01013       loc->directoryLevel = -1;
01014    }
01015 
01016    if ( maxnum ) {
01017       int localfound = 0;
01018       for ( int i = 0; i < maxnum && !localfound; i++ ) {
01019          char buf[2000];
01020          FILE* fp = fopen ( constructFileName ( buf, i, NULL, filename.c_str()), "r" );
01021          if ( fp ) {
01022             localfound = loc->found = 1;
01023             fclose ( fp );
01024             loc->container = NULL;
01025             loc->directoryLevel = i;
01026          }
01027       }
01028    } else {
01029       char buf[2000];
01030       FILE* fp = fopen ( constructFileName ( buf, -1, ".", filename.c_str()), "r" );
01031       if ( fp ) {
01032          loc->found = 1;
01033          fclose ( fp );
01034          loc->container = NULL;
01035          loc->directoryLevel = -2;
01036       }
01037    }
01038 }
01039 
01041 
01042 
01043 
01044 ASCString listContainer()
01045 {
01046    return containercollector.listContainer();
01047 }
01048 
01049 
01050 ContainerCollector :: ContainerCollector ( void )
01051 {
01052   containernum = 0;
01053 }
01054 
01055 void ContainerCollector :: init ( const char* wildcard )
01056 {
01057    for ( int i = 0; i < searchDirNum; i++ ) {
01058       DIR *dirp; 
01059       struct ASC_direct *direntp;
01060 
01061       char buf[ maxFileStringSize ];
01062       char buf2[ maxFileStringSize ];
01063       char buf3 [ maxFileStringSize ];
01064       dirp = opendir( extractPath ( buf2, constructFileName ( buf, i, NULL, wildcard )));
01065       extractFileName ( buf3, buf );
01066       if( dirp != NULL ) { 
01067          for(;;) { 
01068             direntp = readdir( dirp ); 
01069             if ( direntp == NULL ) {
01070                break; 
01071             }
01072             if ( patimat ( buf3, direntp->d_name )) {
01073                container[containernum++] = new tncontainerstream( constructFileName ( buf, i, buf2, direntp->d_name), this, i);
01074                if ( MessagingHub::Instance().getVerbosity() >= 2 )
01075                   printf("container %s mounted\n", buf );
01076             }
01077          } 
01078          closedir( dirp ); 
01079       } 
01080    }
01081 }
01082 
01083 void ContainerCollector :: addfile ( const char* filename, const pncontainerstream stream, int directoryLevel )
01084 {
01085    int found = 0;
01086    FileIndex* cci = NULL;
01087 
01088    int i1 = toupper ( filename[0] );
01089    for ( int i = 0; i <= index[i1].getlength(); i++ )
01090       if ( index[i1][i].name.compare_ci ( filename ) == 0 )  {
01091          if ( index[i1][i].directoryLevel <= directoryLevel ) 
01092             return;
01093          else {
01094             cci = &(index[i1][i]);
01095             found = 1;
01096          }
01097       }
01098 
01099    if ( !found )
01100       cci = &( index[i1][ index[i1].getlength()+1 ] );
01101 
01102    cci->name = filename;
01103    cci->container = stream;
01104    cci->directoryLevel = directoryLevel;
01105 }
01106 
01107 ContainerCollector::FileIndex* ContainerCollector :: getfile ( const ASCString& filename )
01108 {
01109    int i1 = toupper ( filename[0] );
01110    for ( int i = 0; i <= index[i1].getlength(); i++ )
01111       if ( index[i1][i].name.compare_ci ( filename) == 0 )
01112          return &index[i1][i];
01113 
01114    return NULL;
01115 }
01116 
01117 
01118 ContainerCollector::FileIndex* ContainerCollector :: getfirstname ( void )
01119 {
01120    namesearch.alpha = 0;
01121    namesearch.index = 0;
01122    return getnextname();
01123 }
01124 
01125 ContainerCollector::FileIndex* ContainerCollector :: getnextname ( void )
01126 {
01127    while ( index[namesearch.alpha].getlength() < namesearch.index) {
01128       if ( namesearch.alpha == 255 )
01129          return NULL;
01130       namesearch.alpha++;
01131       namesearch.index = 0;
01132    } /* endwhile */
01133    return &index[namesearch.alpha][namesearch.index++];
01134 }
01135 
01136 ASCString ContainerCollector :: listContainer()
01137 {
01138    ASCString s;
01139    for ( int i = 0; i < containernum; i++ )
01140       s += container[i]->getLocation() + "\n";
01141 
01142    return s;
01143    
01144 }
01145 
01146 
01147 
01148 ContainerCollector :: ~ContainerCollector()
01149 {
01150   int i;
01151    for (i = 0; i < containernum; i++ )
01152       delete container[i];
01153    containernum = 0;
01154 }
01155 
01156 
01157 
01159 
01160 
01161 
01162 libbzip_compression :: libbzip_compression ( p_compressor_stream_interface strm  )
01163 {
01164    bzs.bzalloc = NULL;
01165    bzs.bzfree = NULL;
01166    bzs.opaque = NULL;
01167 
01168    BZ2_bzCompressInit ( &bzs, 5, 0, 0 );
01169 
01170    outputbufsize = 100000;
01171    outputbuf = new char [ outputbufsize ];
01172 
01173    stream = strm;
01174 }
01175 
01176 
01177 void libbzip_compression :: writedata ( const void* buf, int size )
01178 {
01179    char* cbuf = (char*) buf;
01180 
01181    bzs.next_in = cbuf ;
01182    bzs.avail_in = size ;
01183    bzs.total_in_lo32 = 0 ;
01184    bzs.total_in_hi32 = 0 ;
01185 
01186    while ( bzs.total_in_lo32 < size ) {
01187 
01188      bzs.next_out = outputbuf;
01189      bzs.avail_out = outputbufsize;
01190      bzs.total_out_lo32 = 0;
01191      bzs.total_out_hi32 = 0;
01192 
01193      int res = BZ2_bzCompress ( &bzs, BZ_RUN );
01194      if ( res < 0 )
01195         throw tcompressionerror ( "MBZLB2 compression :: writedata", res );
01196 
01197      for ( int i = 0; i < bzs.total_out_lo32; i++ )
01198         outputbuf[i] ^= bzip_xor_byte;
01199 
01200      stream->writecmpdata ( outputbuf, bzs.total_out_lo32 );
01201    }
01202 }
01203 
01204 
01205 void libbzip_compression :: close_compression ( void )
01206 {
01207    int res;
01208    do {
01209      bzs.next_in = outputbuf;
01210      bzs.avail_in = 0;
01211 
01212      bzs.next_out = outputbuf;
01213      bzs.avail_out = outputbufsize;
01214      bzs.total_out_lo32 = 0;
01215      bzs.total_out_hi32 = 0;
01216 
01217      res = BZ2_bzCompress ( &bzs, BZ_FINISH );
01218      if ( res < 0 )
01219         throw tcompressionerror ( "MBZLB2 compression :: closecompression", res );
01220 
01221      for ( int i = 0; i < bzs.total_out_lo32; i++ )
01222         outputbuf[i] ^= bzip_xor_byte;
01223      stream->writecmpdata ( outputbuf, bzs.total_out_lo32 );
01224 
01225    } while ( res != BZ_STREAM_END );
01226 
01227 
01228    BZ2_bzCompressEnd ( &bzs );
01229 }
01230 
01231 libbzip_compression :: ~libbzip_compression ( )
01232 {
01233    if ( outputbuf ) {
01234       delete[] outputbuf;
01235       outputbuf = NULL;
01236    }
01237 }
01238 
01239 
01240 
01241 
01242 libbzip_decompression :: libbzip_decompression ( p_compressor_stream_interface strm  )
01243 {
01244    bzs.bzalloc = NULL;
01245    bzs.bzfree = NULL;
01246    bzs.opaque = NULL;
01247 
01248    BZ2_bzDecompressInit ( &bzs, 0, 0 );
01249 
01250    inputbufsize = 100000;
01251    inputbuf = new char [ inputbufsize ];
01252    inputbufused = 0;
01253    inputbufread = 0;
01254 
01255    stream = strm;
01256 }
01257 
01258 
01259 int libbzip_decompression :: readdata ( void* buf, int size, bool excpt )
01260 {
01261    int decompressed = 0;
01262    char* cbuf = (char*) buf;
01263 
01264    bzs.next_in = cbuf ;
01265    bzs.avail_in = size ;
01266    bzs.total_in_lo32 = 0 ;
01267    bzs.total_in_hi32 = 0 ;
01268 
01269    int abrt = 0;
01270 
01271    while ( decompressed < size  && !abrt ) {
01272      if ( inputbufread >= inputbufused ) {
01273         inputbufused = stream->readcmpdata ( inputbuf, inputbufsize, 0 );
01274 
01275         if ( !inputbufused && excpt )
01276            throw tcompressionerror ( "Decompressor :: out of data", 0 );
01277 
01278 
01279         for ( int i = 0; i < inputbufused; i++ )
01280            inputbuf[i] ^= bzip_xor_byte;
01281 
01282         inputbufread = 0;
01283      }
01284      bzs.next_in = inputbuf + inputbufread;
01285      bzs.avail_in = inputbufused - inputbufread;
01286      bzs.total_in_lo32 = 0;
01287      bzs.total_in_hi32 = 0;
01288 
01289      bzs.next_out = cbuf + decompressed;
01290      bzs.avail_out = size - decompressed;
01291      bzs.total_out_lo32 = 0;
01292      bzs.total_out_hi32 = 0;
01293 
01294      int res = BZ2_bzDecompress ( &bzs );
01295      decompressed += bzs.total_out_lo32;
01296      inputbufread += bzs.total_in_lo32;
01297 
01298      if ( decompressed < size  ) {
01299         if ( res == BZ_STREAM_END ) {
01300            if ( excpt )
01301               throw treadafterend ( "BZ_decompress_stream" );
01302            abrt = 1;
01303         } else {
01304            if ( res != BZ_OK ) {
01305               if ( excpt ) {
01306                  if ( res == BZ_MEM_ERROR )
01307                     throw toutofmem ( -1 );
01308                  else
01309                     throw tcompressionerror ( "MBZLB2 decompression :: readdata", res );
01310               }
01311               abrt = 1;
01312            }
01313         }
01314      }
01315    }
01316    return decompressed;
01317 }
01318 
01319 
01320 libbzip_decompression :: ~libbzip_decompression ( )
01321 {
01322    if ( inputbuf ) {
01323       BZ2_bzDecompressEnd ( &bzs );
01324       delete[] inputbuf;
01325       inputbuf = NULL;
01326    }
01327 }
01328 
01329 
01330 
01332 
01333 /*
01334 t_compressor_2ndbuf_filter :: t_compressor_2ndbuf_filter ( t_compressor_stream_interface* strm )
01335 {
01336    stream = strm;
01337 }
01338 
01339 void t_compressor_2ndbuf_filter :: writecmpdata ( const void* buf, int size )
01340 {
01341    stream->writecmpdata ( buf, size );
01342 }
01343 
01344 int t_compressor_2ndbuf_filter :: readcmpdata ( void* buf, int size, bool excpt )
01345 {
01346    int got = 0;
01347 
01348    char* pc = (char*) buf;
01349 
01350    while ( size && _queue.size() ) {
01351        *pc = _queue.front();
01352        _queue.pop();
01353        pc++;
01354        size--;
01355        got++;
01356    }
01357 
01358    if ( size )
01359       got += stream->readcmpdata ( pc, size, excpt );
01360 
01361    return got;
01362 }
01363 
01364 void t_compressor_2ndbuf_filter :: insert_data_into_queue ( const void* buf, int size )
01365 {
01366    char* pc = (char*) buf;
01367    for (int i = 0; i < size; i++) {
01368       _queue.push ( *pc );
01369       pc++;
01370    }
01371 }
01372 */
01373 
01374 
01375 
01376 tanycompression :: tanycompression ( int md )
01377 {
01378    mmd = md;
01379    bzip_compress = NULL;
01380    bzip_decompress = NULL;
01381 }
01382 
01383 void tanycompression :: init ( void )
01384 {
01385    if ( mmd == 1 ) {
01386       char buf[10];
01387 
01388       int maxlen = strlen ( BZIP_SIGNATURE ) + 1;
01389       int bufdatanum = readcmpdata ( buf, maxlen, 0 );
01390       int siglen = 0;
01391 
01392       if ( bufdatanum  == maxlen ) {
01393 
01394          if ( strncmp ( &buf[1], LZ_SIGNATURE, 9 ) == 0  && !buf[0]) {
01395             status = 110;
01396             siglen = 0;
01397          } else
01398          if ( strncmp ( &buf[1], RLE_SIGNATURE, 9 ) == 0 && !buf[0]) {
01399             status = 111;
01400             siglen = 0;
01401          } else
01402          if ( strncmp ( buf, BZIP_SIGNATURE, 9 ) == 0 ) {
01403             status = 112;
01404             siglen = strlen ( BZIP_SIGNATURE ) + 1;
01405             bzip_decompress = new libbzip_decompression ( this );
01406          } else
01407             status= 109;
01408 
01409       } else
01410          status = 109;
01411 
01412       for ( int i = siglen; i < bufdatanum; i++ )
01413           _queue.push ( buf[i] );
01414 
01415 
01416    } else {
01417        status = 201;
01418        bzip_compress = new libbzip_compression ( this );
01419        writecmpdata ( BZIP_SIGNATURE, strlen ( BZIP_SIGNATURE ) + 1 );
01420    }
01421 }
01422 
01423 
01424 int  tanycompression :: readdata ( void* rbuf, int size, bool excpt )
01425 {
01426    int red = 0;
01427    if ( size ) {
01428       switch ( status ) {
01429       case 109: red += readlzwdata ( rbuf, size, excpt );
01430          break;
01431       case 110:
01432       case 111: red += tlzwstreamcompression :: readdata ( rbuf, size, excpt );
01433          break;
01434       case 112: red += bzip_decompress -> readdata ( rbuf, size, excpt );
01435          break;
01436       } /* endswitch */
01437    }
01438    return red;   
01439 }                          
01440 
01441 
01442 
01443 void tanycompression :: writedata ( const void* buf, int size )
01444 {
01445   bzip_compress -> writedata ( buf, size );
01446   // writecmpdata ( buf, size );
01447 }
01448 
01449 
01450 int tanycompression :: readlzwdata ( void* buf, int size, bool excpt )
01451 {
01452    if ( _queue.size() ) {
01453       int got = 0;
01454 
01455       char* pc = (char*) buf;
01456 
01457       while ( size && _queue.size() ) {
01458           *pc = _queue.front();
01459           _queue.pop();
01460           pc++;
01461           size--;
01462           got++;
01463       } /* endwhile */
01464 
01465       if ( size )
01466          got += readcmpdata ( pc, size, excpt );
01467 
01468       return got;
01469    } else
01470       return readcmpdata ( buf, size, excpt );
01471 }
01472 
01473 void tanycompression :: writelzwdata ( const void* buf, int size )
01474 {
01475    writecmpdata ( buf, size );
01476 }
01477 
01478 
01479 void tanycompression :: close_compression ( void )
01480 {
01481    if ( bzip_compress ) {
01482       bzip_compress->close_compression ( );
01483       delete bzip_compress;
01484       bzip_compress = NULL;
01485    }
01486 }
01487 
01488 
01489 tanycompression :: ~tanycompression ( )
01490 {
01491    if ( bzip_decompress ) {
01492       delete bzip_decompress;
01493       bzip_decompress = NULL;
01494    }
01495 
01496 }
01497 
01498 
01500 
01501 /*
01502 void tn_lzw_bufstream :: writedata ( const void* buf, int size )
01503 {
01504    tlzwstreamcompression :: writedata ( buf, size );
01505 }
01506 
01507 int tn_lzw_bufstream :: readdata  ( void* buf, int size, bool excpt  )
01508 {
01509    return tlzwstreamcompression :: readdata ( buf, size, excpt );
01510 }
01511 
01512 int  tn_lzw_bufstream :: readlzwdata ( void* buf, int size, bool excpt  )
01513 {
01514    return tnbufstream :: readdata ( buf, size, excpt );
01515 }
01516 
01517 void tn_lzw_bufstream :: writelzwdata ( const void* buf, int size )
01518 {
01519    tnbufstream :: writedata ( buf, size );
01520 }
01521 
01522 tn_lzw_bufstream :: ~tn_lzw_bufstream ()
01523 {
01524    tlzwstreamcompression :: close();
01525    tnbufstream :: close();
01526 }
01527 
01528 */
01529 
01531 
01532 void tn_lzw_file_buf_stream :: writedata ( const void* buf, int size )
01533 {
01534    tanycompression :: writedata ( buf, size );
01535 }
01536 
01537 int  tn_lzw_file_buf_stream :: readdata  ( void* buf, int size, bool excpt  )
01538 {
01539    return tanycompression :: readdata ( buf, size, excpt );
01540 }
01541 
01542 int  tn_lzw_file_buf_stream:: readcmpdata ( void* buf, int size, bool excpt  )
01543 {
01544    return tn_file_buf_stream :: readdata ( buf, size, excpt  );
01545 }
01546 
01547 void tn_lzw_file_buf_stream :: writecmpdata ( const void* buf, int size )
01548 {
01549    tn_file_buf_stream :: writedata ( buf, size );
01550 }
01551 
01552 tn_lzw_file_buf_stream :: ~tn_lzw_file_buf_stream()
01553 {
01554    close_compression ();
01555    tn_file_buf_stream :: close();
01556 }
01557 
01558 
01560 
01561 
01562 tn_c_lzw_filestream :: tn_c_lzw_filestream ( const ASCString& name, IOMode mode ) : tanycompression ( mode )
01563 {
01564    #ifdef logfiles
01565     FILE* fp = fopen ( "files.lst", "at" );
01566     fprintf ( fp, "%s\n", name );
01567     fclose ( fp );
01568    #endif
01569 
01570    strm = NULL;
01571    inp = 0;
01572    containerstream = NULL;
01573 
01574    FileLocation fl;
01575    if ( mode == tnstream::reading ) {
01576       locateFile ( name, &fl );
01577 
01578       if ( !fl.found )
01579          throw tfileerror ( name );
01580 
01581    } else {
01582       fl.directoryLevel = 0;
01583       fl.container = NULL;
01584    }
01585 
01586 
01587    if ( fl.container == NULL ) {
01588       char string[2000];
01589 
01590       ASCString fileNameComplete = constructFileName ( string, fl.directoryLevel, NULL, name.c_str());
01591       strm = new tn_file_buf_stream ( fileNameComplete, mode );
01592       inp = 1;
01593       devicename = fileNameComplete;
01594       location = fileNameComplete;
01595 
01596    } else {
01597       containerstream = fl.container;
01598       if ( containerstream ) {
01599          containerstream->opencontainerfile ( name.c_str() );
01600          devicename = name;
01601          location = name + " located inside " + containerstream->getDeviceName();
01602          inp = 2;
01603       } else
01604          throw tfileerror ( name );
01605    }
01606    fname = name;
01607 
01608    tanycompression :: init (  );
01609 }
01610 
01611 ASCString tn_c_lzw_filestream::getLocation()
01612 {
01613    return location;
01614 }
01615 
01616 int tn_c_lzw_filestream :: getSize ( void )
01617 {
01618    if ( inp == 2 )
01619       return containerstream->getSize();
01620    else
01621       return strm->getSize();
01622 }
01623 
01624 void tn_c_lzw_filestream :: writecmpdata ( const void* buf, int size )
01625 {
01626    if ( inp == 2 )
01627       throw tinvalidmode ( fname, tnstream::reading, tnstream::writing );
01628    else
01629       strm->writedata ( buf, size );
01630 }
01631 
01632 int tn_c_lzw_filestream :: readcmpdata  ( void* buf, int size, bool excpt  )
01633 {
01634    if ( inp == 2 )
01635       return containerstream->readcontainerdata ( buf, size, excpt );
01636    else
01637       return strm->readdata ( buf, size, excpt  );
01638 };
01639 
01640 
01641 void tn_c_lzw_filestream :: writedata ( const void* buf, int size )
01642 {
01643    tanycompression :: writedata ( buf, size );
01644 }
01645 
01646 int tn_c_lzw_filestream :: readdata  ( void* buf, int size, bool excpt  )
01647 {
01648    if ( tanycompression :: mode == readingdirect  && !tempbuf.size() )
01649       if ( inp == 2 )
01650          return containerstream->readcontainerdata ( buf, size, excpt  );
01651       else
01652          return strm->readdata ( buf, size, excpt  );
01653    else
01654       return tanycompression :: readdata ( buf, size, excpt );
01655 };
01656 
01657 
01658 time_t tn_c_lzw_filestream :: get_time ( void )
01659 {
01660    if ( inp == 2 )
01661       return containerstream->get_time();
01662    else
01663       return strm->get_time();
01664 }
01665 
01666 tn_c_lzw_filestream :: ~tn_c_lzw_filestream()
01667 {
01668    close_compression ();
01669    close();
01670    if ( inp == 1 ) {
01671       delete strm;
01672       strm = NULL;
01673    } else
01674       containerstream->closecontainerfile();
01675 }
01676 
01677 
01678 
01680 
01681 
01682 
01683 int    compressrle ( const void* p, void* q)
01684 {
01685    trleheader* sourcehead = (trleheader*) p;
01686    if ( sourcehead->id == 16973 ) {
01687       memcpy ( q, p, sourcehead->size + sizeof ( trleheader ) );
01688       return sourcehead->size + sizeof ( trleheader );
01689    }
01690 
01691 
01692    char* s = (char*) p;
01693    char* d = (char*) q;
01694 
01695    trleheader* header = (trleheader*) q;
01696 
01697    Uint16 x,y;
01698    int size;
01699    {
01700       Uint16* pw = (Uint16*) s;
01701       x = pw[0];
01702       y = pw[1];
01703 
01704       header->x = x;
01705       header->y = y;
01706 
01707       x++;
01708       y++;
01709 
01710       size = x * y;
01711 
01712       header->id = 16973;
01713    }
01714 
01715    {
01716       int bts[256];
01717       memset ( bts, 0, sizeof ( bts ));
01718       for ( int i = 0; i < size ;i++ )
01719          bts[int(s[i+4])]++;
01720 
01721       int min = 70000;
01722       for ( int i = 0; i < 256; i++ )
01723          if ( bts[i] < min ) {
01724             min = bts[i];
01725             header->rle = i;
01726          }
01727 
01728    }
01729 
01730    s+=4;
01731    d+=sizeof ( trleheader );
01732 
01733    {
01734       char* startpos = d;
01735       int xp;
01736 
01737       for (int j = 0; j < y ; j++ ) {
01738          xp = 0;
01739          unsigned char num;
01740          unsigned char actbyte ;
01741 
01742          do {
01743             num = 1;
01744             actbyte = *s;
01745    
01746             while ( xp+num < x   &&   num < 255 && s[num] == actbyte ) 
01747                num++;
01748    
01749             if ( num > 2  ||  actbyte == header->rle ) {
01750                *(d++) = header->rle;
01751                *(d++) = num;
01752                *(d++) = actbyte;
01753             } else {
01754                *(d++) = actbyte;
01755                if ( num > 1 )
01756                   *(d++) = actbyte;
01757             }
01758 
01759             s  += num;   
01760             xp += num;
01761          } while ( xp < x );
01762 
01763 
01764       } /* endfor */
01765 
01766       header->size = d - startpos;
01767    }
01768    return header->size + sizeof ( trleheader );
01769 }
01770 
01772 
01773 
01774 
01775 
01776 bool patimat (const char *pat, const char *str, bool forceCaseInsensitivity )
01777 {
01778    switch (*pat)
01779    {
01780       case '\0':
01781          return !*str;
01782 
01783       case '*' :
01784          return patimat(pat+1, str, forceCaseInsensitivity) || (*str && patimat(pat, str+1, forceCaseInsensitivity));
01785 
01786       case '?' :
01787          return *str && patimat(pat+1, str+1, forceCaseInsensitivity);
01788 
01789       default  :
01790          if ( forceCaseInsensitivity ||
01791 #if CASE_SENSITIVE_FILE_NAMES == 0
01792               true
01793 #else
01794               false
01795 #endif
01796            )
01797             return (toupper(*pat) == toupper(*str)) && patimat(pat+1, str+1, forceCaseInsensitivity);
01798          else
01799             return (*pat == *str) && patimat(pat+1, str+1, forceCaseInsensitivity );
01800       }
01801 }
01802 
01803 bool patimat (const ASCString& pat, const ASCString& str, bool forceCaseInsensitivity)
01804 {
01805    return patimat( pat.c_str(), str.c_str(), forceCaseInsensitivity );
01806 }
01807 
01808 
01809 tfindfile :: tfindfile ( ASCString name, SearchPosition searchPosition, SearchTypes searchTypes )
01810 {
01811    convertPathDelimitters ( name );
01812 
01813    if ( searchPosition == DefaultDir )
01814       searchPosition = AllDirs;
01815 
01816    
01817    if ( searchDirNum == 0 )
01818       searchPosition = CurrentDir;
01819    
01820    found = 0;
01821    act = 0;
01822    if ( name.empty() )
01823       return;
01824 
01825    ASCString directory[maxSearchDirNum];
01826    int dirNum;
01827    ASCString wildcard;
01828 
01829    int ppos = name.rfind ( pathdelimitterstring );
01830    if ( ppos != name.npos ) {
01831       // name contains a directory entry
01832 
01833 
01834       // checking if absolute or relative path
01835       bool absolute = false;
01836       if ( name[0] == pathdelimitter )
01837          absolute = true;
01838 
01839       if ( has_drive_letters && name.length() > 3 && name.find ( ":\\", 1 ) != name.npos )
01840          absolute = true;
01841 
01842       if ( absolute || searchPosition == CurrentDir ) {
01843          directory[0].assign ( name, 0, ppos );
01844          dirNum = 1;
01845       } else {
01846          ASCString strippedPath;
01847          strippedPath.assign ( name, 0, ppos );
01848          if ( name.find ( ASCString(".") + pathdelimitterstring ) == 0 )
01849             strippedPath.erase( 0, 2);
01850 
01851          int upDir = 0;
01852          while ( name.find ( ASCString("..") + pathdelimitterstring ) == 0 ) {
01853             upDir++;
01854             strippedPath.erase ( 0, 3 );
01855          }
01856 
01857          int dirsToProcess;
01858          if ( searchPosition == AllDirs ) {
01859             dirsToProcess = searchDirNum;
01860          } else
01861             dirsToProcess = 1;
01862 
01863          dirNum = 0;
01864          for ( int i = 0; i < dirsToProcess; i++ ) {
01865             ASCString dir = ascDirectory[i];
01866 
01867             // removing the trailing pathdelimitterstring
01868             dir.erase ( dir.length() -1 );
01869 
01870             for ( int j = 0; j < upDir; j++ ) {
01871                int pos = dir.rfind ( pathdelimitterstring );
01872                if ( pos > 0 && pos == dir.npos )
01873                   dir.erase ( pos );
01874             }
01875 
01876             // append the trailing pathdelimitterstring again
01877             dir += pathdelimitterstring;
01878 
01879             directory[dirNum++] = dir + strippedPath;
01880          }
01881 
01882          if ( !dirNum  ) {
01883             directory[0] = ".";
01884             dirNum = 1;
01885          }
01886 
01887       }
01888 
01889       wildcard.assign ( name, ppos+1, name.npos );
01890 
01891    } else {
01892       if ( searchDirNum ) {
01893          for (int i = 0; i < searchDirNum; i++ )
01894             directory[i] = ascDirectory[i];
01895          dirNum = searchDirNum;
01896       } else {
01897          directory[0] = ".";
01898          dirNum = 1;
01899       }
01900       wildcard = name;
01901    }
01902 
01903    if ( searchTypes == All || searchTypes == OutsideContainer )
01904       for ( int i = 0; i < dirNum; i++ ) {
01905          DIR *dirp;
01906          struct ASC_direct *direntp;
01907 
01908          dirp = opendir( directory[i].c_str() );
01909          if( dirp != NULL ) {
01910            for(;;)