1 /* -*- Mode: C++; c-default-style: "k&r"; indent-tabs-mode: nil; tab-width: 2; c-basic-offset: 2 -*- */
2 
3 /* libstaroffice
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 /*
35  *  freely inspired from istorage :
36  * ------------------------------------------------------------
37  *      Generic OLE Zones furnished with a copy of the file header
38  *
39  * Compound Storage (32 bit version)
40  * Storage implementation
41  *
42  * This file contains the compound file implementation
43  * of the storage interface.
44  *
45  * Copyright 1999 Francis Beaudet
46  * Copyright 1999 Sylvain St-Germain
47  * Copyright 1999 Thuy Nguyen
48  * Copyright 2005 Mike McCormack
49  *
50  * This library is free software; you can redistribute it and/or
51  * modify it under the terms of the GNU Lesser General Public
52  * License as published by the Free Software Foundation; either
53  * version 2.1 of the License, or (at your option) any later version.
54  *
55  * This library is distributed in the hope that it will be useful,
56  * but WITHOUT ANY WARRANTY; without even the implied warranty of
57  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
58  * Lesser General Public License for more details.
59  *
60  * ------------------------------------------------------------
61  */
62 
63 #ifndef STOFF_OLE_PARSER_H
64 #define STOFF_OLE_PARSER_H
65 
66 #include <string>
67 #include <vector>
68 
69 #include <librevenge-stream/librevenge-stream.h>
70 
71 #include <libstaroffice/STOFFDocument.hxx>
72 
73 #include "libstaroffice_internal.hxx"
74 #include "STOFFPosition.hxx"
75 
76 #include "STOFFDebug.hxx"
77 
78 namespace STOFFOLEParserInternal
79 {
80 struct State;
81 }
82 
83 /** \brief a class used to parse some basic oles
84     Tries to read the different ole parts and stores their contents in form of picture.
85  */
86 class STOFFOLEParser
87 {
88 public:
89   struct OleDirectory;
90 
91   /** constructor */
92   STOFFOLEParser();
93 
94   /** destructor */
95   ~STOFFOLEParser();
96 
97   /** tries to parse basic OLE (excepted mainName)
98       \return false if fileInput is not an Ole file */
99   bool parse(STOFFInputStreamPtr fileInput);
100 
101   //! returns the list of directory ole
102   std::vector<std::shared_ptr<OleDirectory> > &getDirectoryList();
103   //! returns a OleDirectory corresponding to a dir if found
104   std::shared_ptr<OleDirectory> getDirectory(std::string const &dir);
105   //! returns the main compobj program name
106   bool getCompObjName(STOFFInputStreamPtr fileInput, std::string &programName);
107 
108   /** structure use to store an object content */
109   struct OleContent {
110     //! constructor
OleContentSTOFFOLEParser::OleContent111     OleContent(std::string const &dir, std::string const &base)
112       : m_dir(dir)
113       , m_base(base)
114       , m_isParsed(false)
115       , m_position()
116       , m_imageData()
117       , m_imageType("")
118     {
119     }
120     //! returns the base name
getBaseNameSTOFFOLEParser::OleContent121     std::string getBaseName()
122     {
123       return m_base;
124     }
125     //! returns the ole name
getOleNameSTOFFOLEParser::OleContent126     std::string getOleName() const
127     {
128       if (m_dir.empty()) return m_base;
129       return m_dir+"/"+m_base;
130     }
131     //! returns true if the object if parsed
isParsedSTOFFOLEParser::OleContent132     bool isParsed() const
133     {
134       return m_isParsed;
135     }
136     //! sets the parsed flag
setParsedSTOFFOLEParser::OleContent137     void setParsed(bool flag=true)
138     {
139       m_isParsed=flag;
140     }
141     //! return the image position
getPositionSTOFFOLEParser::OleContent142     STOFFPosition const &getPosition() const
143     {
144       return m_position;
145     }
146     //! set the image position
setPositionSTOFFOLEParser::OleContent147     void setPosition(STOFFPosition const &pos)
148     {
149       m_position=pos;
150     }
151     //! returns the image data
getImageDataSTOFFOLEParser::OleContent152     bool getImageData(librevenge::RVNGBinaryData &data, std::string &type) const
153     {
154       if (m_imageData.empty()) {
155         data.clear();
156         type="";
157         return false;
158       }
159       data=m_imageData;
160       type=m_imageType;
161       return true;
162     }
163     //! sets the image data
setImageDataSTOFFOLEParser::OleContent164     void setImageData(librevenge::RVNGBinaryData const &data, std::string const &type)
165     {
166       m_imageData=data;
167       m_imageType=type;
168     }
169   protected:
170     //! the directory
171     std::string m_dir;
172     //! the base name
173     std::string m_base;
174     //! true if the data has been parsed
175     bool m_isParsed;
176     //! the image position (if known)
177     STOFFPosition m_position;
178     //! the image content ( if known )
179     librevenge::RVNGBinaryData m_imageData;
180     //! the image type ( if known)
181     std::string m_imageType;
182   };
183 
184   /** Internal: internal method to keep ole directory and their content */
185   struct OleDirectory {
186     //! constructor
OleDirectorySTOFFOLEParser::OleDirectory187     OleDirectory(STOFFInputStreamPtr &input, std::string const &dir)
188       : m_input(input)
189       , m_dir(dir)
190       , m_contentList()
191       , m_kind(STOFFDocument::STOFF_K_UNKNOWN)
192       , m_hasCompObj(false)
193       , m_clsName("")
194       , m_clipName("")
195       , m_parsed(false)
196       , m_inUse(false) { }
197     //! add a new base file
addNewBaseSTOFFOLEParser::OleDirectory198     void addNewBase(std::string const &base)
199     {
200       if (base=="CompObj")
201         m_hasCompObj=true;
202       else
203         m_contentList.push_back(OleContent(m_dir,base));
204     }
205     //! returns the list of unknown ole
getUnparsedOlesSTOFFOLEParser::OleDirectory206     std::vector<std::string> getUnparsedOles() const
207     {
208       std::vector<std::string> res;
209       for (auto const &c : m_contentList) {
210         if (c.isParsed()) continue;
211         res.push_back(c.getOleName());
212       }
213       return res;
214     }
215     //! the main input
216     STOFFInputStreamPtr m_input;
217     /**the dir name*/
218     std::string m_dir;
219     /**the list of base name*/
220     std::vector<OleContent> m_contentList;
221     //! the ole kind
222     STOFFDocument::Kind m_kind;
223     /** true if the directory contains a compobj object */
224     bool m_hasCompObj;
225     /** the compobj CLSname */
226     std::string m_clsName;
227     /** the compobj clipname */
228     std::string m_clipName;
229     /** a flag to know if the directory is parsed or not */
230     bool m_parsed;
231     /** a flag to know if the directory is currently used */
232     mutable bool m_inUse;
233   };
234 
235 protected:
236   //! the summary information
237   static bool readSummaryInformation(STOFFInputStreamPtr input, std::string const &oleName,
238                                      libstoff::DebugFile &ascii);
239   //!  parse the "CompObj" contains : UserType,ClipName,ProgIdName
240   bool readCompObj(STOFFInputStreamPtr ip, OleDirectory &directory);
241   //!  the "Ole" small structure : unknown contain
242   static bool readOle(STOFFInputStreamPtr ip, std::string const &oleName,
243                       libstoff::DebugFile &ascii);
244   //!  the "ObjInfo" small structure : seems to contain 3 ints=0,3,4
245   static bool readObjInfo(STOFFInputStreamPtr input, std::string const &oleName,
246                           libstoff::DebugFile &ascii);
247 
248   /** the OlePres001 seems to contain standart picture file and size */
249   static  bool isOlePres(STOFFInputStreamPtr ip, std::string const &oleName);
250   /** extracts the picture of OlePres001 if it is possible.
251 
252    \note it only sets the image size with setNaturalSize.*/
253   static bool readOlePres(STOFFInputStreamPtr ip, OleContent &content);
254 
255   //! theOle10Native : basic Windows� picture, with no size
256   static bool isOle10Native(STOFFInputStreamPtr ip, std::string const &oleName);
257   /** extracts the picture if it is possible.
258 
259    \note it does not set the image position*/
260   static bool readOle10Native(STOFFInputStreamPtr ip, OleContent &content);
261 
262   /** \brief the Contents : in general a picture : a PNG, an JPEG, a basic metafile,
263    * I find also a Word art picture, which are not sucefull read
264    */
265   bool readContents(STOFFInputStreamPtr input, OleContent &content);
266 
267   /** the CONTENTS : seems to store a header size, the header
268    * and then a object in EMF (with the same header)...
269    * \note I only find such lib in 2 files, so the parsing may be incomplete
270    *  and many such Ole rejected
271    */
272   bool readCONTENTS(STOFFInputStreamPtr input, OleContent &content);
273 
274 protected:
275   //
276   // data
277   //
278 
279   //! the class state
280   std::shared_ptr<STOFFOLEParserInternal::State> m_state;
281 };
282 
283 #endif
284 // vim: set filetype=cpp tabstop=2 shiftwidth=2 cindent autoindent smartindent noexpandtab:
285