26#include "KoTarStore.h"
27#include "KoZipStore.h"
28#include "KoDirectoryStore.h"
30#include <tqfileinfo.h>
37#include <tdemessagebox.h>
38#include <tdeio/netaccess.h>
41#define DefaultFormat KoStore::Zip
43const int KoStore::s_area = 30002;
45KoStore::Backend KoStore::determineBackend( TQIODevice* dev )
48 if ( dev->readBlock( (
char *)buf, 4 ) < 4 )
50 if ( buf[0] == 0037 && buf[1] == 0213 )
52 if ( buf[0] ==
'P' && buf[1] ==
'K' && buf[2] == 3 && buf[3] == 4 )
59 if ( backend == Auto ) {
60 if (
mode == KoStore::Write )
61 backend = DefaultFormat;
64 TQFileInfo inf( fileName );
69 TQFile file( fileName );
70 if ( file.open( IO_ReadOnly ) )
71 backend = determineBackend( &file );
73 backend = DefaultFormat;
80 return new KoTarStore( fileName,
mode, appIdentification );
82 return new KoZipStore( fileName,
mode, appIdentification );
84 return new KoDirectoryStore( fileName ,
mode );
86 kdWarning(s_area) <<
"Unsupported backend requested for KoStore : " << backend << endl;
93 if ( backend == Auto )
95 if (
mode == KoStore::Write )
96 backend = DefaultFormat;
98 if (
device->open( IO_ReadOnly ) ) {
99 backend = determineBackend(
device );
107 return new KoTarStore(
device,
mode, appIdentification );
109 kdError(s_area) <<
"Can't create a Directory store for a memory buffer!" << endl;
112 return new KoZipStore(
device,
mode, appIdentification );
114 kdWarning(s_area) <<
"Unsupported backend requested for KoStore : " << backend << endl;
121 if ( url.isLocalFile() )
125 if (
mode == KoStore::Write )
127 if ( backend == Auto )
128 backend = DefaultFormat;
132 const bool downloaded =
133 TDEIO::NetAccess::download( url, tmpFile, window );
137 kdError(s_area) <<
"Could not download file!" << endl;
138 backend = DefaultFormat;
140 else if ( backend == Auto )
142 TQFile file( tmpFile );
143 if ( file.open( IO_ReadOnly ) )
145 backend = determineBackend( &file );
153 return new KoTarStore( window, url, tmpFile,
mode, appIdentification );
155 return new KoZipStore( window, url, tmpFile,
mode, appIdentification );
157 kdWarning(s_area) <<
"Unsupported backend requested for KoStore (KURL) : " << backend << endl;
159 i18n(
"The directory mode is not supported for remote locations."),
160 i18n(
"KOffice Storage"));
166 const char*
const ROOTPART =
"root";
167 const char*
const MAINNAME =
"maindoc.xml";
178 m_namingVersion = NAMING_VERSION_2_2;
190 m_sName = toExternalNaming( _name );
194 kdWarning(s_area) <<
"KoStore: File is already opened" << endl;
201 kdError(s_area) <<
"KoStore: Filename " <<
m_sName <<
" is too long" << endl;
206 if ( m_mode == Write )
208 kdDebug(s_area) <<
"KoStore: opening for writing '" <<
m_sName <<
"'" << endl;
211 kdWarning(s_area) <<
"KoStore: Duplicate filename " <<
m_sName << endl;
222 else if ( m_mode == Read )
224 kdDebug(s_area) <<
"Opening for reading '" <<
m_sName <<
"'" << endl;
243 kdDebug(s_area) <<
"KoStore: Closing" << endl;
247 kdWarning(s_area) <<
"KoStore: You must open before closing" << endl;
263 kdWarning(s_area) <<
"KoStore: You must open before asking for a device" << endl;
264 if ( m_mode != Read )
265 kdWarning(s_area) <<
"KoStore: Can not get device from store that is opened for writing" << endl;
275 kdWarning(s_area) <<
"KoStore: You must open before reading" << endl;
279 if ( m_mode != Read )
281 kdError(s_area) <<
"KoStore: Can not read from store that is opened for writing" << endl;
300 char *p =
new char[ max ];
303 data.setRawData( p, max );
309 return write( data.data(), data.size() );
316 kdError(s_area) <<
"KoStore: You must open before reading" << endl;
319 if ( m_mode != Read )
321 kdError(s_area) <<
"KoStore: Can not read from store that is opened for writing" << endl;
333 return m_stream->readBlock( _buffer, _len );
338 if ( _len == 0L )
return 0;
342 kdError(s_area) <<
"KoStore: You must open before writing" << endl;
345 if ( m_mode != Write )
347 kdError(s_area) <<
"KoStore: Can not write to store that is opened for reading" << endl;
351 int nwritten =
m_stream->writeBlock( _data, _len );
352 Q_ASSERT( nwritten == (
int)_len );
362 kdWarning(s_area) <<
"KoStore: You must open before asking for a size" << endl;
363 return static_cast<TQIODevice::Offset
>(-1);
365 if ( m_mode != Read )
367 kdWarning(s_area) <<
"KoStore: Can not get size from store that is opened for writing" << endl;
368 return static_cast<TQIODevice::Offset
>(-1);
378 TQString tmp( directory );
380 while ( ( pos = tmp.find(
'/' ) ) != -1 &&
381 ( success = enterDirectoryInternal( tmp.left( pos ) ) ) )
382 tmp = tmp.mid( pos + 1 );
384 if ( success && !tmp.isEmpty() )
385 return enterDirectoryInternal( tmp );
409 for ( ; it != end; ++it ) {
430 TQFileInfo fi( fileName );
431 uint
size = fi.size();
432 TQFile file( fileName );
433 if ( !file.open( IO_ReadOnly ))
438 if ( !
open ( destName ) )
443 TQByteArray data ( 8 * 1024 );
446 for (
int block = 0; ( block = file.readBlock ( data.data(), data.size() ) ) > 0; total += block )
449 if (
write( data ) != block )
453 Q_ASSERT( total ==
size );
463 if ( !
open ( srcName ) )
466 TQFile file( fileName );
468 if( !file.open ( IO_WriteOnly ) )
474 TQByteArray data ( 8 * 1024 );
476 for(
int block = 0; ( block =
read ( data.data(), data.size() ) ) > 0; total += block )
478 file.writeBlock ( data.data(), block );
481 if(
size() !=
static_cast<TQIODevice::Offset
>(-1) )
482 Q_ASSERT( total ==
size() );
493 TQString dotdot =
"..";
494 TQStringList content;
500 TQStringList files = dir.entryList();
501 for ( TQStringList::Iterator it = files.begin(); it != files.end(); ++it )
503 if ( *it != dot && *it != dotdot )
505 TQString currentFile = dirPath +
"/" + *it;
506 TQString dest = destName.isEmpty() ? *it : (destName +
"/" + *it);
508 TQFileInfo fi ( currentFile );
512 content.append(dest);
514 else if ( fi.isDir() )
535bool KoStore::atEnd()
const
541TQString KoStore::toExternalNaming(
const TQString & _internalNaming )
const
543 if ( _internalNaming == ROOTPART )
544 return expandEncodedDirectory(
currentPath() ) + MAINNAME;
547 if ( _internalNaming.startsWith(
"tar:/" ) )
548 intern = _internalNaming.mid( 5 );
552 return expandEncodedPath( intern );
555TQString KoStore::expandEncodedPath( TQString intern )
const
557 if ( m_namingVersion == NAMING_VERSION_RAW )
563 if ( ( pos = intern.findRev(
'/', -1 ) ) != -1 ) {
564 result = expandEncodedDirectory( intern.left( pos ) ) +
'/';
565 intern = intern.mid( pos + 1 );
570 if ( TQChar(intern.at(0)).isDigit() )
574 if ( ( m_namingVersion == NAMING_VERSION_2_2 ) &&
575 ( m_mode == Read ) &&
576 (
fileExists( result +
"part" + intern +
".xml" ) ) )
577 m_namingVersion = NAMING_VERSION_2_1;
579 if ( m_namingVersion == NAMING_VERSION_2_1 )
580 result = result +
"part" + intern +
".xml";
582 result = result +
"part" + intern +
"/" + MAINNAME;
589TQString KoStore::expandEncodedDirectory( TQString intern )
const
591 if ( m_namingVersion == NAMING_VERSION_RAW )
596 while ( ( pos = intern.find(
'/' ) ) != -1 ) {
597 if ( TQChar(intern.at(0)).isDigit() )
599 result += intern.left( pos + 1 );
600 intern = intern.mid( pos + 1 );
603 if ( TQChar(intern.at(0)).isDigit() )
609bool KoStore::enterDirectoryInternal(
const TQString& directory )
621 m_namingVersion = NAMING_VERSION_RAW;
static void sorry(TQWidget *parent, const TQString &text, const TQString &caption=TQString::null, int options=Notify)
bool close()
Close the file inside the store.
virtual bool closeRead()=0
virtual bool openRead(const TQString &name)=0
Open the file name in the store, for reading.
bool isOpen() const
Check whether a file inside the store is currently opened with open(), ready to be read or written.
virtual bool closeWrite()=0
bool hasFile(const TQString &fileName) const
virtual bool openWrite(const TQString &name)=0
Open the file name in the store, for writing On success, this method must set m_stream to a stream in...
TQStringList m_currentPath
The "current directory" (path).
void pushDirectory()
Stacks the current directory.
void popDirectory()
Restores the previously pushed directory.
bool leaveDirectory()
Leaves a directory.
TQIODevice * device() const
Get a device for reading a file from the store directly (slightly faster than read() calls) You need ...
virtual bool fileExists(const TQString &absPath) const =0
Check if a file exists inside the store.
TQString m_sName
Current filename (between an open() and a close()).
bool open(const TQString &name)
Open a new file inside the store.
TQIODevice::Offset m_iSize
Current size of the file named m_sName.
TQIODevice::Offset size() const
virtual bool init(Mode mode)
Init store - called by constructor.
bool extractFile(const TQString &srcName, const TQString &fileName)
Extracts a file out of the store.
TQString currentPath() const
Returns the current path including a trailing slash.
TQStringList addLocalDirectory(const TQString &dirPath, const TQString &dest)
Imports a local directory.
bool at(TQIODevice::Offset pos)
See TQIODevice.
virtual bool enterRelativeDirectory(const TQString &dirName)=0
Enter a subdirectory of the current directory.
virtual bool enterAbsoluteDirectory(const TQString &path)=0
Enter a directory where we've been before.
TQ_LONG write(const TQByteArray &_data)
Write data into the currently opened file.
static KoStore * createStore(const TQString &fileName, Mode mode, const TQCString &appIdentification="", Backend backend=Auto)
Open a store (i.e.
void disallowNameExpansion(void)
Do not expand file and directory names Useful when using KoStore on non-KOffice files.
bool enterDirectory(const TQString &directory)
Enters one or multiple directories.
virtual ~KoStore()
Destroys the store (i.e.
TQString currentDirectory() const
Returns the current directory.
TQByteArray read(unsigned long int max)
Read data from the currently opened file.
bool addLocalFile(const TQString &fileName, const TQString &destName)
Imports a local file into a store.
TQValueStack< TQString > m_directoryStack
Used to push/pop directories to make it easy to save/restore the state.
TQIODevice * m_stream
The stream for the current read or write operation.
TQStringList m_strFiles
Store the filenames (with full path inside the archive) when writing, to avoid duplicates.