LCOV - code coverage report
Current view: top level - xmlhelp/source/cxxhelp/provider - urlparameter.cxx (source / functions) Hit Total Coverage
Test: commit c8344322a7af75b84dd3ca8f78b05543a976dfd5 Lines: 152 520 29.2 %
Date: 2015-06-13 12:38:46 Functions: 22 53 41.5 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*
       3             :  * This file is part of the LibreOffice project.
       4             :  *
       5             :  * This Source Code Form is subject to the terms of the Mozilla Public
       6             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       7             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       8             :  *
       9             :  * This file incorporates work covered by the following license notice:
      10             :  *
      11             :  *   Licensed to the Apache Software Foundation (ASF) under one or more
      12             :  *   contributor license agreements. See the NOTICE file distributed
      13             :  *   with this work for additional information regarding copyright
      14             :  *   ownership. The ASF licenses this file to you under the Apache
      15             :  *   License, Version 2.0 (the "License"); you may not use this file
      16             :  *   except in compliance with the License. You may obtain a copy of
      17             :  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
      18             :  */
      19             : 
      20             : 
      21             : #include "bufferedinputstream.hxx"
      22             : 
      23             : #include <string.h>
      24             : #include <osl/diagnose.hxx>
      25             : #include <osl/thread.h>
      26             : #include <osl/file.hxx>
      27             : #include <cppuhelper/weak.hxx>
      28             : #include <cppuhelper/queryinterface.hxx>
      29             : #include <comphelper/processfactory.hxx>
      30             : #include <rtl/uri.hxx>
      31             : #include <rtl/ustrbuf.hxx>
      32             : #include <libxslt/xslt.h>
      33             : #include <libxslt/transform.h>
      34             : #include <libxslt/xsltutils.h>
      35             : #include "db.hxx"
      36             : #include <com/sun/star/io/XActiveDataSink.hpp>
      37             : #include <com/sun/star/io/XInputStream.hpp>
      38             : #include <com/sun/star/io/XSeekable.hpp>
      39             : #include <com/sun/star/ucb/OpenCommandArgument2.hpp>
      40             : #include <com/sun/star/ucb/OpenMode.hpp>
      41             : #include <com/sun/star/ucb/XCommandProcessor.hpp>
      42             : #include <com/sun/star/ucb/XCommandEnvironment.hpp>
      43             : #include <com/sun/star/ucb/XContentIdentifier.hpp>
      44             : #include <com/sun/star/ucb/XContentProvider.hpp>
      45             : #include <com/sun/star/ucb/XContentIdentifierFactory.hpp>
      46             : #include <com/sun/star/container/XHierarchicalNameAccess.hpp>
      47             : 
      48             : #include "urlparameter.hxx"
      49             : #include "databases.hxx"
      50             : 
      51             : namespace chelp {
      52             : 
      53        2939 :     inline bool ascii_isDigit( sal_Unicode ch )
      54             :     {
      55        2939 :         return ((ch >= 0x0030) && (ch <= 0x0039));
      56             :     }
      57             : 
      58       23100 :     inline bool ascii_isLetter( sal_Unicode ch )
      59             :     {
      60       43261 :         return ( ( (ch >= 0x0041) && (ch <= 0x005A) ) ||
      61       43261 :                  ( (ch >= 0x0061) && (ch <= 0x007A) ) );
      62             :     }
      63             : 
      64       23100 :     inline bool isLetterOrDigit( sal_Unicode ch )
      65             :     {
      66       23100 :         return ascii_isLetter( ch ) || ascii_isDigit( ch );
      67             :     }
      68             : 
      69             : }
      70             : 
      71             : using namespace cppu;
      72             : using namespace com::sun::star::io;
      73             : using namespace com::sun::star::uno;
      74             : using namespace com::sun::star::lang;
      75             : using namespace com::sun::star::ucb;
      76             : using namespace com::sun::star::beans;
      77             : using namespace com::sun::star::container;
      78             : using namespace chelp;
      79             : 
      80             : 
      81        2939 : URLParameter::URLParameter( const OUString& aURL,
      82             :                             Databases* pDatabases )
      83             :     throw( com::sun::star::ucb::IllegalIdentifierException )
      84             :     : m_pDatabases( pDatabases ),
      85        2939 :       m_aURL( aURL )
      86             : {
      87        2939 :     init( false );
      88        2939 :     parse();
      89        2939 : }
      90             : 
      91             : 
      92           0 : bool URLParameter::isErrorDocument()
      93             : {
      94           0 :     bool bErrorDoc = false;
      95             : 
      96           0 :     if( isFile() )
      97             :     {
      98             :         Reference< XHierarchicalNameAccess > xNA =
      99           0 :             m_pDatabases->findJarFileForPath( get_jar(), get_language(), get_path() );
     100           0 :         bErrorDoc = !xNA.is();
     101             :     }
     102             : 
     103           0 :     return bErrorDoc;
     104             : }
     105             : 
     106             : 
     107           0 : OString URLParameter::getByName( const char* par )
     108             : {
     109           0 :     OUString val;
     110             : 
     111           0 :     if( strcmp( par,"Program" ) == 0 )
     112           0 :         val = get_program();
     113           0 :     else if( strcmp( par,"Database" ) == 0 )
     114           0 :         val = get_module();
     115           0 :     else if( strcmp( par,"DatabasePar" ) == 0 )
     116           0 :         val = get_dbpar();
     117           0 :     else if( strcmp( par,"Id" ) == 0 )
     118           0 :         val = get_id();
     119           0 :     else if( strcmp( par,"Path" ) == 0 )
     120           0 :         val = get_path();
     121           0 :     else if( strcmp( par,"Language" ) == 0 )
     122           0 :         val = get_language();
     123           0 :     else if( strcmp( par,"System" ) == 0 )
     124           0 :         val = get_system();
     125           0 :     else if( strcmp( par,"HelpPrefix" ) == 0 )
     126           0 :         val = get_prefix();
     127             : 
     128           0 :     return OString( val.getStr(),val.getLength(),RTL_TEXTENCODING_UTF8 );
     129             : }
     130             : 
     131             : 
     132        2900 : OUString URLParameter::get_id()
     133             : {
     134        2900 :     if( m_aId == "start" )
     135             :     {   // module is set
     136             :         StaticModuleInformation* inf =
     137             :             m_pDatabases->getStaticInformationForModule( get_module(),
     138         200 :                                                          get_language() );
     139         200 :         if( inf )
     140           0 :             m_aId = inf->get_id();
     141             : 
     142         200 :         m_bStart = true;
     143             :     }
     144             : 
     145        2900 :     return m_aId;
     146             : }
     147             : 
     148        1350 : OUString URLParameter::get_tag()
     149             : {
     150        1350 :     if( isFile() )
     151        1350 :         return get_the_tag();
     152             :     else
     153           0 :         return m_aTag;
     154             : }
     155             : 
     156             : 
     157           0 : OUString URLParameter::get_title()
     158             : {
     159           0 :     if( isFile() )
     160           0 :         return get_the_title();
     161           0 :     else if( !m_aModule.isEmpty() )
     162             :     {
     163             :         StaticModuleInformation* inf =
     164             :             m_pDatabases->getStaticInformationForModule( get_module(),
     165           0 :                                                          get_language() );
     166           0 :         if( inf )
     167           0 :             m_aTitle = inf->get_title();
     168             :     }
     169             :     else   // This must be the root
     170           0 :         m_aTitle = "root";
     171             : 
     172           0 :     return m_aTitle;
     173             : }
     174             : 
     175             : 
     176        3138 : OUString URLParameter::get_language()
     177             : {
     178        3138 :     if( m_aLanguage.isEmpty() )
     179           0 :         return m_aDefaultLanguage;
     180             : 
     181        3138 :     return m_aLanguage;
     182             : }
     183             : 
     184             : 
     185           0 : OUString URLParameter::get_program()
     186             : {
     187           0 :     if( m_aProgram.isEmpty() )
     188             :     {
     189             :         StaticModuleInformation* inf =
     190             :             m_pDatabases->getStaticInformationForModule( get_module(),
     191           0 :                                                          get_language() );
     192           0 :         if( inf )
     193           0 :             m_aProgram = inf->get_program();
     194             :     }
     195           0 :     return m_aProgram;
     196             : }
     197             : 
     198             : 
     199        2939 : void URLParameter::init( bool bDefaultLanguageIsInitialized )
     200             : {
     201             :     (void)bDefaultLanguageIsInitialized;
     202             : 
     203        2939 :     m_bHelpDataFileRead = false;
     204        2939 :     m_bStart = false;
     205        2939 :     m_bUseDB = true;
     206        2939 :     m_nHitCount = 100;                // The default maximum hitcount
     207        2939 : }
     208             : 
     209             : 
     210        1350 : OUString URLParameter::get_the_tag()
     211             : {
     212        1350 :     if(m_bUseDB) {
     213        1350 :         if( ! m_bHelpDataFileRead )
     214        1350 :             readHelpDataFile();
     215             : 
     216        1350 :         m_bHelpDataFileRead = true;
     217             : 
     218        1350 :         return m_aTag;
     219             :     }
     220             :     else
     221           0 :         return OUString();
     222             : }
     223             : 
     224             : 
     225             : 
     226           0 : OUString URLParameter::get_the_path()
     227             : {
     228           0 :     if(m_bUseDB) {
     229           0 :         if( ! m_bHelpDataFileRead )
     230           0 :             readHelpDataFile();
     231           0 :         m_bHelpDataFileRead = true;
     232             : 
     233           0 :         return m_aPath;
     234             :     }
     235             :     else
     236           0 :         return get_id();
     237             : }
     238             : 
     239             : 
     240             : 
     241           0 : OUString URLParameter::get_the_title()
     242             : {
     243           0 :     if(m_bUseDB) {
     244           0 :         if( ! m_bHelpDataFileRead )
     245           0 :             readHelpDataFile();
     246           0 :         m_bHelpDataFileRead = true;
     247             : 
     248           0 :         return m_aTitle;
     249             :     }
     250             :     else
     251           0 :         return OUString();
     252             : }
     253             : 
     254             : 
     255           0 : OUString URLParameter::get_the_jar()
     256             : {
     257           0 :     if(m_bUseDB) {
     258           0 :         if( ! m_bHelpDataFileRead )
     259           0 :             readHelpDataFile();
     260           0 :         m_bHelpDataFileRead = true;
     261             : 
     262           0 :         return m_aJar;
     263             :     }
     264             :     else
     265           0 :         return get_module() + ".jar";
     266             : }
     267             : 
     268             : 
     269        1350 : void URLParameter::readHelpDataFile()
     270             : {
     271        1350 :     if( get_id().isEmpty() )
     272        1350 :         return;
     273             : 
     274        1350 :     OUString aModule = get_module();
     275        2700 :     OUString aLanguage = get_language();
     276             : 
     277        2700 :     DataBaseIterator aDbIt( *m_pDatabases, aModule, aLanguage, false );
     278        1350 :     bool bSuccess = false;
     279             : 
     280        1350 :     const sal_Char* pData = NULL;
     281             : 
     282        2700 :     helpdatafileproxy::HDFData aHDFData;
     283        2700 :     OUString aExtensionPath;
     284        2700 :     OUString aExtensionRegistryPath;
     285             :     while( true )
     286             :     {
     287        1350 :         helpdatafileproxy::Hdf* pHdf = aDbIt.nextHdf( &aExtensionPath, &aExtensionRegistryPath );
     288        1350 :         if( !pHdf )
     289        2700 :             break;
     290             : 
     291           0 :         OString keyStr( m_aId.getStr(),m_aId.getLength(),RTL_TEXTENCODING_UTF8 );
     292           0 :         bSuccess = pHdf->getValueForKey( keyStr, aHDFData );
     293           0 :         if( bSuccess )
     294             :         {
     295           0 :             pData = aHDFData.getData();
     296           0 :             break;
     297             :         }
     298           0 :     }
     299             : 
     300        1350 :     if( bSuccess )
     301             :     {
     302           0 :         DbtToStringConverter converter( pData );
     303           0 :         m_aTitle = converter.getTitle();
     304           0 :         m_pDatabases->replaceName( m_aTitle );
     305           0 :         m_aPath  = converter.getFile();
     306           0 :         m_aJar   = converter.getDatabase();
     307           0 :         if( !aExtensionPath.isEmpty() )
     308             :         {
     309           0 :             m_aJar = "?" + aExtensionPath + "?" + m_aJar;
     310           0 :             m_aExtensionRegistryPath = aExtensionRegistryPath;
     311             :         }
     312           0 :         m_aTag   = converter.getHash();
     313        1350 :     }
     314             : }
     315             : 
     316             : 
     317             : 
     318             : // Class encapsulating the transformation of the XInputStream to XHTML
     319             : 
     320             : 
     321             : class InputStreamTransformer
     322             :     : public OWeakObject,
     323             :       public XInputStream,
     324             :       public XSeekable
     325             : {
     326             : public:
     327             : 
     328             :     InputStreamTransformer( URLParameter* urlParam,
     329             :                             Databases*    pDatatabases,
     330             :                             bool isRoot = false );
     331             : 
     332             :     virtual ~InputStreamTransformer();
     333             : 
     334             :     virtual Any SAL_CALL queryInterface( const Type& rType ) throw( RuntimeException, std::exception ) SAL_OVERRIDE;
     335             :     virtual void SAL_CALL acquire() throw() SAL_OVERRIDE;
     336             :     virtual void SAL_CALL release() throw() SAL_OVERRIDE;
     337             : 
     338             :     virtual sal_Int32 SAL_CALL readBytes( Sequence< sal_Int8 >& aData,sal_Int32 nBytesToRead )
     339             :         throw( NotConnectedException,
     340             :                BufferSizeExceededException,
     341             :                IOException,
     342             :                RuntimeException, std::exception) SAL_OVERRIDE;
     343             : 
     344             :     virtual sal_Int32 SAL_CALL readSomeBytes( Sequence< sal_Int8 >& aData,sal_Int32 nMaxBytesToRead )
     345             :         throw( NotConnectedException,
     346             :                BufferSizeExceededException,
     347             :                IOException,
     348             :                RuntimeException, std::exception) SAL_OVERRIDE;
     349             : 
     350             :     virtual void SAL_CALL skipBytes( sal_Int32 nBytesToSkip ) throw( NotConnectedException,
     351             :                                                                      BufferSizeExceededException,
     352             :                                                                      IOException,
     353             :                                                                      RuntimeException, std::exception ) SAL_OVERRIDE;
     354             : 
     355             :     virtual sal_Int32 SAL_CALL available() throw( NotConnectedException,
     356             :                                                         IOException,
     357             :                                                         RuntimeException, std::exception ) SAL_OVERRIDE;
     358             : 
     359             :     virtual void SAL_CALL closeInput() throw( NotConnectedException,
     360             :                                                     IOException,
     361             :                                                     RuntimeException, std::exception ) SAL_OVERRIDE;
     362             : 
     363             :     virtual void SAL_CALL seek( sal_Int64 location ) throw( IllegalArgumentException,
     364             :                                                             IOException,
     365             :                                                             RuntimeException, std::exception ) SAL_OVERRIDE;
     366             : 
     367             :     virtual sal_Int64 SAL_CALL getPosition() throw( IOException,RuntimeException, std::exception ) SAL_OVERRIDE;
     368             : 
     369             :     virtual sal_Int64 SAL_CALL getLength() throw( IOException,RuntimeException, std::exception ) SAL_OVERRIDE;
     370             : 
     371             :     void addToBuffer( const char* buffer,int len );
     372             : 
     373           0 :     sal_Int8 const * getData() const { return reinterpret_cast<sal_Int8 const *>(buffer); }
     374             : 
     375           0 :     sal_Int32 getLen() const { return sal_Int32( len ); }
     376             : 
     377             : private:
     378             : 
     379             :     osl::Mutex m_aMutex;
     380             : 
     381             :     int len,pos;
     382             :     char *buffer;
     383             : };
     384             : 
     385             : 
     386             : 
     387           0 : void URLParameter::open( const Command& aCommand,
     388             :                          sal_Int32 CommandId,
     389             :                          const Reference< XCommandEnvironment >& Environment,
     390             :                          const Reference< XOutputStream >& xDataSink )
     391             : {
     392             :     (void)aCommand;
     393             :     (void)CommandId;
     394             :     (void)Environment;
     395             : 
     396           0 :     if( ! xDataSink.is() )
     397           0 :         return;
     398             : 
     399           0 :     if( isPicture() )
     400             :     {
     401           0 :         Reference< XInputStream > xStream;
     402             :         Reference< XHierarchicalNameAccess > xNA =
     403             :             m_pDatabases->jarFile( OUString( "picture.jar" ),
     404           0 :                                    get_language() );
     405             : 
     406           0 :         OUString path = get_path();
     407           0 :         if( xNA.is() )
     408             :         {
     409             :             try
     410             :             {
     411           0 :                 Any aEntry = xNA->getByHierarchicalName( path );
     412           0 :                 Reference< XActiveDataSink > xSink;
     413           0 :                 if( ( aEntry >>= xSink ) && xSink.is() )
     414           0 :                     xStream = xSink->getInputStream();
     415             :             }
     416           0 :             catch ( NoSuchElementException & )
     417             :             {
     418             :             }
     419             :         }
     420           0 :         if( xStream.is() )
     421             :         {
     422             :             sal_Int32 ret;
     423           0 :             Sequence< sal_Int8 > aSeq( 4096 );
     424             :             while( true )
     425             :             {
     426             :                 try
     427             :                 {
     428           0 :                     ret = xStream->readBytes( aSeq,4096 );
     429           0 :                     xDataSink->writeBytes( aSeq );
     430           0 :                     if( ret < 4096 )
     431           0 :                         break;
     432             :                 }
     433           0 :                 catch( const Exception& )
     434             :                 {
     435           0 :                     break;
     436             :                 }
     437           0 :             }
     438           0 :         }
     439             :     }
     440             :     else
     441             :     {
     442             :         // a standard document or else an active help text, plug in the new input stream
     443           0 :         InputStreamTransformer* p = new InputStreamTransformer( this,m_pDatabases,isRoot() );
     444             :         try
     445             :         {
     446           0 :             xDataSink->writeBytes( Sequence< sal_Int8 >( p->getData(),p->getLen() ) );
     447             :         }
     448           0 :         catch( const Exception& )
     449             :         {
     450             :         }
     451           0 :         delete p;
     452             :     }
     453           0 :     xDataSink->closeOutput();
     454             : }
     455             : 
     456             : 
     457             : 
     458        1550 : void URLParameter::open( const Command& aCommand,
     459             :                          sal_Int32 CommandId,
     460             :                          const Reference< XCommandEnvironment >& Environment,
     461             :                          const Reference< XActiveDataSink >& xDataSink )
     462             : {
     463             :     (void)aCommand;
     464             :     (void)CommandId;
     465             :     (void)Environment;
     466             : 
     467        1550 :     if( isPicture() )
     468             :     {
     469           0 :         Reference< XInputStream > xStream;
     470             :         Reference< XHierarchicalNameAccess > xNA =
     471             :             m_pDatabases->jarFile( OUString( "picture.jar" ),
     472           0 :                                    get_language() );
     473             : 
     474           0 :         OUString path = get_path();
     475           0 :         if( xNA.is() )
     476             :         {
     477             :             try
     478             :             {
     479           0 :                 Any aEntry = xNA->getByHierarchicalName( path );
     480           0 :                 Reference< XActiveDataSink > xSink;
     481           0 :                 if( ( aEntry >>= xSink ) && xSink.is() )
     482           0 :                     xStream = xSink->getInputStream();
     483             :             }
     484           0 :             catch ( NoSuchElementException & )
     485             :             {
     486             :             }
     487             :         }
     488           0 :         xDataSink->setInputStream( turnToSeekable(xStream) );
     489             :     }
     490             :     else
     491             :         // a standard document or else an active help text, plug in the new input stream
     492        1550 :         xDataSink->setInputStream( new InputStreamTransformer( this,m_pDatabases,isRoot() ) );
     493        1550 : }
     494             : 
     495             : 
     496        2939 : void URLParameter::parse() throw( com::sun::star::ucb::IllegalIdentifierException )
     497             : {
     498        2939 :     m_aExpr = m_aURL;
     499             : 
     500        2939 :     sal_Int32 lstIdx = m_aExpr.lastIndexOf( '#' );
     501        2939 :     if( lstIdx != -1 )
     502           0 :         m_aExpr = m_aExpr.copy( 0,lstIdx );
     503             : 
     504        8817 :     if( ! scheme() ||
     505        5878 :         ! name( module() ) ||
     506        5878 :         ! query() ||
     507        8817 :         m_aLanguage.isEmpty() ||
     508        2939 :         m_aSystem.isEmpty() )
     509           0 :         throw com::sun::star::ucb::IllegalIdentifierException();
     510        2939 : }
     511             : 
     512             : 
     513        2939 : bool URLParameter::scheme()
     514             : {
     515             :     // Correct extension help links as sometimes the
     516             :     // module is missing resulting in a malformed URL
     517        2939 :     if( m_aExpr.startsWith("vnd.sun.star.help:///") )
     518             :     {
     519           0 :         sal_Int32 nLen = m_aExpr.getLength();
     520             :         OUString aLastStr =
     521           0 :             m_aExpr.copy(sal::static_int_cast<sal_uInt32>(nLen) - 6);
     522           0 :         if( aLastStr == "DbPAR=" )
     523             :         {
     524           0 :             OUString aNewExpr = m_aExpr.copy( 0, 20 );
     525           0 :             OUString aSharedStr("shared");
     526           0 :             aNewExpr += aSharedStr;
     527           0 :             aNewExpr += m_aExpr.copy( 20 );
     528           0 :             aNewExpr += aSharedStr;
     529           0 :             m_aExpr = aNewExpr;
     530           0 :         }
     531             :     }
     532             : 
     533        2939 :     for( sal_Int32 nPrefixLen = 20 ; nPrefixLen >= 18 ; --nPrefixLen )
     534             :     {
     535        2939 :         if( m_aExpr.matchAsciiL( "vnd.sun.star.help://", nPrefixLen ) )
     536             :         {
     537        2939 :             m_aExpr = m_aExpr.copy( nPrefixLen );
     538        2939 :             return true;
     539             :         }
     540             :     }
     541           0 :     return false;
     542             : }
     543             : 
     544             : 
     545        2939 : bool URLParameter::module()
     546             : {
     547        2939 :     sal_Int32 idx = 0,length = m_aExpr.getLength();
     548             : 
     549       26039 :     while( idx < length && isLetterOrDigit( (m_aExpr.getStr())[idx] ) )
     550       20161 :         ++idx;
     551             : 
     552        2939 :     if( idx != 0 )
     553             :     {
     554        2901 :         m_aModule = m_aExpr.copy( 0,idx );
     555        2901 :         m_aExpr = m_aExpr.copy( idx );
     556        2901 :         return true;
     557             :     }
     558             :     else
     559          38 :         return false;
     560             : }
     561             : 
     562             : 
     563             : 
     564        2939 : bool URLParameter::name( bool modulePresent )
     565             : {
     566             :     // if modulepresent, a name may be present, but must not
     567             : 
     568        2939 :     sal_Int32 length = m_aExpr.getLength();
     569             : 
     570        2939 :     if( length != 0 && (m_aExpr.getStr())[0] == '/' )
     571             :     {
     572        2900 :         sal_Int32 idx = 1;
     573       49452 :         while( idx < length && (m_aExpr.getStr())[idx] != '?' )
     574       43652 :             ++idx;
     575             : 
     576        2900 :         if( idx != 1 && ! modulePresent )
     577           0 :             return false;
     578             :         else
     579             :         {
     580        2900 :             m_aId = m_aExpr.copy( 1,idx-1 );
     581        2900 :             m_aExpr = m_aExpr.copy( idx );
     582             :         }
     583             :     }
     584             : 
     585        2939 :     return true;
     586             : }
     587             : 
     588             : 
     589        2939 : bool URLParameter::query()
     590             : {
     591        2939 :     OUString query_;
     592             : 
     593        2939 :     if( m_aExpr.isEmpty() )
     594           0 :         return true;
     595        2939 :     else if( (m_aExpr.getStr())[0] == '?' )
     596        2939 :         query_ = m_aExpr.copy( 1 ).trim();
     597             :     else
     598           0 :         return false;
     599             : 
     600             : 
     601        2939 :     bool ret = true;
     602             :     sal_Int32 delimIdx,equalIdx;
     603        5878 :     OUString parameter,value;
     604             : 
     605       16247 :     while( !query_.isEmpty() )
     606             :     {
     607       10369 :         delimIdx = query_.indexOf( '&' );
     608       10369 :         equalIdx = query_.indexOf( '=' );
     609       10369 :         parameter = query_.copy( 0,equalIdx ).trim();
     610       10369 :         if( delimIdx == -1 )
     611             :         {
     612        2939 :             value = query_.copy( equalIdx + 1 ).trim();
     613        2939 :             query_.clear();
     614             :         }
     615             :         else
     616             :         {
     617        7430 :             value = query_.copy( equalIdx+1,delimIdx - equalIdx - 1 ).trim();
     618        7430 :             query_ = query_.copy( delimIdx+1 ).trim();
     619             :         }
     620             : 
     621       10369 :         if( parameter == "Language" )
     622        2939 :             m_aLanguage = value;
     623        7430 :         else if( parameter == "Device" )
     624           0 :             m_aDevice = value;
     625        7430 :         else if( parameter == "Program" )
     626           0 :             m_aProgram = value;
     627        7430 :         else if( parameter == "Eid" )
     628           0 :             m_aEid = value;
     629        7430 :         else if( parameter == "UseDB" )
     630           0 :             m_bUseDB = value != "no";
     631        7430 :         else if( parameter == "DbPAR" )
     632           0 :             m_aDbPar = value;
     633        7430 :         else if( parameter == "Query" )
     634             :         {
     635           1 :             if( m_aQuery.isEmpty() )
     636           1 :                 m_aQuery = value;
     637             :             else
     638           0 :                 m_aQuery += " " + value;
     639             :         }
     640        7429 :         else if( parameter == "Scope" )
     641           1 :             m_aScope = value;
     642        7428 :         else if( parameter == "System" )
     643        2939 :             m_aSystem = value;
     644        4489 :         else if( parameter == "HelpPrefix" )
     645           0 :             m_aPrefix = rtl::Uri::decode(
     646             :                 value,
     647             :                 rtl_UriDecodeWithCharset,
     648           0 :                 RTL_TEXTENCODING_UTF8 );
     649        4489 :         else if( parameter == "HitCount" )
     650           1 :             m_nHitCount = value.toInt32();
     651        4488 :         else if( parameter == "Active" )
     652        1550 :             m_aActive = value;
     653        2938 :         else if( parameter == "Version" )
     654             :             ; // ignored (but accepted) in the build-in help, useful only for the online help
     655             :         else
     656           0 :             ret = false;
     657             :     }
     658             : 
     659        5878 :     return ret;
     660             : }
     661             : 
     662             : struct UserData {
     663             : 
     664           0 :     UserData( InputStreamTransformer* pTransformer,
     665             :               URLParameter*           pInitial,
     666             :               Databases*              pDatabases )
     667             :         : m_pTransformer( pTransformer ),
     668             :           m_pDatabases( pDatabases ),
     669           0 :           m_pInitial( pInitial )
     670             :     {
     671           0 :     }
     672             : 
     673             :     InputStreamTransformer*             m_pTransformer;
     674             :     Databases*                          m_pDatabases;
     675             :     URLParameter*                       m_pInitial;
     676             : };
     677             : 
     678             : UserData *ugblData = 0;
     679             : 
     680             : extern "C" {
     681             : 
     682             : static int
     683           0 : fileMatch(const char * URI) {
     684           0 :     if ((URI != NULL) && !strncmp(URI, "file:/", 6))
     685           0 :         return 1;
     686           0 :     return 0;
     687             : }
     688             : 
     689             : static int
     690           0 : zipMatch(const char * URI) {
     691           0 :     if ((URI != NULL) && !strncmp(URI, "vnd.sun.star.zip:/", 18))
     692           0 :         return 1;
     693           0 :     return 0;
     694             : }
     695             : 
     696             : static int
     697           0 : helpMatch(const char * URI) {
     698           0 :     if ((URI != NULL) && !strncmp(URI, "vnd.sun.star.help:/", 19))
     699           0 :         return 1;
     700           0 :     return 0;
     701             : }
     702             : 
     703             : static void *
     704           0 : fileOpen(const char *URI) {
     705           0 :     osl::File *pRet = new osl::File(OUString(URI, strlen(URI), RTL_TEXTENCODING_UTF8));
     706           0 :     pRet->open(osl_File_OpenFlag_Read);
     707           0 :     return pRet;
     708             : }
     709             : 
     710             : static void *
     711           0 : zipOpen(SAL_UNUSED_PARAMETER const char *) {
     712           0 :     OUString language,jar,path;
     713             : 
     714           0 :     if( !ugblData->m_pInitial->get_eid().isEmpty() )
     715           0 :         return static_cast<void*>(new Reference< XHierarchicalNameAccess >);
     716             :     else
     717             :     {
     718           0 :         jar = ugblData->m_pInitial->get_jar();
     719           0 :         language = ugblData->m_pInitial->get_language();
     720           0 :         path = ugblData->m_pInitial->get_path();
     721             :     }
     722             : 
     723             :     Reference< XHierarchicalNameAccess > xNA =
     724           0 :         ugblData->m_pDatabases->findJarFileForPath( jar, language, path );
     725             : 
     726           0 :     Reference< XInputStream > xInputStream;
     727             : 
     728           0 :     if( xNA.is() )
     729             :     {
     730             :         try
     731             :         {
     732           0 :             Any aEntry = xNA->getByHierarchicalName( path );
     733           0 :             Reference< XActiveDataSink > xSink;
     734           0 :             if( ( aEntry >>= xSink ) && xSink.is() )
     735           0 :                 xInputStream = xSink->getInputStream();
     736             :         }
     737           0 :         catch ( NoSuchElementException & )
     738             :         {
     739             :         }
     740             :     }
     741             : 
     742           0 :     if( xInputStream.is() )
     743             :     {
     744           0 :         return new Reference<XInputStream>(xInputStream);
     745             :     }
     746           0 :     return 0;
     747             : }
     748             : 
     749             : static void *
     750           0 : helpOpen(const char * URI) {
     751           0 :     OUString language,jar,path;
     752             : 
     753             :     URLParameter urlpar( OUString::createFromAscii( URI ),
     754           0 :                          ugblData->m_pDatabases );
     755             : 
     756           0 :     jar = urlpar.get_jar();
     757           0 :     language = urlpar.get_language();
     758           0 :     path = urlpar.get_path();
     759             : 
     760             :     Reference< XHierarchicalNameAccess > xNA =
     761           0 :         ugblData->m_pDatabases->findJarFileForPath( jar, language, path );
     762             : 
     763           0 :     Reference< XInputStream > xInputStream;
     764             : 
     765           0 :     if( xNA.is() )
     766             :     {
     767             :         try
     768             :         {
     769           0 :             Any aEntry = xNA->getByHierarchicalName( path );
     770           0 :             Reference< XActiveDataSink > xSink;
     771           0 :             if( ( aEntry >>= xSink ) && xSink.is() )
     772           0 :                 xInputStream = xSink->getInputStream();
     773             :         }
     774           0 :         catch ( NoSuchElementException & )
     775             :         {
     776             :         }
     777             :     }
     778             : 
     779           0 :     if( xInputStream.is() )
     780           0 :         return new Reference<XInputStream>(xInputStream);
     781           0 :     return 0;
     782             : }
     783             : 
     784             : static int
     785           0 : helpRead(void * context, char * buffer, int len) {
     786           0 :     Reference< XInputStream > *pRef = static_cast<Reference< XInputStream >*>(context);
     787             : 
     788           0 :     Sequence< sal_Int8 > aSeq;
     789           0 :     len = (*pRef)->readBytes( aSeq,len);
     790           0 :     memcpy(buffer, aSeq.getConstArray(), len);
     791             : 
     792           0 :     return len;
     793             : }
     794             : 
     795             : static int
     796           0 : zipRead(void * context, char * buffer, int len) {
     797           0 :     return helpRead(context, buffer, len);
     798             : }
     799             : 
     800             : static int
     801           0 : fileRead(void * context, char * buffer, int len) {
     802           0 :     int nRead = 0;
     803           0 :     osl::File *pFile = static_cast<osl::File*>(context);
     804           0 :     if (pFile)
     805             :     {
     806           0 :         sal_uInt64 uRead = 0;
     807           0 :         if (osl::FileBase::E_None == pFile->read(buffer, len, uRead))
     808           0 :             nRead = static_cast<int>(uRead);
     809             :     }
     810           0 :     return nRead;
     811             : }
     812             : 
     813             : static int
     814           0 : uriClose(void * context) {
     815           0 :     Reference< XInputStream > *pRef = static_cast<Reference< XInputStream >*>(context);
     816           0 :     delete pRef;
     817           0 :     return 0;
     818             : }
     819             : 
     820             : static int
     821           0 : fileClose(void * context) {
     822           0 :     osl::File *pFile = static_cast<osl::File*>(context);
     823           0 :     if (pFile)
     824             :     {
     825           0 :         pFile->close();
     826           0 :         delete pFile;
     827             :     }
     828           0 :     return 0;
     829             : }
     830             : 
     831             : } // extern "C"
     832             : 
     833        1550 : InputStreamTransformer::InputStreamTransformer( URLParameter* urlParam,
     834             :                                                 Databases*    pDatabases,
     835             :                                                 bool isRoot )
     836             :     : len( 0 ),
     837             :       pos( 0 ),
     838        1550 :       buffer( new char[1] ) // Initializing with one element to avoid gcc compiler warning
     839             : {
     840        1550 :     if( isRoot )
     841             :     {
     842           0 :         delete[] buffer;
     843             :         pDatabases->cascadingStylesheet( urlParam->get_language(),
     844             :                                          &buffer,
     845           0 :                                          &len );
     846             :     }
     847        1550 :     else if( urlParam->isActive() )
     848             :     {
     849        1550 :         delete[] buffer;
     850             :         pDatabases->setActiveText( urlParam->get_module(),
     851             :                                    urlParam->get_language(),
     852             :                                    urlParam->get_id(),
     853             :                                    &buffer,
     854        1550 :                                    &len );
     855             :     }
     856             :     else
     857             :     {
     858           0 :         UserData userData( this,urlParam,pDatabases );
     859             : 
     860             :         // Uses the implementation detail, that OString::getStr returns a zero terminated character-array
     861             : 
     862             :         const char* parameter[47];
     863           0 :         OString parString[46];
     864           0 :         int last = 0;
     865             : 
     866           0 :         parString[last++] = "Program";
     867           0 :         OString aPureProgramm( urlParam->getByName( "Program" ) );
     868           0 :         parString[last++] = OString('\'') + aPureProgramm + OString('\'');
     869           0 :         parString[last++] = "Database";
     870           0 :         parString[last++] = OString('\'') + urlParam->getByName( "DatabasePar" ) + OString('\'');
     871           0 :         parString[last++] = "Id";
     872           0 :         parString[last++] = OString('\'') + urlParam->getByName( "Id" ) + OString('\'');
     873           0 :         parString[last++] = "Path";
     874           0 :         OString aPath( urlParam->getByName( "Path" ) );
     875           0 :         parString[last++] = OString('\'') + aPath + OString('\'');
     876             : 
     877           0 :         OString aPureLanguage = urlParam->getByName( "Language" );
     878           0 :         parString[last++] = "Language";
     879           0 :         parString[last++] = OString('\'') + aPureLanguage + OString('\'');
     880           0 :         parString[last++] = "System";
     881           0 :         parString[last++] = OString('\'') + urlParam->getByName( "System" ) + OString('\'');
     882           0 :         parString[last++] = "productname";
     883           0 :         parString[last++] = OString('\'') + OString(
     884             :             pDatabases->getProductName().getStr(),
     885             :             pDatabases->getProductName().getLength(),
     886           0 :             RTL_TEXTENCODING_UTF8 ) + OString('\'');
     887           0 :         parString[last++] = "productversion";
     888           0 :         parString[last++] = OString('\'') +
     889             :             OString(  pDatabases->getProductVersion().getStr(),
     890             :                           pDatabases->getProductVersion().getLength(),
     891           0 :                           RTL_TEXTENCODING_UTF8 ) + OString('\'');
     892             : 
     893           0 :         parString[last++] = "imgrepos";
     894           0 :         parString[last++] = OString('\'') + pDatabases->getImagesZipFileURL() + OString('\'');
     895           0 :         parString[last++] = "hp";
     896           0 :         parString[last++] = OString('\'') + urlParam->getByName( "HelpPrefix" ) + OString('\'');
     897             : 
     898           0 :         if( !parString[last-1].isEmpty() )
     899             :         {
     900           0 :             parString[last++] = "sm";
     901           0 :             parString[last++] = "'vnd.sun.star.help%3A%2F%2F'";
     902           0 :             parString[last++] = "qm";
     903           0 :             parString[last++] = "'%3F'";
     904           0 :             parString[last++] = "es";
     905           0 :             parString[last++] = "'%3D'";
     906           0 :             parString[last++] = "am";
     907           0 :             parString[last++] = "'%26'";
     908           0 :             parString[last++] = "cl";
     909           0 :             parString[last++] = "'%3A'";
     910           0 :             parString[last++] = "sl";
     911           0 :             parString[last++] = "'%2F'";
     912           0 :             parString[last++] = "hm";
     913           0 :             parString[last++] = "'%23'";
     914           0 :             parString[last++] = "cs";
     915           0 :             parString[last++] = "'css'";
     916             : 
     917           0 :             parString[last++] = "vendorname";
     918           0 :             parString[last++] = OString("''");
     919           0 :             parString[last++] = "vendorversion";
     920           0 :             parString[last++] = OString("''");
     921           0 :             parString[last++] = "vendorshort";
     922           0 :             parString[last++] = OString("''");
     923             :         }
     924             : 
     925             :         // Do we need to add extension path?
     926           0 :         OUString aExtensionPath;
     927           0 :         OUString aJar = urlParam->get_jar();
     928             : 
     929           0 :         bool bAddExtensionPath = false;
     930           0 :         OUString aExtensionRegistryPath;
     931           0 :         sal_Int32 nQuestionMark1 = aJar.indexOf( '?' );
     932           0 :         sal_Int32 nQuestionMark2 = aJar.lastIndexOf( '?' );
     933           0 :         if( nQuestionMark1 != -1 && nQuestionMark2 != -1 && nQuestionMark1 != nQuestionMark2 )
     934             :         {
     935           0 :             aExtensionPath = aJar.copy( nQuestionMark1 + 1, nQuestionMark2 - nQuestionMark1 - 1 );
     936           0 :             aExtensionRegistryPath = urlParam->get_ExtensionRegistryPath();
     937           0 :             bAddExtensionPath = true;
     938             :         }
     939             :         else
     940             :         {
     941             :             // Path not yet specified, search directly
     942             :             Reference< XHierarchicalNameAccess > xNA = pDatabases->findJarFileForPath
     943           0 :                 ( aJar, urlParam->get_language(), urlParam->get_path(), &aExtensionPath, &aExtensionRegistryPath );
     944           0 :             if( xNA.is() && !aExtensionPath.isEmpty() )
     945           0 :                 bAddExtensionPath = true;
     946             :         }
     947             : 
     948           0 :         if( bAddExtensionPath )
     949             :         {
     950             :             Reference< XComponentContext > xContext(
     951           0 :                 comphelper::getProcessComponentContext() );
     952             : 
     953           0 :             OUString aOUExpandedExtensionPath = Databases::expandURL( aExtensionRegistryPath, xContext );
     954           0 :             OString aExpandedExtensionPath = OUStringToOString( aOUExpandedExtensionPath, osl_getThreadTextEncoding() );
     955             : 
     956           0 :             parString[last++] = "ExtensionPath";
     957           0 :             parString[last++] = OString('\'') + aExpandedExtensionPath + OString('\'');
     958             : 
     959             :             // ExtensionId
     960           0 :             OString aPureExtensionId;
     961           0 :             sal_Int32 iSlash = aPath.indexOf( '/' );
     962           0 :             if( iSlash != -1 )
     963           0 :                 aPureExtensionId = aPath.copy( 0, iSlash );
     964             : 
     965           0 :             parString[last++] = "ExtensionId";
     966           0 :             parString[last++] = OString('\'') + aPureExtensionId + OString('\'');
     967             :         }
     968             : 
     969           0 :         for( int i = 0; i < last; ++i )
     970           0 :             parameter[i] = parString[i].getStr();
     971           0 :         parameter[last] = 0;
     972             : 
     973           0 :         OUString xslURL = pDatabases->getInstallPathAsURL();
     974             : 
     975             :         OString xslURLascii(
     976             :             xslURL.getStr(),
     977             :             xslURL.getLength(),
     978           0 :             RTL_TEXTENCODING_UTF8);
     979           0 :         xslURLascii += "main_transform.xsl";
     980             : 
     981           0 :         ugblData = &userData;
     982             : 
     983           0 :         xmlInitParser();
     984           0 :         xmlRegisterInputCallbacks(zipMatch, zipOpen, zipRead, uriClose);
     985           0 :         xmlRegisterInputCallbacks(helpMatch, helpOpen, helpRead, uriClose);
     986           0 :         xmlRegisterInputCallbacks(fileMatch, fileOpen, fileRead, fileClose);
     987             : 
     988             :         xsltStylesheetPtr cur =
     989           0 :             xsltParseStylesheetFile(reinterpret_cast<const xmlChar *>(xslURLascii.getStr()));
     990             : 
     991           0 :         xmlDocPtr doc = xmlParseFile("vnd.sun.star.zip:/");
     992             : 
     993           0 :         xmlDocPtr res = xsltApplyStylesheet(cur, doc, parameter);
     994           0 :         if (res)
     995             :         {
     996           0 :             xmlChar *doc_txt_ptr=0;
     997             :             int doc_txt_len;
     998           0 :             xsltSaveResultToString(&doc_txt_ptr, &doc_txt_len, res, cur);
     999           0 :             addToBuffer(reinterpret_cast<char*>(doc_txt_ptr), doc_txt_len);
    1000           0 :             xmlFree(doc_txt_ptr);
    1001             :         }
    1002           0 :         xmlPopInputCallbacks(); //filePatch
    1003           0 :         xmlPopInputCallbacks(); //helpPatch
    1004           0 :         xmlPopInputCallbacks(); //zipMatch
    1005           0 :         xmlFreeDoc(res);
    1006           0 :         xmlFreeDoc(doc);
    1007           0 :         xsltFreeStylesheet(cur);
    1008             :     }
    1009        1550 : }
    1010             : 
    1011             : 
    1012        4650 : InputStreamTransformer::~InputStreamTransformer()
    1013             : {
    1014        1550 :     delete[] buffer;
    1015        3100 : }
    1016             : 
    1017             : 
    1018           0 : Any SAL_CALL InputStreamTransformer::queryInterface( const Type& rType ) throw( RuntimeException, std::exception )
    1019             : {
    1020             :     Any aRet = ::cppu::queryInterface( rType,
    1021             :                                        (static_cast< XInputStream* >(this)),
    1022           0 :                                        (static_cast< XSeekable* >(this)) );
    1023             : 
    1024           0 :     return aRet.hasValue() ? aRet : OWeakObject::queryInterface( rType );
    1025             : }
    1026             : 
    1027             : 
    1028             : 
    1029        4650 : void SAL_CALL InputStreamTransformer::acquire() throw()
    1030             : {
    1031        4650 :     OWeakObject::acquire();
    1032        4650 : }
    1033             : 
    1034             : 
    1035             : 
    1036        4650 : void SAL_CALL InputStreamTransformer::release() throw()
    1037             : {
    1038        4650 :     OWeakObject::release();
    1039        4650 : }
    1040             : 
    1041             : 
    1042             : 
    1043        1550 : sal_Int32 SAL_CALL InputStreamTransformer::readBytes( Sequence< sal_Int8 >& aData,sal_Int32 nBytesToRead )
    1044             :     throw( NotConnectedException,
    1045             :            BufferSizeExceededException,
    1046             :            IOException,
    1047             :            RuntimeException, std::exception)
    1048             : {
    1049        1550 :     osl::MutexGuard aGuard( m_aMutex );
    1050             : 
    1051        1550 :     int curr,available_ = len-pos;
    1052        1550 :     if( nBytesToRead <= available_ )
    1053           0 :         curr = nBytesToRead;
    1054             :     else
    1055        1550 :         curr = available_;
    1056             : 
    1057        1550 :     if( 0 <= curr && aData.getLength() < curr )
    1058           0 :         aData.realloc( curr );
    1059             : 
    1060        1550 :     for( int k = 0; k < curr; ++k )
    1061           0 :         aData[k] = buffer[pos++];
    1062             : 
    1063        1550 :     return curr > 0 ? curr : 0;
    1064             : }
    1065             : 
    1066             : 
    1067           0 : sal_Int32 SAL_CALL InputStreamTransformer::readSomeBytes( Sequence< sal_Int8 >& aData,sal_Int32 nMaxBytesToRead )
    1068             :     throw( NotConnectedException,
    1069             :            BufferSizeExceededException,
    1070             :            IOException,
    1071             :            RuntimeException, std::exception)
    1072             : {
    1073           0 :     return readBytes( aData,nMaxBytesToRead );
    1074             : }
    1075             : 
    1076             : 
    1077             : 
    1078           0 : void SAL_CALL InputStreamTransformer::skipBytes( sal_Int32 nBytesToSkip ) throw( NotConnectedException,
    1079             :                                                                                  BufferSizeExceededException,
    1080             :                                                                                  IOException,
    1081             :                                                                                  RuntimeException, std::exception )
    1082             : {
    1083           0 :     osl::MutexGuard aGuard( m_aMutex );
    1084           0 :     while( nBytesToSkip-- ) ++pos;
    1085           0 : }
    1086             : 
    1087             : 
    1088             : 
    1089           0 : sal_Int32 SAL_CALL InputStreamTransformer::available() throw( NotConnectedException,
    1090             :                                                                     IOException,
    1091             :                                                                     RuntimeException, std::exception )
    1092             : {
    1093           0 :     osl::MutexGuard aGuard( m_aMutex );
    1094           0 :     return len-pos > 0 ? len - pos : 0 ;
    1095             : }
    1096             : 
    1097             : 
    1098             : 
    1099           0 : void SAL_CALL InputStreamTransformer::closeInput() throw( NotConnectedException,
    1100             :                                                                 IOException,
    1101             :                                                                 RuntimeException, std::exception )
    1102             : {
    1103           0 : }
    1104             : 
    1105             : 
    1106             : 
    1107           0 : void SAL_CALL InputStreamTransformer::seek( sal_Int64 location ) throw( IllegalArgumentException,
    1108             :                                                                         IOException,
    1109             :                                                                         RuntimeException, std::exception )
    1110             : {
    1111           0 :     osl::MutexGuard aGuard( m_aMutex );
    1112           0 :     if( location < 0 )
    1113           0 :         throw IllegalArgumentException();
    1114             :     else
    1115           0 :         pos = sal::static_int_cast<sal_Int32>( location );
    1116             : 
    1117           0 :     if( pos > len )
    1118           0 :         pos = len;
    1119           0 : }
    1120             : 
    1121             : 
    1122             : 
    1123           0 : sal_Int64 SAL_CALL InputStreamTransformer::getPosition() throw( IOException,
    1124             :                                                                       RuntimeException, std::exception )
    1125             : {
    1126           0 :     osl::MutexGuard aGuard( m_aMutex );
    1127           0 :     return sal_Int64( pos );
    1128             : }
    1129             : 
    1130             : 
    1131             : 
    1132           0 : sal_Int64 SAL_CALL InputStreamTransformer::getLength() throw( IOException,RuntimeException, std::exception )
    1133             : {
    1134           0 :     osl::MutexGuard aGuard( m_aMutex );
    1135             : 
    1136           0 :     return len;
    1137             : }
    1138             : 
    1139             : 
    1140           0 : void InputStreamTransformer::addToBuffer( const char* buffer_,int len_ )
    1141             : {
    1142           0 :     osl::MutexGuard aGuard( m_aMutex );
    1143             : 
    1144           0 :     char* tmp = buffer;
    1145           0 :     buffer = new char[ len+len_ ];
    1146           0 :     memcpy( static_cast<void*>(buffer),static_cast<void*>(tmp),sal_uInt32( len ) );
    1147           0 :     memcpy( static_cast<void*>(buffer+len),static_cast<void const *>(buffer_),sal_uInt32( len_ ) );
    1148           0 :     delete[] tmp;
    1149           0 :     len += len_;
    1150           0 : }
    1151             : 
    1152             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.11