13cd96b95SAndrew Rist /************************************************************** 23cd96b95SAndrew Rist * 33cd96b95SAndrew Rist * Licensed to the Apache Software Foundation (ASF) under one 43cd96b95SAndrew Rist * or more contributor license agreements. See the NOTICE file 53cd96b95SAndrew Rist * distributed with this work for additional information 63cd96b95SAndrew Rist * regarding copyright ownership. The ASF licenses this file 73cd96b95SAndrew Rist * to you under the Apache License, Version 2.0 (the 83cd96b95SAndrew Rist * "License"); you may not use this file except in compliance 93cd96b95SAndrew Rist * with the License. You may obtain a copy of the License at 103cd96b95SAndrew Rist * 113cd96b95SAndrew Rist * http://www.apache.org/licenses/LICENSE-2.0 123cd96b95SAndrew Rist * 133cd96b95SAndrew Rist * Unless required by applicable law or agreed to in writing, 143cd96b95SAndrew Rist * software distributed under the License is distributed on an 153cd96b95SAndrew Rist * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 163cd96b95SAndrew Rist * KIND, either express or implied. See the License for the 173cd96b95SAndrew Rist * specific language governing permissions and limitations 183cd96b95SAndrew Rist * under the License. 193cd96b95SAndrew Rist * 203cd96b95SAndrew Rist *************************************************************/ 213cd96b95SAndrew Rist 223cd96b95SAndrew Rist 23cdf0e10cSrcweir 24cdf0e10cSrcweir #include "HelpCompiler.hxx" 25cdf0e10cSrcweir 26cdf0e10cSrcweir #include <map> 27cdf0e10cSrcweir 28cdf0e10cSrcweir #include <string.h> 29cdf0e10cSrcweir #include <limits.h> 30cdf0e10cSrcweir 31cdf0e10cSrcweir #include <libxslt/xslt.h> 32cdf0e10cSrcweir #include <libxslt/transform.h> 33cdf0e10cSrcweir #include <libxslt/xsltutils.h> 34cdf0e10cSrcweir #include <libxslt/functions.h> 35cdf0e10cSrcweir #include <libxslt/extensions.h> 36cdf0e10cSrcweir 37cdf0e10cSrcweir #include <sal/types.h> 38cdf0e10cSrcweir #include <osl/time.h> 39cdf0e10cSrcweir #include <rtl/bootstrap.hxx> 40cdf0e10cSrcweir 41cdf0e10cSrcweir #include <expat.h> 42cdf0e10cSrcweir 43cdf0e10cSrcweir class IndexerPreProcessor 44cdf0e10cSrcweir { 45cdf0e10cSrcweir private: 46cdf0e10cSrcweir std::string m_aModuleName; 47cdf0e10cSrcweir fs::path m_fsIndexBaseDir; 48cdf0e10cSrcweir fs::path m_fsCaptionFilesDirName; 49cdf0e10cSrcweir fs::path m_fsContentFilesDirName; 50cdf0e10cSrcweir 51cdf0e10cSrcweir xsltStylesheetPtr m_xsltStylesheetPtrCaption; 52cdf0e10cSrcweir xsltStylesheetPtr m_xsltStylesheetPtrContent; 53cdf0e10cSrcweir 54cdf0e10cSrcweir public: 55cdf0e10cSrcweir IndexerPreProcessor( const std::string& aModuleName, const fs::path& fsIndexBaseDir, 56cdf0e10cSrcweir const fs::path& idxCaptionStylesheet, const fs::path& idxContentStylesheet ); 57cdf0e10cSrcweir ~IndexerPreProcessor(); 58cdf0e10cSrcweir 59cdf0e10cSrcweir void processDocument( xmlDocPtr doc, const std::string& EncodedDocPath ); 60cdf0e10cSrcweir }; 61cdf0e10cSrcweir 62cdf0e10cSrcweir IndexerPreProcessor::IndexerPreProcessor 63cdf0e10cSrcweir ( const std::string& aModuleName, const fs::path& fsIndexBaseDir, 64cdf0e10cSrcweir const fs::path& idxCaptionStylesheet, const fs::path& idxContentStylesheet ) 65cdf0e10cSrcweir : m_aModuleName( aModuleName ) 66cdf0e10cSrcweir , m_fsIndexBaseDir( fsIndexBaseDir ) 67cdf0e10cSrcweir { 68cdf0e10cSrcweir m_fsCaptionFilesDirName = fsIndexBaseDir / "caption"; 69cdf0e10cSrcweir fs::create_directory( m_fsCaptionFilesDirName ); 70cdf0e10cSrcweir 71cdf0e10cSrcweir m_fsContentFilesDirName = fsIndexBaseDir / "content"; 72cdf0e10cSrcweir fs::create_directory( m_fsContentFilesDirName ); 73cdf0e10cSrcweir 74cdf0e10cSrcweir m_xsltStylesheetPtrCaption = xsltParseStylesheetFile 75cdf0e10cSrcweir ((const xmlChar *)idxCaptionStylesheet.native_file_string().c_str()); 76cdf0e10cSrcweir m_xsltStylesheetPtrContent = xsltParseStylesheetFile 77cdf0e10cSrcweir ((const xmlChar *)idxContentStylesheet.native_file_string().c_str()); 78cdf0e10cSrcweir } 79cdf0e10cSrcweir 80cdf0e10cSrcweir IndexerPreProcessor::~IndexerPreProcessor() 81cdf0e10cSrcweir { 82cdf0e10cSrcweir if( m_xsltStylesheetPtrCaption ) 83cdf0e10cSrcweir xsltFreeStylesheet( m_xsltStylesheetPtrCaption ); 84cdf0e10cSrcweir if( m_xsltStylesheetPtrContent ) 85cdf0e10cSrcweir xsltFreeStylesheet( m_xsltStylesheetPtrContent ); 86cdf0e10cSrcweir } 87cdf0e10cSrcweir 88cdf0e10cSrcweir 89cdf0e10cSrcweir std::string getEncodedPath( const std::string& Path ) 90cdf0e10cSrcweir { 91cdf0e10cSrcweir rtl::OString aOStr_Path( Path.c_str() ); 92cdf0e10cSrcweir rtl::OUString aOUStr_Path( rtl::OStringToOUString 93cdf0e10cSrcweir ( aOStr_Path, fs::getThreadTextEncoding() ) ); 94cdf0e10cSrcweir rtl::OUString aPathURL; 95cdf0e10cSrcweir osl::File::getFileURLFromSystemPath( aOUStr_Path, aPathURL ); 96cdf0e10cSrcweir rtl::OString aOStr_PathURL( rtl::OUStringToOString 97cdf0e10cSrcweir ( aPathURL, fs::getThreadTextEncoding() ) ); 98cdf0e10cSrcweir std::string aStdStr_PathURL( aOStr_PathURL.getStr() ); 99cdf0e10cSrcweir return aStdStr_PathURL; 100cdf0e10cSrcweir } 101cdf0e10cSrcweir 102cdf0e10cSrcweir void IndexerPreProcessor::processDocument 103cdf0e10cSrcweir ( xmlDocPtr doc, const std::string &EncodedDocPath ) 104cdf0e10cSrcweir { 105cdf0e10cSrcweir std::string aStdStr_EncodedDocPathURL = getEncodedPath( EncodedDocPath ); 106cdf0e10cSrcweir 107cdf0e10cSrcweir if( m_xsltStylesheetPtrCaption ) 108cdf0e10cSrcweir { 109cdf0e10cSrcweir xmlDocPtr resCaption = xsltApplyStylesheet( m_xsltStylesheetPtrCaption, doc, NULL ); 110cdf0e10cSrcweir xmlNodePtr pResNodeCaption = resCaption->xmlChildrenNode; 111cdf0e10cSrcweir if( pResNodeCaption ) 112cdf0e10cSrcweir { 113cdf0e10cSrcweir fs::path fsCaptionPureTextFile_docURL = m_fsCaptionFilesDirName / aStdStr_EncodedDocPathURL; 114cdf0e10cSrcweir std::string aCaptionPureTextFileStr_docURL = fsCaptionPureTextFile_docURL.native_file_string(); 115cdf0e10cSrcweir #ifdef WNT //We need _wfopen to support long file paths on Windows XP 116cdf0e10cSrcweir FILE* pFile_docURL = _wfopen( 117cdf0e10cSrcweir fsCaptionPureTextFile_docURL.native_file_string_w(), L"w" ); 118cdf0e10cSrcweir #else 119cdf0e10cSrcweir FILE* pFile_docURL = fopen( 120cdf0e10cSrcweir fsCaptionPureTextFile_docURL.native_file_string().c_str(), "w" ); 121cdf0e10cSrcweir #endif 122cdf0e10cSrcweir if( pFile_docURL ) 123cdf0e10cSrcweir { 124cdf0e10cSrcweir fprintf( pFile_docURL, "%s\n", pResNodeCaption->content ); 125cdf0e10cSrcweir fclose( pFile_docURL ); 126cdf0e10cSrcweir } 127cdf0e10cSrcweir } 128cdf0e10cSrcweir xmlFreeDoc(resCaption); 129cdf0e10cSrcweir } 130cdf0e10cSrcweir 131cdf0e10cSrcweir if( m_xsltStylesheetPtrContent ) 132cdf0e10cSrcweir { 133cdf0e10cSrcweir xmlDocPtr resContent = xsltApplyStylesheet( m_xsltStylesheetPtrContent, doc, NULL ); 134cdf0e10cSrcweir xmlNodePtr pResNodeContent = resContent->xmlChildrenNode; 135cdf0e10cSrcweir if( pResNodeContent ) 136cdf0e10cSrcweir { 137cdf0e10cSrcweir fs::path fsContentPureTextFile_docURL = m_fsContentFilesDirName / aStdStr_EncodedDocPathURL; 138cdf0e10cSrcweir #ifdef WNT //We need _wfopen to support long file paths on Windows XP 139cdf0e10cSrcweir FILE* pFile_docURL = _wfopen( 140cdf0e10cSrcweir fsContentPureTextFile_docURL.native_file_string_w(), L"w" ); 141cdf0e10cSrcweir #else 142cdf0e10cSrcweir FILE* pFile_docURL = fopen( 143cdf0e10cSrcweir fsContentPureTextFile_docURL.native_file_string().c_str(), "w" ); 144cdf0e10cSrcweir #endif 145cdf0e10cSrcweir if( pFile_docURL ) 146cdf0e10cSrcweir { 147cdf0e10cSrcweir fprintf( pFile_docURL, "%s\n", pResNodeContent->content ); 148cdf0e10cSrcweir fclose( pFile_docURL ); 149cdf0e10cSrcweir } 150cdf0e10cSrcweir } 151cdf0e10cSrcweir xmlFreeDoc(resContent); 152cdf0e10cSrcweir } 153cdf0e10cSrcweir } 154cdf0e10cSrcweir 155cdf0e10cSrcweir struct Data 156cdf0e10cSrcweir { 157cdf0e10cSrcweir std::vector<std::string> _idList; 158cdf0e10cSrcweir typedef std::vector<std::string>::const_iterator cIter; 159cdf0e10cSrcweir 160cdf0e10cSrcweir void append(const std::string &id) 161cdf0e10cSrcweir { 162cdf0e10cSrcweir _idList.push_back(id); 163cdf0e10cSrcweir } 164cdf0e10cSrcweir 165cdf0e10cSrcweir std::string getString() const 166cdf0e10cSrcweir { 167cdf0e10cSrcweir std::string ret; 168cdf0e10cSrcweir cIter aEnd = _idList.end(); 169cdf0e10cSrcweir for (cIter aIter = _idList.begin(); aIter != aEnd; ++aIter) 170cdf0e10cSrcweir ret += *aIter + ";"; 171cdf0e10cSrcweir return ret; 172cdf0e10cSrcweir } 173cdf0e10cSrcweir }; 174cdf0e10cSrcweir 175cdf0e10cSrcweir void writeKeyValue_DBHelp( FILE* pFile, const std::string& aKeyStr, const std::string& aValueStr ) 176cdf0e10cSrcweir { 177cdf0e10cSrcweir if( pFile == NULL ) 178cdf0e10cSrcweir return; 179cdf0e10cSrcweir char cLF = 10; 180cdf0e10cSrcweir unsigned int nKeyLen = aKeyStr.length(); 181cdf0e10cSrcweir unsigned int nValueLen = aValueStr.length(); 182cdf0e10cSrcweir fprintf( pFile, "%x ", nKeyLen ); 183cdf0e10cSrcweir if( nKeyLen > 0 ) 184cdf0e10cSrcweir { 185cdf0e10cSrcweir if (fwrite( aKeyStr.c_str(), 1, nKeyLen, pFile ) != nKeyLen) 186cdf0e10cSrcweir fprintf(stderr, "fwrite to db failed\n"); 187cdf0e10cSrcweir } 188cdf0e10cSrcweir if (fprintf( pFile, " %x ", nValueLen ) < 0) 189cdf0e10cSrcweir fprintf(stderr, "fwrite to db failed\n"); 190cdf0e10cSrcweir if( nValueLen > 0 ) 191cdf0e10cSrcweir { 192cdf0e10cSrcweir if (fwrite( aValueStr.c_str(), 1, nValueLen, pFile ) != nValueLen) 193cdf0e10cSrcweir fprintf(stderr, "fwrite to db failed\n"); 194cdf0e10cSrcweir } 195cdf0e10cSrcweir if (fprintf( pFile, "%c", cLF ) < 0) 196cdf0e10cSrcweir fprintf(stderr, "fwrite to db failed\n"); 197cdf0e10cSrcweir } 198cdf0e10cSrcweir 199cdf0e10cSrcweir class HelpKeyword 200cdf0e10cSrcweir { 201cdf0e10cSrcweir private: 202cdf0e10cSrcweir typedef std::hash_map<std::string, Data, pref_hash> DataHashtable; 203cdf0e10cSrcweir DataHashtable _hash; 204cdf0e10cSrcweir 205cdf0e10cSrcweir public: 206cdf0e10cSrcweir void insert(const std::string &key, const std::string &id) 207cdf0e10cSrcweir { 208cdf0e10cSrcweir Data &data = _hash[key]; 209cdf0e10cSrcweir data.append(id); 210cdf0e10cSrcweir } 211cdf0e10cSrcweir 212cdf0e10cSrcweir void dump_DBHelp( const fs::path& rFileName ) 213cdf0e10cSrcweir { 214cdf0e10cSrcweir #ifdef WNT //We need _wfopen to support long file paths on Windows XP 215cdf0e10cSrcweir FILE* pFile = _wfopen( rFileName.native_file_string_w(), L"wb" ); 216cdf0e10cSrcweir #else 217cdf0e10cSrcweir FILE* pFile = fopen( rFileName.native_file_string().c_str(), "wb" ); 218cdf0e10cSrcweir #endif 219cdf0e10cSrcweir if( pFile == NULL ) 220cdf0e10cSrcweir return; 221cdf0e10cSrcweir 222cdf0e10cSrcweir DataHashtable::const_iterator aEnd = _hash.end(); 223cdf0e10cSrcweir for (DataHashtable::const_iterator aIter = _hash.begin(); aIter != aEnd; ++aIter) 224cdf0e10cSrcweir writeKeyValue_DBHelp( pFile, aIter->first, aIter->second.getString() ); 225cdf0e10cSrcweir 226cdf0e10cSrcweir fclose( pFile ); 227cdf0e10cSrcweir } 228cdf0e10cSrcweir }; 229cdf0e10cSrcweir 230cdf0e10cSrcweir class HelpLinker 231cdf0e10cSrcweir { 232cdf0e10cSrcweir public: 233cdf0e10cSrcweir void main(std::vector<std::string> &args, 234cdf0e10cSrcweir std::string* pExtensionPath = NULL, 235cdf0e10cSrcweir std::string* pDestination = NULL, 236cdf0e10cSrcweir const rtl::OUString* pOfficeHelpPath = NULL ) 237cdf0e10cSrcweir 238cdf0e10cSrcweir throw( HelpProcessingException ); 239cdf0e10cSrcweir 240cdf0e10cSrcweir HelpLinker() 241cdf0e10cSrcweir : init(true) 242cdf0e10cSrcweir , m_pIndexerPreProcessor(NULL) 243cdf0e10cSrcweir {} 244cdf0e10cSrcweir ~HelpLinker() 245cdf0e10cSrcweir { delete m_pIndexerPreProcessor; } 246cdf0e10cSrcweir 247cdf0e10cSrcweir private: 248cdf0e10cSrcweir int locCount, totCount; 249cdf0e10cSrcweir Stringtable additionalFiles; 250cdf0e10cSrcweir HashSet helpFiles; 251cdf0e10cSrcweir fs::path sourceRoot; 252cdf0e10cSrcweir fs::path embeddStylesheet; 253cdf0e10cSrcweir fs::path idxCaptionStylesheet; 254cdf0e10cSrcweir fs::path idxContentStylesheet; 255cdf0e10cSrcweir fs::path zipdir; 256cdf0e10cSrcweir fs::path outputFile; 257cdf0e10cSrcweir std::string extsource; 258cdf0e10cSrcweir std::string extdestination; 259cdf0e10cSrcweir std::string module; 260cdf0e10cSrcweir std::string lang; 261cdf0e10cSrcweir std::string extensionPath; 262cdf0e10cSrcweir std::string extensionDestination; 263cdf0e10cSrcweir bool bExtensionMode; 264cdf0e10cSrcweir fs::path indexDirName; 265cdf0e10cSrcweir fs::path indexDirParentName; 266cdf0e10cSrcweir bool init; 267cdf0e10cSrcweir IndexerPreProcessor* m_pIndexerPreProcessor; 268cdf0e10cSrcweir void initIndexerPreProcessor(); 269cdf0e10cSrcweir void link() throw( HelpProcessingException ); 270*c01398f2SHerbert Dürr void addBookmark( FILE* pFile_DBHelp, std::string thishid, 271cdf0e10cSrcweir const std::string& fileB, const std::string& anchorB, 272cdf0e10cSrcweir const std::string& jarfileB, const std::string& titleB ); 273cdf0e10cSrcweir }; 274cdf0e10cSrcweir 275cdf0e10cSrcweir namespace URLEncoder 276cdf0e10cSrcweir { 277cdf0e10cSrcweir static std::string encode(const std::string &rIn) 278cdf0e10cSrcweir { 279cdf0e10cSrcweir const char *good = "!$&'()*+,-.=@_"; 280cdf0e10cSrcweir static const char hex[17] = "0123456789ABCDEF"; 281cdf0e10cSrcweir 282cdf0e10cSrcweir std::string result; 283cdf0e10cSrcweir for (size_t i=0; i < rIn.length(); ++i) 284cdf0e10cSrcweir { 285cdf0e10cSrcweir unsigned char c = rIn[i]; 286cdf0e10cSrcweir if (isalnum (c) || strchr (good, c)) 287cdf0e10cSrcweir result += c; 288cdf0e10cSrcweir else { 289cdf0e10cSrcweir result += '%'; 290cdf0e10cSrcweir result += hex[c >> 4]; 291cdf0e10cSrcweir result += hex[c & 0xf]; 292cdf0e10cSrcweir } 293cdf0e10cSrcweir } 294cdf0e10cSrcweir return result; 295cdf0e10cSrcweir } 296cdf0e10cSrcweir } 297cdf0e10cSrcweir 298*c01398f2SHerbert Dürr void HelpLinker::addBookmark( FILE* pFile_DBHelp, std::string thishid, 299cdf0e10cSrcweir const std::string& fileB, const std::string& anchorB, 300cdf0e10cSrcweir const std::string& jarfileB, const std::string& titleB) 301cdf0e10cSrcweir { 302cdf0e10cSrcweir HCDBG(std::cerr << "HelpLinker::addBookmark " << thishid << " " << 303cdf0e10cSrcweir fileB << " " << anchorB << " " << jarfileB << " " << titleB << std::endl); 304cdf0e10cSrcweir 305cdf0e10cSrcweir thishid = URLEncoder::encode(thishid); 306cdf0e10cSrcweir 307cdf0e10cSrcweir int fileLen = fileB.length(); 308cdf0e10cSrcweir if (!anchorB.empty()) 309cdf0e10cSrcweir fileLen += (1 + anchorB.length()); 310cdf0e10cSrcweir int dataLen = 1 + fileLen + 1 + jarfileB.length() + 1 + titleB.length(); 311cdf0e10cSrcweir 312cdf0e10cSrcweir std::vector<unsigned char> dataB(dataLen); 313cdf0e10cSrcweir size_t i = 0; 314cdf0e10cSrcweir dataB[i++] = static_cast<unsigned char>(fileLen); 315cdf0e10cSrcweir for (size_t j = 0; j < fileB.length(); ++j) 316cdf0e10cSrcweir dataB[i++] = fileB[j]; 317cdf0e10cSrcweir if (!anchorB.empty()) 318cdf0e10cSrcweir { 319cdf0e10cSrcweir dataB[i++] = '#'; 320cdf0e10cSrcweir for (size_t j = 0; j < anchorB.length(); ++j) 321cdf0e10cSrcweir dataB[i++] = anchorB[j]; 322cdf0e10cSrcweir } 323cdf0e10cSrcweir dataB[i++] = static_cast<unsigned char>(jarfileB.length()); 324cdf0e10cSrcweir for (size_t j = 0; j < jarfileB.length(); ++j) 325cdf0e10cSrcweir dataB[i++] = jarfileB[j]; 326cdf0e10cSrcweir 327cdf0e10cSrcweir dataB[i++] = static_cast<unsigned char>(titleB.length()); 328cdf0e10cSrcweir for (size_t j = 0; j < titleB.length(); ++j) 329cdf0e10cSrcweir dataB[i++] = titleB[j]; 330cdf0e10cSrcweir 331cdf0e10cSrcweir if( pFile_DBHelp != NULL ) 332cdf0e10cSrcweir { 333cdf0e10cSrcweir std::string aValueStr( dataB.begin(), dataB.end() ); 334cdf0e10cSrcweir writeKeyValue_DBHelp( pFile_DBHelp, thishid, aValueStr ); 335cdf0e10cSrcweir } 336cdf0e10cSrcweir } 337cdf0e10cSrcweir 338cdf0e10cSrcweir void HelpLinker::initIndexerPreProcessor() 339cdf0e10cSrcweir { 340cdf0e10cSrcweir if( m_pIndexerPreProcessor ) 341cdf0e10cSrcweir delete m_pIndexerPreProcessor; 342cdf0e10cSrcweir std::string mod = module; 343cdf0e10cSrcweir std::transform (mod.begin(), mod.end(), mod.begin(), tolower); 344cdf0e10cSrcweir m_pIndexerPreProcessor = new IndexerPreProcessor( mod, indexDirParentName, 345cdf0e10cSrcweir idxCaptionStylesheet, idxContentStylesheet ); 346cdf0e10cSrcweir } 347cdf0e10cSrcweir 348cdf0e10cSrcweir /** 349cdf0e10cSrcweir * 350cdf0e10cSrcweir */ 351cdf0e10cSrcweir void HelpLinker::link() throw( HelpProcessingException ) 352cdf0e10cSrcweir { 353cdf0e10cSrcweir bool bIndexForExtension = true; 354cdf0e10cSrcweir 355cdf0e10cSrcweir if( bExtensionMode ) 356cdf0e10cSrcweir { 357cdf0e10cSrcweir //indexDirParentName = sourceRoot; 358cdf0e10cSrcweir indexDirParentName = extensionDestination; 359cdf0e10cSrcweir } 360cdf0e10cSrcweir else 361cdf0e10cSrcweir { 362cdf0e10cSrcweir indexDirParentName = zipdir; 363cdf0e10cSrcweir fs::create_directory(indexDirParentName); 364cdf0e10cSrcweir } 365cdf0e10cSrcweir 366cdf0e10cSrcweir std::string mod = module; 367cdf0e10cSrcweir std::transform (mod.begin(), mod.end(), mod.begin(), tolower); 368cdf0e10cSrcweir 369cdf0e10cSrcweir // do the work here 370cdf0e10cSrcweir // continue with introduction of the overall process thing into the 371cdf0e10cSrcweir // here all hzip files will be worked on 372cdf0e10cSrcweir std::string appl = mod; 373cdf0e10cSrcweir if (appl[0] == 's') 374cdf0e10cSrcweir appl = appl.substr(1); 375cdf0e10cSrcweir 376cdf0e10cSrcweir bool bUse_ = true; 377cdf0e10cSrcweir if( !bExtensionMode ) 378cdf0e10cSrcweir bUse_ = false; 379cdf0e10cSrcweir 380cdf0e10cSrcweir fs::path helpTextFileName_DBHelp(indexDirParentName / (mod + (bUse_ ? ".ht_" : ".ht"))); 381cdf0e10cSrcweir #ifdef WNT 382cdf0e10cSrcweir //We need _wfopen to support long file paths on Windows XP 383cdf0e10cSrcweir FILE* pFileHelpText_DBHelp = _wfopen 384cdf0e10cSrcweir ( helpTextFileName_DBHelp.native_file_string_w(), L"wb" ); 385cdf0e10cSrcweir #else 386cdf0e10cSrcweir 387cdf0e10cSrcweir FILE* pFileHelpText_DBHelp = fopen 388cdf0e10cSrcweir ( helpTextFileName_DBHelp.native_file_string().c_str(), "wb" ); 389cdf0e10cSrcweir #endif 390cdf0e10cSrcweir 391cdf0e10cSrcweir fs::path dbBaseFileName_DBHelp(indexDirParentName / (mod + (bUse_ ? ".db_" : ".db"))); 392cdf0e10cSrcweir #ifdef WNT 393cdf0e10cSrcweir //We need _wfopen to support long file paths on Windows XP 394cdf0e10cSrcweir FILE* pFileDbBase_DBHelp = _wfopen 395cdf0e10cSrcweir ( dbBaseFileName_DBHelp.native_file_string_w(), L"wb" ); 396cdf0e10cSrcweir #else 397cdf0e10cSrcweir FILE* pFileDbBase_DBHelp = fopen 398cdf0e10cSrcweir ( dbBaseFileName_DBHelp.native_file_string().c_str(), "wb" ); 399cdf0e10cSrcweir #endif 400cdf0e10cSrcweir 401cdf0e10cSrcweir fs::path keyWordFileName_DBHelp(indexDirParentName / (mod + (bUse_ ? ".key_" : ".key"))); 402cdf0e10cSrcweir 403cdf0e10cSrcweir HelpKeyword helpKeyword; 404cdf0e10cSrcweir 405cdf0e10cSrcweir // catch HelpProcessingException to avoid locking data bases 406cdf0e10cSrcweir try 407cdf0e10cSrcweir { 408cdf0e10cSrcweir 409cdf0e10cSrcweir // lastly, initialize the indexBuilder 410cdf0e10cSrcweir if ( (!bExtensionMode || bIndexForExtension) && !helpFiles.empty()) 411cdf0e10cSrcweir initIndexerPreProcessor(); 412cdf0e10cSrcweir 413cdf0e10cSrcweir if( !bExtensionMode ) 414cdf0e10cSrcweir { 415cdf0e10cSrcweir #ifndef OS2 // YD @TODO@ crashes libc runtime :-( 416cdf0e10cSrcweir std::cout << "Making " << outputFile.native_file_string() << 417cdf0e10cSrcweir " from " << helpFiles.size() << " input files" << std::endl; 418cdf0e10cSrcweir #endif 419cdf0e10cSrcweir } 420cdf0e10cSrcweir 421cdf0e10cSrcweir // here we start our loop over the hzip files. 422cdf0e10cSrcweir HashSet::iterator end = helpFiles.end(); 423cdf0e10cSrcweir for (HashSet::iterator iter = helpFiles.begin(); iter != end; ++iter) 424cdf0e10cSrcweir { 425cdf0e10cSrcweir if( !bExtensionMode ) 426cdf0e10cSrcweir { 427cdf0e10cSrcweir std::cout << "."; 428cdf0e10cSrcweir std::cout.flush(); 429cdf0e10cSrcweir } 430cdf0e10cSrcweir 431cdf0e10cSrcweir // process one file 432cdf0e10cSrcweir // streamTable contains the streams in the hzip file 433cdf0e10cSrcweir StreamTable streamTable; 434cdf0e10cSrcweir const std::string &xhpFileName = *iter; 435cdf0e10cSrcweir 436cdf0e10cSrcweir if (!bExtensionMode && xhpFileName.rfind(".xhp") != xhpFileName.length()-4) 437cdf0e10cSrcweir { 438cdf0e10cSrcweir // only work on .xhp - files 439cdf0e10cSrcweir std::cerr << 440cdf0e10cSrcweir "ERROR: input list entry '" 441cdf0e10cSrcweir << xhpFileName 442cdf0e10cSrcweir << "' has the wrong extension (only files with extension .xhp " 443cdf0e10cSrcweir << "are accepted)"; 444cdf0e10cSrcweir continue; 445cdf0e10cSrcweir } 446cdf0e10cSrcweir 447cdf0e10cSrcweir fs::path langsourceRoot(sourceRoot); 448cdf0e10cSrcweir fs::path xhpFile; 449cdf0e10cSrcweir 450cdf0e10cSrcweir if( bExtensionMode ) 451cdf0e10cSrcweir { 452cdf0e10cSrcweir // langsourceRoot == sourceRoot for extensions 453cdf0e10cSrcweir std::string xhpFileNameComplete( extensionPath ); 454cdf0e10cSrcweir xhpFileNameComplete.append( '/' + xhpFileName ); 455cdf0e10cSrcweir xhpFile = fs::path( xhpFileNameComplete ); 456cdf0e10cSrcweir } 457cdf0e10cSrcweir else 458cdf0e10cSrcweir { 459cdf0e10cSrcweir langsourceRoot.append('/' + lang + '/'); 460cdf0e10cSrcweir xhpFile = fs::path(xhpFileName, fs::native); 461cdf0e10cSrcweir } 462cdf0e10cSrcweir 463cdf0e10cSrcweir HelpCompiler hc( streamTable, xhpFile, langsourceRoot, 464cdf0e10cSrcweir embeddStylesheet, module, lang, bExtensionMode ); 465cdf0e10cSrcweir 466cdf0e10cSrcweir HCDBG(std::cerr << "before compile of " << xhpFileName << std::endl); 467cdf0e10cSrcweir bool success = hc.compile(); 468cdf0e10cSrcweir HCDBG(std::cerr << "after compile of " << xhpFileName << std::endl); 469cdf0e10cSrcweir 470cdf0e10cSrcweir if (!success && !bExtensionMode) 471cdf0e10cSrcweir { 472cdf0e10cSrcweir std::stringstream aStrStream; 473cdf0e10cSrcweir aStrStream << 474cdf0e10cSrcweir "\nERROR: compiling help particle '" 475cdf0e10cSrcweir << xhpFileName 476cdf0e10cSrcweir << "' for language '" 477cdf0e10cSrcweir << lang 478cdf0e10cSrcweir << "' failed!"; 479cdf0e10cSrcweir throw HelpProcessingException( HELPPROCESSING_GENERAL_ERROR, aStrStream.str() ); 480cdf0e10cSrcweir } 481cdf0e10cSrcweir 482cdf0e10cSrcweir const std::string documentBaseId = streamTable.document_id; 483cdf0e10cSrcweir std::string documentPath = streamTable.document_path; 484cdf0e10cSrcweir if (documentPath.find("/") == 0) 485cdf0e10cSrcweir documentPath = documentPath.substr(1); 486cdf0e10cSrcweir 487cdf0e10cSrcweir std::string documentJarfile = streamTable.document_module + ".jar"; 488cdf0e10cSrcweir 489cdf0e10cSrcweir std::string documentTitle = streamTable.document_title; 490cdf0e10cSrcweir if (documentTitle.empty()) 491cdf0e10cSrcweir documentTitle = "<notitle>"; 492cdf0e10cSrcweir 493cdf0e10cSrcweir const std::string& fileB = documentPath; 494cdf0e10cSrcweir const std::string& jarfileB = documentJarfile; 495cdf0e10cSrcweir std::string& titleB = documentTitle; 496cdf0e10cSrcweir 497cdf0e10cSrcweir // add once this as its own id. 498*c01398f2SHerbert Dürr addBookmark(pFileDbBase_DBHelp, documentPath, fileB, std::string(), jarfileB, titleB); 499cdf0e10cSrcweir 500cdf0e10cSrcweir const HashSet *hidlist = streamTable.appl_hidlist; 501cdf0e10cSrcweir if (!hidlist) 502cdf0e10cSrcweir hidlist = streamTable.default_hidlist; 503cdf0e10cSrcweir if (hidlist && !hidlist->empty()) 504cdf0e10cSrcweir { 505cdf0e10cSrcweir // now iterate over all elements of the hidlist 506cdf0e10cSrcweir HashSet::const_iterator aEnd = hidlist->end(); 507cdf0e10cSrcweir for (HashSet::const_iterator hidListIter = hidlist->begin(); 508cdf0e10cSrcweir hidListIter != aEnd; ++hidListIter) 509cdf0e10cSrcweir { 510cdf0e10cSrcweir std::string thishid = *hidListIter; 511cdf0e10cSrcweir 512cdf0e10cSrcweir std::string anchorB; 513cdf0e10cSrcweir size_t index = thishid.rfind('#'); 514cdf0e10cSrcweir if (index != std::string::npos) 515cdf0e10cSrcweir { 516cdf0e10cSrcweir anchorB = thishid.substr(1 + index); 517cdf0e10cSrcweir thishid = thishid.substr(0, index); 518cdf0e10cSrcweir } 519*c01398f2SHerbert Dürr addBookmark(pFileDbBase_DBHelp, thishid, fileB, anchorB, jarfileB, titleB); 520cdf0e10cSrcweir } 521cdf0e10cSrcweir } 522cdf0e10cSrcweir 523cdf0e10cSrcweir // now the keywords 524cdf0e10cSrcweir const Hashtable *anchorToLL = streamTable.appl_keywords; 525cdf0e10cSrcweir if (!anchorToLL) 526cdf0e10cSrcweir anchorToLL = streamTable.default_keywords; 527cdf0e10cSrcweir if (anchorToLL && !anchorToLL->empty()) 528cdf0e10cSrcweir { 529cdf0e10cSrcweir std::string fakedHid = URLEncoder::encode(documentPath); 530cdf0e10cSrcweir Hashtable::const_iterator aEnd = anchorToLL->end(); 531cdf0e10cSrcweir for (Hashtable::const_iterator enumer = anchorToLL->begin(); 532cdf0e10cSrcweir enumer != aEnd; ++enumer) 533cdf0e10cSrcweir { 534cdf0e10cSrcweir const std::string &anchor = enumer->first; 535*c01398f2SHerbert Dürr addBookmark(pFileDbBase_DBHelp, documentPath, fileB, 536cdf0e10cSrcweir anchor, jarfileB, titleB); 537cdf0e10cSrcweir std::string totalId = fakedHid + "#" + anchor; 538cdf0e10cSrcweir // std::cerr << hzipFileName << std::endl; 539cdf0e10cSrcweir const LinkedList& ll = enumer->second; 540cdf0e10cSrcweir LinkedList::const_iterator aOtherEnd = ll.end(); 541cdf0e10cSrcweir for (LinkedList::const_iterator llIter = ll.begin(); 542cdf0e10cSrcweir llIter != aOtherEnd; ++llIter) 543cdf0e10cSrcweir { 544cdf0e10cSrcweir helpKeyword.insert(*llIter, totalId); 545cdf0e10cSrcweir } 546cdf0e10cSrcweir } 547cdf0e10cSrcweir 548cdf0e10cSrcweir } 549cdf0e10cSrcweir 550cdf0e10cSrcweir // and last the helptexts 551cdf0e10cSrcweir const Stringtable *helpTextHash = streamTable.appl_helptexts; 552cdf0e10cSrcweir if (!helpTextHash) 553cdf0e10cSrcweir helpTextHash = streamTable.default_helptexts; 554cdf0e10cSrcweir if (helpTextHash && !helpTextHash->empty()) 555cdf0e10cSrcweir { 556cdf0e10cSrcweir Stringtable::const_iterator aEnd = helpTextHash->end(); 557cdf0e10cSrcweir for (Stringtable::const_iterator helpTextIter = helpTextHash->begin(); 558cdf0e10cSrcweir helpTextIter != aEnd; ++helpTextIter) 559cdf0e10cSrcweir { 560cdf0e10cSrcweir std::string helpTextId = helpTextIter->first; 561cdf0e10cSrcweir const std::string& helpTextText = helpTextIter->second; 562cdf0e10cSrcweir 563cdf0e10cSrcweir helpTextId = URLEncoder::encode(helpTextId); 564cdf0e10cSrcweir 565cdf0e10cSrcweir if( pFileHelpText_DBHelp != NULL ) 566cdf0e10cSrcweir writeKeyValue_DBHelp( pFileHelpText_DBHelp, helpTextId, helpTextText ); 567cdf0e10cSrcweir } 568cdf0e10cSrcweir } 569cdf0e10cSrcweir 570cdf0e10cSrcweir //IndexerPreProcessor 571cdf0e10cSrcweir if( !bExtensionMode || bIndexForExtension ) 572cdf0e10cSrcweir { 573cdf0e10cSrcweir // now the indexing 574cdf0e10cSrcweir xmlDocPtr document = streamTable.appl_doc; 575cdf0e10cSrcweir if (!document) 576cdf0e10cSrcweir document = streamTable.default_doc; 577cdf0e10cSrcweir if (document) 578cdf0e10cSrcweir { 579cdf0e10cSrcweir std::string temp = module; 580cdf0e10cSrcweir std::transform (temp.begin(), temp.end(), temp.begin(), tolower); 581cdf0e10cSrcweir m_pIndexerPreProcessor->processDocument(document, URLEncoder::encode(documentPath) ); 582cdf0e10cSrcweir } 583cdf0e10cSrcweir } 584cdf0e10cSrcweir 585cdf0e10cSrcweir } // while loop over hzip files ending 586cdf0e10cSrcweir if( !bExtensionMode ) 587cdf0e10cSrcweir std::cout << std::endl; 588cdf0e10cSrcweir 589cdf0e10cSrcweir } // try 590cdf0e10cSrcweir catch( const HelpProcessingException& ) 591cdf0e10cSrcweir { 592cdf0e10cSrcweir // catch HelpProcessingException to avoid locking data bases 593cdf0e10cSrcweir if( pFileHelpText_DBHelp != NULL ) 594cdf0e10cSrcweir fclose( pFileHelpText_DBHelp ); 595cdf0e10cSrcweir if( pFileDbBase_DBHelp != NULL ) 596cdf0e10cSrcweir fclose( pFileDbBase_DBHelp ); 597cdf0e10cSrcweir throw; 598cdf0e10cSrcweir } 599cdf0e10cSrcweir 600cdf0e10cSrcweir if( pFileHelpText_DBHelp != NULL ) 601cdf0e10cSrcweir fclose( pFileHelpText_DBHelp ); 602cdf0e10cSrcweir if( pFileDbBase_DBHelp != NULL ) 603cdf0e10cSrcweir fclose( pFileDbBase_DBHelp ); 604cdf0e10cSrcweir 605cdf0e10cSrcweir helpKeyword.dump_DBHelp( keyWordFileName_DBHelp); 606cdf0e10cSrcweir 607cdf0e10cSrcweir if( !bExtensionMode ) 608cdf0e10cSrcweir { 609cdf0e10cSrcweir // New index 610cdf0e10cSrcweir Stringtable::iterator aEnd = additionalFiles.end(); 611cdf0e10cSrcweir for (Stringtable::iterator enumer = additionalFiles.begin(); enumer != aEnd; 612cdf0e10cSrcweir ++enumer) 613cdf0e10cSrcweir { 614cdf0e10cSrcweir const std::string &additionalFileName = enumer->second; 615cdf0e10cSrcweir const std::string &additionalFileKey = enumer->first; 616cdf0e10cSrcweir 617cdf0e10cSrcweir fs::path fsAdditionalFileName( additionalFileName, fs::native ); 618cdf0e10cSrcweir std::string aNativeStr = fsAdditionalFileName.native_file_string(); 619cdf0e10cSrcweir const char* pStr = aNativeStr.c_str(); 620cdf0e10cSrcweir std::cerr << pStr; 621cdf0e10cSrcweir 622cdf0e10cSrcweir fs::path fsTargetName( indexDirParentName / additionalFileKey ); 623cdf0e10cSrcweir 624cdf0e10cSrcweir fs::copy( fsAdditionalFileName, fsTargetName ); 625cdf0e10cSrcweir } 626cdf0e10cSrcweir } 627cdf0e10cSrcweir 628cdf0e10cSrcweir } 629cdf0e10cSrcweir 630cdf0e10cSrcweir 631cdf0e10cSrcweir void HelpLinker::main( std::vector<std::string> &args, 632cdf0e10cSrcweir std::string* pExtensionPath, std::string* pDestination, 633cdf0e10cSrcweir const rtl::OUString* pOfficeHelpPath ) 634cdf0e10cSrcweir throw( HelpProcessingException ) 635cdf0e10cSrcweir { 636cdf0e10cSrcweir bExtensionMode = false; 637cdf0e10cSrcweir helpFiles.clear(); 638cdf0e10cSrcweir 639cdf0e10cSrcweir if (args.size() > 0 && args[0][0] == '@') 640cdf0e10cSrcweir { 641cdf0e10cSrcweir std::vector<std::string> stringList; 642cdf0e10cSrcweir std::string strBuf; 643cdf0e10cSrcweir std::ifstream fileReader(args[0].substr(1).c_str()); 644cdf0e10cSrcweir 645cdf0e10cSrcweir while (fileReader) 646cdf0e10cSrcweir { 647cdf0e10cSrcweir std::string token; 648cdf0e10cSrcweir fileReader >> token; 649cdf0e10cSrcweir if (!token.empty()) 650cdf0e10cSrcweir stringList.push_back(token); 651cdf0e10cSrcweir } 652cdf0e10cSrcweir fileReader.close(); 653cdf0e10cSrcweir 654cdf0e10cSrcweir args = stringList; 655cdf0e10cSrcweir } 656cdf0e10cSrcweir 657cdf0e10cSrcweir size_t i = 0; 658cdf0e10cSrcweir bool bSrcOption = false; 659cdf0e10cSrcweir while (i < args.size()) 660cdf0e10cSrcweir { 661cdf0e10cSrcweir if (args[i].compare("-extlangsrc") == 0) 662cdf0e10cSrcweir { 663cdf0e10cSrcweir ++i; 664cdf0e10cSrcweir if (i >= args.size()) 665cdf0e10cSrcweir { 666cdf0e10cSrcweir std::stringstream aStrStream; 667cdf0e10cSrcweir aStrStream << "extension source missing" << std::endl; 668cdf0e10cSrcweir throw HelpProcessingException( HELPPROCESSING_GENERAL_ERROR, aStrStream.str() ); 669cdf0e10cSrcweir } 670cdf0e10cSrcweir extsource = args[i]; 671cdf0e10cSrcweir } 672cdf0e10cSrcweir else if (args[i].compare("-extlangdest") == 0) 673cdf0e10cSrcweir { 674cdf0e10cSrcweir //If this argument is not provided then the location provided in -extsource will 675cdf0e10cSrcweir //also be the destination 676cdf0e10cSrcweir ++i; 677cdf0e10cSrcweir if (i >= args.size()) 678cdf0e10cSrcweir { 679cdf0e10cSrcweir std::stringstream aStrStream; 680cdf0e10cSrcweir aStrStream << "extension destination missing" << std::endl; 681cdf0e10cSrcweir throw HelpProcessingException( HELPPROCESSING_GENERAL_ERROR, aStrStream.str() ); 682cdf0e10cSrcweir } 683cdf0e10cSrcweir extdestination = args[i]; 684cdf0e10cSrcweir } 685cdf0e10cSrcweir else if (args[i].compare("-src") == 0) 686cdf0e10cSrcweir { 687cdf0e10cSrcweir ++i; 688cdf0e10cSrcweir if (i >= args.size()) 689cdf0e10cSrcweir { 690cdf0e10cSrcweir std::stringstream aStrStream; 691cdf0e10cSrcweir aStrStream << "sourceroot missing" << std::endl; 692cdf0e10cSrcweir throw HelpProcessingException( HELPPROCESSING_GENERAL_ERROR, aStrStream.str() ); 693cdf0e10cSrcweir } 694cdf0e10cSrcweir bSrcOption = true; 695cdf0e10cSrcweir sourceRoot = fs::path(args[i], fs::native); 696cdf0e10cSrcweir } 697cdf0e10cSrcweir else if (args[i].compare("-sty") == 0) 698cdf0e10cSrcweir { 699cdf0e10cSrcweir ++i; 700cdf0e10cSrcweir if (i >= args.size()) 701cdf0e10cSrcweir { 702cdf0e10cSrcweir std::stringstream aStrStream; 703cdf0e10cSrcweir aStrStream << "embeddingStylesheet missing" << std::endl; 704cdf0e10cSrcweir throw HelpProcessingException( HELPPROCESSING_GENERAL_ERROR, aStrStream.str() ); 705cdf0e10cSrcweir } 706cdf0e10cSrcweir 707cdf0e10cSrcweir embeddStylesheet = fs::path(args[i], fs::native); 708cdf0e10cSrcweir } 709cdf0e10cSrcweir else if (args[i].compare("-zipdir") == 0) 710cdf0e10cSrcweir { 711cdf0e10cSrcweir ++i; 712cdf0e10cSrcweir if (i >= args.size()) 713cdf0e10cSrcweir { 714cdf0e10cSrcweir std::stringstream aStrStream; 715cdf0e10cSrcweir aStrStream << "idxtemp missing" << std::endl; 716cdf0e10cSrcweir throw HelpProcessingException( HELPPROCESSING_GENERAL_ERROR, aStrStream.str() ); 717cdf0e10cSrcweir } 718cdf0e10cSrcweir 719cdf0e10cSrcweir zipdir = fs::path(args[i], fs::native); 720cdf0e10cSrcweir } 721cdf0e10cSrcweir else if (args[i].compare("-idxcaption") == 0) 722cdf0e10cSrcweir { 723cdf0e10cSrcweir ++i; 724cdf0e10cSrcweir if (i >= args.size()) 725cdf0e10cSrcweir { 726cdf0e10cSrcweir std::stringstream aStrStream; 727cdf0e10cSrcweir aStrStream << "idxcaption stylesheet missing" << std::endl; 728cdf0e10cSrcweir throw HelpProcessingException( HELPPROCESSING_GENERAL_ERROR, aStrStream.str() ); 729cdf0e10cSrcweir } 730cdf0e10cSrcweir 731cdf0e10cSrcweir idxCaptionStylesheet = fs::path(args[i], fs::native); 732cdf0e10cSrcweir } 733cdf0e10cSrcweir else if (args[i].compare("-idxcontent") == 0) 734cdf0e10cSrcweir { 735cdf0e10cSrcweir ++i; 736cdf0e10cSrcweir if (i >= args.size()) 737cdf0e10cSrcweir { 738cdf0e10cSrcweir std::stringstream aStrStream; 739cdf0e10cSrcweir aStrStream << "idxcontent stylesheet missing" << std::endl; 740cdf0e10cSrcweir throw HelpProcessingException( HELPPROCESSING_GENERAL_ERROR, aStrStream.str() ); 741cdf0e10cSrcweir } 742cdf0e10cSrcweir 743cdf0e10cSrcweir idxContentStylesheet = fs::path(args[i], fs::native); 744cdf0e10cSrcweir } 745cdf0e10cSrcweir else if (args[i].compare("-o") == 0) 746cdf0e10cSrcweir { 747cdf0e10cSrcweir ++i; 748cdf0e10cSrcweir if (i >= args.size()) 749cdf0e10cSrcweir { 750cdf0e10cSrcweir std::stringstream aStrStream; 751cdf0e10cSrcweir aStrStream << "outputfilename missing" << std::endl; 752cdf0e10cSrcweir throw HelpProcessingException( HELPPROCESSING_GENERAL_ERROR, aStrStream.str() ); 753cdf0e10cSrcweir } 754cdf0e10cSrcweir 755cdf0e10cSrcweir outputFile = fs::path(args[i], fs::native); 756cdf0e10cSrcweir } 757cdf0e10cSrcweir else if (args[i].compare("-mod") == 0) 758cdf0e10cSrcweir { 759cdf0e10cSrcweir ++i; 760cdf0e10cSrcweir if (i >= args.size()) 761cdf0e10cSrcweir { 762cdf0e10cSrcweir std::stringstream aStrStream; 763cdf0e10cSrcweir aStrStream << "module name missing" << std::endl; 764cdf0e10cSrcweir throw HelpProcessingException( HELPPROCESSING_GENERAL_ERROR, aStrStream.str() ); 765cdf0e10cSrcweir } 766cdf0e10cSrcweir 767cdf0e10cSrcweir module = args[i]; 768cdf0e10cSrcweir } 769cdf0e10cSrcweir else if (args[i].compare("-lang") == 0) 770cdf0e10cSrcweir { 771cdf0e10cSrcweir ++i; 772cdf0e10cSrcweir if (i >= args.size()) 773cdf0e10cSrcweir { 774cdf0e10cSrcweir std::stringstream aStrStream; 775cdf0e10cSrcweir aStrStream << "language name missing" << std::endl; 776cdf0e10cSrcweir throw HelpProcessingException( HELPPROCESSING_GENERAL_ERROR, aStrStream.str() ); 777cdf0e10cSrcweir } 778cdf0e10cSrcweir 779cdf0e10cSrcweir lang = args[i]; 780cdf0e10cSrcweir } 781cdf0e10cSrcweir else if (args[i].compare("-hid") == 0) 782cdf0e10cSrcweir { 783cdf0e10cSrcweir ++i; 784cdf0e10cSrcweir throw HelpProcessingException( HELPPROCESSING_GENERAL_ERROR, "obsolete -hid argument used" ); 785cdf0e10cSrcweir } 786cdf0e10cSrcweir else if (args[i].compare("-add") == 0) 787cdf0e10cSrcweir { 788cdf0e10cSrcweir std::string addFile, addFileUnderPath; 789cdf0e10cSrcweir ++i; 790cdf0e10cSrcweir if (i >= args.size()) 791cdf0e10cSrcweir { 792cdf0e10cSrcweir std::stringstream aStrStream; 793cdf0e10cSrcweir aStrStream << "pathname missing" << std::endl; 794cdf0e10cSrcweir throw HelpProcessingException( HELPPROCESSING_GENERAL_ERROR, aStrStream.str() ); 795cdf0e10cSrcweir } 796cdf0e10cSrcweir 797cdf0e10cSrcweir addFileUnderPath = args[i]; 798cdf0e10cSrcweir ++i; 799cdf0e10cSrcweir if (i >= args.size()) 800cdf0e10cSrcweir { 801cdf0e10cSrcweir std::stringstream aStrStream; 802cdf0e10cSrcweir aStrStream << "pathname missing" << std::endl; 803cdf0e10cSrcweir throw HelpProcessingException( HELPPROCESSING_GENERAL_ERROR, aStrStream.str() ); 804cdf0e10cSrcweir } 805cdf0e10cSrcweir addFile = args[i]; 806cdf0e10cSrcweir if (!addFileUnderPath.empty() && !addFile.empty()) 807cdf0e10cSrcweir additionalFiles[addFileUnderPath] = addFile; 808cdf0e10cSrcweir } 809cdf0e10cSrcweir else 810cdf0e10cSrcweir helpFiles.push_back(args[i]); 811cdf0e10cSrcweir ++i; 812cdf0e10cSrcweir } 813cdf0e10cSrcweir 814cdf0e10cSrcweir //We can be called from the helplinker executable or the extension manager 815cdf0e10cSrcweir //In the latter case extsource is not used. 816cdf0e10cSrcweir if( (pExtensionPath && pExtensionPath->length() > 0 && pOfficeHelpPath) 817cdf0e10cSrcweir || !extsource.empty()) 818cdf0e10cSrcweir { 819cdf0e10cSrcweir bExtensionMode = true; 820cdf0e10cSrcweir if (!extsource.empty()) 821cdf0e10cSrcweir { 822cdf0e10cSrcweir //called from helplinker.exe, pExtensionPath and pOfficeHelpPath 823cdf0e10cSrcweir //should be NULL 824cdf0e10cSrcweir sourceRoot = fs::path(extsource, fs::native); 825cdf0e10cSrcweir extensionPath = sourceRoot.toUTF8(); 826cdf0e10cSrcweir 827cdf0e10cSrcweir if (extdestination.empty()) 828cdf0e10cSrcweir { 829cdf0e10cSrcweir std::stringstream aStrStream; 830cdf0e10cSrcweir aStrStream << "-extlangdest is missing" << std::endl; 831cdf0e10cSrcweir throw HelpProcessingException( HELPPROCESSING_GENERAL_ERROR, aStrStream.str() ); 832cdf0e10cSrcweir } 833cdf0e10cSrcweir else 834cdf0e10cSrcweir { 835cdf0e10cSrcweir //Convert from system path to file URL!!! 836cdf0e10cSrcweir fs::path p(extdestination, fs::native); 837cdf0e10cSrcweir extensionDestination = p.toUTF8(); 838cdf0e10cSrcweir } 839cdf0e10cSrcweir } 840cdf0e10cSrcweir else 841cdf0e10cSrcweir { //called from extension manager 842cdf0e10cSrcweir extensionPath = *pExtensionPath; 843cdf0e10cSrcweir sourceRoot = fs::path(extensionPath); 844cdf0e10cSrcweir extensionDestination = *pDestination; 845cdf0e10cSrcweir } 846cdf0e10cSrcweir //check if -src option was used. This option must not be used 847cdf0e10cSrcweir //when extension help is compiled. 848cdf0e10cSrcweir if (bSrcOption) 849cdf0e10cSrcweir { 850cdf0e10cSrcweir std::stringstream aStrStream; 851cdf0e10cSrcweir aStrStream << "-src must not be used together with -extsource missing" << std::endl; 852cdf0e10cSrcweir throw HelpProcessingException( HELPPROCESSING_GENERAL_ERROR, aStrStream.str() ); 853cdf0e10cSrcweir } 854cdf0e10cSrcweir } 855cdf0e10cSrcweir 856cdf0e10cSrcweir if (!bExtensionMode && zipdir.empty()) 857cdf0e10cSrcweir { 858cdf0e10cSrcweir std::stringstream aStrStream; 859cdf0e10cSrcweir aStrStream << "no index dir given" << std::endl; 860cdf0e10cSrcweir throw HelpProcessingException( HELPPROCESSING_GENERAL_ERROR, aStrStream.str() ); 861cdf0e10cSrcweir } 862cdf0e10cSrcweir 863cdf0e10cSrcweir if (!bExtensionMode && idxCaptionStylesheet.empty() 864cdf0e10cSrcweir || !extsource.empty() && idxCaptionStylesheet.empty()) 865cdf0e10cSrcweir { 866cdf0e10cSrcweir //No extension mode and extension mode using commandline 867cdf0e10cSrcweir //!extsource.empty indicates extension mode using commandline 868cdf0e10cSrcweir // -idxcaption paramter is required 869cdf0e10cSrcweir std::stringstream aStrStream; 870cdf0e10cSrcweir aStrStream << "no index caption stylesheet given" << std::endl; 871cdf0e10cSrcweir throw HelpProcessingException( HELPPROCESSING_GENERAL_ERROR, aStrStream.str() ); 872cdf0e10cSrcweir } 873cdf0e10cSrcweir else if ( bExtensionMode && extsource.empty()) 874cdf0e10cSrcweir { 875cdf0e10cSrcweir //This part is used when compileExtensionHelp is called from the extensions manager. 876cdf0e10cSrcweir //If extension help is compiled using helplinker in the build process 877cdf0e10cSrcweir rtl::OUString aIdxCaptionPathFileURL( *pOfficeHelpPath ); 878cdf0e10cSrcweir aIdxCaptionPathFileURL += rtl::OUString::createFromAscii( "/idxcaption.xsl" ); 879cdf0e10cSrcweir 880cdf0e10cSrcweir rtl::OString aOStr_IdxCaptionPathFileURL( rtl::OUStringToOString 881cdf0e10cSrcweir ( aIdxCaptionPathFileURL, fs::getThreadTextEncoding() ) ); 882cdf0e10cSrcweir std::string aStdStr_IdxCaptionPathFileURL( aOStr_IdxCaptionPathFileURL.getStr() ); 883cdf0e10cSrcweir 884cdf0e10cSrcweir idxCaptionStylesheet = fs::path( aStdStr_IdxCaptionPathFileURL ); 885cdf0e10cSrcweir } 886cdf0e10cSrcweir 887cdf0e10cSrcweir if (!bExtensionMode && idxContentStylesheet.empty() 888cdf0e10cSrcweir || !extsource.empty() && idxContentStylesheet.empty()) 889cdf0e10cSrcweir { 890cdf0e10cSrcweir //No extension mode and extension mode using commandline 891cdf0e10cSrcweir //!extsource.empty indicates extension mode using commandline 892cdf0e10cSrcweir // -idxcontent paramter is required 893cdf0e10cSrcweir std::stringstream aStrStream; 894cdf0e10cSrcweir aStrStream << "no index content stylesheet given" << std::endl; 895cdf0e10cSrcweir throw HelpProcessingException( HELPPROCESSING_GENERAL_ERROR, aStrStream.str() ); 896cdf0e10cSrcweir } 897cdf0e10cSrcweir else if ( bExtensionMode && extsource.empty()) 898cdf0e10cSrcweir { 899cdf0e10cSrcweir //If extension help is compiled using helplinker in the build process 900cdf0e10cSrcweir //then -idxcontent must be supplied 901cdf0e10cSrcweir //This part is used when compileExtensionHelp is called from the extensions manager. 902cdf0e10cSrcweir rtl::OUString aIdxContentPathFileURL( *pOfficeHelpPath ); 903cdf0e10cSrcweir aIdxContentPathFileURL += rtl::OUString::createFromAscii( "/idxcontent.xsl" ); 904cdf0e10cSrcweir 905cdf0e10cSrcweir rtl::OString aOStr_IdxContentPathFileURL( rtl::OUStringToOString 906cdf0e10cSrcweir ( aIdxContentPathFileURL, fs::getThreadTextEncoding() ) ); 907cdf0e10cSrcweir std::string aStdStr_IdxContentPathFileURL( aOStr_IdxContentPathFileURL.getStr() ); 908cdf0e10cSrcweir 909cdf0e10cSrcweir idxContentStylesheet = fs::path( aStdStr_IdxContentPathFileURL ); 910cdf0e10cSrcweir } 911cdf0e10cSrcweir if (!bExtensionMode && embeddStylesheet.empty()) 912cdf0e10cSrcweir { 913cdf0e10cSrcweir std::stringstream aStrStream; 914cdf0e10cSrcweir aStrStream << "no embedding resolving file given" << std::endl; 915cdf0e10cSrcweir throw HelpProcessingException( HELPPROCESSING_GENERAL_ERROR, aStrStream.str() ); 916cdf0e10cSrcweir } 917cdf0e10cSrcweir if (sourceRoot.empty()) 918cdf0e10cSrcweir { 919cdf0e10cSrcweir std::stringstream aStrStream; 920cdf0e10cSrcweir aStrStream << "no sourceroot given" << std::endl; 921cdf0e10cSrcweir throw HelpProcessingException( HELPPROCESSING_GENERAL_ERROR, aStrStream.str() ); 922cdf0e10cSrcweir } 923cdf0e10cSrcweir if (!bExtensionMode && outputFile.empty()) 924cdf0e10cSrcweir { 925cdf0e10cSrcweir std::stringstream aStrStream; 926cdf0e10cSrcweir aStrStream << "no output file given" << std::endl; 927cdf0e10cSrcweir throw HelpProcessingException( HELPPROCESSING_GENERAL_ERROR, aStrStream.str() ); 928cdf0e10cSrcweir } 929cdf0e10cSrcweir if (module.empty()) 930cdf0e10cSrcweir { 931cdf0e10cSrcweir std::stringstream aStrStream; 932cdf0e10cSrcweir aStrStream << "module missing" << std::endl; 933cdf0e10cSrcweir throw HelpProcessingException( HELPPROCESSING_GENERAL_ERROR, aStrStream.str() ); 934cdf0e10cSrcweir } 935cdf0e10cSrcweir if (!bExtensionMode && lang.empty()) 936cdf0e10cSrcweir { 937cdf0e10cSrcweir std::stringstream aStrStream; 938cdf0e10cSrcweir aStrStream << "language missing" << std::endl; 939cdf0e10cSrcweir throw HelpProcessingException( HELPPROCESSING_GENERAL_ERROR, aStrStream.str() ); 940cdf0e10cSrcweir } 941cdf0e10cSrcweir link(); 942cdf0e10cSrcweir } 943cdf0e10cSrcweir 944cdf0e10cSrcweir int main(int argc, char**argv) 945cdf0e10cSrcweir { 946cdf0e10cSrcweir sal_uInt32 starttime = osl_getGlobalTimer(); 947cdf0e10cSrcweir std::vector<std::string> args; 948cdf0e10cSrcweir for (int i = 1; i < argc; ++i) 949cdf0e10cSrcweir args.push_back(std::string(argv[i])); 950cdf0e10cSrcweir try 951cdf0e10cSrcweir { 952cdf0e10cSrcweir HelpLinker* pHelpLinker = new HelpLinker(); 953cdf0e10cSrcweir pHelpLinker->main( args ); 954cdf0e10cSrcweir delete pHelpLinker; 955cdf0e10cSrcweir } 956cdf0e10cSrcweir catch( const HelpProcessingException& e ) 957cdf0e10cSrcweir { 958cdf0e10cSrcweir std::cerr << e.m_aErrorMsg; 959cdf0e10cSrcweir exit(1); 960cdf0e10cSrcweir } 961cdf0e10cSrcweir sal_uInt32 endtime = osl_getGlobalTimer(); 962cdf0e10cSrcweir #ifndef OS2 // YD @TODO@ crashes libc runtime :-( 963cdf0e10cSrcweir std::cout << "time taken was " << (endtime-starttime)/1000.0 << " seconds" << std::endl; 964cdf0e10cSrcweir #endif 965cdf0e10cSrcweir return 0; 966cdf0e10cSrcweir } 967cdf0e10cSrcweir 968cdf0e10cSrcweir // Variable to set an exception in "C" StructuredXMLErrorFunction 969cdf0e10cSrcweir static const HelpProcessingException* GpXMLParsingException = NULL; 970cdf0e10cSrcweir 971cdf0e10cSrcweir extern "C" void StructuredXMLErrorFunction(void *userData, xmlErrorPtr error) 972cdf0e10cSrcweir { 973cdf0e10cSrcweir (void)userData; 974cdf0e10cSrcweir (void)error; 975cdf0e10cSrcweir 976cdf0e10cSrcweir std::string aErrorMsg = error->message; 977cdf0e10cSrcweir std::string aXMLParsingFile; 978cdf0e10cSrcweir if( error->file != NULL ) 979cdf0e10cSrcweir aXMLParsingFile = error->file; 980cdf0e10cSrcweir int nXMLParsingLine = error->line; 981cdf0e10cSrcweir HelpProcessingException* pException = new HelpProcessingException( aErrorMsg, aXMLParsingFile, nXMLParsingLine ); 982cdf0e10cSrcweir GpXMLParsingException = pException; 983cdf0e10cSrcweir 984cdf0e10cSrcweir // Reset error handler 985cdf0e10cSrcweir xmlSetStructuredErrorFunc( NULL, NULL ); 986cdf0e10cSrcweir } 987cdf0e10cSrcweir 988cdf0e10cSrcweir HelpProcessingErrorInfo& HelpProcessingErrorInfo::operator=( const struct HelpProcessingException& e ) 989cdf0e10cSrcweir { 990cdf0e10cSrcweir m_eErrorClass = e.m_eErrorClass; 991cdf0e10cSrcweir rtl::OString tmpErrorMsg( e.m_aErrorMsg.c_str() ); 992cdf0e10cSrcweir m_aErrorMsg = rtl::OStringToOUString( tmpErrorMsg, fs::getThreadTextEncoding() ); 993cdf0e10cSrcweir rtl::OString tmpXMLParsingFile( e.m_aXMLParsingFile.c_str() ); 994cdf0e10cSrcweir m_aXMLParsingFile = rtl::OStringToOUString( tmpXMLParsingFile, fs::getThreadTextEncoding() ); 995cdf0e10cSrcweir m_nXMLParsingLine = e.m_nXMLParsingLine; 996cdf0e10cSrcweir return *this; 997cdf0e10cSrcweir } 998cdf0e10cSrcweir 999cdf0e10cSrcweir 1000cdf0e10cSrcweir // Returns true in case of success, false in case of error 1001cdf0e10cSrcweir HELPLINKER_DLLPUBLIC bool compileExtensionHelp 1002cdf0e10cSrcweir ( 1003cdf0e10cSrcweir const rtl::OUString& aOfficeHelpPath, 1004cdf0e10cSrcweir const rtl::OUString& aExtensionName, 1005cdf0e10cSrcweir const rtl::OUString& aExtensionLanguageRoot, 1006cdf0e10cSrcweir sal_Int32 nXhpFileCount, const rtl::OUString* pXhpFiles, 1007cdf0e10cSrcweir const rtl::OUString& aDestination, 1008cdf0e10cSrcweir HelpProcessingErrorInfo& o_rHelpProcessingErrorInfo 1009cdf0e10cSrcweir ) 1010cdf0e10cSrcweir { 1011cdf0e10cSrcweir bool bSuccess = true; 1012cdf0e10cSrcweir 1013cdf0e10cSrcweir std::vector<std::string> args; 1014cdf0e10cSrcweir args.reserve(nXhpFileCount + 2); 1015cdf0e10cSrcweir args.push_back(std::string("-mod")); 1016cdf0e10cSrcweir rtl::OString aOExtensionName = rtl::OUStringToOString( aExtensionName, fs::getThreadTextEncoding() ); 1017cdf0e10cSrcweir args.push_back(std::string(aOExtensionName.getStr())); 1018cdf0e10cSrcweir 1019cdf0e10cSrcweir for( sal_Int32 iXhp = 0 ; iXhp < nXhpFileCount ; ++iXhp ) 1020cdf0e10cSrcweir { 1021cdf0e10cSrcweir rtl::OUString aXhpFile = pXhpFiles[iXhp]; 1022cdf0e10cSrcweir 1023cdf0e10cSrcweir rtl::OString aOXhpFile = rtl::OUStringToOString( aXhpFile, fs::getThreadTextEncoding() ); 1024cdf0e10cSrcweir args.push_back(std::string(aOXhpFile.getStr())); 1025cdf0e10cSrcweir } 1026cdf0e10cSrcweir 1027cdf0e10cSrcweir rtl::OString aOExtensionLanguageRoot = rtl::OUStringToOString( aExtensionLanguageRoot, fs::getThreadTextEncoding() ); 1028cdf0e10cSrcweir const char* pExtensionPath = aOExtensionLanguageRoot.getStr(); 1029cdf0e10cSrcweir std::string aStdStrExtensionPath = pExtensionPath; 1030cdf0e10cSrcweir rtl::OString aODestination = rtl::OUStringToOString(aDestination, fs::getThreadTextEncoding()); 1031cdf0e10cSrcweir const char* pDestination = aODestination.getStr(); 1032cdf0e10cSrcweir std::string aStdStrDestination = pDestination; 1033cdf0e10cSrcweir 1034cdf0e10cSrcweir // Set error handler 1035cdf0e10cSrcweir xmlSetStructuredErrorFunc( NULL, (xmlStructuredErrorFunc)StructuredXMLErrorFunction ); 1036cdf0e10cSrcweir try 1037cdf0e10cSrcweir { 1038cdf0e10cSrcweir HelpLinker* pHelpLinker = new HelpLinker(); 1039cdf0e10cSrcweir pHelpLinker->main( args, &aStdStrExtensionPath, &aStdStrDestination, &aOfficeHelpPath ); 1040cdf0e10cSrcweir delete pHelpLinker; 1041cdf0e10cSrcweir } 1042cdf0e10cSrcweir catch( const HelpProcessingException& e ) 1043cdf0e10cSrcweir { 1044cdf0e10cSrcweir if( GpXMLParsingException != NULL ) 1045cdf0e10cSrcweir { 1046cdf0e10cSrcweir o_rHelpProcessingErrorInfo = *GpXMLParsingException; 1047cdf0e10cSrcweir delete GpXMLParsingException; 1048cdf0e10cSrcweir GpXMLParsingException = NULL; 1049cdf0e10cSrcweir } 1050cdf0e10cSrcweir else 1051cdf0e10cSrcweir { 1052cdf0e10cSrcweir o_rHelpProcessingErrorInfo = e; 1053cdf0e10cSrcweir } 1054cdf0e10cSrcweir bSuccess = false; 1055cdf0e10cSrcweir } 1056cdf0e10cSrcweir // Reset error handler 1057cdf0e10cSrcweir xmlSetStructuredErrorFunc( NULL, NULL ); 1058cdf0e10cSrcweir 1059cdf0e10cSrcweir // i83624: Tree files 1060cdf0e10cSrcweir ::rtl::OUString aTreeFileURL = aExtensionLanguageRoot; 1061cdf0e10cSrcweir aTreeFileURL += rtl::OUString::createFromAscii( "/help.tree" ); 1062cdf0e10cSrcweir osl::DirectoryItem aTreeFileItem; 1063cdf0e10cSrcweir osl::FileBase::RC rcGet = osl::DirectoryItem::get( aTreeFileURL, aTreeFileItem ); 1064cdf0e10cSrcweir osl::FileStatus aFileStatus( FileStatusMask_FileSize ); 1065cdf0e10cSrcweir if( rcGet == osl::FileBase::E_None && 1066cdf0e10cSrcweir aTreeFileItem.getFileStatus( aFileStatus ) == osl::FileBase::E_None && 1067cdf0e10cSrcweir aFileStatus.isValid( FileStatusMask_FileSize ) ) 1068cdf0e10cSrcweir { 1069cdf0e10cSrcweir sal_uInt64 ret, len = aFileStatus.getFileSize(); 1070cdf0e10cSrcweir char* s = new char[ int(len) ]; // the buffer to hold the installed files 1071cdf0e10cSrcweir osl::File aFile( aTreeFileURL ); 1072cdf0e10cSrcweir aFile.open( OpenFlag_Read ); 1073cdf0e10cSrcweir aFile.read( s, len, ret ); 1074cdf0e10cSrcweir aFile.close(); 1075cdf0e10cSrcweir 1076cdf0e10cSrcweir XML_Parser parser = XML_ParserCreate( 0 ); 1077cdf0e10cSrcweir int parsed = XML_Parse( parser, s, int( len ), true ); 1078cdf0e10cSrcweir 1079cdf0e10cSrcweir if( parsed == 0 ) 1080cdf0e10cSrcweir { 1081cdf0e10cSrcweir XML_Error nError = XML_GetErrorCode( parser ); 1082cdf0e10cSrcweir o_rHelpProcessingErrorInfo.m_eErrorClass = HELPPROCESSING_XMLPARSING_ERROR; 1083cdf0e10cSrcweir o_rHelpProcessingErrorInfo.m_aErrorMsg = rtl::OUString::createFromAscii( XML_ErrorString( nError ) );; 1084cdf0e10cSrcweir o_rHelpProcessingErrorInfo.m_aXMLParsingFile = aTreeFileURL; 1085cdf0e10cSrcweir // CRAHSES!!! o_rHelpProcessingErrorInfo.m_nXMLParsingLine = XML_GetCurrentLineNumber( parser ); 1086cdf0e10cSrcweir bSuccess = false; 1087cdf0e10cSrcweir } 1088cdf0e10cSrcweir 1089cdf0e10cSrcweir XML_ParserFree( parser ); 1090cdf0e10cSrcweir delete[] s; 1091cdf0e10cSrcweir } 1092cdf0e10cSrcweir 1093cdf0e10cSrcweir return bSuccess; 1094cdf0e10cSrcweir } 1095cdf0e10cSrcweir 1096