1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 #ifndef HELPCOMPILER_HXX
25 #define HELPCOMPILER_HXX
26 
27 #include <string>
28 #include <hash_map>
29 #include <vector>
30 #include <list>
31 #include <fstream>
32 #include <iostream>
33 #include <sstream>
34 #include <algorithm>
35 #include <ctype.h>
36 
37 #include <boost/shared_ptr.hpp>
38 
39 #include <libxml/xmlmemory.h>
40 #include <libxml/debugXML.h>
41 #include <libxml/HTMLtree.h>
42 #include <libxml/xmlIO.h>
43 #include <libxml/xinclude.h>
44 #include <libxml/catalog.h>
45 
46 #include <rtl/ustring.hxx>
47 #include <osl/thread.h>
48 #include <osl/process.h>
49 #include <osl/file.hxx>
50 
51 #include <compilehelp.hxx>
52 
53 #define EMULATEORIGINAL 1
54 
55 #ifdef CMCDEBUG
56 	#define HCDBG(foo) do { if (1) foo; } while(0)
57 #else
58 	#define HCDBG(foo) do { if (0) foo; } while(0)
59 #endif
60 
61 namespace fs
62 {
63 	rtl_TextEncoding getThreadTextEncoding( void );
64 
65 	enum convert { native };
66 	class path
67 	{
68 	public:
69 		::rtl::OUString data;
70 	public:
path()71 		path() {}
path(const path & rOther)72 		path(const path &rOther) : data(rOther.data) {}
path(const std::string & in,convert)73 		path(const std::string &in, convert)
74 		{
75 			rtl::OUString sWorkingDir;
76 			osl_getProcessWorkingDir(&sWorkingDir.pData);
77 
78 			rtl::OString tmp(in.c_str());
79 			rtl::OUString ustrSystemPath(rtl::OStringToOUString(tmp, getThreadTextEncoding()));
80 			osl::File::getFileURLFromSystemPath(ustrSystemPath, data);
81 			osl::File::getAbsoluteFileURL(sWorkingDir, data, data);
82 		}
path(const std::string & FileURL)83 		path(const std::string &FileURL)
84 		{
85 			rtl::OString tmp(FileURL.c_str());
86 			data = rtl::OStringToOUString(tmp, getThreadTextEncoding());
87 		}
native_file_string() const88 		std::string native_file_string() const
89 		{
90 			::rtl::OUString ustrSystemPath;
91 			osl::File::getSystemPathFromFileURL(data, ustrSystemPath);
92 			rtl::OString tmp(rtl::OUStringToOString(ustrSystemPath, getThreadTextEncoding()));
93 			HCDBG(std::cerr << "native_file_string is " << tmp.getStr() << std::endl);
94 			return std::string(tmp.getStr());
95 		}
96 #ifdef WNT
native_file_string_w() const97 		wchar_t const * native_file_string_w() const
98 		{
99 			::rtl::OUString ustrSystemPath;
100 			osl::File::getSystemPathFromFileURL(data, ustrSystemPath);
101 			return reinterpret_cast< wchar_t const * >(ustrSystemPath.getStr());
102 		}
103 #endif
native_directory_string() const104 		std::string native_directory_string() const { return native_file_string(); }
toUTF8() const105 		std::string toUTF8() const
106 		{
107 			rtl::OString tmp(rtl::OUStringToOString(data, RTL_TEXTENCODING_UTF8));
108 			return std::string(tmp.getStr());
109 		}
empty() const110 		bool empty() const { return data.getLength() == 0; }
operator /(const std::string & in) const111 		path operator/(const std::string &in) const
112 		{
113 			path ret(*this);
114 			HCDBG(std::cerr << "orig was " <<
115 				rtl::OUStringToOString(ret.data, RTL_TEXTENCODING_UTF8).getStr() << std::endl);
116 			rtl::OString tmp(in.c_str());
117 			rtl::OUString ustrSystemPath(rtl::OStringToOUString(tmp, getThreadTextEncoding()));
118 			ret.data += rtl::OUString(sal_Unicode('/'));
119 			ret.data += ustrSystemPath;
120 			HCDBG(std::cerr << "final is " <<
121 				rtl::OUStringToOString(ret.data, RTL_TEXTENCODING_UTF8).getStr() << std::endl);
122 			return ret;
123 		}
append(const char * in)124 		void append(const char *in)
125 		{
126 			rtl::OString tmp(in);
127 			rtl::OUString ustrSystemPath(rtl::OStringToOUString(tmp, getThreadTextEncoding()));
128 			data = data + ustrSystemPath;
129 		}
append(const std::string & in)130 		void append(const std::string &in) { append(in.c_str()); }
131 	};
132 
133 	void create_directory(const fs::path indexDirName);
134 	void rename(const fs::path &src, const fs::path &dest);
135 	void copy(const fs::path &src, const fs::path &dest);
136 	bool exists(const fs::path &in);
137 	void remove_all(const fs::path &in);
138 	void remove(const fs::path &in);
139 }
140 
141 struct joaat_hash
142 {
operator ()joaat_hash143 	size_t operator()(const std::string &str) const
144 	{
145 		size_t hash = 0;
146 		const char *key = str.data();
147 		for (size_t i = 0; i < str.size(); i++)
148 		{
149 			hash += key[i];
150 			hash += (hash << 10);
151 			hash ^= (hash >> 6);
152 		}
153 		hash += (hash << 3);
154 		hash ^= (hash >> 11);
155 		hash += (hash << 15);
156 		return hash;
157 	}
158 };
159 
160 #define get16bits(d) ((((sal_uInt32)(((const sal_uInt8 *)(d))[1])) << 8)\
161 					   +(sal_uInt32)(((const sal_uInt8 *)(d))[0]) )
162 
163 struct SuperFastHash
164 {
operator ()SuperFastHash165 	size_t operator()(const std::string &str) const
166 	{
167 		const char * data = str.data();
168 		int len = str.size();
169 		size_t hash = len, tmp;
170 		if (len <= 0 || data == NULL) return 0;
171 
172 		int rem = len & 3;
173 		len >>= 2;
174 
175 		/* Main loop */
176 		for (;len > 0; len--)
177 		{
178 			hash  += get16bits (data);
179 			tmp    = (get16bits (data+2) << 11) ^ hash;
180 			hash   = (hash << 16) ^ tmp;
181 			data  += 2*sizeof (sal_uInt16);
182 			hash  += hash >> 11;
183 		}
184 
185 		/* Handle end cases */
186 		switch (rem)
187 		{
188 			case 3: hash += get16bits (data);
189 					hash ^= hash << 16;
190 					hash ^= data[sizeof (sal_uInt16)] << 18;
191 					hash += hash >> 11;
192 					break;
193 			case 2: hash += get16bits (data);
194 					hash ^= hash << 11;
195 					hash += hash >> 17;
196 					break;
197 			case 1: hash += *data;
198 					hash ^= hash << 10;
199 					hash += hash >> 1;
200 		}
201 
202 		/* Force "avalanching" of final 127 bits */
203 		hash ^= hash << 3;
204 		hash += hash >> 5;
205 		hash ^= hash << 4;
206 		hash += hash >> 17;
207 		hash ^= hash << 25;
208 		hash += hash >> 6;
209 
210 		return hash;
211 	}
212 };
213 
214 #define pref_hash joaat_hash
215 
216 typedef std::hash_map<std::string, std::string, pref_hash> Stringtable;
217 typedef std::list<std::string> LinkedList;
218 typedef std::vector<std::string> HashSet;
219 
220 typedef std::hash_map<std::string, LinkedList, pref_hash> Hashtable;
221 
222 class StreamTable
223 {
224 public:
225 	std::string document_id;
226 	std::string document_path;
227 	std::string document_module;
228 	std::string document_title;
229 
230 	HashSet *appl_hidlist;
231 	Hashtable *appl_keywords;
232 	Stringtable *appl_helptexts;
233 	xmlDocPtr appl_doc;
234 
235 	HashSet *default_hidlist;
236 	Hashtable *default_keywords;
237 	Stringtable *default_helptexts;
238 	xmlDocPtr default_doc;
239 
StreamTable()240 	StreamTable() :
241 		appl_hidlist(NULL), appl_keywords(NULL), appl_helptexts(NULL), appl_doc(NULL),
242 		default_hidlist(NULL), default_keywords(NULL), default_helptexts(NULL), default_doc(NULL)
243 	{}
dropdefault()244 	void dropdefault()
245 	{
246 		delete default_hidlist;
247 		delete default_keywords;
248 		delete default_helptexts;
249 		if (default_doc) xmlFreeDoc(default_doc);
250 	}
dropappl()251 	void dropappl()
252 	{
253 		delete appl_hidlist;
254 		delete appl_keywords;
255 		delete appl_helptexts;
256 		if (appl_doc) xmlFreeDoc(appl_doc);
257 	}
~StreamTable()258 	~StreamTable()
259 	{
260 		dropappl();
261 		dropdefault();
262 	}
263 };
264 
265 struct HelpProcessingException
266 {
267 	HelpProcessingErrorClass		m_eErrorClass;
268 	std::string						m_aErrorMsg;
269 	std::string						m_aXMLParsingFile;
270 	int								m_nXMLParsingLine;
271 
HelpProcessingExceptionHelpProcessingException272 	HelpProcessingException( HelpProcessingErrorClass eErrorClass, const std::string& aErrorMsg )
273 		: m_eErrorClass( eErrorClass )
274 		, m_aErrorMsg( aErrorMsg )
275 	{}
HelpProcessingExceptionHelpProcessingException276 	HelpProcessingException( const std::string& aErrorMsg, const std::string& aXMLParsingFile, int nXMLParsingLine )
277 		: m_eErrorClass( HELPPROCESSING_XMLPARSING_ERROR )
278 		, m_aErrorMsg( aErrorMsg )
279 		, m_aXMLParsingFile( aXMLParsingFile )
280 		, m_nXMLParsingLine( nXMLParsingLine )
281 	{}
282 };
283 
284 class HelpCompiler
285 {
286 public:
287 	HelpCompiler(StreamTable &streamTable,
288 				const fs::path &in_inputFile,
289 				const fs::path &in_src,
290 				const fs::path &in_resEmbStylesheet,
291 				const std::string &in_module,
292 				const std::string &in_lang,
293 				bool in_bExtensionMode);
294 	bool compile( void ) throw (HelpProcessingException);
295 	void addEntryToJarFile(const std::string &prefix,
296 		const std::string &entryName, const std::string &bytesToAdd);
297 	void addEntryToJarFile(const std::string &prefix,
298 				const std::string &entryName, const HashSet &bytesToAdd);
299 	void addEntryToJarFile(const std::string &prefix,
300 				const std::string &entryName, const Stringtable &bytesToAdd);
301 	void addEntryToJarFile(const std::string &prefix,
302 				const std::string &entryName, const Hashtable &bytesToAdd);
303 private:
304 	xmlDocPtr getSourceDocument(const fs::path &filePath);
305 	HashSet switchFind(xmlDocPtr doc);
306 	xmlNodePtr clone(xmlNodePtr node, const std::string& appl);
307 	StreamTable &streamTable;
308 	const fs::path inputFile, src;
309 	const std::string module, lang;
310 	const fs::path resEmbStylesheet;
311 	bool bExtensionMode;
312 };
313 
314 #endif
315 
316 /* vim: set noet sw=4 ts=4: */
317