22#include <osl/thread.h>
23#include <osl/file.hxx>
29#include <rtl/character.hxx>
31#include <libxslt/transform.h>
32#include <libxslt/xsltutils.h>
33#include <libxslt/security.h>
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>
59URLParameter::URLParameter(
const OUString& aURL,
61 : m_pDatabases( pDatabases ),
71 bool bErrorDoc =
false;
77 bErrorDoc = !xNA.is();
88 if( strcmp( par,
"Program" ) == 0 )
90 else if( strcmp( par,
"Database" ) == 0 )
92 else if( strcmp( par,
"DatabasePar" ) == 0 )
94 else if( strcmp( par,
"Id" ) == 0 )
96 else if( strcmp( par,
"Path" ) == 0 )
98 else if( strcmp( par,
"Language" ) == 0 )
100 else if( strcmp( par,
"System" ) == 0 )
102 else if( strcmp( par,
"HelpPrefix" ) == 0 )
111 if(
m_aId ==
"start" )
245 bool bSuccess =
false;
247 const char*
pData =
nullptr;
250 OUString aExtensionPath;
251 OUString aExtensionRegistryPath;
275 if( !aExtensionPath.isEmpty() )
288class InputStreamTransformer
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; }
328 OStringBuffer buffer;
335 if( ! xDataSink.is() )
344 catch(
const Exception& )
348 xDataSink->closeOutput();
355 xDataSink->setInputStream(
new InputStreamTransformer(
this,
m_pDatabases,
isRoot() ) );
363 sal_Int32 lstIdx =
m_aExpr.lastIndexOf(
'#' );
372 throw css::ucb::IllegalIdentifierException();
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=" )
394 for( sal_Int32 nPrefixLen = 20 ; nPrefixLen >= 18 ; --nPrefixLen )
396 if(
m_aExpr.matchAsciiL(
"vnd.sun.star.help://", nPrefixLen ) )
436 if(
idx != 1 && ! modulePresent )
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 ));
477 value =
o3tl::trim(query_.subView( equalIdx+1,delimIdx - equalIdx - 1 ));
478 query_ =
o3tl::trim(query_.subView( delimIdx+1 ));
481 if( parameter ==
"Language" )
483 else if( parameter ==
"Device" )
485 else if( parameter ==
"Program" )
487 else if( parameter ==
"Eid" )
489 else if( parameter ==
"UseDB" )
491 else if( parameter ==
"DbPAR" )
493 else if( parameter ==
"Query" )
500 else if( parameter ==
"Scope" )
502 else if( parameter ==
"System" )
504 else if( parameter ==
"HelpPrefix" )
507 rtl_UriDecodeWithCharset,
508 RTL_TEXTENCODING_UTF8 );
509 else if( parameter ==
"HitCount" )
511 else if( parameter ==
"Active" )
513 else if( parameter ==
"Version" )
528 : m_pDatabases( pDatabases ),
529 m_pInitial( pInitial )
545 if ((URI !=
nullptr) && !strncmp(URI,
"file:/", 6))
552 if ((URI !=
nullptr) && !strncmp(URI,
"vnd.sun.star.zip:/", 18))
559 if ((URI !=
nullptr) && !strncmp(URI,
"vnd.sun.star.help:/", 19))
566 osl::File *pRet =
new osl::File(OUString(URI, strlen(URI), RTL_TEXTENCODING_UTF8));
567 (void)pRet->open(osl_File_OpenFlag_Read);
573 OUString language,jar,path;
575 if( !
ugblData->m_pInitial->get_eid().isEmpty() )
579 jar =
ugblData->m_pInitial->get_jar();
580 language =
ugblData->m_pInitial->get_language();
581 path =
ugblData->m_pInitial->get_path();
585 ugblData->m_pDatabases->findJarFileForPath( jar, language, path );
593 Any aEntry = xNA->getByHierarchicalName( path );
596 xInputStream =
xSink->getInputStream();
598 catch ( NoSuchElementException & )
603 if( xInputStream.is() )
612 OUString language,jar,path;
622 ugblData->m_pDatabases->findJarFileForPath( jar, language, path );
630 Any aEntry = xNA->getByHierarchicalName( path );
633 xInputStream =
xSink->getInputStream();
635 catch ( NoSuchElementException & )
640 if( xInputStream.is() )
650 len = (*pRef)->readBytes(
aSeq,len);
651 memcpy(buffer,
aSeq.getConstArray(), len);
657zipRead(
void * context,
char * buffer,
int len) {
658 return helpRead(context, buffer, len);
664 osl::File *pFile =
static_cast<osl::File*
>(context);
667 sal_uInt64 uRead = 0;
668 if (osl::FileBase::E_None == pFile->read(buffer, len, uRead))
669 nRead =
static_cast<int>(uRead);
683 osl::File *pFile =
static_cast<osl::File*
>(context);
694InputStreamTransformer::InputStreamTransformer(
URLParameter* urlParam,
715 UserData userData( urlParam,pDatabases );
719 const char* parameter[47];
720 OString parString[46];
723 parString[
last++] =
"Program";
724 OString aPureProgramm( urlParam->
getByName(
"Program" ) );
725 parString[
last++] =
"'" + aPureProgramm +
"'";
726 parString[
last++] =
"Database";
727 parString[
last++] =
"'" + urlParam->
getByName(
"DatabasePar" ) +
"'";
728 parString[
last++] =
"Id";
730 parString[
last++] =
"Path";
731 OString aPath( urlParam->
getByName(
"Path" ) );
732 parString[
last++] =
"'" + aPath +
"'";
734 OString aPureLanguage = urlParam->
getByName(
"Language" );
735 parString[
last++] =
"Language";
736 parString[
last++] =
"'" + aPureLanguage +
"'";
737 parString[
last++] =
"System";
738 parString[
last++] =
"'" + urlParam->
getByName(
"System" ) +
"'";
739 parString[
last++] =
"productname";
742 RTL_TEXTENCODING_UTF8 ) +
"'";
743 parString[
last++] =
"productversion";
744 parString[
last++] =
"'" +
746 RTL_TEXTENCODING_UTF8 ) +
"'";
748 parString[
last++] =
"imgtheme";
750 parString[
last++] =
"hp";
751 parString[
last++] =
"'" + urlParam->
getByName(
"HelpPrefix" ) +
"'";
753 if( !parString[last-1].isEmpty() )
755 parString[
last++] =
"sm";
756 parString[
last++] =
"'vnd.sun.star.help%3A%2F%2F'";
757 parString[
last++] =
"qm";
758 parString[
last++] =
"'%3F'";
759 parString[
last++] =
"es";
760 parString[
last++] =
"'%3D'";
761 parString[
last++] =
"am";
762 parString[
last++] =
"'%26'";
763 parString[
last++] =
"cl";
764 parString[
last++] =
"'%3A'";
765 parString[
last++] =
"sl";
766 parString[
last++] =
"'%2F'";
767 parString[
last++] =
"hm";
768 parString[
last++] =
"'%23'";
769 parString[
last++] =
"cs";
770 parString[
last++] =
"'css'";
772 parString[
last++] =
"vendorname";
773 parString[
last++] = OString(
"''");
774 parString[
last++] =
"vendorversion";
775 parString[
last++] = OString(
"''");
776 parString[
last++] =
"vendorshort";
777 parString[
last++] = OString(
"''");
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 );
792 bAddExtensionPath =
true;
798 ( aJar, urlParam->
get_language(), urlParam->
get_path(), &aExtensionPath, &aExtensionRegistryPath );
799 if( xNA.is() && !aExtensionPath.isEmpty() )
800 bAddExtensionPath =
true;
803 if( bAddExtensionPath )
808 OUString aOUExpandedExtensionPath = Databases::expandURL( aExtensionRegistryPath, xContext );
809 OString aExpandedExtensionPath =
OUStringToOString( aOUExpandedExtensionPath, osl_getThreadTextEncoding() );
811 parString[
last++] =
"ExtensionPath";
812 parString[
last++] =
"'" + aExpandedExtensionPath +
"'";
815 OString aPureExtensionId;
816 sal_Int32 iSlash = aPath.indexOf(
'/' );
818 aPureExtensionId = aPath.copy( 0, iSlash );
820 parString[
last++] =
"ExtensionId";
821 parString[
last++] =
"'" + aPureExtensionId +
"'";
824 for(
int i = 0;
i <
last; ++
i )
825 parameter[i] = parString[i].getStr();
826 parameter[
last] =
nullptr;
832 RTL_TEXTENCODING_UTF8) +
833 "main_transform.xsl";
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();
854 xsltSetSecurityPrefs(securityPrefs, XSLT_SECPREF_READ_FILE, xsltSecurityAllow);
855 if (xsltSetCtxtSecurityPrefs(securityPrefs, transformContext) == 0)
857 res = xsltApplyStylesheetUser(cur, doc, parameter,
nullptr,
nullptr, transformContext);
860 xmlChar *doc_txt_ptr=
nullptr;
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();
872 xmlPopInputCallbacks();
873 xmlPopInputCallbacks();
876 xsltFreeStylesheet(cur);
881Any 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 );
891void SAL_CALL InputStreamTransformer::acquire() noexcept
893 OWeakObject::acquire();
897void SAL_CALL InputStreamTransformer::release() noexcept
899 OWeakObject::release();
903sal_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_ )
913 if( 0 <= curr &&
aData.getLength() < curr )
914 aData.realloc( curr );
916 std::copy_n(buffer.getStr() + pos, curr,
aData.getArray());
919 return std::max(curr, 0);
923sal_Int32 SAL_CALL InputStreamTransformer::readSomeBytes(
Sequence< sal_Int8 >& aData,sal_Int32 nMaxBytesToRead )
925 return readBytes( aData,nMaxBytesToRead );
929void SAL_CALL InputStreamTransformer::skipBytes( sal_Int32 nBytesToSkip )
931 std::scoped_lock aGuard( m_aMutex );
932 while( nBytesToSkip-- ) ++
pos;
936sal_Int32 SAL_CALL InputStreamTransformer::available()
938 std::scoped_lock aGuard( m_aMutex );
939 return std::min<sal_Int64>(SAL_MAX_INT32, buffer.getLength() - pos);
943void SAL_CALL InputStreamTransformer::closeInput()
948void SAL_CALL InputStreamTransformer::seek( sal_Int64 location )
950 std::scoped_lock aGuard( m_aMutex );
952 throw IllegalArgumentException();
954 pos = sal::static_int_cast<sal_Int32>( location );
956 if( pos > buffer.getLength() )
957 pos = buffer.getLength();
961sal_Int64 SAL_CALL InputStreamTransformer::getPosition()
963 std::scoped_lock aGuard( m_aMutex );
964 return sal_Int64( pos );
968sal_Int64 SAL_CALL InputStreamTransformer::getLength()
970 std::scoped_lock aGuard( m_aMutex );
972 return buffer.getLength();
976void InputStreamTransformer::addToBuffer(
const char* buffer_,
int len_ )
978 std::scoped_lock aGuard( m_aMutex );
980 buffer.append( buffer_, len_ );
helpdatafileproxy::Hdf * nextHdf(OUString *o_pExtensionPath=nullptr, OUString *o_pExtensionRegistryPath=nullptr)
css::uno::Reference< css::container::XHierarchicalNameAccess > findJarFileForPath(const OUString &jar, const OUString &Language, const OUString &path, OUString *o_pExtensionPath=nullptr, OUString *o_pExtensionRegistryPath=nullptr)
OString getImageTheme() const
const OUString & getProductName() const
void cascadingStylesheet(const OUString &Language, OStringBuffer &buffer)
Returns the cascading style sheet used to format the HTML-output.
OUString getInstallPathAsURL()
StaticModuleInformation * getStaticInformationForModule(std::u16string_view Module, const OUString &Language)
void replaceName(OUString &oustring) const
void setActiveText(const OUString &Module, const OUString &Language, std::u16string_view Id, OStringBuffer &buffer)
Returns the active help text for the given module, language and id.
const OUString & getProductVersion() const
OUString getDatabase() const
OUString getTitle() const
OUString const & get_id()
const OUString & get_ExtensionRegistryPath() const
OString getByName(const char *par)
OUString const & get_dbpar() const
OUString m_aExtensionRegistryPath
void open(const css::uno::Reference< css::io::XActiveDataSink > &xDataSink)
const OUString & get_module() const
const OUString & get_system() const
bool name(bool modulePresent)
OUString const & get_language() const
OUString const & get_path()
OUString const & get_program()
const char * getData() const
bool getValueForKey(const OString &rKey, HDFData &rValue)
tools::SvRef< SvBaseLink > xSink
Sequence< sal_Int8 > aSeq
std::unique_ptr< sal_Int32[]> pData
constexpr OUStringLiteral aData
Reference< XComponentContext > getProcessComponentContext()
css::uno::Any SAL_CALL queryInterface(const css::uno::Type &rType, Interface1 *p1)
constexpr OUStringLiteral last
std::basic_string_view< charT, traits > trim(std::basic_string_view< charT, traits > str)
OString OUStringToOString(std::u16string_view str, ConnectionSettings const *settings)
UserData(OUString aPropertyPath, bool isReadOnly)
static int helpMatch(const char *URI)
static UserData * ugblData
static int zipMatch(const char *URI)
static int uriClose(void *context)
static int fileClose(void *context)
static int zipRead(void *context, char *buffer, int len)
static int fileMatch(const char *URI)
static void * zipOpen(SAL_UNUSED_PARAMETER const char *)
static void * helpOpen(const char *URI)
static int fileRead(void *context, char *buffer, int len)
static void * fileOpen(const char *URI)
static int helpRead(void *context, char *buffer, int len)