summaryrefslogtreecommitdiff
path: root/xmlhelp/source/cxxhelp/provider/urlparameter.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'xmlhelp/source/cxxhelp/provider/urlparameter.cxx')
-rw-r--r--xmlhelp/source/cxxhelp/provider/urlparameter.cxx1239
1 files changed, 1239 insertions, 0 deletions
diff --git a/xmlhelp/source/cxxhelp/provider/urlparameter.cxx b/xmlhelp/source/cxxhelp/provider/urlparameter.cxx
new file mode 100644
index 000000000000..9268ec19cd7f
--- /dev/null
+++ b/xmlhelp/source/cxxhelp/provider/urlparameter.cxx
@@ -0,0 +1,1239 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_xmlhelp.hxx"
+
+#define WORKAROUND_98119
+
+#ifdef WORKAROUND_98119
+#include "bufferedinputstream.hxx"
+#endif
+
+#include <string.h>
+#ifndef _VOS_DIAGNOSE_HXX_
+#include <vos/diagnose.hxx>
+#endif
+#include <osl/thread.h>
+#include <rtl/memory.h>
+#include <osl/file.hxx>
+#include <cppuhelper/weak.hxx>
+#include <cppuhelper/queryinterface.hxx>
+#include <comphelper/processfactory.hxx>
+#include <rtl/uri.hxx>
+#include <rtl/ustrbuf.hxx>
+#include <libxslt/xslt.h>
+#include <libxslt/transform.h>
+#include <libxslt/xsltutils.h>
+#include "db.hxx"
+#include <com/sun/star/io/XActiveDataSink.hpp>
+#include <com/sun/star/io/XInputStream.hpp>
+#include <com/sun/star/io/XSeekable.hpp>
+#include <com/sun/star/ucb/OpenCommandArgument2.hpp>
+#include <com/sun/star/ucb/OpenMode.hpp>
+#include <com/sun/star/ucb/XCommandProcessor.hpp>
+#include <com/sun/star/ucb/XCommandEnvironment.hpp>
+#include <com/sun/star/ucb/XContentIdentifier.hpp>
+#include <com/sun/star/ucb/XContentProvider.hpp>
+#include <com/sun/star/ucb/XContentIdentifierFactory.hpp>
+#include <com/sun/star/container/XHierarchicalNameAccess.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+
+#include "urlparameter.hxx"
+#include "databases.hxx"
+
+namespace chelp {
+
+ inline bool ascii_isDigit( sal_Unicode ch )
+ {
+ return ((ch >= 0x0030) && (ch <= 0x0039));
+ }
+
+ inline bool ascii_isLetter( sal_Unicode ch )
+ {
+ return ( ( (ch >= 0x0041) && (ch <= 0x005A) ) ||
+ ( (ch >= 0x0061) && (ch <= 0x007A) ) );
+ }
+
+ inline bool isLetterOrDigit( sal_Unicode ch )
+ {
+ return ascii_isLetter( ch ) || ascii_isDigit( ch );
+ }
+
+}
+
+using namespace cppu;
+using namespace com::sun::star::io;
+using namespace com::sun::star::uno;
+using namespace com::sun::star::lang;
+using namespace com::sun::star::ucb;
+using namespace com::sun::star::beans;
+using namespace com::sun::star::container;
+using namespace berkeleydbproxy;
+using namespace chelp;
+
+
+URLParameter::URLParameter( const rtl::OUString& aURL,
+ Databases* pDatabases )
+ throw( com::sun::star::ucb::IllegalIdentifierException )
+ : m_pDatabases( pDatabases ),
+ m_aURL( aURL )
+{
+ init( false );
+ parse();
+}
+
+
+bool URLParameter::isErrorDocument()
+{
+ bool bErrorDoc = false;
+
+ if( isFile() )
+ {
+ Reference< XHierarchicalNameAccess > xNA =
+ m_pDatabases->findJarFileForPath( get_jar(), get_language(), get_path() );
+ bErrorDoc = !xNA.is();
+ }
+
+ return bErrorDoc;
+}
+
+
+rtl::OString URLParameter::getByName( const char* par )
+{
+ rtl::OUString val;
+
+ if( strcmp( par,"Program" ) == 0 )
+ val = get_program();
+ else if( strcmp( par,"Database" ) == 0 )
+ val = get_module();
+ else if( strcmp( par,"DatabasePar" ) == 0 )
+ val = get_dbpar();
+ else if( strcmp( par,"Id" ) == 0 )
+ val = get_id();
+ else if( strcmp( par,"Path" ) == 0 )
+ val = get_path();
+ else if( strcmp( par,"Language" ) == 0 )
+ val = get_language();
+ else if( strcmp( par,"System" ) == 0 )
+ val = get_system();
+ else if( strcmp( par,"HelpPrefix" ) == 0 )
+ val = get_prefix();
+
+ return rtl::OString( val.getStr(),val.getLength(),RTL_TEXTENCODING_UTF8 );
+}
+
+
+rtl::OUString URLParameter::get_id()
+{
+ if( m_aId.compareToAscii("start") == 0 )
+ { // module is set
+ StaticModuleInformation* inf =
+ m_pDatabases->getStaticInformationForModule( get_module(),
+ get_language() );
+ if( inf )
+ m_aId = inf->get_id();
+
+ m_bStart = true;
+ }
+
+ return m_aId;
+}
+
+rtl::OUString URLParameter::get_tag()
+{
+ if( isFile() )
+ return get_the_tag();
+ else
+ return m_aTag;
+}
+
+
+rtl::OUString URLParameter::get_title()
+{
+ if( isFile() )
+ return get_the_title();
+ else if( m_aModule.compareToAscii("") != 0 )
+ {
+ StaticModuleInformation* inf =
+ m_pDatabases->getStaticInformationForModule( get_module(),
+ get_language() );
+ if( inf )
+ m_aTitle = inf->get_title();
+ }
+ else // This must be the root
+ m_aTitle = rtl::OUString::createFromAscii("root");
+
+ return m_aTitle;
+}
+
+
+rtl::OUString URLParameter::get_language()
+{
+ if( m_aLanguage.getLength() == 0 )
+ return m_aDefaultLanguage;
+
+ return m_aLanguage;
+}
+
+
+rtl::OUString URLParameter::get_program()
+{
+ if( ! m_aProgram.getLength() )
+ {
+ StaticModuleInformation* inf =
+ m_pDatabases->getStaticInformationForModule( get_module(),
+ get_language() );
+ if( inf )
+ m_aProgram = inf->get_program();
+ }
+ return m_aProgram;
+}
+
+
+void URLParameter::init( bool bDefaultLanguageIsInitialized )
+{
+ (void)bDefaultLanguageIsInitialized;
+
+ m_bBerkeleyRead = false;
+ m_bStart = false;
+ m_bUseDB = true;
+ m_nHitCount = 100; // The default maximum hitcount
+}
+
+
+rtl::OUString URLParameter::get_the_tag()
+{
+ if(m_bUseDB) {
+ if( ! m_bBerkeleyRead )
+ readBerkeley();
+
+ m_bBerkeleyRead = true;
+
+ return m_aTag;
+ }
+ else
+ return rtl::OUString();
+}
+
+
+
+rtl::OUString URLParameter::get_the_path()
+{
+ if(m_bUseDB) {
+ if( ! m_bBerkeleyRead )
+ readBerkeley();
+ m_bBerkeleyRead = true;
+
+ return m_aPath;
+ }
+ else
+ return get_id();
+}
+
+
+
+rtl::OUString URLParameter::get_the_title()
+{
+ if(m_bUseDB) {
+ if( ! m_bBerkeleyRead )
+ readBerkeley();
+ m_bBerkeleyRead = true;
+
+ return m_aTitle;
+ }
+ else
+ return rtl::OUString();
+}
+
+
+rtl::OUString URLParameter::get_the_jar()
+{
+ if(m_bUseDB) {
+ if( ! m_bBerkeleyRead )
+ readBerkeley();
+ m_bBerkeleyRead = true;
+
+ return m_aJar;
+ }
+ else
+ return get_module() + rtl::OUString::createFromAscii(".jar");
+}
+
+
+
+
+void URLParameter::readBerkeley()
+{
+ static rtl::OUString aQuestionMark( rtl::OUString::createFromAscii( "?" ) );
+
+ if( get_id().compareToAscii("") == 0 )
+ return;
+
+ rtl::OUString aModule = get_module();
+ rtl::OUString aLanguage = get_language();
+
+ DataBaseIterator aDbIt( *m_pDatabases, aModule, aLanguage, false );
+ bool bSuccess = false;
+
+ int nSize = 0;
+ const sal_Char* pData = NULL;
+
+ Dbt data;
+ DBData aDBData;
+ rtl::OUString aExtensionPath;
+ while( true )
+ {
+ Db* db = aDbIt.nextDb( &aExtensionPath );
+ if( !db )
+ break;
+
+ rtl::OString keyStr( m_aId.getStr(),m_aId.getLength(),RTL_TEXTENCODING_UTF8 );
+
+ DBHelp* pDBHelp = db->getDBHelp();
+ if( pDBHelp != NULL )
+ {
+ bSuccess = pDBHelp->getValueForKey( keyStr, aDBData );
+ if( bSuccess )
+ {
+ nSize = aDBData.getSize();
+ pData = aDBData.getData();
+ break;
+ }
+ }
+ else
+ {
+ Dbt key( static_cast< void* >( const_cast< sal_Char* >( keyStr.getStr() ) ),
+ keyStr.getLength() );
+ int err = db->get( 0,&key,&data,0 );
+ if( err == 0 )
+ {
+ bSuccess = true;
+ nSize = data.get_size();
+ pData = static_cast<sal_Char*>( data.get_data() );
+ break;
+ }
+ }
+ }
+
+ if( bSuccess )
+ {
+ DbtToStringConverter converter( pData, nSize );
+ m_aTitle = converter.getTitle();
+ m_pDatabases->replaceName( m_aTitle );
+ m_aPath = converter.getFile();
+ m_aJar = converter.getDatabase();
+ if( aExtensionPath.getLength() > 0 )
+ {
+ rtl::OUStringBuffer aExtendedJarStrBuf;
+ aExtendedJarStrBuf.append( aQuestionMark );
+ aExtendedJarStrBuf.append( aExtensionPath );
+ aExtendedJarStrBuf.append( aQuestionMark );
+ aExtendedJarStrBuf.append( m_aJar );
+ m_aJar = aExtendedJarStrBuf.makeStringAndClear();
+ }
+ m_aTag = converter.getHash();
+ }
+}
+
+
+
+// Class encapsulating the transformation of the XInputStream to XHTML
+
+
+class InputStreamTransformer
+ : public OWeakObject,
+ public XInputStream,
+ public XSeekable
+{
+public:
+
+ InputStreamTransformer( URLParameter* urlParam,
+ Databases* pDatatabases,
+ bool isRoot = false );
+
+ ~InputStreamTransformer();
+
+ virtual Any SAL_CALL queryInterface( const Type& rType ) throw( RuntimeException );
+ virtual void SAL_CALL acquire( void ) throw();
+ virtual void SAL_CALL release( void ) throw();
+
+ virtual sal_Int32 SAL_CALL readBytes( Sequence< sal_Int8 >& aData,sal_Int32 nBytesToRead )
+ throw( NotConnectedException,
+ BufferSizeExceededException,
+ IOException,
+ RuntimeException);
+
+ virtual sal_Int32 SAL_CALL readSomeBytes( Sequence< sal_Int8 >& aData,sal_Int32 nMaxBytesToRead )
+ throw( NotConnectedException,
+ BufferSizeExceededException,
+ IOException,
+ RuntimeException);
+
+ virtual void SAL_CALL skipBytes( sal_Int32 nBytesToSkip ) throw( NotConnectedException,
+ BufferSizeExceededException,
+ IOException,
+ RuntimeException );
+
+ virtual sal_Int32 SAL_CALL available( void ) throw( NotConnectedException,
+ IOException,
+ RuntimeException );
+
+ virtual void SAL_CALL closeInput( void ) throw( NotConnectedException,
+ IOException,
+ RuntimeException );
+
+ virtual void SAL_CALL seek( sal_Int64 location ) throw( IllegalArgumentException,
+ IOException,
+ RuntimeException );
+
+ virtual sal_Int64 SAL_CALL getPosition( void ) throw( IOException,RuntimeException );
+
+ virtual sal_Int64 SAL_CALL getLength( void ) throw( IOException,RuntimeException );
+
+ void addToBuffer( const char* buffer,int len );
+
+ sal_Int8* getData() const { return (sal_Int8*) buffer; }
+
+ sal_Int32 getLen() const { return sal_Int32( len ); }
+
+private:
+
+ osl::Mutex m_aMutex;
+
+ int len,pos;
+ char *buffer;
+};
+
+
+
+void URLParameter::open( const Reference< XMultiServiceFactory >& rxSMgr,
+ const Command& aCommand,
+ sal_Int32 CommandId,
+ const Reference< XCommandEnvironment >& Environment,
+ const Reference< XOutputStream >& xDataSink )
+{
+ (void)rxSMgr;
+ (void)aCommand;
+ (void)CommandId;
+ (void)Environment;
+
+ if( ! xDataSink.is() )
+ return;
+
+ if( isPicture() )
+ {
+ Reference< XInputStream > xStream;
+ Reference< XHierarchicalNameAccess > xNA =
+ m_pDatabases->jarFile( rtl::OUString::createFromAscii( "picture.jar" ),
+ get_language() );
+
+ rtl::OUString path = get_path();
+ if( xNA.is() )
+ {
+ try
+ {
+ Any aEntry = xNA->getByHierarchicalName( path );
+ Reference< XActiveDataSink > xSink;
+ if( ( aEntry >>= xSink ) && xSink.is() )
+ xStream = xSink->getInputStream();
+ }
+ catch ( NoSuchElementException & )
+ {
+ }
+ }
+ if( xStream.is() )
+ {
+ sal_Int32 ret;
+ Sequence< sal_Int8 > aSeq( 4096 );
+ while( true )
+ {
+ try
+ {
+ ret = xStream->readBytes( aSeq,4096 );
+ xDataSink->writeBytes( aSeq );
+ if( ret < 4096 )
+ break;
+ }
+ catch( const Exception& )
+ {
+ break;
+ }
+ }
+ }
+ }
+ else
+ {
+ // a standard document or else an active help text, plug in the new input stream
+ InputStreamTransformer* p = new InputStreamTransformer( this,m_pDatabases,isRoot() );
+ try
+ {
+ xDataSink->writeBytes( Sequence< sal_Int8 >( p->getData(),p->getLen() ) );
+ }
+ catch( const Exception& )
+ {
+ }
+ delete p;
+ }
+ xDataSink->closeOutput();
+}
+
+
+
+void URLParameter::open( const Reference< XMultiServiceFactory >& rxSMgr,
+ const Command& aCommand,
+ sal_Int32 CommandId,
+ const Reference< XCommandEnvironment >& Environment,
+ const Reference< XActiveDataSink >& xDataSink )
+{
+ (void)rxSMgr;
+ (void)aCommand;
+ (void)CommandId;
+ (void)Environment;
+
+ if( isPicture() )
+ {
+ Reference< XInputStream > xStream;
+ Reference< XHierarchicalNameAccess > xNA =
+ m_pDatabases->jarFile( rtl::OUString::createFromAscii( "picture.jar" ),
+ get_language() );
+
+ rtl::OUString path = get_path();
+ if( xNA.is() )
+ {
+ try
+ {
+ Any aEntry = xNA->getByHierarchicalName( path );
+ Reference< XActiveDataSink > xSink;
+ if( ( aEntry >>= xSink ) && xSink.is() )
+ xStream = xSink->getInputStream();
+ }
+ catch ( NoSuchElementException & )
+ {
+ }
+ }
+#ifdef WORKAROUND_98119
+ xDataSink->setInputStream( turnToSeekable(xStream) );
+#else
+ xDataSink->setInputStream( xStream );
+#endif
+ }
+ else
+ // a standard document or else an active help text, plug in the new input stream
+ xDataSink->setInputStream( new InputStreamTransformer( this,m_pDatabases,isRoot() ) );
+}
+
+
+// #include <stdio.h>
+
+void URLParameter::parse() throw( com::sun::star::ucb::IllegalIdentifierException )
+{
+ // fprintf(stdout,"url send to xmlhelp: %s\n",(rtl::OUStringToOString(m_aURL,RTL_TEXTENCODING_UTF8).getStr()));
+ m_aExpr = m_aURL;
+
+ sal_Int32 lstIdx = m_aExpr.lastIndexOf( sal_Unicode( '#' ) );
+ if( lstIdx != -1 )
+ m_aExpr = m_aExpr.copy( 0,lstIdx );
+
+ if( ! scheme() ||
+ ! name( module() ) ||
+ ! query() ||
+ ! m_aLanguage.getLength() ||
+ ! m_aSystem.getLength() )
+ throw com::sun::star::ucb::IllegalIdentifierException();
+}
+
+
+bool URLParameter::scheme()
+{
+ // Correct extension help links as sometimes the
+ // module is missing resulting in a misformed URL
+ if( m_aExpr.compareToAscii( "vnd.sun.star.help:///", 21 ) == 0 )
+ {
+ sal_Int32 nLen = m_aExpr.getLength();
+ rtl::OUString aLastStr = m_aExpr.copy( nLen - 6 );
+ if( aLastStr.compareToAscii( "DbPAR=" ) == 0 )
+ {
+ rtl::OUString aNewExpr = m_aExpr.copy( 0, 20 );
+ rtl::OUString aSharedStr = rtl::OUString::createFromAscii( "shared" );
+ aNewExpr += aSharedStr;
+ aNewExpr += m_aExpr.copy( 20 );
+ aNewExpr += aSharedStr;
+ m_aExpr = aNewExpr;
+ }
+ }
+
+ for( sal_Int32 nPrefixLen = 20 ; nPrefixLen >= 18 ; --nPrefixLen )
+ {
+ if( m_aExpr.compareToAscii( "vnd.sun.star.help://", nPrefixLen ) == 0 )
+ {
+ m_aExpr = m_aExpr.copy( nPrefixLen );
+ return true;
+ }
+ }
+ return false;
+}
+
+
+bool URLParameter::module()
+{
+ sal_Int32 idx = 0,length = m_aExpr.getLength();
+
+ while( idx < length && isLetterOrDigit( (m_aExpr.getStr())[idx] ) )
+ ++idx;
+
+ if( idx != 0 )
+ {
+ m_aModule = m_aExpr.copy( 0,idx );
+ m_aExpr = m_aExpr.copy( idx );
+ return true;
+ }
+ else
+ return false;
+}
+
+
+
+bool URLParameter::name( bool modulePresent )
+{
+ // if modulepresent, a name may be present, but must not
+
+ sal_Int32 length = m_aExpr.getLength();
+
+ if( length != 0 && (m_aExpr.getStr())[0] == sal_Unicode( '/' ) )
+ {
+ sal_Int32 idx = 1;
+ while( idx < length && (m_aExpr.getStr())[idx] != '?' )
+// ( isLetterOrDigit( (m_aExpr.getStr())[idx] )
+// || (m_aExpr.getStr())[idx] == '/'
+// || (m_aExpr.getStr())[idx] == '.' ))
+ ++idx;
+
+ if( idx != 1 && ! modulePresent )
+ return false;
+ else
+ {
+ m_aId = m_aExpr.copy( 1,idx-1 );
+ m_aExpr = m_aExpr.copy( idx );
+ }
+ }
+
+// fprintf(stdout,"id %s\n",(rtl::OUStringToOString(m_aId,RTL_TEXTENCODING_UTF8).getStr()));
+ return true;
+}
+
+
+bool URLParameter::query()
+{
+ rtl::OUString query_;
+
+ if( ! m_aExpr.getLength() )
+ return true;
+ else if( (m_aExpr.getStr())[0] == sal_Unicode( '?' ) )
+ query_ = m_aExpr.copy( 1 ).trim();
+ else
+ return false;
+
+
+ bool ret = true;
+ sal_Int32 delimIdx,equalIdx;
+ rtl::OUString parameter,value;
+
+ while( query_.getLength() != 0 )
+ {
+ delimIdx = query_.indexOf( sal_Unicode( '&' ) );
+ equalIdx = query_.indexOf( sal_Unicode( '=' ) );
+ parameter = query_.copy( 0,equalIdx ).trim();
+ if( delimIdx == -1 )
+ {
+ value = query_.copy( equalIdx + 1 ).trim();
+ query_ = rtl::OUString();
+ }
+ else
+ {
+ value = query_.copy( equalIdx+1,delimIdx - equalIdx - 1 ).trim();
+ query_ = query_.copy( delimIdx+1 ).trim();
+ }
+
+ if( parameter.compareToAscii( "Language" ) == 0 )
+ m_aLanguage = value;
+ else if( parameter.compareToAscii( "Device" ) == 0 )
+ m_aDevice = value;
+ else if( parameter.compareToAscii( "Program" ) == 0 )
+ m_aProgram = value;
+ else if( parameter.compareToAscii( "Eid" ) == 0 )
+ m_aEid = value;
+ else if( parameter.compareToAscii( "UseDB" ) == 0 )
+ m_bUseDB = ! ( value.compareToAscii("no") == 0 );
+ else if( parameter.compareToAscii( "DbPAR" ) == 0 )
+ m_aDbPar = value;
+ else if( parameter.compareToAscii( "Query" ) == 0 )
+ {
+ if( ! m_aQuery.getLength() )
+ m_aQuery = value;
+ else
+ m_aQuery += ( rtl::OUString::createFromAscii( " " ) + value );
+ }
+ else if( parameter.compareToAscii( "Scope" ) == 0 )
+ m_aScope = value;
+ else if( parameter.compareToAscii( "System" ) == 0 )
+ m_aSystem = value;
+ else if( parameter.compareToAscii( "HelpPrefix" ) == 0 )
+ m_aPrefix = rtl::Uri::decode(
+ value,
+ rtl_UriDecodeWithCharset,
+ RTL_TEXTENCODING_UTF8 );
+ else if( parameter.compareToAscii( "HitCount" ) == 0 )
+ m_nHitCount = value.toInt32();
+ else if( parameter.compareToAscii( "Active" ) == 0 )
+ m_aActive = value;
+ else
+ ret = false;
+ }
+
+ return ret;
+}
+
+struct UserData {
+
+ UserData( InputStreamTransformer* pTransformer,
+ URLParameter* pInitial,
+ Databases* pDatabases )
+ : m_pTransformer( pTransformer ),
+ m_pDatabases( pDatabases ),
+ m_pInitial( pInitial )
+ {
+ }
+
+ InputStreamTransformer* m_pTransformer;
+ Databases* m_pDatabases;
+ URLParameter* m_pInitial;
+};
+
+UserData *ugblData = 0;
+
+extern "C" {
+
+static int
+fileMatch(const char * URI) {
+ if ((URI != NULL) && !strncmp(URI, "file:/", 6))
+ return 1;
+ return 0;
+}
+
+static int
+zipMatch(const char * URI) {
+ if ((URI != NULL) && !strncmp(URI, "vnd.sun.star.zip:/", 18))
+ return 1;
+ return 0;
+}
+
+static int
+helpMatch(const char * URI) {
+ if ((URI != NULL) && !strncmp(URI, "vnd.sun.star.help:/", 19))
+ return 1;
+ return 0;
+}
+
+static void *
+fileOpen(const char *URI) {
+ osl::File *pRet = new osl::File(rtl::OUString(URI, strlen(URI), RTL_TEXTENCODING_UTF8));
+ pRet->open(OpenFlag_Read);
+ return pRet;
+}
+
+static void *
+zipOpen(const char * /*URI*/) {
+ rtl::OUString language,jar,path;
+
+ if( ugblData->m_pInitial->get_eid().getLength() )
+ return (void*)(new Reference< XHierarchicalNameAccess >);
+ else
+ {
+ jar = ugblData->m_pInitial->get_jar();
+ language = ugblData->m_pInitial->get_language();
+ path = ugblData->m_pInitial->get_path();
+ }
+
+ Reference< XHierarchicalNameAccess > xNA =
+ ugblData->m_pDatabases->findJarFileForPath( jar, language, path );
+
+ Reference< XInputStream > xInputStream;
+
+ if( xNA.is() )
+ {
+ try
+ {
+ Any aEntry = xNA->getByHierarchicalName( path );
+ Reference< XActiveDataSink > xSink;
+ if( ( aEntry >>= xSink ) && xSink.is() )
+ xInputStream = xSink->getInputStream();
+ }
+ catch ( NoSuchElementException & )
+ {
+ }
+ }
+
+ if( xInputStream.is() )
+ {
+ return new Reference<XInputStream>(xInputStream);
+ }
+ return 0;
+}
+
+static void *
+helpOpen(const char * URI) {
+ rtl::OUString language,jar,path;
+
+ URLParameter urlpar( rtl::OUString::createFromAscii( URI ),
+ ugblData->m_pDatabases );
+
+ jar = urlpar.get_jar();
+ language = urlpar.get_language();
+ path = urlpar.get_path();
+
+ Reference< XHierarchicalNameAccess > xNA =
+ ugblData->m_pDatabases->findJarFileForPath( jar, language, path );
+
+ Reference< XInputStream > xInputStream;
+
+ if( xNA.is() )
+ {
+ try
+ {
+ Any aEntry = xNA->getByHierarchicalName( path );
+ Reference< XActiveDataSink > xSink;
+ if( ( aEntry >>= xSink ) && xSink.is() )
+ xInputStream = xSink->getInputStream();
+ }
+ catch ( NoSuchElementException & )
+ {
+ }
+ }
+
+ if( xInputStream.is() )
+ return new Reference<XInputStream>(xInputStream);
+ return 0;
+}
+
+static int
+helpRead(void * context, char * buffer, int len) {
+ Reference< XInputStream > *pRef = (Reference< XInputStream >*)context;
+
+ Sequence< sal_Int8 > aSeq;
+ len = (*pRef)->readBytes( aSeq,len);
+ memcpy(buffer, aSeq.getConstArray(), len);
+
+ return len;
+}
+
+static int
+zipRead(void * context, char * buffer, int len) {
+ if( ugblData->m_pInitial->get_eid().getLength() )
+ {
+ ugblData->m_pDatabases->popupDocument( ugblData->m_pInitial,&buffer,&len);
+ return len;
+ }
+ else
+ return helpRead(context, buffer, len);
+}
+
+static int
+fileRead(void * context, char * buffer, int len) {
+ int nRead = 0;
+ osl::File *pFile = (osl::File*)context;
+ if (pFile)
+ {
+ sal_uInt64 uRead = 0;
+ if (osl::FileBase::E_None == pFile->read(buffer, len, uRead))
+ nRead = static_cast<int>(uRead);
+ }
+ return nRead;
+}
+
+static int
+uriClose(void * context) {
+ Reference< XInputStream > *pRef = (Reference< XInputStream >*)context;
+ delete pRef;
+ return 0;
+}
+
+static int
+fileClose(void * context) {
+ osl::File *pFile = (osl::File*)context;
+ if (pFile)
+ {
+ pFile->close();
+ delete pFile;
+ }
+ return 0;
+}
+
+} // extern "C"
+
+/*
+// For debugging only
+extern "C" void StructuredXMLErrorFunction(void *userData, xmlErrorPtr error)
+{
+ (void)userData;
+ (void)error;
+
+ // Reset error handler
+ xmlSetStructuredErrorFunc( NULL, NULL );
+}
+*/
+
+InputStreamTransformer::InputStreamTransformer( URLParameter* urlParam,
+ Databases* pDatabases,
+ bool isRoot )
+ : len( 0 ),
+ pos( 0 ),
+ buffer( new char[1] ) // Initializing with one element to avoid gcc compiler warning
+{
+ if( isRoot )
+ {
+ delete[] buffer;
+ pDatabases->cascadingStylesheet( urlParam->get_language(),
+ &buffer,
+ &len );
+ }
+ else if( urlParam->isActive() )
+ {
+ delete[] buffer;
+ pDatabases->setActiveText( urlParam->get_module(),
+ urlParam->get_language(),
+ urlParam->get_id(),
+ &buffer,
+ &len );
+ }
+ else
+ {
+ UserData userData( this,urlParam,pDatabases );
+
+ // Uses the implementation detail, that rtl::OString::getStr returns a zero terminated character-array
+
+ const char* parameter[47];
+ rtl::OString parString[46];
+ int last = 0;
+
+ parString[last++] = "Program";
+ rtl::OString aPureProgramm( urlParam->getByName( "Program" ) );
+ parString[last++] = rtl::OString('\'') + aPureProgramm + rtl::OString('\'');
+ parString[last++] = "Database";
+ parString[last++] = rtl::OString('\'') + urlParam->getByName( "DatabasePar" ) + rtl::OString('\'');
+ parString[last++] = "Id";
+ parString[last++] = rtl::OString('\'') + urlParam->getByName( "Id" ) + rtl::OString('\'');
+ parString[last++] = "Path";
+ rtl::OString aPath( urlParam->getByName( "Path" ) );
+ parString[last++] = rtl::OString('\'') + aPath + rtl::OString('\'');
+
+ rtl::OString aPureLanguage = urlParam->getByName( "Language" );
+ parString[last++] = "Language";
+ parString[last++] = rtl::OString('\'') + aPureLanguage + rtl::OString('\'');
+ parString[last++] = "System";
+ parString[last++] = rtl::OString('\'') + urlParam->getByName( "System" ) + rtl::OString('\'');
+ parString[last++] = "productname";
+ parString[last++] = rtl::OString('\'') + rtl::OString(
+ pDatabases->getProductName().getStr(),
+ pDatabases->getProductName().getLength(),
+ RTL_TEXTENCODING_UTF8 ) + rtl::OString('\'');
+ parString[last++] = "productversion";
+ parString[last++] = rtl::OString('\'') +
+ rtl::OString( pDatabases->getProductVersion().getStr(),
+ pDatabases->getProductVersion().getLength(),
+ RTL_TEXTENCODING_UTF8 ) + rtl::OString('\'');
+
+ parString[last++] = "imgrepos";
+ parString[last++] = rtl::OString('\'') + pDatabases->getImagesZipFileURL() + rtl::OString('\'');
+ parString[last++] = "hp";
+ parString[last++] = rtl::OString('\'') + urlParam->getByName( "HelpPrefix" ) + rtl::OString('\'');
+
+ if( parString[last-1].getLength() )
+ {
+ parString[last++] = "sm";
+ parString[last++] = "'vnd.sun.star.help%3A%2F%2F'";
+ parString[last++] = "qm";
+ parString[last++] = "'%3F'";
+ parString[last++] = "es";
+ parString[last++] = "'%3D'";
+ parString[last++] = "am";
+ parString[last++] = "'%26'";
+ parString[last++] = "cl";
+ parString[last++] = "'%3A'";
+ parString[last++] = "sl";
+ parString[last++] = "'%2F'";
+ parString[last++] = "hm";
+ parString[last++] = "'%23'";
+ parString[last++] = "cs";
+ parString[last++] = "'css'";
+
+ parString[last++] = "vendorname";
+ parString[last++] = rtl::OString("''");
+ parString[last++] = "vendorversion";
+ parString[last++] = rtl::OString("''");
+ parString[last++] = "vendorshort";
+ parString[last++] = rtl::OString("''");
+ }
+
+ // Do we need to add extension path?
+ ::rtl::OUString aExtensionPath;
+ rtl::OUString aJar = urlParam->get_jar();
+
+ bool bAddExtensionPath = false;
+ sal_Int32 nQuestionMark1 = aJar.indexOf( sal_Unicode('?') );
+ sal_Int32 nQuestionMark2 = aJar.lastIndexOf( sal_Unicode('?') );
+ if( nQuestionMark1 != -1 && nQuestionMark2 != -1 && nQuestionMark1 != nQuestionMark2 )
+ {
+ aExtensionPath = aJar.copy( nQuestionMark1 + 1, nQuestionMark2 - nQuestionMark1 - 1 );
+ bAddExtensionPath = true;
+ }
+ else
+ {
+ // Path not yet specified, search directly
+ Reference< XHierarchicalNameAccess > xNA = pDatabases->findJarFileForPath
+ ( aJar, urlParam->get_language(), urlParam->get_path(), &aExtensionPath );
+ if( xNA.is() && aExtensionPath.getLength() )
+ bAddExtensionPath = true;
+ }
+
+ if( bAddExtensionPath )
+ {
+ Reference< XMultiServiceFactory > xFactory = comphelper::getProcessServiceFactory();
+ Reference< XPropertySet > xProps( xFactory, UNO_QUERY );
+ OSL_ASSERT( xProps.is() );
+ Reference< XComponentContext > xContext;
+ if (xProps.is())
+ {
+ xProps->getPropertyValue(
+ ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("DefaultContext") ) ) >>= xContext;
+ }
+ if( !xContext.is() )
+ {
+ throw RuntimeException(
+ ::rtl::OUString::createFromAscii( "InputStreamTransformer::InputStreamTransformer(), no XComponentContext" ),
+ Reference< XInterface >() );
+ }
+
+ rtl::OUString aOUExpandedExtensionPath = Databases::expandURL( aExtensionPath, xContext );
+ rtl::OString aExpandedExtensionPath = rtl::OUStringToOString( aOUExpandedExtensionPath, osl_getThreadTextEncoding() );
+
+ parString[last++] = "ExtensionPath";
+ parString[last++] = rtl::OString('\'') + aExpandedExtensionPath + rtl::OString('\'');
+
+ // ExtensionId
+ rtl::OString aPureExtensionId;
+ sal_Int32 iSlash = aPath.indexOf( '/' );
+ if( iSlash != -1 )
+ aPureExtensionId = aPath.copy( 0, iSlash );
+
+ parString[last++] = "ExtensionId";
+ parString[last++] = rtl::OString('\'') + aPureExtensionId + rtl::OString('\'');
+ }
+
+ for( int i = 0; i < last; ++i )
+ parameter[i] = parString[i].getStr();
+ parameter[last] = 0;
+
+ rtl::OUString xslURL = pDatabases->getInstallPathAsURL();
+
+ rtl::OString xslURLascii(
+ xslURL.getStr(),
+ xslURL.getLength(),
+ RTL_TEXTENCODING_UTF8);
+ xslURLascii += "main_transform.xsl";
+
+ ugblData = &userData;
+
+ xmlInitParser();
+ xmlRegisterInputCallbacks(zipMatch, zipOpen, zipRead, uriClose);
+ xmlRegisterInputCallbacks(helpMatch, helpOpen, helpRead, uriClose);
+ xmlRegisterInputCallbacks(fileMatch, fileOpen, fileRead, fileClose);
+ //xmlSetStructuredErrorFunc( NULL, (xmlStructuredErrorFunc)StructuredXMLErrorFunction );
+
+ xsltStylesheetPtr cur =
+ xsltParseStylesheetFile((const xmlChar *)xslURLascii.getStr());
+
+ xmlDocPtr doc = xmlParseFile("vnd.sun.star.zip:/");
+
+ xmlDocPtr res = xsltApplyStylesheet(cur, doc, parameter);
+ if (res)
+ {
+ xmlChar *doc_txt_ptr=0;
+ int doc_txt_len;
+ xsltSaveResultToString(&doc_txt_ptr, &doc_txt_len, res, cur);
+ addToBuffer((const char*)doc_txt_ptr, doc_txt_len);
+ xmlFree(doc_txt_ptr);
+ }
+ xmlPopInputCallbacks(); //filePatch
+ xmlPopInputCallbacks(); //helpPatch
+ xmlPopInputCallbacks(); //zipMatch
+ xmlFreeDoc(res);
+ xmlFreeDoc(doc);
+ xsltFreeStylesheet(cur);
+ }
+}
+
+
+InputStreamTransformer::~InputStreamTransformer()
+{
+ delete[] buffer;
+}
+
+
+Any SAL_CALL InputStreamTransformer::queryInterface( const Type& rType ) throw( RuntimeException )
+{
+ Any aRet = ::cppu::queryInterface( rType,
+ SAL_STATIC_CAST( XInputStream*,this ),
+ SAL_STATIC_CAST( XSeekable*,this ) );
+
+ return aRet.hasValue() ? aRet : OWeakObject::queryInterface( rType );
+}
+
+
+
+void SAL_CALL InputStreamTransformer::acquire( void ) throw()
+{
+ OWeakObject::acquire();
+}
+
+
+
+void SAL_CALL InputStreamTransformer::release( void ) throw()
+{
+ OWeakObject::release();
+}
+
+
+
+sal_Int32 SAL_CALL InputStreamTransformer::readBytes( Sequence< sal_Int8 >& aData,sal_Int32 nBytesToRead )
+ throw( NotConnectedException,
+ BufferSizeExceededException,
+ IOException,
+ RuntimeException)
+{
+ osl::MutexGuard aGuard( m_aMutex );
+
+ int curr,available_ = len-pos;
+ if( nBytesToRead <= available_ )
+ curr = nBytesToRead;
+ else
+ curr = available_;
+
+ if( 0 <= curr && aData.getLength() < curr )
+ aData.realloc( curr );
+
+ for( int k = 0; k < curr; ++k )
+ aData[k] = buffer[pos++];
+
+ return curr > 0 ? curr : 0;
+}
+
+
+sal_Int32 SAL_CALL InputStreamTransformer::readSomeBytes( Sequence< sal_Int8 >& aData,sal_Int32 nMaxBytesToRead )
+ throw( NotConnectedException,
+ BufferSizeExceededException,
+ IOException,
+ RuntimeException)
+{
+ return readBytes( aData,nMaxBytesToRead );
+}
+
+
+
+void SAL_CALL InputStreamTransformer::skipBytes( sal_Int32 nBytesToSkip ) throw( NotConnectedException,
+ BufferSizeExceededException,
+ IOException,
+ RuntimeException )
+{
+ osl::MutexGuard aGuard( m_aMutex );
+ while( nBytesToSkip-- ) ++pos;
+}
+
+
+
+sal_Int32 SAL_CALL InputStreamTransformer::available( void ) throw( NotConnectedException,
+ IOException,
+ RuntimeException )
+{
+ osl::MutexGuard aGuard( m_aMutex );
+ return len-pos > 0 ? len - pos : 0 ;
+}
+
+
+
+void SAL_CALL InputStreamTransformer::closeInput( void ) throw( NotConnectedException,
+ IOException,
+ RuntimeException )
+{
+}
+
+
+
+void SAL_CALL InputStreamTransformer::seek( sal_Int64 location ) throw( IllegalArgumentException,
+ IOException,
+ RuntimeException )
+{
+ osl::MutexGuard aGuard( m_aMutex );
+ if( location < 0 )
+ throw IllegalArgumentException();
+ else
+ pos = sal::static_int_cast<sal_Int32>( location );
+
+ if( pos > len )
+ pos = len;
+}
+
+
+
+sal_Int64 SAL_CALL InputStreamTransformer::getPosition( void ) throw( IOException,
+ RuntimeException )
+{
+ osl::MutexGuard aGuard( m_aMutex );
+ return sal_Int64( pos );
+}
+
+
+
+sal_Int64 SAL_CALL InputStreamTransformer::getLength( void ) throw( IOException,RuntimeException )
+{
+ osl::MutexGuard aGuard( m_aMutex );
+
+ return len;
+}
+
+
+void InputStreamTransformer::addToBuffer( const char* buffer_,int len_ )
+{
+ osl::MutexGuard aGuard( m_aMutex );
+
+ char* tmp = buffer;
+ buffer = new char[ len+len_ ];
+ rtl_copyMemory( (void*)(buffer),(void*)(tmp),sal_uInt32( len ) );
+ rtl_copyMemory( (void*)(buffer+len),(void*)(buffer_),sal_uInt32( len_ ) );
+ delete[] tmp;
+ len += len_;
+}