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-2010  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 <bzlib.h>
00042 
00043 #include "global.h"
00044 #include "basestrm.h"
00045 
00046 #ifdef _DOS_
00047   #include "dos/fileio.h"
00048 #else
00049  #ifdef _WIN32_
00050    #include "win32/fileio.h"
00051  #else
00052   #ifdef _UNIX_
00053     #include "unix/fileio.h"
00054   #endif
00055  #endif
00056 #endif
00057 
00058 //#include sdlheader
00059 #include <SDL_endian.h>
00060 
00061 
00062 #include "util/messaginghub.h"
00063 
00064 
00065  const int maxSearchDirNum = 30;
00066  int searchDirNum = 0;
00067  char* ascDirectory[maxSearchDirNum] = { NULL, NULL, NULL, NULL, NULL,
00068                                          NULL, NULL, NULL, NULL, NULL };
00069 
00070 
00071 
00072 
00073 #pragma pack(1)
00074 struct trleheader {
00075    unsigned short int id;
00076    unsigned short int size;
00077    char rle;
00078    unsigned short int x;
00079    unsigned short int y;
00080 };
00081 
00082 #pragma pack()
00083 
00084 #define bzip_xor_byte 'M'
00085 
00086 const char* containermagic = "NCBM";
00087 
00088 const char* LZ_SIGNATURE  =  "MBLZW16";
00089 const char* RLE_SIGNATURE =  "MBRLE1";
00090 const char* BZIP_SIGNATURE = "MBZLB2X!";
00091 
00092 
00093 
00094 
00095 
00099 
00100 CharBuf :: CharBuf ( void )
00101          {
00102             size = 0;
00103             buf = NULL;
00104          }
00105 
00106 CharBuf :: CharBuf ( int _size )
00107 
00108          {
00109             size = _size;
00110             buf = new char[ size ];
00111          }
00112 
00113 void CharBuf :: resize ( int newsize )
00114          {
00115             char* nb = new char[newsize];
00116             for ( int i = 0; i < size; i++ )
00117                nb[i] = buf[i];
00118 
00119             delete[] buf;
00120             buf = nb;
00121          }
00122 
00123 CharBuf :: ~CharBuf()
00124          {
00125             if ( buf )
00126                delete[] buf;
00127             buf = NULL;
00128          }
00129 
00133 
00134 
00135 
00136 OutOfMemoryError::OutOfMemoryError ( int m )
00137 {
00138   required = m; 
00139 }
00140 
00141 tfileerror::tfileerror ( const ASCString& fileName )
00142 {
00143    _filename = fileName ;
00144 }
00145 
00146 
00147 tinvalidmode :: tinvalidmode ( const ASCString& _fileName, tnstream::IOMode org_mode, tnstream::IOMode requested_mode )
00148               : tfileerror ( _fileName )
00149 {
00150    orgmode = org_mode;
00151    requestmode = requested_mode;
00152 }
00153 
00154 
00155 
00156 treadafterend :: treadafterend ( const ASCString& _fileName )
00157                : tfileerror ( _fileName )
00158 {
00159 
00160 }
00161 
00162 
00163 tinternalerror::tinternalerror (  const char* filename, int l )
00164 {
00165    linenum = l;
00166    sourcefilename = filename;
00167 }
00168 
00169 
00170 
00171 tinvalidversion :: tinvalidversion ( const ASCString& _fileName, int ex, int fnd )
00172                  : tfileerror ( _fileName ), expected ( ex ), found ( fnd )
00173 {
00174 }
00175 
00176 ASCString tinvalidversion :: getMessage() const
00177 {
00178    ASCString s;
00179    if ( expected < found )
00180       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 );
00181    else
00182       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 );
00183 
00184    return s;
00185 }
00186 
00187 
00188 
00192 
00193 
00194 tnstream :: tnstream ( void ) 
00195           : devicename ( "-abstract tnstream-" ) {}
00196 
00197 void tnstream::seek ( int pos )
00198 {
00199    throw tfileerror ( "Seeking not supported for stream " + getDeviceName() );
00200 }
00201 
00202 void         tnstream::readrlepict( void** pnter, bool allocated, int* size)
00203 { 
00204   trleheader   hd; 
00205   int          w;
00206   char*        q;
00207 
00208   hd.id = readWord();
00209   hd.size = readWord();
00210   hd.rle = readChar();
00211   hd.x = readWord();
00212   hd.y = readWord();
00213 
00214    if (hd.id == 16973) {
00215       if (!allocated)
00216         *pnter = new char [ hd.size + sizeof(hd) ];
00217       memcpy( *pnter, &hd, sizeof(hd));
00218       q = (char*) (*pnter) + sizeof(hd);
00219 
00220       readdata( q, hd.size);  // endian ok ?
00221       *size = hd.size + sizeof(hd);
00222    }
00223    else {
00224       w =  (hd.id + 1) * (hd.size + 1) + 4 ;
00225       if (!allocated)
00226         *pnter = new char [ w ];
00227       memcpy ( *pnter, &hd, sizeof ( hd ));
00228       q = (char*) (*pnter) + sizeof(hd);
00229       readdata ( q, w - sizeof(hd) ); // endian ok ?
00230       *size = w;
00231    }
00232 }
00233 
00234 
00235 
00236 void tnstream :: writerlepict ( const void* buf )
00237 {
00238    writeImage( buf, true );
00239 }
00240 
00241 void tnstream :: writeImage ( const void* buf, bool compress )
00242 {
00243    if ( compress ) {
00244       char* tempbuf = new char [ 0xffff ];
00245       if ( tempbuf ) {
00246          int   size    = compressrle ( buf, tempbuf );
00247          trleheader* hd = (trleheader*) tempbuf;
00248          writeWord( hd->id );
00249          writeWord( hd->size );
00250          writeChar( hd->rle );
00251          writeWord( hd->x );
00252          writeWord( hd->y );
00253          
00254          writedata ( hd+1, size - sizeof(*hd) );
00255          delete[] tempbuf;
00256       } else
00257          compress = false;
00258    }
00259 
00260    if ( !compress )  {
00261       Uint16* pw = (Uint16*) buf;
00262       writeWord(pw[0] );
00263       writeWord(pw[1] );
00264       writedata ( pw+2, ( pw[0] + 1 ) * ( pw[1] + 1 ) );
00265    }
00266 }
00267 
00268 
00269 ASCString tnstream::getDeviceName()
00270 {
00271    return devicename;
00272 }
00273 
00274 ASCString tnstream::getLocation()
00275 {
00276    return devicename;
00277 }
00278 
00279 ASCString tnstream::getArchive()
00280 {
00281    return "";
00282 }
00283 
00284 int  tnstream::readInt  ( void )
00285 {
00286    int i;
00287    readdata2 ( i );
00288    return SDL_SwapLE32( i );
00289 }
00290 
00291 int tnstream::readWord ( void )
00292 {
00293    Uint16 w;
00294    readdata2 ( w );
00295    return SDL_SwapLE16( w );
00296 }
00297 
00298 char tnstream::readChar ( void )
00299 {
00300    char c;
00301    readdata2 ( c );
00302    return c;
00303 }
00304 
00305 float SwapFloat( float f )
00306 {
00307   union
00308   {
00309     float f;
00310     unsigned char b[4];
00311   } dat1, dat2;
00312 
00313   dat1.f = f;
00314   dat2.b[0] = dat1.b[3];
00315   dat2.b[1] = dat1.b[2];
00316   dat2.b[2] = dat1.b[1];
00317   dat2.b[3] = dat1.b[0];
00318   return dat2.f;
00319 }
00320 
00321 float tnstream::readFloat ( void )
00322 {
00323    float c;
00324    readdata2 ( c );
00325 #if SDL_BYTEORDER == SDL_BIG_ENDIAN
00326    c = SwapFloat(c);
00327 #endif
00328    return c;
00329 }
00330 
00331 #if SIZE_T_not_identical_to_INT
00332 
00333 void tnstream::writeInt  ( size_t i )
00334 {
00335 #ifdef HAVE_LIMITS
00336    // assert( i <=  numeric_limits<int>::max());
00337 #endif
00338    writeInt( int(i) );
00339 }
00340 
00341 #endif
00342 
00343 void tnstream::writeInt  ( unsigned int i )
00344 {
00345    i = SDL_SwapLE32(i);
00346    writedata2 ( i );
00347 }
00348 
00349 void tnstream::writeInt  ( bool b )
00350 {
00351    int i = b;
00352    i = SDL_SwapLE32(i);
00353    writedata2 ( i );
00354 }
00355 
00356 void tnstream::writeInt  ( int i )
00357 {
00358    i = SDL_SwapLE32(i);
00359    writedata2 ( i );
00360 }
00361 
00362 void tnstream::writeWord ( int w )
00363 {
00364    Uint16 w2 = SDL_SwapLE16( Uint16(w) );
00365    writedata2 ( w2 );
00366 }
00367 
00368 void tnstream::writeChar ( char c )
00369 {
00370    writedata2 ( c );
00371 }
00372 
00373 void tnstream::writeFloat ( float f )
00374 {
00375    writedata2 ( f );
00376 }
00377 
00378 void         tnstream::readpchar(char** pc, int maxlength )
00379 { 
00380    int actpos2 = 0; 
00381 
00382    int maxav = 100000;
00383                             
00384    if ( maxlength )
00385       if ( maxav > maxlength )
00386          maxav = maxlength;
00387 
00388    CharBuf charbuf ( maxav );
00389 
00390    maxav--;
00391 
00392 
00393    char* pch2 = charbuf.buf;
00394 
00395    int loop = 0;
00396 
00397    do {
00398      actpos2++;
00399      if ( loop )
00400         pch2++;
00401         
00402      loop++;
00403 
00404      readdata( pch2, 1 ); // endian ok !
00405 
00406    } while (*pch2 != 0   &&   actpos2 < maxav ); /* enddo */
00407 
00408    if ( actpos2 >= maxav ) {
00409       pch2[1] = 0;
00410       actpos2++;
00411 
00412       if ( pch2[0] ) {
00413          char temp;
00414          do {
00415             readdata( &temp, 1 ); // endian ok !
00416          } while ( temp ); /* enddo */
00417       }
00418    }
00419                       
00420    pch2 = new char [ actpos2 ];
00421 
00422    memcpy ( pch2, charbuf.buf, actpos2 );
00423 
00424    *pc = pch2;
00425 } 
00426 
00427 
00428 void         tnstream::readpnchar(char** pc, int maxlength )
00429 { 
00430    int actpos2 = 0; 
00431 
00432    int maxav = 10000;
00433                             
00434    if ( maxlength )
00435       if ( maxav > maxlength )
00436          maxav = maxlength;
00437 
00438 
00439    CharBuf charbuf ( maxav );
00440 
00441    maxav--;
00442 
00443 
00444    char* pch2 = charbuf.buf;
00445 
00446    int ende = 0;
00447 
00448    do {
00449      char bt;
00450 
00451      int red = readdata( &bt, 1, 0 );
00452 
00453      if ( red < 1 ) {
00454         ende = 2;
00455         *pch2 = 0;
00456      } else
00457        if ( bt == '\n' || bt == 0 ) {
00458           *pch2 = 0;
00459           ende = 1;
00460        } else
00461           if ( bt != '\r' ) {
00462             *pch2 = bt;
00463             pch2++;
00464             actpos2++;
00465           }
00466 
00467    } while ( !ende  && actpos2 < maxav ); /* enddo */
00468 
00469 
00470    if ( !ende ) {
00471       if ( actpos2 >= maxav ) {
00472          *pch2 = 0;
00473 
00474          if ( pch2[0] ) {
00475             char temp;
00476             do {
00477 
00478                int red = readdata( &temp, 1, 0 );
00479                if ( red < 1 )  {
00480                   temp = 0;
00481                }  else
00482                  if ( temp == '\n' )
00483                     temp = 0;
00484 
00485             } while ( temp ); /* enddo */
00486          }
00487       }
00488    }
00489    if ( ende == 2 ) {
00490       if ( !actpos2 )
00491          *pc = NULL;
00492       else
00493          *pc = strdup ( charbuf.buf );
00494    } else
00495       *pc = strdup ( charbuf.buf );
00496 }
00497 
00498 
00499 bool  tnstream::readTextString ( ASCString& s, bool includeCR  )
00500 {
00501   s = "";
00502   char c;
00503   int red;
00504   int end = 0;
00505   do {
00506      red = readdata( &c, 1, 0 ); // endian ok !
00507      if ( red < 1 ) {
00508         end = 2;
00509      } else
00510        if ( (c == '\n' && !includeCR) || c == 0 ) {
00511           end = 1;
00512        } else
00513           if ( c != '\r' )
00514              s += c;
00515   } while ( red && !end );
00516   if ( end == 2)
00517      return false;
00518   else
00519      return true;
00520 }
00521 
00522 
00523 ASCString  tnstream::readString ( bool includeCR )
00524 {
00525   ASCString s;
00526   bool data = readTextString ( s, includeCR );
00527   if ( !data && s.empty() )
00528      throw treadafterend ( getLocation() );
00529   return s;
00530 }
00531 
00532 
00533 void         tnstream::writeString(const string& pc, bool binary )
00534 {
00535    if ( binary )
00536       writepchar ( pc.c_str() );
00537    else
00538       writedata ( pc.data(), pc.length() );
00539 }
00540 
00541 
00542 void         tnstream::writepchar(const char* pc)
00543 { 
00544    if ( pc ) {
00545       const char *pch1 = pc;
00546       int loop = 0;
00547 
00548       do {
00549          if ( loop )
00550             pch1++;
00551          writedata( pch1, 1 );
00552          loop++;
00553       } while ( *pch1 > 0  ); /* enddo */
00554    } else {
00555        char         pch1 = 0;
00556        writedata ( &pch1, 1 );
00557    }
00558 
00559 } 
00560 
00562 
00563 
00564 
00565 
00566 MemoryStreamCopy :: MemoryStreamCopy ( tnstream* stream )
00567 {
00568   buf = NULL;
00569   int bufused = 0;
00570   int memreserved = 0;
00571   int blocksize = 500000;
00572   int red;
00573   do {
00574     if ( bufused + blocksize > memreserved ) {
00575        int newsize = memreserved + blocksize;
00576        void* newbuf = malloc (newsize);
00577        if ( buf ) {
00578           memcpy ( newbuf, buf, bufused );
00579           free ( buf );
00580        }
00581        buf = newbuf;
00582        memreserved = newsize;
00583     }
00584     char* cp = (char*) buf;
00585     red = stream->readdata ( cp + bufused, blocksize, 0 ); // endian ok !
00586     bufused += red;
00587 
00588   } while ( red == blocksize );
00589   size = bufused;
00590   pos = 0;
00591 
00592   devicename = stream->getDeviceName();
00593 }
00594 
00595 ASCString MemoryStreamCopy::getLocation()
00596 {
00597   return devicename + " (memory buffered)";
00598 }
00599 
00600 MemoryStreamCopy :: ~MemoryStreamCopy ( )
00601 {
00602    if ( buf )
00603       free ( buf );
00604 }
00605 
00606 
00607 void MemoryStreamCopy :: writedata ( const void* buf, int size )
00608 {
00609    throw  tinvalidmode ( getDeviceName(), reading, writing );
00610 }
00611 
00612 int MemoryStreamCopy :: readdata  ( void* buffer, int _size, bool excpt )
00613 {
00614    char* cp = (char*) buf;
00615    if ( pos + _size > size ) {
00616       if ( excpt )
00617           throw treadafterend ( getDeviceName() );
00618       else {
00619          int tr = size-pos;
00620          memcpy ( buffer, cp+pos, tr );
00621          pos += tr;
00622          return tr;
00623       }
00624 
00625    } else {
00626       memcpy ( buffer, cp+pos, _size );
00627       pos += _size;
00628       return _size;
00629    }
00630 }
00631 
00632 void MemoryStreamCopy :: seek ( int newpos )
00633 {
00634    if ( newpos > size || newpos < 0 )
00635      throw treadafterend ( getDeviceName() );
00636 
00637    pos = newpos;
00638 }
00639 
00640 
00642 
00643 
00644 static int stream_seek( struct SDL_RWops *context, int offset, int whence)
00645 {
00646         MemoryStreamCopy* stream = (MemoryStreamCopy*) context->hidden.unknown.data1;
00647         if ( whence == SEEK_SET )
00648            stream->seek ( offset );
00649         else
00650         if ( whence == SEEK_CUR )
00651               stream->seek ( offset + stream->getPosition() );
00652            else
00653          if ( whence == SEEK_END )
00654             stream->seek ( offset + stream->getSize() );
00655   return stream->getPosition();
00656 }
00657 
00658 
00659 static int stream_read(SDL_RWops *context, void *ptr, int size, int maxnum)
00660 
00661 {
00662         MemoryStreamCopy* stream = (MemoryStreamCopy*) context->hidden.unknown.data1;
00663         size_t nread = stream->readdata ( ptr, size * maxnum, 0 );
00664 
00665         return(nread / size);
00666 }
00667 
00668 static int stream_close(SDL_RWops *context)
00669 {
00670         if ( context ) {
00671                 if ( context->hidden.unknown.data1 ) {
00672                         MemoryStreamCopy* stream = (MemoryStreamCopy*) context->hidden.unknown.data1;
00673                         delete stream;
00674                 }
00675                 SDL_FreeRW(context);
00676         }
00677         return(0);
00678 }
00679 
00680 
00681 SDL_RWops *SDL_RWFromStream( tnstream* stream )
00682 {
00683    MemoryStreamCopy* msb = new MemoryStreamCopy ( stream );
00684 
00685         SDL_RWops *rwops;
00686 
00687         rwops = SDL_AllocRW();
00688         if ( rwops != NULL ) {
00689            rwops->seek = stream_seek;
00690            rwops->read = stream_read;
00691            rwops->write = NULL;
00692            rwops->close = stream_close;
00693            rwops->hidden.unknown.data1 = msb;
00694         }
00695         return(rwops);
00696 }
00697 
00699 
00700 
00701 
00702 
00703 tncontainerstream :: tncontainerstream ( const char* containerfilename, ContainerIndexer* indexer, int dirLevel )
00704         : tn_file_buf_stream ( containerfilename, reading ), index(NULL)
00705 {
00706    num = 0;
00707    char magic[4];
00708    readdata ( &magic, 4 ); // endian ok !
00709    if ( strncmp ( magic, containermagic, 4 ) == 0) {
00710       int pos = readInt();
00711       seek ( pos );
00712       num = readInt();
00713       index = new tcontainerindex[num];
00714       for ( int i = 0; i < num; i++ ) {
00715 
00716          bool __loadName = readInt();
00717          index[i].start = readInt();
00718          index[i].end = readInt();
00719          if ( __loadName ) {
00720             readpchar ( &index[i].name );
00721 
00722            #if CASE_SENSITIVE_FILE_NAMES == 1
00723             // quick hack to be able to use existing CON files.
00724             char *c = index[i].name;
00725             while ( *c ) {
00726                *c = tolower( *c );
00727                c++;
00728             }
00729            #endif
00730 
00731             indexer->addfile ( index[i].name, this, dirLevel );
00732          } else
00733             index[i].name = NULL;
00734       }
00735    }
00736    actfile = NULL;
00737    containerfilepos = 0;
00738 }
00739 
00740 
00741 int  tncontainerstream :: getcontainerfilesize ( const char* name )
00742 {
00743    int i = 0;
00744    while ( i < num  &&  stricmp ( index[i].name, name ) )
00745       i++;
00746 
00747    if ( i >= num )
00748       return -1;
00749    else
00750       return index[i].end - index[i].start + 1;
00751 
00752 }
00753 
00754 
00755 void tncontainerstream :: opencontainerfile ( const char* name )
00756 {
00757    if ( actfile ) {
00758       ASCString err = ASCString("two files simultaneously: ") + actfile->name + " and " + name;
00759       throw tfileerror (  err );
00760    }
00761 
00762    containerfilepos = 0;
00763    int i = 0;
00764    while ( i < num  && stricmp ( index[i].name, name ) )
00765       i++;
00766 
00767    if ( i >= num )
00768       throw tfileerror ( name );
00769 
00770    displayLogMessage( 9, ASCString("opencontainerfile ") + name );
00771    containerfilepos = 0;
00772    seek ( index[i].start );
00773    actfile = &index[i];
00774 }
00775 
00776 int tncontainerstream :: readcontainerdata ( void* buf, int size, bool excpt  )
00777 {
00778    if ( actfile->start + containerfilepos + size > actfile->end+1 ) {
00779       if ( excpt ) 
00780          throw treadafterend ( actfile->name );
00781       else {
00782          int got = readdata ( buf, (actfile->end+1 - actfile->start) - containerfilepos  , excpt );
00783          containerfilepos+=got;
00784          return got;
00785 
00786       }
00787    }
00788 
00789    readdata ( buf, size );
00790    containerfilepos+=size;
00791    return size;
00792 }
00793 
00794 void tncontainerstream :: closecontainerfile ( void )
00795 {
00796    actfile = NULL;
00797 }
00798 
00799 char* tncontainerstream :: getfirstname ( void )
00800 {
00801    actname = 0;
00802    return getnextname();
00803 }
00804 
00805 char* tncontainerstream :: getnextname ( void )
00806 {
00807    if ( actname < num )
00808       return index[actname++].name;
00809    else
00810       return NULL;
00811 
00812 }
00813 
00814 
00815 
00816 tncontainerstream  :: ~tncontainerstream  ()
00817 {
00818    for ( int i = 0; i < num; i++ ) 
00819       if ( index[i].name )
00820          delete[] index[i].name;
00821    delete[] index;
00822 }
00823 
00824 
00825 
00826 
00828 
00829 class ContainerCollector : public ContainerIndexer {
00830    public:
00831       struct FileIndex {
00832          ASCString name;
00833          pncontainerstream container;
00834          int directoryLevel;
00835       };
00836    protected:
00837 
00838       dynamic_array<FileIndex> index[256];    // not very efficient, but who cares :-)
00839 
00840       dynamic_array<pncontainerstream> container;
00841       int containernum;
00842       struct {
00843          int alpha;
00844          int index;
00845       } namesearch;       // next entry to return
00846    public:
00847       ContainerCollector ( void );
00848       void init ( const char* wildcard );
00849       void addfile ( const char* filename, const pncontainerstream stream, int directoryLevel );
00850            // pncontainerstream getfile ( const char* filename );
00851       FileIndex* getfile ( const ASCString& filename );
00852       FileIndex* getfirstname ( void );
00853       FileIndex* getnextname ( void );
00854       ASCString listContainer();
00855       virtual ~ContainerCollector();
00856 };
00857 
00858 
00859 ContainerCollector containercollector;
00860 
00861 char* constructFileName( char* buf, int directoryLevel, const char* path, const char* filename )
00862 {
00863   if ( buf ) {
00864 
00865      const char* filename2 = filename;
00866      buf[0] = 0;
00867 
00868      // filenames beginning with / or ~/ have an absolute path ; ignore variable path for them
00869      if ( ! (filename && (filename[0] == pathdelimitter || (filename[0]=='~' && filename[1] == pathdelimitter)) )) {
00870         if ( path )
00871            strcpy ( buf, path);
00872         else
00873            if ( directoryLevel >= 0 && ascDirectory[ directoryLevel ] )
00874               strcpy ( buf, ascDirectory[ directoryLevel ]);
00875      }
00876 
00877      appendbackslash ( buf );
00878 
00879      if ( filename && strchr ( filename, pathdelimitter )) {
00880      
00881         char name2[ maxFileStringSize ];
00882         // filename contains directories
00883         strcpy ( name2, filename );
00884         int i = strlen ( name2 )-1;
00885         while ( name2[i] != pathdelimitter )
00886            i--;
00887 
00888         name2[i+1] = 0;
00889 
00890         filename2 = &filename[i+1];
00891 
00892         // filename2 is now the pure filename without directory
00893         // name2 is the directory
00894         
00895         if ( buf[0] && name2[0]==pathdelimitter )
00896            strcpy ( buf, name2+1);
00897         else
00898            strcpy ( buf, name2);
00899      }
00900 
00901      if ( buf[0] == '~' && buf[1] == pathdelimitter ) {
00902         char* home = getenv ( "HOME" );
00903         if ( home ) {
00904            char temp[ maxFileStringSize ];
00905            strcpy ( temp, buf );
00906            strcpy ( buf, home );
00907            appendbackslash ( buf );
00908            strcat ( buf, &temp[2]);
00909         }
00910      }
00911 
00912 
00913      appendbackslash ( buf );
00914 
00915      if ( filename2 )
00916         strcat ( buf, filename2 );
00917   }
00918 
00919   return buf;
00920 }
00921 
00922 bool isPathRelative( const ASCString& path )
00923 {
00924   if ( path.length() < 2 )
00925      return true;
00926      
00927   if ( path[0] == '~' && path[1] == pathdelimitter )
00928      return false;
00929 
00930 #ifdef WIN32
00931   if ( path[1] == ':' && path[2] == pathdelimitter )
00932      return false;
00933 
00934 #endif
00935      
00936   if ( path[0] == pathdelimitter )
00937      return false;
00938 
00939   return true;     
00940 }
00941 
00942 ASCString constructFileName( int directoryLevel, const ASCString& path, ASCString filename )
00943 {
00944      ASCString result;
00945    
00946      // filenames beginning with / or ~/ have an absolute path ; ignore variable path for them
00947      if ( isPathRelative( filename )) {
00948         if ( !path.empty() )
00949            result += path;
00950         else
00951            if ( directoryLevel >= 0 && ascDirectory[ directoryLevel ] )
00952               result += ascDirectory[ directoryLevel ];
00953      }
00954 
00955      appendbackslash ( result );
00956 
00957      if ( !filename.empty() && filename.find( pathdelimitter )!= ASCString::npos ) {
00958         ASCString dir = filename;
00959         
00960         dir.erase( dir.rfind( pathdelimitter ) + 1);
00961 
00962         filename.erase( 0, filename.find( pathdelimitter ) + 1 );
00963         
00964         if ( dir.find( pathdelimitter ) == 0 )
00965            dir.erase( 0, 1 );
00966            
00967         result = dir;   
00968      }
00969 
00970      if ( result.length() > 2 && result[0] == '~' && result[1] == pathdelimitter ) {
00971         char* home = getenv ( "HOME" );
00972         if ( home ) {
00973            ASCString temp = result;
00974            result = home;
00975            appendbackslash ( result );
00976            result += temp.substr( 2 );
00977         }
00978      }
00979 
00980 
00981      appendbackslash ( result );
00982 
00983      result += filename;
00984 
00985      return result;
00986 }
00987 
00988 
00989 
00990 struct FileLocation {
00991         int directoryLevel;
00992         pncontainerstream container;
00993         int found;
00994      };
00995 
00996 void locateFile ( const ASCString& filename, FileLocation* loc )
00997 {
00998    loc->found = 0;
00999    ContainerCollector::FileIndex* idx = containercollector.getfile ( filename );
01000    int maxnum;
01001    if ( idx ) {
01002       maxnum = idx->directoryLevel+1;
01003       loc->directoryLevel = idx->directoryLevel;
01004       loc->found = 1;
01005       loc->container = idx->container;
01006    } else {
01007       maxnum = searchDirNum;
01008       loc->container = NULL;
01009       loc->directoryLevel = -1;
01010    }
01011 
01012    if ( maxnum ) {
01013       int localfound = 0;
01014       for ( int i = 0; i < maxnum && !localfound; i++ ) {
01015          char buf[2000];
01016          FILE* fp = fopen ( constructFileName ( buf, i, NULL, filename.c_str()), "r" );
01017          if ( fp ) {
01018             localfound = loc->found = 1;
01019             fclose ( fp );
01020             loc->container = NULL;
01021             loc->directoryLevel = i;
01022          }
01023       }
01024    } else {
01025       char buf[2000];
01026       FILE* fp = fopen ( constructFileName ( buf, -1, ".", filename.c_str()), "r" );
01027       if ( fp ) {
01028          loc->found = 1;
01029          fclose ( fp );
01030          loc->container = NULL;
01031          loc->directoryLevel = -2;
01032       }
01033    }
01034 }
01035 
01037 
01038 
01039 
01040 ASCString listContainer()
01041 {
01042    return containercollector.listContainer();
01043 }
01044 
01045 
01046 ContainerCollector :: ContainerCollector ( void )
01047 {
01048   containernum = 0;
01049 }
01050 
01051 void ContainerCollector :: init ( const char* wildcard )
01052 {
01053    for ( int i = 0; i < searchDirNum; i++ ) {
01054       DIR *dirp; 
01055       struct ASC_direct *direntp;
01056 
01057       char buf[ maxFileStringSize ];
01058       char buf2[ maxFileStringSize ];
01059       char buf3 [ maxFileStringSize ];
01060       dirp = opendir( extractPath ( buf2, constructFileName ( buf, i, NULL, wildcard )));
01061       extractFileName ( buf3, buf );
01062       if( dirp != NULL ) { 
01063          for(;;) { 
01064             direntp = readdir( dirp ); 
01065             if ( direntp == NULL ) {
01066                break; 
01067             }
01068             if ( patimat ( buf3, direntp->d_name )) {
01069                container[containernum++] = new tncontainerstream( constructFileName ( buf, i, buf2, direntp->d_name), this, i);
01070                if ( MessagingHub::Instance().getVerbosity() >= 2 )
01071                   printf("container %s mounted\n", buf );
01072             }
01073          } 
01074          closedir( dirp ); 
01075       } 
01076    }
01077 }
01078 
01079 void ContainerCollector :: addfile ( const char* filename, const pncontainerstream stream, int directoryLevel )
01080 {
01081    int found = 0;
01082    FileIndex* cci = NULL;
01083 
01084    int i1 = toupper ( filename[0] );
01085    for ( int i = 0; i <= index[i1].getlength(); i++ )
01086       if ( index[i1][i].name.compare_ci ( filename ) == 0 )  {
01087          if ( index[i1][i].directoryLevel <= directoryLevel ) 
01088             return;
01089          else {
01090             cci = &(index[i1][i]);
01091             found = 1;
01092          }
01093       }
01094 
01095    if ( !found )
01096       cci = &( index[i1][ index[i1].getlength()+1 ] );
01097 
01098    cci->name = filename;
01099    cci->container = stream;
01100    cci->directoryLevel = directoryLevel;
01101 }
01102 
01103 ContainerCollector::FileIndex* ContainerCollector :: getfile ( const ASCString& filename )
01104 {
01105    int i1 = toupper ( filename[0] );
01106    for ( int i = 0; i <= index[i1].getlength(); i++ )
01107       if ( index[i1][i].name.compare_ci ( filename) == 0 )
01108          return &index[i1][i];
01109 
01110    return NULL;
01111 }
01112 
01113 
01114 ContainerCollector::FileIndex* ContainerCollector :: getfirstname ( void )
01115 {
01116    namesearch.alpha = 0;
01117    namesearch.index = 0;
01118    return getnextname();
01119 }
01120 
01121 ContainerCollector::FileIndex* ContainerCollector :: getnextname ( void )
01122 {
01123    while ( index[namesearch.alpha].getlength() < namesearch.index) {
01124       if ( namesearch.alpha == 255 )
01125          return NULL;
01126       namesearch.alpha++;
01127       namesearch.index = 0;
01128    } /* endwhile */
01129    return &index[namesearch.alpha][namesearch.index++];
01130 }
01131 
01132 ASCString ContainerCollector :: listContainer()
01133 {
01134    ASCString s;
01135    for ( int i = 0; i < containernum; i++ )
01136       s += container[i]->getLocation() + "\n";
01137 
01138    return s;
01139    
01140 }
01141 
01142 
01143 
01144 ContainerCollector :: ~ContainerCollector()
01145 {
01146   int i;
01147    for (i = 0; i < containernum; i++ )
01148       delete container[i];
01149    containernum = 0;
01150 }
01151 
01152 
01153 
01155 
01156 CompressionStreamAdapter::CompressionStreamAdapter( tnstream* compressedStream )
01157    : stream ( compressedStream )
01158 {
01159 }
01160 void CompressionStreamAdapter::writecmpdata ( const void* buf, int size )
01161 {
01162    stream->writedata( buf, size );
01163 }
01164 
01165 int CompressionStreamAdapter::readcmpdata ( void* buf, int size, bool excpt  )
01166 {
01167    return stream->readdata( buf, size, excpt );
01168 }
01169 
01170 
01171 class PrivateCompressionData {
01172    public:  
01173       bz_stream bzs;
01174       static const int outputbufsize = 100000;
01175       char outputbuf[outputbufsize];
01176       
01177       PrivateCompressionData() {
01178          bzs.bzalloc = NULL;
01179          bzs.bzfree = NULL;
01180          bzs.opaque = NULL;
01181       };
01182       
01183       ~PrivateCompressionData() {
01184          BZ2_bzCompressEnd ( &bzs );
01185       }
01186 };
01187 
01188 libbzip_compression :: libbzip_compression ( CompressionStreamInterface* strm  )
01189 {
01190    data = new PrivateCompressionData();
01191    BZ2_bzCompressInit ( &data->bzs, 5, 0, 0 );
01192 
01193    stream = strm;
01194 }
01195 
01196 
01197 void libbzip_compression :: writedata ( const void* buf, int size )
01198 {
01199    char* cbuf = (char*) buf;
01200 
01201    data->bzs.next_in = cbuf ;
01202    data->bzs.avail_in = size ;
01203    data->bzs.total_in_lo32 = 0 ;
01204    data->bzs.total_in_hi32 = 0 ;
01205 
01206    while ( data->bzs.total_in_lo32 < size ) {
01207 
01208      data->bzs.next_out = data->outputbuf;
01209      data->bzs.avail_out = data->outputbufsize;
01210      data->bzs.total_out_lo32 = 0;
01211      data->bzs.total_out_hi32 = 0;
01212 
01213      int res = BZ2_bzCompress ( &data->bzs, BZ_RUN );
01214      if ( res < 0 )
01215         throw StreamCompressionError ( "MBZLB2 compression :: writedata", res );
01216 
01217      for ( int i = 0; i < data->bzs.total_out_lo32; i++ )
01218         data->outputbuf[i] ^= bzip_xor_byte;
01219 
01220      if ( data->bzs.total_out_lo32 > 0 )
01221         stream->writecmpdata ( data->outputbuf, data->bzs.total_out_lo32 );
01222    }
01223 }
01224 
01225 
01226 void libbzip_compression :: close_compression ( void )
01227 {
01228    int res;
01229    do {
01230      data->bzs.next_in = data->outputbuf;
01231      data->bzs.avail_in = 0;
01232 
01233      data->bzs.next_out = data->outputbuf;
01234      data->bzs.avail_out = data->outputbufsize;
01235      data->bzs.total_out_lo32 = 0;
01236      data->bzs.total_out_hi32 = 0;
01237 
01238      res = BZ2_bzCompress ( &data->bzs, BZ_FINISH );
01239      if ( res < 0 )
01240         throw StreamCompressionError ( "MBZLB2 compression :: closecompression", res );
01241 
01242      for ( int i = 0; i < data->bzs.total_out_lo32; i++ )
01243         data->outputbuf[i] ^= bzip_xor_byte;
01244      stream->writecmpdata ( data->outputbuf, data->bzs.total_out_lo32 );
01245 
01246    } while ( res != BZ_STREAM_END );
01247 
01248 
01249    BZ2_bzCompressEnd ( &data->bzs );
01250 }
01251 
01252 libbzip_compression :: ~libbzip_compression ( )
01253 {
01254    delete data;
01255 }
01256 
01257 
01258 
01259 class PrivateDecompressionData {
01260    public: 
01261       bz_stream bzs;
01262       static const int inputbufsize = 100000;
01263       char inputbuf[inputbufsize];
01264       int inputbufused;
01265       int inputbufread;
01266       
01267       PrivateDecompressionData() {
01268          bzs.bzalloc = NULL;
01269          bzs.bzfree = NULL;
01270          bzs.opaque = NULL;
01271          
01272          inputbufused = 0;
01273          inputbufread = 0;
01274          
01275       }
01276       
01277       ~PrivateDecompressionData() {
01278          BZ2_bzDecompressEnd ( &bzs );
01279       }
01280       
01281 };
01282       
01283 libbzip_decompression :: libbzip_decompression ( CompressionStreamInterface* strm  )
01284 {
01285    data = new PrivateDecompressionData();
01286    BZ2_bzDecompressInit ( &data->bzs, 0, 0 );
01287    stream = strm;
01288 }
01289 
01290 
01291 int libbzip_decompression :: readdata ( void* buf, int size, bool excpt )
01292 {
01293    int decompressed = 0;
01294    char* cbuf = (char*) buf;
01295 
01296    data->bzs.next_in = cbuf ;
01297    data->bzs.avail_in = size ;
01298    data->bzs.total_in_lo32 = 0 ;
01299    data->bzs.total_in_hi32 = 0 ;
01300 
01301    int abrt = 0;
01302 
01303    while ( decompressed < size  && !abrt ) {
01304      if ( data->inputbufread >= data->inputbufused ) {
01305         data->inputbufused = stream->readcmpdata ( data->inputbuf, data->inputbufsize, 0 );
01306 
01307         if ( !data->inputbufused && excpt )
01308            throw StreamCompressionError ( "Decompressor :: out of data", 0 );
01309 
01310 
01311         for ( int i = 0; i < data->inputbufused; i++ )
01312            data->inputbuf[i] ^= bzip_xor_byte;
01313 
01314         data->inputbufread = 0;
01315      }
01316      data->bzs.next_in = data->inputbuf + data->inputbufread;
01317      data->bzs.avail_in = data->inputbufused - data->inputbufread;
01318      data->bzs.total_in_lo32 = 0;
01319      data->bzs.total_in_hi32 = 0;
01320 
01321      data->bzs.next_out = cbuf + decompressed;
01322      data->bzs.avail_out = size - decompressed;
01323      data->bzs.total_out_lo32 = 0;
01324      data->bzs.total_out_hi32 = 0;
01325 
01326      int res = BZ2_bzDecompress ( &data->bzs );
01327      decompressed += data->bzs.total_out_lo32;
01328      data->inputbufread += data->bzs.total_in_lo32;
01329 
01330      if ( decompressed < size  ) {
01331         if ( res == BZ_STREAM_END ) {
01332            if ( excpt )
01333               throw treadafterend ( "BZ_decompress_stream" );
01334            abrt = 1;
01335         } else {
01336            if ( res != BZ_OK ) {
01337               if ( excpt ) {
01338                  if ( res == BZ_MEM_ERROR )
01339                     throw OutOfMemoryError ( -1 );
01340                  else
01341                     throw StreamCompressionError ( "MBZLB2 decompression :: readdata", res );
01342               }
01343               abrt = 1;
01344            }
01345         }
01346      }
01347    }
01348    return decompressed;
01349 }
01350 
01351 
01352 libbzip_decompression :: ~libbzip_decompression ( )
01353 {
01354    delete data;
01355 }
01356 
01357 
01358 
01360 
01361 /*
01362 t_compressor_2ndbuf_filter :: t_compressor_2ndbuf_filter ( t_compressor_stream_interface* strm )
01363 {
01364    stream = strm;
01365 }
01366 
01367 void t_compressor_2ndbuf_filter :: writecmpdata ( const void* buf, int size )
01368 {
01369    stream->writecmpdata ( buf, size );
01370 }
01371 
01372 int t_compressor_2ndbuf_filter :: readcmpdata ( void* buf, int size, bool excpt )
01373 {
01374    int got = 0;
01375 
01376    char* pc = (char*) buf;
01377 
01378    while ( size && _queue.size() ) {
01379        *pc = _queue.front();
01380        _queue.pop();
01381        pc++;
01382        size--;
01383        got++;
01384    }
01385 
01386    if ( size )
01387       got += stream->readcmpdata ( pc, size, excpt );
01388 
01389    return got;
01390 }
01391 
01392 void t_compressor_2ndbuf_filter :: insert_data_into_queue ( const void* buf, int size )
01393 {
01394    char* pc = (char*) buf;
01395    for (int i = 0; i < size; i++) {
01396       _queue.push ( *pc );
01397       pc++;
01398    }
01399 }
01400 */
01401 
01402 
01403 
01404 tanycompression :: tanycompression ( int md )
01405 {
01406    mmd = md;
01407    bzip_compress = NULL;
01408    bzip_decompress = NULL;
01409 }
01410 
01411 void tanycompression :: init ( void )
01412 {
01413    if ( mmd == 1 ) {
01414       char buf[10];
01415 
01416       int maxlen = strlen ( BZIP_SIGNATURE ) + 1;
01417       int bufdatanum = readcmpdata ( buf, maxlen, 0 );
01418       int siglen = 0;
01419 
01420       if ( bufdatanum  == maxlen ) {
01421 
01422          if ( strncmp ( &buf[1], LZ_SIGNATURE, 9 ) == 0  && !buf[0]) {
01423             status = 110;
01424             siglen = 0;
01425          } else
01426          if ( strncmp ( &buf[1], RLE_SIGNATURE, 9 ) == 0 && !buf[0]) {
01427             status = 111;
01428             siglen = 0;
01429          } else
01430          if ( strncmp ( buf, BZIP_SIGNATURE, 9 ) == 0 ) {
01431             status = 112;
01432             siglen = strlen ( BZIP_SIGNATURE ) + 1;
01433             bzip_decompress = new libbzip_decompression ( this );
01434          } else
01435             status= 109;
01436 
01437       } else
01438          status = 109;
01439 
01440       for ( int i = siglen; i < bufdatanum; i++ )
01441           _queue.push ( buf[i] );
01442 
01443 
01444    } else {
01445        status = 201;
01446        bzip_compress = new libbzip_compression ( this );
01447        writecmpdata ( BZIP_SIGNATURE, strlen ( BZIP_SIGNATURE ) + 1 );
01448    }
01449 }
01450 
01451 
01452 int  tanycompression :: readdata ( void* rbuf, int size, bool excpt )
01453 {
01454    int red = 0;
01455    if ( size ) {
01456       switch ( status ) {
01457       case 109: red += readlzwdata ( rbuf, size, excpt );
01458          break;
01459       case 110:
01460       case 111: red += tlzwstreamcompression :: readdata ( rbuf, size, excpt );
01461          break;
01462       case 112: red += bzip_decompress -> readdata ( rbuf, size, excpt );
01463          break;
01464       } /* endswitch */
01465    }
01466    return red;   
01467 }                          
01468 
01469 
01470 
01471 void tanycompression :: writedata ( const void* buf, int size )
01472 {
01473   bzip_compress -> writedata ( buf, size );
01474   // writecmpdata ( buf, size );
01475 }
01476 
01477 
01478 int tanycompression :: readlzwdata ( void* buf, int size, bool excpt )
01479 {
01480    if ( _queue.size() ) {
01481       int got = 0;
01482 
01483       char* pc = (char*) buf;
01484 
01485       while ( size && _queue.size() ) {
01486           *pc = _queue.front();
01487           _queue.pop();
01488           pc++;
01489           size--;
01490           got++;
01491       } /* endwhile */
01492 
01493       if ( size )
01494          got += readcmpdata ( pc, size, excpt );
01495 
01496       return got;
01497    } else
01498       return readcmpdata ( buf, size, excpt );
01499 }
01500 
01501 void tanycompression :: writelzwdata ( const void* buf, int size )
01502 {
01503    writecmpdata ( buf, size );
01504 }
01505 
01506 
01507 void tanycompression :: close_compression ( void )
01508 {
01509    if ( bzip_compress ) {
01510       bzip_compress->close_compression ( );
01511       delete bzip_compress;
01512       bzip_compress = NULL;
01513    }
01514 }
01515 
01516 
01517 tanycompression :: ~tanycompression ( )
01518 {
01519    if ( bzip_decompress ) {
01520       delete bzip_decompress;
01521       bzip_decompress = NULL;
01522    }
01523 
01524 }
01525 
01526 
01528 
01529 /*
01530 void tn_lzw_bufstream :: writedata ( const void* buf, int size )
01531 {
01532    tlzwstreamcompression :: writedata ( buf, size );
01533 }
01534 
01535 int tn_lzw_bufstream :: readdata  ( void* buf, int size, bool excpt  )
01536 {
01537    return tlzwstreamcompression :: readdata ( buf, size, excpt );
01538 }
01539 
01540 int  tn_lzw_bufstream :: readlzwdata ( void* buf, int size, bool excpt  )
01541 {
01542    return tnbufstream :: readdata ( buf, size, excpt );
01543 }
01544 
01545 void tn_lzw_bufstream :: writelzwdata ( const void* buf, int size )
01546 {
01547    tnbufstream :: writedata ( buf, size );
01548 }
01549 
01550 tn_lzw_bufstream :: ~tn_lzw_bufstream ()
01551 {
01552    tlzwstreamcompression :: close();
01553    tnbufstream :: close();
01554 }
01555 
01556 */
01557 
01559 
01560 void tn_lzw_file_buf_stream :: writedata ( const void* buf, int size )
01561 {
01562    tanycompression :: writedata ( buf, size );
01563 }
01564 
01565 int  tn_lzw_file_buf_stream :: readdata  ( void* buf, int size, bool excpt  )
01566 {
01567    return tanycompression :: readdata ( buf, size, excpt );
01568 }
01569 
01570 int  tn_lzw_file_buf_stream:: readcmpdata ( void* buf, int size, bool excpt  )
01571 {
01572    return tn_file_buf_stream :: readdata ( buf, size, excpt  );
01573 }
01574 
01575 void tn_lzw_file_buf_stream :: writecmpdata ( const void* buf, int size )
01576 {
01577    tn_file_buf_stream :: writedata ( buf, size );
01578 }
01579 
01580 tn_lzw_file_buf_stream :: ~tn_lzw_file_buf_stream()
01581 {
01582    close_compression ();
01583    tn_file_buf_stream :: close();
01584 }
01585 
01586 
01588 
01589 
01590 tn_c_lzw_filestream :: tn_c_lzw_filestream ( const ASCString& name, IOMode mode ) : tanycompression ( mode )
01591 {
01592    #ifdef logfiles
01593     FILE* fp = fopen ( "files.lst", "at" );
01594     fprintf ( fp, "%s\n", name );
01595     fclose ( fp );
01596    #endif
01597 
01598    strm = NULL;
01599    inp = 0;
01600    containerstream = NULL;
01601 
01602    FileLocation fl;
01603    if ( mode == tnstream::reading ) {
01604       locateFile ( name, &fl );
01605 
01606       if ( !fl.found )
01607          throw tfileerror ( name );
01608 
01609    } else {
01610       fl.directoryLevel = 0;
01611       fl.container = NULL;
01612    }
01613 
01614 
01615    if ( fl.container == NULL ) {
01616       char string[2000];
01617 
01618       ASCString fileNameComplete = constructFileName ( string, fl.directoryLevel, NULL, name.c_str());
01619       strm = new tn_file_buf_stream ( fileNameComplete, mode );
01620       inp = 1;
01621       devicename = fileNameComplete;
01622       location = fileNameComplete;
01623 
01624    } else {
01625       containerstream = fl.container;
01626       if ( containerstream ) {
01627          inp = 2;
01628          containerstream->opencontainerfile ( name.c_str() );
01629          devicename = name;
01630          location = name + " located inside " + containerstream->getDeviceName();
01631       } else
01632          throw tfileerror ( name );
01633    }
01634    fname = name;
01635 
01636    tanycompression :: init (  );
01637 }
01638 
01639 ASCString tn_c_lzw_filestream::getArchive()
01640 {
01641    if ( containerstream )
01642       return containerstream->getDeviceName();
01643    else
01644       return "";
01645 }
01646 
01647 
01648 ASCString tn_c_lzw_filestream::getLocation()
01649 {
01650    return location;
01651 }
01652 
01653 int tn_c_lzw_filestream :: getSize ( void )
01654 {
01655    if ( inp == 2 )
01656       return containerstream->getSize();
01657    else
01658       return strm->getSize();
01659 }
01660 
01661 void tn_c_lzw_filestream :: writecmpdata ( const void* buf, int size )
01662 {
01663    if ( inp == 2 )
01664       throw tinvalidmode ( fname, tnstream::reading, tnstream::writing );
01665    else
01666       strm->writedata ( buf, size );
01667 }
01668 
01669 int tn_c_lzw_filestream :: readcmpdata  ( void* buf, int size, bool excpt  )
01670 {
01671    if ( inp == 2 )
01672       return containerstream->readcontainerdata ( buf, size, excpt );
01673    else
01674       return strm->readdata ( buf, size, excpt  );
01675 };
01676 
01677 
01678 void tn_c_lzw_filestream :: writedata ( const void* buf, int size )
01679 {
01680    tanycompression :: writedata ( buf, size );
01681 }
01682 
01683 int tn_c_lzw_filestream :: readdata  ( void* buf, int size, bool excpt  )
01684 {
01685    if ( tanycompression :: mode == readingdirect  && !tempbuf.size() )
01686       if ( inp == 2 )
01687          return containerstream->readcontainerdata ( buf, size, excpt  );
01688       else
01689          return strm->readdata ( buf, size, excpt  );
01690    else
01691       return tanycompression :: readdata ( buf, size, excpt );
01692 };
01693 
01694 
01695 time_t tn_c_lzw_filestream :: get_time ( void )
01696 {
01697    if ( inp == 2 )
01698       return containerstream->get_time();
01699    else
01700       return strm->get_time();
01701 }
01702 
01703 tn_c_lzw_filestream :: ~tn_c_lzw_filestream()
01704 {
01705    try {
01706       displayLogMessage( 9, "~tn_c_lzw_filestream " + getLocation() );
01707       
01708       close_compression ();
01709       close();
01710       if ( inp == 1 ) {
01711          delete strm;
01712          strm = NULL;
01713       } else {
01714          displayLogMessage( 9, ASCString("~tn_c_lzw_filestream -> closecontainerfile ") );
01715          containerstream->closecontainerfile();
01716       }
01717    } catch ( ... ) {
01718       displayLogMessage( 9, ASCString("~tn_c_lzw_filestream : caught exception") );
01719       throw;
01720    }
01721 }
01722 
01723 
01724 
01726 
01727 static const char asciiCodingTable[64] = { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
01728                                 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
01729                                 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X',
01730                                 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',
01731                                 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
01732                                 'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
01733                                 'w', 'x', 'y', 'z', '0', '1', '2', '3',
01734                                 '4', '5', '6', '7', '8', '9', '+', '/' };
01735 
01736 
01737 ASCIIEncodingStream::ASCIIEncodingStream() : shift(0), buf(0) {};
01738 
01739 void ASCIIEncodingStream::writedata ( const void* buf, int size ) {
01740    const char* c = (const char*)buf;
01741    for ( int i = 0; i < size; ++i )
01742       put ( c[i] );
01743 }
01744 int ASCIIEncodingStream::readdata  ( void* buf, int size, bool excpt  ) {
01745    throw  tinvalidmode ( "Base64SerializingStream", reading, writing );
01746 }
01747 
01748 void ASCIIEncodingStream::put( char c )
01749  {
01750     if ( shift == 0 ) {
01751        buf = c >> 6;
01752        shift = 2;
01753        result += asciiCodingTable[c & 63];
01754     } else if ( shift == 2 ) {
01755        buf |= ( c << 2) & 63;
01756        result += asciiCodingTable[buf];
01757        buf = c >> 4;
01758        shift = 4;
01759     } else if ( shift==4 ) {
01760        buf |= (c << 4) & 63;
01761        result += asciiCodingTable[buf];
01762        shift = 0;
01763        result += asciiCodingTable[int((c>>2) & 63)];
01764     }
01765  }
01766  void ASCIIEncodingStream::flush() {
01767     if ( shift )
01768        result += asciiCodingTable[buf & 63];
01769     result += "#";
01770  }
01771 
01772  ASCString ASCIIEncodingStream::getResult()
01773  {
01774     flush();
01775     return result;
01776  }
01777 
01778 void ASCIIDecodingStream :: generateTable()
01779 {
01780    for ( int i = 0; i< 256; ++i )
01781       reverse[i] = -1;
01782    for ( int i = 0; i < sizeof(asciiCodingTable); ++i )
01783       reverse[ int(asciiCodingTable[i])] = i;
01784 }
01785 
01786 int ASCIIDecodingStream :: get()
01787 {
01788    if ( length < data.length() ) {
01789       int c = data.at(length);
01790       if ( c == '#' )
01791          throw treadafterend("ASCIIDecodingStream");
01792       ++length;
01793 
01794       if ( reverse[c] == -1 )
01795          throw ASCmsgException("Invalid ASCII data to decode");
01796 
01797       return reverse[c];
01798    } else
01799       throw treadafterend("ASCIIDecodingStream");
01800 }
01801 
01802 ASCIIDecodingStream :: ASCIIDecodingStream( const ASCString& data) : shift(0), buf(0), length(0)
01803 {
01804    this->data = data;
01805    generateTable();
01806 }
01807 
01808 void ASCIIDecodingStream  :: writedata ( const void* buf, int size )
01809 {
01810    throw  tinvalidmode ( "ASCIIDecodingStream", writing, reading );
01811 }
01812 
01813 int ASCIIDecodingStream :: readdata  ( void* buffer, int size, bool excpt  )
01814 {
01815    int i = 0;
01816    try {
01817       char* cbuf = (char*) buffer;
01818       for ( i = 0; i < size; ++i ) {
01819          if ( shift == 0 ) {
01820             char c = get();
01821             char c2 = get();
01822             cbuf[i] = c | ((c2 << 6) & 0xff);
01823             shift = 2;
01824             buf = c2 >> 2;
01825          } else if ( shift == 2 ) {
01826             char c = get();
01827             cbuf[i] = buf | ((c << 4) &  0xff );
01828             buf = c >> 4;
01829             shift = 4;
01830          } else if ( shift == 4 ) {
01831             char c = get();
01832             cbuf[i] = buf | (c << 2 );
01833             shift = 0;
01834          }
01835       }
01836    }
01837    catch ( treadafterend trae ) {
01838       if ( excpt )
01839          throw trae;
01840    }
01841    return i;
01842 }
01843 
01844 
01845 StreamCompressionFilter :: StreamCompressionFilter( tnstream* outputstream )
01846    : adapter( outputstream), compressor( &adapter ), closed(false) {
01847 
01848 }
01849 
01850 void StreamCompressionFilter :: writedata ( const void* buf, int size )
01851 {
01852    compressor.writedata(buf,size);
01853 }
01854 
01855 int StreamCompressionFilter :: readdata  ( void* buf, int size, bool excpt )
01856 {
01857    throw  tinvalidmode ( "StreamCompressionFilter", reading, writing );
01858 }
01859 
01860 void StreamCompressionFilter :: close()
01861 {
01862    if ( closed )
01863       return;
01864 
01865    compressor.close_compression();
01866    closed = true;
01867 }
01868 
01869 StreamCompressionFilter ::~StreamCompressionFilter()
01870 {
01871    close();
01872 }
01873 
01874 
01875 StreamDecompressionFilter  :: StreamDecompressionFilter( tnstream* inputstream ) : adapter( inputstream), decompressor( &adapter ) {
01876 
01877 }
01878 
01879 void StreamDecompressionFilter  :: writedata ( const void* buf, int size )
01880 {
01881    throw  tinvalidmode ( "StreamCompressionFilter", writing, reading );
01882 }
01883 
01884 int StreamDecompressionFilter :: readdata  ( void* buf, int size, bool excpt )
01885 {
01886    return decompressor.readdata(buf,size,excpt);
01887 }
01888 
01890 int    compressrle ( const void* p, void* q)
01891 {
01892    trleheader* sourcehead = (trleheader*) p;
01893    if ( sourcehead->id == 16973 ) {
01894       memcpy ( q, p, sourcehead->size + sizeof ( trleheader ) );
01895       return sourcehead->size + sizeof ( trleheader );
01896    }
01897 
01898 
01899    char* s = (char*) p;
01900    char* d = (char*) q;
01901 
01902    trleheader* header = (trleheader*) q;
01903 
01904    Uint16 x,y;
01905    int size;
01906    {
01907       Uint16* pw = (Uint16*) s;
01908       x = pw[0];
01909       y = pw[1];
01910 
01911       header->x = x;
01912       header->y = y;
01913 
01914       x++;
01915       y++;
01916 
01917       size = x * y;
01918 
01919       header->id = 16973;
01920    }
01921 
01922    {
01923       int bts[256];
01924       memset ( bts, 0, sizeof ( bts ));
01925       for ( int i = 0; i < size ;i++ )
01926          bts[int(s[i+4])]++;
01927 
01928       int min = 70000;
01929       for ( int i = 0; i < 256; i++ )
01930          if ( bts[i] < min ) {
01931             min = bts[i];
01932             header->rle = i;
01933          }
01934 
01935    }
01936 
01937    s+=4;
01938    d+=sizeof ( trleheader );
01939 
01940    {
01941       char* startpos = d;
01942       int xp;
01943 
01944       for (int j = 0; j < y ; j++ ) {
01945          xp = 0;
01946          unsigned char num;
01947          unsigned char actbyte ;
01948 
01949          do {
01950             num = 1;
01951             actbyte = *s;
01952    
01953             while ( xp+num < x   &&   num < 255 && s[num] == actbyte ) 
01954                num++;
01955    
01956             if ( num > 2  ||  actbyte == header->rle ) {
01957                *(d++) = header->rle;
01958                *(d++) = num;
01959                *(d++) = actbyte;
01960             } else {
01961                *(d++) = actbyte;
01962                if ( num > 1 )
01963                   *(d++) = actbyte;
01964             }
01965 
01966             s  += num;   
01967             xp += num;
01968          } while ( xp < x );
01969 
01970 
01971       } /* endfor */
01972 
01973       header->size = d - startpos;
01974    }
01975    return header->size + sizeof ( trleheader );
01976 }
01977 
01979 
01980 
01981 
01982 
01983 bool patimat (const char *pat, const char *str, bool forceCaseInsensitivity )
01984 {
01985    switch (*pat)
01986    {
01987       case '\0':
01988          return !*str;
01989 
01990       case '*' :
01991          return patimat(pat+1, str, forceCaseInsensitivity) || (*str && patimat(pat, str+1, forceCaseInsensitivity));
01992 
01993       case '?' :
01994          return *str && patimat(pat+1, str+1, forceCaseInsensitivity);
01995 
01996       default  :
01997          if ( forceCaseInsensitivity ||
01998 #if CASE_SENSITIVE_FILE_NAMES == 0
01999               true
02000 #else
02001               false
02002 #endif
02003            )
02004             return (toupper(*pat) == toupper(*str)) && patimat(pat+1, str+1, forceCaseInsensitivity);
02005          else
02006             return (*pat == *str) && patimat(pat+1, str+1, forceCaseInsensitivity );
02007       }
02008 }
02009 
02010 bool patimat (const ASCString& pat, const ASCString& str, bool forceCaseInsensitivity)
02011 {
02012    return patimat( pat.c_str(), str.c_str(), forceCaseInsensitivity );
02013 }
02014 
02015 
02016 tfindfile :: tfindfile ( ASCString name, SearchPosition searchPosition, SearchTypes searchTypes )
02017 {
02018    convertPathDelimitters ( name );
02019 
02020    if ( searchPosition == DefaultDir )
02021       searchPosition = AllDirs;
02022 
02023    
02024    if ( searchDirNum == 0 )
02025       searchPosition = CurrentDir;
02026    
02027    found = 0;
02028    act = 0;
02029    if ( name.empty() )
02030       return;
02031 
02032    ASCString directory[maxSearchDirNum];
02033    int dirNum;
02034    ASCString wildcard;
02035 
02036    int ppos = name.rfind ( pathdelimitterstring );
02037    if ( ppos != name.npos ) {
02038       // name contains a directory entry
02039 
02040 
02041       // checking if absolute or relative path
02042       bool absolute = false;
02043       if ( name[0] == pathdelimitter )
02044          absolute = true;
02045 
02046       if ( has_drive_letters && name.length() > 3 && name.find ( ":\\", 1 ) != name.npos )
02047          absolute = true;
02048 
02049       if ( absolute || searchPosition == CurrentDir ) {
02050          directory[0].assign ( name, 0, ppos );
02051          dirNum = 1;
02052       } else {
02053          ASCString strippedPath;
02054          strippedPath.assign ( name, 0, ppos );
02055          if ( strippedPath.find ( ASCString(".") + pathdelimitterstring ) == 0 )
02056             strippedPath.erase( 0, 2);
02057 
02058          int upDir = 0;
02059          while ( strippedPath.find ( ASCString("..") + pathdelimitterstring ) == 0 ) {
02060             upDir++;
02061             strippedPath.erase ( 0, 3 );
02062          }
02063 
02064          int dirsToProcess;
02065          if ( searchPosition == AllDirs ) {
02066             dirsToProcess = searchDirNum;
02067          } else
02068             dirsToProcess = 1;
02069 
02070          dirNum = 0;
02071          for ( int i = 0; i < dirsToProcess; i++ ) {
02072             ASCString dir = ascDirectory[i];
02073 
02074             // removing the trailing pathdelimitterstring
02075             dir.erase ( dir.length() -1 );
02076 
02077             for ( int j = 0; j < upDir; j++ ) {
02078                int pos = dir.rfind ( pathdelimitterstring );
02079                if ( pos > 0 && pos == dir.npos )
02080                   dir.erase ( pos );
02081             }
02082 
02083             // append the trailing pathdelimitterstring again
02084             dir += pathdelimitterstring;
02085 
02086             directory[dirNum++] = dir + strippedPath;
02087          }
02088 
02089          if ( !dirNum  ) {
02090             directory[0] = ".";
02091             dirNum = 1;
02092          }
02093 
02094       }
02095 
02096       wildcard.assign ( name, ppos+1, name.npos );
02097 
02098    } else {
02099       if ( searchDirNum ) {
02100          for (int i = 0; i < searchDirNum; i++ )
02101             directory[i] = ascDirectory[i];
02102          dirNum = searchDirNum;
02103       } else {
02104          directory[0] = ".";
02105          dirNum = 1;
02106       }
02107       wildcard = name;
02108    }
02109 
02110    if ( searchTypes == All || searchTypes == OutsideContainer )
02111       for ( int i = 0; i < dirNum; i++ ) {
02112          DIR *dirp;
02113          struct ASC_direct *direntp;
02114 
02115          dirp = opendir( directory[i].c_str() );
02116          if( dirp != NULL ) {
02117            for(;;) {
02118              direntp = readdir( dirp );
02119              if ( direntp == NULL )
02120                 break;
02121  
02122              if ( patimat ( wildcard.c_str(), direntp->d_name )) {
02123                 int localfound = 0;
02124                 for ( int j = 0; j < found; j++ )
02125                    if ( strcmpi ( fileInfo[j].name.c_str(), direntp->d_name ) == 0 )
02126                       localfound++;
02127 
02128                 if ( !localfound ) {
02129                    FileInfo fi;
02130                    fi.name = direntp->d_name;
02131                    fi.directoryLevel = i ;
02132                    fi.isInContainer = false ;
02133                    fi.location = directory[i];
02134 
02135                    char buf[1000];
02136                    ASCString fullName = constructFileName( buf, i, NULL, direntp->d_name );
02137 
02138                    struct stat statbuf;
02139                    stat( fullName.c_str(), &statbuf);
02140 
02141                    fi.size = statbuf.st_size ;
02142                    fi.date = statbuf.st_mtime;
02143 
02144                    fileInfo.push_back ( fi );
02145 
02146                    found++;
02147                 }
02148              }
02149            }
02150            closedir( dirp );
02151          }
02152       }
02153 
02154 
02155 
02156    if ( searchTypes == All || searchTypes == InsideContainer ) {
02157       const ContainerCollector::FileIndex* c = containercollector.getfirstname();
02158       while ( c ) {
02159           if ( patimat ( name.c_str(), c->name ) ) {
02160              int f = 0;
02161              for ( int i = 0; i < found; i++ )
02162                 if ( stricmp ( c->name.c_str(), fileInfo[i].name.c_str() ) == 0 ) {
02163                    if ( fileInfo[i].directoryLevel <= c->directoryLevel )
02164                       f = 1;
02165                    else {
02166                       FileInfo& fi = fileInfo[i];
02167                       fi.name = c->name ;
02168                       fi.isInContainer = true;
02169                       fi.directoryLevel = c->directoryLevel;
02170                       fi.location = c->container->getDeviceName();
02171 
02172                       fi.size = c->container->getstreamsize();
02173                       fi.date = c->container->get_time();
02174                       f = 1;
02175                    }
02176                 }
02177 
02178              if ( !f ) {
02179                 FileInfo fi;
02180                 fi.name = c->name ;
02181                 fi.directoryLevel = c->directoryLevel ;
02182                 fi.isInContainer = true ;
02183                 fi.location = c->container->getDeviceName() ;
02184 
02185                 fi.size = c->container->getstreamsize() ;
02186                 fi.date = c->container->get_time() ;
02187                 fileInfo.push_back ( fi );
02188                 found++;
02189              }
02190           }
02191           c = containercollector.getnextname();
02192       }
02193    }
02194 }
02195 
02196 
02197 ASCString tfindfile :: getnextname ( int* loc, bool* inContainer, ASCString* location )
02198 {
02199    if ( act < found ) {
02200       if ( loc )
02201          *loc = fileInfo[act].directoryLevel;
02202 
02203       if ( inContainer )
02204          *inContainer = fileInfo[act].isInContainer;
02205 
02206       if ( location )
02207          *location = fileInfo[act].location;
02208 
02209       /*
02210       if ( directoryLevel[act] >= 0 && this->location[act] != ascDirectory[directoryLevel[act]] ) {
02211          ASCString s = this->location[act];
02212          appendbackslash ( s );
02213          s += names[act++];
02214          return s;
02215       } else */
02216          return fileInfo[act++].name;
02217    } else {
02218       if ( loc )
02219          *loc = -1;
02220 
02221       return "";
02222    }
02223 }
02224 
02225 bool tfindfile :: getnextname ( FileInfo& fi )
02226 {
02227    if ( act < found ) {
02228       fi = fileInfo[act++];
02229       return true;
02230    } else
02231       return false;
02232 }
02233 
02234 
02236 
02237 
02238 
02239 
02240 
02241 int checkforvaliddirectory ( char* dir )
02242 {
02243    int stat = 0;
02244 
02245       DIR *dirp; 
02246       struct ASC_direct *direntp; 
02247   
02248 /*      char temp[200];
02249       int l = strlen(dir) - 1;
02250       for (int i = 0; i < l; i++) {
02251          temp[i] = dir[i];
02252       } 
02253       temp[i] = 0;
02254 */
02255       dirp = opendir( dir ); 
02256       if( dirp != NULL ) { 
02257         for(;;) { 
02258           direntp = readdir( dirp ); 
02259           if ( direntp == NULL ) 
02260              break;
02261 
02262           if ( strcmp ( direntp -> d_name, ".") == 0 )
02263              stat = 1;
02264         } 
02265         closedir( dirp ); 
02266       } 
02267 
02268    return stat;
02269 }
02270 
02272 
02273   MemoryStreamStorage :: MemoryStreamStorage ( void )
02274   {
02275      used = 0;
02276      allocated = 0;
02277      buf = 0;
02278      memset ( dummy, 0, sizeof ( dummy ));
02279   }
02280 
02281   MemoryStreamStorage :: ~MemoryStreamStorage ( void )
02282   {
02283      if ( buf ) {
02284         delete[] buf;
02285         buf = NULL;
02286      }
02287   }
02288 
02289   void MemoryStreamStorage :: writetostream ( tnstream* stream )
02290   {
02291      if ( stream ) {
02292         stream->writeInt ( 0 );
02293         stream->writeInt ( used );
02294         stream->writeInt ( allocated );
02295         for ( int i = 0; i < 10; i++ )
02296            stream->writeInt ( dummy[i] );
02297         if ( used > 0 )
02298            stream->writedata ( buf, used );
02299      }
02300   }
02301 
02302   void MemoryStreamStorage :: readfromstream ( tnstream* stream )
02303   {
02304      if ( stream ) {
02305         stream->readInt();
02306         used        = stream->readInt();
02307         allocated   = stream->readInt();
02308         for ( int i = 0; i< 10; i++ )
02309            dummy[i] = stream->readInt();
02310 
02311         if ( buf ) {
02312            delete[] buf;
02313            buf = NULL;
02314         }
02315         if ( used > 0 || allocated > 0 ) {
02316            allocated = max(allocated,used);
02317            buf = new char[allocated];
02318            stream->readdata ( buf, used );
02319         }
02320      }
02321   }
02322 
02323 
02324 MemoryStream :: MemoryStream ( MemoryStreamStorage* lbuf, IOMode lmode )
02325 {
02326 
02327    blocksize = 1024;
02328    buf = lbuf;
02329    _mode = lmode;
02330 
02331    if ( !buf )
02332       throw tfileerror ( "memorystream" );
02333 
02334 
02335    if ( _mode == reading ) {
02336       pointer = buf->buf;
02337       actmempos = 0;
02338    } else
02339    if ( _mode == writing ) {     // neuen Puffer anlegen
02340       if ( buf->buf ) {
02341          delete[] buf->buf;
02342          buf->buf = NULL;
02343       }
02344       buf->buf = new char[blocksize];
02345       buf->allocated = blocksize;
02346       buf->used = 0;
02347       pointer = buf->buf;
02348       actmempos = 0;
02349    }
02350    if ( _mode == appending ) {
02351       pointer = buf->buf;
02352       actmempos = buf->used;
02353       _mode = writing;
02354    }
02355 }
02356 
02357 void MemoryStream :: writedata ( const void* nbuf, int size )
02358 {
02359    if ( _mode != writing )
02360       throw tinvalidmode ( "memorystream", _mode, writing );
02361 
02362    if ( buf->used + size > buf->allocated ) {
02363       int newsize = ((buf->used + size + blocksize - 1) / blocksize);
02364       newsize *= blocksize;
02365       char* tmp = new char[newsize];
02366       memcpy ( tmp, buf->buf, buf->used );
02367       delete[] buf->buf;
02368       buf->buf = tmp;
02369       buf->allocated = newsize;
02370    }
02371 
02372    memcpy ( &buf->buf[buf->used], nbuf, size );
02373    buf->used += size;
02374 }   
02375 
02376 
02377 int  MemoryStream :: readdata ( void* nbuf, int size, bool excpt  )
02378 {
02379    if (_mode != reading )
02380       throw  tinvalidmode ( "memorystream", _mode, reading );
02381       
02382    if ( actmempos + size > buf->used ) {
02383       if ( excpt )
02384          throw treadafterend ( "memory stream" );
02385       else
02386          size = buf->used-actmempos;
02387    }
02388 
02389    memcpy ( nbuf, &buf->buf[actmempos], size );
02390    actmempos += size;
02391    return size;
02392 }
02393 
02394 int MemoryStream :: dataavail ( void )
02395 {
02396    if ( _mode == writing )
02397       return 1;
02398    else
02399       return actmempos < buf->used;
02400 }
02401 
02402 
02403 
02404 ASCString getnextfilenumname ( const ASCString& first, const ASCString& suffix, int num )
02405 {
02406    ASCString name;
02407    
02408    if ( num < 0 )
02409      num = 0;
02410 
02411    do {
02412       name = first;
02413       while ( name.length() - first.length() + ASCString::toString(num).length() < 3 )
02414          name += "0";
02415 
02416       name += ASCString::toString(num) + "." + suffix;
02417 
02418       tfindfile ff ( name );
02419       ASCString c = ff.getnextname();
02420       if ( c.empty() )
02421          return name;
02422       
02423       num++;
02424    } while ( true ); 
02425 
02426    return "";
02427 }
02428 
02429 
02430 bool exist ( const ASCString& s )
02431 {
02432    tfindfile ff ( s );
02433    return !ff.getnextname().empty();
02434 }
02435 
02436 
02437 
02438 #include "oldlzw.cpp"
02439 
02440 void  tnbufstream :: writebuffer( void ) {
02441 }
02442 
02443 void opencontainer ( const char* wildcard )
02444 {
02445    if ( !searchDirNum )
02446       addSearchPath(".");
02447 
02448    containercollector.init ( wildcard );
02449 }
02450 
02451 
02452 
02453 
02454 time_t get_filetime ( const char* fileName )
02455 {
02456    FileLocation fl;
02457    locateFile ( fileName, &fl );
02458 
02459    if ( fl.found ) {
02460      if ( fl.container )
02461         return fl.container->get_time();
02462      else {
02463         struct stat stbuf;
02464         char buf[ maxFileStringSize ];
02465         if ( !stat ( constructFileName ( buf, fl.directoryLevel, NULL, fileName), &stbuf) )
02466            return ( stbuf.st_mtime);
02467         else
02468            return -1;
02469      }
02470    } else
02471       return -1;
02472 }
02473 
02474 
02475 int filesize( const char *name)
02476 {
02477   struct stat buf;
02478 
02479   if ( !stat (name, &buf))
02480      return (buf.st_size);
02481   else
02482      return -1;
02483 }
02484 
02485 
02486 bool directoryExist ( const ASCString& path )
02487 {
02488    bool existence = false;
02489 
02490    DIR *dirp = opendir( path.c_str() );
02491 
02492    if( dirp ) {
02493       if ( readdir( dirp ) )
02494          existence = true;
02495       else
02496          existence = false;
02497 
02498       closedir( dirp );
02499    }
02500    return existence;
02501 }
02502 
02503 void addSearchPath ( const ASCString& path )
02504 {
02505    if ( !path.empty() ) {
02506       ASCString s = constructFileName ( -3, path, "" );
02507 
02508       if ( directoryExist( s.c_str() )) {
02509          bool found = false;
02510          for ( int i = 0; i < searchDirNum; i++ )
02511             if ( s == ascDirectory[i] )
02512                found = true;
02513    
02514          if ( !found )
02515             ascDirectory[ searchDirNum++ ] = strdup ( s.c_str() );
02516       }
02517    }
02518 }
02519 
02520 int getSearchPathNum()
02521 {
02522    return searchDirNum;
02523 }
02524 
02525 ASCString getSearchPath ( int i )
02526 {
02527    if ( i < searchDirNum )
02528       return ascDirectory[i];
02529    else
02530       return "";
02531 }
02532 
02533 
02534 char* extractPath ( char* buf, const char* filename )
02535 {
02536    if ( buf && filename ) {
02537       if ( strchr ( filename, pathdelimitter )) {
02538          strcpy ( buf, filename );
02539          int i = strlen ( buf )-1;
02540          while ( buf[i] != pathdelimitter )
02541             i--;
02542 
02543          buf[i+1] = 0;
02544       } else
02545          strcpy ( buf, "./" );
02546    }
02547    return buf;
02548 }
02549 
02550 char* extractFileName ( char* buf, const char* filename )
02551 {
02552    if ( buf && filename ) {
02553       if ( strchr ( filename, pathdelimitter )) {
02554          int i = strlen ( filename )-1;
02555          while ( filename[i] != pathdelimitter )
02556             i--;
02557 
02558          strcpy ( buf, filename +i+1);
02559       } else
02560          strcpy ( buf, filename );
02561    }
02562    return buf;
02563 }
02564 
02565 ASCString extractFileName ( const ASCString& filename )
02566 {
02567    char buf[10000];
02568    return extractFileName( buf, filename.c_str() );
02569 }
02570 
02571 ASCString extractFileName_withoutSuffix ( const ASCString& filename )
02572 {
02573    char buf[10000];
02574    extractFileName( buf, filename.c_str() );
02575    char* c = strchr ( buf, '.' );
02576    if ( c )
02577       *c = 0;
02578    return ASCString(buf);
02579 }
02580 
02581 
02582 void appendbackslash ( char* string )
02583 {
02584    if ( strlen ( string ) && string[strlen ( string ) -1] != pathdelimitter )
02585       strcat ( string, pathdelimitterstring );
02586 }
02587 
02588 void appendbackslash ( ASCString& string )
02589 {
02590    if ( !string.empty()  && string[ string.length() -1] != pathdelimitter )
02591       string += pathdelimitterstring ;
02592 }
02593 
02594 
02595 int createDirectory ( const char* name )
02596 {
02597    #ifdef _UNIX_
02598     char *nname;
02599     int i;
02600 
02601     if (name == NULL || (nname=strdup(name)) == NULL)
02602         return -1;
02603     i = strlen(nname);
02604     /* leave one '/' */
02605     while (i>1 && nname[i-1] == '/')
02606                 nname[--i] = '\0';
02607     i = mkdir ( nname, 0700 );
02608     free(nname);
02609 
02610     return i;
02611    #else
02612     return mkdir ( name );
02613    #endif
02614 }
02615 
02616 
02617 ASCString FileName::suffix ( )
02618 {
02619    size_type slash = find_last_of ( pathdelimitterstring );
02620    size_type point = find_last_of ( "." );
02621    if ( point == npos )
02622       return "";
02623    else
02624       if ( slash == npos || slash < point )
02625          return substr(point+1);
02626       else
02627          return "";
02628 }
02629 
02630 
02631 
02632 void convertPathDelimitters ( ASCString& path )
02633 {
02634    int pos;
02635    while ( (pos = path.find ( foreignPathDelimitterString )) != path.npos )
02636       path.replace ( pos, 1, pathdelimitterstring );
02637 }

Generated on Mon May 21 01:26:28 2012 for Advanced Strategic Command by  doxygen 1.5.1