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:
71         path() {}
72         path(const path &rOther) : data(rOther.data) {}
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         }
83         path(const std::string &FileURL)
84 		{
85             rtl::OString tmp(FileURL.c_str());
86             data = rtl::OStringToOUString(tmp, getThreadTextEncoding());
87 		}
88         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
97         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
104         std::string native_directory_string() const { return native_file_string(); }
105         std::string toUTF8() const
106         {
107             rtl::OString tmp(rtl::OUStringToOString(data, RTL_TEXTENCODING_UTF8));
108             return std::string(tmp.getStr());
109         }
110         bool empty() const { return data.getLength() == 0; }
111         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         }
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         }
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 {
143     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 {
165     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 
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     {}
244     void dropdefault()
245     {
246         delete default_hidlist;
247         delete default_keywords;
248         delete default_helptexts;
249         if (default_doc) xmlFreeDoc(default_doc);
250     }
251     void dropappl()
252     {
253         delete appl_hidlist;
254         delete appl_keywords;
255         delete appl_helptexts;
256         if (appl_doc) xmlFreeDoc(appl_doc);
257     }
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 
272 	HelpProcessingException( HelpProcessingErrorClass eErrorClass, const std::string& aErrorMsg )
273 		: m_eErrorClass( eErrorClass )
274 		, m_aErrorMsg( aErrorMsg )
275 	{}
276 	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 /* vi:set tabstop=4 shiftwidth=4 expandtab: */
317