1 /* -*- Mode: C++; c-default-style: "k&r"; indent-tabs-mode: nil; tab-width: 2; c-basic-offset: 2 -*- */ 2 3 /* libmwaw 4 * Version: MPL 2.0 / LGPLv2+ 5 * 6 * The contents of this file are subject to the Mozilla Public License Version 7 * 2.0 (the "License"); you may not use this file except in compliance with 8 * the License or as specified alternatively below. You may obtain a copy of 9 * the License at http://www.mozilla.org/MPL/ 10 * 11 * Software distributed under the License is distributed on an "AS IS" basis, 12 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License 13 * for the specific language governing rights and limitations under the 14 * License. 15 * 16 * Major Contributor(s): 17 * Copyright (C) 2002 William Lachance (wrlach@gmail.com) 18 * Copyright (C) 2002,2004 Marc Maurer (uwog@uwog.net) 19 * Copyright (C) 2004-2006 Fridrich Strba (fridrich.strba@bluewin.ch) 20 * Copyright (C) 2006, 2007 Andrew Ziem 21 * Copyright (C) 2011, 2012 Alonso Laurent (alonso@loria.fr) 22 * 23 * 24 * All Rights Reserved. 25 * 26 * For minor contributions see the git repository. 27 * 28 * Alternatively, the contents of this file may be used under the terms of 29 * the GNU Lesser General Public License Version 2 or later (the "LGPLv2+"), 30 * in which case the provisions of the LGPLv2+ are applicable 31 * instead of those above. 32 */ 33 34 #ifndef MWAW_INPUT_STREAM_H 35 #define MWAW_INPUT_STREAM_H 36 37 #include <string> 38 #include <vector> 39 40 #include <librevenge/librevenge.h> 41 #include <librevenge-stream/librevenge-stream.h> 42 #include "libmwaw_internal.hxx" 43 44 /*! \class MWAWInputStream 45 * \brief Internal class used to read the file stream 46 * Internal class used to read the file stream, 47 * this class adds some usefull functions to the basic librevenge::RVNGInputStream: 48 * - read number (int8, int16, int32) in low or end endian 49 * - selection of a section of a stream 50 * - read block of data 51 * - interface with modified librevenge::RVNGOLEStream 52 */ 53 class MWAWInputStream 54 { 55 public: 56 /*!\brief creates a stream with given endian 57 * \param input the given input 58 * \param inverted must be set to true for pc doc and ole part and to false for mac doc 59 */ 60 MWAWInputStream(std::shared_ptr<librevenge::RVNGInputStream> input, bool inverted); 61 62 /*!\brief creates a stream with given endian from an existing input 63 * 64 * Note: this functions does not delete input 65 */ 66 MWAWInputStream(librevenge::RVNGInputStream *input, bool inverted, bool checkCompression=false); 67 //! destructor 68 ~MWAWInputStream(); 69 70 //! returns the basic librevenge::RVNGInputStream input()71 std::shared_ptr<librevenge::RVNGInputStream> input() 72 { 73 return m_stream; 74 } 75 //! returns a new input stream corresponding to a librevenge::RVNGBinaryData 76 static std::shared_ptr<MWAWInputStream> get(librevenge::RVNGBinaryData const &data, bool inverted); 77 78 //! returns the endian mode (see constructor) readInverted() const79 bool readInverted() const 80 { 81 return m_inverseRead; 82 } 83 //! sets the endian mode setReadInverted(bool newVal)84 void setReadInverted(bool newVal) 85 { 86 m_inverseRead = newVal; 87 } 88 // 89 // Position: access 90 // 91 92 /*! \brief seeks to a offset position, from actual, beginning or ending position 93 * \return 0 if ok 94 * \sa pushLimit popLimit 95 */ 96 int seek(long offset, librevenge::RVNG_SEEK_TYPE seekType); 97 //! returns actual offset position 98 long tell(); 99 //! returns the stream size size() const100 long size() const 101 { 102 return m_streamSize; 103 } 104 //! checks if a position is or not a valid file position checkPosition(long pos) const105 bool checkPosition(long pos) const 106 { 107 if (pos < 0) return false; 108 if (m_readLimit > 0 && pos > m_readLimit) return false; 109 return pos<=m_streamSize; 110 } 111 //! returns true if we are at the end of the section/file 112 bool isEnd(); 113 114 /*! \brief defines a new section in the file (from actualPos to newLimit) 115 * next call of seek, tell, atEos, ... will be restrained to this section 116 */ pushLimit(long newLimit)117 void pushLimit(long newLimit) 118 { 119 m_prevLimits.push_back(m_readLimit); 120 m_readLimit = newLimit > m_streamSize ? m_streamSize : newLimit; 121 } 122 //! pops a section defined by pushLimit popLimit()123 void popLimit() 124 { 125 if (!m_prevLimits.empty()) { 126 m_readLimit = m_prevLimits.back(); 127 m_prevLimits.pop_back(); 128 } 129 else m_readLimit = -1; 130 } 131 132 /*! internal: recomputes the stream size, must be called after you modify the data of the main input 133 134 For instance, if this input stream is created from a MWAWStringStream and you decide to add some data 135 in the original MWAWStringStream... 136 */ 137 void recomputeStreamSize(); 138 139 // 140 // get data 141 // 142 143 //! returns a uint8, uint16, uint32 readed from actualPos readULong(int num)144 unsigned long readULong(int num) 145 { 146 return readULong(m_stream.get(), num, 0, m_inverseRead); 147 } 148 //! return a int8, int16, int32 readed from actualPos 149 long readLong(int num); 150 //! try to read a double of size 8: 1.5 bytes exponent, 6.5 bytes mantisse 151 bool readDouble8(double &res, bool &isNotANumber); 152 //! try to read a double of size 8: 6.5 bytes mantisse, 1.5 bytes exponent 153 bool readDoubleReverted8(double &res, bool &isNotANumber); 154 //! try to read a double of size 10: 2 bytes exponent, 8 bytes mantisse 155 bool readDouble10(double &res, bool &isNotANumber); 156 157 /**! reads numbytes data, WITHOUT using any endian or section consideration 158 * \return a pointer to the read elements 159 */ 160 const uint8_t *read(size_t numBytes, unsigned long &numBytesRead); 161 /*! \brief internal function used to read num byte, 162 * - where a is the previous read data 163 */ 164 static unsigned long readULong(librevenge::RVNGInputStream *stream, int num, unsigned long a, bool inverseRead); 165 166 //! reads a librevenge::RVNGBinaryData with a given size in the actual section/file 167 bool readDataBlock(long size, librevenge::RVNGBinaryData &data); 168 //! reads a librevenge::RVNGBinaryData from actPos to the end of the section/file 169 bool readEndDataBlock(librevenge::RVNGBinaryData &data); 170 171 // 172 // OLE/Zip access 173 // 174 175 //! return true if the stream is ole 176 bool isStructured(); 177 //! returns the number of substream 178 unsigned subStreamCount(); 179 //! returns the name of the i^th substream 180 std::string subStreamName(unsigned id); 181 182 //! return a new stream for a ole zone 183 std::shared_ptr<MWAWInputStream> getSubStreamByName(std::string const &name); 184 //! return a new stream for a ole zone 185 std::shared_ptr<MWAWInputStream> getSubStreamById(unsigned id); 186 187 // 188 // Finder Info access 189 // 190 /** returns the finder info type and creator (if known) */ getFinderInfo(std::string & type,std::string & creator) const191 bool getFinderInfo(std::string &type, std::string &creator) const 192 { 193 if (!m_fInfoType.length() || !m_fInfoCreator.length()) { 194 type = creator = ""; 195 return false; 196 } 197 type = m_fInfoType; 198 creator = m_fInfoCreator; 199 return true; 200 } 201 202 // 203 // Resource Fork access 204 // 205 206 /** returns true if the data fork block exists */ hasDataFork() const207 bool hasDataFork() const 208 { 209 return bool(m_stream); 210 } 211 /** returns true if the resource fork block exists */ hasResourceFork() const212 bool hasResourceFork() const 213 { 214 return bool(m_resourceFork); 215 } 216 /** returns the resource fork if find */ getResourceForkStream()217 std::shared_ptr<MWAWInputStream> getResourceForkStream() 218 { 219 return m_resourceFork; 220 } 221 222 223 protected: 224 //! update the stream size ( must be called in the constructor ) 225 void updateStreamSize(); 226 //! internal function used to read a byte 227 static uint8_t readU8(librevenge::RVNGInputStream *stream); 228 229 //! unbinhex the data in the file is a BinHex 4.0 file of a mac file 230 bool unBinHex(); 231 //! unzip the data in the file is a zip file of a mac file 232 bool unzipStream(); 233 //! check if some stream are in MacMIME format, if so de MacMIME 234 bool unMacMIME(); 235 //! de MacMIME an input stream 236 bool unMacMIME(MWAWInputStream *input, 237 std::shared_ptr<librevenge::RVNGInputStream> &dataInput, 238 std::shared_ptr<librevenge::RVNGInputStream> &rsrcInput) const; 239 //! check if a stream is an internal merge stream 240 bool unsplitInternalMergeStream(); 241 242 private: 243 MWAWInputStream(MWAWInputStream const &orig) = delete; 244 MWAWInputStream &operator=(MWAWInputStream const &orig) = delete; 245 246 protected: 247 //! the initial input 248 std::shared_ptr<librevenge::RVNGInputStream> m_stream; 249 //! the stream size 250 long m_streamSize; 251 252 //! actual section limit (-1 if no limit) 253 long m_readLimit; 254 //! list of previous limits 255 std::vector<long> m_prevLimits; 256 257 //! finder info type 258 mutable std::string m_fInfoType; 259 //! finder info type 260 mutable std::string m_fInfoCreator; 261 //! the resource fork 262 std::shared_ptr<MWAWInputStream> m_resourceFork; 263 //! big or normal endian 264 bool m_inverseRead; 265 }; 266 267 #endif 268 // vim: set filetype=cpp tabstop=2 shiftwidth=2 cindent autoindent smartindent noexpandtab: 269