Simplify using designated initializers
[LibreOffice.git] / xmlhelp / source / cxxhelp / provider / urlparameter.cxx
blob439a2bcce4217d071d59313ea8427dae51f617d9
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
21 #include <string.h>
22 #include <osl/thread.h>
23 #include <osl/file.hxx>
24 #include <cppuhelper/weak.hxx>
25 #include <cppuhelper/queryinterface.hxx>
26 #include <comphelper/processfactory.hxx>
27 #include <rtl/uri.hxx>
28 #include <rtl/ref.hxx>
29 #include <rtl/character.hxx>
30 #include <o3tl/string_view.hxx>
31 #include <libxslt/transform.h>
32 #include <libxslt/xsltutils.h>
33 #include <libxslt/security.h>
34 #include "db.hxx"
35 #include <com/sun/star/io/XActiveDataSink.hpp>
36 #include <com/sun/star/io/XInputStream.hpp>
37 #include <com/sun/star/io/XSeekable.hpp>
38 #include <com/sun/star/lang/IllegalArgumentException.hpp>
39 #include <com/sun/star/ucb/IllegalIdentifierException.hpp>
40 #include <com/sun/star/container/XHierarchicalNameAccess.hpp>
42 #include "urlparameter.hxx"
43 #include "databases.hxx"
45 #include <algorithm>
46 #include <memory>
47 #include <mutex>
49 using namespace cppu;
50 using namespace com::sun::star::io;
51 using namespace com::sun::star::uno;
52 using namespace com::sun::star::lang;
53 using namespace com::sun::star::ucb;
54 using namespace com::sun::star::beans;
55 using namespace com::sun::star::container;
56 using namespace chelp;
59 URLParameter::URLParameter( const OUString& aURL,
60 Databases* pDatabases )
61 : m_pDatabases( pDatabases ),
62 m_aURL( aURL )
64 init();
65 parse();
69 bool URLParameter::isErrorDocument()
71 bool bErrorDoc = false;
73 if( isFile() )
75 Reference< XHierarchicalNameAccess > xNA =
76 m_pDatabases->findJarFileForPath( get_jar(), get_language(), get_path() );
77 bErrorDoc = !xNA.is();
80 return bErrorDoc;
84 OString URLParameter::getByName( const char* par )
86 OUString val;
88 if( strcmp( par,"Program" ) == 0 )
89 val = get_program();
90 else if( strcmp( par,"Database" ) == 0 )
91 val = get_module();
92 else if( strcmp( par,"DatabasePar" ) == 0 )
93 val = get_dbpar();
94 else if( strcmp( par,"Id" ) == 0 )
95 val = get_id();
96 else if( strcmp( par,"Path" ) == 0 )
97 val = get_path();
98 else if( strcmp( par,"Language" ) == 0 )
99 val = get_language();
100 else if( strcmp( par,"System" ) == 0 )
101 val = get_system();
102 else if( strcmp( par,"HelpPrefix" ) == 0 )
103 val = m_aPrefix;
105 return OUStringToOString( val, RTL_TEXTENCODING_UTF8 );
109 OUString const & URLParameter::get_id()
111 if( m_aId == "start" )
112 { // module is set
113 StaticModuleInformation* inf =
114 m_pDatabases->getStaticInformationForModule( get_module(),
115 get_language() );
116 if( inf )
117 m_aId = inf->get_id();
120 return m_aId;
123 const OUString & URLParameter::get_tag()
125 if( isFile() )
126 return get_the_tag();
127 else
128 return m_aTag;
132 const OUString & URLParameter::get_title()
134 if( isFile() )
135 return get_the_title();
136 else if( !m_aModule.isEmpty() )
138 StaticModuleInformation* inf =
139 m_pDatabases->getStaticInformationForModule( get_module(),
140 get_language() );
141 if( inf )
142 m_aTitle = inf->get_title();
144 else // This must be the root
145 m_aTitle = "root";
147 return m_aTitle;
151 OUString const & URLParameter::get_language() const
153 return m_aLanguage;
157 OUString const & URLParameter::get_program()
159 if( m_aProgram.isEmpty() )
161 StaticModuleInformation* inf =
162 m_pDatabases->getStaticInformationForModule( get_module(),
163 get_language() );
164 if( inf )
165 m_aProgram = inf->get_program();
167 return m_aProgram;
171 void URLParameter::init()
173 m_bHelpDataFileRead = false;
174 m_bUseDB = true;
175 m_nHitCount = 100; // The default maximum hitcount
179 const OUString & URLParameter::get_the_tag()
181 if(m_bUseDB) {
182 if( ! m_bHelpDataFileRead )
183 readHelpDataFile();
185 m_bHelpDataFileRead = true;
187 return m_aTag;
189 else
190 return EMPTY_OUSTRING;
194 OUString const & URLParameter::get_path()
196 if(m_bUseDB) {
197 if( ! m_bHelpDataFileRead )
198 readHelpDataFile();
199 m_bHelpDataFileRead = true;
201 return m_aPath;
203 else
204 return get_id();
208 const OUString & URLParameter::get_the_title()
210 if(m_bUseDB) {
211 if( ! m_bHelpDataFileRead )
212 readHelpDataFile();
213 m_bHelpDataFileRead = true;
215 return m_aTitle;
217 else
218 return EMPTY_OUSTRING;
222 OUString URLParameter::get_jar()
224 if(m_bUseDB) {
225 if( ! m_bHelpDataFileRead )
226 readHelpDataFile();
227 m_bHelpDataFileRead = true;
229 return m_aJar;
231 else
232 return get_module() + ".jar";
236 void URLParameter::readHelpDataFile()
238 if( get_id().isEmpty() )
239 return;
241 OUString aModule = get_module();
242 OUString aLanguage = get_language();
244 DataBaseIterator aDbIt( *m_pDatabases, aModule, aLanguage, false );
245 bool bSuccess = false;
247 const char* pData = nullptr;
249 helpdatafileproxy::HDFData aHDFData;
250 OUString aExtensionPath;
251 OUString aExtensionRegistryPath;
252 while( true )
254 helpdatafileproxy::Hdf* pHdf = aDbIt.nextHdf( &aExtensionPath, &aExtensionRegistryPath );
255 if( !pHdf )
256 break;
258 OString keyStr = OUStringToOString( m_aId,RTL_TEXTENCODING_UTF8 );
259 bSuccess = pHdf->getValueForKey( keyStr, aHDFData );
260 if( bSuccess )
262 pData = aHDFData.getData();
263 break;
267 if( !bSuccess )
268 return;
270 DbtToStringConverter converter( pData );
271 m_aTitle = converter.getTitle();
272 m_pDatabases->replaceName( m_aTitle );
273 m_aPath = converter.getFile();
274 m_aJar = converter.getDatabase();
275 if( !aExtensionPath.isEmpty() )
277 m_aJar = "?" + aExtensionPath + "?" + m_aJar;
278 m_aExtensionRegistryPath = aExtensionRegistryPath;
280 m_aTag = converter.getHash();
284 // Class encapsulating the transformation of the XInputStream to XHTML
286 namespace {
288 class InputStreamTransformer
289 : public OWeakObject,
290 public XInputStream,
291 public XSeekable
293 public:
295 InputStreamTransformer( URLParameter* urlParam,
296 Databases* pDatatabases,
297 bool isRoot );
299 virtual Any SAL_CALL queryInterface( const Type& rType ) override;
300 virtual void SAL_CALL acquire() noexcept override;
301 virtual void SAL_CALL release() noexcept override;
303 virtual sal_Int32 SAL_CALL readBytes( Sequence< sal_Int8 >& aData,sal_Int32 nBytesToRead ) override;
305 virtual sal_Int32 SAL_CALL readSomeBytes( Sequence< sal_Int8 >& aData,sal_Int32 nMaxBytesToRead ) override;
307 virtual void SAL_CALL skipBytes( sal_Int32 nBytesToSkip ) override;
309 virtual sal_Int32 SAL_CALL available() override;
311 virtual void SAL_CALL closeInput() override;
313 virtual void SAL_CALL seek( sal_Int64 location ) override;
315 virtual sal_Int64 SAL_CALL getPosition() override;
317 virtual sal_Int64 SAL_CALL getLength() override;
319 void addToBuffer( const char* buffer,int len );
321 OStringBuffer const & getData() const { return buffer; }
323 private:
325 std::mutex m_aMutex;
327 int pos;
328 OStringBuffer buffer;
333 void URLParameter::open( const Reference< XOutputStream >& xDataSink )
335 if( ! xDataSink.is() )
336 return;
338 // a standard document or else an active help text, plug in the new input stream
339 rtl::Reference<InputStreamTransformer> p(new InputStreamTransformer( this,m_pDatabases,isRoot() ));
342 xDataSink->writeBytes( Sequence< sal_Int8 >( reinterpret_cast<const sal_Int8*>(p->getData().getStr()), p->getData().getLength() ) );
344 catch( const Exception& )
347 p.clear();
348 xDataSink->closeOutput();
352 void URLParameter::open( const Reference< XActiveDataSink >& xDataSink )
354 // a standard document or else an active help text, plug in the new input stream
355 xDataSink->setInputStream( new InputStreamTransformer( this,m_pDatabases,isRoot() ) );
359 void URLParameter::parse()
361 m_aExpr = m_aURL;
363 sal_Int32 lstIdx = m_aExpr.lastIndexOf( '#' );
364 if( lstIdx != -1 )
365 m_aExpr = m_aExpr.copy( 0,lstIdx );
367 if( ! scheme() ||
368 ! name( module() ) ||
369 ! query() ||
370 m_aLanguage.isEmpty() ||
371 m_aSystem.isEmpty() )
372 throw css::ucb::IllegalIdentifierException();
376 bool URLParameter::scheme()
378 // Correct extension help links as sometimes the
379 // module is missing resulting in a malformed URL
380 if( m_aExpr.startsWith("vnd.sun.star.help:///") )
382 sal_Int32 nLen = m_aExpr.getLength();
383 std::u16string_view aLastStr =
384 m_aExpr.subView(sal::static_int_cast<sal_uInt32>(nLen) - 6);
385 if( aLastStr == u"DbPAR=" )
387 m_aExpr = OUString::Concat(m_aExpr.subView( 0, 20 )) +
388 "shared" +
389 m_aExpr.subView( 20 ) +
390 "shared";
394 for( sal_Int32 nPrefixLen = 20 ; nPrefixLen >= 18 ; --nPrefixLen )
396 if( m_aExpr.matchAsciiL( "vnd.sun.star.help://", nPrefixLen ) )
398 m_aExpr = m_aExpr.copy( nPrefixLen );
399 return true;
402 return false;
406 bool URLParameter::module()
408 sal_Int32 idx = 0,length = m_aExpr.getLength();
410 while( idx < length && rtl::isAsciiAlphanumeric( m_aExpr[idx] ) )
411 ++idx;
413 if( idx != 0 )
415 m_aModule = m_aExpr.copy( 0,idx );
416 m_aExpr = m_aExpr.copy( idx );
417 return true;
419 else
420 return false;
424 bool URLParameter::name( bool modulePresent )
426 // if modulepresent, a name may be present, but must not
428 sal_Int32 length = m_aExpr.getLength();
430 if( length != 0 && m_aExpr[0] == '/' )
432 sal_Int32 idx = 1;
433 while( idx < length && m_aExpr[idx] != '?' )
434 ++idx;
436 if( idx != 1 && ! modulePresent )
437 return false;
438 else
440 m_aId = m_aExpr.copy( 1,idx-1 );
441 m_aExpr = m_aExpr.copy( idx );
445 return true;
449 bool URLParameter::query()
451 OUString query_;
453 if( m_aExpr.isEmpty() )
454 return true;
455 else if( m_aExpr[0] == '?' )
456 query_ = o3tl::trim(m_aExpr.subView( 1 ));
457 else
458 return false;
461 bool ret = true;
462 sal_Int32 delimIdx,equalIdx;
463 OUString parameter,value;
465 while( !query_.isEmpty() )
467 delimIdx = query_.indexOf( '&' );
468 equalIdx = query_.indexOf( '=' );
469 parameter = o3tl::trim(query_.subView( 0,equalIdx ));
470 if( delimIdx == -1 )
472 value = o3tl::trim(query_.subView( equalIdx + 1 ));
473 query_.clear();
475 else
477 value = o3tl::trim(query_.subView( equalIdx+1,delimIdx - equalIdx - 1 ));
478 query_ = o3tl::trim(query_.subView( delimIdx+1 ));
481 if( parameter == "Language" )
482 m_aLanguage = value;
483 else if( parameter == "Device" )
485 else if( parameter == "Program" )
486 m_aProgram = value;
487 else if( parameter == "Eid" )
488 m_aEid = value;
489 else if( parameter == "UseDB" )
490 m_bUseDB = value != "no";
491 else if( parameter == "DbPAR" )
492 m_aDbPar = value;
493 else if( parameter == "Query" )
495 if( m_aQuery.isEmpty() )
496 m_aQuery = value;
497 else
498 m_aQuery += " " + value;
500 else if( parameter == "Scope" )
501 m_aScope = value;
502 else if( parameter == "System" )
503 m_aSystem = value;
504 else if( parameter == "HelpPrefix" )
505 m_aPrefix = rtl::Uri::decode(
506 value,
507 rtl_UriDecodeWithCharset,
508 RTL_TEXTENCODING_UTF8 );
509 else if( parameter == "HitCount" )
510 m_nHitCount = value.toInt32();
511 else if( parameter == "Active" )
512 m_aActive = value;
513 else if( parameter == "Version" )
514 ; // ignored (but accepted) in the built-in help, useful only for the online help
515 else
516 ret = false;
519 return ret;
522 namespace {
524 struct UserData {
526 UserData( URLParameter* pInitial,
527 Databases* pDatabases )
528 : m_pDatabases( pDatabases ),
529 m_pInitial( pInitial )
533 Databases* m_pDatabases;
534 URLParameter* m_pInitial;
539 static UserData *ugblData = nullptr;
541 extern "C" {
543 static int
544 fileMatch(const char * URI) {
545 if ((URI != nullptr) && !strncmp(URI, "file:/", 6))
546 return 1;
547 return 0;
550 static int
551 zipMatch(const char * URI) {
552 if ((URI != nullptr) && !strncmp(URI, "vnd.sun.star.zip:/", 18))
553 return 1;
554 return 0;
557 static int
558 helpMatch(const char * URI) {
559 if ((URI != nullptr) && !strncmp(URI, "vnd.sun.star.help:/", 19))
560 return 1;
561 return 0;
564 static void *
565 fileOpen(const char *URI) {
566 osl::File *pRet = new osl::File(OUString(URI, strlen(URI), RTL_TEXTENCODING_UTF8));
567 (void)pRet->open(osl_File_OpenFlag_Read);
568 return pRet;
571 static void *
572 zipOpen(SAL_UNUSED_PARAMETER const char *) {
573 OUString language,jar,path;
575 if( !ugblData->m_pInitial->get_eid().isEmpty() )
576 return new Reference<XHierarchicalNameAccess>;
577 else
579 jar = ugblData->m_pInitial->get_jar();
580 language = ugblData->m_pInitial->get_language();
581 path = ugblData->m_pInitial->get_path();
584 Reference< XHierarchicalNameAccess > xNA =
585 ugblData->m_pDatabases->findJarFileForPath( jar, language, path );
587 Reference< XInputStream > xInputStream;
589 if( xNA.is() )
593 Any aEntry = xNA->getByHierarchicalName( path );
594 Reference< XActiveDataSink > xSink;
595 if( ( aEntry >>= xSink ) && xSink.is() )
596 xInputStream = xSink->getInputStream();
598 catch ( NoSuchElementException & )
603 if( xInputStream.is() )
605 return new Reference<XInputStream>(xInputStream);
607 return nullptr;
610 static void *
611 helpOpen(const char * URI) {
612 OUString language,jar,path;
614 URLParameter urlpar( OUString::createFromAscii( URI ),
615 ugblData->m_pDatabases );
617 jar = urlpar.get_jar();
618 language = urlpar.get_language();
619 path = urlpar.get_path();
621 Reference< XHierarchicalNameAccess > xNA =
622 ugblData->m_pDatabases->findJarFileForPath( jar, language, path );
624 Reference< XInputStream > xInputStream;
626 if( xNA.is() )
630 Any aEntry = xNA->getByHierarchicalName( path );
631 Reference< XActiveDataSink > xSink;
632 if( ( aEntry >>= xSink ) && xSink.is() )
633 xInputStream = xSink->getInputStream();
635 catch ( NoSuchElementException & )
640 if( xInputStream.is() )
641 return new Reference<XInputStream>(xInputStream);
642 return nullptr;
645 static int
646 helpRead(void * context, char * buffer, int len) {
647 Reference< XInputStream > *pRef = static_cast<Reference< XInputStream >*>(context);
649 Sequence< sal_Int8 > aSeq;
650 len = (*pRef)->readBytes( aSeq,len);
651 memcpy(buffer, aSeq.getConstArray(), len);
653 return len;
656 static int
657 zipRead(void * context, char * buffer, int len) {
658 return helpRead(context, buffer, len);
661 static int
662 fileRead(void * context, char * buffer, int len) {
663 int nRead = 0;
664 osl::File *pFile = static_cast<osl::File*>(context);
665 if (pFile)
667 sal_uInt64 uRead = 0;
668 if (osl::FileBase::E_None == pFile->read(buffer, len, uRead))
669 nRead = static_cast<int>(uRead);
671 return nRead;
674 static int
675 uriClose(void * context) {
676 Reference< XInputStream > *pRef = static_cast<Reference< XInputStream >*>(context);
677 delete pRef;
678 return 0;
681 static int
682 fileClose(void * context) {
683 osl::File *pFile = static_cast<osl::File*>(context);
684 if (pFile)
686 pFile->close();
687 delete pFile;
689 return 0;
692 } // extern "C"
694 InputStreamTransformer::InputStreamTransformer( URLParameter* urlParam,
695 Databases* pDatabases,
696 bool isRoot )
697 : pos( 0 )
699 if( isRoot )
701 buffer.setLength(0);
702 pDatabases->cascadingStylesheet( urlParam->get_language(),
703 buffer );
705 else if( urlParam->isActive() )
707 buffer.setLength(0);
708 pDatabases->setActiveText( urlParam->get_module(),
709 urlParam->get_language(),
710 urlParam->get_id(),
711 buffer );
713 else
715 UserData userData( urlParam,pDatabases );
717 // Uses the implementation detail, that OString::getStr returns a zero terminated character-array
719 const char* parameter[47];
720 OString parString[46];
721 int last = 0;
723 parString[last++] = "Program"_ostr;
724 OString aPureProgramm( urlParam->getByName( "Program" ) );
725 parString[last++] = "'" + aPureProgramm + "'";
726 parString[last++] = "Database"_ostr;
727 parString[last++] = "'" + urlParam->getByName( "DatabasePar" ) + "'";
728 parString[last++] = "Id"_ostr;
729 parString[last++] = "'" + urlParam->getByName( "Id" ) + "'";
730 parString[last++] = "Path"_ostr;
731 OString aPath( urlParam->getByName( "Path" ) );
732 parString[last++] = "'" + aPath + "'";
734 OString aPureLanguage = urlParam->getByName( "Language" );
735 parString[last++] = "Language"_ostr;
736 parString[last++] = "'" + aPureLanguage + "'";
737 parString[last++] = "System"_ostr;
738 parString[last++] = "'" + urlParam->getByName( "System" ) + "'";
739 parString[last++] = "productname"_ostr;
740 parString[last++] = "'" + OUStringToOString(
741 pDatabases->getProductName(),
742 RTL_TEXTENCODING_UTF8 ) + "'";
743 parString[last++] = "productversion"_ostr;
744 parString[last++] = "'" +
745 OUStringToOString( pDatabases->getProductVersion(),
746 RTL_TEXTENCODING_UTF8 ) + "'";
748 parString[last++] = "imgtheme"_ostr;
749 parString[last++] = "'" + chelp::Databases::getImageTheme() + "'";
750 parString[last++] = "hp"_ostr;
751 parString[last++] = "'" + urlParam->getByName( "HelpPrefix" ) + "'";
753 if( !parString[last-1].isEmpty() )
755 parString[last++] = "sm"_ostr;
756 parString[last++] = "'vnd.sun.star.help%3A%2F%2F'"_ostr;
757 parString[last++] = "qm"_ostr;
758 parString[last++] = "'%3F'"_ostr;
759 parString[last++] = "es"_ostr;
760 parString[last++] = "'%3D'"_ostr;
761 parString[last++] = "am"_ostr;
762 parString[last++] = "'%26'"_ostr;
763 parString[last++] = "cl"_ostr;
764 parString[last++] = "'%3A'"_ostr;
765 parString[last++] = "sl"_ostr;
766 parString[last++] = "'%2F'"_ostr;
767 parString[last++] = "hm"_ostr;
768 parString[last++] = "'%23'"_ostr;
769 parString[last++] = "cs"_ostr;
770 parString[last++] = "'css'"_ostr;
772 parString[last++] = "vendorname"_ostr;
773 parString[last++] = "''"_ostr;
774 parString[last++] = "vendorversion"_ostr;
775 parString[last++] = "''"_ostr;
776 parString[last++] = "vendorshort"_ostr;
777 parString[last++] = "''"_ostr;
780 // Do we need to add extension path?
781 OUString aExtensionPath;
782 OUString aJar = urlParam->get_jar();
784 bool bAddExtensionPath = false;
785 OUString aExtensionRegistryPath;
786 sal_Int32 nQuestionMark1 = aJar.indexOf( '?' );
787 sal_Int32 nQuestionMark2 = aJar.lastIndexOf( '?' );
788 if( nQuestionMark1 != -1 && nQuestionMark2 != -1 && nQuestionMark1 != nQuestionMark2 )
790 aExtensionPath = aJar.copy( nQuestionMark1 + 1, nQuestionMark2 - nQuestionMark1 - 1 );
791 aExtensionRegistryPath = urlParam->get_ExtensionRegistryPath();
792 bAddExtensionPath = true;
794 else
796 // Path not yet specified, search directly
797 Reference< XHierarchicalNameAccess > xNA = pDatabases->findJarFileForPath
798 ( aJar, urlParam->get_language(), urlParam->get_path(), &aExtensionPath, &aExtensionRegistryPath );
799 if( xNA.is() && !aExtensionPath.isEmpty() )
800 bAddExtensionPath = true;
803 if( bAddExtensionPath )
805 const Reference< XComponentContext >& xContext(
806 comphelper::getProcessComponentContext() );
808 OUString aOUExpandedExtensionPath = Databases::expandURL( aExtensionRegistryPath, xContext );
809 OString aExpandedExtensionPath = OUStringToOString( aOUExpandedExtensionPath, osl_getThreadTextEncoding() );
811 parString[last++] = "ExtensionPath"_ostr;
812 parString[last++] = "'" + aExpandedExtensionPath + "'";
814 // ExtensionId
815 OString aPureExtensionId;
816 sal_Int32 iSlash = aPath.indexOf( '/' );
817 if( iSlash != -1 )
818 aPureExtensionId = aPath.copy( 0, iSlash );
820 parString[last++] = "ExtensionId"_ostr;
821 parString[last++] = "'" + aPureExtensionId + "'";
824 for( int i = 0; i < last; ++i )
825 parameter[i] = parString[i].getStr();
826 parameter[last] = nullptr;
828 OUString xslURL = pDatabases->getInstallPathAsURL();
830 OString xslURLascii = OUStringToOString(
831 xslURL,
832 RTL_TEXTENCODING_UTF8) +
833 "main_transform.xsl";
835 ugblData = &userData;
837 xmlInitParser();
838 xmlRegisterInputCallbacks(zipMatch, zipOpen, zipRead, uriClose);
839 xmlRegisterInputCallbacks(helpMatch, helpOpen, helpRead, uriClose);
840 xmlRegisterInputCallbacks(fileMatch, fileOpen, fileRead, fileClose);
842 xsltStylesheetPtr cur =
843 xsltParseStylesheetFile(reinterpret_cast<const xmlChar *>(xslURLascii.getStr()));
845 xmlDocPtr doc = xmlParseFile("vnd.sun.star.zip:/");
847 xmlDocPtr res = nullptr;
848 xsltTransformContextPtr transformContext = xsltNewTransformContext(cur, doc);
849 if (transformContext)
851 xsltSecurityPrefsPtr securityPrefs = xsltNewSecurityPrefs();
852 if (securityPrefs)
854 xsltSetSecurityPrefs(securityPrefs, XSLT_SECPREF_READ_FILE, xsltSecurityAllow);
855 if (xsltSetCtxtSecurityPrefs(securityPrefs, transformContext) == 0)
857 res = xsltApplyStylesheetUser(cur, doc, parameter, nullptr, nullptr, transformContext);
858 if (res)
860 xmlChar *doc_txt_ptr=nullptr;
861 int doc_txt_len;
862 xsltSaveResultToString(&doc_txt_ptr, &doc_txt_len, res, cur);
863 addToBuffer(reinterpret_cast<char*>(doc_txt_ptr), doc_txt_len);
864 xmlFree(doc_txt_ptr);
867 xsltFreeSecurityPrefs(securityPrefs);
869 xsltFreeTransformContext(transformContext);
871 xmlPopInputCallbacks(); //filePatch
872 xmlPopInputCallbacks(); //helpPatch
873 xmlPopInputCallbacks(); //zipMatch
874 xmlFreeDoc(res);
875 xmlFreeDoc(doc);
876 xsltFreeStylesheet(cur);
881 Any SAL_CALL InputStreamTransformer::queryInterface( const Type& rType )
883 Any aRet = ::cppu::queryInterface( rType,
884 static_cast< XInputStream* >(this),
885 static_cast< XSeekable* >(this) );
887 return aRet.hasValue() ? aRet : OWeakObject::queryInterface( rType );
891 void SAL_CALL InputStreamTransformer::acquire() noexcept
893 OWeakObject::acquire();
897 void SAL_CALL InputStreamTransformer::release() noexcept
899 OWeakObject::release();
903 sal_Int32 SAL_CALL InputStreamTransformer::readBytes( Sequence< sal_Int8 >& aData,sal_Int32 nBytesToRead )
905 std::scoped_lock aGuard( m_aMutex );
907 int curr,available_ = buffer.getLength() - pos;
908 if( nBytesToRead <= available_ )
909 curr = nBytesToRead;
910 else
911 curr = available_;
913 if( 0 <= curr && aData.getLength() < curr )
914 aData.realloc( curr );
916 std::copy_n(buffer.getStr() + pos, curr, aData.getArray());
917 pos += curr;
919 return std::max(curr, 0);
923 sal_Int32 SAL_CALL InputStreamTransformer::readSomeBytes( Sequence< sal_Int8 >& aData,sal_Int32 nMaxBytesToRead )
925 return readBytes( aData,nMaxBytesToRead );
929 void SAL_CALL InputStreamTransformer::skipBytes( sal_Int32 nBytesToSkip )
931 std::scoped_lock aGuard( m_aMutex );
932 while( nBytesToSkip-- ) ++pos;
936 sal_Int32 SAL_CALL InputStreamTransformer::available()
938 std::scoped_lock aGuard( m_aMutex );
939 return std::min<sal_Int64>(SAL_MAX_INT32, buffer.getLength() - pos);
943 void SAL_CALL InputStreamTransformer::closeInput()
948 void SAL_CALL InputStreamTransformer::seek( sal_Int64 location )
950 std::scoped_lock aGuard( m_aMutex );
951 if( location < 0 )
952 throw IllegalArgumentException();
954 pos = sal::static_int_cast<sal_Int32>( location );
956 if( pos > buffer.getLength() )
957 pos = buffer.getLength();
961 sal_Int64 SAL_CALL InputStreamTransformer::getPosition()
963 std::scoped_lock aGuard( m_aMutex );
964 return sal_Int64( pos );
968 sal_Int64 SAL_CALL InputStreamTransformer::getLength()
970 std::scoped_lock aGuard( m_aMutex );
972 return buffer.getLength();
976 void InputStreamTransformer::addToBuffer( const char* buffer_,int len_ )
978 std::scoped_lock aGuard( m_aMutex );
980 buffer.append( buffer_, len_ );
983 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */