Bug Summary

File:home/maarten/src/libreoffice/core/helpcompiler/source/HelpLinker.cxx
Warning:line 748, column 43
Forming reference to null pointer

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-unknown-linux-gnu -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name HelpLinker.cxx -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -mframe-pointer=all -fmath-errno -fno-rounding-math -mconstructor-aliases -munwind-tables -target-cpu x86-64 -fno-split-dwarf-inlining -debugger-tuning=gdb -resource-dir /usr/lib64/clang/11.0.0 -isystem /usr/include/libxml2 -isystem /usr/include/libxml2 -D BOOST_ERROR_CODE_HEADER_ONLY -D BOOST_SYSTEM_NO_DEPRECATED -D CPPU_ENV=gcc3 -D LINUX -D OSL_DEBUG_LEVEL=1 -D SAL_LOG_INFO -D SAL_LOG_WARN -D UNIX -D UNX -D X86_64 -D _PTHREADS -D _REENTRANT -D L10N_DLLIMPLEMENTATION -D HELPLINKER_DLLIMPLEMENTATION -D SYSTEM_LIBXML -D EXCEPTIONS_ON -D LIBO_INTERNAL_ONLY -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/clucene/src/core -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/clucene/src/shared -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/clucene/src/contribs-lib -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/expat/lib -I /home/maarten/src/libreoffice/core/external/boost/include -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/boost -I /home/maarten/src/libreoffice/core/helpcompiler/inc -I /home/maarten/src/libreoffice/core/include -I /usr/lib/jvm/java-11-openjdk-11.0.9.10-0.0.ea.fc33.x86_64/include -I /usr/lib/jvm/java-11-openjdk-11.0.9.10-0.0.ea.fc33.x86_64/include/linux -I /home/maarten/src/libreoffice/core/config_host -I /home/maarten/src/libreoffice/core/workdir/UnoApiHeadersTarget/udkapi/normal -I /home/maarten/src/libreoffice/core/workdir/UnoApiHeadersTarget/offapi/normal -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/10/../../../../include/c++/10 -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/10/../../../../include/c++/10/x86_64-redhat-linux -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/10/../../../../include/c++/10/backward -internal-isystem /usr/local/include -internal-isystem /usr/lib64/clang/11.0.0/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O0 -Wno-missing-braces -std=c++17 -fdeprecated-macro -fdebug-compilation-dir /home/maarten/src/libreoffice/core -ferror-limit 19 -fvisibility hidden -fvisibility-inlines-hidden -stack-protector 2 -fgnuc-version=4.2.1 -fcxx-exceptions -fexceptions -debug-info-kind=constructor -analyzer-output=html -faddrsig -o /home/maarten/tmp/wis/scan-build-libreoffice/output/report/2020-10-07-141433-9725-1 -x c++ /home/maarten/src/libreoffice/core/helpcompiler/source/HelpLinker.cxx
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 */
19
20#include <HelpCompiler.hxx>
21#include <HelpLinker.hxx>
22
23#include <algorithm>
24#include <fstream>
25
26#include <string.h>
27
28#include <libxslt/transform.h>
29
30#include <sal/types.h>
31#include <o3tl/char16_t2wchar_t.hxx>
32#include <sal/log.hxx>
33
34#include <expat.h>
35#include <memory>
36
37namespace {
38FILE* fopen_impl(const fs::path& rPath, const char* szMode)
39{
40#ifdef _WIN32 //We need _wfopen to support long file paths on Windows XP
41 return _wfopen(rPath.native_file_string_w().c_str(), o3tl::toW(OUString::createFromAscii(szMode).getStr()));
42#else
43 return fopen(rPath.native_file_string().c_str(), szMode);
44#endif
45}
46}
47
48IndexerPreProcessor::IndexerPreProcessor
49 ( const fs::path& fsIndexBaseDir,
50 const fs::path& idxCaptionStylesheet, const fs::path& idxContentStylesheet )
51{
52 m_fsCaptionFilesDirName = fsIndexBaseDir / "caption";
53 fs::create_directory( m_fsCaptionFilesDirName );
54
55 m_fsContentFilesDirName = fsIndexBaseDir / "content";
56 fs::create_directory( m_fsContentFilesDirName );
57
58 m_xsltStylesheetPtrCaption = xsltParseStylesheetFile
59 (reinterpret_cast<const xmlChar *>(idxCaptionStylesheet.native_file_string().c_str()));
60 m_xsltStylesheetPtrContent = xsltParseStylesheetFile
61 (reinterpret_cast<const xmlChar *>(idxContentStylesheet.native_file_string().c_str()));
62}
63
64IndexerPreProcessor::~IndexerPreProcessor()
65{
66 if( m_xsltStylesheetPtrCaption )
67 xsltFreeStylesheet( m_xsltStylesheetPtrCaption );
68 if( m_xsltStylesheetPtrContent )
69 xsltFreeStylesheet( m_xsltStylesheetPtrContent );
70}
71
72static std::string getEncodedPath( const std::string& Path )
73{
74 OString aOStr_Path( Path.c_str() );
75 OUString aOUStr_Path( OStringToOUString
76 ( aOStr_Path, osl_getThreadTextEncoding() ) );
77 OUString aPathURL;
78 osl::File::getFileURLFromSystemPath( aOUStr_Path, aPathURL );
79 OString aOStr_PathURL( OUStringToOString
80 ( aPathURL, osl_getThreadTextEncoding() ) );
81 std::string aStdStr_PathURL( aOStr_PathURL.getStr() );
82 return aStdStr_PathURL;
83}
84
85void IndexerPreProcessor::processDocument
86 ( xmlDocPtr doc, const std::string &EncodedDocPath )
87{
88 std::string aStdStr_EncodedDocPathURL = getEncodedPath( EncodedDocPath );
89
90 if( m_xsltStylesheetPtrCaption )
91 {
92 xmlDocPtr resCaption = xsltApplyStylesheet( m_xsltStylesheetPtrCaption, doc, nullptr );
93 xmlNodePtr pResNodeCaption = resCaption->xmlChildrenNodechildren;
94 if( pResNodeCaption )
95 {
96 fs::path fsCaptionPureTextFile_docURL = m_fsCaptionFilesDirName / aStdStr_EncodedDocPathURL;
97 FILE* pFile_docURL = fopen_impl( fsCaptionPureTextFile_docURL, "w" );
98 if( pFile_docURL )
99 {
100 fprintf( pFile_docURL, "%s\n", pResNodeCaption->content );
101 fclose( pFile_docURL );
102 }
103 }
104 xmlFreeDoc(resCaption);
105 }
106
107 if( !m_xsltStylesheetPtrContent )
108 return;
109
110 xmlDocPtr resContent = xsltApplyStylesheet( m_xsltStylesheetPtrContent, doc, nullptr );
111 xmlNodePtr pResNodeContent = resContent->xmlChildrenNodechildren;
112 if( pResNodeContent )
113 {
114 fs::path fsContentPureTextFile_docURL = m_fsContentFilesDirName / aStdStr_EncodedDocPathURL;
115 FILE* pFile_docURL = fopen_impl( fsContentPureTextFile_docURL, "w" );
116 if( pFile_docURL )
117 {
118 fprintf( pFile_docURL, "%s\n", pResNodeContent->content );
119 fclose( pFile_docURL );
120 }
121 }
122 xmlFreeDoc(resContent);
123}
124
125namespace {
126
127struct Data
128{
129 std::vector<std::string> _idList;
130
131 void append(const std::string &id)
132 {
133 _idList.push_back(id);
134 }
135
136 std::string getString() const
137 {
138 std::string ret;
139 for (auto const& elem : _idList)
140 ret += elem + ";";
141 return ret;
142 }
143};
144
145}
146
147static void writeKeyValue_DBHelp( FILE* pFile, const std::string& aKeyStr, const std::string& aValueStr )
148{
149 if( pFile == nullptr )
150 return;
151 char const cLF = 10;
152 unsigned int nKeyLen = aKeyStr.length();
153 unsigned int nValueLen = aValueStr.length();
154 fprintf( pFile, "%x ", nKeyLen );
155 if( nKeyLen > 0 )
156 {
157 if (fwrite( aKeyStr.c_str(), 1, nKeyLen, pFile ) != nKeyLen)
158 fprintf(stderrstderr, "fwrite to db failed\n");
159 }
160 if (fprintf( pFile, " %x ", nValueLen ) < 0)
161 fprintf(stderrstderr, "fwrite to db failed\n");
162 if( nValueLen > 0 )
163 {
164 if (fwrite( aValueStr.c_str(), 1, nValueLen, pFile ) != nValueLen)
165 fprintf(stderrstderr, "fwrite to db failed\n");
166 }
167 if (fprintf( pFile, "%c", cLF ) < 0)
168 fprintf(stderrstderr, "fwrite to db failed\n");
169}
170
171namespace {
172
173class HelpKeyword
174{
175private:
176 typedef std::unordered_map<std::string, Data> DataHashtable;
177 DataHashtable _hash;
178
179public:
180 void insert(const std::string &key, const std::string &id)
181 {
182 Data &data = _hash[key];
183 data.append(id);
184 }
185
186 void dump_DBHelp( const fs::path& rFileName )
187 {
188 FILE* pFile = fopen_impl( rFileName, "wb" );
189 if( pFile == nullptr )
190 return;
191
192 for (auto const& elem : _hash)
193 writeKeyValue_DBHelp( pFile, elem.first, elem.second.getString() );
194
195 fclose( pFile );
196 }
197};
198
199}
200
201namespace URLEncoder
202{
203 static std::string encode(const std::string &rIn)
204 {
205 const char * const good = "!$&'()*+,-.=@_";
206 static const char hex[17] = "0123456789ABCDEF";
207
208 std::string result;
209 for (char c : rIn)
210 {
211 if (rtl::isAsciiAlphanumeric (static_cast<unsigned char>(c))
212 || strchr (good, c))
213 {
214 result += c;
215 } else {
216 result += '%';
217 result += hex[static_cast<unsigned char>(c) >> 4];
218 result += hex[c & 0xf];
219 }
220 }
221 return result;
222 }
223}
224
225void HelpLinker::addBookmark( FILE* pFile_DBHelp, std::string thishid,
226 const std::string& fileB, const std::string& anchorB,
227 const std::string& jarfileB, const std::string& titleB)
228{
229 HCDBG(std::cerr << "HelpLinker::addBookmark " << thishid << " " <<do { } while(false)
230 fileB << " " << anchorB << " " << jarfileB << " " << titleB << std::endl)do { } while(false);
231
232 thishid = URLEncoder::encode(thishid);
233
234 int fileLen = fileB.length();
235 if (!anchorB.empty())
236 fileLen += (1 + anchorB.length());
237 int dataLen = 1 + fileLen + 1 + jarfileB.length() + 1 + titleB.length();
238
239 std::vector<unsigned char> dataB(dataLen);
240 size_t i = 0;
241 dataB[i++] = static_cast<unsigned char>(fileLen);
242 for (char j : fileB)
243 dataB[i++] = static_cast<unsigned char>(j);
244 if (!anchorB.empty())
245 {
246 dataB[i++] = '#';
247 for (char j : anchorB)
248 dataB[i++] = j;
249 }
250 dataB[i++] = static_cast<unsigned char>(jarfileB.length());
251 for (char j : jarfileB)
252 dataB[i++] = j;
253
254 dataB[i++] = static_cast<unsigned char>(titleB.length());
255 for (char j : titleB)
256 dataB[i++] = j;
257
258 if( pFile_DBHelp != nullptr )
259 {
260 std::string aValueStr( dataB.begin(), dataB.end() );
261 writeKeyValue_DBHelp( pFile_DBHelp, thishid, aValueStr );
262 }
263}
264
265void HelpLinker::initIndexerPreProcessor()
266{
267 m_pIndexerPreProcessor.reset( new IndexerPreProcessor( indexDirParentName,
268 idxCaptionStylesheet, idxContentStylesheet ) );
269}
270
271void HelpLinker::link()
272{
273
274 if( bExtensionMode )
275 {
276 indexDirParentName = extensionDestination;
277 }
278 else
279 {
280 indexDirParentName = zipdir;
281 fs::create_directory(indexDirParentName);
282 }
283
284 std::string mod = module;
285 std::transform (mod.begin(), mod.end(), mod.begin(), tocharlower);
286
287 // do the work here
288 // continue with introduction of the overall process thing into the
289 // here all hzip files will be worked on
290 bool bUse_ = true;
291 if( !bExtensionMode )
292 bUse_ = false;
293
294 fs::path helpTextFileName_DBHelp(indexDirParentName / (mod + (bUse_ ? ".ht_" : ".ht")));
295 FILE* pFileHelpText_DBHelp = fopen_impl( helpTextFileName_DBHelp, "wb" );
296
297 fs::path dbBaseFileName_DBHelp(indexDirParentName / (mod + (bUse_ ? ".db_" : ".db")));
298 FILE* pFileDbBase_DBHelp = fopen_impl( dbBaseFileName_DBHelp, "wb" );
299
300 fs::path keyWordFileName_DBHelp(indexDirParentName / (mod + (bUse_ ? ".key_" : ".key")));
301
302 HelpKeyword helpKeyword;
303
304 // catch HelpProcessingException to avoid locking data bases
305 try
306 {
307 bool bIndexForExtension = true;
308 // lastly, initialize the indexBuilder
309 if ( (!bExtensionMode || bIndexForExtension) && !helpFiles.empty())
310 initIndexerPreProcessor();
311
312 // here we start our loop over the hzip files.
313 for (auto const& helpFile : helpFiles)
314 {
315 // process one file
316 // streamTable contains the streams in the hzip file
317 StreamTable streamTable;
318 const std::string &xhpFileName = helpFile;
319
320 if (!bExtensionMode && xhpFileName.rfind(".xhp") != xhpFileName.length()-4)
321 {
322 // only work on .xhp - files
323 SAL_WARN("helpcompiler",do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_WARN
, "helpcompiler")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break
; case SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult
( ::sal::detail::StreamStart() << "ERROR: input list entry '"
<< xhpFileName << "' has the wrong extension (only files with extension .xhp are accepted)"
) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("helpcompiler"
), ("/home/maarten/src/libreoffice/core/helpcompiler/source/HelpLinker.cxx"
":" "326" ": "), ::sal::detail::unwrapStream( ::sal::detail::
StreamStart() << "ERROR: input list entry '" << xhpFileName
<< "' has the wrong extension (only files with extension .xhp are accepted)"
), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "ERROR: input list entry '" << xhpFileName <<
"' has the wrong extension (only files with extension .xhp are accepted)"
; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("helpcompiler"
), ("/home/maarten/src/libreoffice/core/helpcompiler/source/HelpLinker.cxx"
":" "326" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "ERROR: input list entry '" << xhpFileName <<
"' has the wrong extension (only files with extension .xhp are accepted)"
) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("helpcompiler"
), ("/home/maarten/src/libreoffice/core/helpcompiler/source/HelpLinker.cxx"
":" "326" ": "), ::sal::detail::unwrapStream( ::sal::detail::
StreamStart() << "ERROR: input list entry '" << xhpFileName
<< "' has the wrong extension (only files with extension .xhp are accepted)"
), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "ERROR: input list entry '" << xhpFileName <<
"' has the wrong extension (only files with extension .xhp are accepted)"
; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("helpcompiler"
), ("/home/maarten/src/libreoffice/core/helpcompiler/source/HelpLinker.cxx"
":" "326" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
324 "ERROR: input list entry '"do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_WARN
, "helpcompiler")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break
; case SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult
( ::sal::detail::StreamStart() << "ERROR: input list entry '"
<< xhpFileName << "' has the wrong extension (only files with extension .xhp are accepted)"
) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("helpcompiler"
), ("/home/maarten/src/libreoffice/core/helpcompiler/source/HelpLinker.cxx"
":" "326" ": "), ::sal::detail::unwrapStream( ::sal::detail::
StreamStart() << "ERROR: input list entry '" << xhpFileName
<< "' has the wrong extension (only files with extension .xhp are accepted)"
), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "ERROR: input list entry '" << xhpFileName <<
"' has the wrong extension (only files with extension .xhp are accepted)"
; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("helpcompiler"
), ("/home/maarten/src/libreoffice/core/helpcompiler/source/HelpLinker.cxx"
":" "326" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "ERROR: input list entry '" << xhpFileName <<
"' has the wrong extension (only files with extension .xhp are accepted)"
) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("helpcompiler"
), ("/home/maarten/src/libreoffice/core/helpcompiler/source/HelpLinker.cxx"
":" "326" ": "), ::sal::detail::unwrapStream( ::sal::detail::
StreamStart() << "ERROR: input list entry '" << xhpFileName
<< "' has the wrong extension (only files with extension .xhp are accepted)"
), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "ERROR: input list entry '" << xhpFileName <<
"' has the wrong extension (only files with extension .xhp are accepted)"
; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("helpcompiler"
), ("/home/maarten/src/libreoffice/core/helpcompiler/source/HelpLinker.cxx"
":" "326" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
325 << xhpFileNamedo { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_WARN
, "helpcompiler")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break
; case SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult
( ::sal::detail::StreamStart() << "ERROR: input list entry '"
<< xhpFileName << "' has the wrong extension (only files with extension .xhp are accepted)"
) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("helpcompiler"
), ("/home/maarten/src/libreoffice/core/helpcompiler/source/HelpLinker.cxx"
":" "326" ": "), ::sal::detail::unwrapStream( ::sal::detail::
StreamStart() << "ERROR: input list entry '" << xhpFileName
<< "' has the wrong extension (only files with extension .xhp are accepted)"
), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "ERROR: input list entry '" << xhpFileName <<
"' has the wrong extension (only files with extension .xhp are accepted)"
; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("helpcompiler"
), ("/home/maarten/src/libreoffice/core/helpcompiler/source/HelpLinker.cxx"
":" "326" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "ERROR: input list entry '" << xhpFileName <<
"' has the wrong extension (only files with extension .xhp are accepted)"
) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("helpcompiler"
), ("/home/maarten/src/libreoffice/core/helpcompiler/source/HelpLinker.cxx"
":" "326" ": "), ::sal::detail::unwrapStream( ::sal::detail::
StreamStart() << "ERROR: input list entry '" << xhpFileName
<< "' has the wrong extension (only files with extension .xhp are accepted)"
), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "ERROR: input list entry '" << xhpFileName <<
"' has the wrong extension (only files with extension .xhp are accepted)"
; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("helpcompiler"
), ("/home/maarten/src/libreoffice/core/helpcompiler/source/HelpLinker.cxx"
":" "326" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
326 << "' has the wrong extension (only files with extension .xhp are accepted)")do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_WARN
, "helpcompiler")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break
; case SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult
( ::sal::detail::StreamStart() << "ERROR: input list entry '"
<< xhpFileName << "' has the wrong extension (only files with extension .xhp are accepted)"
) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("helpcompiler"
), ("/home/maarten/src/libreoffice/core/helpcompiler/source/HelpLinker.cxx"
":" "326" ": "), ::sal::detail::unwrapStream( ::sal::detail::
StreamStart() << "ERROR: input list entry '" << xhpFileName
<< "' has the wrong extension (only files with extension .xhp are accepted)"
), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "ERROR: input list entry '" << xhpFileName <<
"' has the wrong extension (only files with extension .xhp are accepted)"
; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("helpcompiler"
), ("/home/maarten/src/libreoffice/core/helpcompiler/source/HelpLinker.cxx"
":" "326" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "ERROR: input list entry '" << xhpFileName <<
"' has the wrong extension (only files with extension .xhp are accepted)"
) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("helpcompiler"
), ("/home/maarten/src/libreoffice/core/helpcompiler/source/HelpLinker.cxx"
":" "326" ": "), ::sal::detail::unwrapStream( ::sal::detail::
StreamStart() << "ERROR: input list entry '" << xhpFileName
<< "' has the wrong extension (only files with extension .xhp are accepted)"
), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "ERROR: input list entry '" << xhpFileName <<
"' has the wrong extension (only files with extension .xhp are accepted)"
; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("helpcompiler"
), ("/home/maarten/src/libreoffice/core/helpcompiler/source/HelpLinker.cxx"
":" "326" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
327
328 continue;
329 }
330
331 fs::path langsourceRoot(sourceRoot);
332 fs::path xhpFile;
333
334 if( bExtensionMode )
335 {
336 // langsourceRoot == sourceRoot for extensions
337 std::string xhpFileNameComplete( extensionPath );
338 xhpFileNameComplete.append( '/' + xhpFileName );
339 xhpFile = fs::path( xhpFileNameComplete );
340 }
341 else
342 {
343 langsourceRoot.append( "/" );
344 if ( m_bUseLangRoot )
345 langsourceRoot.append( lang + '/' );
346 xhpFile = fs::path(xhpFileName, fs::native);
347 }
348
349 HelpCompiler hc( streamTable, xhpFile, langsourceRoot, zipdir,
350 compactStylesheet, embeddStylesheet, module, lang, bExtensionMode );
351
352 HCDBG(std::cerr << "before compile of " << xhpFileName << std::endl)do { } while(false);
353 hc.compile();
354 HCDBG(std::cerr << "after compile of " << xhpFileName << std::endl)do { } while(false);
355
356 if (!m_bCreateIndex)
357 continue;
358
359 std::string documentPath = streamTable.document_path;
360 if (documentPath.compare(0, 1, "/") == 0)
361 documentPath = documentPath.substr(1);
362
363 std::string documentJarfile = streamTable.document_module + ".jar";
364
365 std::string documentTitle = streamTable.document_title;
366 if (documentTitle.empty())
367 documentTitle = "<notitle>";
368
369 const std::string& fileB = documentPath;
370 const std::string& jarfileB = documentJarfile;
371 std::string& titleB = documentTitle;
372
373 // add once this as its own id.
374 addBookmark( pFileDbBase_DBHelp, documentPath, fileB, std::string(), jarfileB, titleB);
375
376 const std::vector<std::string> *hidlist = streamTable.appl_hidlist.get();
377 if (hidlist)
378 {
379 // now iterate over all elements of the hidlist
380 for (auto & elem : *hidlist)
381 {
382 std::string thishid = elem;
383
384 std::string anchorB;
385 size_t index = thishid.rfind('#');
386 if (index != std::string::npos)
387 {
388 anchorB = thishid.substr(1 + index);
389 thishid = thishid.substr(0, index);
390 }
391 addBookmark( pFileDbBase_DBHelp, thishid, fileB, anchorB, jarfileB, titleB);
392 }
393 }
394
395 // now the keywords
396 const Hashtable *anchorToLL = streamTable.appl_keywords.get();
397 if (anchorToLL && !anchorToLL->empty())
398 {
399 std::string fakedHid = URLEncoder::encode(documentPath);
400 for (auto const& elemAnchor : *anchorToLL)
401 {
402 const std::string &anchor = elemAnchor.first;
403 addBookmark(pFileDbBase_DBHelp, documentPath, fileB,
404 anchor, jarfileB, titleB);
405 std::string totalId = fakedHid + "#" + anchor;
406 // std::cerr << hzipFileName << std::endl;
407 const LinkedList& ll = elemAnchor.second;
408 for (auto const& elem : ll)
409 {
410 helpKeyword.insert(elem, totalId);
411 }
412 }
413
414 }
415
416 // and last the helptexts
417 const Stringtable *helpTextHash = streamTable.appl_helptexts.get();
418 if (helpTextHash)
419 {
420 for (auto const& elem : *helpTextHash)
421 {
422 std::string helpTextId = elem.first;
423 const std::string& helpTextText = elem.second;
424
425 helpTextId = URLEncoder::encode(helpTextId);
426
427 if( pFileHelpText_DBHelp != nullptr )
428 writeKeyValue_DBHelp( pFileHelpText_DBHelp, helpTextId, helpTextText );
429 }
430 }
431
432 //IndexerPreProcessor
433 if( !bExtensionMode || bIndexForExtension )
434 {
435 // now the indexing
436 xmlDocPtr document = streamTable.appl_doc;
437 if (document)
438 {
439 std::string temp = module;
440 std::transform (temp.begin(), temp.end(), temp.begin(), tocharlower);
441 m_pIndexerPreProcessor->processDocument(document, URLEncoder::encode(documentPath) );
442 }
443 }
444
445 }
446
447 }
448 catch( const HelpProcessingException& )
449 {
450 // catch HelpProcessingException to avoid locking data bases
451 if( pFileHelpText_DBHelp != nullptr )
452 fclose( pFileHelpText_DBHelp );
453 if( pFileDbBase_DBHelp != nullptr )
454 fclose( pFileDbBase_DBHelp );
455 throw;
456 }
457
458 if( pFileHelpText_DBHelp != nullptr )
459 fclose( pFileHelpText_DBHelp );
460 if( pFileDbBase_DBHelp != nullptr )
461 fclose( pFileDbBase_DBHelp );
462
463 helpKeyword.dump_DBHelp( keyWordFileName_DBHelp);
464
465 if( bExtensionMode )
466 return;
467
468 // New index
469 for (auto const& additionalFile : additionalFiles)
470 {
471 const std::string &additionalFileName = additionalFile.second;
472 const std::string &additionalFileKey = additionalFile.first;
473
474 fs::path fsAdditionalFileName( additionalFileName, fs::native );
475 HCDBG({do { } while(false)
476 std::string aNativeStr = fsAdditionalFileName.native_file_string();do { } while(false)
477 const char* pStr = aNativeStr.c_str();do { } while(false)
478 std::cerr << pStr << std::endl;do { } while(false)
479 })do { } while(false);
480
481 fs::path fsTargetName( indexDirParentName / additionalFileKey );
482
483 fs::copy( fsAdditionalFileName, fsTargetName );
484 }
485}
486
487
488void HelpLinker::main( std::vector<std::string> &args,
489 std::string const * pExtensionPath, std::string const * pDestination,
490 const OUString* pOfficeHelpPath )
491{
492 bExtensionMode = false;
493 helpFiles.clear();
494
495 if ((!args.empty()) && args[0][0] == '@')
1
Assuming the condition is false
496 {
497 std::vector<std::string> stringList;
498 std::ifstream fileReader(args[0].substr(1).c_str());
499
500 while (fileReader)
501 {
502 std::string token;
503 fileReader >> token;
504 if (!token.empty())
505 stringList.push_back(token);
506 }
507 fileReader.close();
508
509 args = stringList;
510 }
511
512 size_t i = 0;
513 bool bSrcOption = false;
514 while (i < args.size())
2
Assuming the condition is false
3
Loop condition is false. Execution continues on line 687
515 {
516 if (args[i].compare("-extlangsrc") == 0)
517 {
518 ++i;
519 if (i >= args.size())
520 {
521 std::stringstream aStrStream;
522 aStrStream << "extension source missing" << std::endl;
523 throw HelpProcessingException( HelpProcessingErrorClass::General, aStrStream.str() );
524 }
525 extsource = args[i];
526 }
527 else if (args[i].compare("-extlangdest") == 0)
528 {
529 //If this argument is not provided then the location provided in -extsource will
530 //also be the destination
531 ++i;
532 if (i >= args.size())
533 {
534 std::stringstream aStrStream;
535 aStrStream << "extension destination missing" << std::endl;
536 throw HelpProcessingException( HelpProcessingErrorClass::General, aStrStream.str() );
537 }
538 extdestination = args[i];
539 }
540 else if (args[i].compare("-src") == 0)
541 {
542 ++i;
543 if (i >= args.size())
544 {
545 std::stringstream aStrStream;
546 aStrStream << "sourceroot missing" << std::endl;
547 throw HelpProcessingException( HelpProcessingErrorClass::General, aStrStream.str() );
548 }
549 bSrcOption = true;
550 sourceRoot = fs::path(args[i], fs::native);
551 }
552 else if (args[i].compare("-compact") == 0)
553 {
554 ++i;
555 if (i >= args.size())
556 {
557 std::stringstream aStrStream;
558 aStrStream << "compactStylesheet missing" << std::endl;
559 throw HelpProcessingException( HelpProcessingErrorClass::General, aStrStream.str() );
560 }
561
562 compactStylesheet = fs::path(args[i], fs::native);
563 }
564 else if (args[i].compare("-sty") == 0)
565 {
566 ++i;
567 if (i >= args.size())
568 {
569 std::stringstream aStrStream;
570 aStrStream << "embeddingStylesheet missing" << std::endl;
571 throw HelpProcessingException( HelpProcessingErrorClass::General, aStrStream.str() );
572 }
573
574 embeddStylesheet = fs::path(args[i], fs::native);
575 }
576 else if (args[i].compare("-zipdir") == 0)
577 {
578 ++i;
579 if (i >= args.size())
580 {
581 std::stringstream aStrStream;
582 aStrStream << "idxtemp missing" << std::endl;
583 throw HelpProcessingException( HelpProcessingErrorClass::General, aStrStream.str() );
584 }
585
586 zipdir = fs::path(args[i], fs::native);
587 }
588 else if (args[i].compare("-idxcaption") == 0)
589 {
590 ++i;
591 if (i >= args.size())
592 {
593 std::stringstream aStrStream;
594 aStrStream << "idxcaption stylesheet missing" << std::endl;
595 throw HelpProcessingException( HelpProcessingErrorClass::General, aStrStream.str() );
596 }
597
598 idxCaptionStylesheet = fs::path(args[i], fs::native);
599 }
600 else if (args[i].compare("-idxcontent") == 0)
601 {
602 ++i;
603 if (i >= args.size())
604 {
605 std::stringstream aStrStream;
606 aStrStream << "idxcontent stylesheet missing" << std::endl;
607 throw HelpProcessingException( HelpProcessingErrorClass::General, aStrStream.str() );
608 }
609
610 idxContentStylesheet = fs::path(args[i], fs::native);
611 }
612 else if (args[i].compare("-o") == 0)
613 {
614 ++i;
615 if (i >= args.size())
616 {
617 std::stringstream aStrStream;
618 aStrStream << "outputfilename missing" << std::endl;
619 throw HelpProcessingException( HelpProcessingErrorClass::General, aStrStream.str() );
620 }
621
622 outputFile = fs::path(args[i], fs::native);
623 }
624 else if (args[i].compare("-mod") == 0)
625 {
626 ++i;
627 if (i >= args.size())
628 {
629 std::stringstream aStrStream;
630 aStrStream << "module name missing" << std::endl;
631 throw HelpProcessingException( HelpProcessingErrorClass::General, aStrStream.str() );
632 }
633
634 module = args[i];
635 }
636 else if (args[i].compare("-lang") == 0)
637 {
638 ++i;
639 if (i >= args.size())
640 {
641 std::stringstream aStrStream;
642 aStrStream << "language name missing" << std::endl;
643 throw HelpProcessingException( HelpProcessingErrorClass::General, aStrStream.str() );
644 }
645
646 lang = args[i];
647 }
648 else if (args[i].compare("-hid") == 0)
649 {
650 ++i;
651 throw HelpProcessingException( HelpProcessingErrorClass::General, "obsolete -hid argument used" );
652 }
653 else if (args[i].compare("-add") == 0)
654 {
655 std::string addFile, addFileUnderPath;
656 ++i;
657 if (i >= args.size())
658 {
659 std::stringstream aStrStream;
660 aStrStream << "pathname missing" << std::endl;
661 throw HelpProcessingException( HelpProcessingErrorClass::General, aStrStream.str() );
662 }
663
664 addFileUnderPath = args[i];
665 ++i;
666 if (i >= args.size())
667 {
668 std::stringstream aStrStream;
669 aStrStream << "pathname missing" << std::endl;
670 throw HelpProcessingException( HelpProcessingErrorClass::General, aStrStream.str() );
671 }
672 addFile = args[i];
673 if (!addFileUnderPath.empty() && !addFile.empty())
674 additionalFiles[addFileUnderPath] = addFile;
675 }
676 else if (args[i].compare("-nolangroot") == 0)
677 m_bUseLangRoot = false;
678 else if (args[i].compare("-noindex") == 0)
679 m_bCreateIndex = false;
680 else
681 helpFiles.push_back(args[i]);
682 ++i;
683 }
684
685 //We can be called from the helplinker executable or the extension manager
686 //In the latter case extsource is not used.
687 if( (pExtensionPath && pExtensionPath->length() > 0 && pOfficeHelpPath)
4
Assuming 'pExtensionPath' is non-null
5
Assuming the condition is true
6
Assuming 'pOfficeHelpPath' is null
7
Assuming pointer value is null
9
Taking false branch
688 || !extsource.empty())
8
Assuming the condition is false
689 {
690 bExtensionMode = true;
691 if (!extsource.empty())
692 {
693 //called from helplinker.exe, pExtensionPath and pOfficeHelpPath
694 //should be NULL
695 sourceRoot = fs::path(extsource, fs::native);
696 extensionPath = sourceRoot.toUTF8();
697
698 if (extdestination.empty())
699 {
700 std::stringstream aStrStream;
701 aStrStream << "-extlangdest is missing" << std::endl;
702 throw HelpProcessingException( HelpProcessingErrorClass::General, aStrStream.str() );
703 }
704 else
705 {
706 //Convert from system path to file URL!!!
707 fs::path p(extdestination, fs::native);
708 extensionDestination = p.toUTF8();
709 }
710 }
711 else
712 { //called from extension manager
713 extensionPath = *pExtensionPath;
714 sourceRoot = fs::path(extensionPath);
715 extensionDestination = *pDestination;
716 }
717 //check if -src option was used. This option must not be used
718 //when extension help is compiled.
719 if (bSrcOption)
720 {
721 std::stringstream aStrStream;
722 aStrStream << "-src must not be used together with -extsource missing" << std::endl;
723 throw HelpProcessingException( HelpProcessingErrorClass::General, aStrStream.str() );
724 }
725 }
726
727 if (!bExtensionMode && zipdir.empty())
10
Assuming field 'bExtensionMode' is true
728 {
729 std::stringstream aStrStream;
730 aStrStream << "no index dir given" << std::endl;
731 throw HelpProcessingException( HelpProcessingErrorClass::General, aStrStream.str() );
732 }
733
734 if ( (!bExtensionMode
10.1
Field 'bExtensionMode' is true
&& idxCaptionStylesheet.empty())
735 || (!extsource.empty() && idxCaptionStylesheet.empty()) )
11
Assuming the condition is false
736 {
737 //No extension mode and extension mode using commandline
738 //!extsource.empty indicates extension mode using commandline
739 // -idxcaption parameter is required
740 std::stringstream aStrStream;
741 aStrStream << "no index caption stylesheet given" << std::endl;
742 throw HelpProcessingException( HelpProcessingErrorClass::General, aStrStream.str() );
743 }
744 else if ( bExtensionMode
11.1
Field 'bExtensionMode' is true
&& extsource.empty())
12
Assuming the condition is true
13
Taking true branch
745 {
746 //This part is used when compileExtensionHelp is called from the extensions manager.
747 //If extension help is compiled using helplinker in the build process
748 OUString aIdxCaptionPathFileURL = *pOfficeHelpPath + "/idxcaption.xsl";
14
Forming reference to null pointer
749
750 OString aOStr_IdxCaptionPathFileURL( OUStringToOString
751 ( aIdxCaptionPathFileURL, osl_getThreadTextEncoding() ) );
752 std::string aStdStr_IdxCaptionPathFileURL( aOStr_IdxCaptionPathFileURL.getStr() );
753
754 idxCaptionStylesheet = fs::path( aStdStr_IdxCaptionPathFileURL );
755 }
756
757 if ( (!bExtensionMode && idxContentStylesheet.empty())
758 || (!extsource.empty() && idxContentStylesheet.empty()) )
759 {
760 //No extension mode and extension mode using commandline
761 //!extsource.empty indicates extension mode using commandline
762 // -idxcontent parameter is required
763 std::stringstream aStrStream;
764 aStrStream << "no index content stylesheet given" << std::endl;
765 throw HelpProcessingException( HelpProcessingErrorClass::General, aStrStream.str() );
766 }
767 else if ( bExtensionMode && extsource.empty())
768 {
769 //If extension help is compiled using helplinker in the build process
770 //then -idxcontent must be supplied
771 //This part is used when compileExtensionHelp is called from the extensions manager.
772 OUString aIdxContentPathFileURL = *pOfficeHelpPath + "/idxcontent.xsl";
773
774 OString aOStr_IdxContentPathFileURL( OUStringToOString
775 ( aIdxContentPathFileURL, osl_getThreadTextEncoding() ) );
776 std::string aStdStr_IdxContentPathFileURL( aOStr_IdxContentPathFileURL.getStr() );
777
778 idxContentStylesheet = fs::path( aStdStr_IdxContentPathFileURL );
779 }
780 if (!bExtensionMode && embeddStylesheet.empty())
781 {
782 std::stringstream aStrStream;
783 aStrStream << "no embedding resolving file given" << std::endl;
784 throw HelpProcessingException( HelpProcessingErrorClass::General, aStrStream.str() );
785 }
786 if (sourceRoot.empty())
787 {
788 std::stringstream aStrStream;
789 aStrStream << "no sourceroot given" << std::endl;
790 throw HelpProcessingException( HelpProcessingErrorClass::General, aStrStream.str() );
791 }
792 if (!bExtensionMode && outputFile.empty())
793 {
794 std::stringstream aStrStream;
795 aStrStream << "no output file given" << std::endl;
796 throw HelpProcessingException( HelpProcessingErrorClass::General, aStrStream.str() );
797 }
798 if (module.empty())
799 {
800 std::stringstream aStrStream;
801 aStrStream << "module missing" << std::endl;
802 throw HelpProcessingException( HelpProcessingErrorClass::General, aStrStream.str() );
803 }
804 if (!bExtensionMode && lang.empty())
805 {
806 std::stringstream aStrStream;
807 aStrStream << "language missing" << std::endl;
808 throw HelpProcessingException( HelpProcessingErrorClass::General, aStrStream.str() );
809 }
810 link();
811}
812
813// Variable to set an exception in "C" StructuredXMLErrorFunction
814static const HelpProcessingException* GpXMLParsingException = nullptr;
815
816extern "C" {
817
818static void StructuredXMLErrorFunction(SAL_UNUSED_PARAMETER__attribute__ ((unused)) void *, xmlErrorPtr error)
819{
820 std::string aErrorMsg = error->message;
821 std::string aXMLParsingFile;
822 if( error->file != nullptr )
823 aXMLParsingFile = error->file;
824 int nXMLParsingLine = error->line;
825 HelpProcessingException* pException = new HelpProcessingException( aErrorMsg, aXMLParsingFile, nXMLParsingLine );
826 GpXMLParsingException = pException;
827
828 // Reset error handler
829 xmlSetStructuredErrorFunc( nullptr, nullptr );
830}
831
832}
833
834HelpProcessingErrorInfo& HelpProcessingErrorInfo::operator=( const struct HelpProcessingException& e )
835{
836 m_eErrorClass = e.m_eErrorClass;
837 OString tmpErrorMsg( e.m_aErrorMsg.c_str() );
838 m_aErrorMsg = OStringToOUString( tmpErrorMsg, osl_getThreadTextEncoding() );
839 OString tmpXMLParsingFile( e.m_aXMLParsingFile.c_str() );
840 m_aXMLParsingFile = OStringToOUString( tmpXMLParsingFile, osl_getThreadTextEncoding() );
841 m_nXMLParsingLine = e.m_nXMLParsingLine;
842 return *this;
843}
844
845
846// Returns true in case of success, false in case of error
847bool compileExtensionHelp
848(
849 const OUString& aOfficeHelpPath,
850 const OUString& aExtensionName,
851 const OUString& aExtensionLanguageRoot,
852 sal_Int32 nXhpFileCount, const OUString* pXhpFiles,
853 const OUString& aDestination,
854 HelpProcessingErrorInfo& o_rHelpProcessingErrorInfo
855)
856{
857 bool bSuccess = true;
858
859 std::vector<std::string> args;
860 args.reserve(nXhpFileCount + 2);
861 args.push_back(std::string("-mod"));
862 OString aOExtensionName = OUStringToOString( aExtensionName, osl_getThreadTextEncoding() );
863 args.push_back(std::string(aOExtensionName.getStr()));
864
865 for( sal_Int32 iXhp = 0 ; iXhp < nXhpFileCount ; ++iXhp )
866 {
867 OUString aXhpFile = pXhpFiles[iXhp];
868
869 OString aOXhpFile = OUStringToOString( aXhpFile, osl_getThreadTextEncoding() );
870 args.push_back(std::string(aOXhpFile.getStr()));
871 }
872
873 OString aOExtensionLanguageRoot = OUStringToOString( aExtensionLanguageRoot, osl_getThreadTextEncoding() );
874 const char* pExtensionPath = aOExtensionLanguageRoot.getStr();
875 std::string aStdStrExtensionPath = pExtensionPath;
876 OString aODestination = OUStringToOString(aDestination, osl_getThreadTextEncoding());
877 const char* pDestination = aODestination.getStr();
878 std::string aStdStrDestination = pDestination;
879
880 // Set error handler
881 xmlSetStructuredErrorFunc( nullptr, StructuredXMLErrorFunction );
882 try
883 {
884 std::unique_ptr<HelpLinker> pHelpLinker(new HelpLinker());
885 pHelpLinker->main( args, &aStdStrExtensionPath, &aStdStrDestination, &aOfficeHelpPath );
886 }
887 catch( const HelpProcessingException& e )
888 {
889 if( GpXMLParsingException != nullptr )
890 {
891 o_rHelpProcessingErrorInfo = *GpXMLParsingException;
892 delete GpXMLParsingException;
893 GpXMLParsingException = nullptr;
894 }
895 else
896 {
897 o_rHelpProcessingErrorInfo = e;
898 }
899 bSuccess = false;
900 }
901 // Reset error handler
902 xmlSetStructuredErrorFunc( nullptr, nullptr );
903
904 // i83624: Tree files
905 // The following basically checks if the help.tree is well formed XML.
906 // Apparently there have been cases when translations contained
907 // non-well-formed XML in the past.
908 OUString aTreeFileURL = aExtensionLanguageRoot + "/help.tree";
909 osl::DirectoryItem aTreeFileItem;
910 osl::FileBase::RC rcGet = osl::DirectoryItem::get( aTreeFileURL, aTreeFileItem );
911 osl::FileStatus aFileStatus( osl_FileStatus_Mask_FileSize0x00000080 );
912 if( rcGet == osl::FileBase::E_None &&
913 aTreeFileItem.getFileStatus( aFileStatus ) == osl::FileBase::E_None &&
914 aFileStatus.isValid( osl_FileStatus_Mask_FileSize0x00000080 ) )
915 {
916 sal_uInt64 ret, len = aFileStatus.getFileSize();
917 std::unique_ptr<char[]> s(new char[ int(len) ]); // the buffer to hold the installed files
918 osl::File aFile( aTreeFileURL );
919 (void)aFile.open( osl_File_OpenFlag_Read0x00000001L );
920 aFile.read( s.get(), len, ret );
921 aFile.close();
922
923 XML_Parser parser = XML_ParserCreate( nullptr );
924 XML_Status parsed = XML_Parse( parser, s.get(), int( len ), true );
925
926 if (XML_STATUS_ERRORXML_STATUS_ERROR == parsed)
927 {
928 XML_Error nError = XML_GetErrorCode( parser );
929 o_rHelpProcessingErrorInfo.m_eErrorClass = HelpProcessingErrorClass::XmlParsing;
930 o_rHelpProcessingErrorInfo.m_aErrorMsg = OUString::createFromAscii( XML_ErrorString( nError ) );
931 o_rHelpProcessingErrorInfo.m_aXMLParsingFile = aTreeFileURL;
932 // CRASHES!!! o_rHelpProcessingErrorInfo.m_nXMLParsingLine = XML_GetCurrentLineNumber( parser );
933 bSuccess = false;
934 }
935
936 XML_ParserFree( parser );
937 }
938
939 return bSuccess;
940}
941
942/* vim:set shiftwidth=4 softtabstop=4 expandtab: */