/************************************************************************* * * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * Copyright 2008 by Sun Microsystems, Inc. * * OpenOffice.org - a multi-platform office productivity suite * * $RCSfile: urlparameter.cxx,v $ * $Revision: 1.44 $ * * 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 * * 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 #ifndef _VOS_DIAGNOSE_HXX_ #include #endif #include #include #include #include #include #include #include #include #include #include #include #include "db.hxx" #include #include #include #include #include #include #include #include #include #include #include #include #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; Dbt data; 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 ); 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; break; } } if( bSuccess ) { DbtToStringConverter converter( static_cast< sal_Char* >( data.get_data() ), data.get_size() ); 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 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 pkgMatch(const char * URI) { if ((URI != NULL) && !strncmp(URI, "vnd.sun.star.pkg:/", 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 * pkgOpen(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); } 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); 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 pkgRead(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(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('\'') + rtl::OString( pDatabases->getVendorName().getStr(), pDatabases->getVendorName().getLength(), RTL_TEXTENCODING_UTF8 ) + rtl::OString('\''); parString[last++] = "vendorversion"; parString[last++] = rtl::OString('\'') + rtl::OString( pDatabases->getVendorVersion().getStr(), pDatabases->getVendorVersion().getLength(), RTL_TEXTENCODING_UTF8 ) + rtl::OString('\''); parString[last++] = "vendorshort"; parString[last++] = rtl::OString('\'') + rtl::OString( pDatabases->getVendorShort().getStr(), pDatabases->getVendorShort().getLength(), RTL_TEXTENCODING_UTF8 ) + 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() ); // Add extension language part rtl::OString aExtensionLanguage = aPureLanguage; if( aExtensionLanguage.getLength() > 2 ) aExtensionLanguage = aExtensionLanguage.copy( 0, 2 ); aExpandedExtensionPath += rtl::OString('/'); aExpandedExtensionPath += aExtensionLanguage; 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; xmlRegisterInputCallbacks(pkgMatch, pkgOpen, pkgRead, 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.pkg:/"); 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(); //pkgMatch 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( 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_; }