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