bump product version to 5.0.4.1
[LibreOffice.git] / xmlhelp / source / cxxhelp / provider / urlparameter.cxx
blobef143c66169700b7049aab3c3758ce0218d57c16
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
21 #include "bufferedinputstream.hxx"
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>
48 #include "urlparameter.hxx"
49 #include "databases.hxx"
51 namespace chelp {
53 inline bool ascii_isDigit( sal_Unicode ch )
55 return ((ch >= 0x0030) && (ch <= 0x0039));
58 inline bool ascii_isLetter( sal_Unicode ch )
60 return ( ( (ch >= 0x0041) && (ch <= 0x005A) ) ||
61 ( (ch >= 0x0061) && (ch <= 0x007A) ) );
64 inline bool isLetterOrDigit( sal_Unicode ch )
66 return ascii_isLetter( ch ) || ascii_isDigit( ch );
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;
81 URLParameter::URLParameter( const OUString& aURL,
82 Databases* pDatabases )
83 throw( com::sun::star::ucb::IllegalIdentifierException )
84 : m_pDatabases( pDatabases ),
85 m_aURL( aURL )
87 init( false );
88 parse();
92 bool URLParameter::isErrorDocument()
94 bool bErrorDoc = false;
96 if( isFile() )
98 Reference< XHierarchicalNameAccess > xNA =
99 m_pDatabases->findJarFileForPath( get_jar(), get_language(), get_path() );
100 bErrorDoc = !xNA.is();
103 return bErrorDoc;
107 OString URLParameter::getByName( const char* par )
109 OUString val;
111 if( strcmp( par,"Program" ) == 0 )
112 val = get_program();
113 else if( strcmp( par,"Database" ) == 0 )
114 val = get_module();
115 else if( strcmp( par,"DatabasePar" ) == 0 )
116 val = get_dbpar();
117 else if( strcmp( par,"Id" ) == 0 )
118 val = get_id();
119 else if( strcmp( par,"Path" ) == 0 )
120 val = get_path();
121 else if( strcmp( par,"Language" ) == 0 )
122 val = get_language();
123 else if( strcmp( par,"System" ) == 0 )
124 val = get_system();
125 else if( strcmp( par,"HelpPrefix" ) == 0 )
126 val = get_prefix();
128 return OString( val.getStr(),val.getLength(),RTL_TEXTENCODING_UTF8 );
132 OUString URLParameter::get_id()
134 if( m_aId == "start" )
135 { // module is set
136 StaticModuleInformation* inf =
137 m_pDatabases->getStaticInformationForModule( get_module(),
138 get_language() );
139 if( inf )
140 m_aId = inf->get_id();
142 m_bStart = true;
145 return m_aId;
148 OUString URLParameter::get_tag()
150 if( isFile() )
151 return get_the_tag();
152 else
153 return m_aTag;
157 OUString URLParameter::get_title()
159 if( isFile() )
160 return get_the_title();
161 else if( !m_aModule.isEmpty() )
163 StaticModuleInformation* inf =
164 m_pDatabases->getStaticInformationForModule( get_module(),
165 get_language() );
166 if( inf )
167 m_aTitle = inf->get_title();
169 else // This must be the root
170 m_aTitle = "root";
172 return m_aTitle;
176 OUString URLParameter::get_language()
178 if( m_aLanguage.isEmpty() )
179 return m_aDefaultLanguage;
181 return m_aLanguage;
185 OUString URLParameter::get_program()
187 if( m_aProgram.isEmpty() )
189 StaticModuleInformation* inf =
190 m_pDatabases->getStaticInformationForModule( get_module(),
191 get_language() );
192 if( inf )
193 m_aProgram = inf->get_program();
195 return m_aProgram;
199 void URLParameter::init( bool bDefaultLanguageIsInitialized )
201 (void)bDefaultLanguageIsInitialized;
203 m_bHelpDataFileRead = false;
204 m_bStart = false;
205 m_bUseDB = true;
206 m_nHitCount = 100; // The default maximum hitcount
210 OUString URLParameter::get_the_tag()
212 if(m_bUseDB) {
213 if( ! m_bHelpDataFileRead )
214 readHelpDataFile();
216 m_bHelpDataFileRead = true;
218 return m_aTag;
220 else
221 return OUString();
226 OUString URLParameter::get_the_path()
228 if(m_bUseDB) {
229 if( ! m_bHelpDataFileRead )
230 readHelpDataFile();
231 m_bHelpDataFileRead = true;
233 return m_aPath;
235 else
236 return get_id();
241 OUString URLParameter::get_the_title()
243 if(m_bUseDB) {
244 if( ! m_bHelpDataFileRead )
245 readHelpDataFile();
246 m_bHelpDataFileRead = true;
248 return m_aTitle;
250 else
251 return OUString();
255 OUString URLParameter::get_the_jar()
257 if(m_bUseDB) {
258 if( ! m_bHelpDataFileRead )
259 readHelpDataFile();
260 m_bHelpDataFileRead = true;
262 return m_aJar;
264 else
265 return get_module() + ".jar";
269 void URLParameter::readHelpDataFile()
271 if( get_id().isEmpty() )
272 return;
274 OUString aModule = get_module();
275 OUString aLanguage = get_language();
277 DataBaseIterator aDbIt( *m_pDatabases, aModule, aLanguage, false );
278 bool bSuccess = false;
280 const sal_Char* pData = NULL;
282 helpdatafileproxy::HDFData aHDFData;
283 OUString aExtensionPath;
284 OUString aExtensionRegistryPath;
285 while( true )
287 helpdatafileproxy::Hdf* pHdf = aDbIt.nextHdf( &aExtensionPath, &aExtensionRegistryPath );
288 if( !pHdf )
289 break;
291 OString keyStr( m_aId.getStr(),m_aId.getLength(),RTL_TEXTENCODING_UTF8 );
292 bSuccess = pHdf->getValueForKey( keyStr, aHDFData );
293 if( bSuccess )
295 pData = aHDFData.getData();
296 break;
300 if( bSuccess )
302 DbtToStringConverter converter( pData );
303 m_aTitle = converter.getTitle();
304 m_pDatabases->replaceName( m_aTitle );
305 m_aPath = converter.getFile();
306 m_aJar = converter.getDatabase();
307 if( !aExtensionPath.isEmpty() )
309 m_aJar = "?" + aExtensionPath + "?" + m_aJar;
310 m_aExtensionRegistryPath = aExtensionRegistryPath;
312 m_aTag = converter.getHash();
318 // Class encapsulating the transformation of the XInputStream to XHTML
321 class InputStreamTransformer
322 : public OWeakObject,
323 public XInputStream,
324 public XSeekable
326 public:
328 InputStreamTransformer( URLParameter* urlParam,
329 Databases* pDatatabases,
330 bool isRoot = false );
332 virtual ~InputStreamTransformer();
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;
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;
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;
350 virtual void SAL_CALL skipBytes( sal_Int32 nBytesToSkip ) throw( NotConnectedException,
351 BufferSizeExceededException,
352 IOException,
353 RuntimeException, std::exception ) SAL_OVERRIDE;
355 virtual sal_Int32 SAL_CALL available() throw( NotConnectedException,
356 IOException,
357 RuntimeException, std::exception ) SAL_OVERRIDE;
359 virtual void SAL_CALL closeInput() throw( NotConnectedException,
360 IOException,
361 RuntimeException, std::exception ) SAL_OVERRIDE;
363 virtual void SAL_CALL seek( sal_Int64 location ) throw( IllegalArgumentException,
364 IOException,
365 RuntimeException, std::exception ) SAL_OVERRIDE;
367 virtual sal_Int64 SAL_CALL getPosition() throw( IOException,RuntimeException, std::exception ) SAL_OVERRIDE;
369 virtual sal_Int64 SAL_CALL getLength() throw( IOException,RuntimeException, std::exception ) SAL_OVERRIDE;
371 void addToBuffer( const char* buffer,int len );
373 sal_Int8 const * getData() const { return reinterpret_cast<sal_Int8 const *>(buffer); }
375 sal_Int32 getLen() const { return sal_Int32( len ); }
377 private:
379 osl::Mutex m_aMutex;
381 int len,pos;
382 char *buffer;
387 void URLParameter::open( const Command& aCommand,
388 sal_Int32 CommandId,
389 const Reference< XCommandEnvironment >& Environment,
390 const Reference< XOutputStream >& xDataSink )
392 (void)aCommand;
393 (void)CommandId;
394 (void)Environment;
396 if( ! xDataSink.is() )
397 return;
399 if( isPicture() )
401 Reference< XInputStream > xStream;
402 Reference< XHierarchicalNameAccess > xNA =
403 m_pDatabases->jarFile( OUString( "picture.jar" ),
404 get_language() );
406 OUString path = get_path();
407 if( xNA.is() )
411 Any aEntry = xNA->getByHierarchicalName( path );
412 Reference< XActiveDataSink > xSink;
413 if( ( aEntry >>= xSink ) && xSink.is() )
414 xStream = xSink->getInputStream();
416 catch ( NoSuchElementException & )
420 if( xStream.is() )
422 sal_Int32 ret;
423 Sequence< sal_Int8 > aSeq( 4096 );
424 while( true )
428 ret = xStream->readBytes( aSeq,4096 );
429 xDataSink->writeBytes( aSeq );
430 if( ret < 4096 )
431 break;
433 catch( const Exception& )
435 break;
440 else
442 // a standard document or else an active help text, plug in the new input stream
443 InputStreamTransformer* p = new InputStreamTransformer( this,m_pDatabases,isRoot() );
446 xDataSink->writeBytes( Sequence< sal_Int8 >( p->getData(),p->getLen() ) );
448 catch( const Exception& )
451 delete p;
453 xDataSink->closeOutput();
458 void URLParameter::open( const Command& aCommand,
459 sal_Int32 CommandId,
460 const Reference< XCommandEnvironment >& Environment,
461 const Reference< XActiveDataSink >& xDataSink )
463 (void)aCommand;
464 (void)CommandId;
465 (void)Environment;
467 if( isPicture() )
469 Reference< XInputStream > xStream;
470 Reference< XHierarchicalNameAccess > xNA =
471 m_pDatabases->jarFile( OUString( "picture.jar" ),
472 get_language() );
474 OUString path = get_path();
475 if( xNA.is() )
479 Any aEntry = xNA->getByHierarchicalName( path );
480 Reference< XActiveDataSink > xSink;
481 if( ( aEntry >>= xSink ) && xSink.is() )
482 xStream = xSink->getInputStream();
484 catch ( NoSuchElementException & )
488 xDataSink->setInputStream( turnToSeekable(xStream) );
490 else
491 // a standard document or else an active help text, plug in the new input stream
492 xDataSink->setInputStream( new InputStreamTransformer( this,m_pDatabases,isRoot() ) );
496 void URLParameter::parse() throw( com::sun::star::ucb::IllegalIdentifierException )
498 m_aExpr = m_aURL;
500 sal_Int32 lstIdx = m_aExpr.lastIndexOf( '#' );
501 if( lstIdx != -1 )
502 m_aExpr = m_aExpr.copy( 0,lstIdx );
504 if( ! scheme() ||
505 ! name( module() ) ||
506 ! query() ||
507 m_aLanguage.isEmpty() ||
508 m_aSystem.isEmpty() )
509 throw com::sun::star::ucb::IllegalIdentifierException();
513 bool URLParameter::scheme()
515 // Correct extension help links as sometimes the
516 // module is missing resulting in a malformed URL
517 if( m_aExpr.startsWith("vnd.sun.star.help:///") )
519 sal_Int32 nLen = m_aExpr.getLength();
520 OUString aLastStr =
521 m_aExpr.copy(sal::static_int_cast<sal_uInt32>(nLen) - 6);
522 if( aLastStr == "DbPAR=" )
524 OUString aNewExpr = m_aExpr.copy( 0, 20 );
525 OUString aSharedStr("shared");
526 aNewExpr += aSharedStr;
527 aNewExpr += m_aExpr.copy( 20 );
528 aNewExpr += aSharedStr;
529 m_aExpr = aNewExpr;
533 for( sal_Int32 nPrefixLen = 20 ; nPrefixLen >= 18 ; --nPrefixLen )
535 if( m_aExpr.matchAsciiL( "vnd.sun.star.help://", nPrefixLen ) )
537 m_aExpr = m_aExpr.copy( nPrefixLen );
538 return true;
541 return false;
545 bool URLParameter::module()
547 sal_Int32 idx = 0,length = m_aExpr.getLength();
549 while( idx < length && isLetterOrDigit( (m_aExpr.getStr())[idx] ) )
550 ++idx;
552 if( idx != 0 )
554 m_aModule = m_aExpr.copy( 0,idx );
555 m_aExpr = m_aExpr.copy( idx );
556 return true;
558 else
559 return false;
564 bool URLParameter::name( bool modulePresent )
566 // if modulepresent, a name may be present, but must not
568 sal_Int32 length = m_aExpr.getLength();
570 if( length != 0 && (m_aExpr.getStr())[0] == '/' )
572 sal_Int32 idx = 1;
573 while( idx < length && (m_aExpr.getStr())[idx] != '?' )
574 ++idx;
576 if( idx != 1 && ! modulePresent )
577 return false;
578 else
580 m_aId = m_aExpr.copy( 1,idx-1 );
581 m_aExpr = m_aExpr.copy( idx );
585 return true;
589 bool URLParameter::query()
591 OUString query_;
593 if( m_aExpr.isEmpty() )
594 return true;
595 else if( (m_aExpr.getStr())[0] == '?' )
596 query_ = m_aExpr.copy( 1 ).trim();
597 else
598 return false;
601 bool ret = true;
602 sal_Int32 delimIdx,equalIdx;
603 OUString parameter,value;
605 while( !query_.isEmpty() )
607 delimIdx = query_.indexOf( '&' );
608 equalIdx = query_.indexOf( '=' );
609 parameter = query_.copy( 0,equalIdx ).trim();
610 if( delimIdx == -1 )
612 value = query_.copy( equalIdx + 1 ).trim();
613 query_.clear();
615 else
617 value = query_.copy( equalIdx+1,delimIdx - equalIdx - 1 ).trim();
618 query_ = query_.copy( delimIdx+1 ).trim();
621 if( parameter == "Language" )
622 m_aLanguage = value;
623 else if( parameter == "Device" )
624 m_aDevice = value;
625 else if( parameter == "Program" )
626 m_aProgram = value;
627 else if( parameter == "Eid" )
628 m_aEid = value;
629 else if( parameter == "UseDB" )
630 m_bUseDB = value != "no";
631 else if( parameter == "DbPAR" )
632 m_aDbPar = value;
633 else if( parameter == "Query" )
635 if( m_aQuery.isEmpty() )
636 m_aQuery = value;
637 else
638 m_aQuery += " " + value;
640 else if( parameter == "Scope" )
641 m_aScope = value;
642 else if( parameter == "System" )
643 m_aSystem = value;
644 else if( parameter == "HelpPrefix" )
645 m_aPrefix = rtl::Uri::decode(
646 value,
647 rtl_UriDecodeWithCharset,
648 RTL_TEXTENCODING_UTF8 );
649 else if( parameter == "HitCount" )
650 m_nHitCount = value.toInt32();
651 else if( parameter == "Active" )
652 m_aActive = value;
653 else if( parameter == "Version" )
654 ; // ignored (but accepted) in the build-in help, useful only for the online help
655 else
656 ret = false;
659 return ret;
662 struct UserData {
664 UserData( InputStreamTransformer* pTransformer,
665 URLParameter* pInitial,
666 Databases* pDatabases )
667 : m_pTransformer( pTransformer ),
668 m_pDatabases( pDatabases ),
669 m_pInitial( pInitial )
673 InputStreamTransformer* m_pTransformer;
674 Databases* m_pDatabases;
675 URLParameter* m_pInitial;
678 UserData *ugblData = 0;
680 extern "C" {
682 static int
683 fileMatch(const char * URI) {
684 if ((URI != NULL) && !strncmp(URI, "file:/", 6))
685 return 1;
686 return 0;
689 static int
690 zipMatch(const char * URI) {
691 if ((URI != NULL) && !strncmp(URI, "vnd.sun.star.zip:/", 18))
692 return 1;
693 return 0;
696 static int
697 helpMatch(const char * URI) {
698 if ((URI != NULL) && !strncmp(URI, "vnd.sun.star.help:/", 19))
699 return 1;
700 return 0;
703 static void *
704 fileOpen(const char *URI) {
705 osl::File *pRet = new osl::File(OUString(URI, strlen(URI), RTL_TEXTENCODING_UTF8));
706 pRet->open(osl_File_OpenFlag_Read);
707 return pRet;
710 static void *
711 zipOpen(SAL_UNUSED_PARAMETER const char *) {
712 OUString language,jar,path;
714 if( !ugblData->m_pInitial->get_eid().isEmpty() )
715 return (void*)(new Reference< XHierarchicalNameAccess >);
716 else
718 jar = ugblData->m_pInitial->get_jar();
719 language = ugblData->m_pInitial->get_language();
720 path = ugblData->m_pInitial->get_path();
723 Reference< XHierarchicalNameAccess > xNA =
724 ugblData->m_pDatabases->findJarFileForPath( jar, language, path );
726 Reference< XInputStream > xInputStream;
728 if( xNA.is() )
732 Any aEntry = xNA->getByHierarchicalName( path );
733 Reference< XActiveDataSink > xSink;
734 if( ( aEntry >>= xSink ) && xSink.is() )
735 xInputStream = xSink->getInputStream();
737 catch ( NoSuchElementException & )
742 if( xInputStream.is() )
744 return new Reference<XInputStream>(xInputStream);
746 return 0;
749 static void *
750 helpOpen(const char * URI) {
751 OUString language,jar,path;
753 URLParameter urlpar( OUString::createFromAscii( URI ),
754 ugblData->m_pDatabases );
756 jar = urlpar.get_jar();
757 language = urlpar.get_language();
758 path = urlpar.get_path();
760 Reference< XHierarchicalNameAccess > xNA =
761 ugblData->m_pDatabases->findJarFileForPath( jar, language, path );
763 Reference< XInputStream > xInputStream;
765 if( xNA.is() )
769 Any aEntry = xNA->getByHierarchicalName( path );
770 Reference< XActiveDataSink > xSink;
771 if( ( aEntry >>= xSink ) && xSink.is() )
772 xInputStream = xSink->getInputStream();
774 catch ( NoSuchElementException & )
779 if( xInputStream.is() )
780 return new Reference<XInputStream>(xInputStream);
781 return 0;
784 static int
785 helpRead(void * context, char * buffer, int len) {
786 Reference< XInputStream > *pRef = static_cast<Reference< XInputStream >*>(context);
788 Sequence< sal_Int8 > aSeq;
789 len = (*pRef)->readBytes( aSeq,len);
790 memcpy(buffer, aSeq.getConstArray(), len);
792 return len;
795 static int
796 zipRead(void * context, char * buffer, int len) {
797 return helpRead(context, buffer, len);
800 static int
801 fileRead(void * context, char * buffer, int len) {
802 int nRead = 0;
803 osl::File *pFile = static_cast<osl::File*>(context);
804 if (pFile)
806 sal_uInt64 uRead = 0;
807 if (osl::FileBase::E_None == pFile->read(buffer, len, uRead))
808 nRead = static_cast<int>(uRead);
810 return nRead;
813 static int
814 uriClose(void * context) {
815 Reference< XInputStream > *pRef = static_cast<Reference< XInputStream >*>(context);
816 delete pRef;
817 return 0;
820 static int
821 fileClose(void * context) {
822 osl::File *pFile = static_cast<osl::File*>(context);
823 if (pFile)
825 pFile->close();
826 delete pFile;
828 return 0;
831 } // extern "C"
833 InputStreamTransformer::InputStreamTransformer( URLParameter* urlParam,
834 Databases* pDatabases,
835 bool isRoot )
836 : len( 0 ),
837 pos( 0 ),
838 buffer( new char[1] ) // Initializing with one element to avoid gcc compiler warning
840 if( isRoot )
842 delete[] buffer;
843 pDatabases->cascadingStylesheet( urlParam->get_language(),
844 &buffer,
845 &len );
847 else if( urlParam->isActive() )
849 delete[] buffer;
850 pDatabases->setActiveText( urlParam->get_module(),
851 urlParam->get_language(),
852 urlParam->get_id(),
853 &buffer,
854 &len );
856 else
858 UserData userData( this,urlParam,pDatabases );
860 // Uses the implementation detail, that OString::getStr returns a zero terminated character-array
862 const char* parameter[47];
863 OString parString[46];
864 int last = 0;
866 parString[last++] = "Program";
867 OString aPureProgramm( urlParam->getByName( "Program" ) );
868 parString[last++] = OString('\'') + aPureProgramm + OString('\'');
869 parString[last++] = "Database";
870 parString[last++] = OString('\'') + urlParam->getByName( "DatabasePar" ) + OString('\'');
871 parString[last++] = "Id";
872 parString[last++] = OString('\'') + urlParam->getByName( "Id" ) + OString('\'');
873 parString[last++] = "Path";
874 OString aPath( urlParam->getByName( "Path" ) );
875 parString[last++] = OString('\'') + aPath + OString('\'');
877 OString aPureLanguage = urlParam->getByName( "Language" );
878 parString[last++] = "Language";
879 parString[last++] = OString('\'') + aPureLanguage + OString('\'');
880 parString[last++] = "System";
881 parString[last++] = OString('\'') + urlParam->getByName( "System" ) + OString('\'');
882 parString[last++] = "productname";
883 parString[last++] = OString('\'') + OString(
884 pDatabases->getProductName().getStr(),
885 pDatabases->getProductName().getLength(),
886 RTL_TEXTENCODING_UTF8 ) + OString('\'');
887 parString[last++] = "productversion";
888 parString[last++] = OString('\'') +
889 OString( pDatabases->getProductVersion().getStr(),
890 pDatabases->getProductVersion().getLength(),
891 RTL_TEXTENCODING_UTF8 ) + OString('\'');
893 parString[last++] = "imgtheme";
894 parString[last++] = OString('\'') + pDatabases->getImageTheme() + OString('\'');
895 parString[last++] = "hp";
896 parString[last++] = OString('\'') + urlParam->getByName( "HelpPrefix" ) + OString('\'');
898 if( !parString[last-1].isEmpty() )
900 parString[last++] = "sm";
901 parString[last++] = "'vnd.sun.star.help%3A%2F%2F'";
902 parString[last++] = "qm";
903 parString[last++] = "'%3F'";
904 parString[last++] = "es";
905 parString[last++] = "'%3D'";
906 parString[last++] = "am";
907 parString[last++] = "'%26'";
908 parString[last++] = "cl";
909 parString[last++] = "'%3A'";
910 parString[last++] = "sl";
911 parString[last++] = "'%2F'";
912 parString[last++] = "hm";
913 parString[last++] = "'%23'";
914 parString[last++] = "cs";
915 parString[last++] = "'css'";
917 parString[last++] = "vendorname";
918 parString[last++] = OString("''");
919 parString[last++] = "vendorversion";
920 parString[last++] = OString("''");
921 parString[last++] = "vendorshort";
922 parString[last++] = OString("''");
925 // Do we need to add extension path?
926 OUString aExtensionPath;
927 OUString aJar = urlParam->get_jar();
929 bool bAddExtensionPath = false;
930 OUString aExtensionRegistryPath;
931 sal_Int32 nQuestionMark1 = aJar.indexOf( '?' );
932 sal_Int32 nQuestionMark2 = aJar.lastIndexOf( '?' );
933 if( nQuestionMark1 != -1 && nQuestionMark2 != -1 && nQuestionMark1 != nQuestionMark2 )
935 aExtensionPath = aJar.copy( nQuestionMark1 + 1, nQuestionMark2 - nQuestionMark1 - 1 );
936 aExtensionRegistryPath = urlParam->get_ExtensionRegistryPath();
937 bAddExtensionPath = true;
939 else
941 // Path not yet specified, search directly
942 Reference< XHierarchicalNameAccess > xNA = pDatabases->findJarFileForPath
943 ( aJar, urlParam->get_language(), urlParam->get_path(), &aExtensionPath, &aExtensionRegistryPath );
944 if( xNA.is() && !aExtensionPath.isEmpty() )
945 bAddExtensionPath = true;
948 if( bAddExtensionPath )
950 Reference< XComponentContext > xContext(
951 comphelper::getProcessComponentContext() );
953 OUString aOUExpandedExtensionPath = Databases::expandURL( aExtensionRegistryPath, xContext );
954 OString aExpandedExtensionPath = OUStringToOString( aOUExpandedExtensionPath, osl_getThreadTextEncoding() );
956 parString[last++] = "ExtensionPath";
957 parString[last++] = OString('\'') + aExpandedExtensionPath + OString('\'');
959 // ExtensionId
960 OString aPureExtensionId;
961 sal_Int32 iSlash = aPath.indexOf( '/' );
962 if( iSlash != -1 )
963 aPureExtensionId = aPath.copy( 0, iSlash );
965 parString[last++] = "ExtensionId";
966 parString[last++] = OString('\'') + aPureExtensionId + OString('\'');
969 for( int i = 0; i < last; ++i )
970 parameter[i] = parString[i].getStr();
971 parameter[last] = 0;
973 OUString xslURL = pDatabases->getInstallPathAsURL();
975 OString xslURLascii(
976 xslURL.getStr(),
977 xslURL.getLength(),
978 RTL_TEXTENCODING_UTF8);
979 xslURLascii += "main_transform.xsl";
981 ugblData = &userData;
983 xmlInitParser();
984 xmlRegisterInputCallbacks(zipMatch, zipOpen, zipRead, uriClose);
985 xmlRegisterInputCallbacks(helpMatch, helpOpen, helpRead, uriClose);
986 xmlRegisterInputCallbacks(fileMatch, fileOpen, fileRead, fileClose);
988 xsltStylesheetPtr cur =
989 xsltParseStylesheetFile(reinterpret_cast<const xmlChar *>(xslURLascii.getStr()));
991 xmlDocPtr doc = xmlParseFile("vnd.sun.star.zip:/");
993 xmlDocPtr res = xsltApplyStylesheet(cur, doc, parameter);
994 if (res)
996 xmlChar *doc_txt_ptr=0;
997 int doc_txt_len;
998 xsltSaveResultToString(&doc_txt_ptr, &doc_txt_len, res, cur);
999 addToBuffer(reinterpret_cast<char*>(doc_txt_ptr), doc_txt_len);
1000 xmlFree(doc_txt_ptr);
1002 xmlPopInputCallbacks(); //filePatch
1003 xmlPopInputCallbacks(); //helpPatch
1004 xmlPopInputCallbacks(); //zipMatch
1005 xmlFreeDoc(res);
1006 xmlFreeDoc(doc);
1007 xsltFreeStylesheet(cur);
1012 InputStreamTransformer::~InputStreamTransformer()
1014 delete[] buffer;
1018 Any SAL_CALL InputStreamTransformer::queryInterface( const Type& rType ) throw( RuntimeException, std::exception )
1020 Any aRet = ::cppu::queryInterface( rType,
1021 (static_cast< XInputStream* >(this)),
1022 (static_cast< XSeekable* >(this)) );
1024 return aRet.hasValue() ? aRet : OWeakObject::queryInterface( rType );
1029 void SAL_CALL InputStreamTransformer::acquire() throw()
1031 OWeakObject::acquire();
1036 void SAL_CALL InputStreamTransformer::release() throw()
1038 OWeakObject::release();
1043 sal_Int32 SAL_CALL InputStreamTransformer::readBytes( Sequence< sal_Int8 >& aData,sal_Int32 nBytesToRead )
1044 throw( NotConnectedException,
1045 BufferSizeExceededException,
1046 IOException,
1047 RuntimeException, std::exception)
1049 osl::MutexGuard aGuard( m_aMutex );
1051 int curr,available_ = len-pos;
1052 if( nBytesToRead <= available_ )
1053 curr = nBytesToRead;
1054 else
1055 curr = available_;
1057 if( 0 <= curr && aData.getLength() < curr )
1058 aData.realloc( curr );
1060 for( int k = 0; k < curr; ++k )
1061 aData[k] = buffer[pos++];
1063 return curr > 0 ? curr : 0;
1067 sal_Int32 SAL_CALL InputStreamTransformer::readSomeBytes( Sequence< sal_Int8 >& aData,sal_Int32 nMaxBytesToRead )
1068 throw( NotConnectedException,
1069 BufferSizeExceededException,
1070 IOException,
1071 RuntimeException, std::exception)
1073 return readBytes( aData,nMaxBytesToRead );
1078 void SAL_CALL InputStreamTransformer::skipBytes( sal_Int32 nBytesToSkip ) throw( NotConnectedException,
1079 BufferSizeExceededException,
1080 IOException,
1081 RuntimeException, std::exception )
1083 osl::MutexGuard aGuard( m_aMutex );
1084 while( nBytesToSkip-- ) ++pos;
1089 sal_Int32 SAL_CALL InputStreamTransformer::available() throw( NotConnectedException,
1090 IOException,
1091 RuntimeException, std::exception )
1093 osl::MutexGuard aGuard( m_aMutex );
1094 return len-pos > 0 ? len - pos : 0 ;
1099 void SAL_CALL InputStreamTransformer::closeInput() throw( NotConnectedException,
1100 IOException,
1101 RuntimeException, std::exception )
1107 void SAL_CALL InputStreamTransformer::seek( sal_Int64 location ) throw( IllegalArgumentException,
1108 IOException,
1109 RuntimeException, std::exception )
1111 osl::MutexGuard aGuard( m_aMutex );
1112 if( location < 0 )
1113 throw IllegalArgumentException();
1114 else
1115 pos = sal::static_int_cast<sal_Int32>( location );
1117 if( pos > len )
1118 pos = len;
1123 sal_Int64 SAL_CALL InputStreamTransformer::getPosition() throw( IOException,
1124 RuntimeException, std::exception )
1126 osl::MutexGuard aGuard( m_aMutex );
1127 return sal_Int64( pos );
1132 sal_Int64 SAL_CALL InputStreamTransformer::getLength() throw( IOException,RuntimeException, std::exception )
1134 osl::MutexGuard aGuard( m_aMutex );
1136 return len;
1140 void InputStreamTransformer::addToBuffer( const char* buffer_,int len_ )
1142 osl::MutexGuard aGuard( m_aMutex );
1144 char* tmp = buffer;
1145 buffer = new char[ len+len_ ];
1146 memcpy( (void*)(buffer),(void*)(tmp),sal_uInt32( len ) );
1147 memcpy( (void*)(buffer+len),(void*)(buffer_),sal_uInt32( len_ ) );
1148 delete[] tmp;
1149 len += len_;
1152 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */