1 /* -*- mode: C++; tab-width: 4; c-basic-offset: 4; -*- */
2 /* AbiWord
3  * Copyright (C) 2001 Dom Lachowicz
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public License
7  * as published by the Free Software Foundation; either version 2
8  * of the License, or (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18  * 02110-1301 USA.
19  */
20 
21 #include <stdio.h>
22 
23 #include "ut_Script.h"
24 #include "ut_string.h"
25 #include "ut_vector.h"
26 #include "ut_debugmsg.h"
27 #include "ut_assert.h"
28 #include "ut_misc.h"
29 
30 /************************************************************************/
31 /************************************************************************/
32 
UT_ScriptSniffer()33 UT_ScriptSniffer::UT_ScriptSniffer()
34 	: m_type (-1)
35 {
36 }
37 
~UT_ScriptSniffer()38 UT_ScriptSniffer::~UT_ScriptSniffer()
39 {
40 }
41 
42 /************************************************************************/
43 /************************************************************************/
44 
UT_Script()45 UT_Script::UT_Script ()
46 {
47 }
48 
~UT_Script()49 UT_Script::~UT_Script()
50 {
51 }
52 
53 /************************************************************************/
54 /************************************************************************/
55 UT_ScriptLibrary * UT_ScriptLibrary::m_pInstance = NULL;
56 
UT_ScriptLibrary()57 UT_ScriptLibrary::UT_ScriptLibrary ()
58   :     mSniffers (new UT_GenericVector<UT_ScriptSniffer *>(5)),
59     m_stErrMsg("")
60 {
61   m_pInstance = this;
62   UT_DEBUGMSG(("Construct a scriptlibrary %p \n",this));
63 }
64 
~UT_ScriptLibrary()65 UT_ScriptLibrary::~UT_ScriptLibrary ()
66 {
67   UT_DEBUGMSG(("Delete the scriptlibrary %p \n",this));
68 	DELETEP(mSniffers);
69 }
70 
instance()71 UT_ScriptLibrary * UT_ScriptLibrary::instance ()
72 {
73 	return m_pInstance;
74 }
75 
execute(const char * script,UT_ScriptIdType type)76 UT_Error UT_ScriptLibrary::execute (const char * script,
77 									UT_ScriptIdType type )
78 {
79 	UT_Script* pScript = NULL;
80 	UT_ScriptIdType scriptId = -1;
81 
82 	UT_Error err = UT_OK;
83 
84 	if ((err = constructScript(script, type, &pScript, &scriptId)) == UT_OK)
85     {
86 		if ((err = pScript->execute(script)) != UT_OK)
87 		{
88 			UT_DEBUGMSG(("Error executing script: %d\n", err));
89 			errmsg(pScript->errmsg());
90 		}
91 
92 		DELETEP(pScript);
93     }
94 
95 	return err;
96 }
97 
getNumScripts() const98 UT_uint32 UT_ScriptLibrary::getNumScripts () const
99 {
100 	return mSniffers->size ();
101 }
102 
registerScript(UT_ScriptSniffer * s)103 void UT_ScriptLibrary::registerScript ( UT_ScriptSniffer * s )
104 {
105 	UT_sint32 ndx = 0;
106 	UT_Error err = mSniffers->addItem (s, &ndx);
107 
108 	UT_return_if_fail(err == UT_OK);
109 	s->setType(ndx+1);
110 }
111 
unregisterScript(UT_ScriptSniffer * s)112 void UT_ScriptLibrary::unregisterScript ( UT_ScriptSniffer * s )
113 {
114 	UT_uint32 ndx = s->getType(); // 1:1 mapping
115 
116 	UT_return_if_fail( ndx > 0);
117 
118 	mSniffers->deleteNthItem (ndx-1);
119 
120 	// Refactor the indexes
121 	UT_ScriptSniffer * pSniffer = 0;
122 	UT_sint32 size  = mSniffers->size();
123 	UT_sint32 i     = 0;
124 	for( i = ndx-1; i < size; i++)
125     {
126 		pSniffer = mSniffers->getNthItem(i);
127 		if (pSniffer)
128 			pSniffer->setType(i+1);
129     }
130 }
131 
unregisterAllScripts()132 void UT_ScriptLibrary::unregisterAllScripts ()
133 {
134 	UT_ScriptSniffer * pSniffer = 0;
135 	UT_sint32 size = mSniffers->size();
136 
137 	for (UT_sint32 i = 0; i < size; i++)
138 	{
139 		pSniffer = mSniffers->getNthItem(i);
140 		if (pSniffer)
141 			delete pSniffer;
142     }
143 
144 	mSniffers->clear();
145 }
146 
typeForContents(const char * szBuf,UT_uint32 iNumbytes)147 UT_ScriptIdType	UT_ScriptLibrary::typeForContents(const char * szBuf,
148 												  UT_uint32 iNumbytes)
149 {
150 	// we have to construct the loop this way because a
151 	// given filter could support more than one file type,
152 	// so we must query a match for all file types
153 	UT_uint32 nrElements = getNumScripts();
154 
155 	for (UT_uint32 k=0; k < nrElements; k++)
156     {
157 		const UT_ScriptSniffer * s = mSniffers->getNthItem (k);
158 		if (s->recognizeContents(szBuf, iNumbytes))
159 		{
160 			for (UT_sint32 a = 0; a < static_cast<int>(nrElements); a++)
161 			{
162 				if (s->supportsType(static_cast<UT_ScriptIdType>(a+1)))
163 					return static_cast<UT_ScriptIdType>(a+1);
164 			}
165 
166 			UT_ASSERT(UT_SHOULD_NOT_HAPPEN);
167 			// Hm... an importer recognizes the given data
168 			// but refuses to support any file type we request.
169 			return -1;
170 		}
171     }
172 
173 	// No filter recognizes this data
174 	return -1;
175 
176 }
177 
typeForSuffix(const char * szSuffix)178 UT_ScriptIdType	UT_ScriptLibrary::typeForSuffix(const char * szSuffix)
179 {
180 	if (!szSuffix || !(*szSuffix))
181 		return -1;
182 
183 	// we have to construct the loop this way because a
184 	// given filter could support more than one file type,
185 	// so we must query a suffix match for all file types
186 	UT_uint32 nrElements = getNumScripts();
187 
188 	for (UT_uint32 k=0; k < nrElements; k++)
189     {
190 		const UT_ScriptSniffer * s = mSniffers->getNthItem(k);
191 		if (s->recognizeSuffix(szSuffix))
192 		{
193 			for (UT_sint32 a = 0; a < static_cast<int>(nrElements); a++)
194 			{
195 				if (s->supportsType(static_cast<UT_ScriptIdType>(a+1)))
196 					return static_cast<UT_ScriptIdType>(a+1);
197 			}
198 
199 			UT_ASSERT(UT_SHOULD_NOT_HAPPEN);
200 			// Hm... an importer has registered for the given suffix,
201 			// but refuses to support any file type we request.
202 			return -1;
203 		}
204     }
205 
206 	// No filter is registered for that extension
207 	return -1;
208 }
209 
suffixesForType(UT_ScriptIdType ieft)210 const char * UT_ScriptLibrary::suffixesForType(UT_ScriptIdType ieft)
211 {
212 	const char * szSuffixes = 0;
213 
214 	// we have to construct the loop this way because a
215 	// given filter could support more than one file type,
216 	// so we must query a suffix match for all file types
217 	UT_uint32 nrElements = getNumScripts();
218 
219 	for (UT_uint32 k=0; k < nrElements; k++)
220     {
221 		const UT_ScriptSniffer * s = mSniffers->getNthItem(k);
222 		if (s->supportsType(ieft))
223 		{
224 			const char *szDummy;
225 			UT_ScriptIdType ieftDummy;
226 			if (s->getDlgLabels(&szDummy,&szSuffixes,&ieftDummy))
227 			{
228 				return szSuffixes;
229 			}
230 			else
231 			{
232 				UT_ASSERT(UT_SHOULD_NOT_HAPPEN);
233 			}
234 		}
235     }
236 
237 	// The passed in filetype is invalid.
238 	return 0;
239 }
240 
constructScript(const char * szFilename,UT_ScriptIdType ieft,UT_Script ** ppscript,UT_ScriptIdType * pieft)241 UT_Error UT_ScriptLibrary::constructScript(const char * szFilename,
242 										   UT_ScriptIdType ieft,
243 										   UT_Script ** ppscript,
244 										   UT_ScriptIdType * pieft)
245 {
246 	UT_return_val_if_fail(((ieft != -1) || (szFilename && *szFilename)) &&
247 						  ppscript, UT_ERROR);
248 
249 	// no filter will support -1, so we try to detect
250 	// from the contents of the file or the filename suffix
251 	// the importer to use and assign that back to ieft.
252 	// Give precedence to the file contents
253 	if (ieft == -1 && szFilename && *szFilename)
254     {
255 		char szBuf[4096];  // 4096 ought to be enough
256 		int iNumbytes;
257 		FILE *f;
258 		// we must open in binary mode for UCS-2 compatibility
259 		if ( ( f = fopen( szFilename, "rb" ) ) != static_cast<FILE *>(0) )
260 		{
261 			iNumbytes = fread(szBuf, 1, sizeof(szBuf), f);
262 			fclose(f);
263 			ieft = typeForContents(szBuf, iNumbytes);
264 		}
265     }
266 	if (ieft == -1 && szFilename && *szFilename)
267     {
268 		ieft = typeForSuffix(UT_pathSuffix(szFilename).c_str());
269     }
270 
271 	UT_return_val_if_fail(ieft != -1, UT_ERROR);
272 
273 	// tell the caller the type of importer they got
274 	if (pieft != NULL)
275 		*pieft = ieft;
276 
277 	// use the importer for the specified file type
278 	UT_uint32 nrElements = getNumScripts();
279 
280 	for (UT_uint32 k=0; k < nrElements; k++)
281     {
282 		const UT_ScriptSniffer * s = mSniffers->getNthItem (k);
283 		if (s->supportsType(ieft))
284 			return s->constructScript(ppscript);
285     }
286 
287 	// all has failed
288 	return UT_ERROR;
289 }
290 
enumerateDlgLabels(UT_uint32 ndx,const char ** pszDesc,const char ** pszSuffixList,UT_ScriptIdType * ft)291 bool UT_ScriptLibrary::enumerateDlgLabels(UT_uint32 ndx,
292 										  const char ** pszDesc,
293 										  const char ** pszSuffixList,
294 										  UT_ScriptIdType * ft)
295 {
296 	UT_uint32 nrElements = getNumScripts();
297 	if (ndx < nrElements)
298 	{
299 		const UT_ScriptSniffer * s = mSniffers->getNthItem (ndx);
300 		return s->getDlgLabels(pszDesc,pszSuffixList,ft);
301 	}
302 
303 	return false;
304 }
305 
306