1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
2 /* libwps
3  * Version: MPL 2.0 / LGPLv2.1+
4  *
5  * This Source Code Form is subject to the terms of the Mozilla Public
6  * License, v. 2.0. If a copy of the MPL was not distributed with this
7  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8  *
9  * Major Contributor(s):
10  * Copyright (C) 2003 William Lachance (william.lachance@sympatico.ca)
11  * Copyright (C) 2003-2004 Marc Maurer (uwog@uwog.net)
12  * Copyright (C) 2004-2006 Fridrich Strba (fridrich.strba@bluewin.ch)
13  * Copyright (C) 2006, 2007 Andrew Ziem (andrewziem users sourceforge net)
14  *
15  * For minor contributions see the git repository.
16  *
17  * Alternatively, the contents of this file may be used under the terms
18  * of the GNU Lesser General Public License Version 2.1 or later
19  * (LGPLv2.1+), in which case the provisions of the LGPLv2.1+ are
20  * applicable instead of those above.
21  *
22  * For further information visit http://libwps.sourceforge.net
23  */
24 
25 #include <libwps/libwps.h>
26 #include "WKS4.h"
27 #include "WPS4.h"
28 #include "WPS8.h"
29 #include "WPSHeader.h"
30 #include "WPSParser.h"
31 #include "libwps_internal.h"
32 
33 using namespace libwps;
34 
35 /**
36 \mainpage libwps documentation
37 This document contains both the libwps API specification and the normal libwps
38 documentation.
39 \section api_docs libwps API documentation
40 The external libwps API is provided by the WPSDocument class. This class, combined
41 with the librevenge's librevenge::RVNGTextInterface class, are the only two classes that will be
42 of interest for the application programmer using libwps.
43 \section lib_docs libwps documentation
44 If you are interrested in the structure of libwps itself, this whole document
45 would be a good starting point for exploring the interals of libwps. Mind that
46 this document is a work-in-progress, and will most likely not cover libwps for
47 the full 100%.
48 
49  \warning When compiled with -DDEBUG_WITH__FILES, code is added to store the results of the parsing in different files: one file by Ole parts and some files to store the read pictures. These files are created in the current repository, therefore it is recommended to launch the tests in an empty repository...*/
50 
51 /**
52 Analyzes the content of an input stream to see if it can be parsed
53 \param ip The input stream
54 \param kind The document kind
55 \return A confidence value which represents the likelyhood that the content from
56 the input stream can be parsed
57 */
isFileFormatSupported(librevenge::RVNGInputStream * ip,WPSKind & kind)58 WPSLIB WPSConfidence WPSDocument::isFileFormatSupported(librevenge::RVNGInputStream *ip, WPSKind &kind)
59 {
60 	WPS_DEBUG_MSG(("WPSDocument::isFileFormatSupported()\n"));
61 
62 	if (!ip)
63 		return WPS_CONFIDENCE_NONE;
64 
65 	kind=WPS_TEXT;
66 	WPSHeaderPtr header;
67 	shared_ptr<librevenge::RVNGInputStream > input(ip, WPS_shared_ptr_noop_deleter<librevenge::RVNGInputStream>());
68 	try
69 	{
70 		header.reset(WPSHeader::constructHeader(input));
71 
72 		if (!header)
73 			return WPS_CONFIDENCE_NONE;
74 		kind = header->getKind();
75 
76 		WPSConfidence confidence = WPS_CONFIDENCE_NONE;
77 		if (kind==WPS_TEXT && header->getMajorVersion()<=4)
78 		{
79 			// create a WPS4Parser to check the header validity
80 			WPS4Parser parser(header->getInput(), header);
81 			if (!parser.checkHeader(header.get(), true))
82 				return WPS_CONFIDENCE_NONE;
83 			return WPS_CONFIDENCE_EXCELLENT;
84 		}
85 		else if (kind==WPS_SPREADSHEET || kind==WPS_DATABASE)
86 		{
87 			// create a WKS4Parser to check the header validity
88 			WKS4Parser parser(header->getInput(), header);
89 			if (!parser.checkHeader(header.get(), true))
90 				return WPS_CONFIDENCE_NONE;
91 			return WPS_CONFIDENCE_EXCELLENT;
92 		}
93 
94 		/* A word document: as WPS8Parser does not have a checkHeader
95 		   function, only rely on the version
96 		 */
97 		switch (header->getMajorVersion())
98 		{
99 		case 8:
100 		case 7:
101 		case 5:
102 			confidence = WPS_CONFIDENCE_EXCELLENT;
103 			break;
104 		default:
105 			break;
106 		}
107 		return confidence;
108 	}
109 	catch (libwps::FileException)
110 	{
111 		WPS_DEBUG_MSG(("File exception trapped\n"));
112 	}
113 	catch (libwps::ParseException)
114 	{
115 		WPS_DEBUG_MSG(("Parse exception trapped\n"));
116 	}
117 	catch (...)
118 	{
119 		//fixme: too generic
120 		WPS_DEBUG_MSG(("Unknown Exception trapped\n"));
121 	}
122 
123 	return WPS_CONFIDENCE_NONE;
124 }
125 
126 /**
127 Parses the input stream content. It will make callbacks to the functions provided by a
128 librevenge::RVNGTextInterface class implementation when needed. This is often commonly called the
129 'main parsing routine'.
130 \param ip The input stream
131 \param documentInterface A WPSListener implementation
132 */
parse(librevenge::RVNGInputStream * ip,librevenge::RVNGTextInterface * documentInterface)133 WPSLIB WPSResult WPSDocument::parse(librevenge::RVNGInputStream *ip, librevenge::RVNGTextInterface *documentInterface)
134 {
135 	if (!ip || !documentInterface)
136 		return WPS_UNKNOWN_ERROR;
137 
138 	WPSResult error = WPS_OK;
139 
140 	WPSHeaderPtr header;
141 	shared_ptr<WPSParser> parser;
142 	shared_ptr<librevenge::RVNGInputStream > input(ip, WPS_shared_ptr_noop_deleter<librevenge::RVNGInputStream>());
143 	try
144 	{
145 		header.reset(WPSHeader::constructHeader(input));
146 
147 		if (!header || header->getKind() != WPS_TEXT)
148 			return WPS_UNKNOWN_ERROR;
149 
150 		switch (header->getMajorVersion())
151 		{
152 		case 8:
153 		case 7:
154 		case 6:
155 		case 5:
156 		{
157 			parser.reset(new WPS8Parser(header->getInput(), header));
158 			if (!parser) return WPS_UNKNOWN_ERROR;
159 			parser->parse(documentInterface);
160 			break;
161 		}
162 
163 		case 4:
164 		case 3:
165 		case 2:
166 		case 1:
167 		{
168 			parser.reset(new WPS4Parser(header->getInput(), header));
169 			if (!parser) return WPS_UNKNOWN_ERROR;
170 			parser->parse(documentInterface);
171 			break;
172 		}
173 		default:
174 			break;
175 		}
176 	}
177 	catch (libwps::FileException)
178 	{
179 		WPS_DEBUG_MSG(("File exception trapped\n"));
180 		error = WPS_FILE_ACCESS_ERROR;
181 	}
182 	catch (libwps::ParseException)
183 	{
184 		WPS_DEBUG_MSG(("Parse exception trapped\n"));
185 		error = WPS_PARSE_ERROR;
186 	}
187 	catch (...)
188 	{
189 		//fixme: too generic
190 		WPS_DEBUG_MSG(("Unknown exception trapped\n"));
191 		error = WPS_UNKNOWN_ERROR;
192 	}
193 
194 	return error;
195 }
196 
197 /**
198 Parses the input stream content. It will make callbacks to the functions provided by a
199 librevenge::RVNGSpreadsheetInterface class implementation when needed. This is often commonly called the
200 'main parsing routine'.
201 \param ip The input stream
202 \param documentInterface A SpreadsheetInterface implementation
203 */
parse(librevenge::RVNGInputStream * ip,librevenge::RVNGSpreadsheetInterface * documentInterface)204 WPSLIB WPSResult WPSDocument::parse(librevenge::RVNGInputStream *ip, librevenge::RVNGSpreadsheetInterface *documentInterface)
205 {
206 	if (!ip || !documentInterface)
207 		return WPS_UNKNOWN_ERROR;
208 
209 	WPSResult error = WPS_OK;
210 
211 	WPSHeaderPtr header;
212 	shared_ptr<WKSParser> parser;
213 	shared_ptr<librevenge::RVNGInputStream > input(ip, WPS_shared_ptr_noop_deleter<librevenge::RVNGInputStream>());
214 	try
215 	{
216 		header.reset(WPSHeader::constructHeader(input));
217 
218 		if (!header || (header->getKind() != WPS_SPREADSHEET && header->getKind() != WPS_DATABASE))
219 			return WPS_UNKNOWN_ERROR;
220 
221 		switch (header->getMajorVersion())
222 		{
223 		case 4:
224 		case 3:
225 		case 2:
226 		case 1:
227 		{
228 			parser.reset(new WKS4Parser(header->getInput(), header));
229 			if (!parser) return WPS_UNKNOWN_ERROR;
230 			parser->parse(documentInterface);
231 			break;
232 		}
233 		default:
234 			break;
235 		}
236 	}
237 	catch (libwps::FileException)
238 	{
239 		WPS_DEBUG_MSG(("File exception trapped\n"));
240 		error = WPS_FILE_ACCESS_ERROR;
241 	}
242 	catch (libwps::ParseException)
243 	{
244 		WPS_DEBUG_MSG(("Parse exception trapped\n"));
245 		error = WPS_PARSE_ERROR;
246 	}
247 	catch (...)
248 	{
249 		//fixme: too generic
250 		WPS_DEBUG_MSG(("Unknown exception trapped\n"));
251 		error = WPS_UNKNOWN_ERROR;
252 	}
253 
254 	return error;
255 }
256 /* vim:set shiftwidth=4 softtabstop=4 noexpandtab: */
257