26#include "KoTarStore.h"
27#include "KoZipStore.h"
28#include "KoDirectoryStore.h"
30#include <tqfileinfo.h>
36#include <tdeversion.h>
38#include <tdemessagebox.h>
39#include <tdeio/netaccess.h>
42#define DefaultFormat KoStore::Zip
44const int KoStore::s_area = 30002;
46KoStore::Backend KoStore::determineBackend( TQIODevice* dev )
49 if ( dev->readBlock( (
char *)buf, 4 ) < 4 )
51 if ( buf[0] == 0037 && buf[1] == 0213 )
53 if ( buf[0] ==
'P' && buf[1] ==
'K' && buf[2] == 3 && buf[3] == 4 )
60 if ( backend == Auto ) {
61 if (
mode == KoStore::Write )
62 backend = DefaultFormat;
65 TQFileInfo inf( fileName );
70 TQFile file( fileName );
71 if ( file.open( IO_ReadOnly ) )
72 backend = determineBackend( &file );
74 backend = DefaultFormat;
81 return new KoTarStore( fileName,
mode, appIdentification );
83 return new KoZipStore( fileName,
mode, appIdentification );
85 return new KoDirectoryStore( fileName ,
mode );
87 kdWarning(s_area) <<
"Unsupported backend requested for KoStore : " << backend << endl;
94 if ( backend == Auto )
96 if (
mode == KoStore::Write )
97 backend = DefaultFormat;
99 if (
device->open( IO_ReadOnly ) ) {
100 backend = determineBackend(
device );
108 return new KoTarStore(
device,
mode, appIdentification );
110 kdError(s_area) <<
"Can't create a Directory store for a memory buffer!" << endl;
113 return new KoZipStore(
device,
mode, appIdentification );
115 kdWarning(s_area) <<
"Unsupported backend requested for KoStore : " << backend << endl;
122 if ( url.isLocalFile() )
126 if (
mode == KoStore::Write )
128 if ( backend == Auto )
129 backend = DefaultFormat;
133 const bool downloaded =
134 TDEIO::NetAccess::download( url, tmpFile, window );
138 kdError(s_area) <<
"Could not download file!" << endl;
139 backend = DefaultFormat;
141 else if ( backend == Auto )
143 TQFile file( tmpFile );
144 if ( file.open( IO_ReadOnly ) )
146 backend = determineBackend( &file );
154 return new KoTarStore( window, url, tmpFile,
mode, appIdentification );
156 return new KoZipStore( window, url, tmpFile,
mode, appIdentification );
158 kdWarning(s_area) <<
"Unsupported backend requested for KoStore (KURL) : " << backend << endl;
160 i18n(
"The directory mode is not supported for remote locations."),
161 i18n(
"KOffice Storage"));
167 const char*
const ROOTPART =
"root";
168 const char*
const MAINNAME =
"maindoc.xml";
179 m_namingVersion = NAMING_VERSION_2_2;
191 m_sName = toExternalNaming( _name );
195 kdWarning(s_area) <<
"KoStore: File is already opened" << endl;
202 kdError(s_area) <<
"KoStore: Filename " <<
m_sName <<
" is too long" << endl;
207 if ( m_mode == Write )
209 kdDebug(s_area) <<
"KoStore: opening for writing '" <<
m_sName <<
"'" << endl;
212 kdWarning(s_area) <<
"KoStore: Duplicate filename " <<
m_sName << endl;
223 else if ( m_mode == Read )
225 kdDebug(s_area) <<
"Opening for reading '" <<
m_sName <<
"'" << endl;
244 kdDebug(s_area) <<
"KoStore: Closing" << endl;
248 kdWarning(s_area) <<
"KoStore: You must open before closing" << endl;
264 kdWarning(s_area) <<
"KoStore: You must open before asking for a device" << endl;
265 if ( m_mode != Read )
266 kdWarning(s_area) <<
"KoStore: Can not get device from store that is opened for writing" << endl;
276 kdWarning(s_area) <<
"KoStore: You must open before reading" << endl;
280 if ( m_mode != Read )
282 kdError(s_area) <<
"KoStore: Can not read from store that is opened for writing" << endl;
301 char *p =
new char[ max ];
304 data.setRawData( p, max );
310 return write( data.data(), data.size() );
317 kdError(s_area) <<
"KoStore: You must open before reading" << endl;
320 if ( m_mode != Read )
322 kdError(s_area) <<
"KoStore: Can not read from store that is opened for writing" << endl;
334 return m_stream->readBlock( _buffer, _len );
339 if ( _len == 0L )
return 0;
343 kdError(s_area) <<
"KoStore: You must open before writing" << endl;
346 if ( m_mode != Write )
348 kdError(s_area) <<
"KoStore: Can not write to store that is opened for reading" << endl;
352 int nwritten =
m_stream->writeBlock( _data, _len );
353 Q_ASSERT( nwritten == (
int)_len );
363 kdWarning(s_area) <<
"KoStore: You must open before asking for a size" << endl;
364 return static_cast<TQIODevice::Offset
>(-1);
366 if ( m_mode != Read )
368 kdWarning(s_area) <<
"KoStore: Can not get size from store that is opened for writing" << endl;
369 return static_cast<TQIODevice::Offset
>(-1);
379 TQString tmp( directory );
381 while ( ( pos = tmp.find(
'/' ) ) != -1 &&
382 ( success = enterDirectoryInternal( tmp.left( pos ) ) ) )
383 tmp = tmp.mid( pos + 1 );
385 if ( success && !tmp.isEmpty() )
386 return enterDirectoryInternal( tmp );
410 for ( ; it != end; ++it ) {
431 TQFileInfo fi( fileName );
432 uint
size = fi.size();
433 TQFile file( fileName );
434 if ( !file.open( IO_ReadOnly ))
439 if ( !
open ( destName ) )
444 TQByteArray data ( 8 * 1024 );
447 for (
int block = 0; ( block = file.readBlock ( data.data(), data.size() ) ) > 0; total += block )
450 if (
write( data ) != block )
454 Q_ASSERT( total ==
size );
464 if ( !
open ( srcName ) )
467 TQFile file( fileName );
469 if( !file.open ( IO_WriteOnly ) )
475 TQByteArray data ( 8 * 1024 );
477 for(
int block = 0; ( block =
read ( data.data(), data.size() ) ) > 0; total += block )
479 file.writeBlock ( data.data(), block );
482 if(
size() !=
static_cast<TQIODevice::Offset
>(-1) )
483 Q_ASSERT( total ==
size() );
494 TQString dotdot =
"..";
495 TQStringList content;
501 TQStringList files = dir.entryList();
502 for ( TQStringList::Iterator it = files.begin(); it != files.end(); ++it )
504 if ( *it != dot && *it != dotdot )
506 TQString currentFile = dirPath +
"/" + *it;
507 TQString dest = destName.isEmpty() ? *it : (destName +
"/" + *it);
509 TQFileInfo fi ( currentFile );
513 content.append(dest);
515 else if ( fi.isDir() )
531TQIODevice::Offset KoStore::at()
const
536bool KoStore::atEnd()
const
542TQString KoStore::toExternalNaming(
const TQString & _internalNaming )
const
544 if ( _internalNaming == ROOTPART )
545 return expandEncodedDirectory(
currentPath() ) + MAINNAME;
548 if ( _internalNaming.startsWith(
"tar:/" ) )
549 intern = _internalNaming.mid( 5 );
553 return expandEncodedPath( intern );
556TQString KoStore::expandEncodedPath( TQString intern )
const
558 if ( m_namingVersion == NAMING_VERSION_RAW )
564 if ( ( pos = intern.findRev(
'/', -1 ) ) != -1 ) {
565 result = expandEncodedDirectory( intern.left( pos ) ) +
'/';
566 intern = intern.mid( pos + 1 );
571 if ( TQChar(intern.at(0)).isDigit() )
575 if ( ( m_namingVersion == NAMING_VERSION_2_2 ) &&
576 ( m_mode == Read ) &&
577 (
fileExists( result +
"part" + intern +
".xml" ) ) )
578 m_namingVersion = NAMING_VERSION_2_1;
580 if ( m_namingVersion == NAMING_VERSION_2_1 )
581 result = result +
"part" + intern +
".xml";
583 result = result +
"part" + intern +
"/" + MAINNAME;
590TQString KoStore::expandEncodedDirectory( TQString intern )
const
592 if ( m_namingVersion == NAMING_VERSION_RAW )
597 while ( ( pos = intern.find(
'/' ) ) != -1 ) {
598 if ( TQChar(intern.at(0)).isDigit() )
600 result += intern.left( pos + 1 );
601 intern = intern.mid( pos + 1 );
604 if ( TQChar(intern.at(0)).isDigit() )
610bool KoStore::enterDirectoryInternal(
const TQString& directory )
622 m_namingVersion = NAMING_VERSION_RAW;
static void sorry(TQWidget *parent, const TQString &text, const TQString &caption=TQString::null, int options=Notify)
Saves and loads KOffice documents using various backends.
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.