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 #ifdef SYSTEM_DB
37 #include <db.h>
38 #else
39 #include <berkeleydb/db.h>
40 #endif
41 
42 #include <boost/shared_ptr.hpp>
43 
44 #include <libxml/xmlmemory.h>
45 #include <libxml/debugXML.h>
46 #include <libxml/HTMLtree.h>
47 #include <libxml/xmlIO.h>
48 #include <libxml/xinclude.h>
49 #include <libxml/catalog.h>
50 
51 #include <rtl/ustring.hxx>
52 #include <osl/thread.h>
53 #include <osl/process.h>
54 #include <osl/file.hxx>
55 
56 #include <compilehelp.hxx>
57 
58 #define EMULATEORIGINAL 1
59 
60 #ifdef CMCDEBUG
61     #define HCDBG(foo) do { if (1) foo; } while(0)
62 #else
63     #define HCDBG(foo) do { if (0) foo; } while(0)
64 #endif
65 
66 namespace fs
67 {
68 	rtl_TextEncoding getThreadTextEncoding( void );
69 
70     enum convert { native };
71     class path
72     {
73     public:
74         ::rtl::OUString data;
75     public:
76         path() {}
77         path(const path &rOther) : data(rOther.data) {}
78         path(const std::string &in, convert)
79         {
80             rtl::OUString sWorkingDir;
81             osl_getProcessWorkingDir(&sWorkingDir.pData);
82 
83             rtl::OString tmp(in.c_str());
84             rtl::OUString ustrSystemPath(rtl::OStringToOUString(tmp, getThreadTextEncoding()));
85             osl::File::getFileURLFromSystemPath(ustrSystemPath, data);
86             osl::File::getAbsoluteFileURL(sWorkingDir, data, data);
87         }
88         path(const std::string &FileURL)
89 		{
90             rtl::OString tmp(FileURL.c_str());
91             data = rtl::OStringToOUString(tmp, getThreadTextEncoding());
92 		}
93         std::string native_file_string() const
94         {
95             ::rtl::OUString ustrSystemPath;
96             osl::File::getSystemPathFromFileURL(data, ustrSystemPath);
97             rtl::OString tmp(rtl::OUStringToOString(ustrSystemPath, getThreadTextEncoding()));
98             HCDBG(std::cerr << "native_file_string is " << tmp.getStr() << std::endl);
99             return std::string(tmp.getStr());
100         }
101 #ifdef WNT
102         wchar_t const * native_file_string_w() const
103         {
104             ::rtl::OUString ustrSystemPath;
105             osl::File::getSystemPathFromFileURL(data, ustrSystemPath);
106             return reinterpret_cast< wchar_t const * >(ustrSystemPath.getStr());
107         }
108 #endif
109         std::string native_directory_string() const { return native_file_string(); }
110         std::string toUTF8() const
111         {
112             rtl::OString tmp(rtl::OUStringToOString(data, RTL_TEXTENCODING_UTF8));
113             return std::string(tmp.getStr());
114         }
115         bool empty() const { return data.getLength() == 0; }
116         path operator/(const std::string &in) const
117         {
118             path ret(*this);
119             HCDBG(std::cerr << "orig was " <<
120                 rtl::OUStringToOString(ret.data, RTL_TEXTENCODING_UTF8).getStr() << std::endl);
121             rtl::OString tmp(in.c_str());
122             rtl::OUString ustrSystemPath(rtl::OStringToOUString(tmp, getThreadTextEncoding()));
123             ret.data += rtl::OUString(sal_Unicode('/'));
124             ret.data += ustrSystemPath;
125             HCDBG(std::cerr << "final is " <<
126                 rtl::OUStringToOString(ret.data, RTL_TEXTENCODING_UTF8).getStr() << std::endl);
127             return ret;
128         }
129         void append(const char *in)
130         {
131             rtl::OString tmp(in);
132             rtl::OUString ustrSystemPath(rtl::OStringToOUString(tmp, getThreadTextEncoding()));
133             data = data + ustrSystemPath;
134         }
135         void append(const std::string &in) { append(in.c_str()); }
136     };
137 
138     void create_directory(const fs::path indexDirName);
139     void rename(const fs::path &src, const fs::path &dest);
140     void copy(const fs::path &src, const fs::path &dest);
141     bool exists(const fs::path &in);
142     void remove_all(const fs::path &in);
143     void remove(const fs::path &in);
144 }
145 
146 struct joaat_hash
147 {
148     size_t operator()(const std::string &str) const
149     {
150         size_t hash = 0;
151         const char *key = str.data();
152         for (size_t i = 0; i < str.size(); i++)
153         {
154             hash += key[i];
155             hash += (hash << 10);
156             hash ^= (hash >> 6);
157         }
158         hash += (hash << 3);
159         hash ^= (hash >> 11);
160         hash += (hash << 15);
161         return hash;
162     }
163 };
164 
165 #define get16bits(d) ((((sal_uInt32)(((const sal_uInt8 *)(d))[1])) << 8)\
166                        +(sal_uInt32)(((const sal_uInt8 *)(d))[0]) )
167 
168 struct SuperFastHash
169 {
170     size_t operator()(const std::string &str) const
171     {
172         const char * data = str.data();
173         int len = str.size();
174         size_t hash = len, tmp;
175         if (len <= 0 || data == NULL) return 0;
176 
177         int rem = len & 3;
178         len >>= 2;
179 
180         /* Main loop */
181         for (;len > 0; len--)
182         {
183             hash  += get16bits (data);
184             tmp    = (get16bits (data+2) << 11) ^ hash;
185             hash   = (hash << 16) ^ tmp;
186             data  += 2*sizeof (sal_uInt16);
187             hash  += hash >> 11;
188         }
189 
190         /* Handle end cases */
191         switch (rem)
192         {
193             case 3: hash += get16bits (data);
194                     hash ^= hash << 16;
195                     hash ^= data[sizeof (sal_uInt16)] << 18;
196                     hash += hash >> 11;
197                     break;
198             case 2: hash += get16bits (data);
199                     hash ^= hash << 11;
200                     hash += hash >> 17;
201                     break;
202             case 1: hash += *data;
203                     hash ^= hash << 10;
204                     hash += hash >> 1;
205         }
206 
207         /* Force "avalanching" of final 127 bits */
208         hash ^= hash << 3;
209         hash += hash >> 5;
210         hash ^= hash << 4;
211         hash += hash >> 17;
212         hash ^= hash << 25;
213         hash += hash >> 6;
214 
215         return hash;
216     }
217 };
218 
219 #define pref_hash joaat_hash
220 
221 typedef std::hash_map<std::string, std::string, pref_hash> Stringtable;
222 typedef std::list<std::string> LinkedList;
223 typedef std::vector<std::string> HashSet;
224 
225 typedef std::hash_map<std::string, LinkedList, pref_hash> Hashtable;
226 
227 class StreamTable
228 {
229 public:
230     std::string document_id;
231     std::string document_path;
232     std::string document_module;
233     std::string document_title;
234 
235     HashSet *appl_hidlist;
236     Hashtable *appl_keywords;
237     Stringtable *appl_helptexts;
238     xmlDocPtr appl_doc;
239 
240     HashSet *default_hidlist;
241     Hashtable *default_keywords;
242     Stringtable *default_helptexts;
243     xmlDocPtr default_doc;
244 
245     StreamTable() :
246         appl_hidlist(NULL), appl_keywords(NULL), appl_helptexts(NULL), appl_doc(NULL),
247         default_hidlist(NULL), default_keywords(NULL), default_helptexts(NULL), default_doc(NULL)
248     {}
249     void dropdefault()
250     {
251         delete default_hidlist;
252         delete default_keywords;
253         delete default_helptexts;
254         if (default_doc) xmlFreeDoc(default_doc);
255     }
256     void dropappl()
257     {
258         delete appl_hidlist;
259         delete appl_keywords;
260         delete appl_helptexts;
261         if (appl_doc) xmlFreeDoc(appl_doc);
262     }
263     ~StreamTable()
264     {
265         dropappl();
266         dropdefault();
267     }
268 };
269 
270 struct HelpProcessingException
271 {
272 	HelpProcessingErrorClass		m_eErrorClass;
273 	std::string						m_aErrorMsg;
274 	std::string						m_aXMLParsingFile;
275 	int								m_nXMLParsingLine;
276 
277 	HelpProcessingException( HelpProcessingErrorClass eErrorClass, const std::string& aErrorMsg )
278 		: m_eErrorClass( eErrorClass )
279 		, m_aErrorMsg( aErrorMsg )
280 	{}
281 	HelpProcessingException( const std::string& aErrorMsg, const std::string& aXMLParsingFile, int nXMLParsingLine )
282 		: m_eErrorClass( HELPPROCESSING_XMLPARSING_ERROR )
283 		, m_aErrorMsg( aErrorMsg )
284 		, m_aXMLParsingFile( aXMLParsingFile )
285 		, m_nXMLParsingLine( nXMLParsingLine )
286 	{}
287 };
288 
289 class HelpCompiler
290 {
291 public:
292     HelpCompiler(StreamTable &streamTable,
293                 const fs::path &in_inputFile,
294                 const fs::path &in_src,
295                 const fs::path &in_resEmbStylesheet,
296                 const std::string &in_module,
297                 const std::string &in_lang,
298 				bool in_bExtensionMode);
299     bool compile( void ) throw (HelpProcessingException);
300     void addEntryToJarFile(const std::string &prefix,
301         const std::string &entryName, const std::string &bytesToAdd);
302     void addEntryToJarFile(const std::string &prefix,
303                 const std::string &entryName, const HashSet &bytesToAdd);
304     void addEntryToJarFile(const std::string &prefix,
305                 const std::string &entryName, const Stringtable &bytesToAdd);
306     void addEntryToJarFile(const std::string &prefix,
307                 const std::string &entryName, const Hashtable &bytesToAdd);
308 private:
309     xmlDocPtr getSourceDocument(const fs::path &filePath);
310     HashSet switchFind(xmlDocPtr doc);
311     xmlNodePtr clone(xmlNodePtr node, const std::string& appl);
312     StreamTable &streamTable;
313     const fs::path inputFile, src;
314     const std::string module, lang;
315     const fs::path resEmbStylesheet;
316 	bool bExtensionMode;
317 };
318 
319 #endif
320 
321 /* vi:set tabstop=4 shiftwidth=4 expandtab: */
322