00001
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
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
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
00147
00148
00149
00150
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);
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) );
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
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 );
00408
00409 } while (*pch2 != 0 && actpos2 < maxav );
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 );
00419 } while ( temp );
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 );
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 );
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 );
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 );
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 );
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 );
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
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];
00843
00844 dynamic_array<pncontainerstream> container;
00845 int containernum;
00846 struct {
00847 int alpha;
00848 int index;
00849 } namesearch;
00850 public:
00851 ContainerCollector ( void );
00852 void init ( const char* wildcard );
00853 void addfile ( const char* filename, const pncontainerstream stream, int directoryLevel );
00854
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
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
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
00897
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
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 }
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
01335
01336
01337
01338
01339
01340
01341
01342
01343
01344
01345
01346
01347
01348
01349
01350
01351
01352
01353
01354
01355
01356
01357
01358
01359
01360
01361
01362
01363
01364
01365
01366
01367
01368
01369
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 }
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
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 }
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
01503
01504
01505
01506
01507
01508
01509
01510
01511
01512
01513
01514
01515
01516
01517
01518
01519
01520
01521
01522
01523
01524
01525
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 }
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
01832
01833
01834
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
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
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(;;)