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