PageRenderTime 60ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 1ms

/source/basestrm.cpp

https://bitbucket.org/val_haris/asc-ai
C++ | 2637 lines | 2066 code | 447 blank | 124 comment | 314 complexity | 44da3823258597314dfaa504bb4958ab MD5 | raw file
Possible License(s): AGPL-1.0, GPL-2.0
  1. /*! \file basestrm.cpp
  2. \brief The various streams that ASC offers, like file and memory streams.
  3. */
  4. /*
  5. This file is part of Advanced Strategic Command; http://www.asc-hq.de
  6. Copyright (C) 1994-2010 Martin Bickel and Marc Schellenberger
  7. This program is free software; you can redistribute it and/or modify
  8. it under the terms of the GNU General Public License as published by
  9. the Free Software Foundation; either version 2 of the License, or
  10. (at your option) any later version.
  11. This program is distributed in the hope that it will be useful,
  12. but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. GNU General Public License for more details.
  15. You should have received a copy of the GNU General Public License
  16. along with this program; see the file COPYING. If not, write to the
  17. Free Software Foundation, Inc., 59 Temple Place, Suite 330,
  18. Boston, MA 02111-1307 USA
  19. */
  20. #include <stdio.h>
  21. #include <ctype.h>
  22. #include <cstdlib>
  23. #include <stdlib.h>
  24. #include <string>
  25. #include <list>
  26. #include "global.h"
  27. #ifdef HAVE_LIMITS
  28. #include <limits>
  29. #endif
  30. #include <sys/stat.h>
  31. #include <bzlib.h>
  32. #include "global.h"
  33. #include "basestrm.h"
  34. #ifdef _DOS_
  35. #include "dos/fileio.h"
  36. #else
  37. #ifdef _WIN32_
  38. #include "win32/fileio.h"
  39. #else
  40. #ifdef _UNIX_
  41. #include "unix/fileio.h"
  42. #endif
  43. #endif
  44. #endif
  45. //#include sdlheader
  46. #include <SDL_endian.h>
  47. #include "util/messaginghub.h"
  48. const int maxSearchDirNum = 30;
  49. int searchDirNum = 0;
  50. char* ascDirectory[maxSearchDirNum] = { NULL, NULL, NULL, NULL, NULL,
  51. NULL, NULL, NULL, NULL, NULL };
  52. #pragma pack(1)
  53. struct trleheader {
  54. unsigned short int id;
  55. unsigned short int size;
  56. char rle;
  57. unsigned short int x;
  58. unsigned short int y;
  59. };
  60. #pragma pack()
  61. #define bzip_xor_byte 'M'
  62. const char* containermagic = "NCBM";
  63. const char* LZ_SIGNATURE = "MBLZW16";
  64. const char* RLE_SIGNATURE = "MBRLE1";
  65. const char* BZIP_SIGNATURE = "MBZLB2X!";
  66. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  67. //////////// Watchpointer
  68. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  69. CharBuf :: CharBuf ( void )
  70. {
  71. size = 0;
  72. buf = NULL;
  73. }
  74. CharBuf :: CharBuf ( int _size )
  75. {
  76. size = _size;
  77. buf = new char[ size ];
  78. }
  79. void CharBuf :: resize ( int newsize )
  80. {
  81. char* nb = new char[newsize];
  82. for ( int i = 0; i < size; i++ )
  83. nb[i] = buf[i];
  84. delete[] buf;
  85. buf = nb;
  86. }
  87. CharBuf :: ~CharBuf()
  88. {
  89. if ( buf )
  90. delete[] buf;
  91. buf = NULL;
  92. }
  93. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  94. //////////// Exceptions
  95. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  96. OutOfMemoryError::OutOfMemoryError ( int m )
  97. {
  98. required = m;
  99. }
  100. tfileerror::tfileerror ( const ASCString& fileName )
  101. {
  102. _filename = fileName ;
  103. }
  104. tinvalidmode :: tinvalidmode ( const ASCString& _fileName, tnstream::IOMode org_mode, tnstream::IOMode requested_mode )
  105. : tfileerror ( _fileName )
  106. {
  107. orgmode = org_mode;
  108. requestmode = requested_mode;
  109. }
  110. treadafterend :: treadafterend ( const ASCString& _fileName )
  111. : tfileerror ( _fileName )
  112. {
  113. }
  114. tinternalerror::tinternalerror ( const char* filename, int l )
  115. {
  116. linenum = l;
  117. sourcefilename = filename;
  118. }
  119. tinvalidversion :: tinvalidversion ( const ASCString& _fileName, int ex, int fnd )
  120. : tfileerror ( _fileName ), expected ( ex ), found ( fnd )
  121. {
  122. }
  123. ASCString tinvalidversion :: getMessage() const
  124. {
  125. ASCString s;
  126. if ( expected < found )
  127. 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 );
  128. else
  129. 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 );
  130. return s;
  131. }
  132. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  133. //////////// Streams
  134. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  135. tnstream :: tnstream ( void )
  136. : devicename ( "-abstract tnstream-" ) {}
  137. void tnstream::seek ( int pos )
  138. {
  139. throw tfileerror ( "Seeking not supported for stream " + getDeviceName() );
  140. }
  141. void tnstream::readrlepict( void** pnter, bool allocated, int* size)
  142. {
  143. trleheader hd;
  144. int w;
  145. char* q;
  146. hd.id = readWord();
  147. hd.size = readWord();
  148. hd.rle = readChar();
  149. hd.x = readWord();
  150. hd.y = readWord();
  151. if (hd.id == 16973) {
  152. if (!allocated)
  153. *pnter = new char [ hd.size + sizeof(hd) ];
  154. memcpy( *pnter, &hd, sizeof(hd));
  155. q = (char*) (*pnter) + sizeof(hd);
  156. readdata( q, hd.size); // endian ok ?
  157. *size = hd.size + sizeof(hd);
  158. }
  159. else {
  160. w = (hd.id + 1) * (hd.size + 1) + 4 ;
  161. if (!allocated)
  162. *pnter = new char [ w ];
  163. memcpy ( *pnter, &hd, sizeof ( hd ));
  164. q = (char*) (*pnter) + sizeof(hd);
  165. readdata ( q, w - sizeof(hd) ); // endian ok ?
  166. *size = w;
  167. }
  168. }
  169. void tnstream :: writerlepict ( const void* buf )
  170. {
  171. writeImage( buf, true );
  172. }
  173. void tnstream :: writeImage ( const void* buf, bool compress )
  174. {
  175. if ( compress ) {
  176. char* tempbuf = new char [ 0xffff ];
  177. if ( tempbuf ) {
  178. int size = compressrle ( buf, tempbuf );
  179. trleheader* hd = (trleheader*) tempbuf;
  180. writeWord( hd->id );
  181. writeWord( hd->size );
  182. writeChar( hd->rle );
  183. writeWord( hd->x );
  184. writeWord( hd->y );
  185. writedata ( hd+1, size - sizeof(*hd) );
  186. delete[] tempbuf;
  187. } else
  188. compress = false;
  189. }
  190. if ( !compress ) {
  191. Uint16* pw = (Uint16*) buf;
  192. writeWord(pw[0] );
  193. writeWord(pw[1] );
  194. writedata ( pw+2, ( pw[0] + 1 ) * ( pw[1] + 1 ) );
  195. }
  196. }
  197. ASCString tnstream::getDeviceName()
  198. {
  199. return devicename;
  200. }
  201. ASCString tnstream::getLocation()
  202. {
  203. return devicename;
  204. }
  205. ASCString tnstream::getArchive()
  206. {
  207. return "";
  208. }
  209. int tnstream::readInt ( void )
  210. {
  211. int i;
  212. readdata2 ( i );
  213. return SDL_SwapLE32( i );
  214. }
  215. int tnstream::readWord ( void )
  216. {
  217. Uint16 w;
  218. readdata2 ( w );
  219. return SDL_SwapLE16( w );
  220. }
  221. char tnstream::readChar ( void )
  222. {
  223. char c;
  224. readdata2 ( c );
  225. return c;
  226. }
  227. float SwapFloat( float f )
  228. {
  229. union
  230. {
  231. float f;
  232. unsigned char b[4];
  233. } dat1, dat2;
  234. dat1.f = f;
  235. dat2.b[0] = dat1.b[3];
  236. dat2.b[1] = dat1.b[2];
  237. dat2.b[2] = dat1.b[1];
  238. dat2.b[3] = dat1.b[0];
  239. return dat2.f;
  240. }
  241. float tnstream::readFloat ( void )
  242. {
  243. float c;
  244. readdata2 ( c );
  245. #if SDL_BYTEORDER == SDL_BIG_ENDIAN
  246. c = SwapFloat(c);
  247. #endif
  248. return c;
  249. }
  250. #if SIZE_T_not_identical_to_INT
  251. void tnstream::writeInt ( size_t i )
  252. {
  253. #ifdef HAVE_LIMITS
  254. // assert( i <= numeric_limits<int>::max());
  255. #endif
  256. writeInt( int(i) );
  257. }
  258. #endif
  259. void tnstream::writeInt ( unsigned int i )
  260. {
  261. i = SDL_SwapLE32(i);
  262. writedata2 ( i );
  263. }
  264. void tnstream::writeInt ( bool b )
  265. {
  266. int i = b;
  267. i = SDL_SwapLE32(i);
  268. writedata2 ( i );
  269. }
  270. void tnstream::writeInt ( int i )
  271. {
  272. i = SDL_SwapLE32(i);
  273. writedata2 ( i );
  274. }
  275. void tnstream::writeWord ( int w )
  276. {
  277. Uint16 w2 = SDL_SwapLE16( Uint16(w) );
  278. writedata2 ( w2 );
  279. }
  280. void tnstream::writeChar ( char c )
  281. {
  282. writedata2 ( c );
  283. }
  284. void tnstream::writeFloat ( float f )
  285. {
  286. writedata2 ( f );
  287. }
  288. void tnstream::readpchar(char** pc, int maxlength )
  289. {
  290. int actpos2 = 0;
  291. int maxav = 100000;
  292. if ( maxlength )
  293. if ( maxav > maxlength )
  294. maxav = maxlength;
  295. CharBuf charbuf ( maxav );
  296. maxav--;
  297. char* pch2 = charbuf.buf;
  298. int loop = 0;
  299. do {
  300. actpos2++;
  301. if ( loop )
  302. pch2++;
  303. loop++;
  304. readdata( pch2, 1 ); // endian ok !
  305. } while (*pch2 != 0 && actpos2 < maxav ); /* enddo */
  306. if ( actpos2 >= maxav ) {
  307. pch2[1] = 0;
  308. actpos2++;
  309. if ( pch2[0] ) {
  310. char temp;
  311. do {
  312. readdata( &temp, 1 ); // endian ok !
  313. } while ( temp ); /* enddo */
  314. }
  315. }
  316. pch2 = new char [ actpos2 ];
  317. memcpy ( pch2, charbuf.buf, actpos2 );
  318. *pc = pch2;
  319. }
  320. void tnstream::readpnchar(char** pc, int maxlength )
  321. {
  322. int actpos2 = 0;
  323. int maxav = 10000;
  324. if ( maxlength )
  325. if ( maxav > maxlength )
  326. maxav = maxlength;
  327. CharBuf charbuf ( maxav );
  328. maxav--;
  329. char* pch2 = charbuf.buf;
  330. int ende = 0;
  331. do {
  332. char bt;
  333. int red = readdata( &bt, 1, 0 );
  334. if ( red < 1 ) {
  335. ende = 2;
  336. *pch2 = 0;
  337. } else
  338. if ( bt == '\n' || bt == 0 ) {
  339. *pch2 = 0;
  340. ende = 1;
  341. } else
  342. if ( bt != '\r' ) {
  343. *pch2 = bt;
  344. pch2++;
  345. actpos2++;
  346. }
  347. } while ( !ende && actpos2 < maxav ); /* enddo */
  348. if ( !ende ) {
  349. if ( actpos2 >= maxav ) {
  350. *pch2 = 0;
  351. if ( pch2[0] ) {
  352. char temp;
  353. do {
  354. int red = readdata( &temp, 1, 0 );
  355. if ( red < 1 ) {
  356. temp = 0;
  357. } else
  358. if ( temp == '\n' )
  359. temp = 0;
  360. } while ( temp ); /* enddo */
  361. }
  362. }
  363. }
  364. if ( ende == 2 ) {
  365. if ( !actpos2 )
  366. *pc = NULL;
  367. else
  368. *pc = strdup ( charbuf.buf );
  369. } else
  370. *pc = strdup ( charbuf.buf );
  371. }
  372. bool tnstream::readTextString ( ASCString& s, bool includeCR )
  373. {
  374. s = "";
  375. char c;
  376. int red;
  377. int end = 0;
  378. do {
  379. red = readdata( &c, 1, 0 ); // endian ok !
  380. if ( red < 1 ) {
  381. end = 2;
  382. } else
  383. if ( (c == '\n' && !includeCR) || c == 0 ) {
  384. end = 1;
  385. } else
  386. if ( c != '\r' )
  387. s += c;
  388. } while ( red && !end );
  389. if ( end == 2)
  390. return false;
  391. else
  392. return true;
  393. }
  394. ASCString tnstream::readString ( bool includeCR )
  395. {
  396. ASCString s;
  397. bool data = readTextString ( s, includeCR );
  398. if ( !data && s.empty() )
  399. throw treadafterend ( getLocation() );
  400. return s;
  401. }
  402. void tnstream::writeString(const string& pc, bool binary )
  403. {
  404. if ( binary )
  405. writepchar ( pc.c_str() );
  406. else
  407. writedata ( pc.data(), pc.length() );
  408. }
  409. void tnstream::writepchar(const char* pc)
  410. {
  411. if ( pc ) {
  412. const char *pch1 = pc;
  413. int loop = 0;
  414. do {
  415. if ( loop )
  416. pch1++;
  417. writedata( pch1, 1 );
  418. loop++;
  419. } while ( *pch1 > 0 ); /* enddo */
  420. } else {
  421. char pch1 = 0;
  422. writedata ( &pch1, 1 );
  423. }
  424. }
  425. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  426. MemoryStreamCopy :: MemoryStreamCopy ( tnstream* stream )
  427. {
  428. buf = NULL;
  429. int bufused = 0;
  430. int memreserved = 0;
  431. int blocksize = 500000;
  432. int red;
  433. do {
  434. if ( bufused + blocksize > memreserved ) {
  435. int newsize = memreserved + blocksize;
  436. void* newbuf = malloc (newsize);
  437. if ( buf ) {
  438. memcpy ( newbuf, buf, bufused );
  439. free ( buf );
  440. }
  441. buf = newbuf;
  442. memreserved = newsize;
  443. }
  444. char* cp = (char*) buf;
  445. red = stream->readdata ( cp + bufused, blocksize, 0 ); // endian ok !
  446. bufused += red;
  447. } while ( red == blocksize );
  448. size = bufused;
  449. pos = 0;
  450. devicename = stream->getDeviceName();
  451. }
  452. ASCString MemoryStreamCopy::getLocation()
  453. {
  454. return devicename + " (memory buffered)";
  455. }
  456. MemoryStreamCopy :: ~MemoryStreamCopy ( )
  457. {
  458. if ( buf )
  459. free ( buf );
  460. }
  461. void MemoryStreamCopy :: writedata ( const void* buf, int size )
  462. {
  463. throw tinvalidmode ( getDeviceName(), reading, writing );
  464. }
  465. int MemoryStreamCopy :: readdata ( void* buffer, int _size, bool excpt )
  466. {
  467. char* cp = (char*) buf;
  468. if ( pos + _size > size ) {
  469. if ( excpt )
  470. throw treadafterend ( getDeviceName() );
  471. else {
  472. int tr = size-pos;
  473. memcpy ( buffer, cp+pos, tr );
  474. pos += tr;
  475. return tr;
  476. }
  477. } else {
  478. memcpy ( buffer, cp+pos, _size );
  479. pos += _size;
  480. return _size;
  481. }
  482. }
  483. void MemoryStreamCopy :: seek ( int newpos )
  484. {
  485. if ( newpos > size || newpos < 0 )
  486. throw treadafterend ( getDeviceName() );
  487. pos = newpos;
  488. }
  489. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  490. static int stream_seek( struct SDL_RWops *context, int offset, int whence)
  491. {
  492. MemoryStreamCopy* stream = (MemoryStreamCopy*) context->hidden.unknown.data1;
  493. if ( whence == SEEK_SET )
  494. stream->seek ( offset );
  495. else
  496. if ( whence == SEEK_CUR )
  497. stream->seek ( offset + stream->getPosition() );
  498. else
  499. if ( whence == SEEK_END )
  500. stream->seek ( offset + stream->getSize() );
  501. return stream->getPosition();
  502. }
  503. static int stream_read(SDL_RWops *context, void *ptr, int size, int maxnum)
  504. {
  505. MemoryStreamCopy* stream = (MemoryStreamCopy*) context->hidden.unknown.data1;
  506. size_t nread = stream->readdata ( ptr, size * maxnum, 0 );
  507. return(nread / size);
  508. }
  509. static int stream_close(SDL_RWops *context)
  510. {
  511. if ( context ) {
  512. if ( context->hidden.unknown.data1 ) {
  513. MemoryStreamCopy* stream = (MemoryStreamCopy*) context->hidden.unknown.data1;
  514. delete stream;
  515. }
  516. SDL_FreeRW(context);
  517. }
  518. return(0);
  519. }
  520. SDL_RWops *SDL_RWFromStream( tnstream* stream )
  521. {
  522. MemoryStreamCopy* msb = new MemoryStreamCopy ( stream );
  523. SDL_RWops *rwops;
  524. rwops = SDL_AllocRW();
  525. if ( rwops != NULL ) {
  526. rwops->seek = stream_seek;
  527. rwops->read = stream_read;
  528. rwops->write = NULL;
  529. rwops->close = stream_close;
  530. rwops->hidden.unknown.data1 = msb;
  531. }
  532. return(rwops);
  533. }
  534. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  535. tncontainerstream :: tncontainerstream ( const char* containerfilename, ContainerIndexer* indexer, int dirLevel )
  536. : tn_file_buf_stream ( containerfilename, reading ), index(NULL)
  537. {
  538. num = 0;
  539. char magic[4];
  540. readdata ( &magic, 4 ); // endian ok !
  541. if ( strncmp ( magic, containermagic, 4 ) == 0) {
  542. int pos = readInt();
  543. seek ( pos );
  544. num = readInt();
  545. index = new tcontainerindex[num];
  546. for ( int i = 0; i < num; i++ ) {
  547. bool __loadName = readInt();
  548. index[i].start = readInt();
  549. index[i].end = readInt();
  550. if ( __loadName ) {
  551. readpchar ( &index[i].name );
  552. #if CASE_SENSITIVE_FILE_NAMES == 1
  553. // quick hack to be able to use existing CON files.
  554. char *c = index[i].name;
  555. while ( *c ) {
  556. *c = tolower( *c );
  557. c++;
  558. }
  559. #endif
  560. indexer->addfile ( index[i].name, this, dirLevel );
  561. } else
  562. index[i].name = NULL;
  563. }
  564. }
  565. actfile = NULL;
  566. containerfilepos = 0;
  567. }
  568. int tncontainerstream :: getcontainerfilesize ( const char* name )
  569. {
  570. int i = 0;
  571. while ( i < num && stricmp ( index[i].name, name ) )
  572. i++;
  573. if ( i >= num )
  574. return -1;
  575. else
  576. return index[i].end - index[i].start + 1;
  577. }
  578. void tncontainerstream :: opencontainerfile ( const char* name )
  579. {
  580. if ( actfile ) {
  581. ASCString err = ASCString("two files simultaneously: ") + actfile->name + " and " + name;
  582. throw tfileerror ( err );
  583. }
  584. containerfilepos = 0;
  585. int i = 0;
  586. while ( i < num && stricmp ( index[i].name, name ) )
  587. i++;
  588. if ( i >= num )
  589. throw tfileerror ( name );
  590. displayLogMessage( 9, ASCString("opencontainerfile ") + name );
  591. containerfilepos = 0;
  592. seek ( index[i].start );
  593. actfile = &index[i];
  594. }
  595. int tncontainerstream :: readcontainerdata ( void* buf, int size, bool excpt )
  596. {
  597. if ( actfile->start + containerfilepos + size > actfile->end+1 ) {
  598. if ( excpt )
  599. throw treadafterend ( actfile->name );
  600. else {
  601. int got = readdata ( buf, (actfile->end+1 - actfile->start) - containerfilepos , excpt );
  602. containerfilepos+=got;
  603. return got;
  604. }
  605. }
  606. readdata ( buf, size );
  607. containerfilepos+=size;
  608. return size;
  609. }
  610. void tncontainerstream :: closecontainerfile ( void )
  611. {
  612. actfile = NULL;
  613. }
  614. char* tncontainerstream :: getfirstname ( void )
  615. {
  616. actname = 0;
  617. return getnextname();
  618. }
  619. char* tncontainerstream :: getnextname ( void )
  620. {
  621. if ( actname < num )
  622. return index[actname++].name;
  623. else
  624. return NULL;
  625. }
  626. tncontainerstream :: ~tncontainerstream ()
  627. {
  628. for ( int i = 0; i < num; i++ )
  629. if ( index[i].name )
  630. delete[] index[i].name;
  631. delete[] index;
  632. }
  633. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  634. class ContainerCollector : public ContainerIndexer {
  635. public:
  636. struct FileIndex {
  637. ASCString name;
  638. pncontainerstream container;
  639. int directoryLevel;
  640. };
  641. protected:
  642. dynamic_array<FileIndex> index[256]; // not very efficient, but who cares :-)
  643. dynamic_array<pncontainerstream> container;
  644. int containernum;
  645. struct {
  646. int alpha;
  647. int index;
  648. } namesearch; // next entry to return
  649. public:
  650. ContainerCollector ( void );
  651. void init ( const char* wildcard );
  652. void addfile ( const char* filename, const pncontainerstream stream, int directoryLevel );
  653. // pncontainerstream getfile ( const char* filename );
  654. FileIndex* getfile ( const ASCString& filename );
  655. FileIndex* getfirstname ( void );
  656. FileIndex* getnextname ( void );
  657. ASCString listContainer();
  658. virtual ~ContainerCollector();
  659. };
  660. ContainerCollector containercollector;
  661. char* constructFileName( char* buf, int directoryLevel, const char* path, const char* filename )
  662. {
  663. if ( buf ) {
  664. const char* filename2 = filename;
  665. buf[0] = 0;
  666. // filenames beginning with / or ~/ have an absolute path ; ignore variable path for them
  667. if ( ! (filename && (filename[0] == pathdelimitter || (filename[0]=='~' && filename[1] == pathdelimitter)) )) {
  668. if ( path )
  669. strcpy ( buf, path);
  670. else
  671. if ( directoryLevel >= 0 && ascDirectory[ directoryLevel ] )
  672. strcpy ( buf, ascDirectory[ directoryLevel ]);
  673. }
  674. appendbackslash ( buf );
  675. if ( filename && strchr ( filename, pathdelimitter )) {
  676. char name2[ maxFileStringSize ];
  677. // filename contains directories
  678. strcpy ( name2, filename );
  679. int i = strlen ( name2 )-1;
  680. while ( name2[i] != pathdelimitter )
  681. i--;
  682. name2[i+1] = 0;
  683. filename2 = &filename[i+1];
  684. // filename2 is now the pure filename without directory
  685. // name2 is the directory
  686. if ( buf[0] && name2[0]==pathdelimitter )
  687. strcpy ( buf, name2+1);
  688. else
  689. strcpy ( buf, name2);
  690. }
  691. if ( buf[0] == '~' && buf[1] == pathdelimitter ) {
  692. char* home = getenv ( "HOME" );
  693. if ( home ) {
  694. char temp[ maxFileStringSize ];
  695. strcpy ( temp, buf );
  696. strcpy ( buf, home );
  697. appendbackslash ( buf );
  698. strcat ( buf, &temp[2]);
  699. }
  700. }
  701. appendbackslash ( buf );
  702. if ( filename2 )
  703. strcat ( buf, filename2 );
  704. }
  705. return buf;
  706. }
  707. bool isPathRelative( const ASCString& path )
  708. {
  709. if ( path.length() < 2 )
  710. return true;
  711. if ( path[0] == '~' && path[1] == pathdelimitter )
  712. return false;
  713. #ifdef WIN32
  714. if ( path[1] == ':' && path[2] == pathdelimitter )
  715. return false;
  716. #endif
  717. if ( path[0] == pathdelimitter )
  718. return false;
  719. return true;
  720. }
  721. ASCString constructFileName( int directoryLevel, const ASCString& path, ASCString filename )
  722. {
  723. ASCString result;
  724. // filenames beginning with / or ~/ have an absolute path ; ignore variable path for them
  725. if ( isPathRelative( filename )) {
  726. if ( !path.empty() )
  727. result += path;
  728. else
  729. if ( directoryLevel >= 0 && ascDirectory[ directoryLevel ] )
  730. result += ascDirectory[ directoryLevel ];
  731. }
  732. appendbackslash ( result );
  733. if ( !filename.empty() && filename.find( pathdelimitter )!= ASCString::npos ) {
  734. ASCString dir = filename;
  735. dir.erase( dir.rfind( pathdelimitter ) + 1);
  736. filename.erase( 0, filename.find( pathdelimitter ) + 1 );
  737. if ( dir.find( pathdelimitter ) == 0 )
  738. dir.erase( 0, 1 );
  739. result = dir;
  740. }
  741. if ( result.length() > 2 && result[0] == '~' && result[1] == pathdelimitter ) {
  742. char* home = getenv ( "HOME" );
  743. if ( home ) {
  744. ASCString temp = result;
  745. result = home;
  746. appendbackslash ( result );
  747. result += temp.substr( 2 );
  748. }
  749. }
  750. appendbackslash ( result );
  751. result += filename;
  752. return result;
  753. }
  754. struct FileLocation {
  755. int directoryLevel;
  756. pncontainerstream container;
  757. int found;
  758. };
  759. void locateFile ( const ASCString& filename, FileLocation* loc )
  760. {
  761. loc->found = 0;
  762. ContainerCollector::FileIndex* idx = containercollector.getfile ( filename );
  763. int maxnum;
  764. if ( idx ) {
  765. maxnum = idx->directoryLevel+1;
  766. loc->directoryLevel = idx->directoryLevel;
  767. loc->found = 1;
  768. loc->container = idx->container;
  769. } else {
  770. maxnum = searchDirNum;
  771. loc->container = NULL;
  772. loc->directoryLevel = -1;
  773. }
  774. if ( maxnum ) {
  775. int localfound = 0;
  776. for ( int i = 0; i < maxnum && !localfound; i++ ) {
  777. char buf[2000];
  778. FILE* fp = fopen ( constructFileName ( buf, i, NULL, filename.c_str()), "r" );
  779. if ( fp ) {
  780. localfound = loc->found = 1;
  781. fclose ( fp );
  782. loc->container = NULL;
  783. loc->directoryLevel = i;
  784. }
  785. }
  786. } else {
  787. char buf[2000];
  788. FILE* fp = fopen ( constructFileName ( buf, -1, ".", filename.c_str()), "r" );
  789. if ( fp ) {
  790. loc->found = 1;
  791. fclose ( fp );
  792. loc->container = NULL;
  793. loc->directoryLevel = -2;
  794. }
  795. }
  796. }
  797. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  798. ASCString listContainer()
  799. {
  800. return containercollector.listContainer();
  801. }
  802. ContainerCollector :: ContainerCollector ( void )
  803. {
  804. containernum = 0;
  805. }
  806. void ContainerCollector :: init ( const char* wildcard )
  807. {
  808. for ( int i = 0; i < searchDirNum; i++ ) {
  809. DIR *dirp;
  810. struct ASC_direct *direntp;
  811. char buf[ maxFileStringSize ];
  812. char buf2[ maxFileStringSize ];
  813. char buf3 [ maxFileStringSize ];
  814. dirp = opendir( extractPath ( buf2, constructFileName ( buf, i, NULL, wildcard )));
  815. extractFileName ( buf3, buf );
  816. if( dirp != NULL ) {
  817. for(;;) {
  818. direntp = readdir( dirp );
  819. if ( direntp == NULL ) {
  820. break;
  821. }
  822. if ( patimat ( buf3, direntp->d_name )) {
  823. container[containernum++] = new tncontainerstream( constructFileName ( buf, i, buf2, direntp->d_name), this, i);
  824. if ( MessagingHub::Instance().getVerbosity() >= 2 )
  825. printf("container %s mounted\n", buf );
  826. }
  827. }
  828. closedir( dirp );
  829. }
  830. }
  831. }
  832. void ContainerCollector :: addfile ( const char* filename, const pncontainerstream stream, int directoryLevel )
  833. {
  834. int found = 0;
  835. FileIndex* cci = NULL;
  836. int i1 = toupper ( filename[0] );
  837. for ( int i = 0; i <= index[i1].getlength(); i++ )
  838. if ( index[i1][i].name.compare_ci ( filename ) == 0 ) {
  839. if ( index[i1][i].directoryLevel <= directoryLevel )
  840. return;
  841. else {
  842. cci = &(index[i1][i]);
  843. found = 1;
  844. }
  845. }
  846. if ( !found )
  847. cci = &( index[i1][ index[i1].getlength()+1 ] );
  848. cci->name = filename;
  849. cci->container = stream;
  850. cci->directoryLevel = directoryLevel;
  851. }
  852. ContainerCollector::FileIndex* ContainerCollector :: getfile ( const ASCString& filename )
  853. {
  854. int i1 = toupper ( filename[0] );
  855. for ( int i = 0; i <= index[i1].getlength(); i++ )
  856. if ( index[i1][i].name.compare_ci ( filename) == 0 )
  857. return &index[i1][i];
  858. return NULL;
  859. }
  860. ContainerCollector::FileIndex* ContainerCollector :: getfirstname ( void )
  861. {
  862. namesearch.alpha = 0;
  863. namesearch.index = 0;
  864. return getnextname();
  865. }
  866. ContainerCollector::FileIndex* ContainerCollector :: getnextname ( void )
  867. {
  868. while ( index[namesearch.alpha].getlength() < namesearch.index) {
  869. if ( namesearch.alpha == 255 )
  870. return NULL;
  871. namesearch.alpha++;
  872. namesearch.index = 0;
  873. } /* endwhile */
  874. return &index[namesearch.alpha][namesearch.index++];
  875. }
  876. ASCString ContainerCollector :: listContainer()
  877. {
  878. ASCString s;
  879. for ( int i = 0; i < containernum; i++ )
  880. s += container[i]->getLocation() + "\n";
  881. return s;
  882. }
  883. ContainerCollector :: ~ContainerCollector()
  884. {
  885. int i;
  886. for (i = 0; i < containernum; i++ )
  887. delete container[i];
  888. containernum = 0;
  889. }
  890. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  891. CompressionStreamAdapter::CompressionStreamAdapter( tnstream* compressedStream )
  892. : stream ( compressedStream )
  893. {
  894. }
  895. void CompressionStreamAdapter::writecmpdata ( const void* buf, int size )
  896. {
  897. stream->writedata( buf, size );
  898. }
  899. int CompressionStreamAdapter::readcmpdata ( void* buf, int size, bool excpt )
  900. {
  901. return stream->readdata( buf, size, excpt );
  902. }
  903. class PrivateCompressionData {
  904. public:
  905. bz_stream bzs;
  906. static const int outputbufsize = 100000;
  907. char outputbuf[outputbufsize];
  908. PrivateCompressionData() {
  909. bzs.bzalloc = NULL;
  910. bzs.bzfree = NULL;
  911. bzs.opaque = NULL;
  912. };
  913. ~PrivateCompressionData() {
  914. BZ2_bzCompressEnd ( &bzs );
  915. }
  916. };
  917. libbzip_compression :: libbzip_compression ( CompressionStreamInterface* strm )
  918. {
  919. data = new PrivateCompressionData();
  920. BZ2_bzCompressInit ( &data->bzs, 5, 0, 0 );
  921. stream = strm;
  922. }
  923. void libbzip_compression :: writedata ( const void* buf, int size )
  924. {
  925. char* cbuf = (char*) buf;
  926. data->bzs.next_in = cbuf ;
  927. data->bzs.avail_in = size ;
  928. data->bzs.total_in_lo32 = 0 ;
  929. data->bzs.total_in_hi32 = 0 ;
  930. while ( data->bzs.total_in_lo32 < size ) {
  931. data->bzs.next_out = data->outputbuf;
  932. data->bzs.avail_out = data->outputbufsize;
  933. data->bzs.total_out_lo32 = 0;
  934. data->bzs.total_out_hi32 = 0;
  935. int res = BZ2_bzCompress ( &data->bzs, BZ_RUN );
  936. if ( res < 0 )
  937. throw StreamCompressionError ( "MBZLB2 compression :: writedata", res );
  938. for ( int i = 0; i < data->bzs.total_out_lo32; i++ )
  939. data->outputbuf[i] ^= bzip_xor_byte;
  940. if ( data->bzs.total_out_lo32 > 0 )
  941. stream->writecmpdata ( data->outputbuf, data->bzs.total_out_lo32 );
  942. }
  943. }
  944. void libbzip_compression :: close_compression ( void )
  945. {
  946. int res;
  947. do {
  948. data->bzs.next_in = data->outputbuf;
  949. data->bzs.avail_in = 0;
  950. data->bzs.next_out = data->outputbuf;
  951. data->bzs.avail_out = data->outputbufsize;
  952. data->bzs.total_out_lo32 = 0;
  953. data->bzs.total_out_hi32 = 0;
  954. res = BZ2_bzCompress ( &data->bzs, BZ_FINISH );
  955. if ( res < 0 )
  956. throw StreamCompressionError ( "MBZLB2 compression :: closecompression", res );
  957. for ( int i = 0; i < data->bzs.total_out_lo32; i++ )
  958. data->outputbuf[i] ^= bzip_xor_byte;
  959. stream->writecmpdata ( data->outputbuf, data->bzs.total_out_lo32 );
  960. } while ( res != BZ_STREAM_END );
  961. BZ2_bzCompressEnd ( &data->bzs );
  962. }
  963. libbzip_compression :: ~libbzip_compression ( )
  964. {
  965. delete data;
  966. }
  967. class PrivateDecompressionData {
  968. public:
  969. bz_stream bzs;
  970. static const int inputbufsize = 100000;
  971. char inputbuf[inputbufsize];
  972. int inputbufused;
  973. int inputbufread;
  974. PrivateDecompressionData() {
  975. bzs.bzalloc = NULL;
  976. bzs.bzfree = NULL;
  977. bzs.opaque = NULL;
  978. inputbufused = 0;
  979. inputbufread = 0;
  980. }
  981. ~PrivateDecompressionData() {
  982. BZ2_bzDecompressEnd ( &bzs );
  983. }
  984. };
  985. libbzip_decompression :: libbzip_decompression ( CompressionStreamInterface* strm )
  986. {
  987. data = new PrivateDecompressionData();
  988. BZ2_bzDecompressInit ( &data->bzs, 0, 0 );
  989. stream = strm;
  990. }
  991. int libbzip_decompression :: readdata ( void* buf, int size, bool excpt )
  992. {
  993. int decompressed = 0;
  994. char* cbuf = (char*) buf;
  995. data->bzs.next_in = cbuf ;
  996. data->bzs.avail_in = size ;
  997. data->bzs.total_in_lo32 = 0 ;
  998. data->bzs.total_in_hi32 = 0 ;
  999. int abrt = 0;
  1000. while ( decompressed < size && !abrt ) {
  1001. if ( data->inputbufread >= data->inputbufused ) {
  1002. data->inputbufused = stream->readcmpdata ( data->inputbuf, data->inputbufsize, 0 );
  1003. if ( !data->inputbufused && excpt )
  1004. throw StreamCompressionError ( "Decompressor :: out of data", 0 );
  1005. for ( int i = 0; i < data->inputbufused; i++ )
  1006. data->inputbuf[i] ^= bzip_xor_byte;
  1007. data->inputbufread = 0;
  1008. }
  1009. data->bzs.next_in = data->inputbuf + data->inputbufread;
  1010. data->bzs.avail_in = data->inputbufused - data->inputbufread;
  1011. data->bzs.total_in_lo32 = 0;
  1012. data->bzs.total_in_hi32 = 0;
  1013. data->bzs.next_out = cbuf + decompressed;
  1014. data->bzs.avail_out = size - decompressed;
  1015. data->bzs.total_out_lo32 = 0;
  1016. data->bzs.total_out_hi32 = 0;
  1017. int res = BZ2_bzDecompress ( &data->bzs );
  1018. decompressed += data->bzs.total_out_lo32;
  1019. data->inputbufread += data->bzs.total_in_lo32;
  1020. if ( decompressed < size ) {
  1021. if ( res == BZ_STREAM_END ) {
  1022. if ( excpt )
  1023. throw treadafterend ( "BZ_decompress_stream" );
  1024. abrt = 1;
  1025. } else {
  1026. if ( res != BZ_OK ) {
  1027. if ( excpt ) {
  1028. if ( res == BZ_MEM_ERROR )
  1029. throw OutOfMemoryError ( -1 );
  1030. else
  1031. throw StreamCompressionError ( "MBZLB2 decompression :: readdata", res );
  1032. }
  1033. abrt = 1;
  1034. }
  1035. }
  1036. }
  1037. }
  1038. return decompressed;
  1039. }
  1040. libbzip_decompression :: ~libbzip_decompression ( )
  1041. {
  1042. delete data;
  1043. }
  1044. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  1045. /*
  1046. t_compressor_2ndbuf_filter :: t_compressor_2ndbuf_filter ( t_compressor_stream_interface* strm )
  1047. {
  1048. stream = strm;
  1049. }
  1050. void t_compressor_2ndbuf_filter :: writecmpdata ( const void* buf, int size )
  1051. {
  1052. stream->writecmpdata ( buf, size );
  1053. }
  1054. int t_compressor_2ndbuf_filter :: readcmpdata ( void* buf, int size, bool excpt )
  1055. {
  1056. int got = 0;
  1057. char* pc = (char*) buf;
  1058. while ( size && _queue.size() ) {
  1059. *pc = _queue.front();
  1060. _queue.pop();
  1061. pc++;
  1062. size--;
  1063. got++;
  1064. }
  1065. if ( size )
  1066. got += stream->readcmpdata ( pc, size, excpt );
  1067. return got;
  1068. }
  1069. void t_compressor_2ndbuf_filter :: insert_data_into_queue ( const void* buf, int size )
  1070. {
  1071. char* pc = (char*) buf;
  1072. for (int i = 0; i < size; i++) {
  1073. _queue.push ( *pc );
  1074. pc++;
  1075. }
  1076. }
  1077. */
  1078. tanycompression :: tanycompression ( int md )
  1079. {
  1080. mmd = md;
  1081. bzip_compress = NULL;
  1082. bzip_decompress = NULL;
  1083. }
  1084. void tanycompression :: init ( void )
  1085. {
  1086. if ( mmd == 1 ) {
  1087. char buf[10];
  1088. int maxlen = strlen ( BZIP_SIGNATURE ) + 1;
  1089. int bufdatanum = readcmpdata ( buf, maxlen, 0 );
  1090. int siglen = 0;
  1091. if ( bufdatanum == maxlen ) {
  1092. if ( strncmp ( &buf[1], LZ_SIGNATURE, 9 ) == 0 && !buf[0]) {
  1093. status = 110;
  1094. siglen = 0;
  1095. } else
  1096. if ( strncmp ( &buf[1], RLE_SIGNATURE, 9 ) == 0 && !buf[0]) {
  1097. status = 111;
  1098. siglen = 0;
  1099. } else
  1100. if ( strncmp ( buf, BZIP_SIGNATURE, 9 ) == 0 ) {
  1101. status = 112;
  1102. siglen = strlen ( BZIP_SIGNATURE ) + 1;
  1103. bzip_decompress = new libbzip_decompression ( this );
  1104. } else
  1105. status= 109;
  1106. } else
  1107. status = 109;
  1108. for ( int i = siglen; i < bufdatanum; i++ )
  1109. _queue.push ( buf[i] );
  1110. } else {
  1111. status = 201;
  1112. bzip_compress = new libbzip_compression ( this );
  1113. writecmpdata ( BZIP_SIGNATURE, strlen ( BZIP_SIGNATURE ) + 1 );
  1114. }
  1115. }
  1116. int tanycompression :: readdata ( void* rbuf, int size, bool excpt )
  1117. {
  1118. int red = 0;
  1119. if ( size ) {
  1120. switch ( status ) {
  1121. case 109: red += readlzwdata ( rbuf, size, excpt );
  1122. break;
  1123. case 110:
  1124. case 111: red += tlzwstreamcompression :: readdata ( rbuf, size, excpt );
  1125. break;
  1126. case 112: red += bzip_decompress -> readdata ( rbuf, size, excpt );
  1127. break;
  1128. } /* endswitch */
  1129. }
  1130. return red;
  1131. }
  1132. void tanycompression :: writedata ( const void* buf, int size )
  1133. {
  1134. bzip_compress -> writedata ( buf, size );
  1135. // writecmpdata ( buf, size );
  1136. }
  1137. int tanycompression :: readlzwdata ( void* buf, int size, bool excpt )
  1138. {
  1139. if ( _queue.size() ) {
  1140. int got = 0;
  1141. char* pc = (char*) buf;
  1142. while ( size && _queue.size() ) {
  1143. *pc = _queue.front();
  1144. _queue.pop();
  1145. pc++;
  1146. size--;
  1147. got++;
  1148. } /* endwhile */
  1149. if ( size )
  1150. got += readcmpdata ( pc, size, excpt );
  1151. return got;
  1152. } else
  1153. return readcmpdata ( buf, size, excpt );
  1154. }
  1155. void tanycompression :: writelzwdata ( const void* buf, int size )
  1156. {
  1157. writecmpdata ( buf, size );
  1158. }
  1159. void tanycompression :: close_compression ( void )
  1160. {
  1161. if ( bzip_compress ) {
  1162. bzip_compress->close_compression ( );
  1163. delete bzip_compress;
  1164. bzip_compress = NULL;
  1165. }
  1166. }
  1167. tanycompression :: ~tanycompression ( )
  1168. {
  1169. if ( bzip_decompress ) {
  1170. delete bzip_decompress;
  1171. bzip_decompress = NULL;
  1172. }
  1173. }
  1174. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  1175. /*
  1176. void tn_lzw_bufstream :: writedata ( const void* buf, int size )
  1177. {
  1178. tlzwstreamcompression :: writedata ( buf, size );
  1179. }
  1180. int tn_lzw_bufstream :: readdata ( void* buf, int size, bool excpt )
  1181. {
  1182. return tlzwstreamcompression :: readdata ( buf, size, excpt );
  1183. }
  1184. int tn_lzw_bufstream :: readlzwdata ( void* buf, int size, bool excpt )
  1185. {
  1186. return tnbufstream :: readdata ( buf, size, excpt );
  1187. }
  1188. void tn_lzw_bufstream :: writelzwdata ( const void* buf, int size )
  1189. {
  1190. tnbufstream :: writedata ( buf, size );
  1191. }
  1192. tn_lzw_bufstream :: ~tn_lzw_bufstream ()
  1193. {
  1194. tlzwstreamcompression :: close();
  1195. tnbufstream :: close();
  1196. }
  1197. */
  1198. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  1199. void tn_lzw_file_buf_stream :: writedata ( const void* buf, int size )
  1200. {
  1201. tanycompression :: writedata ( buf, size );
  1202. }
  1203. int tn_lzw_file_buf_stream :: readdata ( void* buf, int size, bool excpt )
  1204. {
  1205. return tanycompression :: readdata ( buf, size, excpt );
  1206. }
  1207. int tn_lzw_file_buf_stream:: readcmpdata ( void* buf, int size, bool excpt )
  1208. {
  1209. return tn_file_buf_stream :: readdata ( buf, size, excpt );
  1210. }
  1211. void tn_lzw_file_buf_stream :: writecmpdata ( const void* buf, int size )
  1212. {
  1213. tn_file_buf_stream :: writedata ( buf, size );
  1214. }
  1215. tn_lzw_file_buf_stream :: ~tn_lzw_file_buf_stream()
  1216. {
  1217. close_compression ();
  1218. tn_file_buf_stream :: close();
  1219. }
  1220. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  1221. tn_c_lzw_filestream :: tn_c_lzw_filestream ( const ASCString& name, IOMode mode ) : tanycompression ( mode )
  1222. {
  1223. #ifdef logfiles
  1224. FILE* fp = fopen ( "files.lst", "at" );
  1225. fprintf ( fp, "%s\n", name );
  1226. fclose ( fp );
  1227. #endif
  1228. strm = NULL;
  1229. inp = 0;
  1230. containerstream = NULL;
  1231. FileLocation fl;
  1232. if ( mode == tnstream::reading ) {
  1233. locateFile ( name, &fl );
  1234. if ( !fl.found )
  1235. throw tfileerror ( name );
  1236. } else {
  1237. fl.directoryLevel = 0;
  1238. fl.container = NULL;
  1239. }
  1240. if ( fl.container == NULL ) {
  1241. char string[2000];
  1242. ASCString fileNameComplete = constructFileName ( string, fl.directoryLevel, NULL, name.c_str());
  1243. strm = new tn_file_buf_stream ( fileNameComplete, mode );
  1244. inp = 1;
  1245. devicename = fileNameComplete;
  1246. location = fileNameComplete;
  1247. } else {
  1248. containerstream = fl.container;
  1249. if ( containerstream ) {
  1250. inp = 2;
  1251. containerstream->opencontainerfile ( name.c_str() );
  1252. devicename = name;
  1253. location = name + " located inside " + containerstream->getDeviceName();
  1254. } else
  1255. throw tfileerror ( name );
  1256. }
  1257. fname = name;
  1258. tanycompression :: init ( );
  1259. }
  1260. ASCString tn_c_lzw_filestream::getArchive()
  1261. {
  1262. if ( containerstream )
  1263. return containerstream->getDeviceName();
  1264. else
  1265. return "";
  1266. }
  1267. ASCString tn_c_lzw_filestream::getLocation()
  1268. {
  1269. return location;
  1270. }
  1271. int tn_c_lzw_filestream :: getSize ( void )
  1272. {
  1273. if ( inp == 2 )
  1274. return containerstream->getSize();
  1275. else
  1276. return strm->getSize();
  1277. }
  1278. void tn_c_lzw_filestream :: writecmpdata ( const void* buf, int size )
  1279. {
  1280. if ( inp == 2 )
  1281. throw tinvalidmode ( fname, tnstream::reading, tnstream::writing );
  1282. else
  1283. strm->writedata ( buf, size );
  1284. }
  1285. int tn_c_lzw_filestream :: readcmpdata ( void* buf, int size, bool excpt )
  1286. {
  1287. if ( inp == 2 )
  1288. return containerstream->readcontainerdata ( buf, size, excpt );
  1289. else
  1290. return strm->readdata ( buf, size, excpt );
  1291. };
  1292. void tn_c_lzw_filestream :: writedata ( const void* buf, int size )
  1293. {
  1294. tanycompression :: writedata ( buf, size );
  1295. }
  1296. int tn_c_lzw_filestream :: readdata ( void* buf, int size, bool excpt )
  1297. {
  1298. if ( tanycompression :: mode == readingdirect && !tempbuf.size() )
  1299. if ( inp == 2 )
  1300. return containerstream->readcontainerdata ( buf, size, excpt );
  1301. else
  1302. return strm->readdata ( buf, size, excpt );
  1303. else
  1304. return tanycompression :: readdata ( buf, size, excpt );
  1305. };
  1306. time_t tn_c_lzw_filestream :: get_time ( void )
  1307. {
  1308. if ( inp == 2 )
  1309. return containerstream->get_time();
  1310. else
  1311. return strm->get_time();
  1312. }
  1313. tn_c_lzw_filestream :: ~tn_c_lzw_filestream()
  1314. {
  1315. try {
  1316. displayLogMessage( 9, "~tn_c_lzw_filestream " + getLocation() );
  1317. close_compression ();
  1318. close();
  1319. if ( inp == 1 ) {
  1320. delete strm;
  1321. strm = NULL;
  1322. } else {
  1323. displayLogMessage( 9, ASCString("~tn_c_lzw_filestream -> closecontainerfile ") );
  1324. containerstream->closecontainerfile();
  1325. }
  1326. } catch ( ... ) {
  1327. displayLogMessage( 9, ASCString("~tn_c_lzw_filestream : caught exception") );
  1328. throw;
  1329. }
  1330. }
  1331. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  1332. static const char asciiCodingTable[64] = { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
  1333. 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
  1334. 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X',
  1335. 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',
  1336. 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
  1337. 'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
  1338. 'w', 'x', 'y', 'z', '0', '1', '2', '3',
  1339. '4', '5', '6', '7', '8', '9', '+', '/' };
  1340. ASCIIEncodingStream::ASCIIEncodingStream() : shift(0), buf(0) {};
  1341. void ASCIIEncodingStream::writedata ( const void* buf, int size ) {
  1342. const char* c = (const char*)buf;
  1343. for ( int i = 0; i < size; ++i )
  1344. put ( c[i] );
  1345. }
  1346. int ASCIIEncodingStream::readdata ( void* buf, int size, bool excpt ) {
  1347. throw tinvalidmode ( "Base64SerializingStream", reading, writing );
  1348. }
  1349. void ASCIIEncodingStream::put( char c )
  1350. {
  1351. if ( shift == 0 ) {
  1352. buf = c >> 6;
  1353. shift = 2;
  1354. result += asciiCodingTable[c & 63];
  1355. } else if ( shift == 2 ) {
  1356. buf |= ( c << 2) & 63;
  1357. result += asciiCodingTable[buf];
  1358. buf = c >> 4;
  1359. shift = 4;
  1360. } else if ( shift==4 ) {
  1361. buf |= (c << 4) & 63;
  1362. result += asciiCodingTable[buf];
  1363. shift = 0;
  1364. result += asciiCodingTable[int((c>>2) & 63)];
  1365. }
  1366. }
  1367. void ASCIIEncodingStream::flush() {
  1368. if ( shift )
  1369. result += asciiCodingTable[buf & 63];
  1370. result += "#";
  1371. }
  1372. ASCString ASCIIEncodingStream::getResult()
  1373. {
  1374. flush();
  1375. return result;
  1376. }
  1377. void ASCIIDecodingStream :: generateTable()
  1378. {
  1379. for ( int i = 0; i< 256; ++i )
  1380. reverse[i] = -1;
  1381. for ( int i = 0; i < sizeof(asciiCodingTable); ++i )
  1382. reverse[ int(asciiCodingTable[i])] = i;
  1383. }
  1384. int ASCIIDecodingStream :: get()
  1385. {
  1386. if ( length < data.length() ) {
  1387. int c = data.at(length);
  1388. if ( c == '#' )
  1389. throw treadafterend("ASCIIDecodingStream");
  1390. ++length;
  1391. if ( reverse[c] == -1 )
  1392. throw ASCmsgException("Invalid ASCII data to decode");
  1393. return reverse[c];
  1394. } else
  1395. throw treadafterend("ASCIIDecodingStream");
  1396. }
  1397. ASCIIDecodingStream :: ASCIIDecodingStream( const ASCString& data) : shift(0), buf(0), length(0)
  1398. {
  1399. this->data = data;
  1400. generateTable();
  1401. }
  1402. void ASCIIDecodingStream :: writedata ( const void* buf, int size )
  1403. {
  1404. throw tinvalidmode ( "ASCIIDecodingStream", writing, reading );
  1405. }
  1406. int ASCIIDecodingStream :: readdata ( void* buffer, int size, bool excpt )
  1407. {
  1408. int i = 0;
  1409. try {
  1410. char* cbuf = (char*) buffer;
  1411. for ( i = 0; i < size; ++i ) {
  1412. if ( shift == 0 ) {
  1413. char c = get();
  1414. char c2 = get();
  1415. cbuf[i] = c | ((c2 << 6) & 0xff);
  1416. shift = 2;
  1417. buf = c2 >> 2;
  1418. } else if ( shift == 2 ) {
  1419. char c = get();
  1420. cbuf[i] = buf | ((c << 4) & 0xff );
  1421. buf = c >> 4;
  1422. shift = 4;
  1423. } else if ( shift == 4 ) {
  1424. char c = get();
  1425. cbuf[i] = buf | (c << 2 );
  1426. shift = 0;
  1427. }
  1428. }
  1429. }
  1430. catch ( treadafterend trae ) {
  1431. if ( excpt )
  1432. throw trae;
  1433. }
  1434. return i;
  1435. }
  1436. StreamCompressionFilter :: StreamCompressionFilter( tnstream* outputstream )
  1437. : adapter( outputstream), compressor( &adapter ), closed(false) {
  1438. }
  1439. void StreamCompressionFilter :: writedata ( const void* buf, int size )
  1440. {
  1441. compressor.writedata(buf,size);
  1442. }
  1443. int StreamCompressionFilter :: readdata ( void* buf, int size, bool excpt )
  1444. {
  1445. throw tinvalidmode ( "StreamCompressionFilter", reading, writing );
  1446. }
  1447. void StreamCompressionFilter :: close()
  1448. {
  1449. if ( closed )
  1450. return;
  1451. compressor.close_compression();
  1452. closed = true;
  1453. }
  1454. StreamCompressionFilter ::~StreamCompressionFilter()
  1455. {
  1456. close();
  1457. }
  1458. StreamDecompressionFilter :: StreamDecompressionFilter( tnstream* inputstream ) : adapter( inputstream), decompressor( &adapter ) {
  1459. }
  1460. void StreamDecompressionFilter :: writedata ( const void* buf, int size )
  1461. {
  1462. throw tinvalidmode ( "StreamCompressionFilter", writing, reading );
  1463. }
  1464. int StreamDecompressionFilter :: readdata ( void* buf, int size, bool excpt )
  1465. {
  1466. return decompressor.readdata(buf,size,excpt);
  1467. }
  1468. ////////////////////////////////////////////////////////////////////////////////////////
  1469. int compressrle ( const void* p, void* q)
  1470. {
  1471. trleheader* sourcehead = (trleheader*) p;
  1472. if ( sourcehead->id == 16973 ) {
  1473. memcpy ( q, p, sourcehead->size + sizeof ( trleheader ) );
  1474. return sourcehead->size + sizeof ( trleheader );
  1475. }
  1476. char* s = (char*) p;
  1477. char* d = (char*) q;
  1478. trleheader* header = (trleheader*) q;
  1479. Uint16 x,y;
  1480. int size;
  1481. {
  1482. Uint16* pw = (Uint16*) s;
  1483. x = pw[0];
  1484. y = pw[1];
  1485. header->x = x;
  1486. header->y = y;
  1487. x++;
  1488. y++;
  1489. size = x * y;
  1490. header->id = 16973;
  1491. }
  1492. {
  1493. int bts[256];
  1494. memset ( bts, 0, sizeof ( bts ));
  1495. for ( int i = 0; i < size ;i++ )
  1496. bts[int(s[i+4])]++;
  1497. int min = 70000;
  1498. for ( int i = 0; i < 256; i++ )
  1499. if ( bts[i] < min ) {
  1500. min = bts[i];
  1501. header->rle = i;
  1502. }
  1503. }
  1504. s+=4;
  1505. d+=sizeof ( trleheader );
  1506. {
  1507. char* startpos = d;
  1508. int xp;
  1509. for (int j = 0; j < y ; j++ ) {
  1510. xp = 0;
  1511. unsigned char num;
  1512. unsigned char actbyte ;
  1513. do {
  1514. num = 1;
  1515. actbyte = *s;
  1516. while ( xp+num < x && num < 255 && s[num] == actbyte )
  1517. num++;
  1518. if ( num > 2 || actbyte == header->rle ) {
  1519. *(d++) = header->rle;
  1520. *(d++) = num;
  1521. *(d++) = actbyte;
  1522. } else {
  1523. *(d++) = actbyte;
  1524. if ( num > 1 )
  1525. *(d++) = actbyte;
  1526. }
  1527. s += num;
  1528. xp += num;
  1529. } while ( xp < x );
  1530. } /* endfor */
  1531. header->size = d - startpos;
  1532. }
  1533. return header->size + sizeof ( trleheader );
  1534. }
  1535. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  1536. bool patimat (const char *pat, const char *str, bool forceCaseInsensitivity )
  1537. {
  1538. switch (*pat)
  1539. {
  1540. case '\0':
  1541. return !*str;
  1542. case '*' :
  1543. return patimat(pat+1, str, forceCaseInsensitivity) || (*str && patimat(pat, str+1, forceCaseInsensitivity));
  1544. case '?' :
  1545. return *str && patimat(pat+1, str+1, forceCaseInsensitivity);
  1546. default :
  1547. if ( forceCaseInsensitivity ||
  1548. #if CASE_SENSITIVE_FILE_NAMES == 0
  1549. true
  1550. #else
  1551. false
  1552. #endif
  1553. )
  1554. return (toupper(*pat) == toupper(*str)) && patimat(pat+1, str+1, forceCaseInsensitivity);
  1555. else
  1556. return (*pat == *str) && patimat(pat+1, str+1, forceCaseInsensitivity );
  1557. }
  1558. }
  1559. bool patimat (const ASCString& pat, const ASCString& str, bool forceCaseInsensitivity)
  1560. {
  1561. return patimat( pat.c_str(), str.c_str(), forceCaseInsensitivity );
  1562. }
  1563. tfindfile :: tfindfile ( ASCString name, SearchPosition searchPosition, SearchTypes searchTypes )
  1564. {
  1565. convertPathDelimitters ( name );
  1566. if ( searchPosition == DefaultDir )
  1567. searchPosition = AllDirs;
  1568. if ( searchDirNum == 0 )
  1569. searchPosition = CurrentDir;
  1570. found = 0;
  1571. act = 0;
  1572. if ( name.empty() )
  1573. return;
  1574. ASCString directory[maxSearchDirNum];
  1575. int dirNum;
  1576. ASCString wildcard;
  1577. int ppos = name.rfind ( pathdelimitterstring );
  1578. if ( ppos != name.npos ) {
  1579. // name contains a directory entry
  1580. // checking if absolute or relative path
  1581. bool absolute = false;
  1582. if ( name[0] == pathdelimitter )
  1583. absolute = true;
  1584. if ( has_drive_letters && name.length() > 3 && name.find ( ":\\", 1 ) != name.npos )
  1585. absolute = true;
  1586. if ( absolute || searchPosition == CurrentDir ) {
  1587. directory[0].assign ( name, 0, ppos );
  1588. dirNum = 1;
  1589. } else {
  1590. ASCString strippedPath;
  1591. strippedPath.assign ( name, 0, ppos );
  1592. if ( strippedPath.find ( ASCString(".") + pathdelimitterstring ) == 0 )
  1593. strippedPath.erase( 0, 2);
  1594. int upDir = 0;
  1595. while ( strippedPath.find ( ASCString("..") + pathdelimitterstring ) == 0 ) {
  1596. upDir++;
  1597. strippedPath.erase ( 0, 3 );
  1598. }
  1599. int dirsToProcess;
  1600. if ( searchPosition == AllDirs ) {
  1601. dirsToProcess = searchDirNum;
  1602. } else
  1603. dirsToProcess = 1;
  1604. dirNum = 0;
  1605. for ( int i = 0; i < dirsToProcess; i++ ) {
  1606. ASCString dir = ascDirectory[i];
  1607. // removing the trailing pathdelimitterstring
  1608. dir.erase ( dir.length() -1 );
  1609. for ( int j = 0; j < upDir; j++ ) {
  1610. int pos = dir.rfind ( pathdelimitterstring );
  1611. if ( pos > 0 && pos == dir.npos )
  1612. dir.erase ( pos );
  1613. }
  1614. // append the trailing pathdelimitterstring again
  1615. dir += pathdelimitterstring;
  1616. directory[dirNum++] = dir + strippedPath;
  1617. }
  1618. if ( !dirNum ) {
  1619. directory[0] = ".";
  1620. dirNum = 1;
  1621. }
  1622. }
  1623. wildcard.assign ( name, ppos+1, name.npos );
  1624. } else {
  1625. if ( searchDirNum ) {
  1626. for (int i = 0; i < searchDirNum; i++ )
  1627. directory[i] = ascDirectory[i];
  1628. dirNum = searchDirNum;
  1629. } else {
  1630. directory[0] = ".";
  1631. dirNum = 1;
  1632. }
  1633. wildcard = name;
  1634. }
  1635. if ( searchTypes == All || searchTypes == OutsideContainer )
  1636. for ( int i = 0; i < dirNum; i++ ) {
  1637. DIR *dirp;
  1638. struct ASC_direct *direntp;
  1639. dirp = opendir( directory[i].c_str() );
  1640. if( dirp != NULL ) {
  1641. for(;;) {
  1642. direntp = readdir( dirp );
  1643. if ( direntp == NULL )
  1644. break;
  1645. if ( patimat ( wildcard.c_str(), direntp->d_name )) {
  1646. int localfound = 0;
  1647. for ( int j = 0; j < found; j++ )
  1648. if ( strcmpi ( fileInfo[j].name.c_str(), direntp->d_name ) == 0 )
  1649. localfound++;
  1650. if ( !localfound ) {
  1651. FileInfo fi;
  1652. fi.name = direntp->d_name;
  1653. fi.directoryLevel = i ;
  1654. fi.isInContainer = false ;
  1655. fi.location = directory[i];
  1656. char buf[1000];
  1657. ASCString fullName = constructFileName( buf, i, NULL, direntp->d_name );
  1658. struct stat statbuf;
  1659. stat( fullName.c_str(), &statbuf);
  1660. fi.size = statbuf.st_size ;
  1661. fi.date = statbuf.st_mtime;
  1662. fileInfo.push_back ( fi );
  1663. found++;
  1664. }
  1665. }
  1666. }
  1667. closedir( dirp );
  1668. }
  1669. }
  1670. if ( searchTypes == All || searchTypes == InsideContainer ) {
  1671. const ContainerCollector::FileIndex* c = containercollector.getfirstname();
  1672. while ( c ) {
  1673. if ( patimat ( name.c_str(), c->name ) ) {
  1674. int f = 0;
  1675. for ( int i = 0; i < found; i++ )
  1676. if ( stricmp ( c->name.c_str(), fileInfo[i].name.c_str() ) == 0 ) {
  1677. if ( fileInfo[i].directoryLevel <= c->directoryLevel )
  1678. f = 1;
  1679. else {
  1680. FileInfo& fi = fileInfo[i];
  1681. fi.name = c->name ;
  1682. fi.isInContainer = true;
  1683. fi.directoryLevel = c->directoryLevel;
  1684. fi.location = c->container->getDeviceName();
  1685. fi.size = c->container->getstreamsize();
  1686. fi.date = c->container->get_time();
  1687. f = 1;
  1688. }
  1689. }
  1690. if ( !f ) {
  1691. FileInfo fi;
  1692. fi.name = c->name ;
  1693. fi.directoryLevel = c->directoryLevel ;
  1694. fi.isInContainer = true ;
  1695. fi.location = c->container->getDeviceName() ;
  1696. fi.size = c->container->getstreamsize() ;
  1697. fi.date = c->container->get_time() ;
  1698. fileInfo.push_back ( fi );
  1699. found++;
  1700. }
  1701. }
  1702. c = containercollector.getnextname();
  1703. }
  1704. }
  1705. }
  1706. ASCString tfindfile :: getnextname ( int* loc, bool* inContainer, ASCString* location )
  1707. {
  1708. if ( act < found ) {
  1709. if ( loc )
  1710. *loc = fileInfo[act].directoryLevel;
  1711. if ( inContainer )
  1712. *inContainer = fileInfo[act].isInContainer;
  1713. if ( location )
  1714. *location = fileInfo[act].location;
  1715. /*
  1716. if ( directoryLevel[act] >= 0 && this->location[act] != ascDirectory[directoryLevel[act]] ) {
  1717. ASCString s = this->location[act];
  1718. appendbackslash ( s );
  1719. s += names[act++];
  1720. return s;
  1721. } else */
  1722. return fileInfo[act++].name;
  1723. } else {
  1724. if ( loc )
  1725. *loc = -1;
  1726. return "";
  1727. }
  1728. }
  1729. bool tfindfile :: getnextname ( FileInfo& fi )
  1730. {
  1731. if ( act < found ) {
  1732. fi = fileInfo[act++];
  1733. return true;
  1734. } else
  1735. return false;
  1736. }
  1737. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  1738. int checkforvaliddirectory ( char* dir )
  1739. {
  1740. int stat = 0;
  1741. DIR *dirp;
  1742. struct ASC_direct *direntp;
  1743. /* char temp[200];
  1744. int l = strlen(dir) - 1;
  1745. for (int i = 0; i < l; i++) {
  1746. temp[i] = dir[i];
  1747. }
  1748. temp[i] = 0;
  1749. */
  1750. dirp = opendir( dir );
  1751. if( dirp != NULL ) {
  1752. for(;;) {
  1753. direntp = readdir( dirp );
  1754. if ( direntp == NULL )
  1755. break;
  1756. if ( strcmp ( direntp -> d_name, ".") == 0 )
  1757. stat = 1;
  1758. }
  1759. closedir( dirp );
  1760. }
  1761. return stat;
  1762. }
  1763. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  1764. MemoryStreamStorage :: MemoryStreamStorage ( void )
  1765. {
  1766. used = 0;
  1767. allocated = 0;
  1768. buf = 0;
  1769. memset ( dummy, 0, sizeof ( dummy ));
  1770. }
  1771. MemoryStreamStorage :: ~MemoryStreamStorage ( void )
  1772. {
  1773. if ( buf ) {
  1774. delete[] buf;
  1775. buf = NULL;
  1776. }
  1777. }
  1778. void MemoryStreamStorage :: writetostream ( tnstream* stream )
  1779. {
  1780. if ( stream ) {
  1781. stream->writeInt ( 0 );
  1782. stream->writeInt ( used );
  1783. stream->writeInt ( allocated );
  1784. for ( int i = 0; i < 10; i++ )
  1785. stream->writeInt ( dummy[i] );
  1786. if ( used > 0 )
  1787. stream->writedata ( buf, used );
  1788. }
  1789. }
  1790. void MemoryStreamStorage :: readfromstream ( tnstream* stream )
  1791. {
  1792. if ( stream ) {
  1793. stream->readInt();
  1794. used = stream->readInt();
  1795. allocated = stream->readInt();
  1796. for ( int i = 0; i< 10; i++ )
  1797. dummy[i] = stream->readInt();
  1798. if ( buf ) {
  1799. delete[] buf;
  1800. buf = NULL;
  1801. }
  1802. if ( used > 0 || allocated > 0 ) {
  1803. allocated = max(allocated,used);
  1804. buf = new char[allocated];
  1805. stream->readdata ( buf, used );
  1806. }
  1807. }
  1808. }
  1809. MemoryStream :: MemoryStream ( MemoryStreamStorage* lbuf, IOMode lmode )
  1810. {
  1811. blocksize = 1024;
  1812. buf = lbuf;
  1813. _mode = lmode;
  1814. if ( !buf )
  1815. throw tfileerror ( "memorystream" );
  1816. if ( _mode == reading ) {
  1817. pointer = buf->buf;
  1818. actmempos = 0;
  1819. } else
  1820. if ( _mode == writing ) { // neuen Puffer anlegen
  1821. if ( buf->buf ) {
  1822. delete[] buf->buf;
  1823. buf->buf = NULL;
  1824. }
  1825. buf->buf = new char[blocksize];
  1826. buf->allocated = blocksize;
  1827. buf->used = 0;
  1828. pointer = buf->buf;
  1829. actmempos = 0;
  1830. }
  1831. if ( _mode == appending ) {
  1832. pointer = buf->buf;
  1833. actmempos = buf->used;
  1834. _mode = writing;
  1835. }
  1836. }
  1837. void MemoryStream :: writedata ( const void* nbuf, int size )
  1838. {
  1839. if ( _mode != writing )
  1840. throw tinvalidmode ( "memorystream", _mode, writing );
  1841. if ( buf->used + size > buf->allocated ) {
  1842. int newsize = ((buf->used + size + blocksize - 1) / blocksize);
  1843. newsize *= blocksize;
  1844. char* tmp = new char[newsize];
  1845. memcpy ( tmp, buf->buf, buf->used );
  1846. delete[] buf->buf;
  1847. buf->buf = tmp;
  1848. buf->allocated = newsize;
  1849. }
  1850. memcpy ( &buf->buf[buf->used], nbuf, size );
  1851. buf->used += size;
  1852. }
  1853. int MemoryStream :: readdata ( void* nbuf, int size, bool excpt )
  1854. {
  1855. if (_mode != reading )
  1856. throw tinvalidmode ( "memorystream", _mode, reading );
  1857. if ( actmempos + size > buf->used ) {
  1858. if ( excpt )
  1859. throw treadafterend ( "memory stream" );
  1860. else
  1861. size = buf->used-actmempos;
  1862. }
  1863. memcpy ( nbuf, &buf->buf[actmempos], size );
  1864. actmempos += size;
  1865. return size;
  1866. }
  1867. int MemoryStream :: dataavail ( void )
  1868. {
  1869. if ( _mode == writing )
  1870. return 1;
  1871. else
  1872. return actmempos < buf->used;
  1873. }
  1874. ASCString getnextfilenumname ( const ASCString& first, const ASCString& suffix, int num )
  1875. {
  1876. ASCString name;
  1877. if ( num < 0 )
  1878. num = 0;
  1879. do {
  1880. name = first;
  1881. while ( name.length() - first.length() + ASCString::toString(num).length() < 3 )
  1882. name += "0";
  1883. name += ASCString::toString(num) + "." + suffix;
  1884. tfindfile ff ( name );
  1885. ASCString c = ff.getnextname();
  1886. if ( c.empty() )
  1887. return name;
  1888. num++;
  1889. } while ( true );
  1890. return "";
  1891. }
  1892. bool exist ( const ASCString& s )
  1893. {
  1894. tfindfile ff ( s );
  1895. return !ff.getnextname().empty();
  1896. }
  1897. #include "oldlzw.cpp"
  1898. void tnbufstream :: writebuffer( void ) {
  1899. }
  1900. void opencontainer ( const char* wildcard )
  1901. {
  1902. if ( !searchDirNum )
  1903. addSearchPath(".");
  1904. containercollector.init ( wildcard );
  1905. }
  1906. time_t get_filetime ( const char* fileName )
  1907. {
  1908. FileLocation fl;
  1909. locateFile ( fileName, &fl );
  1910. if ( fl.found ) {
  1911. if ( fl.container )
  1912. return fl.container->get_time();
  1913. else {
  1914. struct stat stbuf;
  1915. char buf[ maxFileStringSize ];
  1916. if ( !stat ( constructFileName ( buf, fl.directoryLevel, NULL, fileName), &stbuf) )
  1917. return ( stbuf.st_mtime);
  1918. else
  1919. return -1;
  1920. }
  1921. } else
  1922. return -1;
  1923. }
  1924. int filesize( const char *name)
  1925. {
  1926. struct stat buf;
  1927. if ( !stat (name, &buf))
  1928. return (buf.st_size);
  1929. else
  1930. return -1;
  1931. }
  1932. bool directoryExist ( const ASCString& path )
  1933. {
  1934. bool existence = false;
  1935. DIR *dirp = opendir( path.c_str() );
  1936. if( dirp ) {
  1937. if ( readdir( dirp ) )
  1938. existence = true;
  1939. else
  1940. existence = false;
  1941. closedir( dirp );
  1942. }
  1943. return existence;
  1944. }
  1945. void addSearchPath ( const ASCString& path )
  1946. {
  1947. if ( !path.empty() ) {
  1948. ASCString s = constructFileName ( -3, path, "" );
  1949. if ( directoryExist( s.c_str() )) {
  1950. bool found = false;
  1951. for ( int i = 0; i < searchDirNum; i++ )
  1952. if ( s == ascDirectory[i] )
  1953. found = true;
  1954. if ( !found )
  1955. ascDirectory[ searchDirNum++ ] = strdup ( s.c_str() );
  1956. }
  1957. }
  1958. }
  1959. int getSearchPathNum()
  1960. {
  1961. return searchDirNum;
  1962. }
  1963. ASCString getSearchPath ( int i )
  1964. {
  1965. if ( i < searchDirNum )
  1966. return ascDirectory[i];
  1967. else
  1968. return "";
  1969. }
  1970. char* extractPath ( char* buf, const char* filename )
  1971. {
  1972. if ( buf && filename ) {
  1973. if ( strchr ( filename, pathdelimitter )) {
  1974. strcpy ( buf, filename );
  1975. int i = strlen ( buf )-1;
  1976. while ( buf[i] != pathdelimitter )
  1977. i--;
  1978. buf[i+1] = 0;
  1979. } else
  1980. strcpy ( buf, "./" );
  1981. }
  1982. return buf;
  1983. }
  1984. char* extractFileName ( char* buf, const char* filename )
  1985. {
  1986. if ( buf && filename ) {
  1987. if ( strchr ( filename, pathdelimitter )) {
  1988. int i = strlen ( filename )-1;
  1989. while ( filename[i] != pathdelimitter )
  1990. i--;
  1991. strcpy ( buf, filename +i+1);
  1992. } else
  1993. strcpy ( buf, filename );
  1994. }
  1995. return buf;
  1996. }
  1997. ASCString extractFileName ( const ASCString& filename )
  1998. {
  1999. char buf[10000];
  2000. return extractFileName( buf, filename.c_str() );
  2001. }
  2002. ASCString extractFileName_withoutSuffix ( const ASCString& filename )
  2003. {
  2004. char buf[10000];
  2005. extractFileName( buf, filename.c_str() );
  2006. char* c = strchr ( buf, '.' );
  2007. if ( c )
  2008. *c = 0;
  2009. return ASCString(buf);
  2010. }
  2011. void appendbackslash ( char* string )
  2012. {
  2013. if ( strlen ( string ) && string[strlen ( string ) -1] != pathdelimitter )
  2014. strcat ( string, pathdelimitterstring );
  2015. }
  2016. void appendbackslash ( ASCString& string )
  2017. {
  2018. if ( !string.empty() && string[ string.length() -1] != pathdelimitter )
  2019. string += pathdelimitterstring ;
  2020. }
  2021. int createDirectory ( const char* name )
  2022. {
  2023. #ifdef _UNIX_
  2024. char *nname;
  2025. int i;
  2026. if (name == NULL || (nname=strdup(name)) == NULL)
  2027. return -1;
  2028. i = strlen(nname);
  2029. /* leave one '/' */
  2030. while (i>1 && nname[i-1] == '/')
  2031. nname[--i] = '\0';
  2032. i = mkdir ( nname, 0700 );
  2033. free(nname);
  2034. return i;
  2035. #else
  2036. return mkdir ( name );
  2037. #endif
  2038. }
  2039. ASCString FileName::suffix ( )
  2040. {
  2041. size_type slash = find_last_of ( pathdelimitterstring );
  2042. size_type point = find_last_of ( "." );
  2043. if ( point == npos )
  2044. return "";
  2045. else
  2046. if ( slash == npos || slash < point )
  2047. return substr(point+1);
  2048. else
  2049. return "";
  2050. }
  2051. void convertPathDelimitters ( ASCString& path )
  2052. {
  2053. int pos;
  2054. while ( (pos = path.find ( foreignPathDelimitterString )) != path.npos )
  2055. path.replace ( pos, 1, pathdelimitterstring );
  2056. }