1 /* AbiWord
2  * Copyright (C) 2006 Marc Maurer <uwog@uwog.net>
3  * Copyright (C) 2006 Fridrich Strba <fridrich.strba@bluewin.ch>
4  * Copyright (C) 2006 Dominic Lachowicz <domlachowicz@gmail.com>
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19  * 02110-1301 USA.
20  */
21 
22 #ifdef ABI_PLUGIN_BUILTIN
23 #define abi_plugin_register abipgn_wpg_register
24 #define abi_plugin_unregister abipgn_wpg_unregister
25 #define abi_plugin_supports_version abipgn_wpg_supports_version
26 #endif
27 
28 #include "ie_impGraphic_WPG.h"
29 #include <gsf/gsf-utils.h>
30 #include <gsf/gsf-infile.h>
31 #include <gsf/gsf-input-memory.h>
32 #include <gsf/gsf-input-stdio.h>
33 #include <gsf/gsf-infile-msole.h>
34 #include <gsf/gsf-infile-zip.h>
35 #include <librevenge-stream/librevenge-stream.h>
36 #include "xap_Module.h"
37 
38 using libwpg::WPGraphics;
39 
40 ABI_PLUGIN_DECLARE("WPG")
41 
42 class AbiWordPerfectGraphicsInputStream : public librevenge::RVNGInputStream
43 {
44 public:
45 	AbiWordPerfectGraphicsInputStream(GsfInput *input);
46 	~AbiWordPerfectGraphicsInputStream();
47 
48 	virtual bool isStructured();
49 	virtual unsigned subStreamCount();
50 	virtual const char* subStreamName(unsigned);
51 	bool existsSubStream(const char*);
52 	virtual librevenge::RVNGInputStream* getSubStreamByName(const char*);
53 	virtual librevenge::RVNGInputStream* getSubStreamById(unsigned);
54 	virtual const unsigned char *read(unsigned long numBytes, unsigned long &numBytesRead);
55 	virtual int seek(long offset, librevenge::RVNG_SEEK_TYPE seekType);
56 	virtual long tell();
57 	virtual bool isEnd();
58 
59 private:
60 
61 	GsfInput *m_input;
62 	GsfInfile *m_ole;
63 	std::map<unsigned, std::string> m_substreams;
64 };
65 
AbiWordPerfectGraphicsInputStream(GsfInput * input)66 AbiWordPerfectGraphicsInputStream::AbiWordPerfectGraphicsInputStream(GsfInput *input) :
67 	librevenge::RVNGInputStream(),
68 	m_input(input),
69 	m_ole(NULL),
70 	m_substreams()
71 {
72 	g_object_ref(G_OBJECT(input));
73 }
74 
~AbiWordPerfectGraphicsInputStream()75 AbiWordPerfectGraphicsInputStream::~AbiWordPerfectGraphicsInputStream()
76 {
77 	if (m_ole)
78 		g_object_unref(G_OBJECT(m_ole));
79 
80 	g_object_unref(G_OBJECT(m_input));
81 }
82 
read(unsigned long numBytes,unsigned long & numBytesRead)83 const unsigned char * AbiWordPerfectGraphicsInputStream::read(unsigned long numBytes, unsigned long &numBytesRead)
84 {
85 	const unsigned char *buf = gsf_input_read(m_input, numBytes, NULL);
86 
87 	if (buf == NULL)
88 		numBytesRead = 0;
89 	else
90 		numBytesRead = numBytes;
91 
92 	return buf;
93 }
94 
seek(long offset,librevenge::RVNG_SEEK_TYPE seekType)95 int AbiWordPerfectGraphicsInputStream::seek(long offset, librevenge::RVNG_SEEK_TYPE seekType)
96 {
97 	GSeekType gsfSeekType = G_SEEK_SET;
98 	switch(seekType)
99 	{
100 	case librevenge::RVNG_SEEK_CUR:
101 		gsfSeekType = G_SEEK_CUR;
102 		break;
103 	case librevenge::RVNG_SEEK_SET:
104 		gsfSeekType = G_SEEK_SET;
105 		break;
106 	case librevenge::RVNG_SEEK_END:
107 		gsfSeekType = G_SEEK_END;
108 		break;
109 	}
110 
111 	return gsf_input_seek(m_input, offset, gsfSeekType);
112 }
113 
isStructured()114 bool AbiWordPerfectGraphicsInputStream::isStructured()
115 {
116 	if (!m_ole)
117 		m_ole = GSF_INFILE(gsf_infile_msole_new (m_input, NULL));
118 
119 	if (!m_ole)
120 		m_ole = GSF_INFILE(gsf_infile_zip_new (m_input, NULL));
121 
122 	if (m_ole)
123 		return true;
124 
125 	return false;
126 }
127 
subStreamCount()128 unsigned AbiWordPerfectGraphicsInputStream::subStreamCount()
129 {
130 	if (!m_ole)
131 		m_ole = GSF_INFILE(gsf_infile_msole_new (m_input, NULL));
132 
133 	if (!m_ole)
134 		m_ole = GSF_INFILE(gsf_infile_zip_new (m_input, NULL));
135 
136 	if (m_ole)
137 		{
138 			int numChildren = gsf_infile_num_children(m_ole);
139 			if (numChildren > 0)
140 				return numChildren;
141 			return 0;
142 		}
143 
144 	return 0;
145 }
146 
subStreamName(unsigned id)147 const char * AbiWordPerfectGraphicsInputStream::subStreamName(unsigned id)
148 {
149 	if (!m_ole)
150 		m_ole = GSF_INFILE(gsf_infile_msole_new (m_input, NULL));
151 
152 	if (!m_ole)
153 		m_ole = GSF_INFILE(gsf_infile_zip_new (m_input, NULL));
154 
155 	if (m_ole)
156 		{
157 			if ((int)id >= gsf_infile_num_children(m_ole))
158 			{
159 				return 0;
160 			}
161 			std::map<unsigned, std::string>::iterator i = m_substreams.lower_bound(id);
162 			if (i == m_substreams.end() || m_substreams.key_comp()(id, i->first))
163 				{
164 					std::string name = gsf_infile_name_by_index(m_ole, (int)id);
165 					i = m_substreams.insert(i, std::map<unsigned, std::string>::value_type(id, name));
166 				}
167 			return i->second.c_str();
168 		}
169 
170 	return 0;
171 }
172 
existsSubStream(const char * name)173 bool AbiWordPerfectGraphicsInputStream::existsSubStream(const char * name)
174 {
175 	if (!m_ole)
176 		m_ole = GSF_INFILE(gsf_infile_msole_new (m_input, NULL));
177 
178 	if (!m_ole)
179 		m_ole = GSF_INFILE(gsf_infile_zip_new (m_input, NULL));
180 
181 	if (m_ole)
182 		{
183 			GsfInput *document = gsf_infile_child_by_name(m_ole, name);
184 			if (document)
185 				{
186 					g_object_unref(G_OBJECT (document));
187 					return true;
188 				}
189 		}
190 
191 	return false;
192 }
193 
getSubStreamByName(const char * name)194 librevenge::RVNGInputStream * AbiWordPerfectGraphicsInputStream::getSubStreamByName(const char * name)
195 {
196 	librevenge::RVNGInputStream *documentStream = NULL;
197 
198 	if (!m_ole)
199 		m_ole = GSF_INFILE(gsf_infile_msole_new (m_input, NULL));
200 
201 	if (!m_ole)
202 		m_ole = GSF_INFILE(gsf_infile_zip_new (m_input, NULL));
203 
204 	if (m_ole)
205 		{
206 			GsfInput *document = gsf_infile_child_by_name(m_ole, name);
207 			if (document)
208 				{
209 					documentStream = new AbiWordPerfectGraphicsInputStream(document);
210 					g_object_unref(G_OBJECT (document)); // the only reference should be encapsulated within the new stream
211 				}
212 		}
213 
214 	return documentStream;
215 }
216 
getSubStreamById(unsigned id)217 librevenge::RVNGInputStream * AbiWordPerfectGraphicsInputStream::getSubStreamById(unsigned id)
218 {
219 	librevenge::RVNGInputStream *documentStream = NULL;
220 
221 	if (!m_ole)
222 		m_ole = GSF_INFILE(gsf_infile_msole_new (m_input, NULL));
223 
224 	if (!m_ole)
225 		m_ole = GSF_INFILE(gsf_infile_zip_new (m_input, NULL));
226 
227 	if (m_ole)
228 		{
229 			GsfInput *document = gsf_infile_child_by_index(m_ole, (int)id);
230 			if (document)
231 				{
232 					documentStream = new AbiWordPerfectGraphicsInputStream(document);
233 					g_object_unref(G_OBJECT (document)); // the only reference should be encapsulated within the new stream
234 				}
235 		}
236 
237 	return documentStream;
238 }
239 
tell()240 long AbiWordPerfectGraphicsInputStream::tell()
241 {
242 	return gsf_input_tell(m_input);
243 }
244 
isEnd()245 bool AbiWordPerfectGraphicsInputStream::isEnd()
246 {
247 	return gsf_input_eof(m_input);
248 }
249 
250 static IE_Imp_WordPerfectGraphics_Sniffer * m_ImpSniffer = 0;
251 
252 ABI_FAR_CALL
abi_plugin_register(XAP_ModuleInfo * mi)253 int abi_plugin_register (XAP_ModuleInfo * mi)
254 {
255 	if (!m_ImpSniffer)
256 	{
257 		m_ImpSniffer = new IE_Imp_WordPerfectGraphics_Sniffer ();
258 	}
259 
260 	UT_ASSERT (m_ImpSniffer);
261 
262 	mi->name    = "WordPerfect(tm) Graphics Importer";
263 	mi->desc    = "Import WordPerfect(tm) Graphics";
264 	mi->version = ABI_VERSION_STRING;
265 	mi->author  = "Marc Maurer";
266 	mi->usage   = "No Usage";
267 
268 	IE_ImpGraphic::registerImporter (m_ImpSniffer);
269 	return 1;
270 }
271 
272 ABI_FAR_CALL
abi_plugin_unregister(XAP_ModuleInfo * mi)273 int abi_plugin_unregister (XAP_ModuleInfo * mi)
274 {
275 	mi->name    = 0;
276 	mi->desc    = 0;
277 	mi->version = 0;
278 	mi->author  = 0;
279 	mi->usage   = 0;
280 
281 	UT_ASSERT (m_ImpSniffer);
282 
283 	IE_ImpGraphic::unregisterImporter (m_ImpSniffer);
284 	delete m_ImpSniffer;
285 	m_ImpSniffer = 0;
286 
287 	return 1;
288 }
289 
290 ABI_FAR_CALL
abi_plugin_supports_version(UT_uint32,UT_uint32,UT_uint32)291 int abi_plugin_supports_version (UT_uint32 /*major*/, UT_uint32 /*minor*/,
292 								 UT_uint32 /*release*/)
293 {
294   return 1;
295 }
296 
297 // supported suffixes
298 static IE_SuffixConfidence IE_WordPerfectGraphics_Sniffer__SuffixConfidence[] = {
299 	{ "wpg",        UT_CONFIDENCE_PERFECT   },
300 	{ "",         UT_CONFIDENCE_ZILCH     }
301 };
302 
IE_Imp_WordPerfectGraphics_Sniffer()303 IE_Imp_WordPerfectGraphics_Sniffer::IE_Imp_WordPerfectGraphics_Sniffer()
304 {
305 }
306 
~IE_Imp_WordPerfectGraphics_Sniffer()307 IE_Imp_WordPerfectGraphics_Sniffer::~IE_Imp_WordPerfectGraphics_Sniffer()
308 {
309 }
310 
getSuffixConfidence()311 const IE_SuffixConfidence * IE_Imp_WordPerfectGraphics_Sniffer::getSuffixConfidence()
312 {
313 	return IE_WordPerfectGraphics_Sniffer__SuffixConfidence;
314 }
315 
recognizeContents(GsfInput * input)316 UT_Confidence_t IE_Imp_WordPerfectGraphics_Sniffer::recognizeContents(GsfInput * input)
317 {
318 	AbiWordPerfectGraphicsInputStream gsfInput(input);
319 	if (WPGraphics::isSupported(&gsfInput))
320 		return UT_CONFIDENCE_PERFECT;
321 	return UT_CONFIDENCE_ZILCH;
322 }
323 
getDlgLabels(const char ** szDesc,const char ** szSuffixList,IEGraphicFileType * ft)324 bool IE_Imp_WordPerfectGraphics_Sniffer::getDlgLabels (const char ** szDesc,
325                         const char ** szSuffixList,
326                         IEGraphicFileType *ft)
327 {
328 	*szDesc = "WordPerfect(tm) Graphics Images (.wpg)";
329 	*szSuffixList = "*.wpg";
330 	*ft = getType ();
331 	return true;
332 }
333 
constructImporter(IE_ImpGraphic ** ppieg)334 UT_Error IE_Imp_WordPerfectGraphics_Sniffer::constructImporter(IE_ImpGraphic **ppieg)
335 {
336 	*ppieg = new IE_Imp_WordPerfectGraphics();
337 	if (*ppieg == NULL)
338 		return UT_IE_NOMEMORY;
339 	return UT_OK;
340 }
341 
342 
importGraphic(GsfInput * input,FG_Graphic ** ppfg)343 UT_Error IE_Imp_WordPerfectGraphics::importGraphic(GsfInput *input, FG_Graphic **ppfg)
344 {
345 	AbiWordPerfectGraphicsInputStream gsfInput(input);
346 	librevenge::RVNGString svgOutput;
347 	librevenge::RVNGStringVector vec;
348 	librevenge::RVNGSVGDrawingGenerator generator(vec, "");
349 
350 	if (!libwpg::WPGraphics::parse(&gsfInput, &generator) || vec.empty() || vec[0].empty())
351 	{
352 		return UT_ERROR;
353 	}
354 
355 	svgOutput.append("<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n");
356 	svgOutput.append("<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\"");
357 	svgOutput.append(" \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">\n");
358 	svgOutput.append(vec[0]);
359 	svgOutput.append("\n");
360 
361 	GsfInput * svgInput = gsf_input_memory_new((const guint8*)svgOutput.cstr(), svgOutput.len(), false);
362 	UT_Error result = IE_ImpGraphic::loadGraphic(svgInput, IE_ImpGraphic::fileTypeForSuffix(".svg"), ppfg);
363 	g_object_unref(svgInput);
364 	return result;
365 }
366 
367