File indexing completed on 2024-05-19 04:52:44
0001 // -*- c-basic-offset: 2 -*- 0002 /* This file is part of the KDE project 0003 SPDX-FileCopyrightText: 1998, 1999 David Faure <faure@kde.org> 0004 0005 SPDX-License-Identifier: LGPL-2.0-or-later 0006 */ 0007 0008 #ifndef __koStore_h_ 0009 #define __koStore_h_ 0010 0011 #include <QString> 0012 #include <QStringList> 0013 #include <QStack> 0014 0015 class QByteArray; 0016 class QIODevice; 0017 class QWidget; 0018 class QUrl; 0019 0020 /** 0021 * Saves and loads KOffice documents using various backends. Currently supported 0022 * backends are ZIP, tar and directory. 0023 * We call a "store" the file on the hard disk (the one the users sees) 0024 * and call a "file" a file inside the store. 0025 */ 0026 class /*KOSTORE_EXPORT*/ KoStore 0027 { 0028 public: 0029 0030 enum Mode { Read, Write }; 0031 enum Backend { Auto, Tar, Zip, Directory, Encrypted }; 0032 0033 /** 0034 * Open a store (i.e. the representation on disk of a KOffice document). 0035 * 0036 * @param fileName the name of the file to open 0037 * @param mode if KoStore::Read, open an existing store to read it. 0038 * if KoStore::Write, create or replace a store. 0039 * @param backend the backend to use for the data storage. 0040 * Auto means automatically-determined for reading, 0041 * and the current format (now Zip) for writing. 0042 * 0043 * @param appIdentification the application's mimetype, 0044 * to be written in the file for "mime-magic" identification. 0045 * Only meaningful if mode is Write, and if backend!=Directory. 0046 */ 0047 static KoStore* createStore( const QString& fileName, Mode mode, const QByteArray & appIdentification = "", Backend backend = Auto ); 0048 0049 /** 0050 * Create a store for any kind of QIODevice: file, memory buffer... 0051 * KoStore will take care of opening the QIODevice. 0052 * This method doesn't support the Directory store! 0053 */ 0054 static KoStore* createStore( QIODevice *device, Mode mode, const QByteArray & appIdentification = "", Backend backend = Auto ); 0055 0056 /** 0057 * Open a store (i.e. the representation on disk of a KOffice document). 0058 * 0059 * @param window associated window (for the progress bar dialog and authentication) 0060 * @param url URL of the file to open 0061 * @param mode if KoStore::Read, open an existing store to read it. 0062 * if KoStore::Write, create or replace a store. 0063 * @param backend the backend to use for the data storage. 0064 * Auto means automatically-determined for reading, 0065 * and the current format (now Zip) for writing. 0066 * 0067 * @param appIdentification the application's mimetype, 0068 * to be written in the file for "mime-magic" identification. 0069 * Only meaningful if mode is Write, and if backend!=Directory. 0070 * 0071 * If the file is remote, the backend Directory cannot be used! 0072 * 0073 * @bug saving not completely implemented (fixed temporary file) 0074 */ 0075 static KoStore* createStore( QWidget* window, const QUrl& url, Mode mode, const QByteArray & appIdentification = "", Backend backend = Auto ); 0076 0077 /** 0078 * Destroys the store (i.e. closes the file on the hard disk) 0079 */ 0080 virtual ~KoStore(); 0081 0082 /** 0083 * Open a new file inside the store 0084 * @param name The filename, internal representation ("root", "tar:/0"... ). 0085 * If the tar:/ prefix is missing it's assumed to be a relative URI. 0086 * @return true on success. 0087 */ 0088 bool open( const QString & name ); 0089 0090 /** 0091 * Check whether a file inside the store is currently opened with open(), 0092 * ready to be read or written. 0093 * @return true if a file is currently opened. 0094 */ 0095 bool isOpen() const; 0096 0097 /** 0098 * Close the file inside the store 0099 * @return true on success. 0100 */ 0101 bool close(); 0102 0103 /** 0104 * Get a device for reading a file from the store directly 0105 * (slightly faster than read() calls) 0106 * You need to call @ref open first, and @ref close afterwards. 0107 */ 0108 QIODevice* device() const; 0109 0110 /** 0111 * Read data from the currently opened file. You can also use the streams 0112 * for this. 0113 */ 0114 QByteArray read( qint64 max ); 0115 0116 /** 0117 * Write data into the currently opened file. You can also use the streams 0118 * for this. 0119 */ 0120 qint64 write( const QByteArray& _data ); 0121 0122 /** 0123 * Read data from the currently opened file. You can also use the streams 0124 * for this. 0125 * @return size of data read, -1 on error 0126 */ 0127 qint64 read( char *_buffer, qint64 _len ); 0128 0129 /** 0130 * Write data into the currently opened file. You can also use the streams 0131 * for this. 0132 */ 0133 virtual qint64 write( const char* _data, qint64 _len ); 0134 0135 /** 0136 * @return the size of the currently opened file, -1 on error. 0137 * Can be used as an argument for the read methods, for instance 0138 */ 0139 qint64 size() const; 0140 0141 /** 0142 * @return true if an error occurred 0143 */ 0144 bool bad() const { return !m_bGood; } // :) 0145 0146 /** 0147 * @return the mode used when opening, read or write 0148 */ 0149 Mode mode() const { return m_mode; } 0150 0151 /** 0152 * Enters one or multiple directories. In Read mode this actually 0153 * checks whether the specified directories exist and returns false 0154 * if they don't. In Write mode we don't create the directory, we 0155 * just use the "current directory" to generate the absolute path 0156 * if you pass a relative path (one not starting with tar:/) when 0157 * opening a stream. 0158 * Note: Operates on internal names 0159 */ 0160 bool enterDirectory( const QString& directory ); 0161 0162 /** 0163 * Leaves a directory. Equivalent to "cd .." 0164 * @return true on success, false if we were at the root already to 0165 * make it possible to "loop to the root" 0166 */ 0167 bool leaveDirectory(); 0168 0169 /** 0170 * Returns the current path including a trailing slash. 0171 * Note: Returns a path in "internal name" style 0172 */ 0173 QString currentPath() const; 0174 0175 /** 0176 * Returns the current directory. 0177 * Note: Returns a path in "internal name" style 0178 */ 0179 QString currentDirectory() const; 0180 0181 0182 /** 0183 * Stacks the current directory. Restore the current path using 0184 * @ref popDirectory . 0185 */ 0186 void pushDirectory(); 0187 0188 /** 0189 * Restores the previously pushed directory. No-op if the stack is 0190 * empty. 0191 */ 0192 void popDirectory(); 0193 0194 /** 0195 * @return true if the given file exists in the current directory, 0196 * i.e. if open(fileName) will work. 0197 */ 0198 bool hasFile( const QString& fileName ) const; 0199 0200 /** 0201 * Imports a local file into a store 0202 * @param fileName file on hard disk 0203 * @param destName file in the store 0204 */ 0205 bool addLocalFile( const QString &fileName, const QString &destName ); 0206 0207 /** 0208 * Imports data into a store 0209 * @param buffer data 0210 * @param destName file in the store 0211 */ 0212 bool addDataToFile( QByteArray &buffer, const QString &destName ); 0213 0214 /** 0215 * Imports a local directory 0216 * @param dirPath path to the directory on a disk 0217 * @param dest path in the store where the directory should get saved 0218 * @return the directory index 0219 */ 0220 QStringList addLocalDirectory( const QString &dirPath, const QString &dest ); 0221 0222 0223 /** 0224 * Extracts a file out of the store 0225 * @param srcName file in the store 0226 * @param fileName file on a disk 0227 */ 0228 bool extractFile( const QString &srcName, const QString &fileName ); 0229 0230 /** 0231 * Extracts a file out of the store to a buffer 0232 * @param srcName file in the store 0233 * @param data memory buffer 0234 */ 0235 bool extractFile( const QString &srcName, QByteArray &data ); 0236 0237 //@{ 0238 /// See QIODevice 0239 bool seek( qint64 pos ); 0240 qint64 pos() const; 0241 bool atEnd() const; 0242 //@} 0243 0244 /** 0245 * Do not expand file and directory names 0246 * Useful when using KoStore on non-KOffice files. 0247 * (This method should be called just after the constructor) 0248 */ 0249 void disallowNameExpansion( void ); 0250 0251 /** 0252 * Call this before destroying the store, to be able to catch errors 0253 * (e.g. from ksavefile) 0254 */ 0255 bool finalize(); 0256 0257 /** 0258 * Sets the password to be used for decryption or encryption of the store. 0259 * Use of this function is optional: an encryptable store should make 0260 * a best effort in obtaining a password if it wasn't supplied. 0261 * 0262 * This method only works before opening a file. It might fail when a file 0263 * has already been opened before calling this method. 0264 * 0265 * This method will not function for any store that is not encrypted or 0266 * can't be encrypted when saving. 0267 * 0268 * @param password A non-empty password. 0269 * 0270 * @return True if the password was set. 0271 */ 0272 virtual bool setPassword( const QString& password ); 0273 0274 /** 0275 * Retrieves the password used to encrypt or decrypt the store. Note that 0276 * QString() will returned if no password has been given or the store is 0277 * not encrypted. 0278 * 0279 * @return The password this store is encrypted with. 0280 */ 0281 virtual QString password( ); 0282 0283 /** 0284 * Returns whether a store opened for reading is encrypted or a store opened 0285 * for saving will be encrypted. 0286 * 0287 * @return True if the store is encrypted. 0288 */ 0289 virtual bool isEncrypted( ); 0290 0291 protected: 0292 0293 KoStore(); 0294 0295 /** 0296 * Init store - called by constructor. 0297 * @return true on success 0298 */ 0299 virtual bool init( Mode mode ); 0300 0301 /** 0302 * Finalize store - called by finalize. 0303 * @return true on success 0304 */ 0305 virtual bool doFinalize() { return true; } 0306 0307 /** 0308 * Open the file @p name in the store, for writing 0309 * On success, this method must set m_stream to a stream in which we can write. 0310 * @param name "absolute path" (in the archive) to the file to open 0311 * @return true on success 0312 */ 0313 virtual bool openWrite( const QString& name ) = 0; 0314 /** 0315 * Open the file @p name in the store, for reading. 0316 * On success, this method must set m_stream to a stream from which we can read, 0317 * as well as setting m_iSize to the size of the file. 0318 * @param name "absolute path" (in the archive) to the file to open 0319 * @return true on success 0320 */ 0321 virtual bool openRead( const QString& name ) = 0; 0322 0323 /** 0324 * @return true on success 0325 */ 0326 virtual bool closeRead() = 0; 0327 /** 0328 * @return true on success 0329 */ 0330 virtual bool closeWrite() = 0; 0331 0332 /** 0333 * Enter a subdirectory of the current directory. 0334 * The directory might not exist yet in Write mode. 0335 */ 0336 virtual bool enterRelativeDirectory( const QString& dirName ) = 0; 0337 /** 0338 * Enter a directory where we've been before. 0339 * It is guaranteed to always exist. 0340 */ 0341 virtual bool enterAbsoluteDirectory( const QString& path ) = 0; 0342 0343 /** 0344 * Check if a file exists inside the store. 0345 * @param absPath the absolute path inside the store, i.e. not relative to the current directory 0346 */ 0347 virtual bool fileExists( const QString& absPath ) const = 0; 0348 0349 private: 0350 static Backend determineBackend( QIODevice* dev ); 0351 0352 /** 0353 * Conversion routine 0354 * @param _internalNaming name used internally : "root", "tar:/0", ... 0355 * @return the name used in the file, more user-friendly ("maindoc.xml", 0356 * "part0/maindoc.xml", ...) 0357 * Examples: 0358 * 0359 * tar:/0 is saved as part0/maindoc.xml 0360 * tar:/0/1 is saved as part0/part1/maindoc.xml 0361 * tar:/0/1/pictures/picture0.png is saved as part0/part1/pictures/picture0.png 0362 * 0363 * see specification (koffice/lib/store/SPEC) for details. 0364 */ 0365 QString toExternalNaming( const QString & _internalNaming ) const; 0366 0367 /** 0368 * Expands a full path name for a stream (directories+filename) 0369 */ 0370 QString expandEncodedPath( const QString& intern ) const; 0371 0372 /** 0373 * Expands only directory names(!) 0374 * Needed for the path handling code, as we only operate on internal names 0375 */ 0376 QString expandEncodedDirectory( const QString& intern ) const; 0377 0378 mutable enum 0379 { 0380 NAMING_VERSION_2_1, 0381 NAMING_VERSION_2_2, 0382 NAMING_VERSION_RAW ///< Never expand file and directory names 0383 } m_namingVersion; 0384 0385 /** 0386 * Enter *one* single directory. Nothing like foo/bar/bleh allowed. 0387 * Performs some checking when in Read mode 0388 */ 0389 bool enterDirectoryInternal( const QString& directory ); 0390 0391 bool extractFile( const QString &srcName, QIODevice &buffer ); 0392 0393 protected: 0394 0395 Mode m_mode; 0396 0397 /// Store the filenames (with full path inside the archive) when writing, to avoid duplicates 0398 QStringList m_strFiles; 0399 0400 /// The "current directory" (path) 0401 QStringList m_currentPath; 0402 0403 /// Current filename (between an open() and a close()) 0404 QString m_sName; 0405 /// Current size of the file named m_sName 0406 qint64 m_iSize; 0407 0408 /// The stream for the current read or write operation 0409 QIODevice * m_stream; 0410 0411 bool m_bIsOpen; 0412 /// Must be set by the constructor. 0413 bool m_bGood; 0414 bool m_bFinalized; 0415 0416 private: 0417 /// Used to push/pop directories to make it easy to save/restore the state 0418 QStack<QString> m_directoryStack; 0419 0420 private: 0421 KoStore( const KoStore& store ); ///< don't copy 0422 KoStore& operator=( const KoStore& store ); ///< don't assign 0423 }; 0424 0425 #endif