blob: 8f8ee4dcccdfce9554204ea5169f0e2b92e2eb02 [file] [log] [blame]
/**************************************************************
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the 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 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_bHelpDataFileRead = 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_bHelpDataFileRead )
readHelpDataFile();
m_bHelpDataFileRead = true;
return m_aTag;
}
else
return rtl::OUString();
}
rtl::OUString URLParameter::get_the_path()
{
if(m_bUseDB) {
if( ! m_bHelpDataFileRead )
readHelpDataFile();
m_bHelpDataFileRead = true;
return m_aPath;
}
else
return get_id();
}
rtl::OUString URLParameter::get_the_title()
{
if(m_bUseDB) {
if( ! m_bHelpDataFileRead )
readHelpDataFile();
m_bHelpDataFileRead = true;
return m_aTitle;
}
else
return rtl::OUString();
}
rtl::OUString URLParameter::get_the_jar()
{
if(m_bUseDB) {
if( ! m_bHelpDataFileRead )
readHelpDataFile();
m_bHelpDataFileRead = true;
return m_aJar;
}
else
return get_module() + rtl::OUString::createFromAscii(".jar");
}
void URLParameter::readHelpDataFile()
{
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;
helpdatafileproxy::HDFData aHDFData;
rtl::OUString aExtensionPath;
rtl::OUString aExtensionRegistryPath;
while( true )
{
helpdatafileproxy::Hdf* pHdf = aDbIt.nextHdf( &aExtensionPath, &aExtensionRegistryPath );
if( !pHdf )
break;
rtl::OString keyStr( m_aId.getStr(),m_aId.getLength(),RTL_TEXTENCODING_UTF8 );
bSuccess = pHdf->getValueForKey( keyStr, aHDFData );
if( bSuccess )
{
nSize = aHDFData.getSize();
pData = aHDFData.getData();
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_aExtensionRegistryPath = aExtensionRegistryPath;
}
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;
rtl::OUString aExtensionRegistryPath;
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 );
aExtensionRegistryPath = urlParam->get_ExtensionRegistryPath();
bAddExtensionPath = true;
}
else
{
// Path not yet specified, search directly
Reference< XHierarchicalNameAccess > xNA = pDatabases->findJarFileForPath
( aJar, urlParam->get_language(), urlParam->get_path(), &aExtensionPath, &aExtensionRegistryPath );
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( aExtensionRegistryPath, 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_;
}