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