@@ -, +, @@ --- main/extensions/prj/build.lst | 14 +- main/extensions/prj/d.lst | 5 + main/extensions/source/plugin/aqua/macmgr.cxx | 648 +++++++++++ main/extensions/source/plugin/aqua/makefile.mk | 71 ++ main/extensions/source/plugin/aqua/sysplug.cxx | 804 ++++++++++++++ main/extensions/source/plugin/base/context.cxx | 352 ++++++ main/extensions/source/plugin/base/evtlstnr.cxx | 60 + main/extensions/source/plugin/base/makefile.mk | 66 ++ main/extensions/source/plugin/base/manager.cxx | 221 ++++ main/extensions/source/plugin/base/multiplx.cxx | 328 ++++++ main/extensions/source/plugin/base/nfuncs.cxx | 696 ++++++++++++ main/extensions/source/plugin/base/plcom.cxx | 67 ++ main/extensions/source/plugin/base/plctrl.cxx | 319 ++++++ main/extensions/source/plugin/base/plmodel.cxx | 199 ++++ main/extensions/source/plugin/base/service.cxx | 74 ++ main/extensions/source/plugin/base/xplugin.cxx | 1159 ++++++++++++++++++++ .../source/plugin/inc/plugin/aqua/sysplug.hxx | 163 +++ main/extensions/source/plugin/inc/plugin/impl.hxx | 426 +++++++ main/extensions/source/plugin/inc/plugin/model.hxx | 133 +++ .../source/plugin/inc/plugin/multiplx.hxx | 163 +++ main/extensions/source/plugin/inc/plugin/plcom.hxx | 81 ++ .../extensions/source/plugin/inc/plugin/plctrl.hxx | 177 +++ .../source/plugin/inc/plugin/unx/mediator.hxx | 179 +++ .../source/plugin/inc/plugin/unx/plugcon.hxx | 247 +++++ .../source/plugin/inc/plugin/unx/sysplug.hxx | 79 ++ .../source/plugin/inc/plugin/win/sysplug.hxx | 121 ++ main/extensions/source/plugin/unx/makefile.mk | 106 ++ main/extensions/source/plugin/unx/mediator.cxx | 305 ++++++ main/extensions/source/plugin/unx/npnapi.cxx | 913 +++++++++++++++ main/extensions/source/plugin/unx/nppapi.cxx | 617 +++++++++++ main/extensions/source/plugin/unx/npwrap.cxx | 511 +++++++++ main/extensions/source/plugin/unx/plugcon.cxx | 278 +++++ main/extensions/source/plugin/unx/sysplug.cxx | 127 +++ main/extensions/source/plugin/unx/unxmgr.cxx | 311 ++++++ main/extensions/source/plugin/util/makefile.mk | 113 ++ main/extensions/source/plugin/util/makefile.pmk | 44 + main/extensions/source/plugin/util/pl.component | 33 + main/extensions/source/plugin/win/makefile.mk | 61 ++ main/extensions/source/plugin/win/sysplug.cxx | 439 ++++++++ main/extensions/source/plugin/win/winmgr.cxx | 479 ++++++++ main/postprocess/packcomponents/makefile.mk | 1 + main/scp2/source/ooo/file_library_ooo.scp | 6 + 42 files changed, 11195 insertions(+), 1 deletion(-) create mode 100644 main/extensions/source/plugin/aqua/macmgr.cxx create mode 100644 main/extensions/source/plugin/aqua/makefile.mk create mode 100644 main/extensions/source/plugin/aqua/sysplug.cxx create mode 100644 main/extensions/source/plugin/base/context.cxx create mode 100644 main/extensions/source/plugin/base/evtlstnr.cxx create mode 100644 main/extensions/source/plugin/base/makefile.mk create mode 100644 main/extensions/source/plugin/base/manager.cxx create mode 100644 main/extensions/source/plugin/base/multiplx.cxx create mode 100644 main/extensions/source/plugin/base/nfuncs.cxx create mode 100644 main/extensions/source/plugin/base/plcom.cxx create mode 100644 main/extensions/source/plugin/base/plctrl.cxx create mode 100644 main/extensions/source/plugin/base/plmodel.cxx create mode 100644 main/extensions/source/plugin/base/service.cxx create mode 100644 main/extensions/source/plugin/base/xplugin.cxx create mode 100644 main/extensions/source/plugin/inc/plugin/aqua/sysplug.hxx create mode 100644 main/extensions/source/plugin/inc/plugin/impl.hxx create mode 100644 main/extensions/source/plugin/inc/plugin/model.hxx create mode 100644 main/extensions/source/plugin/inc/plugin/multiplx.hxx create mode 100644 main/extensions/source/plugin/inc/plugin/plcom.hxx create mode 100644 main/extensions/source/plugin/inc/plugin/plctrl.hxx create mode 100644 main/extensions/source/plugin/inc/plugin/unx/mediator.hxx create mode 100644 main/extensions/source/plugin/inc/plugin/unx/plugcon.hxx create mode 100644 main/extensions/source/plugin/inc/plugin/unx/sysplug.hxx create mode 100644 main/extensions/source/plugin/inc/plugin/win/sysplug.hxx create mode 100644 main/extensions/source/plugin/unx/makefile.mk create mode 100644 main/extensions/source/plugin/unx/mediator.cxx create mode 100644 main/extensions/source/plugin/unx/npnapi.cxx create mode 100644 main/extensions/source/plugin/unx/nppapi.cxx create mode 100644 main/extensions/source/plugin/unx/npwrap.cxx create mode 100644 main/extensions/source/plugin/unx/plugcon.cxx create mode 100644 main/extensions/source/plugin/unx/sysplug.cxx create mode 100644 main/extensions/source/plugin/unx/unxmgr.cxx create mode 100644 main/extensions/source/plugin/util/makefile.mk create mode 100644 main/extensions/source/plugin/util/makefile.pmk create mode 100644 main/extensions/source/plugin/util/pl.component create mode 100644 main/extensions/source/plugin/win/makefile.mk create mode 100644 main/extensions/source/plugin/win/sysplug.cxx create mode 100644 main/extensions/source/plugin/win/winmgr.cxx --- a/main/extensions/prj/build.lst +++ a/main/extensions/prj/build.lst @@ -1,4 +1,4 @@ -ex extensions : officecfg L10N:l10n rdbmaker svx SANE:sane TWAIN:twain offuh stoc ZLIB:zlib CURL:curl LIBXSLT:libxslt NULL +ex extensions : officecfg L10N:l10n rdbmaker svx SANE:sane TWAIN:twain offuh stoc ZLIB:zlib CURL:curl LIBXSLT:libxslt MOZ:moz SO:moz_prebuilt NULL ex extensions usr1 - all ex_mkout NULL ex extensions\inc nmake - all ex_inc NULL @@ -22,6 +22,18 @@ ex extensions\source\config\ldap nmake - all ex_ldap ex_inc N ex extensions\source\update\feed nmake - all ex_updchkfeed ex_inc NULL ex extensions\source\update\check nmake - all ex_updchk ex_inc NULL ex extensions\source\update\ui nmake - all ex_updchkui ex_inc NULL + + +ex extensions\source\plugin\workben get - all ex_plwkb ex_inc NULL +ex extensions\source\plugin\inc\plugin\win get - all ex_piwi ex_inc NULL +ex extensions\source\plugin\inc\plugin\unx get - all ex_piux ex_inc NULL +ex extensions\source\plugin\aqua nmake - u ex_plaqua ex_plbase NULL +ex extensions\source\plugin\base nmake - all ex_plbase ex_inc NULL +ex extensions\source\plugin\win nmake - w ex_plwin ex_plbase ex_inc NULL +ex extensions\source\plugin\unx nmake - u ex_plunx ex_inc NULL +ex extensions\source\plugin\util nmake - all ex_plutil ex_plbase ex_plunx.u ex_plwin.w ex_plaqua.u ex_inc NULL + + ex extensions\util nmake - all ex_util ex_preload ex_abpilot ex_dbpilots ex_logging ex_ldap ex_propctrlr ex_bib ex_oooimprovecore NULL # Fails at the moment --- a/main/extensions/prj/d.lst +++ a/main/extensions/prj/d.lst @@ -50,3 +50,8 @@ mkdir: %_DEST%\xml%_EXT%\registry\spool\org\openoffice\Office\Logging ..\%__SRC%\misc\updchk.component %_DEST%\xml%_EXT%\updchk.component ..\%__SRC%\misc\updchk.uno.component %_DEST%\xml%_EXT%\updchk.uno.component ..\%__SRC%\misc\xmx.component %_DEST%\xml%_EXT%\xmx.component + + +..\%__SRC%\bin\pluginapp.bin %_DEST%\bin%_EXT%\pluginapp.bin +..\%__SRC%\misc\pl.component %_DEST%\xml%_EXT%\pl.component + --- a/main/extensions/source/plugin/aqua/macmgr.cxx +++ a/main/extensions/source/plugin/aqua/macmgr.cxx @@ -0,0 +1,648 @@ +/************************************************************** + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + *************************************************************/ + + + +#include "rtl/ustrbuf.hxx" +#include "rtl/strbuf.hxx" + +#include "plugin/impl.hxx" +#include "osl/file.h" +#include "osl/module.hxx" + +using namespace rtl; +using rtl::OUStringBuffer; +using rtl::OUStringToOString; +using rtl::OString; +using rtl::OStringBuffer; +using rtl::OStringToOUString + +using namespace std; +using namespace com::sun::star::uno; +using namespace com::sun::star::plugin; + +namespace plugstringhelper +{ + +OUString getString( CFStringRef i_xString ) +{ + OUStringBuffer aBuf; + if( i_xString ) + { + CFIndex nChars = CFStringGetLength( i_xString ); + CFRange aRange = { 0, nChars }; + aBuf.setLength( nChars ); + CFStringGetCharacters( i_xString, aRange, static_cast< UniChar* >(const_cast(aBuf.getStr())) ); + } + return aBuf.makeStringAndClear(); +} + +OUString getString( CFURLRef i_xURL ) +{ + CFStringRef xString = CFURLGetString( i_xURL ); + return getString( xString ); +} + +CFMutableStringRef createString( const OUString& i_rString ) +{ + CFMutableStringRef xString = CFStringCreateMutable( NULL, 0 ); + if( xString ) + CFStringAppendCharacters( xString, i_rString.getStr(), i_rString.getLength() ); + return xString; +} + +CFURLRef createURL( const OUString& i_rString ) +{ + + CFMutableStringRef xMutableString = createString( i_rString ); + CFURLRef xURL = CFURLCreateWithString( NULL, xMutableString, NULL ); + CFRelease( xMutableString ); + return xURL; +} + +OUString getURLFromPath( const OUString& i_rPath ) +{ + CFMutableStringRef xMutableString = createString( i_rPath ); + CFURLRef xURL = CFURLCreateWithFileSystemPath( NULL, xMutableString, kCFURLPOSIXPathStyle, true ); + CFRelease( xMutableString ); + CFStringRef xString = CFURLGetString( xURL ); + OUString aRet = getString( xString ); + CFRelease( xURL ); + return aRet; +} + +CFURLRef createURLFromPath( const OUString& i_rPath ) +{ + CFMutableStringRef xMutableString = createString( i_rPath ); + CFURLRef xURL = CFURLCreateWithFileSystemPath( NULL, xMutableString, kCFURLPOSIXPathStyle, true ); + return xURL; +} + +OUString CFURLtoOSLURL( CFURLRef i_xURL ) +{ + // make URL absolute + CFURLRef xAbsURL = CFURLCopyAbsoluteURL( i_xURL ); + // copy system path + CFStringRef xSysPath = CFURLCopyFileSystemPath( xAbsURL ? xAbsURL : i_xURL, kCFURLPOSIXPathStyle ); + if( xAbsURL ) + CFRelease( xAbsURL ); + OUString aSysPath( getString( xSysPath ) ); + CFRelease( xSysPath ); + OUString aFileURL; + osl_getFileURLFromSystemPath( aSysPath.pData, &aFileURL.pData ); + return aFileURL; +} + +} + +using namespace plugstringhelper; + +static int parsePlist( CFBundleRef i_xBundle, const OUString& i_rBundleURL , list< PluginDescription* >& io_rDescriptions ) +{ + CFTypeRef xMimeDict = CFBundleGetValueForInfoDictionaryKey( i_xBundle, CFSTR("WebPluginMIMETypes")); + int nMimetypes = 0; + if( xMimeDict == 0 || + CFGetTypeID(xMimeDict) != CFDictionaryGetTypeID() || + (nMimetypes = CFDictionaryGetCount( static_cast(xMimeDict))) <= 0 ) + { + return 0; + } + + // prepare an array of key and value refs + std::vector< CFTypeRef > aKeys( nMimetypes, CFTypeRef(NULL) ); + std::vector< CFTypeRef > aValues( nMimetypes, CFTypeRef(NULL) ); + CFDictionaryGetKeysAndValues(static_cast(xMimeDict), &aKeys[0], &aValues[0] ); + + int nAdded = 0; + for( int i = 0; i < nMimetypes; i++ ) + { + // get the mimetype + CFTypeRef xKey = aKeys[i]; + if( ! xKey || CFGetTypeID(xKey) != CFStringGetTypeID() ) + continue; + OUString aMimetype = getString( (CFStringRef)xKey ); + + // the correspoding value should be a dictionary + CFTypeRef xDict = aValues[i]; + if( ! xDict || CFGetTypeID( xDict ) != CFDictionaryGetTypeID() ) + continue; + + // get the extension list + CFTypeRef xExtArray = CFDictionaryGetValue( (CFDictionaryRef)xDict, CFSTR("WebPluginExtensions" ) ); + if( !xExtArray || CFGetTypeID( xExtArray ) != CFArrayGetTypeID() ) + continue; + + OUStringBuffer aExtBuf; + int nExtensions = CFArrayGetCount( (CFArrayRef)xExtArray ); + for( int n = 0; n < nExtensions; n++ ) + { + CFTypeRef xExt = CFArrayGetValueAtIndex( (CFArrayRef)xExtArray, n ); + if( xExt && CFGetTypeID( xExt ) == CFStringGetTypeID() ) + { + if( aExtBuf.getLength() > 0 ) + aExtBuf.append( sal_Unicode(';') ); + OUString aExt( getString( (CFStringRef)xExt ) ); + if( aExt.indexOfAsciiL( "*.", 2 ) != 0 ) + aExtBuf.appendAscii( "*." ); + aExtBuf.append( aExt ); + } + } + + // get the description string + CFTypeRef xDescString = CFDictionaryGetValue( (CFDictionaryRef)xDict, CFSTR("WebPluginTypeDescription" ) ); + if( !xDescString || CFGetTypeID( xDescString ) != CFStringGetTypeID() ) + continue; + OUString aDescription = getString( (CFStringRef)xDescString ); + + PluginDescription* pNew = new PluginDescription; + // set plugin name (path to library) + pNew->PluginName = i_rBundleURL; + // set mimetype + pNew->Mimetype = aMimetype; + // set extension line + pNew->Extension = aExtBuf.makeStringAndClear(); + // set description + pNew->Description= aDescription; + + io_rDescriptions.push_back( pNew ); + nAdded++; + +#if OSL_DEBUG_LEVEL > 1 + fprintf( stderr, + "Inserting from PList:\n" + " Mimetype: %s\n" + " Extension: %s\n" + " Description: %s\n", + OUStringToOString( pNew->Mimetype, RTL_TEXTENCODING_UTF8 ).getStr(), + OUStringToOString( pNew->Extension, RTL_TEXTENCODING_UTF8 ).getStr(), + OUStringToOString( pNew->Description, RTL_TEXTENCODING_UTF8 ).getStr() + ); +#endif + + } + + return nAdded; +} + +static int parseMimeString( const OUString& i_rBundleURL , list< PluginDescription* >& io_rDescriptions, const char* i_pMime ) +{ + if( ! i_pMime ) + return 0; + + rtl_TextEncoding aEncoding = osl_getThreadTextEncoding(); + + OStringBuffer aMIME; + aMIME.append( i_pMime ); + + if( aMIME.getLength() < 1 ) + return 0; + + OString aLine = aMIME.makeStringAndClear(); + + int nAdded = 0; + sal_Int32 nIndex = 0; + while( nIndex != -1 ) + { + OString aType = aLine.getToken( 0, ';', nIndex ); + + sal_Int32 nTypeIndex = 0; + OString aMimetype = aType.getToken( 0, ':', nTypeIndex ); + OString aExtLine = aType.getToken( 0, ':', nTypeIndex ); + if( nTypeIndex < 0 ) // ensure at least three tokens + continue; + OString aDesc = aType.getToken( 0, ':', nTypeIndex ); + + // create extension list string + sal_Int32 nExtIndex = 0; + OStringBuffer aExtension; + while( nExtIndex != -1 ) + { + OString aExt = aExtLine.getToken( 0, ',', nExtIndex); + if( aExt.indexOf( "*." ) != 0 ) + aExtension.append( "*." ); + aExtension.append( aExt ); + if( nExtIndex != -1 ) + aExtension.append( ';' ); + } + + PluginDescription* pNew = new PluginDescription; + // set plugin name (path to library) + pNew->PluginName = i_rBundleURL; + // set mimetype + pNew->Mimetype = OStringToOUString( aMimetype, aEncoding ); + // set extension line + pNew->Extension = OStringToOUString( aExtension.makeStringAndClear(), aEncoding ); + // set description + pNew->Description= OStringToOUString( aDesc, aEncoding ); + io_rDescriptions.push_back( pNew ); + nAdded++; + +#if OSL_DEBUG_LEVEL > 1 + fprintf( stderr, + "Inserting from mime string:\n" + " Mimetype: %s\n" + " Extension: %s\n" + " Description: %s\n", + OUStringToOString( pNew->Mimetype, aEncoding ).getStr(), + OUStringToOString( pNew->Extension, aEncoding ).getStr(), + OUStringToOString( pNew->Description, aEncoding ).getStr() + ); +#endif + } + return nAdded; +} + +// this is so ugly it you want to tear your eyes out +static OUString GetNextPluginStringFromHandle(Handle h, short *index) +{ + char* pPascalBytes = (*h + *index); + sal_uInt32 nLen = (unsigned char)pPascalBytes[0]; + OStringBuffer aBuf( nLen ); + aBuf.append( pPascalBytes+1, nLen ); + *index += nLen + 1; + return OStringToOUString( aBuf.makeStringAndClear(), RTL_TEXTENCODING_UTF8 ); +} + +static int parseMimeResource( CFBundleRef i_xBundle, + oslModule& i_rMod, + const OUString& i_rBundleURL, + list< PluginDescription* >& io_rDescriptions ) +{ + int nAdded = 0; + // just to hurt our eyes more there is an alternative mimetype function plus the possibility + // of a resource fork. Must be a case of think different. + #if __LP64__ + int + #else + SInt16 + #endif + xRes = 0; + BPSupportedMIMETypes aMIMETypesStrangeStruct = {kBPSupportedMIMETypesStructVers_1, NULL, NULL}; + + BP_GetSupportedMIMETypesUPP pBPGetSupp = (BP_GetSupportedMIMETypesUPP)osl_getAsciiFunctionSymbol( i_rMod, "BP_GetSupportedMIMETypes" ); + if( pBPGetSupp && + noErr == pBPGetSupp( &aMIMETypesStrangeStruct, 0 ) && + aMIMETypesStrangeStruct.typeStrings ) + { + HLock( aMIMETypesStrangeStruct.typeStrings ); + if( aMIMETypesStrangeStruct.infoStrings ) // it's possible some plugins have infoStrings missing + HLock( aMIMETypesStrangeStruct.infoStrings ); + } + else // Try to get data from the resource fork + { + xRes = CFBundleOpenBundleResourceMap( i_xBundle ); + if( xRes > 0 ) + { + aMIMETypesStrangeStruct.typeStrings = Get1Resource('STR#', 128); + if( aMIMETypesStrangeStruct.typeStrings ) + { + DetachResource( aMIMETypesStrangeStruct.typeStrings ); + HLock( aMIMETypesStrangeStruct.typeStrings ); + aMIMETypesStrangeStruct.infoStrings = Get1Resource('STR#', 127); + if( aMIMETypesStrangeStruct.infoStrings ) + { + DetachResource( aMIMETypesStrangeStruct.infoStrings ); + HLock( aMIMETypesStrangeStruct.infoStrings ); + } + } + } + } + + if( aMIMETypesStrangeStruct.typeStrings && aMIMETypesStrangeStruct.infoStrings ) + { + short nVariantCount = (**(short**)aMIMETypesStrangeStruct.typeStrings) / 2; + // Fill in the info struct based on the data in the BPSupportedMIMETypes struct + // this is an array of pascal string of unknown (!) encoding + // whoever thought of this deserves a fair beating + short mimeIndex = 2; + short descriptionIndex = 2; + for( int i = 0; i < nVariantCount; i++ ) + { + OUString aMimetype = GetNextPluginStringFromHandle( aMIMETypesStrangeStruct.typeStrings, &mimeIndex ); + OUString aExtLine = GetNextPluginStringFromHandle( aMIMETypesStrangeStruct.typeStrings, &mimeIndex ); + OUString aDescription; + if( aMIMETypesStrangeStruct.infoStrings ) + aDescription = GetNextPluginStringFromHandle( aMIMETypesStrangeStruct.infoStrings, &descriptionIndex ); + + // create extension list string + sal_Int32 nExtIndex = 0; + OUStringBuffer aExtension; + while( nExtIndex != -1 ) + { + OUString aExt = aExtLine.getToken( 0, ',', nExtIndex); + if( aExt.indexOfAsciiL( "*.", 2 ) != 0 ) + aExtension.appendAscii( "*." ); + aExtension.append( aExt ); + if( nExtIndex != -1 ) + aExtension.append( sal_Unicode(';') ); + } + + PluginDescription* pNew = new PluginDescription; + // set plugin name (path to library) + pNew->PluginName = i_rBundleURL; + // set mimetype + pNew->Mimetype = aMimetype; + // set extension line + pNew->Extension = aExtension.makeStringAndClear(); + // set description + pNew->Description= aDescription; + io_rDescriptions.push_back( pNew ); + nAdded++; + + #if OSL_DEBUG_LEVEL > 1 + fprintf( stderr, + "Inserting from resource:\n" + " Mimetype: %s\n" + " Extension: %s\n" + " Description: %s\n", + OUStringToOString( pNew->Mimetype, RTL_TEXTENCODING_UTF8 ).getStr(), + OUStringToOString( pNew->Extension, RTL_TEXTENCODING_UTF8 ).getStr(), + OUStringToOString( pNew->Description, RTL_TEXTENCODING_UTF8 ).getStr() + ); + #endif + } + } + + + // clean up + if( aMIMETypesStrangeStruct.typeStrings ) + { + HUnlock( aMIMETypesStrangeStruct.typeStrings ); + DisposeHandle( aMIMETypesStrangeStruct.typeStrings ); + } + if( aMIMETypesStrangeStruct.infoStrings ) + { + HUnlock( aMIMETypesStrangeStruct.infoStrings ); + DisposeHandle( aMIMETypesStrangeStruct.infoStrings ); + } + if( xRes ) + CFBundleCloseBundleResourceMap( i_xBundle, xRes ); + + return nAdded; +} + +// check some known bad plugins to avoid crashes +static bool checkBlackList( CFBundleRef i_xBundle ) +{ + OUString aBundleName; + CFTypeRef bundlename = CFBundleGetValueForInfoDictionaryKey( i_xBundle, CFSTR("CFBundleName")); + if( bundlename && CFGetTypeID(bundlename) == CFStringGetTypeID() ) + aBundleName = getString( static_cast(bundlename) ); + + OUString aBundleVersion; + CFTypeRef bundleversion = CFBundleGetValueForInfoDictionaryKey( i_xBundle, CFSTR("CFBundleVersion")); + if( bundleversion && CFGetTypeID(bundleversion) == CFStringGetTypeID() ) + aBundleVersion = getString( static_cast(bundleversion) ); + + bool bReject = false; + // #i102735# VLC plugin prior to 1.0 tends to crash + if( aBundleName.equalsAscii( "VLC Plug-in" ) ) + { + sal_Int32 nIndex = 0; + OUString aMajor( aBundleVersion.getToken( 0, '.', nIndex ) ); + if( aMajor.toInt32() < 1 ) + { + bReject = true; + } + } + // #i103674# Garmin Communicator Plugin crashes + else if( aBundleName.equalsAscii( "Garmin Communicator Plugin" ) ) + { + bReject = true; + } + + #if OSL_DEBUG_LEVEL > 1 + if( bReject ) + fprintf( stderr, "rejecting plugin \"%s\" version %s\n", + OUStringToOString( aBundleName, RTL_TEXTENCODING_UTF8 ).getStr(), + OUStringToOString( aBundleVersion, RTL_TEXTENCODING_UTF8 ).getStr() + ); + #endif + + return bReject; +} + +static int getPluginDescriptions( CFBundleRef i_xBundle , list< PluginDescription* >& io_rDescriptions ) +{ + int nDescriptions = 0; + if( ! i_xBundle ) + return nDescriptions; + + if( checkBlackList( i_xBundle ) ) + return 0; + + OUString aPlugURL; + CFURLRef xURL = CFBundleCopyBundleURL( i_xBundle ); + aPlugURL = getString( xURL ); + CFRelease( xURL ); + + #if OSL_DEBUG_LEVEL > 1 + OUString aPlugName, aPlugDescription; + CFTypeRef name = CFBundleGetValueForInfoDictionaryKey( i_xBundle, CFSTR("WebPluginName")); + if( name && CFGetTypeID(name) == CFStringGetTypeID() ) + aPlugName = getString( static_cast(name) ); + + CFTypeRef description = CFBundleGetValueForInfoDictionaryKey( i_xBundle, CFSTR("WebPluginDescription")); + if( description && CFGetTypeID(description) == CFStringGetTypeID() ) + aPlugDescription = getString( static_cast(description) ); + + fprintf( stderr, "URL: %s\nname: %s\ndescription: %s\n", + OUStringToOString( aPlugURL, RTL_TEXTENCODING_UTF8 ).getStr(), + OUStringToOString( aPlugName, RTL_TEXTENCODING_UTF8 ).getStr(), + OUStringToOString( aPlugDescription, RTL_TEXTENCODING_UTF8 ).getStr() + ); + #endif + + + // get location of plugin library + CFURLRef xLibURL = CFBundleCopyExecutableURL( i_xBundle ); + if( ! xLibURL ) + return 0; + // get the file system path + OUString aModuleURL( CFURLtoOSLURL( xLibURL ) ); + CFRelease( xLibURL ); + + #if OSL_DEBUG_LEVEL > 1 + fprintf( stderr, "exec URL = %s\n", OUStringToOString( aModuleURL, RTL_TEXTENCODING_UTF8 ).getStr() ); + #endif + + /* TODO: originally the C++ wrapper for oslModule was used here, but that led to + mysterious crashes in the event loop (pointing to heap corruption). Why using + the C style oslModule should fix this is completely unknown. It may be that + we have just hidden the heap corruption a little more. + */ + oslModule aMod = osl_loadModule( aModuleURL.pData, SAL_LOADMODULE_DEFAULT ); + if( ! aMod ) + return 0; + + // check for at least the init function of a plugin + if( ! osl_getAsciiFunctionSymbol( aMod, "NP_Initialize") && + ! osl_getAsciiFunctionSymbol( aMod, "NP_GetEntryPoints" ) ) + { + return 0; + } + + // ask the plist of the bundle for mimetypes + nDescriptions = parsePlist( i_xBundle, aPlugURL, io_rDescriptions ); + if( nDescriptions ) + { + osl_unloadModule( aMod ); + return nDescriptions; + } + + // resolve the symbol that might get us the mimetypes + const char* (*pGetMimeDescription)() = (const char*(*)())osl_getAsciiFunctionSymbol( aMod, "_NP_GetMIMEDescription" ); + if( pGetMimeDescription ) + { + const char* pMime = pGetMimeDescription(); + if( pMime ) + { + nDescriptions = parseMimeString( aPlugURL, io_rDescriptions, pMime ); + if( nDescriptions ) + { + osl_unloadModule( aMod ); + return nDescriptions; + } + } + } + + // and as last resort check the resource of the bundle + nDescriptions = parseMimeResource( i_xBundle, aMod, aPlugURL, io_rDescriptions ); + osl_unloadModule( aMod ); + + return nDescriptions; +} + +// Unix specific implementation +static bool CheckPlugin( const OUString& rPath, list< PluginDescription* >& rDescriptions ) +{ +#if OSL_DEBUG_LEVEL > 1 + fprintf( stderr, "Trying path %s ... ", OUStringToOString( rPath, RTL_TEXTENCODING_UTF8 ).getStr() ); +#endif + CFURLRef xURL = createURL( rPath ); + + CFArrayRef xBundles = CFBundleCreateBundlesFromDirectory( NULL, xURL, CFSTR("plugin") ); + if( ! xBundles ) + return false; + + CFIndex nBundles = CFArrayGetCount( xBundles ); + +#if OSL_DEBUG_LEVEL > 1 + fprintf( stderr, "got %d bundles\n", (int)nBundles ); +#endif + + int nDescriptions = 0; + for( CFIndex i = 0; i < nBundles; i++ ) + { + CFBundleRef xBundle = (CFBundleRef)CFArrayGetValueAtIndex( xBundles, i ); + nDescriptions += getPluginDescriptions( xBundle, rDescriptions ); + + CFRelease( xBundle ); + } + CFRelease( xBundles ); + + + return nDescriptions > 0; +} + +static OUString FindFolderURL( FSVolumeRefNum vRefNum, OSType folderType ) +{ + OUString aRet; + + FSRef aFSRef; + OSErr err = FSFindFolder( vRefNum, folderType, kDontCreateFolder, &aFSRef ); + if( err == noErr ) + { + CFURLRef xURL = CFURLCreateFromFSRef( NULL, &aFSRef ); + aRet = getString( xURL ); + CFRelease( xURL ); + } + + return aRet; +} + +Sequence XPluginManager_Impl::impl_getPluginDescriptions() throw() +{ + static Sequence aDescriptions; + static sal_Bool bHavePlugins = sal_False; + if( ! bHavePlugins ) + { + std::list aPlugins; + + static const char* pNPXPluginPath = getenv( "MOZ_PLUGIN_PATH" ); + + // get directories + std::list< OUString > aPaths; + if( pNPXPluginPath ) + { + CFMutableStringRef xMutableString = CFStringCreateMutable( NULL, 0 ); + CFStringAppendCString( xMutableString, pNPXPluginPath, kCFStringEncodingUTF8 ); + CFURLRef xURL = CFURLCreateWithFileSystemPath( NULL, xMutableString, kCFURLPOSIXPathStyle, true ); + CFRelease( xMutableString ); + aPaths.push_back( getString( xURL ) ); + CFRelease( xURL ); + } + + OUString aPath = FindFolderURL( kUserDomain, kInternetPlugInFolderType ); + if( aPath.getLength() ) + aPaths.push_back( aPath ); + aPath = FindFolderURL( kLocalDomain, kInternetPlugInFolderType ); + if( aPath.getLength() ) + aPaths.push_back( aPath ); + aPath = FindFolderURL( kOnAppropriateDisk, kInternetPlugInFolderType ); + if( aPath.getLength() ) + aPaths.push_back( aPath ); + + + const Sequence< ::OUString >& rPaths( PluginManager::getAdditionalSearchPaths() ); + for( sal_Int32 i = 0; i < rPaths.getLength(); i++ ) + { + aPaths.push_back( getURLFromPath( rPaths.getConstArray()[i] ) ); + } + + for( std::list< OUString >::const_iterator it = aPaths.begin(); it != aPaths.end(); ++it ) + { + OUString aPath( *it ); +#if OSL_DEBUG_LEVEL > 1 + fprintf( stderr, "check path %s\n", OUStringToOString( *it, RTL_TEXTENCODING_UTF8 ).getStr() ); +#endif + CheckPlugin( aPath, aPlugins ); + } + + + // create return value + aDescriptions = Sequence( aPlugins.size() ); +#if OSL_DEBUG_LEVEL > 1 + fprintf( stderr, "found %d plugins\n", (int)aPlugins.size() ); +#endif + list::iterator iter; + sal_Int32 nPlug = 0; + for( iter = aPlugins.begin(); iter != aPlugins.end(); ++iter ) + { + aDescriptions.getArray()[ nPlug++ ] = **iter; + delete *iter; + } + aPlugins.clear(); + bHavePlugins = sal_True; + } + return aDescriptions; +} + --- a/main/extensions/source/plugin/aqua/makefile.mk +++ a/main/extensions/source/plugin/aqua/makefile.mk @@ -0,0 +1,71 @@ +#************************************************************** +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# +#************************************************************** + + +PRJ=..$/..$/.. + +PRJNAME=extensions +TARGET=plaqua +#ENABLE_EXCEPTIONS=TRUE +#TARGETTYPE=CUI + +.INCLUDE : ..$/util$/makefile.pmk + +.IF "$(GUIBASE)"!="aqua" || "$(WITH_MOZILLA)"=="NO" + +dummy: + @echo "Nothing to build for GUIBASE $(GUIBASE)." + +.ELSE + +# --- Files -------------------------------------------------------- + +INCPRE+=-I$(SOLARINCDIR)$/mozilla$/plugin +.IF "$(SOLAR_JAVA)" != "" +INCPRE+=-I$(SOLARINCDIR)$/mozilla$/java +INCPRE+=-I$(SOLARINCDIR)$/mozilla$/nspr +INCPRE+=-I$(SOLARINCDIR)$/npsdk +CDEFS+=-DOJI +.ENDIF + +.IF "$(GUIBASE)"=="aqua" +CFLAGSCXX+=$(OBJCXXFLAGS) +.ENDIF # "$(GUIBASE)"=="aqua" + +SLOFILES=\ + $(SLO)$/macmgr.obj \ + $(SLO)$/sysplug.obj + +#APP1TARGET=pluginapp.bin +#APP1OBJS=$(OBJFILES) +#APP1STDLIBS=\ +# $(TOOLSLIB) \ +# $(VOSLIB) \ +# $(SALLIB) + +#APP1DEF= $(MISC)$/$(TARGET).def + + +# --- Targets ------------------------------------------------------ + +.INCLUDE : target.mk + +.ENDIF # $(GUIBASE)==aqua --- a/main/extensions/source/plugin/aqua/sysplug.cxx +++ a/main/extensions/source/plugin/aqua/sysplug.cxx @@ -0,0 +1,804 @@ +/************************************************************** + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + *************************************************************/ + + +#include + +#include +#include +#include +#include + +#include + +extern NPNetscapeFuncs aNPNFuncs; + +#include + +using namespace rtl; +using namespace plugstringhelper; + +#if OSL_DEBUG_LEVEL > 1 +void TRACE( char const * s ); +void TRACEN( char const * s, long n ); +#else +#define TRACE(x) +#define TRACEN(x,n) +#endif + +struct FakeEventRecord : public EventRecord +{ + FakeEventRecord() + { + memset( this, 0, sizeof(EventRecord) ); + ::GetGlobalMouse( &where ); + when = ::TickCount(); + modifiers = ::GetCurrentEventKeyModifiers(); + } +}; + + +@interface OOoPluginView : NSView +{ + XPlugin_Impl* m_pImpl; + MacPluginComm* m_pCom; +} +-(id)initWithInstance: (XPlugin_Impl*)i_pImpl pluginComm: (MacPluginComm*)i_pCom frame: (NSRect)i_aRect; +-(void)drawRect: (NSRect)i_aRect; +-(BOOL)isOpaque; +-(BOOL)isFlipped; + +// NSResponder +-(void)mouseMoved: (NSEvent*)i_pEvent; +-(void)mouseDown: (NSEvent*)i_pEvent; +-(void)mouseDragged: (NSEvent*)i_pEvent; +-(void)mouseUp: (NSEvent*)i_pEvent; +-(void)rightMouseDown: (NSEvent*)i_pEvent; +-(void)rightMouseDragged: (NSEvent*)i_pEvent; +-(void)rightMouseUp: (NSEvent*)i_pEvent; +-(void)otherMouseDown: (NSEvent*)i_pEvent; +-(void)otherMouseDragged: (NSEvent*)i_pEvent; +-(void)otherMouseUp: (NSEvent*)i_pEvent; +-(void)mouseEntered: (NSEvent*)i_pEvent; +-(void)mouseExited: (NSEvent*)i_pEvent; +@end + +@implementation OOoPluginView +-(id)initWithInstance: (XPlugin_Impl*)i_pImpl pluginComm: (MacPluginComm*)i_pCom frame: (NSRect) i_aRect +{ + if( (self = [super initWithFrame: i_aRect]) ) + { + m_pImpl = i_pImpl; + m_pCom = i_pCom; + } + return self; +} + +-(void)drawRect: (NSRect) i_aRect +{ + m_pCom->drawView( m_pImpl ); +} + +-(BOOL)isOpaque +{ + return NO; +} + +-(BOOL)isFlipped +{ + return YES; +} + +// NSResponder +-(void)mouseMoved: (NSEvent*)i_pEvent +{ + FakeEventRecord aRec; + aRec.what = osEvt + 18; // NPEventType_AdjustCursorEvent + m_pCom->NPP_HandleEvent( m_pImpl->getNPPInstance(), &aRec ); +} + +-(void)mouseDown: (NSEvent*)i_pEvent; +{ + FakeEventRecord aRec; + aRec.what = mouseDown; + m_pCom->NPP_HandleEvent( m_pImpl->getNPPInstance(), &aRec ); +} + +-(void)mouseDragged: (NSEvent*)i_pEvent; +{ + FakeEventRecord aRec; + aRec.what = aRec.what = osEvt + 18; // NPEventType_AdjustCursorEvent + m_pCom->NPP_HandleEvent( m_pImpl->getNPPInstance(), &aRec ); +} + +-(void)mouseUp: (NSEvent*)i_pEvent; +{ + FakeEventRecord aRec; + aRec.what = mouseUp; + m_pCom->NPP_HandleEvent( m_pImpl->getNPPInstance(), &aRec ); +} + +-(void)rightMouseDown: (NSEvent*)i_pEvent; +{ + FakeEventRecord aRec; + aRec.what = mouseDown; + m_pCom->NPP_HandleEvent( m_pImpl->getNPPInstance(), &aRec ); +} + +-(void)rightMouseDragged: (NSEvent*)i_pEvent; +{ + FakeEventRecord aRec; + aRec.what = aRec.what = osEvt + 18; // NPEventType_AdjustCursorEvent + m_pCom->NPP_HandleEvent( m_pImpl->getNPPInstance(), &aRec ); +} + +-(void)rightMouseUp: (NSEvent*)i_pEvent; +{ + FakeEventRecord aRec; + aRec.what = mouseUp; + m_pCom->NPP_HandleEvent( m_pImpl->getNPPInstance(), &aRec ); +} + +-(void)otherMouseDown: (NSEvent*)i_pEvent; +{ + FakeEventRecord aRec; + aRec.what = mouseDown; + m_pCom->NPP_HandleEvent( m_pImpl->getNPPInstance(), &aRec ); +} + +-(void)otherMouseDragged: (NSEvent*)i_pEvent; +{ + FakeEventRecord aRec; + aRec.what = aRec.what = osEvt + 18; // NPEventType_AdjustCursorEvent + m_pCom->NPP_HandleEvent( m_pImpl->getNPPInstance(), &aRec ); +} + +-(void)otherMouseUp: (NSEvent*)i_pEvent; +{ + FakeEventRecord aRec; + aRec.what = mouseUp; + m_pCom->NPP_HandleEvent( m_pImpl->getNPPInstance(), &aRec ); +} + +-(void)mouseEntered: (NSEvent*)i_pEvent; +{ + FakeEventRecord aRec; + aRec.what = aRec.what = osEvt + 18; // NPEventType_AdjustCursorEvent + m_pCom->NPP_HandleEvent( m_pImpl->getNPPInstance(), &aRec ); +} + +-(void)mouseExited: (NSEvent*)i_pEvent; +{ + FakeEventRecord aRec; + aRec.what = aRec.what = osEvt + 18; // NPEventType_AdjustCursorEvent + m_pCom->NPP_HandleEvent( m_pImpl->getNPPInstance(), &aRec ); +} + +@end + +//-------------------------------------------------------------------------------------------------- +MacPluginComm::MacPluginComm( const rtl::OUString& i_rMimetype, const rtl::OUString& i_rBundle, NSView* i_pParent ) + : PluginComm( OUStringToOString( i_rBundle, RTL_TEXTENCODING_UTF8 ) ), + m_xBundle( NULL ), + m_hPlugLib( NULL ), + m_pNullTimer( NULL ) +{ + // initialize plugin function table + memset( &m_aNPPfuncs, 0, sizeof( m_aNPPfuncs ) ); + + // load the bundle + CFURLRef xURL = createURL( i_rBundle ); + m_xBundle = CFBundleCreate( NULL, xURL ); + CFRelease( xURL ); + if( m_xBundle ) + { + // ask the plugin library + // first get its location + CFURLRef xLibURL = CFBundleCopyExecutableURL( m_xBundle ); + if( xLibURL ) + { + // get the file system path + rtl::OUString aModuleURL( CFURLtoOSLURL( xLibURL ) ); + CFRelease( xLibURL ); + m_hPlugLib = osl_loadModule( aModuleURL.pData, SAL_LOADMODULE_DEFAULT ); + #if OSL_DEBUG_LEVEL > 1 + if( ! m_hPlugLib ) + fprintf( stderr, "module %s could not be loaded\n", OUStringToOString( aModuleURL, RTL_TEXTENCODING_UTF8 ).getStr() ); + #endif + } + #if OSL_DEBUG_LEVEL > 1 + else + fprintf( stderr, "bundle %s has no exectutable URL\n", OUStringToOString( i_rBundle, RTL_TEXTENCODING_UTF8 ).getStr() ); + #endif + } + else + { + #if OSL_DEBUG_LEVEL > 1 + fprintf( stderr, "bundle %s could not be loaded\n", OUStringToOString( i_rBundle, RTL_TEXTENCODING_UTF8 ).getStr() ); + #endif + } + + DBG_ASSERT( m_xBundle && m_hPlugLib, "loading plugin bundle failed!" ); + + + m_aNPPfuncs.size = sizeof( m_aNPPfuncs ); + m_aNPPfuncs.version = 0; + + + m_eCall = eNP_Initialize; + execute(); +} + +//-------------------------------------------------------------------------------------------------- +MacPluginComm::~MacPluginComm() +{ + if( m_hPlugLib ) + { + // NPP_Shutdown(); + NPError (*pShutdown)(); + if( retrieveFunction( "NP_Shutdown", (void**)&pShutdown ) ) + { + NPError nErr = (*pShutdown)(); (void)nErr; + DBG_ASSERT( nErr == NPERR_NO_ERROR, "NP_Shutdown() failed!" ); + } + osl_unloadModule( m_hPlugLib ); + } + if( m_xBundle ) + CFRelease( m_xBundle ); +} + +//-------------------------------------------------------------------------------------------------- +sal_Bool MacPluginComm::retrieveFunction( const char* i_pName, void** o_ppFunc ) const +{ + if( ! m_hPlugLib || ! o_ppFunc ) + return sal_False; + + *o_ppFunc = (void*)osl_getAsciiFunctionSymbol( m_hPlugLib, i_pName ); + + if( ! *o_ppFunc && m_xBundle ) + { + rtl::OUString aName( OUString::createFromAscii( *i_pName == '_' ? i_pName+1 : i_pName ) ); + CFStringRef xName = createString( aName ); + if( xName ) + { + *o_ppFunc = CFBundleGetFunctionPointerForName( m_xBundle, xName ); + CFRelease( xName ); + } + } + + return (*o_ppFunc != NULL); +} + +IMPL_LINK( MacPluginComm, NullTimerHdl, void*, EMPTYARG ) +{ + // note: this is a Timer handler, we are already protected by the SolarMutex + + FakeEventRecord aRec; + aRec.what = nullEvent; + aRec.where.h = aRec.where.v = 20000; + + for( std::list< XPlugin_Impl* >::iterator it = m_aNullEventClients.begin(); + it != m_aNullEventClients.end(); ++it ) + { + SysPlugData& rPlugData( (*it)->getSysPlugData() ); + if( rPlugData.m_pPlugView ) // for safety do not dispatch null events before first NPP_SetWindow + (*m_aNPPfuncs.event)( (*it)->getNPPInstance(), &aRec ); + } + + return 0; +} + +//-------------------------------------------------------------------------------------------------- + +long MacPluginComm::doIt() +{ + long nRet = 0; + switch( m_eCall ) + { + case eNP_Initialize: + { + TRACE( "eNP_Initialize" ); + NPError (*pInit)( NPNetscapeFuncs* ); + if( retrieveFunction( "NP_Initialize", (void**)&pInit ) ) + { + nRet = (*pInit)( &aNPNFuncs ); + + NPError nErr = NPERR_NO_ERROR; + NPError (*pEntry)( NPPluginFuncs* ); + retrieveFunction( "NP_GetEntryPoints", (void**)&pEntry ); + nErr = (*pEntry)( &m_aNPPfuncs ); + + DBG_ASSERT( nErr == NPERR_NO_ERROR, "NP_GetEntryPoints() failed!" ); + } + else + { + nRet = NPERR_GENERIC_ERROR; + } + DBG_ASSERT( nRet == NPERR_NO_ERROR, "### NP_Initialize() failed!" ); + } + break; + case eNPP_Destroy: + if( m_aNullEventClients.empty() ) + delete m_pNullTimer, m_pNullTimer = NULL; + + TRACE( "eNPP_Destroy" ); + nRet = (m_aNPPfuncs.destroy + ? (*m_aNPPfuncs.destroy)( + (NPP)m_aArgs[0], + (NPSavedData**)m_aArgs[1] ) + : NPERR_GENERIC_ERROR); + break; + case eNPP_DestroyStream: + TRACE( "eNPP_DestroyStream" ); + nRet = (m_aNPPfuncs.destroystream + ? (*m_aNPPfuncs.destroystream)( + (NPP)m_aArgs[0], + (NPStream*)m_aArgs[1], + (NPError)(sal_IntPtr)m_aArgs[2] ) + : NPERR_GENERIC_ERROR); + break; + case eNPP_New: + TRACE( "eNPP_New" ); + nRet = (m_aNPPfuncs.newp + ? (*m_aNPPfuncs.newp)( + (NPMIMEType)m_aArgs[0], + (NPP)m_aArgs[1], + (uint16)(sal_IntPtr)m_aArgs[2], + (int16)(sal_IntPtr)m_aArgs[3], + (char**)m_aArgs[4], + (char**)m_aArgs[5], + (NPSavedData*)m_aArgs[6] ) + : NPERR_GENERIC_ERROR); + + if( ! m_pNullTimer && m_aNPPfuncs.event ) + { + m_pNullTimer = new AutoTimer(); + m_pNullTimer->SetTimeout( 50 ); + m_pNullTimer->SetTimeoutHdl( LINK( this, MacPluginComm, NullTimerHdl ) ); + m_pNullTimer->Start(); + } + + break; + case eNPP_NewStream: + TRACE( "eNPP_NewStream" ); + nRet = (m_aNPPfuncs.newstream + ? (*m_aNPPfuncs.newstream)( + (NPP)m_aArgs[0], + (NPMIMEType)m_aArgs[1], + (NPStream*)m_aArgs[2], + (NPBool)(sal_IntPtr)m_aArgs[3], + (uint16*)m_aArgs[4] ) + : NPERR_GENERIC_ERROR); + break; + case eNPP_Print: + TRACE( "eNPP_Print" ); + if (m_aNPPfuncs.print) + (*m_aNPPfuncs.print)( + (NPP)m_aArgs[0], + (NPPrint*)m_aArgs[1] ); + break; + case eNPP_SetWindow: + { + TRACE( "eNPP_SetWindow" ); + nRet = (m_aNPPfuncs.setwindow + ? (*m_aNPPfuncs.setwindow)( + (NPP)m_aArgs[0], + (NPWindow*)m_aArgs[1] ) + : NPERR_GENERIC_ERROR); + + break; + } + case eNPP_HandleEvent: + { + TRACE( "eNPP_HandleEvent" ); + nRet = (m_aNPPfuncs.event + ? (*m_aNPPfuncs.event)( + (NPP)m_aArgs[0], + m_aArgs[1] ) + : NPERR_GENERIC_ERROR); + + break; + } + case eNPP_StreamAsFile: + TRACE( "eNPP_StreamAsFile" ); + if (m_aNPPfuncs.asfile) + (*m_aNPPfuncs.asfile)( + (NPP)m_aArgs[0], + (NPStream*)m_aArgs[1], + (char*)m_aArgs[2] ); + break; + case eNPP_URLNotify: + TRACE( "eNPP_URLNotify" ); + if (m_aNPPfuncs.urlnotify) + (*m_aNPPfuncs.urlnotify)( + (NPP)m_aArgs[0], + (char*)m_aArgs[1], + (NPReason)(sal_IntPtr)m_aArgs[2], + m_aArgs[3] ); + break; + case eNPP_Write: + TRACEN( "eNPP_Write n=", (int32)m_aArgs[3] ); + nRet = (m_aNPPfuncs.write + ? (*m_aNPPfuncs.write)( + (NPP)m_aArgs[0], + (NPStream*)m_aArgs[1], + (int32)m_aArgs[2], + (int32)m_aArgs[3], + m_aArgs[4] ) + : 0); + break; + case eNPP_WriteReady: + TRACE( "eNPP_WriteReady" ); + nRet = (m_aNPPfuncs.writeready + ? (*m_aNPPfuncs.writeready)( + (NPP)m_aArgs[0], + (NPStream*)m_aArgs[1] ) + : 0); + break; + case eNPP_GetValue: + TRACE( "eNPP_GetValue" ); + nRet = (m_aNPPfuncs.getvalue + ? (*m_aNPPfuncs.getvalue)( + (NPP)m_aArgs[0], + (NPPVariable)(int)m_aArgs[1], + m_aArgs[2] ) + : NPERR_GENERIC_ERROR); + break; + case eNPP_SetValue: + TRACE( "eNPP_SetValue" ); + nRet = (m_aNPPfuncs.setvalue + ? (*m_aNPPfuncs.setvalue)( + (NPP)m_aArgs[0], + (NPNVariable)(int)m_aArgs[1], + m_aArgs[2] ) + : NPERR_GENERIC_ERROR); + break; + case eNPP_Shutdown: + { + TRACE( "eNPP_Shutdown" ); + NPP_ShutdownUPP pFunc; + if (retrieveFunction( "NPP_Shutdown", (void**)&pFunc )) + (*pFunc)(); + } + break; + case eNPP_Initialize: + TRACE( "eNPP_Initialize" ); + OSL_ENSURE( false, "NPP_Initialize: not implemented!" ); + break; + case eNPP_GetJavaClass: + TRACE( "eNPP_GetJavaClass" ); + OSL_ENSURE( false, "NPP_GetJavaClass: not implemented!" ); + break; + } + return nRet; +} + +//-------------------------------------------------------------------------------------------------- +NPError MacPluginComm::NPP_Destroy( XPlugin_Impl* i_pImpl, NPSavedData** save ) +{ + // remove from NullEvent timer + m_aNullEventClients.remove( i_pImpl ); + + NPError nErr = NPP_Destroy( i_pImpl->getNPPInstance(), save ); + + // release plugin view + SysPlugData& rPlugData( i_pImpl->getSysPlugData() ); + if( rPlugData.m_pPlugView ) + { + [rPlugData.m_pPlugView removeFromSuperview]; + [rPlugData.m_pPlugView release]; + rPlugData.m_pPlugView = nil; + } + + return nErr; +} + + +NPError MacPluginComm::NPP_Destroy( NPP instance, NPSavedData** save ) +{ + DBG_ASSERT( m_aNPPfuncs.destroy, "### NPP_Destroy(): null pointer in NPP functions table!" ); + m_eCall = eNPP_Destroy; + m_aArgs[0] = (void*)instance; + m_aArgs[1] = (void*)save; + return (NPError)execute(); +} + +//-------------------------------------------------------------------------------------------------- +NPError MacPluginComm::NPP_DestroyStream( NPP instance, NPStream* stream, NPError reason ) +{ + DBG_ASSERT( m_aNPPfuncs.destroystream, "### NPP_DestroyStream(): null pointer in NPP functions table!" ); + m_eCall = eNPP_DestroyStream; + m_aArgs[0] = (void*)instance; + m_aArgs[1] = (void*)stream; + m_aArgs[2] = (void*)reason; + return (NPError)execute(); +} + +//-------------------------------------------------------------------------------------------------- +NPError MacPluginComm::NPP_New( NPMIMEType pluginType, NPP instance, uint16 mode, int16 argc, + char* argn[], char* argv[], NPSavedData *saved ) +{ + XPlugin_Impl* pImpl = XPluginManager_Impl::getXPluginFromNPP( instance ); + DBG_ASSERT( pImpl, "no instance found" ); + + if( pImpl ) // sanity check + m_aNullEventClients.push_back( pImpl ); + + DBG_ASSERT( m_aNPPfuncs.newp, "### NPP_New(): null pointer in NPP functions table!" ); + #if OSL_DEBUG_LEVEL > 1 + fprintf( stderr, "NPP_New( %s. %p, %d, %d", + pluginType, instance, (int)mode, (int)argc ); + for( int16 i = 0; i < argc; i++ ) + fprintf( stderr, "\n%s = %s", argn[i], argv[i] ); + fprintf( stderr, ", %p )\n", saved ); + #endif + m_eCall = eNPP_New; + m_aArgs[0] = (void*)pluginType; + m_aArgs[1] = (void*)instance; + m_aArgs[2] = (void*)mode; + m_aArgs[3] = (void*)argc; + m_aArgs[4] = (void*)argn; + m_aArgs[5] = (void*)argv; + m_aArgs[6] = (void*)saved; + + return (NPError)execute(); +} + +//-------------------------------------------------------------------------------------------------- +NPError MacPluginComm::NPP_NewStream( NPP instance, NPMIMEType type, NPStream* stream, + NPBool seekable, uint16* stype ) +{ + DBG_ASSERT( m_aNPPfuncs.newstream, "### NPP_NewStream(): null pointer in NPP functions table!" ); + m_eCall = eNPP_NewStream; + m_aArgs[0] = (void*)instance; + m_aArgs[1] = (void*)type; + m_aArgs[2] = (void*)stream; + m_aArgs[3] = (void*)seekable; + m_aArgs[4] = (void*)stype; + return (NPError)execute(); +} + +//-------------------------------------------------------------------------------------------------- +void MacPluginComm::NPP_Print( NPP instance, NPPrint* platformPrint ) +{ + DBG_ASSERT( m_aNPPfuncs.print, "### NPP_Print(): null pointer in NPP functions table!" ); + m_eCall = eNPP_Print; + m_aArgs[0] = (void*)instance; + m_aArgs[1] = (void*)platformPrint; + execute(); +} + +//-------------------------------------------------------------------------------------------------- +NPError MacPluginComm::NPP_SetWindow( NPP instance, NPWindow* window ) +{ + DBG_ASSERT( m_aNPPfuncs.setwindow, "### NPP_SetWindow(): null pointer in NPP functions table!" ); + m_eCall = eNPP_SetWindow; + m_aArgs[0] = (void*)instance; + m_aArgs[1] = (void*)window; + return (NPError)execute(); +} + +//-------------------------------------------------------------------------------------------------- +NPError MacPluginComm::NPP_HandleEvent( NPP instance, void* event ) +{ + DBG_ASSERT( m_aNPPfuncs.event, "### NPP_HandleEvent(): null pointer in NPP functions table!" ); + m_eCall = eNPP_HandleEvent; + m_aArgs[0] = (void*)instance; + m_aArgs[1] = event; + return (NPError)execute(); +} + +//-------------------------------------------------------------------------------------------------- +void MacPluginComm::NPP_StreamAsFile( NPP instance, NPStream* stream, const char* fname ) +{ + DBG_ASSERT( m_aNPPfuncs.asfile, "### NPP_StreamAsFile(): null pointer in NPP functions table!" ); + m_eCall = eNPP_StreamAsFile; + m_aArgs[0] = (void*)instance; + m_aArgs[1] = (void*)stream; + m_aArgs[2] = (void*)fname; + execute(); +} + +//-------------------------------------------------------------------------------------------------- +void MacPluginComm::NPP_URLNotify( NPP instance, const char* url, NPReason reason, void* notifyData ) +{ + DBG_ASSERT( m_aNPPfuncs.urlnotify, "### NPP_URLNotify(): null pointer in NPP functions table!" ); + m_eCall = eNPP_URLNotify; + m_aArgs[0] = (void*)instance; + m_aArgs[1] = (void*)url; + m_aArgs[2] = (void*)reason; + m_aArgs[3] = notifyData; + execute(); +} + +//-------------------------------------------------------------------------------------------------- +int32 MacPluginComm::NPP_Write( NPP instance, NPStream* stream, int32 offset, int32 len, void* buffer ) +{ + DBG_ASSERT( m_aNPPfuncs.write, "### NPP_Write(): null pointer in NPP functions table!" ); + m_eCall = eNPP_Write; + m_aArgs[0] = (void*)instance; + m_aArgs[1] = (void*)stream; + m_aArgs[2] = (void*)offset; + m_aArgs[3] = (void*)len; + m_aArgs[4] = buffer; + return (NPError)execute(); +} + +//-------------------------------------------------------------------------------------------------- +int32 MacPluginComm::NPP_WriteReady( NPP instance, NPStream* stream ) +{ + DBG_ASSERT( m_aNPPfuncs.writeready, "### NPP_WriteReady(): null pointer in NPP functions table!" ); + m_eCall = eNPP_WriteReady; + m_aArgs[0] = (void*)instance; + m_aArgs[1] = (void*)stream; + return execute(); +} + +//-------------------------------------------------------------------------------------------------- +NPError MacPluginComm::NPP_GetValue( NPP instance, NPPVariable variable, void *ret_value ) +{ + DBG_ASSERT( m_aNPPfuncs.getvalue, "### NPP_GetValue(): null pointer in NPP functions table!" ); + m_eCall = eNPP_GetValue; + m_aArgs[0] = (void*)instance; + m_aArgs[1] = (void*)variable; + m_aArgs[2] = ret_value; + return (NPError)execute(); +} + +//-------------------------------------------------------------------------------------------------- +NPError MacPluginComm::NPP_SetValue( NPP instance, NPNVariable variable, void *set_value ) +{ + DBG_ASSERT( m_aNPPfuncs.setvalue, "### NPP_SetValue(): null pointer in NPP functions table!" ); + m_eCall = eNPP_SetValue; + m_aArgs[0] = (void*)instance; + m_aArgs[1] = (void*)variable; + m_aArgs[2] = set_value; + return (NPError)execute(); +} + +//-------------------------------------------------------------------------------------------------- +void * MacPluginComm::NPP_GetJavaClass() +{ + DBG_ERROR( "no java class available!" ); + return 0; +} + +//-------------------------------------------------------------------------------------------------- +NPError MacPluginComm::NPP_Initialize() +{ + return NPERR_NO_ERROR; +} + +//-------------------------------------------------------------------------------------------------- +void MacPluginComm::NPP_Shutdown() +{ + m_eCall = eNPP_Shutdown; + execute(); +} + +//-------------------------------------------------------------------------------------------------- +NPError MacPluginComm::NPP_SetWindow( XPlugin_Impl* i_pImpl ) +{ + // update window NPWindow from view + SysPlugData& rPlugData( i_pImpl->getSysPlugData() ); + + // update plug view + NSRect aPlugRect = [rPlugData.m_pParentView frame]; + aPlugRect.origin.x = aPlugRect.origin.y = 0; + if( ! rPlugData.m_pPlugView ) + { + rPlugData.m_pPlugView = [[OOoPluginView alloc] initWithInstance: i_pImpl pluginComm: this frame: aPlugRect]; + [rPlugData.m_pParentView addSubview: rPlugData.m_pPlugView]; + } + else + [rPlugData.m_pPlugView setFrame: aPlugRect]; + + NPWindow* pNPWin = i_pImpl->getNPWindow(); + NSWindow* pWin = [rPlugData.m_pPlugView window]; + NSRect aWinRect = [pWin frame]; + NSRect aBounds = [rPlugData.m_pPlugView frame]; + NSRect aVisibleBounds = [rPlugData.m_pPlugView visibleRect]; + + #if OSL_DEBUG_LEVEL > 1 + fprintf( stderr, "visible bounds = %d+%d+%dx%d\n", + (int)aVisibleBounds.origin.x, (int)aVisibleBounds.origin.y, + (int)aVisibleBounds.size.width, (int)aVisibleBounds.size.height ); + #endif + + NSPoint aViewOrigin = [rPlugData.m_pPlugView convertPoint: NSZeroPoint toView: nil]; + // save view origin so we can notice movement of the view in drawView + // in case of a moved view we need to reset the port/context + rPlugData.m_aLastPlugViewOrigin = aViewOrigin; + + // convert view origin to topdown coordinates + aViewOrigin.y = aWinRect.size.height - aViewOrigin.y; + + // same for clipping + NSPoint aClipOrigin = [rPlugData.m_pPlugView convertPoint: aVisibleBounds.origin toView: nil]; + aClipOrigin.y = aWinRect.size.height - aClipOrigin.y; + + #if OSL_DEBUG_LEVEL > 1 + fprintf( stderr, "view origin: %d+%d, clip origin = %d+%d\n", + (int)aViewOrigin.x, (int)aViewOrigin.y, + (int)aClipOrigin.x, (int)aClipOrigin.y ); + #endif + + pNPWin->x = aViewOrigin.x; + pNPWin->y = aViewOrigin.y; + pNPWin->width = aBounds.size.width; + pNPWin->height = aBounds.size.height; + pNPWin->clipRect.left = aClipOrigin.x; + pNPWin->clipRect.top = aClipOrigin.y; + pNPWin->clipRect.right = aClipOrigin.x + aVisibleBounds.size.width; + pNPWin->clipRect.bottom = aClipOrigin.y + aVisibleBounds.size.height; + + if( rPlugData.m_nDrawingModel == 1 ) + { + rPlugData.m_aCGContext.window = reinterpret_cast([pWin windowRef]); + pNPWin->window = &rPlugData.m_aCGContext; + rPlugData.m_aCGContext.context = reinterpret_cast([[pWin graphicsContext] graphicsPort]); + #if OSL_DEBUG_LEVEL > 1 + fprintf( stderr, "window is %p, context is %p\n", + rPlugData.m_aCGContext.window, rPlugData.m_aCGContext.context ); + #endif + } + else + { + rPlugData.m_aNPPort.port = GetWindowPort( reinterpret_cast([pWin windowRef]) ); + rPlugData.m_aNPPort.portx = aClipOrigin.x; + rPlugData.m_aNPPort.porty = aClipOrigin.y; + pNPWin->window = &rPlugData.m_aNPPort; + #if OSL_DEBUG_LEVEL > 1 + fprintf( stderr, "port is %p at (%d,%d)\n", + rPlugData.m_aNPPort.port, (int)rPlugData.m_aNPPort.portx, (int)rPlugData.m_aNPPort.porty ); + #endif + } + + if( pNPWin->width == 0 || pNPWin->height == 0 || [rPlugData.m_pPlugView isHiddenOrHasHiddenAncestor] ) + rPlugData.m_bSetWindowOnDraw = true; + + NPError nErr = NPP_SetWindow( i_pImpl->getNPPInstance(), i_pImpl->getNPWindow() ); + + return nErr; +} + +void MacPluginComm::drawView( XPlugin_Impl* i_pImpl ) +{ + SysPlugData& rPlugData( i_pImpl->getSysPlugData() ); + + // check if the view was moved since the last SetWindow + NSPoint aViewOrigin = [rPlugData.m_pPlugView convertPoint: NSZeroPoint toView: nil]; + if( rPlugData.m_bSetWindowOnDraw || + aViewOrigin.x != rPlugData.m_aLastPlugViewOrigin.x || + aViewOrigin.y != rPlugData.m_aLastPlugViewOrigin.y ) + { + NPP_SetWindow( i_pImpl ); + rPlugData.m_bSetWindowOnDraw = false; + } + + // send a paint event + NSWindow* pWin = [rPlugData.m_pPlugView window]; + FakeEventRecord aRec; + aRec.what = updateEvt; + aRec.message = (UInt32)[pWin windowRef]; + this->NPP_HandleEvent( i_pImpl->getNPPInstance(), &aRec ); +} + --- a/main/extensions/source/plugin/base/context.cxx +++ a/main/extensions/source/plugin/base/context.cxx @@ -0,0 +1,352 @@ +/************************************************************** + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + *************************************************************/ + + + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_extensions.hxx" + +#if STLPORT_VERSION>=321 +#include +#include +#endif + +#include + +#ifndef _COM_SUN_STAR_FRAME_FRAMESEARCHFLAGS_HPP_ +#include +#endif +#include +#include +#include + +#include + +using namespace com::sun::star::io; +using rtl::OUString; + +namespace ext_plug { + +class FileSink : public ::cppu::WeakAggImplHelper1< ::com::sun::star::io::XOutputStream > +{ +private: + Reference< ::com::sun::star::uno::XComponentContext > m_xContext; + FILE* fp; + Reference< ::com::sun::star::plugin::XPlugin > m_xPlugin; + ::rtl::OUString m_aMIMEType; + ::rtl::OUString m_aTarget; + ::rtl::OUString m_aFileName; + +public: + FileSink( const Reference< ::com::sun::star::uno::XComponentContext > &, + const Reference< ::com::sun::star::plugin::XPlugin > & plugin, + const ::rtl::OUString& mimetype, + const ::rtl::OUString& target, + const Reference< ::com::sun::star::io::XActiveDataSource > & source ); + virtual ~FileSink(); + + // ::com::sun::star::io::XOutputStream + virtual void SAL_CALL writeBytes( const Sequence& ) throw(); + virtual void SAL_CALL flush() throw(); + virtual void SAL_CALL closeOutput() throw(); +}; + +} +using namespace ext_plug; + +class XPluginContext_Impl : public ::cppu::WeakAggImplHelper1< ::com::sun::star::plugin::XPluginContext > +{ + Reference< ::com::sun::star::uno::XComponentContext > m_xContext; + rtl_TextEncoding m_aEncoding; +public: + + XPluginContext_Impl( const Reference< ::com::sun::star::uno::XComponentContext > & ); + virtual ~XPluginContext_Impl(); + + + virtual ::rtl::OUString SAL_CALL getValue(const Reference< ::com::sun::star::plugin::XPlugin > & plugin, ::com::sun::star::plugin::PluginVariable variable) throw( ::com::sun::star::plugin::PluginException, RuntimeException ); + virtual void SAL_CALL getURLNotify(const Reference< ::com::sun::star::plugin::XPlugin > & plugin, const ::rtl::OUString& url, const ::rtl::OUString& target, const Reference< ::com::sun::star::lang::XEventListener > & listener) throw( ::com::sun::star::plugin::PluginException, RuntimeException ); + virtual void SAL_CALL getURL(const Reference< ::com::sun::star::plugin::XPlugin > & plugin, const ::rtl::OUString& url, const ::rtl::OUString& target) throw( ::com::sun::star::plugin::PluginException, RuntimeException ); + virtual void SAL_CALL postURLNotify(const Reference< ::com::sun::star::plugin::XPlugin > & plugin, const ::rtl::OUString& url, const ::rtl::OUString& target, const Sequence< sal_Int8 >& buf, sal_Bool file, const Reference< ::com::sun::star::lang::XEventListener > & listener) throw( ::com::sun::star::plugin::PluginException, RuntimeException ); + virtual void SAL_CALL postURL(const Reference< ::com::sun::star::plugin::XPlugin > & plugin, const ::rtl::OUString& url, const ::rtl::OUString& target, const Sequence< sal_Int8 >& buf, sal_Bool file) throw( ::com::sun::star::plugin::PluginException, RuntimeException ); + virtual void SAL_CALL newStream(const Reference< ::com::sun::star::plugin::XPlugin > & plugin, const ::rtl::OUString& mimetype, const ::rtl::OUString& target, const Reference< ::com::sun::star::io::XActiveDataSource > & source) throw( ::com::sun::star::plugin::PluginException, RuntimeException ); + virtual void SAL_CALL displayStatusText(const Reference< ::com::sun::star::plugin::XPlugin > & plugin, const ::rtl::OUString& message) throw( ::com::sun::star::plugin::PluginException, RuntimeException ); + virtual ::rtl::OUString SAL_CALL getUserAgent(const Reference< ::com::sun::star::plugin::XPlugin > & plugin) throw( ::com::sun::star::plugin::PluginException, RuntimeException ); +}; + +Reference< ::com::sun::star::plugin::XPluginContext > XPluginManager_Impl::createPluginContext() throw() +{ + return new XPluginContext_Impl( m_xContext ); +} + +XPluginContext_Impl::XPluginContext_Impl( const Reference< ::com::sun::star::uno::XComponentContext > & rxContext ) + : m_xContext( rxContext ), + m_aEncoding( gsl_getSystemTextEncoding() ) +{ +} + +XPluginContext_Impl::~XPluginContext_Impl() +{ +} + +::rtl::OUString XPluginContext_Impl::getValue( const Reference< ::com::sun::star::plugin::XPlugin > & /*plugin*/, ::com::sun::star::plugin::PluginVariable /*variable*/ ) + throw( ::com::sun::star::plugin::PluginException, RuntimeException ) +{ + return ::rtl::OUString(); +} + + +void XPluginContext_Impl::getURL( + const Reference< ::com::sun::star::plugin::XPlugin > & plugin, + const ::rtl::OUString& url, + const ::rtl::OUString& target) +throw( ::com::sun::star::plugin::PluginException, + RuntimeException ) +{ + Reference< ::com::sun::star::frame::XComponentLoader > xLoader( + m_xContext->getServiceManager()->createInstanceWithContext( + OUString( RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.frame.Desktop" )), m_xContext ), UNO_QUERY ); + if( ! xLoader.is() ) + return; + + if( ! target.getLength() ) + { + INetURLObject aURL; + aURL.SetSmartProtocol( INET_PROT_FILE ); + aURL.SetSmartURL( ::rtl::OUStringToOString( url, m_aEncoding ) ); + + rtl::OUString aUrl = aURL.GetMainURL(INetURLObject::DECODE_TO_IURI); + // the mimetype cannot be specified + plugin->provideNewStream( ::rtl::OUString(), + Reference< XActiveDataSource >(), + aUrl, + 0, 0, (sal_Bool)(aUrl.compareToAscii( "file:", 5 ) == 0) ); + return; + } + + XPlugin_Impl* pPlugin = XPluginManager_Impl::getPluginImplementation( plugin ); + + if( pPlugin ) + { + try + { + ::com::sun::star::beans::PropertyValue aValue; + aValue.Name = ::rtl::OUString::createFromAscii( "Referer" ); + aValue.Value <<= pPlugin->getRefererURL(); + + Sequence< ::com::sun::star::beans::PropertyValue > aArgs( &aValue, 1 ); + Reference< ::com::sun::star::lang::XComponent > xComp = + xLoader->loadComponentFromURL( + url, + target, + ::com::sun::star::frame::FrameSearchFlag::PARENT | + ::com::sun::star::frame::FrameSearchFlag::SELF | + ::com::sun::star::frame::FrameSearchFlag::CHILDREN | + ::com::sun::star::frame::FrameSearchFlag::SIBLINGS | + ::com::sun::star::frame::FrameSearchFlag::TASKS | + ::com::sun::star::frame::FrameSearchFlag::CREATE, + aArgs + ); + } + catch(...) + { + throw ::com::sun::star::plugin::PluginException(); + } + } +} + +void XPluginContext_Impl::getURLNotify(const Reference< ::com::sun::star::plugin::XPlugin > & plugin, const ::rtl::OUString& url, const ::rtl::OUString& target, const Reference< ::com::sun::star::lang::XEventListener > & listener ) + throw( ::com::sun::star::plugin::PluginException, RuntimeException ) +{ + getURL( plugin, url, target ); + if( listener.is() ) + listener->disposing( ::com::sun::star::lang::EventObject() ); +} + +::rtl::OUString XPluginContext_Impl::getUserAgent(const Reference< ::com::sun::star::plugin::XPlugin > & /*plugin*/) + throw( ::com::sun::star::plugin::PluginException, RuntimeException ) +{ + return ::rtl::OUString::createFromAscii( "Mozilla 3.0" ); +} + +void XPluginContext_Impl::displayStatusText(const Reference< ::com::sun::star::plugin::XPlugin > & /*plugin*/, const ::rtl::OUString& /*message*/) + throw( ::com::sun::star::plugin::PluginException, RuntimeException ) +{ +} + +void XPluginContext_Impl::postURL(const Reference< ::com::sun::star::plugin::XPlugin > & plugin, const ::rtl::OUString& url, const ::rtl::OUString& target, const Sequence< sal_Int8 >& buf, sal_Bool file) + throw( ::com::sun::star::plugin::PluginException, RuntimeException ) +{ + Sequence< sal_Int8 > aBuf; + + if( file ) + { + String aFileName( (char*)buf.getConstArray(), m_aEncoding ); + INetURLObject aFilePath( aFileName ); + aFileName = aFilePath.PathToFileName(); + SvFileStream aStream( aFileName, STREAM_READ ); + if( aStream.IsOpen() ) + { + int nBytes = 0; + aStream.Seek( STREAM_SEEK_TO_END ); + aBuf = Sequence( nBytes = aStream.Tell() ); + aStream.Seek( STREAM_SEEK_TO_BEGIN ); + aStream.Read( aBuf.getArray(), nBytes ); + aStream.Close(); + DirEntry( aFileName ).Kill(); + } + } + + Reference< ::com::sun::star::frame::XComponentLoader > xLoader( + m_xContext->getServiceManager()->createInstanceWithContext( + OUString( RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.frame.Desktop" )), m_xContext ), UNO_QUERY ); + if( ! xLoader.is() ) + return ; + + XPlugin_Impl* pPlugin = XPluginManager_Impl::getPluginImplementation( plugin ); + if( pPlugin ) + { + try + { + ::com::sun::star::beans::PropertyValue aValues[2]; + aValues[0].Name = ::rtl::OUString::createFromAscii( "Referer" ); + aValues[0].Value <<= pPlugin->getRefererURL(); + + aValues[1].Name = ::rtl::OUString::createFromAscii( "PostString" ); + aValues[1].Value <<= ::rtl::OStringToOUString( (char*)( file ? aBuf : buf ).getConstArray(), m_aEncoding ); + Sequence< ::com::sun::star::beans::PropertyValue > aArgs( aValues, 2 ); + Reference< ::com::sun::star::lang::XComponent > xComp = + xLoader->loadComponentFromURL( + url, + target, + ::com::sun::star::frame::FrameSearchFlag::PARENT | + ::com::sun::star::frame::FrameSearchFlag::SELF | + ::com::sun::star::frame::FrameSearchFlag::CHILDREN | + ::com::sun::star::frame::FrameSearchFlag::SIBLINGS | + ::com::sun::star::frame::FrameSearchFlag::TASKS | + ::com::sun::star::frame::FrameSearchFlag::CREATE, + aArgs + ); + } + catch( ... ) + { + throw ::com::sun::star::plugin::PluginException(); + } + } +} + +void XPluginContext_Impl::postURLNotify(const Reference< ::com::sun::star::plugin::XPlugin > & plugin, const ::rtl::OUString& url, const ::rtl::OUString& target, const Sequence< sal_Int8 >& buf, sal_Bool file, const Reference< ::com::sun::star::lang::XEventListener > & listener ) + throw( ::com::sun::star::plugin::PluginException, RuntimeException ) +{ + postURL( plugin, url, target, buf, file ); + if( listener.is() ) + listener->disposing( ::com::sun::star::lang::EventObject() ); +} + +void XPluginContext_Impl::newStream( const Reference< ::com::sun::star::plugin::XPlugin > & plugin, const ::rtl::OUString& mimetype, const ::rtl::OUString& target, const Reference< ::com::sun::star::io::XActiveDataSource > & source ) + throw( ::com::sun::star::plugin::PluginException, RuntimeException ) +{ + FileSink* pNewSink = new FileSink( m_xContext, plugin, mimetype, target, source ); + pNewSink->acquire(); +} + + + +FileSink::FileSink( const Reference< ::com::sun::star::uno::XComponentContext > & rxContext, const Reference< ::com::sun::star::plugin::XPlugin > & plugin, + const ::rtl::OUString& mimetype, + const ::rtl::OUString& target, const Reference< ::com::sun::star::io::XActiveDataSource > & source ) : + m_xContext( rxContext ), + m_xPlugin( plugin ), + m_aMIMEType( mimetype ), + m_aTarget( target ) +{ + DirEntry aEntry; + m_aFileName = aEntry.TempName().GetFull(); + ::rtl::OString aFile = ::rtl::OUStringToOString( m_aFileName, gsl_getSystemTextEncoding() ); + fp = fopen( aFile.getStr() , "wb" ); + + Reference< ::com::sun::star::io::XActiveDataControl > xControl( source, UNO_QUERY ); + + source->setOutputStream( Reference< ::com::sun::star::io::XOutputStream > ( this ) ); + if( xControl.is() ) + xControl->start(); +} + +FileSink::~FileSink() +{ + DirEntry aEntry( m_aFileName ); + aEntry.Kill(); +} + +void FileSink::closeOutput() throw() +{ + if( fp ) + fclose( fp ); + + Reference< ::com::sun::star::frame::XComponentLoader > xLoader( + m_xContext->getServiceManager()->createInstanceWithContext( + OUString( RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.frame.Desktop" )), m_xContext ), UNO_QUERY ); + + XPlugin_Impl* pPlugin = XPluginManager_Impl::getPluginImplementation( m_xPlugin ); + + if( xLoader.is() && pPlugin ) + { + try + { + ::com::sun::star::beans::PropertyValue aValue; + aValue.Name = ::rtl::OUString::createFromAscii( "Referer" ); + aValue.Value <<= pPlugin->getRefererURL(); + + Sequence< ::com::sun::star::beans::PropertyValue > aArgs( &aValue, 1 ); + Reference< ::com::sun::star::lang::XComponent > xComp = + xLoader->loadComponentFromURL( + m_aFileName, + m_aTarget, + ::com::sun::star::frame::FrameSearchFlag::PARENT | + ::com::sun::star::frame::FrameSearchFlag::SELF | + ::com::sun::star::frame::FrameSearchFlag::CHILDREN | + ::com::sun::star::frame::FrameSearchFlag::SIBLINGS | + ::com::sun::star::frame::FrameSearchFlag::TASKS | + ::com::sun::star::frame::FrameSearchFlag::CREATE, + aArgs + ); + } + catch( ... ) + { + } + } + release(); +} + +void FileSink::writeBytes( const Sequence& Buffer ) throw() +{ + if( fp ) + fwrite( Buffer.getConstArray(), 1, Buffer.getLength(), fp ); +} + +void FileSink::flush() throw() +{ + if( fp ) + fflush( fp ); +} --- a/main/extensions/source/plugin/base/evtlstnr.cxx +++ a/main/extensions/source/plugin/base/evtlstnr.cxx @@ -0,0 +1,60 @@ +/************************************************************** + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + *************************************************************/ + + + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_extensions.hxx" + +#if STLPORT_VERSION>=321 +#include +#endif + +#include + +PluginEventListener::PluginEventListener( XPlugin_Impl* pPlugin, + const char* url, + const char* normurl, + void* notifyData ) : + m_pPlugin( pPlugin ), + m_xPlugin( pPlugin ), + m_pUrl( strdup( url ) ), + m_pNormalizedUrl( strdup( normurl ) ), + m_pNotifyData( notifyData ) +{ +} + +PluginEventListener::~PluginEventListener() +{ + if( m_pUrl ) + free( m_pUrl ); + if( m_pNormalizedUrl ) + free( m_pNormalizedUrl ); +} + +void PluginEventListener::disposing( const ::com::sun::star::lang::EventObject& /*rEvt*/ ) throw() +{ + m_pPlugin->getPluginComm()-> + NPP_URLNotify( m_pPlugin->getNPPInstance(), + m_pUrl, + NPRES_DONE, + m_pNotifyData ); +} --- a/main/extensions/source/plugin/base/makefile.mk +++ a/main/extensions/source/plugin/base/makefile.mk @@ -0,0 +1,66 @@ +#************************************************************** +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# +#************************************************************** + + +PRJ=..$/..$/.. + +PRJNAME=extensions +TARGET=plbase +TARGETTYPE=GUI +ENABLE_EXCEPTIONS=TRUE + +.INCLUDE : ..$/util$/makefile.pmk + +INCPRE+=-I$(SOLARINCDIR)$/mozilla$/plugin +.IF "$(SOLAR_JAVA)" != "" +INCPRE+=-I$(SOLARINCDIR)$/mozilla$/java +INCPRE+=-I$(SOLARINCDIR)$/mozilla$/nspr +CDEFS+=-DOJI +.ENDIF + +.IF "$(DISABLE_XAW)" != "" +CDEFS+=-DDISABLE_XAW +.ENDIF + +.IF "$(WITH_MOZILLA)" != "NO" + +.IF "$(GUIBASE)"=="aqua" +CFLAGSCXX+=$(OBJCXXFLAGS) +.ENDIF # "$(GUIBASE)"=="aqua" + +SLOFILES= \ + $(SLO)$/plctrl.obj \ + $(SLO)$/service.obj \ + $(SLO)$/xplugin.obj \ + $(SLO)$/nfuncs.obj \ + $(SLO)$/manager.obj \ + $(SLO)$/context.obj \ + $(SLO)$/evtlstnr.obj \ + $(SLO)$/plcom.obj \ + $(SLO)$/multiplx.obj \ + $(SLO)$/plmodel.obj + +.ENDIF # $(WITH_MOZILLA) != "NO" + +# --- Targets ------------------------------------------------------ + +.INCLUDE : target.mk + --- a/main/extensions/source/plugin/base/manager.cxx +++ a/main/extensions/source/plugin/base/manager.cxx @@ -0,0 +1,221 @@ +/************************************************************** + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + *************************************************************/ + + + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_extensions.hxx" + +#if STLPORT_VERSION>=321 +#include +#endif + +#include "plugin/impl.hxx" + +#include "osl/mutex.hxx" +#include "unotools/pathoptions.hxx" +#include "vcl/configsettings.hxx" + +#include "com/sun/star/container/XEnumerationAccess.hpp" +#include "com/sun/star/container/XNameAccess.hpp" +#include "com/sun/star/container/XEnumeration.hpp" +#include "com/sun/star/container/XElementAccess.hpp" +#include "com/sun/star/container/XIndexAccess.hpp" +#include "com/sun/star/loader/XImplementationLoader.hpp" +#include "com/sun/star/loader/CannotActivateFactoryException.hpp" + +PluginManager* PluginManager::pManager = NULL; + +PluginManager& PluginManager::get() +{ + if( ! pManager ) + pManager = new PluginManager(); + return *pManager; +} + +void PluginManager::setComponentContext( const Reference< ::com::sun::star::uno::XComponentContext >& xContext ) +{ + PluginManager& rManager = get(); + if( ! rManager.m_xContext.is() ) + rManager.m_xContext = xContext; +} + +PluginManager::PluginManager() +{ +} + +const Sequence< ::rtl::OUString >& PluginManager::getAdditionalSearchPaths() +{ + static Sequence< ::rtl::OUString > aPaths; + + if( ! aPaths.getLength() ) + { + SvtPathOptions aOptions; + String aPluginPath( aOptions.GetPluginPath() ); + if( aPluginPath.Len() ) + { + sal_uInt16 nPaths = aPluginPath.GetTokenCount( ';' ); + aPaths.realloc( nPaths ); + for( sal_uInt16 i = 0; i < nPaths; i++ ) + aPaths.getArray()[i] = aPluginPath.GetToken( i, ';' ); + } + } + + return aPaths; +} + +//================================================================================================== +Reference< XInterface > SAL_CALL PluginManager_CreateInstance( const Reference< ::com::sun::star::uno::XComponentContext > & rxContext ) throw( Exception ) +{ + Reference< XInterface > xService = *new XPluginManager_Impl( rxContext ); + return xService; +} + +// ::com::sun::star::lang::XServiceInfo +::rtl::OUString XPluginManager_Impl::getImplementationName() throw( ) + +{ + return getImplementationName_Static(); + +} + +// ::com::sun::star::lang::XServiceInfo +sal_Bool XPluginManager_Impl::supportsService(const ::rtl::OUString& ServiceName) throw( ) +{ + Sequence< ::rtl::OUString > aSNL = getSupportedServiceNames(); + const ::rtl::OUString * pArray = aSNL.getConstArray(); + for( sal_Int32 i = 0; i < aSNL.getLength(); i++ ) + if( pArray[i] == ServiceName ) + return sal_True; + return sal_False; +} + +// ::com::sun::star::lang::XServiceInfo +Sequence< ::rtl::OUString > XPluginManager_Impl::getSupportedServiceNames(void) throw( ) +{ + return getSupportedServiceNames_Static(); +} + +// XPluginManager_Impl +Sequence< ::rtl::OUString > XPluginManager_Impl::getSupportedServiceNames_Static(void) throw( ) +{ + Sequence< ::rtl::OUString > aSNS( 1 ); + aSNS.getArray()[0] = ::rtl::OUString::createFromAscii( "com.sun.star.plugin.PluginManager" ); + return aSNS; +} + +XPluginManager_Impl::XPluginManager_Impl( const Reference< ::com::sun::star::uno::XComponentContext > & rxContext ) +: m_xContext( rxContext ) +{ + PluginManager::setComponentContext( rxContext ); +} + +XPluginManager_Impl::~XPluginManager_Impl() +{ +} + +XPlugin_Impl* XPluginManager_Impl::getXPluginFromNPP( NPP instance ) +{ + ::std::list::iterator iter; + for( iter = PluginManager::get().getPlugins().begin(); + iter != PluginManager::get().getPlugins().end(); ++iter ) + { + if( (*iter)->getNPPInstance() == instance ) + return *iter; + } + + return NULL; +} + +XPlugin_Impl* XPluginManager_Impl::getPluginImplementation( const Reference< ::com::sun::star::plugin::XPlugin >& plugin ) +{ + ::std::list::iterator iter; + for( iter = PluginManager::get().getPlugins().begin(); + iter != PluginManager::get().getPlugins().end(); ++iter ) + { + if( plugin == Reference< ::com::sun::star::plugin::XPlugin >((*iter)) ) + return *iter; + } + + return NULL; +} + +Sequence XPluginManager_Impl::getPluginDescriptions() throw() +{ + Sequence aRet; + + vcl::SettingsConfigItem* pCfg = vcl::SettingsConfigItem::get(); + rtl::OUString aVal( pCfg->getValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "BrowserPlugins" ) ), + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Disabled" ) ) ) ); + if( ! aVal.toBoolean() ) + { + aRet = impl_getPluginDescriptions(); + } + return aRet; +} + +Reference< ::com::sun::star::plugin::XPlugin > XPluginManager_Impl::createPlugin( const Reference< ::com::sun::star::plugin::XPluginContext >& acontext, sal_Int16 mode, const Sequence< ::rtl::OUString >& argn, const Sequence< ::rtl::OUString >& argv, const ::com::sun::star::plugin::PluginDescription& plugintype) + throw( RuntimeException,::com::sun::star::plugin::PluginException ) +{ + XPlugin_Impl* pImpl = new XPlugin_Impl( m_xContext ); + pImpl->setPluginContext( acontext ); + + PluginManager::get().getPlugins().push_back( pImpl ); + + pImpl->initInstance( plugintype, + argn, + argv, + mode ); + + return pImpl; +} + +Reference< ::com::sun::star::plugin::XPlugin > XPluginManager_Impl::createPluginFromURL( const Reference< ::com::sun::star::plugin::XPluginContext > & acontext, sal_Int16 mode, const Sequence< ::rtl::OUString >& argn, const Sequence< ::rtl::OUString >& argv, const Reference< ::com::sun::star::awt::XToolkit > & toolkit, const Reference< ::com::sun::star::awt::XWindowPeer > & parent, const ::rtl::OUString& url ) throw() +{ + XPlugin_Impl* pImpl = new XPlugin_Impl( m_xContext ); + Reference< ::com::sun::star::plugin::XPlugin > xRef = pImpl; + + pImpl->setPluginContext( acontext ); + + PluginManager::get().getPlugins().push_back( pImpl ); + + + pImpl->initInstance( url, + argn, + argv, + mode ); + + pImpl->createPeer( toolkit, parent ); + + pImpl->provideNewStream( pImpl->getDescription().Mimetype, + Reference< com::sun::star::io::XActiveDataSource >(), + url, + 0, 0, (sal_Bool)(url.compareToAscii( "file:", 5 ) == 0) ); + + if( ! pImpl->getPluginComm() ) + { + pImpl->dispose(); + xRef = NULL; + } + + return xRef; +} + --- a/main/extensions/source/plugin/base/multiplx.cxx +++ a/main/extensions/source/plugin/base/multiplx.cxx @@ -0,0 +1,328 @@ +/************************************************************** + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + *************************************************************/ + + + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_extensions.hxx" +#include +#include + +// --------------------------------------------------------------------- +// class MRCListenerMultiplexerHelper +// --------------------------------------------------------------------- +MRCListenerMultiplexerHelper::MRCListenerMultiplexerHelper +( + const Reference< ::com::sun::star::awt::XWindow > & rControl + , const Reference< ::com::sun::star::awt::XWindow > & rPeer +) + : xPeer( rPeer ) + , xControl( Reference< ::com::sun::star::awt::XControl >( rControl, UNO_QUERY ) ) + , aListenerHolder( aMutex ) +{ +} + + +void MRCListenerMultiplexerHelper::setPeer( const Reference< ::com::sun::star::awt::XWindow > & rPeer ) +{ + ::osl::Guard< ::osl::Mutex > aGuard( aMutex ); + if( xPeer != rPeer ) + { + if( xPeer.is() ) + { + // get all uiks from the listener added to the peer + Sequence aContainedTypes = aListenerHolder.getContainedTypes(); + const Type* pArray = aContainedTypes.getConstArray(); + sal_Int32 nCount = aContainedTypes.getLength(); + // loop over all listener types and remove the listeners from the peer + for( sal_Int32 i = 0; i < nCount; i++ ) + unadviseFromPeer( xPeer, pArray[i] ); + } + xPeer = rPeer; + if( xPeer.is() ) + { + // get all uiks from the listener added to the peer + Sequence aContainedTypes = aListenerHolder.getContainedTypes(); + const Type * pArray = aContainedTypes.getConstArray(); + sal_Int32 nCount = aContainedTypes.getLength(); + // loop over all listener types and add the listeners to the peer + for( sal_Int32 i = 0; i < nCount; i++ ) + adviseToPeer( xPeer, pArray[i] ); + } + } +} + +// MRCListenerMultiplexerHelper +void MRCListenerMultiplexerHelper::disposeAndClear() +{ + ::com::sun::star::lang::EventObject aEvt; + aEvt.Source = xControl; + aListenerHolder.disposeAndClear( aEvt ); +} + +// MRCListenerMultiplexerHelper +void MRCListenerMultiplexerHelper::adviseToPeer( const Reference< ::com::sun::star::awt::XWindow > & rPeer, const Type & type ) +{ + // add a listener to the source (peer) + if( type == ::getCppuType((const Reference< ::com::sun::star::awt::XWindowListener >*)0) ) + rPeer->addWindowListener( this ); + else if( type == ::getCppuType((const Reference< ::com::sun::star::awt::XKeyListener >*)0) ) + rPeer->addKeyListener( this ); + else if( type == ::getCppuType((const Reference< ::com::sun::star::awt::XFocusListener >*)0) ) + rPeer->addFocusListener( this ); + else if( type == ::getCppuType((const Reference< ::com::sun::star::awt::XMouseListener >*)0) ) + rPeer->addMouseListener( this ); + else if( type == ::getCppuType((const Reference< ::com::sun::star::awt::XMouseMotionListener >*)0) ) + rPeer->addMouseMotionListener( this ); + else if( type == ::getCppuType((const Reference< ::com::sun::star::awt::XPaintListener >*)0) ) + rPeer->addPaintListener( this ); + else if( type == ::getCppuType((const Reference< ::com::sun::star::awt::XTopWindowListener >*)0) ) + { + Reference< ::com::sun::star::awt::XTopWindow > xTop( rPeer, UNO_QUERY ); + if( xTop.is() ) + xTop->addTopWindowListener( this ); + } + else + { + VOS_ENSHURE( sal_False, "unknown listener" ); + } +} + +// MRCListenerMultiplexerHelper +void MRCListenerMultiplexerHelper::unadviseFromPeer( const Reference< ::com::sun::star::awt::XWindow > & rPeer, const Type & type ) +{ + // the last listener is removed, remove the listener from the source (peer) + if( type == ::getCppuType((const Reference< ::com::sun::star::awt::XWindowListener >*)0) ) + rPeer->removeWindowListener( this ); + else if( type == ::getCppuType((const Reference< ::com::sun::star::awt::XKeyListener >*)0) ) + rPeer->removeKeyListener( this ); + else if( type == ::getCppuType((const Reference< ::com::sun::star::awt::XFocusListener >*)0) ) + rPeer->removeFocusListener( this ); + else if( type == ::getCppuType((const Reference< ::com::sun::star::awt::XMouseListener >*)0) ) + rPeer->removeMouseListener( this ); + else if( type == ::getCppuType((const Reference< ::com::sun::star::awt::XMouseMotionListener >*)0) ) + rPeer->removeMouseMotionListener( this ); + else if( type == ::getCppuType((const Reference< ::com::sun::star::awt::XPaintListener >*)0) ) + rPeer->removePaintListener( this ); + else if( type == ::getCppuType((const Reference< ::com::sun::star::awt::XTopWindowListener >*)0) ) + { + Reference< ::com::sun::star::awt::XTopWindow > xTop( rPeer, UNO_QUERY ); + if( xTop.is() ) + xTop->removeTopWindowListener( this ); + } + else + { + VOS_ENSHURE( sal_False, "unknown listener" ); + } +} + +// MRCListenerMultiplexerHelper +void MRCListenerMultiplexerHelper::advise( const Type & type, const Reference< XInterface > & listener) +{ + ::osl::Guard< ::osl::Mutex > aGuard( aMutex ); + if( 1 == aListenerHolder.addInterface( type, listener ) ) + { + // the first listener is added + if( xPeer.is() ) + adviseToPeer( xPeer, type ); + } +} + +// MRCListenerMultiplexerHelper +void MRCListenerMultiplexerHelper::unadvise(const Type & type, const Reference< XInterface > & listener) +{ + ::osl::Guard< ::osl::Mutex > aGuard( aMutex ); + ::cppu::OInterfaceContainerHelper * pCont = aListenerHolder.getContainer( type ); + if( pCont ) + { + if( 0 == pCont->removeInterface( listener ) && xPeer.is() ) + // the last listener is removed + unadviseFromPeer( xPeer, type ); + } +} + +// ::com::sun::star::lang::XEventListener +void MRCListenerMultiplexerHelper::disposing(const ::com::sun::star::lang::EventObject& ) throw() +{ + ::osl::Guard< ::osl::Mutex > aGuard( aMutex ); + // peer is disposed, clear the reference + xPeer = Reference< ::com::sun::star::awt::XWindow > (); +} + +#define MULTIPLEX( InterfaceName, MethodName, EventName ) \ +::cppu::OInterfaceContainerHelper * pCont; \ +pCont = aListenerHolder.getContainer( ::getCppuType((const Reference< InterfaceName >*)0) ); \ +if( pCont ) \ +{ \ + ::cppu::OInterfaceIteratorHelper aIt( *pCont ); \ + EventName aEvt = e; \ + /* Remark: The control is the event source not the peer. We must change */ \ + /* the source of the event */ \ + aEvt.Source = xControl;\ + /*.is the control not destroyed */ \ + if( aEvt.Source.is() ) \ + { \ + if( aIt.hasMoreElements() ) \ + { \ + InterfaceName * pListener = (InterfaceName *)aIt.next(); \ + try \ + { \ + pListener->MethodName( aEvt ); \ + } \ + catch( RuntimeException& ) \ + { \ + /* ignore all usr system exceptions from the listener */ \ + } \ + } \ + } \ +} + +// ::com::sun::star::awt::XFocusListener +void MRCListenerMultiplexerHelper::focusGained(const ::com::sun::star::awt::FocusEvent& e) throw() +{ + MULTIPLEX( ::com::sun::star::awt::XFocusListener, focusGained, ::com::sun::star::awt::FocusEvent ) +} + +// ::com::sun::star::awt::XFocusListener +void MRCListenerMultiplexerHelper::focusLost(const ::com::sun::star::awt::FocusEvent& e) throw() +{ + MULTIPLEX( ::com::sun::star::awt::XFocusListener, focusLost, ::com::sun::star::awt::FocusEvent ) +} + +// ::com::sun::star::awt::XWindowListener +void MRCListenerMultiplexerHelper::windowResized(const ::com::sun::star::awt::WindowEvent& e) throw() +{ + MULTIPLEX( ::com::sun::star::awt::XWindowListener, windowResized, ::com::sun::star::awt::WindowEvent ) +} + +// ::com::sun::star::awt::XWindowListener +void MRCListenerMultiplexerHelper::windowMoved(const ::com::sun::star::awt::WindowEvent& e) throw() +{ + MULTIPLEX( ::com::sun::star::awt::XWindowListener, windowMoved, ::com::sun::star::awt::WindowEvent ) +} + +// ::com::sun::star::awt::XWindowListener +void MRCListenerMultiplexerHelper::windowShown(const ::com::sun::star::lang::EventObject& e) throw() +{ + MULTIPLEX( ::com::sun::star::awt::XWindowListener, windowShown, ::com::sun::star::lang::EventObject ) +} + +// ::com::sun::star::awt::XWindowListener +void MRCListenerMultiplexerHelper::windowHidden(const ::com::sun::star::lang::EventObject& e) throw() +{ + MULTIPLEX( ::com::sun::star::awt::XWindowListener, windowHidden, ::com::sun::star::lang::EventObject ) +} + +// ::com::sun::star::awt::XKeyListener +void MRCListenerMultiplexerHelper::keyPressed(const ::com::sun::star::awt::KeyEvent& e) throw() +{ + MULTIPLEX( ::com::sun::star::awt::XKeyListener, keyPressed, ::com::sun::star::awt::KeyEvent ) +} + +// ::com::sun::star::awt::XKeyListener +void MRCListenerMultiplexerHelper::keyReleased(const ::com::sun::star::awt::KeyEvent& e) throw() +{ + MULTIPLEX( ::com::sun::star::awt::XKeyListener, keyReleased, ::com::sun::star::awt::KeyEvent ) +} + +// ::com::sun::star::awt::XMouseListener +void MRCListenerMultiplexerHelper::mousePressed(const ::com::sun::star::awt::MouseEvent& e) throw() +{ + MULTIPLEX( ::com::sun::star::awt::XMouseListener, mousePressed, ::com::sun::star::awt::MouseEvent ) +} + +// ::com::sun::star::awt::XMouseListener +void MRCListenerMultiplexerHelper::mouseReleased(const ::com::sun::star::awt::MouseEvent& e) throw() +{ + MULTIPLEX( ::com::sun::star::awt::XMouseListener, mouseReleased, ::com::sun::star::awt::MouseEvent ) +} + +// ::com::sun::star::awt::XMouseListener +void MRCListenerMultiplexerHelper::mouseEntered(const ::com::sun::star::awt::MouseEvent& e) throw() +{ + MULTIPLEX( ::com::sun::star::awt::XMouseListener, mouseEntered, ::com::sun::star::awt::MouseEvent ) +} + +// ::com::sun::star::awt::XMouseListener +void MRCListenerMultiplexerHelper::mouseExited(const ::com::sun::star::awt::MouseEvent& e) throw() +{ + MULTIPLEX( ::com::sun::star::awt::XMouseListener, mouseExited, ::com::sun::star::awt::MouseEvent ) +} + +// ::com::sun::star::awt::XMouseMotionListener +void MRCListenerMultiplexerHelper::mouseDragged(const ::com::sun::star::awt::MouseEvent& e) throw() +{ + MULTIPLEX( ::com::sun::star::awt::XMouseMotionListener, mouseDragged, ::com::sun::star::awt::MouseEvent ) +} + +// ::com::sun::star::awt::XMouseMotionListener +void MRCListenerMultiplexerHelper::mouseMoved(const ::com::sun::star::awt::MouseEvent& e) throw() +{ + MULTIPLEX( ::com::sun::star::awt::XMouseMotionListener, mouseMoved, ::com::sun::star::awt::MouseEvent ) +} + +// ::com::sun::star::awt::XPaintListener +void MRCListenerMultiplexerHelper::windowPaint(const ::com::sun::star::awt::PaintEvent& e) throw() +{ + MULTIPLEX( ::com::sun::star::awt::XPaintListener, windowPaint, ::com::sun::star::awt::PaintEvent ) +} + +// ::com::sun::star::awt::XTopWindowListener +void MRCListenerMultiplexerHelper::windowOpened(const ::com::sun::star::lang::EventObject& e) throw() +{ + MULTIPLEX( ::com::sun::star::awt::XTopWindowListener, windowOpened, ::com::sun::star::lang::EventObject ) +} + +// ::com::sun::star::awt::XTopWindowListener +void MRCListenerMultiplexerHelper::windowClosing( const ::com::sun::star::lang::EventObject& e ) throw() +{ + MULTIPLEX( ::com::sun::star::awt::XTopWindowListener, windowClosing, ::com::sun::star::lang::EventObject ) +} + +// ::com::sun::star::awt::XTopWindowListener +void MRCListenerMultiplexerHelper::windowClosed( const ::com::sun::star::lang::EventObject& e ) throw() +{ + MULTIPLEX( ::com::sun::star::awt::XTopWindowListener, windowClosed, ::com::sun::star::lang::EventObject ) +} + +// ::com::sun::star::awt::XTopWindowListener +void MRCListenerMultiplexerHelper::windowMinimized( const ::com::sun::star::lang::EventObject& e ) throw() +{ + MULTIPLEX( ::com::sun::star::awt::XTopWindowListener, windowMinimized, ::com::sun::star::lang::EventObject ) +} + +// ::com::sun::star::awt::XTopWindowListener +void MRCListenerMultiplexerHelper::windowNormalized( const ::com::sun::star::lang::EventObject& e ) throw() +{ + MULTIPLEX( ::com::sun::star::awt::XTopWindowListener, windowNormalized, ::com::sun::star::lang::EventObject ) +} + +// ::com::sun::star::awt::XTopWindowListener +void MRCListenerMultiplexerHelper::windowActivated( const ::com::sun::star::lang::EventObject& e ) throw() +{ + MULTIPLEX( ::com::sun::star::awt::XTopWindowListener, windowActivated, ::com::sun::star::lang::EventObject ) +} + +// ::com::sun::star::awt::XTopWindowListener +void MRCListenerMultiplexerHelper::windowDeactivated( const ::com::sun::star::lang::EventObject& e ) throw() +{ + MULTIPLEX( ::com::sun::star::awt::XTopWindowListener, windowDeactivated, ::com::sun::star::lang::EventObject ) +} --- a/main/extensions/source/plugin/base/nfuncs.cxx +++ a/main/extensions/source/plugin/base/nfuncs.cxx @@ -0,0 +1,696 @@ +/************************************************************** + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + *************************************************************/ + + + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_extensions.hxx" + +#if STLPORT_VERSION>=321 +#include +#endif + +#include + +#include +#include + +#if OSL_DEBUG_LEVEL > 1 +#include +#include +static FILE * s_file = 0; +void TRACE( char const * s ) +{ + if (! s_file) + s_file = stderr; + if (s_file) + { + oslThreadIdentifier t = osl_getThreadIdentifier(0); + fprintf( s_file, "log [t_id=%"SAL_PRIuUINT32"]: %s\n", t, s ); + fflush( s_file ); + } +} +void TRACEN( char const * s, long n ) +{ + if (! s_file) + s_file = stderr; + if (s_file) + { + oslThreadIdentifier t = osl_getThreadIdentifier(0); + fprintf( s_file, "log [t_id=%"SAL_PRIuUINT32"]: %s%ld\n", t, s, n ); + fflush( s_file ); + } +} +void TRACES( char const* s, char const* s2 ) +{ + if (! s_file) + s_file = stderr; + if (s_file) + { + oslThreadIdentifier t = osl_getThreadIdentifier(0); + fprintf( s_file, "log [t_id=%"SAL_PRIuUINT32"]: %s %s\n", t, s, s2 ); + fflush( s_file ); + } +} +#else +#define TRACE(x) +#define TRACEN(x,n) +#define TRACES(x,s) +#endif + +using namespace rtl; +using namespace com::sun::star::lang; + +/* +warning: missing initializer for member '_NPNetscapeFuncs::getstringidentifier' [-Wmissing-field-initializers] +warning: missing initializer for member '_NPNetscapeFuncs::getstringidentifiers' [-Wmissing-field-initializers] +warning: missing initializer for member '_NPNetscapeFuncs::getintidentifier' [-Wmissing-field-initializers] +warning: missing initializer for member '_NPNetscapeFuncs::identifierisstring' [-Wmissing-field-initializers] +warning: missing initializer for member '_NPNetscapeFuncs::utf8fromidentifier' [-Wmissing-field-initializers] +warning: missing initializer for member '_NPNetscapeFuncs::intfromidentifier' [-Wmissing-field-initializers] +warning: missing initializer for member '_NPNetscapeFuncs::createobject' [-Wmissing-field-initializers] +warning: missing initializer for member '_NPNetscapeFuncs::retainobject' [-Wmissing-field-initializers] +warning: missing initializer for member '_NPNetscapeFuncs::releaseobject' [-Wmissing-field-initializers] +warning: missing initializer for member '_NPNetscapeFuncs::invoke' [-Wmissing-field-initializers] +warning: missing initializer for member '_NPNetscapeFuncs::invokeDefault' [-Wmissing-field-initializers] +warning: missing initializer for member '_NPNetscapeFuncs::evaluate' [-Wmissing-field-initializers] +warning: missing initializer for member '_NPNetscapeFuncs::getproperty' [-Wmissing-field-initializers] +warning: missing initializer for member '_NPNetscapeFuncs::setproperty' [-Wmissing-field-initializers] +warning: missing initializer for member '_NPNetscapeFuncs::removeproperty' [-Wmissing-field-initializers] +warning: missing initializer for member '_NPNetscapeFuncs::hasproperty' [-Wmissing-field-initializers] +warning: missing initializer for member '_NPNetscapeFuncs::hasmethod' [-Wmissing-field-initializers] +warning: missing initializer for member '_NPNetscapeFuncs::releasevariantvalue' [-Wmissing-field-initializers] +warning: missing initializer for member '_NPNetscapeFuncs::setexception' [-Wmissing-field-initializers] +warning: missing initializer for member '_NPNetscapeFuncs::pushpopupsenabledstate' [-Wmissing-field-initializers] +warning: missing initializer for member '_NPNetscapeFuncs::poppopupsenabledstate' [-Wmissing-field-initializers] + */ +NPNetscapeFuncs aNPNFuncs = +{ + sizeof( NPNetscapeFuncs ), + (NP_VERSION_MAJOR << 8) | NP_VERSION_MINOR, + NPN_GetURL, + NPN_PostURL, + NPN_RequestRead, + NPN_NewStream, + NPN_Write, + NPN_DestroyStream, + NPN_Status, + NPN_UserAgent, + NPN_MemAlloc, + NPN_MemFree, + NPN_MemFlush, + NPN_ReloadPlugins, +#ifdef OJI + NPN_GetJavaEnv, + NPN_GetJavaPeer, +#else + 0, + 0, +#endif + NPN_GetURLNotify, + NPN_PostURLNotify, + NPN_GetValue, + NPN_SetValue, + NPN_InvalidateRect, + NPN_InvalidateRegion, + NPN_ForceRedraw +}; + +static ::rtl::OString normalizeURL( XPlugin_Impl* plugin, const ::rtl::OString& url ) +{ + ::rtl::OString aLoadURL; + if( url.indexOf( ":" ) == -1 ) + { + aLoadURL = ::rtl::OUStringToOString( plugin->getCreationURL(), plugin->getTextEncoding() ); + int nPos; + if( ( nPos = aLoadURL.indexOf( "://" ) ) != -1 ) + { + if( url.getLength() && (url.getStr()[ 0 ] == '/' || url.indexOf( '/' ) != -1) ) + { + // this means same server but new path + nPos = aLoadURL.indexOf( '/', nPos+3 ); + + if( nPos != -1 ) + aLoadURL = aLoadURL.copy( 0, url.getStr()[0] == '/' ? nPos : nPos+1 ); + } + else + { + // same server but new file + nPos = aLoadURL.lastIndexOf( '/' ); + aLoadURL = aLoadURL.copy( 0, nPos+1 ); + } + aLoadURL += url; + } + else + aLoadURL = url; + } + else if( url.indexOf( ":/" ) != -1 ) + aLoadURL = url; + + return aLoadURL; +} + +struct AsynchronousGetURL +{ + OUString aUrl; + OUString aTarget; + Reference< XEventListener > xListener; + + DECL_LINK( getURL, XPlugin_Impl* ); +}; + +IMPL_LINK( AsynchronousGetURL, getURL, XPlugin_Impl*, pImpl ) +{ + try + { + pImpl->enterPluginCallback(); + if( xListener.is() ) + pImpl->getPluginContext()-> + getURLNotify( pImpl, + aUrl, + aTarget, + xListener ); + else + pImpl->getPluginContext()-> + getURL( pImpl, + aUrl, + aTarget ); + } + catch( ::com::sun::star::plugin::PluginException& e ) + { + (void)e; + } + pImpl->leavePluginCallback(); + delete this; + return 0; +} + + +extern "C" { + + void* SAL_CALL NP_LOADDS NPN_MemAlloc( uint32 nBytes ) + { + TRACE( "NPN_MemAlloc" ); + void* pMem = malloc( nBytes ); + return pMem; + } + + void SAL_CALL NP_LOADDS NPN_MemFree( void* pMem ) + { + TRACE( "NPN_MemFree" ); + free( pMem ); + } + + uint32 SAL_CALL NP_LOADDS NPN_MemFlush( uint32 /*nSize*/ ) + { + TRACE( "NPN_MemFlush" ); + return 0; + } + + NPError SAL_CALL NP_LOADDS NPN_DestroyStream( NPP instance, NPStream* stream, NPError /*reason*/ ) + { + TRACE( "NPN_DestroyStream" ); + XPlugin_Impl* pImpl = XPluginManager_Impl::getXPluginFromNPP( instance ); + if( ! pImpl ) + return NPERR_INVALID_INSTANCE_ERROR; + + PluginStream* pStream = pImpl->getStreamFromNPStream( stream ); + if( pStream ) + { + if( pStream->getStreamType() == InputStream ) + static_cast(pStream)->releaseSelf(); + else + delete pStream; + } + + return NPERR_NO_ERROR; + } + + #ifdef OJI + const JRIEnvInterface** SAL_CALL NP_LOADDS NPN_GetJavaEnv() + { + TRACE( "NPN_GetJavaEnv" ); + // no java in this program + return NULL; + } + + jref SAL_CALL NP_LOADDS NPN_GetJavaPeer( NPP /*instance*/ ) + { + TRACE( "NPN_GetJavaPeer" ); + return NULL; + } + #endif + + NPError SAL_CALL NP_LOADDS NPN_GetURL( NPP instance, const char* url, const char* window ) + { + TRACES( "NPN_GetURL", url ); + XPlugin_Impl* pImpl = XPluginManager_Impl::getXPluginFromNPP( instance ); + if( ! pImpl ) + return NPERR_INVALID_INSTANCE_ERROR; + + AsynchronousGetURL* pAsync = new AsynchronousGetURL(); + + OString aLoadURL = normalizeURL( pImpl, url ); + TRACES( "NPN_GetURL", aLoadURL.getStr() ); + pAsync->aUrl = OStringToOUString( aLoadURL, pImpl->getTextEncoding() ); + pAsync->aTarget = OStringToOUString( window, pImpl->getTextEncoding() ); + pImpl->setLastGetUrl( aLoadURL ); + Application::PostUserEvent( LINK( pAsync, AsynchronousGetURL, getURL ), pImpl ); + return NPERR_NO_ERROR; + } + + NPError SAL_CALL NP_LOADDS NPN_GetURLNotify( NPP instance, const char* url, const char* target, + void* notifyData ) + { + TRACES( "NPN_GetURLNotify", url ); + XPlugin_Impl* pImpl = XPluginManager_Impl::getXPluginFromNPP( instance ); + if( ! pImpl ) + return NPERR_INVALID_INSTANCE_ERROR; + + OString aLoadURL = normalizeURL( pImpl, url ); + if( !aLoadURL.getLength() ) + return NPERR_INVALID_URL; + + AsynchronousGetURL* pAsync = new AsynchronousGetURL(); + PluginEventListener* pListener = + new PluginEventListener( pImpl, url, aLoadURL.getStr(), notifyData ); + if( ! target || ! *target ) + { + // stream will be fed back to plugin, + // notify immediately after destruction of stream + pImpl->addPluginEventListener( pListener ); + pListener = NULL; + } + pAsync->aUrl = OStringToOUString( aLoadURL, pImpl->getTextEncoding() ); + pAsync->aTarget = OStringToOUString( target, pImpl->getTextEncoding() ); + pAsync->xListener = pListener; + pImpl->setLastGetUrl( aLoadURL ); + Application::PostUserEvent( LINK( pAsync, AsynchronousGetURL, getURL ), pImpl ); + + return NPERR_NO_ERROR; + } + + NPError SAL_CALL NP_LOADDS NPN_NewStream( NPP instance, NPMIMEType type, const char* target, + NPStream** stream ) + // stream is a return value + { + TRACE( "NPN_NewStream" ); + XPlugin_Impl* pImpl = XPluginManager_Impl::getXPluginFromNPP( instance ); + if( ! pImpl ) + return NPERR_INVALID_INSTANCE_ERROR; + + PluginOutputStream* pStream = new PluginOutputStream( pImpl, + "", 0, 0 ); + *stream = pStream->getStream(); + + try + { + pImpl->enterPluginCallback(); + pImpl->getPluginContext()-> + newStream( + pImpl, + ::rtl::OStringToOUString( type, pImpl->getTextEncoding () ), + ::rtl::OStringToOUString( target, pImpl->getTextEncoding() ), + ::com::sun::star::uno::Reference< ::com::sun::star::io::XActiveDataSource > ( pStream->getOutputStream(), UNO_QUERY ) + ); + pImpl->leavePluginCallback(); + } + catch( ::com::sun::star::plugin::PluginException& e ) + { + pImpl->leavePluginCallback(); + return e.ErrorCode; + } + + return NPERR_NO_ERROR; + } + + NPError SAL_CALL NP_LOADDS NPN_PostURLNotify( NPP instance, const char* url, const char* target, uint32 len, const char* buf, NPBool file, void* notifyData ) + { + TRACE( "NPN_PostURLNotify" ); + XPlugin_Impl* pImpl = XPluginManager_Impl::getXPluginFromNPP( instance ); + if( ! pImpl ) + return NPERR_INVALID_INSTANCE_ERROR; + + ::com::sun::star::uno::Sequence Bytes( (sal_Int8*)buf, len ); + + ::rtl::OString aPostURL = normalizeURL( pImpl, url ); + PluginEventListener* pListener = + new PluginEventListener( pImpl, url, aPostURL.getStr(), notifyData ); + + if( ! target || ! *target ) + { + // stream will be fed back to plugin, + // notify immediately after destruction of stream + pImpl->addPluginEventListener( pListener ); + pListener = NULL; + } + + try + { + pImpl->enterPluginCallback(); + pImpl->getPluginContext()-> + postURLNotify( pImpl, + ::rtl::OStringToOUString( aPostURL, pImpl->getTextEncoding() ), + ::rtl::OStringToOUString( target, pImpl->getTextEncoding() ), + Bytes, + file, + ::com::sun::star::uno::Reference< ::com::sun::star::lang::XEventListener > ( pListener ) ); + pImpl->leavePluginCallback(); + } + catch( ::com::sun::star::plugin::PluginException& e ) + { + pImpl->leavePluginCallback(); + return e.ErrorCode; + } + + return NPERR_NO_ERROR; + } + + NPError SAL_CALL NP_LOADDS NPN_PostURL( NPP instance, const char* url, const char* window, uint32 len, const char* buf, NPBool file ) + { + TRACE( "NPN_PostURL" ); + XPlugin_Impl* pImpl = XPluginManager_Impl::getXPluginFromNPP( instance ); + if( ! pImpl ) + return NPERR_INVALID_INSTANCE_ERROR; + + ::com::sun::star::uno::Sequence Bytes( (sal_Int8*)buf, len ); + ::rtl::OString aPostURL = normalizeURL( pImpl, url ); + try + { + pImpl->enterPluginCallback(); + pImpl->getPluginContext()-> + postURL( pImpl, + ::rtl::OStringToOUString( aPostURL, pImpl->getTextEncoding() ), + ::rtl::OStringToOUString( window, pImpl->getTextEncoding () ), + Bytes, + file ); + pImpl->leavePluginCallback(); + } + catch( ::com::sun::star::plugin::PluginException& e ) + { + pImpl->leavePluginCallback(); + return e.ErrorCode; + } + + return NPERR_NO_ERROR; + } + + NPError SAL_CALL NP_LOADDS NPN_RequestRead( NPStream* stream, NPByteRange* rangeList ) + { + TRACE( "NPN_RequestRead" ); + if( ! rangeList ) + return NPERR_NO_ERROR; + + ::std::list& rList = PluginManager::get().getPlugins(); + ::std::list::iterator iter; + XPlugin_Impl* pPlugin = NULL; + PluginStream* pStream = NULL; + for( iter = rList.begin(); iter!= rList.end(); ++iter ) + { + pStream = (*iter)->getStreamFromNPStream( stream ); + if( pStream ) + { + pPlugin = *iter; + break; + } + } + if( ! pPlugin ) + return NPERR_INVALID_INSTANCE_ERROR; + if( ! pStream || pStream->getStreamType() != InputStream ) + return NPERR_FILE_NOT_FOUND; + + PluginInputStream* pInputStream = (PluginInputStream*)pStream; + sal_Int8* pBytes = NULL; + int nBytes = 0; + pPlugin->enterPluginCallback(); + while( rangeList ) + { + if( pBytes && nBytes < (int)rangeList->length ) + { + delete [] pBytes; + pBytes = NULL; + } + if( ! pBytes ) + pBytes = new sal_Int8[ nBytes = rangeList->length ]; + int nRead = + pInputStream->read( rangeList->offset, pBytes, rangeList->length ); + int nPos = 0; + int nNow; + do + { + nNow = pPlugin->getPluginComm()-> + NPP_WriteReady( pPlugin->getNPPInstance(), + stream ); + nNow = pPlugin->getPluginComm()-> + NPP_Write( pPlugin->getNPPInstance(), + stream, + rangeList->offset + nPos, + nNow, + pBytes+nPos ); + nPos += nNow; + nRead -= nNow; + } while( nRead > 0 && nNow ); + rangeList = rangeList->next; + } + pPlugin->leavePluginCallback(); + + return NPERR_NO_ERROR; + } + + void SAL_CALL NP_LOADDS NPN_Status( NPP instance, const char* message ) + { + TRACE( "NPN_Status" ); + XPlugin_Impl* pImpl = XPluginManager_Impl::getXPluginFromNPP( instance ); + if( ! pImpl ) + return; + + try + { + pImpl->enterPluginCallback(); + pImpl->getPluginContext()-> + displayStatusText( pImpl, ::rtl::OStringToOUString( message, pImpl->getTextEncoding() ) ); + pImpl->leavePluginCallback(); + } + catch( ::com::sun::star::plugin::PluginException& ) + { + pImpl->leavePluginCallback(); + return; + } + } + + const char* SAL_CALL NP_LOADDS NPN_UserAgent( NPP instance ) + { + static char* pAgent = strdup( "Mozilla 3.0" ); + + XPlugin_Impl* pImpl = XPluginManager_Impl::getXPluginFromNPP( instance ); + if( pImpl ) + { + rtl::OUString UserAgent; + try + { + pImpl->enterPluginCallback(); + UserAgent = pImpl->getPluginContext()-> + getUserAgent( pImpl ); + pImpl->leavePluginCallback(); + if( pAgent ) + free( pAgent ); + pAgent = strdup( ::rtl::OUStringToOString( UserAgent, pImpl->getTextEncoding() ).getStr() ); + } + catch( ::com::sun::star::plugin::PluginException& ) + { + pImpl->leavePluginCallback(); + } + } + + TRACES( "NPN_UserAgent: returning", pAgent ); + + return pAgent; + } + +void SAL_CALL NP_LOADDS NPN_Version( int* major, int* minor, int* net_major, int* net_minor ) +{ + TRACE( "NPN_Version" ); + *major = 4; + *minor = 0; + *net_major = 4; + *net_minor = 5; +} + +int32 SAL_CALL NP_LOADDS NPN_Write( NPP instance, NPStream* stream, int32 len, + void* buffer ) +{ + TRACE( "NPN_Write" ); + XPlugin_Impl* pImpl = XPluginManager_Impl::getXPluginFromNPP( instance ); + if( ! pImpl ) + return 0; + + PluginStream* pStream = pImpl->getStreamFromNPStream( stream ); + if( ! pStream || pStream->getStreamType() != OutputStream ) + return 0; + + pImpl->enterPluginCallback(); + ::com::sun::star::uno::Sequence Bytes( (sal_Int8*)buffer, len ); + ((PluginOutputStream*)pStream)->getOutputStream()->writeBytes( Bytes ); + pImpl->leavePluginCallback(); + + return len; +} + + +NPError SAL_CALL NP_LOADDS NPN_GetValue( NPP instance, NPNVariable variable, void* value ) +{ + TRACEN( "NPN_GetValue: ", variable ); + XPlugin_Impl* pImpl = XPluginManager_Impl::getXPluginFromNPP( instance ); + + if( ! pImpl ) + return 0; + + NPError aResult( NPERR_NO_ERROR ); + + switch( variable ) + { + case NPNVxDisplay: + // Unix only, handled in sysdep part + case NPNVxtAppContext: + // Unix only, handled in sysdep part + default: + aResult = NPERR_INVALID_PARAM; + break; + #ifdef QUARTZ + case 2000: // NPNVsupportsQuickDrawBool + *(NPBool*)value = false; + break; + case 2001: // NPNVsupportsCoreGraphicsBool + *(NPBool*)value = true; + break; + #endif + case NPNVjavascriptEnabledBool: + // no javascript + *(NPBool*)value = false; + break; + case NPNVasdEnabledBool: + // no SmartUpdate + *(NPBool*)value = false; + break; + case NPNVisOfflineBool: + // no offline browsing + *(NPBool*)value = false; + break; + } + /* + provisional code should there ever be NPNVariables that we actually + want to query from the PluginContext + ::rtl::OUString aValue; + try + { + pImpl->enterPluginCallback(); + aValue = pImpl->getPluginContext()-> + getValue( pImpl, (::com::sun::star::plugin::PluginVariable)variable ); + pImpl->leavePluginCallback(); + } + catch( ::com::sun::star::plugin::PluginException& e ) + { + pImpl->leavePluginCallback(); + return e.ErrorCode; + } + */ + + return aResult; +} + +void SAL_CALL NP_LOADDS NPN_ReloadPlugins(NPBool /*reloadPages*/) +{ + TRACE( "NPN_ReloadPlugins" ); +} + + +NPError SAL_CALL NP_LOADDS NPN_SetValue( NPP instance, + NPPVariable variable, + void* value ) +{ + NPError nError = NPERR_NO_ERROR; + TRACEN( "NPN_SetValue ", variable ); + switch( variable ) + { + #ifdef QUARTZ + case (NPPVariable)1000: // NPNVpluginDrawingModel + { + int nDrawingModel = (int)value; // ugly, but that's the way we need to do it + + TRACEN( "drawing model: ", nDrawingModel ); + + XPlugin_Impl* pImpl = XPluginManager_Impl::getXPluginFromNPP( instance ); + if( pImpl ) + pImpl->getSysPlugData().m_nDrawingModel = nDrawingModel; + } + break; + #endif + case NPPVpluginNameString: // make the windows compiler happy, it needs at least one case statement + break; + default: + break; + } + #ifndef QUARTZ + (void)instance; + (void)value; + #endif + return nError; +} + +void SAL_CALL NP_LOADDS NPN_InvalidateRect(NPP instance, NPRect* /*invalidRect*/) +{ + TRACE( "NPN_InvalidateRect" ); + + #ifdef QUARTZ + NPN_ForceRedraw( instance ); + #else + (void)instance; + #endif +} + +void SAL_CALL NP_LOADDS NPN_InvalidateRegion(NPP instance, NPRegion /*invalidRegion*/) +{ + TRACE( "NPN_InvalidateRegion" ); + + #ifdef QUARTZ + NPN_ForceRedraw( instance ); + #else + (void)instance; + #endif +} + +void SAL_CALL NP_LOADDS NPN_ForceRedraw(NPP instance) +{ + TRACE( "NPN_ForceRedraw" ); + #ifdef QUARTZ + XPlugin_Impl* pImpl = XPluginManager_Impl::getXPluginFromNPP( instance ); + if( pImpl ) + { + SysPlugData& rPlugData( pImpl->getSysPlugData() ); + if( rPlugData.m_pPlugView ) + [rPlugData.m_pPlugView setNeedsDisplay: YES]; + } + #else + (void)instance; + #endif +} + +} --- a/main/extensions/source/plugin/base/plcom.cxx +++ a/main/extensions/source/plugin/base/plcom.cxx @@ -0,0 +1,67 @@ +/************************************************************** + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + *************************************************************/ + + + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_extensions.hxx" + +#ifdef SOLARIS +#include +#endif + +#if STLPORT_VERSION>=321 +#include +#endif + +#include +#include + +PluginComm::PluginComm( const ::rtl::OString& rLibName, bool bReusable ) : + m_nRefCount( 0 ), + m_aLibName( rLibName ) +{ + if( bReusable ) + PluginManager::get().getPluginComms().push_back( this ); +} + +PluginComm::~PluginComm() +{ + PluginManager::get().getPluginComms().remove( this ); + while( m_aFilesToDelete.size() ) + { + String aFile = m_aFilesToDelete.front(); + m_aFilesToDelete.pop_front(); + DirEntry aEntry( aFile ); + aEntry.Kill(); + } +} + +NPError PluginComm::NPP_SetWindow( XPlugin_Impl* i_pImpl ) +{ + return NPP_SetWindow( i_pImpl->getNPPInstance(), i_pImpl->getNPWindow() ); +} + +NPError PluginComm::NPP_Destroy( XPlugin_Impl* i_pImpl, NPSavedData** save ) +{ + return NPP_Destroy( i_pImpl->getNPPInstance(), save ); +} + --- a/main/extensions/source/plugin/base/plctrl.cxx +++ a/main/extensions/source/plugin/base/plctrl.cxx @@ -0,0 +1,319 @@ +/************************************************************** + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + *************************************************************/ + + + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_extensions.hxx" +#include +#include +#include +#include +#include +#include + +#include +#include +#include + + +//-------------------------------------------------------------------------------------------------- +PluginControl_Impl::PluginControl_Impl() : + _pMultiplexer( NULL ) + , _nX( 0 ) + , _nY( 0 ) + , _nWidth( 100 ) + , _nHeight( 100 ) + , _nFlags( WINDOW_POSSIZE_ALL ) + , _bVisible( sal_False ) + , _bInDesignMode( sal_False ) + , _bEnable( sal_True ) +{ +} + +//-------------------------------------------------------------------------------------------------- +PluginControl_Impl::~PluginControl_Impl() +{ +} + +MRCListenerMultiplexerHelper* PluginControl_Impl::getMultiplexer() +{ + if( ! _pMultiplexer ) + _pMultiplexer = new MRCListenerMultiplexerHelper( this, _xPeerWindow ); + return _pMultiplexer; +} +//================================================================================================== + +void PluginControl_Impl::addEventListener( const Reference< ::com::sun::star::lang::XEventListener > & l ) + throw( RuntimeException ) +{ + _aDisposeListeners.push_back( l ); +} + +//---- ::com::sun::star::lang::XComponent ---------------------------------------------------------------------------------- +void PluginControl_Impl::removeEventListener( const Reference< ::com::sun::star::lang::XEventListener > & l ) + throw( RuntimeException ) +{ + _aDisposeListeners.remove( l ); +} + +//---- ::com::sun::star::lang::XComponent ---------------------------------------------------------------------------------- +void PluginControl_Impl::dispose(void) + throw( RuntimeException ) +{ + // send disposing events + ::com::sun::star::lang::EventObject aEvt; + if( getMultiplexer() ) + getMultiplexer()->disposeAndClear(); + + // release context + _xContext = Reference< XInterface > (); + releasePeer(); +} + + +//---- ::com::sun::star::awt::XWindow ------------------------------------------------------------------------------------- +void PluginControl_Impl::setPosSize( sal_Int32 nX_, sal_Int32 nY_, sal_Int32 nWidth_, sal_Int32 nHeight_, sal_Int16 nFlags ) + throw( RuntimeException ) +{ + _nX = nX_ >=0 ? nX_ : 0; + _nY = nY_ >=0 ? nY_ : 0; + _nWidth = nWidth_ >=0 ? nWidth_ : 0; + _nHeight = nHeight_ >=0 ? nHeight_ : 0; + _nFlags = nFlags; + + if (_xPeerWindow.is()) + _xPeerWindow->setPosSize( _nX, _nY, _nWidth, _nHeight, nFlags ); +} + +//---- ::com::sun::star::awt::XWindow ------------------------------------------------------------------------------------- +::com::sun::star::awt::Rectangle PluginControl_Impl::getPosSize(void) + throw( RuntimeException ) +{ + return _xPeerWindow->getPosSize(); +} + +//---- ::com::sun::star::awt::XWindow ------------------------------------------------------------------------------------- +void PluginControl_Impl::setVisible( sal_Bool bVisible ) + throw( RuntimeException ) +{ + _bVisible = bVisible; + if (_xPeerWindow.is()) + _xPeerWindow->setVisible( _bVisible && !_bInDesignMode ); +} + +//---- ::com::sun::star::awt::XWindow ------------------------------------------------------------------------------------- +void PluginControl_Impl::setEnable( sal_Bool bEnable ) + throw( RuntimeException ) +{ + _bEnable = bEnable; + if (_xPeerWindow.is()) + _xPeerWindow->setEnable( _bEnable ); +} + +//---- ::com::sun::star::awt::XWindow ------------------------------------------------------------------------------------- +void PluginControl_Impl::setFocus(void) throw( RuntimeException ) +{ + if (_xPeerWindow.is()) + _xPeerWindow->setFocus(); +} + + +//-------------------------------------------------------------------------------------------------- +void PluginControl_Impl::releasePeer() +{ + if (_xPeer.is()) + { + _xParentWindow->removeFocusListener( this ); + _xPeerWindow->dispose(); + _pSysChild = NULL; + _xPeerWindow = Reference< ::com::sun::star::awt::XWindow > (); + _xPeer = Reference< ::com::sun::star::awt::XWindowPeer > (); + getMultiplexer()->setPeer( Reference< ::com::sun::star::awt::XWindow > () ); + } +} + +//---- ::com::sun::star::awt::XControl ------------------------------------------------------------------------------------ +void PluginControl_Impl::createPeer( const Reference< ::com::sun::star::awt::XToolkit > & /*xToolkit*/, const Reference< ::com::sun::star::awt::XWindowPeer > & xParentPeer ) + throw( RuntimeException ) +{ + if (_xPeer.is()) + { + DBG_ERROR( "### Peer is already set!" ); + return; + } + + _xParentPeer = xParentPeer; + _xParentWindow = Reference< ::com::sun::star::awt::XWindow > ( xParentPeer, UNO_QUERY ); + DBG_ASSERT( _xParentWindow.is(), "### no parent peer window!" ); + + Window* pImpl = VCLUnoHelper::GetWindow( xParentPeer ); + if (pImpl) + { + _pSysChild = new SystemChildWindow( pImpl, WB_CLIPCHILDREN ); + if (pImpl->HasFocus()) + _pSysChild->GrabFocus(); + + // get peer + _xPeer = Reference< ::com::sun::star::awt::XWindowPeer > ( _pSysChild->GetComponentInterface() ); + _xPeerWindow = Reference< ::com::sun::star::awt::XWindow > ( _xPeer, UNO_QUERY ); + // !_BOTH_ MUST BE VALID! + DBG_ASSERT( (_xPeer.is() && _xPeerWindow.is()), "### no peer!" ); + + _xParentWindow->addFocusListener( this ); + _xPeerWindow->setPosSize( _nX, _nY, _nWidth, _nHeight, _nFlags ); + _xPeerWindow->setEnable( _bEnable ); + _xPeerWindow->setVisible( _bVisible && !_bInDesignMode ); + } + else + { + DBG_ERROR( "### cannot get implementation of parent peer!" ); + } + + getMultiplexer()->setPeer( _xPeerWindow ); +} + +//---- ::com::sun::star::awt::XControl ------------------------------------------------------------------------------------ +void PluginControl_Impl::setDesignMode( sal_Bool bOn ) + throw( RuntimeException ) +{ + _bInDesignMode = bOn; + if (_xPeerWindow.is()) + _xPeerWindow->setVisible( _bVisible && !_bInDesignMode ); +} + +//---- ::com::sun::star::awt::XWindow ------------------------------------------------------------------------------------- +void PluginControl_Impl::addPaintListener( const Reference< ::com::sun::star::awt::XPaintListener > & l ) + throw( RuntimeException ) +{ + getMultiplexer()->advise( ::getCppuType((const Reference< ::com::sun::star::awt::XPaintListener >*)0), l ); +} + +//---- ::com::sun::star::awt::XWindow ------------------------------------------------------------------------------------- +void PluginControl_Impl::removePaintListener( const Reference< ::com::sun::star::awt::XPaintListener > & l ) + throw( RuntimeException ) +{ + getMultiplexer()->unadvise( ::getCppuType((const Reference< ::com::sun::star::awt::XPaintListener >*)0), l ); +} + +//---- ::com::sun::star::awt::XWindow ------------------------------------------------------------------------------------- +void PluginControl_Impl::addWindowListener( const Reference< ::com::sun::star::awt::XWindowListener > & l ) + throw( RuntimeException ) +{ + getMultiplexer()->advise( ::getCppuType((const Reference< ::com::sun::star::awt::XWindowListener >*)0), l ); +} + +//---- ::com::sun::star::awt::XWindow ------------------------------------------------------------------------------------- +void PluginControl_Impl::removeWindowListener( const Reference< ::com::sun::star::awt::XWindowListener > & l ) + throw( RuntimeException ) +{ + getMultiplexer()->unadvise( ::getCppuType((const Reference< ::com::sun::star::awt::XWindowListener >*)0), l ); +} + +//---- ::com::sun::star::awt::XWindow ------------------------------------------------------------------------------------- +void PluginControl_Impl::addFocusListener( const Reference< ::com::sun::star::awt::XFocusListener > & l ) + throw( RuntimeException ) +{ + getMultiplexer()->advise( ::getCppuType((const Reference< ::com::sun::star::awt::XFocusListener >*)0), l ); +} + +//---- ::com::sun::star::awt::XWindow ------------------------------------------------------------------------------------- +void PluginControl_Impl::removeFocusListener( const Reference< ::com::sun::star::awt::XFocusListener > & l ) + throw( RuntimeException ) +{ + getMultiplexer()->unadvise( ::getCppuType((const Reference< ::com::sun::star::awt::XFocusListener >*)0), l ); +} + +//---- ::com::sun::star::awt::XWindow ------------------------------------------------------------------------------------- +void PluginControl_Impl::addKeyListener( const Reference< ::com::sun::star::awt::XKeyListener > & l ) + throw( RuntimeException ) +{ + getMultiplexer()->advise( ::getCppuType((const Reference< ::com::sun::star::awt::XKeyListener >*)0), l ); +} + +//---- ::com::sun::star::awt::XWindow ------------------------------------------------------------------------------------- +void PluginControl_Impl::removeKeyListener( const Reference< ::com::sun::star::awt::XKeyListener > & l ) + throw( RuntimeException ) +{ + getMultiplexer()->unadvise( ::getCppuType((const Reference< ::com::sun::star::awt::XKeyListener >*)0), l ); +} + +//---- ::com::sun::star::awt::XWindow ------------------------------------------------------------------------------------- +void PluginControl_Impl::addMouseListener( const Reference< ::com::sun::star::awt::XMouseListener > & l ) + throw( RuntimeException ) +{ + getMultiplexer()->advise( ::getCppuType((const Reference< ::com::sun::star::awt::XMouseListener >*)0), l ); +} + +//---- ::com::sun::star::awt::XWindow ------------------------------------------------------------------------------------- +void PluginControl_Impl::removeMouseListener( const Reference< ::com::sun::star::awt::XMouseListener > & l ) + throw( RuntimeException ) +{ + getMultiplexer()->unadvise( ::getCppuType((const Reference< ::com::sun::star::awt::XMouseListener >*)0), l ); +} + +//---- ::com::sun::star::awt::XWindow ------------------------------------------------------------------------------------- +void PluginControl_Impl::addMouseMotionListener( const Reference< ::com::sun::star::awt::XMouseMotionListener > & l ) + throw( RuntimeException ) +{ + getMultiplexer()->advise( ::getCppuType((const Reference< ::com::sun::star::awt::XMouseMotionListener >*)0), l ); +} + +//---- ::com::sun::star::awt::XWindow ------------------------------------------------------------------------------------- +void PluginControl_Impl::removeMouseMotionListener( const Reference< ::com::sun::star::awt::XMouseMotionListener > & l ) + throw( RuntimeException ) +{ + getMultiplexer()->unadvise( ::getCppuType((const Reference< ::com::sun::star::awt::XMouseMotionListener >*)0), l ); +} + + +//---- ::com::sun::star::awt::XView --------------------------------------------------------------------------------------- +void PluginControl_Impl::draw( sal_Int32 /*x*/, sal_Int32 /*y*/ ) + throw( RuntimeException ) +{ + // has to be done by further implementation of control +} + +//---- ::com::sun::star::awt::XView --------------------------------------------------------------------------------------- +void PluginControl_Impl::setZoom( float /*ZoomX*/, float /*ZoomY*/ ) + throw( RuntimeException ) +{ + // has to be done by further implementation of control +} + +//---- ::com::sun::star::lang::XEventListener ------------------------------------------------------------------------------ +void PluginControl_Impl::disposing( const ::com::sun::star::lang::EventObject & /*rSource*/ ) + throw( RuntimeException ) +{ +} +//---- ::com::sun::star::awt::XFocusListener ------------------------------------------------------------------------------ +void PluginControl_Impl::focusGained( const ::com::sun::star::awt::FocusEvent & /*rEvt*/ ) + throw( RuntimeException ) +{ + if (_xPeerWindow.is()) + _xPeerWindow->setFocus(); +} +//---- ::com::sun::star::awt::XFocusListener ------------------------------------------------------------------------------ +void PluginControl_Impl::focusLost( const ::com::sun::star::awt::FocusEvent & /*rEvt*/ ) + throw( RuntimeException ) +{ +} + --- a/main/extensions/source/plugin/base/plmodel.cxx +++ a/main/extensions/source/plugin/base/plmodel.cxx @@ -0,0 +1,199 @@ +/************************************************************** + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + *************************************************************/ + + + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_extensions.hxx" +#include +#include + +using namespace com::sun::star::uno; + +//================================================================================================== +Reference< XInterface > SAL_CALL PluginModel_CreateInstance( const Reference< ::com::sun::star::uno::XComponentContext > & ) throw( Exception ) +{ + Reference< XInterface > xService = *new PluginModel(); + return xService; +} + +Any PluginModel::queryAggregation( const Type& type ) throw( RuntimeException ) +{ + Any aRet( ::cppu::queryInterface( type, + static_cast< ::com::sun::star::lang::XComponent* >(this), + static_cast< ::com::sun::star::io::XPersistObject* >(this ), + static_cast< ::com::sun::star::awt::XControlModel* >(this), + static_cast< ::com::sun::star::beans::XPropertySet* >(this), + static_cast< ::com::sun::star::beans::XMultiPropertySet* >(this), + static_cast< ::com::sun::star::beans::XFastPropertySet* >(this) + ) ); + return aRet.hasValue() ? aRet : OWeakAggObject::queryAggregation( type ); +} + + +// XPluginManager_Impl +Sequence< ::rtl::OUString > PluginModel::getSupportedServiceNames_Static(void) throw() +{ + Sequence< ::rtl::OUString > aSNS( 1 ); + aSNS.getArray()[0] = ::rtl::OUString::createFromAscii( "com.sun.star.plugin.PluginModel" ); + return aSNS; +} + + +static const char* aCreationURL = "URL"; +static const char* aMime = "TYPE"; + +static ::osl::Mutex aPropertyMutex; + +static ::com::sun::star::beans::Property aProps[] = +{ + ::com::sun::star::beans::Property( + ::rtl::OUString::createFromAscii( aMime ), + 1, + ::getCppuType((const ::rtl::OUString*)0), + ::com::sun::star::beans::PropertyAttribute::BOUND ), + ::com::sun::star::beans::Property( + ::rtl::OUString::createFromAscii( aCreationURL ), + 2, + ::getCppuType((const ::rtl::OUString*)0), + ::com::sun::star::beans::PropertyAttribute::BOUND ) +}; + +PluginModel::PluginModel() : + BroadcasterHelperHolder( aPropertyMutex ), + OPropertySetHelper( m_aHelper ), + OPropertyArrayHelper( aProps, 2 ) +{ +} + +PluginModel::PluginModel(const ::rtl::OUString& rURL, const rtl::OUString& rMimeType ) : + BroadcasterHelperHolder( aPropertyMutex ), + OPropertySetHelper( m_aHelper ), + OPropertyArrayHelper( aProps, 2 ), + m_aCreationURL( rURL ), + m_aMimeType( rMimeType ) +{ +} + +PluginModel::~PluginModel() +{ +} + +Reference< ::com::sun::star::beans::XPropertySetInfo > PluginModel::getPropertySetInfo() throw() +{ + static Reference< ::com::sun::star::beans::XPropertySetInfo > aInfo = + createPropertySetInfo( *this ); + return aInfo; +} + +::cppu::IPropertyArrayHelper& PluginModel::getInfoHelper() +{ + return *this; +} + +sal_Bool PluginModel::convertFastPropertyValue( Any & rConvertedValue, + Any & rOldValue, + sal_Int32 nHandle, + const Any& rValue ) throw() +{ + if( nHandle == 1 || nHandle == 2 ) + { + if( rValue.getValueTypeClass() == TypeClass_STRING ) + { + rConvertedValue = rValue; + if( nHandle == 2 ) + rOldValue <<= m_aCreationURL; + else if( nHandle == 1 ) + rOldValue <<= m_aMimeType; + return sal_True; + } + } + return sal_False; +} + +void PluginModel::setFastPropertyValue_NoBroadcast( sal_Int32 nHandle, + const Any& rValue ) + throw(::com::sun::star::uno::Exception) +{ + if( rValue.getValueTypeClass() == TypeClass_STRING ) // FIXME wrong type! + + { + if( nHandle == 2 ) + rValue >>= m_aCreationURL; + else if( nHandle == 1 ) + rValue >>= m_aMimeType; + } + else + throw ::com::sun::star::lang::IllegalArgumentException(); +} + +void PluginModel::getFastPropertyValue( Any& rValue, sal_Int32 nHandle ) const throw() +{ + if( nHandle == 2 ) + rValue <<= m_aCreationURL; + else if( nHandle == 1 ) + rValue <<= m_aMimeType; +} + +//---- ::com::sun::star::lang::XComponent ---------------------------------------------------------------------------------- +void PluginModel::addEventListener( const Reference< ::com::sun::star::lang::XEventListener > & l ) throw() +{ + m_aDisposeListeners.push_back( l ); +} + +//---- ::com::sun::star::lang::XComponent ---------------------------------------------------------------------------------- +void PluginModel::removeEventListener( const Reference< ::com::sun::star::lang::XEventListener > & l ) throw() +{ + m_aDisposeListeners.remove( l ); +} + +//---- ::com::sun::star::lang::XComponent ---------------------------------------------------------------------------------- +void PluginModel::dispose(void) throw() +{ + // send disposing events + ::com::sun::star::lang::EventObject aEvt; + aEvt.Source = (::cppu::OWeakObject*)this; + ::std::list< Reference< ::com::sun::star::lang::XEventListener > > aLocalListeners = m_aDisposeListeners; + for( ::std::list< Reference< ::com::sun::star::lang::XEventListener > >::iterator it = aLocalListeners.begin(); + it != aLocalListeners.end(); ++it ) + (*it)->disposing( aEvt ); + + m_aDisposeListeners.clear(); + + disposing(); +} + + +// ::com::sun::star::io::XPersistObject +::rtl::OUString PluginModel::getServiceName() throw() +{ + return ::rtl::OUString::createFromAscii( "com.sun.star.plugin.PluginModel" ); +} + +void PluginModel::write(const Reference< ::com::sun::star::io::XObjectOutputStream > & OutStream) throw() +{ + OutStream->writeUTF( m_aCreationURL ); +} + +void PluginModel::read(const Reference< ::com::sun::star::io::XObjectInputStream > & InStream) throw() +{ + m_aCreationURL = InStream->readUTF(); +} --- a/main/extensions/source/plugin/base/service.cxx +++ a/main/extensions/source/plugin/base/service.cxx @@ -0,0 +1,74 @@ +/************************************************************** + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + *************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_extensions.hxx" + +#include +#include +#include + + +namespace pq_sdbc_driver +{ + void *SAL_CALL CreateDriverSingleton( void *pServiceManager ); + + static struct cppu::ImplementationEntry g_entries[] = + { + { + PluginManager_CreateInstance, + XPluginManager_Impl::getImplementationName_Static, + XPluginManager_Impl::getSupportedServiceNames_Static, + cppu::createSingleComponentFactory, + 0, + 0 + }, + { + PluginModel_CreateInstance, + PluginModel::getImplementationName_Static, + PluginModel::getSupportedServiceNames_Static, + cppu::createSingleComponentFactory, + 0, + 0 + }, + { 0, 0, 0, 0, 0, 0 } + }; +} + +extern "C" +{ + SAL_DLLPUBLIC_EXPORT void SAL_CALL component_getImplementationEnvironment( + const sal_Char **ppEnvTypeName, uno_Environment **/*ppEnv*/ ) + { + *ppEnvTypeName = CPPU_CURRENT_LANGUAGE_BINDING_NAME; + } + + SAL_DLLPUBLIC_EXPORT void *SAL_CALL component_getFactory( + const sal_Char *pImplName, void *pServiceManager, void *pRegistryKey ) + { + return ::cppu::component_getFactoryHelper( + pImplName, + pServiceManager, + pRegistryKey , + pq_sdbc_driver::g_entries ); + } +} + --- a/main/extensions/source/plugin/base/xplugin.cxx +++ a/main/extensions/source/plugin/base/xplugin.cxx @@ -0,0 +1,1159 @@ +/************************************************************** + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + *************************************************************/ + + + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_extensions.hxx" +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef UNX +#include +#include +#endif + +#if OSL_DEBUG_LEVEL > 1 +#include +#endif + +using namespace com::sun::star; +using namespace com::sun::star::io; +using namespace com::sun::star::beans; +using namespace com::sun::star::plugin; +using namespace rtl; +using namespace osl; + +class PluginDisposer : public vos::OTimer +{ +private: + XPlugin_Impl* m_pPlugin; + + virtual void SAL_CALL onShot(); +public: + PluginDisposer( XPlugin_Impl* pPlugin ) : + OTimer( vos::TTimeValue( 2, 0 ), + vos::TTimeValue( 2, 0 ) ), + m_pPlugin( pPlugin ) + { start(); } + ~PluginDisposer() {} +}; + +void PluginDisposer::onShot() +{ + if( m_pPlugin ) + { + if( m_pPlugin->isDisposable() ) + { + sal_uLong nEvent; + Application::PostUserEvent( nEvent, LINK( m_pPlugin, XPlugin_Impl, secondLevelDispose ), (void*)m_pPlugin ); + } + } + else + release(); +} + +//================================================================================================== + +Any XPlugin_Impl::queryInterface( const Type& type ) throw( RuntimeException ) +{ + return OWeakAggObject::queryInterface( type ); +} + +Any XPlugin_Impl::queryAggregation( const Type& type ) throw( RuntimeException ) +{ + Any aRet( cppu::queryInterface( type, static_cast< XPlugin* >(this) ) ); + if( ! aRet.hasValue() ) + aRet = PluginControl_Impl::queryAggregation( type ); + return aRet; +} + + +XPlugin_Impl::XPlugin_Impl( const uno::Reference< com::sun::star::uno::XComponentContext > & rxContext) : + PluginControl_Impl(), + m_xContext( rxContext ), + m_pPluginComm( NULL ), + m_aEncoding( gsl_getSystemTextEncoding() ), + m_pArgv( NULL ), + m_pArgn( NULL ), + m_nArgs( 0 ), + m_aPluginMode( NP_FULL ), + m_nProvidingState( PROVIDING_NONE ), + m_nCalledFromPlugin( 0 ), + m_pDisposer( NULL ), + m_bIsDisposed( sal_False ) +{ + memset( &m_aInstance, 0, sizeof( m_aInstance ) ); + memset( &m_aNPWindow, 0, sizeof( m_aNPWindow ) ); + memset( &m_aSysPlugData, 0, sizeof( m_aSysPlugData ) ); + + m_xModel = new PluginModel(); + uno::Reference< com::sun::star::beans::XPropertySet > xPS( m_xModel, UNO_QUERY ); + xPS->addPropertyChangeListener( OUString(), this ); + + Guard< Mutex > aGuard( PluginManager::get().getPluginMutex() ); + PluginManager::get().getPlugins().push_back( this ); +} + +void XPlugin_Impl::destroyInstance() +{ + Guard< Mutex > aGuard( m_aMutex ); + + NPSavedData* pSavedData = NULL; + + destroyStreams(); + if( getPluginComm() ) + { + getPluginComm()->NPP_Destroy( this, &pSavedData ); + getPluginComm()->decRef(); + m_pPluginComm = NULL; + } + + freeArgs(); + + while( m_aPEventListeners.size() ) + { + delete *m_aPEventListeners.begin(); + m_aPEventListeners.pop_front(); + } +} + +XPlugin_Impl::~XPlugin_Impl() +{ + destroyInstance(); +} + +void XPlugin_Impl::checkListeners( const char* normalizedURL ) +{ + if( ! normalizedURL ) + return; + + Guard< Mutex > aGuard( m_aMutex ); + + std::list::iterator iter; + for( iter = m_aPEventListeners.begin(); + iter != m_aPEventListeners.end(); + ++iter ) + { + if( ! strcmp( normalizedURL, (*iter)->getURL() ) || + ! strcmp( normalizedURL, (*iter)->getNormalizedURL() ) ) + { + (*iter)->disposing( com::sun::star::lang::EventObject() ); + delete *iter; + m_aPEventListeners.remove( *iter ); + return; + } + } +} + +IMPL_LINK( XPlugin_Impl, secondLevelDispose, XPlugin_Impl*, /*pThis*/ ) +{ + Guard< Mutex > aGuard( m_aMutex ); + + // may have become undisposable between PostUserEvent and here + // or may have disposed and receive a second UserEvent + std::list& rList = PluginManager::get().getPlugins(); + std::list::iterator iter; + + { + Guard< Mutex > aPluginGuard( PluginManager::get().getPluginMutex() ); + for( iter = rList.begin(); iter != rList.end(); ++iter ) + { + if( *iter == this ) + break; + } + if( iter == rList.end() || ! isDisposable() ) + return 0; + } + + if (m_pDisposer) + { + m_pDisposer->release(); + m_pDisposer = NULL; + } + + uno::Reference< XPlugin > xProtection( this ); + uno::Reference< com::sun::star::beans::XPropertySet > xPS( m_xModel, UNO_QUERY ); + xPS->removePropertyChangeListener( OUString(), this ); + { + Guard< Mutex > aPluginGuard( PluginManager::get().getPluginMutex() ); + rList.remove( this ); + } + m_aNPWindow.window = NULL; +#ifndef UNX + // acrobat does an unconditional XtParent on the windows widget + getPluginComm()->NPP_SetWindow( this ); +#endif + destroyInstance(); + PluginControl_Impl::dispose(); + return 0; +} + +void XPlugin_Impl::dispose() throw() +{ + Guard< Mutex > aGuard( m_aMutex ); + + if (m_bIsDisposed || !getPluginComm()) + return; + m_bIsDisposed = sal_True; + + if( isDisposable() ) + secondLevelDispose( this ); + else + { + m_pDisposer = new PluginDisposer( this ); + m_pDisposer->acquire(); + } +} + +void XPlugin_Impl::initArgs( const Sequence< OUString >& argn, + const Sequence< OUString >& argv, + sal_Int16 mode ) +{ + m_aPluginMode = mode; + + m_nArgs = argn.getLength(); + m_pArgn = new const char*[m_nArgs]; + m_pArgv = new const char*[m_nArgs]; + const OUString* pUArgn = argn.getConstArray(); + const OUString* pUArgv = argv.getConstArray(); + for( int i = 0; i < m_nArgs; i++ ) + { + m_pArgn[i] = strdup( + OUStringToOString( pUArgn[i], m_aEncoding ).getStr() + ); + m_pArgv[i] = strdup( + OUStringToOString( pUArgv[i], m_aEncoding ).getStr() + ); + } +} + +void XPlugin_Impl::freeArgs() +{ + if( m_nArgs > 0 ) + { + for( ; m_nArgs--; ) + { + free( (void*)m_pArgn[m_nArgs] ); + free( (void*)m_pArgv[m_nArgs] ); + } + delete [] m_pArgn; + delete [] m_pArgv; + } +} + +void XPlugin_Impl::prependArg( const char* pName, const char* pValue ) +{ + const char** pNewNames = new const char*[m_nArgs+1]; + const char** pNewValues = new const char*[m_nArgs+1]; + + pNewNames[0] = strdup( pName ); + pNewValues[0] = strdup( pValue ); + for( int nIndex = 0; nIndex < m_nArgs; ++nIndex ) + { + pNewNames[nIndex+1] = m_pArgn[nIndex]; + pNewValues[nIndex+1]= m_pArgv[nIndex]; + } + // free old arrays + delete [] m_pArgn; + delete [] m_pArgv; + // set new arrays + m_pArgn = pNewNames; + m_pArgv = pNewValues; + // set new number of arguments + m_nArgs++; +#if OSL_DEBUG_LEVEL > 1 + fprintf( stderr, "inserted %s=%s\n", pNewNames[0], pNewValues[0] ); +#endif +} + +void XPlugin_Impl::handleSpecialArgs() +{ + // special handling for real audio which needs a lot of parameters + // or won't function at all + if( ! m_aDescription.Mimetype.compareToAscii( "audio/x-pn-realaudio-plugin" ) && m_nArgs < 1 ) + { + OUString aURL; + if( m_xModel.is() ) + { + try + { + uno::Reference< XPropertySet > xProp( m_xModel, UNO_QUERY ); + Any aProp = xProp->getPropertyValue( OUString( RTL_CONSTASCII_USTRINGPARAM( "URL" ) ) ); + aProp >>= aURL; + } + catch( UnknownPropertyException ) + { + } + } + + if( aURL.getLength() ) + { + // set new args, old args need not be freed as there were none set + m_nArgs = 6; + m_pArgn = new const char*[m_nArgs]; + m_pArgv = new const char*[m_nArgs]; + + // SRC + m_pArgn[0] = strdup( "SRC" ); + m_pArgv[0] = strdup( OUStringToOString( aURL, m_aEncoding ).getStr() ); + // WIDTH + m_pArgn[1] = strdup( "WIDTH" ); + m_pArgv[1] = strdup( "200" ); + // HEIGHT + m_pArgn[2] = strdup( "HEIGHT" ); + m_pArgv[2] = strdup( "200" ); + // CONTROLS + m_pArgn[3] = strdup( "CONTROLS" ); + m_pArgv[3] = strdup( "PlayButton,StopButton,ImageWindow" ); + // AUTOSTART + m_pArgn[4] = strdup( "AUTOSTART" ); + m_pArgv[4] = strdup( "TRUE" ); + // NOJAVA + m_pArgn[5] = strdup( "NOJAVA" ); + m_pArgv[5] = strdup( "TRUE" ); + } + } + // #69333# special for pdf + else if( ! m_aDescription.Mimetype.compareToAscii( "application/pdf" ) ) + m_aPluginMode = PluginMode::FULL; + + // see if we have a TYPE tag + int nIndex; + for( nIndex = 0; nIndex < m_nArgs; ++nIndex ) + if( m_pArgn[nIndex][0] == 'T' && + m_pArgn[nIndex][1] == 'Y' && + m_pArgn[nIndex][2] == 'P' && + m_pArgn[nIndex][3] == 'E' && + m_pArgn[nIndex][4] == 0 ) + break; + if( nIndex >= m_nArgs ) + { + // TYPE + prependArg( "TYPE", OUStringToOString( m_aDescription.Mimetype, m_aEncoding ).getStr() ); + } + + // see if we have a SRC tag + for( nIndex = 0; nIndex < m_nArgs; ++nIndex ) + if( m_pArgn[nIndex][0] == 'S' && + m_pArgn[nIndex][1] == 'R' && + m_pArgn[nIndex][2] == 'C' && + m_pArgn[nIndex][3] == 0 ) + break; + if( nIndex >= m_nArgs ) + { + // need a SRC parameter (as all browser set one on the plugin + OUString aURL; + if( m_xModel.is() ) + { + try + { + uno::Reference< XPropertySet > xProp( m_xModel, UNO_QUERY ); + Any aProp = xProp->getPropertyValue( OUString( RTL_CONSTASCII_USTRINGPARAM( "URL" ) ) ); + aProp >>= aURL; + } + catch( UnknownPropertyException ) + { + } + } + + if( aURL.getLength() ) + { + // SRC + prependArg( "SRC", OUStringToOString( aURL, m_aEncoding ).getStr() ); + } + } +} + +void XPlugin_Impl::initInstance( const PluginDescription& rDescription, + const Sequence< OUString >& argn, + const Sequence< OUString >& argv, + sal_Int16 mode ) +{ + Guard< Mutex > aGuard( m_aMutex ); + + m_aDescription = rDescription; + initArgs( argn, argv, mode ); + handleSpecialArgs(); +} + +void XPlugin_Impl::initInstance( const OUString& rURL, + const Sequence< OUString >& argn, + const Sequence< OUString >& argv, + sal_Int16 mode ) +{ + Guard< Mutex > aGuard( m_aMutex ); + + initArgs( argn, argv, mode ); + m_aDescription = fitDescription( rURL ); + + m_xModel = new PluginModel( rURL, m_aDescription.Mimetype ); + handleSpecialArgs(); +} + +void XPlugin_Impl::modelChanged() +{ + Guard< Mutex > aGuard( m_aMutex ); + + m_nProvidingState = PROVIDING_MODEL_UPDATE; + + destroyInstance(); + + m_aDescription = fitDescription( getCreationURL() ); + if( !m_aDescription.Mimetype.getLength() ) + { + m_nProvidingState = PROVIDING_NONE; + return; + } + + OUString aURL = getCreationURL(); + provideNewStream( m_aDescription.Mimetype, + uno::Reference< XActiveDataSource >(), + aURL, + 0, 0, (sal_Bool)(aURL.compareToAscii( "file:", 5 ) == 0) ); + m_nProvidingState = PROVIDING_NONE; +} + +OUString XPlugin_Impl::getCreationURL() +{ + Guard< Mutex > aGuard( m_aMutex ); + + OUString aRet; + uno::Reference< com::sun::star::beans::XPropertySet > xPS( m_xModel, UNO_QUERY ); + if( xPS.is() ) + { + Any aValue = xPS->getPropertyValue( OUString::createFromAscii( "URL" ) ); + aValue >>= aRet; + } + return aRet; +} + + +sal_Bool XPlugin_Impl::setModel( const uno::Reference< com::sun::star::awt::XControlModel > & Model ) + throw( RuntimeException ) +{ + Guard< Mutex > aGuard( m_aMutex ); + + uno::Reference< com::sun::star::beans::XPropertySet > xPS( Model, UNO_QUERY ); + if( ! xPS.is() ) + return sal_False; + + if( getCreationURL().getLength() ) + { + m_xModel = Model; + modelChanged(); + xPS->addPropertyChangeListener( OUString(), this ); + return sal_True; + } + return sal_False; +} + +void XPlugin_Impl::createPeer( const uno::Reference< com::sun::star::awt::XToolkit > & xToolkit, const uno::Reference< com::sun::star::awt::XWindowPeer > & Parent ) + throw( RuntimeException ) +{ + Guard< Mutex > aGuard( m_aMutex ); + + if( ! _xPeer.is() ) + { + if( ! Parent.is() ) + throw RuntimeException(); + PluginControl_Impl::createPeer( xToolkit, Parent ); + } +} + +void XPlugin_Impl::loadPlugin() +{ + Guard< Mutex > aGuard( m_aMutex ); + + std::list::iterator iter; + for( iter = PluginManager::get().getPluginComms().begin(); + iter != PluginManager::get().getPluginComms().end(); ++iter ) + { + if( OStringToOUString( (*iter)->getLibName(), m_aEncoding ) == m_aDescription.PluginName ) + { + setPluginComm( *iter ); + break; + } + } + const SystemEnvData* pEnvData = getSysChildSysData(); +#if defined( UNX ) && !(defined(QUARTZ)) + XSync( (Display*)pEnvData->pDisplay, False ); +#endif + if( ! getPluginComm() ) + { + if( m_aDescription.PluginName.getLength() ) + { +#if defined QUARTZ + PluginComm* pComm = new MacPluginComm( m_aDescription.Mimetype, + m_aDescription.PluginName, + pEnvData->pView ); +#elif defined UNX + // need a new PluginComm + PluginComm* pComm = NULL; + int sv[2]; + if( !socketpair( AF_UNIX, SOCK_STREAM, 0, sv ) ) + pComm = new UnxPluginComm( m_aDescription.Mimetype, + m_aDescription.PluginName, + (XLIB_Window)pEnvData->aWindow, + sv[0], + sv[1] + ); +#elif (defined WNT || defined OS2) + PluginComm* pComm = new PluginComm_Impl( m_aDescription.Mimetype, + m_aDescription.PluginName, + (HWND)pEnvData->hWnd ); +#endif + setPluginComm( pComm ); + } + else + return; + } + + NPError aError = getPluginComm()-> + NPP_New( (char*)OUStringToOString( m_aDescription.Mimetype, + m_aEncoding).getStr(), + getNPPInstance(), + m_aPluginMode == PluginMode::FULL ? NP_FULL : NP_EMBED, + ::sal::static_int_cast< int16, int >( m_nArgs ), + (char**)(m_nArgs ? m_pArgn : NULL), + (char**)(m_nArgs ? m_pArgv : NULL), + NULL ); +#ifdef QUARTZ + // m_aNPWindow is set up in the MacPluginComm from the view + m_aSysPlugData.m_pParentView = pEnvData->pView; +#elif defined( UNX ) + XSync( (Display*)pEnvData->pDisplay, False ); + m_aNPWindow.window = (void*)pEnvData->aWindow; + m_aNPWindow.ws_info = NULL; +#else + m_aNPWindow.window = (void*)pEnvData->hWnd; +#endif + com::sun::star::awt::Rectangle aPosSize = getPosSize(); + + for( int i = 0; i < m_nArgs; i++ ) + { + OString aName( m_pArgn[i] ); + if( aName.equalsIgnoreAsciiCase( "width" ) ) + { + OString aValue( m_pArgv[i] ); + aPosSize.Width = aValue.toInt32(); + } + else if( aName.equalsIgnoreAsciiCase( "height" ) ) + { + OString aValue( m_pArgv[i] ); + aPosSize.Height = aValue.toInt32(); + } + } + + m_aNPWindow.clipRect.top = 0; + m_aNPWindow.clipRect.left = 0; + m_aNPWindow.clipRect.bottom = ::sal::static_int_cast< uint16, sal_Int32 >( aPosSize.Height ); + m_aNPWindow.clipRect.right = ::sal::static_int_cast< uint16, sal_Int32 >( aPosSize.Width ); + m_aNPWindow.type = NPWindowTypeWindow; + + m_aNPWindow.x = 0; + m_aNPWindow.y = 0; + m_aNPWindow.width = aPosSize.Width ? aPosSize.Width : 600; + m_aNPWindow.height = aPosSize.Height ? aPosSize.Height : 600; + + aError = getPluginComm()->NPP_SetWindow( this ); + (void) aError; +} + +void XPlugin_Impl::destroyStreams() +{ + Guard< Mutex > aGuard( m_aMutex ); + + // streams remove themselves from this list when deleted + while( m_aOutputStreams.size() ) + delete *m_aOutputStreams.begin(); + + // input streams are XOutputStreams, they cannot be simply deleted + std::list aLocalList( m_aInputStreams ); + for( std::list::iterator it = aLocalList.begin(); + it != aLocalList.end(); ++it ) + (*it)->setMode( -1 ); +} + +PluginStream* XPlugin_Impl::getStreamFromNPStream( NPStream* stream ) +{ + Guard< Mutex > aGuard( m_aMutex ); + + std::list::iterator iter; + for( iter = m_aInputStreams.begin(); iter != m_aInputStreams.end(); ++iter ) + if( (*iter)->getStream() == stream ) + return *iter; + + std::list::iterator iter2; + for( iter2 = m_aOutputStreams.begin(); iter2 != m_aOutputStreams.end(); ++iter2 ) + if( (*iter2)->getStream() == stream ) + return *iter2; + + return NULL; +} + +sal_Bool XPlugin_Impl::provideNewStream(const OUString& mimetype, + const uno::Reference< com::sun::star::io::XActiveDataSource > & stream, + const OUString& url, sal_Int32 length, + sal_Int32 lastmodified, sal_Bool isfile) throw() + +{ + Guard< Mutex > aGuard( m_aMutex ); + sal_Bool bRet = sal_False; + + if( m_nProvidingState != PROVIDING_NONE ) + { + m_nProvidingState = PROVIDING_NOW; + Any aAny; + aAny <<= url; + uno::Reference< com::sun::star::beans::XPropertySet > xPS( m_xModel, UNO_QUERY ); + if( xPS.is() ) + { + try + { + xPS->setPropertyValue( OUString::createFromAscii( "URL" ), aAny ); + aAny <<= mimetype; + xPS->setPropertyValue( OUString::createFromAscii( "TYPE" ), aAny ); + } + catch(...) + { + } + } + } + m_nProvidingState = PROVIDING_NOW; + + OString aMIME; + if( mimetype.getLength() ) + aMIME = OUStringToOString( mimetype, m_aEncoding ); + else + aMIME = OUStringToOString( m_aDescription.Mimetype, m_aEncoding ); + + OString aURL = OUStringToOString( url, m_aEncoding ); + + // check wether there is a notifylistener for this stream + // this means that the strema is created from the plugin + // via NPN_GetURLNotify or NPN_PostURLNotify + std::list::iterator iter; + for( iter = m_aPEventListeners.begin(); + iter != m_aPEventListeners.end(); + ++iter ) + { + if( (*iter)->getNormalizedURL() == aURL ) + { + aURL = (*iter)->getURL(); + break; + } + } + + if( ! m_pPluginComm ) + { + loadPlugin(); + if( m_aLastGetUrl.getLength() && m_aLastGetUrl == aURL ) + { + // plugin is pulling data, don't push the same stream; + // this complicated method could have been avoided if + // all plugins respected the SRC parameter; but e.g. + // acrobat reader plugin does not + m_nProvidingState = PROVIDING_NONE; + return sal_True; + } + } + if( ! m_pPluginComm ) + return sal_False; + + if( ! url.getLength() ) + // this is valid if the plugin is supposed to + // pull data (via e.g. NPN_GetURL) + return sal_True; + + // set mimetype on model + { + uno::Reference< com::sun::star::beans::XPropertySet > xPS( m_xModel, UNO_QUERY ); + if( xPS.is() ) + { + try + { + Any aAny; + aAny <<= m_aDescription.Mimetype; + xPS->setPropertyValue( OUString::createFromAscii( "TYPE" ), aAny ); + } + catch(...) + { + } + } + } + + // there may be plugins that can use the file length information, + // but currently none are known. Since this file opening/seeking/closing + // is rather costly, it is #if'ed out. If there are plugins known to + // make use of the file length, simply put it in +#if 0 + if( isfile && ! length ) + { + osl::File aFile( url ); + if( aFile.open( OpenFlag_Read ) == FileBase::E_None ) + { + aFile.setPos( Pos_End, 0 ); + sal_uInt64 nPos = 0; + if( aFile.getPos( nPos ) == FileBase::E_None ) + length = nPos; + aFile.close(); + } + } +#endif + + PluginInputStream* pStream = new PluginInputStream( this, aURL.getStr(), + length, lastmodified ); + uno::Reference< com::sun::star::io::XOutputStream > xNewStream( pStream ); + + if( iter != m_aPEventListeners.end() ) + pStream->getStream()->notifyData = (*iter)->getNotifyData(); + + uint16 stype = 0; + + // special handling acrobat reader + // presenting a seekable stream to it does not seem to work correctly + if( aMIME.equals( "application/pdf" ) ) + isfile = sal_False; + +#if OSL_DEBUG_LEVEL > 1 + fprintf( stderr, + "new stream \"%s\" of MIMEType \"%s\"\n" + "for plugin \"%s\"\n" + "seekable = %s, length = %"SAL_PRIdINT32"\n", + aURL.getStr(), aMIME.getStr(), getPluginComm()->getLibName().getStr(), + isfile ? "true" : "false", length ); + +#endif + if( ! m_pPluginComm->NPP_NewStream( &m_aInstance, + (char*)aMIME.getStr(), + pStream->getStream(), isfile, + &stype ) ) + { +#if OSL_DEBUG_LEVEL > 1 + const char* pType; + switch( stype ) + { + case NP_NORMAL: pType = "NP_NORMAL";break; + case NP_SEEK: pType = "NP_SEEK";break; + case NP_ASFILE: pType = "NP_ASFILE";break; + case NP_ASFILEONLY: pType = "NP_ASFILEONLY";break; + default: pType = "unknown!!!"; + } + fprintf( stderr, "Plugin wants it in Mode %s\n", pType ); +#endif + if( isfile && stype == NP_ASFILEONLY ) + { + OString aFileName; + if( url.compareToAscii( "file:", 5 ) == 0 ) + { + OUString aSysName; + osl_getSystemPathFromFileURL( url.pData, &aSysName.pData ); + aFileName = OUStringToOString( aSysName, m_aEncoding ); + } + else + aFileName = OUStringToOString( url, m_aEncoding ); + m_pPluginComm-> + NPP_StreamAsFile( &m_aInstance, + pStream->getStream(), + aFileName.getStr() ); + } + else + { + pStream->setMode( stype ); + + if( ! stream.is() ) + { + // stream has to be loaded by PluginStream itself via UCB + pStream->load(); + } + else + { + uno::Reference< com::sun::star::io::XConnectable > xConnectable( stream, UNO_QUERY ); + pStream->setPredecessor( xConnectable ); + if( xConnectable.is() ) + { + xConnectable->setSuccessor( static_cast< com::sun::star::io::XConnectable* >(pStream) ); + while( xConnectable->getPredecessor().is() ) + xConnectable = xConnectable->getPredecessor(); + } + stream->setOutputStream( xNewStream ); + pStream->setSource( stream ); + uno::Reference< com::sun::star::io::XActiveDataControl > xController; + if( xConnectable.is() ) + xController = uno::Reference< com::sun::star::io::XActiveDataControl >( xConnectable, UNO_QUERY ); + else + xController = uno::Reference< com::sun::star::io::XActiveDataControl >( stream, UNO_QUERY ); + + if( xController.is() ) + xController->start(); + } + } + bRet = sal_True; + } + + m_nProvidingState = PROVIDING_NONE; + + return bRet; +} + +void XPlugin_Impl::disposing( const com::sun::star::lang::EventObject& /*rSource*/ ) throw() +{ +} + +void XPlugin_Impl::propertyChange( const com::sun::star::beans::PropertyChangeEvent& rEvent ) throw() +{ + Guard< Mutex > aGuard( m_aMutex ); + + if( ! rEvent.PropertyName.compareToAscii( "URL" ) ) + { + OUString aStr; + rEvent.NewValue >>= aStr; + if( m_nProvidingState == PROVIDING_NONE ) + { + if( aStr != m_aURL ) + { + m_aURL = aStr; + modelChanged(); + } + } + } +} + +void XPlugin_Impl::setPluginContext( const uno::Reference< XPluginContext > & rContext ) +{ + m_rBrowserContext = rContext; +} + +void XPlugin_Impl::setPosSize( sal_Int32 nX_, sal_Int32 nY_, sal_Int32 nWidth_, sal_Int32 nHeight_, sal_Int16 nFlags ) + throw( RuntimeException ) +{ + Guard< Mutex > aGuard( m_aMutex ); + +#if OSL_DEBUG_LEVEL > 1 + fprintf( stderr, "XPlugin_Impl::setPosSize( %"SAL_PRIdINT32", %"SAL_PRIdINT32", %"SAL_PRIdINT32", %"SAL_PRIdINT32", %d )\n", + nX_, nY_, nWidth_, nHeight_, nFlags ); +#endif + + PluginControl_Impl::setPosSize(nX_, nY_, nWidth_, nHeight_, nFlags); + + m_aNPWindow.x = 0; + m_aNPWindow.y = 0; + m_aNPWindow.width = nWidth_; + m_aNPWindow.height = nHeight_; + m_aNPWindow.clipRect.top = 0; + m_aNPWindow.clipRect.left = 0; + m_aNPWindow.clipRect.right = ::sal::static_int_cast< uint16, sal_Int32 >( nWidth_ ); + m_aNPWindow.clipRect.bottom = ::sal::static_int_cast< uint16, sal_Int32 >( nHeight_ ); + + if( getPluginComm() ) + getPluginComm()->NPP_SetWindow( this ); +} + +PluginDescription XPlugin_Impl::fitDescription( const OUString& rURL ) +{ + uno::Reference< XPluginManager > xPMgr( + m_xContext->getServiceManager()->createInstanceWithContext( + OUString( RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.plugin.PluginManager" )), m_xContext ), UNO_QUERY ); + if( !xPMgr.is() ) + { + m_nProvidingState = PROVIDING_NONE; + return PluginDescription(); + } + + Sequence< PluginDescription > aDescrs = xPMgr->getPluginDescriptions(); + const PluginDescription* pDescrs = aDescrs.getConstArray(); + + for( int nArg = 0; nArg < m_nArgs; nArg++ ) + { + if( strncmp( m_pArgn[nArg], "TYPE", 4 ) == 0 && + m_pArgn[nArg][4] == 0 ) + { + for( int i = 0; i < aDescrs.getLength(); i++ ) + { + if( pDescrs[i].Mimetype.compareToAscii( m_pArgv[nArg] ) == 0 ) + return pDescrs[i]; + } + } + } + + int nPos = rURL.lastIndexOf( (sal_Unicode)'.' ); + OUString aExt = rURL.copy( nPos ).toAsciiLowerCase(); + if( nPos != -1 ) + { + for( int i = 0; i < aDescrs.getLength(); i++ ) + { + OUString aThisExt = pDescrs[ i ].Extension.toAsciiLowerCase(); + if( aThisExt.indexOf( aExt ) != -1 ) + { + return pDescrs[i]; + } + } + } + return PluginDescription(); +} + + +PluginStream::PluginStream( XPlugin_Impl* pPlugin, + const char* url, sal_uInt32 len, sal_uInt32 lastmod ) : + m_pPlugin( pPlugin ) +{ + memset( &m_aNPStream, 0, sizeof( m_aNPStream ) ); + m_aNPStream.url = strdup( url ); + m_aNPStream.end = len; + m_aNPStream.lastmodified = lastmod; +} + +PluginStream::~PluginStream() +{ + Guard< Mutex > aGuard( m_pPlugin->getMutex() ); + + if( m_pPlugin && m_pPlugin->getPluginComm() ) + { + m_pPlugin->getPluginComm()->NPP_DestroyStream( m_pPlugin->getNPPInstance(), + &m_aNPStream, NPRES_DONE ); + m_pPlugin->checkListeners( m_aNPStream.url ); + m_pPlugin->getPluginComm()->NPP_SetWindow( m_pPlugin ); + } + ::free( (void*)m_aNPStream.url ); +} + +PluginInputStream::PluginInputStream( XPlugin_Impl* pPlugin, + const char* url, + sal_uInt32 len, + sal_uInt32 lastmod ) : + PluginStream( pPlugin, url, len, lastmod ), + m_pContent( NULL ), + m_nMode( NP_NORMAL ), + m_nWritePos( 0 ) +{ + Guard< Mutex > aGuard( m_pPlugin->getMutex() ); + + m_pPlugin->getInputStreams().push_back( this ); + DirEntry aEntry; + aEntry = aEntry.TempName(); + + // set correct extension, some plugins need that + DirEntry aName( String( m_aNPStream.url, m_pPlugin->getTextEncoding() ) ); + String aExtension = aName.GetExtension(); + if( aExtension.Len() ) + aEntry.SetExtension( aExtension ); + m_aFileStream.Open( aEntry.GetFull(), STREAM_READ | STREAM_WRITE ); + if( ! m_aFileStream.IsOpen() ) + { + // #74808# might be that the extension scrambled the whole filename + aEntry = aEntry.TempName(); + m_aFileStream.Open( aEntry.GetFull(), STREAM_READ | STREAM_WRITE ); + } +} + +PluginInputStream::~PluginInputStream() +{ + Guard< Mutex > aGuard( m_pPlugin->getMutex() ); + + m_pPlugin->getInputStreams().remove( this ); + + String aFile( m_aFileStream.GetFileName() ); + + m_aFileStream.Close(); + if( m_pPlugin ) + { + ByteString aFileName( aFile, m_pPlugin->getTextEncoding() ); + if( m_pPlugin->getPluginComm() && m_nMode != -1 ) + // mode -1 means either an error occured, + // or the plugin is already disposing + { + m_pPlugin->getPluginComm()->addFileToDelete( aFile ); + if( m_nMode == NP_ASFILE ) + { + m_pPlugin->getPluginComm()-> + NPP_StreamAsFile( m_pPlugin->getNPPInstance(), + &m_aNPStream, + aFileName.GetBuffer() ); + } + m_pPlugin->getPluginComm()->NPP_SetWindow( m_pPlugin ); + m_pPlugin->getInputStreams().remove( this ); + } + else + DirEntry( m_aFileStream.GetFileName() ).Kill(); + } + else + DirEntry( m_aFileStream.GetFileName() ).Kill(); + if( m_pContent ) + delete m_pContent; +} + +PluginStreamType PluginInputStream::getStreamType() +{ + return InputStream; +} + +void PluginInputStream::load() +{ + Guard< Mutex > aGuard( m_pPlugin->getMutex() ); + + INetURLObject aUrl; + aUrl.SetSmartProtocol( INET_PROT_FILE ); + aUrl.SetSmartURL( + String( getStream()->url, + ::sal::static_int_cast< sal_uInt16, size_t >( strlen( getStream()->url ) ), + RTL_TEXTENCODING_MS_1252 + ) ); + try + { + m_pContent = + new ::ucbhelper::Content( + aUrl.GetMainURL(INetURLObject::DECODE_TO_IURI), + uno::Reference< com::sun::star::ucb::XCommandEnvironment >() + ); + m_pContent->openStream( static_cast< XOutputStream* >( this ) ); + } + catch( com::sun::star::uno::Exception ) + { + } +} + +void PluginInputStream::setMode( sal_Int32 nMode ) +{ + Guard< Mutex > aGuard( m_pPlugin->getMutex() ); + + m_nMode = nMode; + + // invalidation by plugin + if( m_nMode == -1 && m_pPlugin ) + { + m_pPlugin->getInputStreams().remove( this ); + m_pPlugin = NULL; + } +} + +void PluginInputStream::writeBytes( const Sequence& Buffer ) throw() +{ + Guard< Mutex > aGuard( m_pPlugin->getMutex() ); + + m_aFileStream.Seek( STREAM_SEEK_TO_END ); + m_aFileStream.Write( Buffer.getConstArray(), Buffer.getLength() ); + + if( m_nMode == NP_SEEK ) + // hold reference, streem gets destroyed in NPN_DestroyStream + m_xSelf = this; + + if( m_nMode == -1 || !m_pPlugin->getPluginComm() ) + return; + + sal_uInt32 nPos = m_aFileStream.Tell(); + sal_uInt32 nBytes = 0; + while( m_nMode != NP_ASFILEONLY && + m_nWritePos < nPos && + (nBytes = m_pPlugin->getPluginComm()-> NPP_WriteReady( + m_pPlugin->getNPPInstance(), &m_aNPStream )) > 0 ) + { + nBytes = (nBytes > nPos - m_nWritePos) ? nPos - m_nWritePos : nBytes; + + char* pBuffer = new char[ nBytes ]; + m_aFileStream.Seek( m_nWritePos ); + nBytes = m_aFileStream.Read( pBuffer, nBytes ); + + int32 nBytesRead = 0; + try + { + nBytesRead = m_pPlugin->getPluginComm()->NPP_Write( + m_pPlugin->getNPPInstance(), &m_aNPStream, m_nWritePos, nBytes, pBuffer ); + } + catch( ... ) + { + nBytesRead = 0; + } + delete [] pBuffer; + + if( nBytesRead < 0 ) + { + m_nMode = -1; + return; + } + + m_nWritePos += nBytesRead; + } +} + +void PluginInputStream::closeOutput() throw() +{ + Guard< Mutex > aGuard( m_pPlugin->getMutex() ); + + flush(); + m_xSource = uno::Reference< com::sun::star::io::XActiveDataSource >(); +} + +sal_uInt32 PluginInputStream::read( sal_uInt32 offset, sal_Int8* buffer, sal_uInt32 size ) +{ + Guard< Mutex > aGuard( m_pPlugin->getMutex() ); + + if( m_nMode != NP_SEEK ) + return 0; + + m_aFileStream.Seek( offset ); + return m_aFileStream.Read( buffer, size ); +} + +void PluginInputStream::flush(void) throw() +{ +} + +PluginOutputStream::PluginOutputStream( XPlugin_Impl* pPlugin, + const char* url, + sal_uInt32 len, + sal_uInt32 lastmod ) : + PluginStream( pPlugin, url, len, lastmod ), + m_xStream( pPlugin->getComponentContext() + ->getServiceManager()->createInstanceWithContext( + OUString( RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.io.DataOutputStream" )), + pPlugin->getComponentContext() ), UNO_QUERY ) +{ + Guard< Mutex > aGuard( m_pPlugin->getMutex() ); + + m_pPlugin->getOutputStreams().push_back( this ); +} + +PluginOutputStream::~PluginOutputStream() +{ + Guard< Mutex > aGuard( m_pPlugin->getMutex() ); + + m_pPlugin->getOutputStreams().remove( this ); +} + +PluginStreamType PluginOutputStream::getStreamType() +{ + return OutputStream; +} + --- a/main/extensions/source/plugin/inc/plugin/aqua/sysplug.hxx +++ a/main/extensions/source/plugin/inc/plugin/aqua/sysplug.hxx @@ -0,0 +1,163 @@ +/************************************************************** + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + *************************************************************/ + + +#ifndef __PLUGIN_INC_MACPLUG_HXX +#define __PLUGIN_INC_MACPLUG_HXX + +#include + +#include +#include +#include +#include "premac.h" +#include +#include +#include "postmac.h" +#undef uint32 + +#define XP_MAC +#include +#include + +#include "plugin/plcom.hxx" +#include "premac.h" +#include +#include "postmac.h" + +#include "vcl/sysdata.hxx" +#include "vcl/threadex.hxx" +#include "vcl/timer.hxx" +#include "osl/module.h" + +class XPlugin_Impl; + +namespace plugstringhelper +{ +rtl::OUString getString( CFStringRef i_xString ); +rtl::OUString getString( CFURLRef i_xURL ); +CFMutableStringRef createString( const rtl::OUString& i_rString ); +CFURLRef createURL( const rtl::OUString& i_rString ); +rtl::OUString getURLFromPath( const rtl::OUString& i_rPath ); +CFURLRef createURLFromPath( const rtl::OUString& i_rPath ); +rtl::OUString CFURLtoOSLURL( CFURLRef i_xURL ); +} + +//================================================================================================== +class MacPluginComm : + public PluginComm, + public ::vcl::SolarThreadExecutor + +{ + enum CallType { + eNPP_Destroy, + eNPP_DestroyStream, + eNPP_GetJavaClass, + eNPP_Initialize, + eNPP_New, + eNPP_NewStream, + eNPP_Print, + eNPP_SetWindow, + eNPP_Shutdown, + eNPP_StreamAsFile, + eNPP_URLNotify, + eNPP_Write, + eNPP_WriteReady, + eNPP_GetValue, + eNPP_SetValue, + eNPP_HandleEvent, + eNP_Initialize + }; + + void* m_aArgs[ 8 ]; + CallType m_eCall; + + virtual long doIt(); +public: + MacPluginComm( const rtl::OUString& rMIME, const rtl::OUString& rName, NSView* pView ); + virtual ~MacPluginComm(); + + // FIXME: + // this actually should be from the NP headers + // but currently we have too old a version + // changes this when we have updated our headers + typedef struct NP_CGContext + { + CGContextRef context; + WindowRef window; + } NP_CGContext; + +public: + virtual NPError NPP_Destroy( NPP instance, NPSavedData** save ); + virtual NPError NPP_DestroyStream( NPP instance, NPStream* stream, NPError reason ); + virtual void * NPP_GetJavaClass(); + virtual NPError NPP_Initialize(); + virtual NPError NPP_New( NPMIMEType pluginType, NPP instance, uint16 mode, int16 argc, + char* argn[], char* argv[], NPSavedData *saved ); + virtual NPError NPP_NewStream( NPP instance, NPMIMEType type, NPStream* stream, + NPBool seekable, uint16* stype ); + virtual void NPP_Print( NPP instance, NPPrint* platformPrint ); + virtual NPError NPP_SetWindow( NPP instance, NPWindow* window ); + virtual void NPP_Shutdown(); + virtual void NPP_StreamAsFile( NPP instance, NPStream* stream, const char* fname ); + virtual void NPP_URLNotify( NPP instance, const char* url, + NPReason reason, void* notifyData ); + virtual int32 NPP_Write( NPP instance, NPStream* stream, int32 offset, + int32 len, void* buffer ); + virtual int32 NPP_WriteReady( NPP instance, NPStream* stream ); + virtual NPError NPP_GetValue( NPP instance, NPPVariable variable, void *ret_value ); + virtual NPError NPP_SetValue( NPP instance, NPNVariable variable, void *ret_value ); + virtual int16 NPP_HandleEvent( NPP instance, void* event ); + + virtual NPError NPP_SetWindow( XPlugin_Impl* ); + virtual NPError NPP_Destroy( XPlugin_Impl*, NPSavedData** save ); + + void drawView( XPlugin_Impl* ); +private: + sal_Bool retrieveFunction( const char* i_pName, void** i_ppFunc ) const; + DECL_LINK( NullTimerHdl, void* ); + +private: + CFBundleRef m_xBundle; + oslModule m_hPlugLib; + NPPluginFuncs m_aNPPfuncs; + + // timer for sending nullEvents + AutoTimer* m_pNullTimer; + std::list< XPlugin_Impl* > m_aNullEventClients; +}; + +struct SysPlugData +{ + MacPluginComm::NP_CGContext m_aCGContext; + NP_Port m_aNPPort; + NSView* m_pParentView; + NSView* m_pPlugView; + int m_nDrawingModel; + NSPoint m_aLastPlugViewOrigin; + bool m_bSetWindowOnDraw; +}; + + + +#endif + + --- a/main/extensions/source/plugin/inc/plugin/impl.hxx +++ a/main/extensions/source/plugin/inc/plugin/impl.hxx @@ -0,0 +1,426 @@ +/************************************************************** + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + *************************************************************/ + + +#ifndef __PLUGIN_SOURCE_MGR_IMPL_HXX +#define __PLUGIN_SOURCE_MGR_IMPL_HXX + +#ifdef SOLARIS +#include +#endif + +#include "cppuhelper/weak.hxx" + +#include "com/sun/star/awt/Key.hpp" +#include "com/sun/star/awt/KeyFunction.hpp" +#include "com/sun/star/beans/PropertyAttribute.hpp" +#include "com/sun/star/plugin/PluginMode.hpp" +#include "com/sun/star/plugin/PluginDescription.hpp" +#include "com/sun/star/plugin/PluginException.hpp" +#include "com/sun/star/plugin/PluginVariable.hpp" +#include "com/sun/star/plugin/XPlugin.hpp" +#include "com/sun/star/plugin/XPluginManager.hpp" +#include "com/sun/star/plugin/XPluginContext.hpp" +#include "com/sun/star/io/XConnectable.hpp" +#include "com/sun/star/io/XOutputStream.hpp" +#include "com/sun/star/io/XDataOutputStream.hpp" +#include "com/sun/star/io/XActiveDataControl.hpp" +#include "com/sun/star/io/XDataInputStream.hpp" +#include "com/sun/star/io/XMarkableStream.hpp" +#include "com/sun/star/io/XInputStream.hpp" +#include "com/sun/star/io/XStreamListener.hpp" +#include "com/sun/star/io/XActiveDataSink.hpp" +#include "com/sun/star/io/XActiveDataSource.hpp" +#include "com/sun/star/lang/XServiceName.hpp" +#include "com/sun/star/lang/XServiceInfo.hpp" +#include "com/sun/star/lang/XMultiServiceFactory.hpp" +#include "com/sun/star/lang/XSingleServiceFactory.hpp" +#include "com/sun/star/awt/GradientStyle.hpp" +#include "com/sun/star/awt/RasterOperation.hpp" +#include "com/sun/star/awt/Gradient.hpp" +#include "com/sun/star/awt/XGraphics.hpp" + +#include "cppuhelper/implbase3.hxx" +#include "cppuhelper/implbase2.hxx" +#include "cppuhelper/implbase1.hxx" + +#include + +#ifdef WNT +#include "plugin/win/sysplug.hxx" +#endif + +#ifdef WNT +#include +#elif defined(OS2) +#include "plugin/os2/sysplug.hxx" +#elif defined(QUARTZ) +#include "plugin/aqua/sysplug.hxx" +#elif defined(UNX) +#include "plugin/unx/sysplug.hxx" +#endif + +#if ! defined (QUARTZ) +// the QUARTZ implementation needs special instance data +typedef int SysPlugData; +#endif + +#include "plugin/plctrl.hxx" +#include "plugin/model.hxx" + +#include "vcl/sysdata.hxx" +#include "vcl/syschild.hxx" + +#include "tools/link.hxx" +#include "tools/stream.hxx" + + +using namespace com::sun::star::uno; + +#define PROVIDING_NONE 0 +#define PROVIDING_NOW 1 +#define PROVIDING_MODEL_UPDATE 2 + +// forwards +namespace ucbhelper { class Content; } +class PluginStream; +class PluginInputStream; +class PluginOutputStream; +class XPlugin_Impl; +class PluginDisposer; +class PluginEventListener; + +class XPlugin_Impl : public com::sun::star::plugin::XPlugin, + public PluginControl_Impl, + public com::sun::star::beans::XPropertyChangeListener +{ +private: + ::osl::Mutex m_aMutex; + Reference< com::sun::star::uno::XComponentContext > m_xContext; + Reference< com::sun::star::plugin::XPluginContext > m_rBrowserContext; + + PluginComm* m_pPluginComm; + NPP_t m_aInstance; + NPWindow m_aNPWindow; + SysPlugData m_aSysPlugData; + rtl_TextEncoding m_aEncoding; + + const char** m_pArgv; + const char** m_pArgn; + int m_nArgs; + rtl::OString m_aLastGetUrl; + + Reference< com::sun::star::awt::XControlModel > m_xModel; + + ::com::sun::star::plugin::PluginDescription m_aDescription; + sal_Int16 m_aPluginMode; + + int m_nProvidingState; + int m_nCalledFromPlugin; + PluginDisposer* m_pDisposer; + + ::std::list m_aInputStreams; + ::std::list m_aOutputStreams; + ::std::list m_aPEventListeners; + ::rtl::OUString m_aURL; + + sal_Bool m_bIsDisposed; + + void prependArg( const char* pName, const char* pValue ); // arguments will be strdup'ed + void initArgs( const Sequence< rtl::OUString >& argn, + const Sequence< rtl::OUString >& argv, + sal_Int16 mode ); + void freeArgs(); + void handleSpecialArgs(); + + void loadPlugin(); + void destroyInstance(); + void modelChanged(); + +public: + XPlugin_Impl( const Reference< com::sun::star::uno::XComponentContext > & rxContext ); + virtual ~XPlugin_Impl(); + + ::osl::Mutex& getMutex() { return m_aMutex; } + + void destroyStreams(); + + void setLastGetUrl( const rtl::OString& rUrl ) { m_aLastGetUrl = rUrl; } + + com::sun::star::plugin::PluginDescription fitDescription( const rtl::OUString& rURL ); + + ::std::list& getInputStreams() { return m_aInputStreams; } + ::std::list& getOutputStreams() { return m_aOutputStreams; } + PluginComm* getPluginComm() { return m_pPluginComm; } + void setPluginComm( PluginComm* comm ) + { + if( ! m_pPluginComm ) + { + m_pPluginComm = comm; + m_pPluginComm->addRef(); + } + } + Reference< com::sun::star::uno::XComponentContext > getComponentContext() { return m_xContext; } + const com::sun::star::plugin::PluginDescription& getDescription() const { return m_aDescription; } + rtl_TextEncoding getTextEncoding() { return m_aEncoding; } + NPP getNPPInstance() { return &m_aInstance; } + NPWindow* getNPWindow() { return &m_aNPWindow; } + SysPlugData& getSysPlugData() { return m_aSysPlugData; } + + void enterPluginCallback() { m_nCalledFromPlugin++; } + void leavePluginCallback() { m_nCalledFromPlugin--; } + sal_Bool isDisposable() { return m_nCalledFromPlugin < 1 ? sal_True : sal_False; } + DECL_LINK( secondLevelDispose, XPlugin_Impl* ); + + void addPluginEventListener( PluginEventListener* pListener ) + { m_aPEventListeners.push_back( pListener ); } + void checkListeners( const char* normalizedURL ); + + void initInstance( + const com::sun::star::plugin::PluginDescription& rDescription, + const Sequence< rtl::OUString >& argn, + const Sequence< rtl::OUString >& argv, + sal_Int16 mode ); + void initInstance( + const rtl::OUString& rURL, + const Sequence< rtl::OUString >& argn, + const Sequence< rtl::OUString >& argv, + sal_Int16 mode ); + + const rtl::OUString& getRefererURL() { return m_aURL; } + ::rtl::OUString getCreationURL(); + + PluginStream* getStreamFromNPStream( NPStream* ); + + const SystemEnvData* getSysChildSysData() + { return _pSysChild->GetSystemData(); } + + const Reference< com::sun::star::plugin::XPluginContext > & getPluginContext() const + { return m_rBrowserContext; } + void setPluginContext( const Reference< com::sun::star::plugin::XPluginContext > & ); + + void secondLevelDispose(); + +// static const Reference< com::sun::star::reflection::XIdlClass > & staticGetIdlClass(); + + // XInterface + virtual Any SAL_CALL queryInterface( const Type& ) throw( com::sun::star::uno::RuntimeException ); + virtual void SAL_CALL acquire() throw() + { OWeakAggObject::acquire(); } + virtual void SAL_CALL release() throw() + { OWeakAggObject::release(); } + + // OWeakAggObject + virtual Any SAL_CALL queryAggregation( const Type& ) + throw( com::sun::star::uno::RuntimeException ); + + // PluginContol_Impl + virtual void SAL_CALL dispose() throw(); + virtual void SAL_CALL createPeer( const Reference< com::sun::star::awt::XToolkit > & xToolkit, const Reference< com::sun::star::awt::XWindowPeer > & Parent) throw( RuntimeException ); + + virtual sal_Bool SAL_CALL setModel( const Reference< com::sun::star::awt::XControlModel > & Model ) throw( RuntimeException ); + virtual Reference< com::sun::star::awt::XControlModel > SAL_CALL getModel()throw( RuntimeException ) + { return m_xModel; } + + virtual void SAL_CALL setPosSize( sal_Int32 nX_, sal_Int32 nY_, sal_Int32 nWidth_, sal_Int32 nHeight_, sal_Int16 nFlags ) throw( RuntimeException ); + + // com::sun::star::plugin::XPlugin + virtual sal_Bool SAL_CALL provideNewStream(const rtl::OUString& mimetype, const Reference< com::sun::star::io::XActiveDataSource > & stream, const rtl::OUString& url, sal_Int32 length, sal_Int32 lastmodified, sal_Bool isfile) throw(); + + // com::sun::star::beans::XPropertyChangeListener + virtual void SAL_CALL disposing( const com::sun::star::lang::EventObject& rSource ) throw(); + virtual void SAL_CALL propertyChange( const com::sun::star::beans::PropertyChangeEvent& rEvent ) throw(); +}; + +class PluginManager +{ +private: + Reference< com::sun::star::uno::XComponentContext > m_xContext; + ::std::list m_aPluginComms; + ::std::list m_aAllPlugins; + ::osl::Mutex m_aPluginMutex; + + static PluginManager* pManager; + + PluginManager(); +public: + + static PluginManager& get(); + static void setComponentContext( const Reference< com::sun::star::uno::XComponentContext >& xContext ); + static const Sequence< rtl::OUString >& getAdditionalSearchPaths(); + + ::std::list& getPluginComms() { return m_aPluginComms; } + ::std::list& getPlugins() { return m_aAllPlugins; } + ::osl::Mutex& getPluginMutex() { return m_aPluginMutex; } +}; + +class XPluginManager_Impl : + public cppu::WeakAggImplHelper1< com::sun::star::plugin::XPluginManager > +{ + Reference< com::sun::star::uno::XComponentContext > m_xContext; +public: + XPluginManager_Impl( const Reference< com::sun::star::uno::XComponentContext > & ); + virtual ~XPluginManager_Impl(); + + static XPlugin_Impl* getXPluginFromNPP( NPP ); + static XPlugin_Impl* getPluginImplementation( const Reference< com::sun::star::plugin::XPlugin >& plugin ); + + virtual Reference< com::sun::star::plugin::XPluginContext > SAL_CALL createPluginContext() throw(); + + // has to be implemented per system + virtual Sequence< com::sun::star::plugin::PluginDescription > SAL_CALL impl_getPluginDescriptions(void) throw(); + // calls system specific impl_getPluginDescriptions + // checks whether plugins are disabled + virtual Sequence< com::sun::star::plugin::PluginDescription > SAL_CALL getPluginDescriptions(void) throw(); + + virtual Reference< com::sun::star::plugin::XPlugin > SAL_CALL createPlugin( const Reference< com::sun::star::plugin::XPluginContext > & acontext, sal_Int16 mode, const Sequence< rtl::OUString >& argn, const Sequence< rtl::OUString >& argv, const com::sun::star::plugin::PluginDescription& plugintype) throw( RuntimeException,::com::sun::star::plugin::PluginException ); + + virtual Reference< com::sun::star::plugin::XPlugin > SAL_CALL createPluginFromURL( const Reference< com::sun::star::plugin::XPluginContext > & acontext, sal_Int16 mode, const Sequence< rtl::OUString >& argn, const Sequence< rtl::OUString >& argv, const Reference< com::sun::star::awt::XToolkit > & toolkit, const Reference< com::sun::star::awt::XWindowPeer > & parent, const rtl::OUString& url ) throw(); + + virtual sal_Bool SAL_CALL supportsService(const rtl::OUString& ServiceName) throw(); + virtual rtl::OUString SAL_CALL getImplementationName() throw(); + + Sequence< rtl::OUString > SAL_CALL getSupportedServiceNames(void) throw( ); + static Sequence< rtl::OUString > getSupportedServiceNames_Static(void) throw( ); + static rtl::OUString getImplementationName_Static() throw( ) + { + /** the soplayer uses this name in its source! maybe not after 5.2 */ + return rtl::OUString::createFromAscii( "com.sun.star.extensions.PluginManager" ); + } +}; +Reference< XInterface > SAL_CALL PluginManager_CreateInstance( const Reference< com::sun::star::uno::XComponentContext > & ) throw( Exception ); + +enum PluginStreamType { InputStream, OutputStream }; + +class PluginStream +{ +protected: + XPlugin_Impl* m_pPlugin; + NPStream m_aNPStream; +public: + PluginStream( XPlugin_Impl* pPlugin, + const char* url, sal_uInt32 len, sal_uInt32 lastmod ); + virtual ~PluginStream(); + + NPStream* getStream() { return &m_aNPStream; } + XPlugin_Impl* getPlugin() { return m_pPlugin; } + + virtual PluginStreamType getStreamType() = 0; +}; + +class PluginInputStream : + public PluginStream, + public cppu::WeakAggImplHelper2< + ::com::sun::star::io::XOutputStream, + ::com::sun::star::io::XConnectable + > +{ +private: + ::ucbhelper::Content* m_pContent; + sal_Int32 m_nMode; + sal_uInt32 m_nWritePos; + + Reference< com::sun::star::io::XActiveDataSource > m_xSource; + // hold a reference on input until closeOutput is called + + Reference< com::sun::star::io::XConnectable > m_xPredecessor; + Reference< com::sun::star::io::XConnectable > m_xSuccessor; + + // needed to hold a reference to self in NP_SEEK mode + Reference< com::sun::star::io::XOutputStream > m_xSelf; + + SvFileStream m_aFileStream; +public: + PluginInputStream( XPlugin_Impl* pPlugin, + const char* url, sal_uInt32 len, sal_uInt32 lastmod ); + + PluginInputStream() : PluginStream( NULL, NULL, 0, 0 ) {} + + virtual ~PluginInputStream(); + + virtual PluginStreamType getStreamType(); + + void setMode( sal_Int32 nMode ); + sal_uInt32 read( sal_uInt32 offset, sal_Int8* buffer, sal_uInt32 size ); + void setSource( const Reference< com::sun::star::io::XActiveDataSource >& xSource ) { m_xSource = xSource; } + // get contents ot url via ucbhelper::Content + void load(); + + // clear reference + bool releaseSelf() + { bool bRet = m_xSelf.is(); m_xSelf.clear(); return bRet; } + + // XOutputStream + virtual void SAL_CALL writeBytes( const Sequence& ) throw(); + virtual void SAL_CALL flush() throw(); + virtual void SAL_CALL closeOutput() throw(); + + // XConnectable + virtual void SAL_CALL setPredecessor( const Reference< com::sun::star::io::XConnectable >& xPredecessor ) throw() + { m_xPredecessor = xPredecessor; } + virtual Reference< com::sun::star::io::XConnectable > SAL_CALL getPredecessor() throw() + { return m_xPredecessor; } + + virtual void SAL_CALL setSuccessor( const Reference< com::sun::star::io::XConnectable >& xSuccessor ) throw() + { m_xSuccessor = xSuccessor; } + virtual Reference< com::sun::star::io::XConnectable > SAL_CALL getSuccessor() throw() + { return m_xSuccessor; } +}; + +class PluginOutputStream : public PluginStream +{ +private: + Reference< com::sun::star::io::XOutputStream > m_xStream; +public: + PluginOutputStream( XPlugin_Impl* pPlugin, const char* url, + sal_uInt32 len, sal_uInt32 lastmod ); + virtual ~PluginOutputStream(); + + virtual PluginStreamType getStreamType(); + + Reference< com::sun::star::io::XOutputStream > & getOutputStream() { return m_xStream; } +}; + +class PluginEventListener : + public cppu::WeakAggImplHelper1< com::sun::star::lang::XEventListener > +{ +private: + XPlugin_Impl* m_pPlugin; + Reference< com::sun::star::plugin::XPlugin > m_xPlugin; // just to hold the plugin + char* m_pUrl; + char* m_pNormalizedUrl; + void* m_pNotifyData; +public: + PluginEventListener( XPlugin_Impl*, + const char* url, + const char* normurl, + void* notifyData ); + virtual ~PluginEventListener(); + + const char* getURL() { return m_pUrl; } + const char* getNormalizedURL() { return m_pNormalizedUrl; } + void* getNotifyData() { return m_pNotifyData; } + + // com::sun::star::lang::XEventListener + virtual void SAL_CALL disposing( const com::sun::star::lang::EventObject& Source ) throw(); +}; + +#endif --- a/main/extensions/source/plugin/inc/plugin/model.hxx +++ a/main/extensions/source/plugin/inc/plugin/model.hxx @@ -0,0 +1,133 @@ +/************************************************************** + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + *************************************************************/ + + +#ifndef __PLUGIN_MODEL_HXX +#define __PLUGIN_MODEL_HXX + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include + +using namespace com::sun::star::uno; + +class BroadcasterHelperHolder +{ +protected: + ::cppu::OBroadcastHelper m_aHelper; +public: + BroadcasterHelperHolder( osl::Mutex& rMutex ) : + m_aHelper( rMutex ) {} + ~BroadcasterHelperHolder() {} + + ::cppu::OBroadcastHelper& getHelper() { return m_aHelper; } + +}; + +class PluginModel : public BroadcasterHelperHolder, + public cppu::OPropertySetHelper, + public cppu::OPropertyArrayHelper, + public cppu::OWeakAggObject, + public com::sun::star::lang::XComponent, + public com::sun::star::io::XPersistObject, + public com::sun::star::awt::XControlModel +{ + private: + rtl::OUString m_aCreationURL; + rtl::OUString m_aMimeType; + + std::list< Reference< com::sun::star::lang::XEventListener > > + m_aDisposeListeners; + public: + // these are here to force memory de/allocation to sal lib. + static void * SAL_CALL operator new( size_t nSize ) throw() + { return rtl_allocateMemory( nSize ); } + static void SAL_CALL operator delete( void * pMem ) throw() + { rtl_freeMemory( pMem ); } + + PluginModel(); + PluginModel( const rtl::OUString& rURL, const rtl::OUString& rMimeType ); + virtual ~PluginModel(); + + + const rtl::OUString& getCreationURL() { return m_aCreationURL; } + void setMimeType( const rtl::OUString& rMime ) { m_aMimeType = rMime; } + + // XInterface + virtual Any SAL_CALL queryInterface( const Type& rType ) throw( com::sun::star::uno::RuntimeException ) + { return OWeakAggObject::queryInterface( rType ); } + virtual void SAL_CALL acquire() throw() + { OWeakAggObject::acquire(); } + virtual void SAL_CALL release() throw() + { OWeakAggObject::release(); } + + virtual Any SAL_CALL queryAggregation( const Type& ) throw( com::sun::star::uno::RuntimeException ); + + + // com::sun::star::lang::XTypeProvider + + static Sequence< rtl::OUString > SAL_CALL getSupportedServiceNames_Static(void) throw( ); + static rtl::OUString SAL_CALL getImplementationName_Static() throw( ) + { + /** the soplayer uses this name in its source! maybe not after 5.2 */ + return rtl::OUString::createFromAscii( "com.sun.star.extensions.PluginModel" ); + } + + // OPropertySetHelper + virtual cppu::IPropertyArrayHelper& SAL_CALL getInfoHelper(); + virtual sal_Bool SAL_CALL convertFastPropertyValue( Any & rConvertedValue, + Any & rOldValue, + sal_Int32 nHandle, + const Any& rValue ) throw(); + virtual void SAL_CALL setFastPropertyValue_NoBroadcast( sal_Int32 nHandle, + const Any& rValue ) + throw(::com::sun::star::uno::Exception); + virtual void SAL_CALL getFastPropertyValue( Any& rValue, sal_Int32 nHandle ) const throw(); + virtual Reference< com::sun::star::beans::XPropertySetInfo > SAL_CALL getPropertySetInfo() throw(); + + // com::sun::star::io::XPersistObject + virtual rtl::OUString SAL_CALL getServiceName() throw(); + virtual void SAL_CALL write(const Reference< com::sun::star::io::XObjectOutputStream > & OutStream) throw(); + virtual void SAL_CALL read(const Reference< com::sun::star::io::XObjectInputStream > & InStream) throw(); + + // com::sun::star::lang::XComponent + virtual void SAL_CALL addEventListener( const Reference< com::sun::star::lang::XEventListener > & l ) throw(); + virtual void SAL_CALL removeEventListener( const Reference< com::sun::star::lang::XEventListener > & l ) throw(); + virtual void SAL_CALL dispose() throw(); + private: + using cppu::OPropertySetHelper::getFastPropertyValue; +}; +Reference< XInterface > SAL_CALL PluginModel_CreateInstance( const Reference< com::sun::star::uno::XComponentContext > & ) throw( Exception ); + +#endif // __PLUGIN_MODEL_HXX --- a/main/extensions/source/plugin/inc/plugin/multiplx.hxx +++ a/main/extensions/source/plugin/inc/plugin/multiplx.hxx @@ -0,0 +1,163 @@ +/************************************************************** + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + *************************************************************/ + + +#ifndef _MRC_MULTIPLX_HXX +#define _MRC_MULTIPLX_HXX + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +using namespace com::sun::star::uno; + +struct MRCListenerMultiplexerHelper_Mutex +{ + ::osl::Mutex aMutex; +}; + +class MRCListenerMultiplexerHelper : + public MRCListenerMultiplexerHelper_Mutex, + + public ::cppu::WeakAggImplHelper7< + ::com::sun::star::awt::XFocusListener, + ::com::sun::star::awt::XWindowListener, + ::com::sun::star::awt::XKeyListener, + ::com::sun::star::awt::XMouseListener, + ::com::sun::star::awt::XMouseMotionListener, + ::com::sun::star::awt::XPaintListener, + ::com::sun::star::awt::XTopWindowListener > +{ +public: + /** + * Create a Multiplexer of XWindowEvents. + * + * @param rControl The control. All listeners think that this is the original + * broadcaster. + * @param rPeer The peer from which the original events are dispatched. Null is + * allowed. + */ + MRCListenerMultiplexerHelper( const Reference< ::com::sun::star::awt::XWindow > & rControl, const Reference< ::com::sun::star::awt::XWindow > & rPeer ); + + /** + * Remove all listeners from the previous set peer and add the needed listeners to rPeer. + * @param rPeer The peer from which the original events are dispatched. Null is + * allowed. + */ + void setPeer( const Reference< ::com::sun::star::awt::XWindow > & rPeer ); + + /** + * Remove all listeners and send a disposing message. + */ + void disposeAndClear(); + + /** + * Add the specified listener to the source. + */ + void advise( const Type& type, const Reference< XInterface > & listener); + /** + * Remove the specified listener from the source. + */ + void unadvise(const Type& type, const Reference< XInterface > & listener); + + // ::com::sun::star::lang::XEventListener + void SAL_CALL disposing(const ::com::sun::star::lang::EventObject& Source) throw(); + // ::com::sun::star::awt::XFocusListener + void SAL_CALL focusGained(const ::com::sun::star::awt::FocusEvent& e) throw(); + void SAL_CALL focusLost(const ::com::sun::star::awt::FocusEvent& e) throw(); + // ::com::sun::star::awt::XWindowListener + void SAL_CALL windowResized(const ::com::sun::star::awt::WindowEvent& e) throw(); + void SAL_CALL windowMoved(const ::com::sun::star::awt::WindowEvent& e) throw(); + void SAL_CALL windowShown(const ::com::sun::star::lang::EventObject& e) throw(); + void SAL_CALL windowHidden(const ::com::sun::star::lang::EventObject& e) throw(); + // ::com::sun::star::awt::XKeyListener + void SAL_CALL keyPressed( const ::com::sun::star::awt::KeyEvent& e ) throw(); + void SAL_CALL keyReleased( const ::com::sun::star::awt::KeyEvent& e ) throw(); + // ::com::sun::star::awt::XMouseListener + void SAL_CALL mousePressed(const ::com::sun::star::awt::MouseEvent& e) throw(); + void SAL_CALL mouseReleased(const ::com::sun::star::awt::MouseEvent& e) throw(); + void SAL_CALL mouseEntered(const ::com::sun::star::awt::MouseEvent& e) throw(); + void SAL_CALL mouseExited(const ::com::sun::star::awt::MouseEvent& e) throw(); + // ::com::sun::star::awt::XMouseMotionListener + void SAL_CALL mouseDragged(const ::com::sun::star::awt::MouseEvent& e) throw(); + void SAL_CALL mouseMoved(const ::com::sun::star::awt::MouseEvent& e) throw(); + // ::com::sun::star::awt::XPaintListener + void SAL_CALL windowPaint(const ::com::sun::star::awt::PaintEvent& e) throw(); + // ::com::sun::star::awt::XTopWindowListener + void SAL_CALL windowOpened( const ::com::sun::star::lang::EventObject& e ) throw(); + void SAL_CALL windowClosing( const ::com::sun::star::lang::EventObject& e ) throw(); + void SAL_CALL windowClosed( const ::com::sun::star::lang::EventObject& e ) throw(); + void SAL_CALL windowMinimized( const ::com::sun::star::lang::EventObject& e ) throw(); + void SAL_CALL windowNormalized( const ::com::sun::star::lang::EventObject& e ) throw(); + void SAL_CALL windowActivated( const ::com::sun::star::lang::EventObject& e ) throw(); + void SAL_CALL windowDeactivated( const ::com::sun::star::lang::EventObject& e ) throw(); +protected: + /** + * Remove the listener with the uik rUik from the peer rPeer. + * @param rPeer the peer from which the listener is removed. + * @param rUik the listener uik, which specify the type of the listener. + */ + void adviseToPeer( const Reference< ::com::sun::star::awt::XWindow > & rPeer, const Type & type ); + /** + * Add the listener with the uik rUik to the peer rPeer. + * @param rPeer the peer to which the listener is added. + * @param rUik the listener uik, which specify the type of the listener. + */ + void unadviseFromPeer( const Reference< ::com::sun::star::awt::XWindow > & rPeer, const Type & type ); +private: + /** The source of the events. Normally this is the peer object.*/ + Reference< ::com::sun::star::awt::XWindow > xPeer; + WeakReference< ::com::sun::star::awt::XControl > xControl; + ::cppu::OMultiTypeInterfaceContainerHelper aListenerHolder; + + + MRCListenerMultiplexerHelper( const MRCListenerMultiplexerHelper & ); + MRCListenerMultiplexerHelper & operator = ( const MRCListenerMultiplexerHelper & ); +}; + +#endif // _MRC_MULTIPLX_HXX + + + --- a/main/extensions/source/plugin/inc/plugin/plcom.hxx +++ a/main/extensions/source/plugin/inc/plugin/plcom.hxx @@ -0,0 +1,81 @@ +/************************************************************** + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + *************************************************************/ + + +#ifndef __PLUGIN_INC_PLCOM_HXX +#define __PLUGIN_INC_PLCOM_HXX + +#include +#include + +class XPlugin_Impl; + +class PluginComm +{ +protected: + int m_nRefCount; + ::rtl::OString m_aLibName; + std::list< String > m_aFilesToDelete; +public: + PluginComm( const ::rtl::OString& rLibName, bool bReusable = true ); + virtual ~PluginComm(); + + int getRefCount() { return m_nRefCount; } + void addRef() { m_nRefCount++; } + void decRef() { m_nRefCount--; if( ! m_nRefCount ) delete this; } + + const ::rtl::OString& getLibName() { return m_aLibName; } + void setLibName( const ::rtl::OString& rName ) { m_aLibName = rName; } + + void addFileToDelete( const String& filename ) + { m_aFilesToDelete.push_back( filename ); } + + virtual NPError NPP_Destroy( NPP instance, NPSavedData** save ) = 0; + virtual NPError NPP_DestroyStream( NPP instance, NPStream* stream, + NPError reason ) = 0; + virtual void* NPP_GetJavaClass() = 0; + virtual NPError NPP_Initialize() = 0; + virtual NPError NPP_New( NPMIMEType pluginType, NPP instance, + uint16 mode, int16 argc, + char* argn[], char* argv[], + NPSavedData *saved ) = 0; + virtual NPError NPP_NewStream( NPP instance, NPMIMEType type, + NPStream* stream, + NPBool seekable, uint16* stype ) = 0; + virtual void NPP_Print( NPP instance, NPPrint* platformPrint ) = 0; + virtual NPError NPP_SetWindow( NPP instance, NPWindow* window ) = 0; + virtual void NPP_Shutdown() = 0; + virtual void NPP_StreamAsFile( NPP instance, NPStream* stream, + const char* fname ) = 0; + virtual void NPP_URLNotify( NPP instance, const char* url, + NPReason reason, void* notifyData ) = 0; + virtual int32 NPP_Write( NPP instance, NPStream* stream, int32 offset, + int32 len, void* buffer ) = 0; + virtual int32 NPP_WriteReady( NPP instance, NPStream* stream ) = 0; + virtual NPError NPP_GetValue( NPP instance, NPPVariable variable, void* value ) = 0; + virtual NPError NPP_SetValue( NPP instance, NPNVariable variable, + void *value) = 0; + + virtual NPError NPP_SetWindow( XPlugin_Impl* ); + virtual NPError NPP_Destroy( XPlugin_Impl*, NPSavedData** save ); +}; + +#endif --- a/main/extensions/source/plugin/inc/plugin/plctrl.hxx +++ a/main/extensions/source/plugin/inc/plugin/plctrl.hxx @@ -0,0 +1,177 @@ +/************************************************************** + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + *************************************************************/ + + +#ifndef __PLCTRL_HXX +#define __PLCTRL_HXX + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +class SystemChildWindow; + +//================================================================================================== +class PluginControl_Impl : public ::cppu::WeakAggImplHelper4< + ::com::sun::star::awt::XControl, + ::com::sun::star::awt::XWindow, + ::com::sun::star::awt::XFocusListener, + ::com::sun::star::awt::XView > +{ +public: + // ::com::sun::star::awt::XControl + virtual void SAL_CALL setContext( const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > & xContext ) throw( ::com::sun::star::uno::RuntimeException ) + { _xContext = xContext; } + virtual ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > SAL_CALL getContext() throw( ::com::sun::star::uno::RuntimeException ) + { return _xContext; } + + virtual sal_Bool SAL_CALL setModel( const ::com::sun::star::uno::Reference< ::com::sun::star::awt::XControlModel > & Model ) throw( ::com::sun::star::uno::RuntimeException ) = 0; +// { DBG_ERROR( "### setModel() illegal on plugincontrol!" ); return sal_False; } + virtual ::com::sun::star::uno::Reference< ::com::sun::star::awt::XControlModel > SAL_CALL getModel() throw( ::com::sun::star::uno::RuntimeException ) = 0; + + virtual ::com::sun::star::uno::Reference< ::com::sun::star::awt::XView > SAL_CALL getView() throw( ::com::sun::star::uno::RuntimeException ) + { return (::com::sun::star::awt::XView*)this; } + + virtual sal_Bool SAL_CALL isTransparent() throw( ::com::sun::star::uno::RuntimeException ) + { return sal_False; } + + virtual void SAL_CALL setDesignMode( sal_Bool bOn ) throw( ::com::sun::star::uno::RuntimeException ); + virtual sal_Bool SAL_CALL isDesignMode() throw( ::com::sun::star::uno::RuntimeException ) + { return _bInDesignMode; } + + virtual void SAL_CALL createPeer( const ::com::sun::star::uno::Reference< ::com::sun::star::awt::XToolkit > & xToolkit, const ::com::sun::star::uno::Reference< ::com::sun::star::awt::XWindowPeer > & Parent) throw( ::com::sun::star::uno::RuntimeException ); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::awt::XWindowPeer > SAL_CALL getPeer() throw( ::com::sun::star::uno::RuntimeException ) + { return _xPeer; } + + // ::com::sun::star::awt::XWindow + virtual void SAL_CALL setVisible( sal_Bool bVisible ) throw( ::com::sun::star::uno::RuntimeException ); + virtual void SAL_CALL setEnable( sal_Bool bEnable ) throw( ::com::sun::star::uno::RuntimeException ); + virtual void SAL_CALL setFocus(void) throw( ::com::sun::star::uno::RuntimeException ); + + virtual void SAL_CALL setPosSize( sal_Int32 nX_, sal_Int32 nY_, sal_Int32 nWidth_, sal_Int32 nHeight_, sal_Int16 nFlags ) throw( ::com::sun::star::uno::RuntimeException ); + virtual ::com::sun::star::awt::Rectangle SAL_CALL getPosSize(void) throw( ::com::sun::star::uno::RuntimeException ); + + virtual void SAL_CALL addWindowListener( const ::com::sun::star::uno::Reference< ::com::sun::star::awt::XWindowListener > & l ) throw( ::com::sun::star::uno::RuntimeException ); + virtual void SAL_CALL removeWindowListener( const ::com::sun::star::uno::Reference< ::com::sun::star::awt::XWindowListener > & l ) throw( ::com::sun::star::uno::RuntimeException ); + virtual void SAL_CALL addFocusListener( const ::com::sun::star::uno::Reference< ::com::sun::star::awt::XFocusListener > & l ) throw( ::com::sun::star::uno::RuntimeException ); + virtual void SAL_CALL removeFocusListener( const ::com::sun::star::uno::Reference< ::com::sun::star::awt::XFocusListener > & l ) throw( ::com::sun::star::uno::RuntimeException ); + virtual void SAL_CALL addKeyListener( const ::com::sun::star::uno::Reference< ::com::sun::star::awt::XKeyListener > & l ) throw( ::com::sun::star::uno::RuntimeException ); + virtual void SAL_CALL removeKeyListener( const ::com::sun::star::uno::Reference< ::com::sun::star::awt::XKeyListener > & l ) throw( ::com::sun::star::uno::RuntimeException ); + virtual void SAL_CALL addMouseListener( const ::com::sun::star::uno::Reference< ::com::sun::star::awt::XMouseListener > & l ) throw( ::com::sun::star::uno::RuntimeException ); + virtual void SAL_CALL removeMouseListener( const ::com::sun::star::uno::Reference< ::com::sun::star::awt::XMouseListener > & l ) throw( ::com::sun::star::uno::RuntimeException ); + virtual void SAL_CALL addMouseMotionListener( const Reference< ::com::sun::star::awt::XMouseMotionListener > & l ) throw( RuntimeException ); + virtual void SAL_CALL removeMouseMotionListener( const ::com::sun::star::uno::Reference< ::com::sun::star::awt::XMouseMotionListener > & l ) throw( ::com::sun::star::uno::RuntimeException ); + virtual void SAL_CALL addPaintListener( const ::com::sun::star::uno::Reference< ::com::sun::star::awt::XPaintListener > & l ) throw( ::com::sun::star::uno::RuntimeException ); + virtual void SAL_CALL removePaintListener( const ::com::sun::star::uno::Reference< ::com::sun::star::awt::XPaintListener > & l ) throw( ::com::sun::star::uno::RuntimeException ); + + // ::com::sun::star::lang::XEventListener + virtual void SAL_CALL disposing( const ::com::sun::star::lang::EventObject & rSource ) throw( ::com::sun::star::uno::RuntimeException ); + // ::com::sun::star::awt::XFocusListener + virtual void SAL_CALL focusGained( const ::com::sun::star::awt::FocusEvent & rEvt ) throw( ::com::sun::star::uno::RuntimeException ); + virtual void SAL_CALL focusLost( const ::com::sun::star::awt::FocusEvent & rEvt ) throw( ::com::sun::star::uno::RuntimeException ); + + // ::com::sun::star::lang::XComponent + virtual void SAL_CALL addEventListener( const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XEventListener > & l ) throw( ::com::sun::star::uno::RuntimeException ); + virtual void SAL_CALL removeEventListener( const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XEventListener > & l ) throw( ::com::sun::star::uno::RuntimeException ); + + virtual void SAL_CALL dispose() throw( ::com::sun::star::uno::RuntimeException ); + + // ::com::sun::star::awt::XView + virtual sal_Bool SAL_CALL setGraphics( const ::com::sun::star::uno::Reference< ::com::sun::star::awt::XGraphics > & /*aDevice*/ ) throw( ::com::sun::star::uno::RuntimeException ) + { return sal_False; } + virtual ::com::sun::star::uno::Reference< ::com::sun::star::awt::XGraphics > SAL_CALL getGraphics(void) throw( ::com::sun::star::uno::RuntimeException ) + { return ::com::sun::star::uno::Reference< ::com::sun::star::awt::XGraphics > (); } + + virtual ::com::sun::star::awt::Size SAL_CALL getSize(void) throw( ::com::sun::star::uno::RuntimeException ) + { return ::com::sun::star::awt::Size(_nWidth, _nHeight); } + + virtual void SAL_CALL draw( sal_Int32 x, sal_Int32 y ) throw( ::com::sun::star::uno::RuntimeException ); + virtual void SAL_CALL setZoom( float ZoomX, float ZoomY ) throw( ::com::sun::star::uno::RuntimeException ); + +public: + PluginControl_Impl(); + virtual ~PluginControl_Impl(); + + MRCListenerMultiplexerHelper* getMultiplexer(); + +protected: + void releasePeer(); + +protected: + ::std::list< Reference< ::com::sun::star::lang::XEventListener > > _aDisposeListeners; + MRCListenerMultiplexerHelper* _pMultiplexer; + + Reference< XInterface > _xContext; + + sal_Int32 _nX; + sal_Int32 _nY; + sal_Int32 _nWidth; + sal_Int32 _nHeight; + sal_Int16 _nFlags; + + sal_Bool _bVisible; + sal_Bool _bInDesignMode; + sal_Bool _bEnable; + + SystemChildWindow* _pSysChild; + ::com::sun::star::uno::Reference< ::com::sun::star::awt::XWindowPeer > _xPeer; + ::com::sun::star::uno::Reference< ::com::sun::star::awt::XWindow > _xPeerWindow; + + ::com::sun::star::uno::Reference< ::com::sun::star::awt::XWindow > _xParentWindow; + ::com::sun::star::uno::Reference< ::com::sun::star::awt::XWindowPeer > _xParentPeer; +}; + +#endif + + --- a/main/extensions/source/plugin/inc/plugin/unx/mediator.hxx +++ a/main/extensions/source/plugin/inc/plugin/unx/mediator.hxx @@ -0,0 +1,179 @@ +/************************************************************** + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + *************************************************************/ + + +#ifndef _MEDIATOR_HXX +#define _MEDIATOR_HXX + +#include +#include +#include +#include +#include +#include +#include +#include +#if OSL_DEBUG_LEVEL > 1 +#include +#endif + +#include + +struct MediatorMessage +{ + sal_uLong m_nID; + sal_uLong m_nBytes; + char* m_pBytes; + char* m_pRun; + + MediatorMessage() : m_nID( 0 ), m_nBytes( 0 ), + m_pBytes( NULL ), m_pRun( NULL ) {} + MediatorMessage( sal_uLong nID, sal_uLong nBytes, char* pBytes ) : + m_nID( nID ),m_nBytes( nBytes ), m_pRun( NULL ) + { + m_pBytes = new char[ m_nBytes ]; + memcpy( m_pBytes, pBytes, (size_t)m_nBytes ); + } + + ~MediatorMessage() + { + if( m_pBytes ) + delete [] m_pBytes; + } + + void Set( sal_uLong nBytes, char* pBytes ) + { + if( m_pBytes ) + delete [] m_pBytes; + m_nBytes = nBytes; + m_pBytes = new char[ m_nBytes ]; + memcpy( m_pBytes, pBytes, (size_t)m_nBytes ); + } + + sal_uLong ExtractULONG(); + char* GetString(); + sal_uInt32 GetUINT32(); + void* GetBytes( sal_uLong& ); + void* GetBytes() { sal_uLong nBytes; return GetBytes( nBytes ); } + + void Rewind() { m_pRun = NULL; } +}; + +class MediatorListener; + +class Mediator +{ + friend class MediatorListener; +protected: + int m_nSocket; + + std::vector m_aMessageQueue; + vos::OMutex m_aQueueMutex; + vos::OMutex m_aSendMutex; + // only one thread can send a message at any given time + vos::OCondition m_aNewMessageCdtn; + MediatorListener* m_pListener; + // thread to fill the queue + + sal_uLong m_nCurrentID; + // will be constantly increased with each message sent + bool m_bValid; + + Link m_aConnectionLostHdl; + Link m_aNewMessageHdl; +public: + Mediator( int nSocket ); + ~Mediator(); + + // mark mediator as invalid. No more messages will be processed, + // SendMessage, WaitForMessage, TransactMessage will return immediatly + // with error + void invalidate() { m_bValid = false; } + + sal_uLong SendMessage( sal_uLong nBytes, const char* pBytes, sal_uLong nMessageID = 0 ); + sal_uLong SendMessage( const ByteString& rMessage, sal_uLong nMessageID = 0 ) + { + return SendMessage( rMessage.Len(), rMessage.GetBuffer(), nMessageID ); + } + + sal_Bool WaitForMessage( sal_uLong nTimeOut = 5000 ); + // timeout in ms + // TRUE: Message came in + // FALSE: timed out + // if timeout is set, WaitForMessage will wait even if there are messages + // in the queue + + virtual MediatorMessage* WaitForAnswer( sal_uLong nMessageID ); + // wait for an answer message ( ID >= 1 << 24 ) + // the message will be removed from the queue and returned + + MediatorMessage* TransactMessage( sal_uLong nBytes, char* pBytes ); + // sends a message and waits for an answer + + MediatorMessage* GetNextMessage( sal_Bool bWait = sal_False ); + + + Link SetConnectionLostHdl( const Link& rLink ) + { + Link aRet = m_aConnectionLostHdl; + m_aConnectionLostHdl = rLink; + return aRet; + } + + Link SetNewMessageHdl( const Link& rLink ) + { + Link aRet = m_aNewMessageHdl; + m_aNewMessageHdl = rLink; + return aRet; + } +}; + +class MediatorListener : public vos:: OThread +{ + friend class Mediator; + private: + Mediator* m_pMediator; + ::vos::OMutex m_aMutex; + + MediatorListener( Mediator* ); + ~MediatorListener(); + + virtual void run(); + virtual void onTerminated(); +}; + +inline void medDebug( int condition, const char* pFormat, ... ) +{ +#if OSL_DEBUG_LEVEL > 1 + if( condition ) + { + va_list ap; + va_start( ap, pFormat ); + vfprintf( stderr, pFormat, ap ); + va_end( ap ); + } +#else + (void)condition; + (void)pFormat; +#endif +} + +#endif // _MEDIATOR_HXX --- a/main/extensions/source/plugin/inc/plugin/unx/plugcon.hxx +++ a/main/extensions/source/plugin/inc/plugin/unx/plugcon.hxx @@ -0,0 +1,247 @@ +/************************************************************** + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + *************************************************************/ + + +#ifndef _PLUGCON_HXX +#define _PLUGCON_HXX + +#include +#include + +#include +#include +#include + +#if defined SOLARIS +#define USE_MOTIF +#endif + +#define Window XLIB_Window +#define Font XLIB_Font +#define KeyCode XLIB_KeyCode +#define Time XLIB_Time +#define Cursor XLIB_Cursor +#define Region XLIB_Region +#define String XLIB_String +#define Boolean XLIB_Boolean +#define XPointer XLIB_XPointer +#include +extern "C" { +#include +} +#include +#include /* Intrinsics Definitions*/ +#include /* Standard Name-String definitions*/ +#if defined USE_MOTIF +#include +#else +# if defined DISABLE_XAW +# include +# else +# include +# endif +#endif +#include +#ifndef XP_UNIX +# define XP_UNIX +#endif +#define MOZ_X11 +#include +#ifdef SYSTEM_MOZILLA +#ifndef OJI +# define OJI +#endif +#define MOZ_X11 +#endif + +//http://qa.openoffice.org/issues/show_bug.cgi?id=82545 +//https://bugzilla.mozilla.org/show_bug.cgi?id=241262 +#ifdef UNIX +# ifndef _UINT32 +# if defined(__alpha) || defined(__LP64__) + typedef unsigned int uint32; +# else /* __alpha */ + typedef unsigned long uint32; +# endif +# define _UINT32 +# endif +# ifndef _INT32 +# if defined(__alpha) || defined(__LP64__) + typedef int int32; +# else /* __alpha */ + typedef long int32; +# endif +# define _INT32 +# endif +#endif + +#ifndef _NPAPI_H_ +extern "C" { +#include +} +#include + +#if NP_VERSION_MINOR < 17 +// compatibility hack: compile with older NPN api header, but define +// some later introduced constants +// for gcc 3 +#define NP_ABI_MASK 0x10000000 +#define NPNVSupportsXEmbedBool ((NPNVariable)14) +#define NPPVpluginNeedsXEmbed ((NPPVariable)14) +#define NPNVToolkit ((int)(13 | NP_ABI_MASK)) +#define NPNVGtk12 1 +#define NPNVGtk2 2 +#endif +#endif + +#ifdef ENABLE_GTK +#include +#include +#else +#define GtkWidget void +#endif + +#undef Window +#undef Font +#undef KeyCode +#undef Time +#undef Cursor +#undef String +#undef Region +#undef Boolean +#undef XPointer + +class ConnectorInstance +{ +public: + NPP instance; + NPWindow window; + NPSetWindowCallbackStruct ws_info; + char* pMimeType; + void* pShell; + void* pWidget; + void* pForm; + + GtkWidget* pGtkWindow; + GtkWidget* pGtkWidget; + + bool bShouldUseXEmbed; + + int nArg; + char** argn; + char** argv; + char* pArgnBuf; + char* pArgvBuf; + NPSavedData aData; + + ConnectorInstance( NPP inst, char* type, + int args, char* pargnbuf, sal_uLong nargnbytes, + char* pargvbuf, sal_uLong nargvbytes, + char* savedata, sal_uLong savebytes ); + ~ConnectorInstance(); +}; + +class PluginConnector : public Mediator +{ +protected: + vos::OMutex m_aUserEventMutex; + + static std::vector allConnectors; + + DECL_LINK( NewMessageHdl, Mediator* ); + DECL_LINK( WorkOnNewMessageHdl, Mediator* ); + + std::vector m_aNPWrapStreams; + std::vector m_aInstances; + + sal_uLong FillBuffer( char*&, const char*, sal_uLong, va_list ); +public: + PluginConnector( int nSocket ); + ~PluginConnector(); + + virtual MediatorMessage* WaitForAnswer( sal_uLong nMessageID ); + MediatorMessage* Transact( const char*, sal_uLong, ... ); + MediatorMessage* Transact( sal_uInt32, ... ); + void Respond( sal_uLong nID, char*, sal_uLong, ... ); + sal_uLong Send( sal_uInt32, ... ); + + static const sal_uInt32 UnknownStreamID = 0xffffffff; + static const sal_uInt32 UnknownNPPID = 0xffffffff; + + sal_uInt32 GetStreamID( NPStream* pStream ); + sal_uInt32 GetNPPID( NPP ); + + std::vector& getStreamList() { return m_aNPWrapStreams; } + + NPError GetNPError( MediatorMessage* pMes ) + { + NPError* pErr = (NPError*)pMes->GetBytes(); + NPError aErr = *pErr; + delete [] pErr; + return aErr; + } + + void CallWorkHandler() + { + LINK( this, PluginConnector, WorkOnNewMessageHdl ). + Call( (Mediator*)this ); + } + + ConnectorInstance* getInstance( NPP ); + ConnectorInstance* getInstanceById( sal_uInt32 ); +}; + +enum CommandAtoms +{ + eNPN_GetURL, + eNPN_GetURLNotify, + eNPN_DestroyStream, + eNPN_NewStream, + eNPN_PostURLNotify, + eNPN_PostURL, + eNPN_RequestRead, + eNPN_Status, + eNPN_Version, + eNPN_Write, + eNPN_UserAgent, + + eNPP_DestroyStream, + eNPP_Destroy, + eNPP_DestroyPhase2, + eNPP_NewStream, + eNPP_New, + eNPP_SetWindow, + eNPP_StreamAsFile, + eNPP_URLNotify, + eNPP_WriteReady, + eNPP_Write, + eNPP_GetMIMEDescription, + eNPP_Initialize, + eNPP_Shutdown, + + eMaxCommand +}; + +const char* GetCommandName( CommandAtoms ); + +#define POST_STRING( x ) x ? x : const_cast(""), x ? strlen(x) : 1 + +#endif // _PLUGCON_HXX --- a/main/extensions/source/plugin/inc/plugin/unx/sysplug.hxx +++ a/main/extensions/source/plugin/inc/plugin/unx/sysplug.hxx @@ -0,0 +1,79 @@ +/************************************************************** + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + *************************************************************/ + + +#ifndef __PLUGIN_INC_UNXPLUG_HXX +#define __PLUGIN_INC_UNXPLUG_HXX + +#include + +#include +#include +#include + +class UnxPluginComm : public PluginComm, public PluginConnector +{ +private: + static int nConnCounter; + + pid_t m_nCommPID; +public: + UnxPluginComm( const String& mimetype, + const String& library, + XLIB_Window aParent, + int nDescriptor1, + int nDescriptor2 + ); + virtual ~UnxPluginComm(); + + using PluginComm::NPP_Destroy; + virtual NPError NPP_Destroy( NPP instance, NPSavedData** save ); + virtual NPError NPP_DestroyStream( NPP instance, NPStream* stream, + NPError reason ); + virtual void* NPP_GetJavaClass(); + virtual NPError NPP_Initialize(); + virtual NPError NPP_New( NPMIMEType pluginType, NPP instance, + uint16 mode, int16 argc, + char* argn[], char* argv[], NPSavedData *saved ); + virtual NPError NPP_NewStream( NPP instance, NPMIMEType type, + NPStream* stream, + NPBool seekable, uint16* stype ); + virtual void NPP_Print( NPP instance, NPPrint* platformPrint ); + + using PluginComm::NPP_SetWindow; + virtual NPError NPP_SetWindow( NPP instance, NPWindow* window ); + virtual void NPP_Shutdown(); + virtual void NPP_StreamAsFile( NPP instance, NPStream* stream, + const char* fname ); + virtual void NPP_URLNotify( NPP instance, const char* url, NPReason reason, + void* notifyData ); + virtual int32 NPP_Write( NPP instance, NPStream* stream, int32 offset, + int32 len, void* buffer ); + virtual int32 NPP_WriteReady( NPP instance, NPStream* stream ); + virtual char* NPP_GetMIMEDescription(); + virtual NPError NPP_GetValue( NPP instance, NPPVariable variable, void* value ); + virtual NPError NPP_SetValue( NPP instance, NPNVariable variable, + void *value); + + static bool getPluginappPath(rtl::OString * path); +}; + +#endif --- a/main/extensions/source/plugin/inc/plugin/win/sysplug.hxx +++ a/main/extensions/source/plugin/inc/plugin/win/sysplug.hxx @@ -0,0 +1,121 @@ +/************************************************************** + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + *************************************************************/ + + + +#ifndef __PLUGIN_INC_WINPLUG_HXX +#define __PLUGIN_INC_WINPLUG_HXX + +#pragma warning (push,1) +#pragma warning (disable:4005) + +#include + +#include +#include +#include + +#include + +#pragma pack( push, 8 ) +#include +#include +#pragma pack( pop ) + +#pragma warning (pop) + +#include +#include +#include + +#include +#include + +//================================================================================================== +class PluginComm_Impl : + public PluginComm, + public ::vcl::SolarThreadExecutor + +{ + enum CallType { + eNPP_Destroy, + eNPP_DestroyStream, + eNPP_GetJavaClass, + eNPP_Initialize, + eNPP_New, + eNPP_NewStream, + eNPP_Print, + eNPP_SetWindow, + eNPP_Shutdown, + eNPP_StreamAsFile, + eNPP_URLNotify, + eNPP_Write, + eNPP_WriteReady, + eNPP_GetValue, + eNPP_SetValue, + eNP_Initialize + }; + + void* m_aArgs[ 8 ]; + CallType m_eCall; + + virtual long doIt(); +public: + PluginComm_Impl( const rtl::OUString& rMIME, const rtl::OUString& rName, HWND hWnd ); + virtual ~PluginComm_Impl(); + +public: + using PluginComm::NPP_Destroy; + virtual NPError NPP_Destroy( NPP instance, NPSavedData** save ); + virtual NPError NPP_DestroyStream( NPP instance, NPStream* stream, NPError reason ); + virtual void * NPP_GetJavaClass(); + virtual NPError NPP_Initialize(); + virtual NPError NPP_New( NPMIMEType pluginType, NPP instance, uint16 mode, int16 argc, + char* argn[], char* argv[], NPSavedData *saved ); + virtual NPError NPP_NewStream( NPP instance, NPMIMEType type, NPStream* stream, + NPBool seekable, uint16* stype ); + virtual void NPP_Print( NPP instance, NPPrint* platformPrint ); + + using PluginComm::NPP_SetWindow; + virtual NPError NPP_SetWindow( NPP instance, NPWindow* window ); + virtual void NPP_Shutdown(); + virtual void NPP_StreamAsFile( NPP instance, NPStream* stream, const char* fname ); + virtual void NPP_URLNotify( NPP instance, const char* url, + NPReason reason, void* notifyData ); + virtual int32 NPP_Write( NPP instance, NPStream* stream, int32 offset, + int32 len, void* buffer ); + virtual int32 NPP_WriteReady( NPP instance, NPStream* stream ); + virtual NPError NPP_GetValue( NPP instance, NPPVariable variable, void *ret_alue ); + virtual NPError NPP_SetValue( NPP instance, NPNVariable variable, void *ret_alue ); + +private: + BOOL retrieveFunction( TCHAR* pName, void** ppFunc ) const; + +private: + HINSTANCE _plDLL; + + NPPluginFuncs _NPPfuncs; +}; + + +#endif + + --- a/main/extensions/source/plugin/unx/makefile.mk +++ a/main/extensions/source/plugin/unx/makefile.mk @@ -0,0 +1,106 @@ +#************************************************************** +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# +#************************************************************** + + +PRJ=..$/..$/.. + +PRJNAME=extensions +TARGET=plunx +TARGETTYPE=CUI +ENABLE_EXCEPTIONS=TRUE + +.INCLUDE : ..$/util$/makefile.pmk + +.IF "$(GUIBASE)"=="aqua" +dummy: + @echo "Nothing to build for GUIBASE aqua." + +.ELSE + +# --- Files -------------------------------------------------------- + +INCPRE+=-I$(SOLARINCDIR)$/mozilla$/plugin +.IF "$(SOLAR_JAVA)" != "" +INCPRE+=-I$(SOLARINCDIR)$/mozilla$/java +INCPRE+=-I$(SOLARINCDIR)$/mozilla$/nspr +CDEFS+=-DOJI +.ENDIF + +.IF "$(WITH_MOZILLA)" != "NO" + +.IF "$(DISABLE_XAW)" == "TRUE" +CDEFS+=-DDISABLE_XAW +.ENDIF + +SLOFILES=\ + $(SLO)$/nppapi.obj \ + $(SLO)$/sysplug.obj \ + $(SLO)$/mediator.obj \ + $(SLO)$/plugcon.obj \ + $(SLO)$/unxmgr.obj + +OBJFILES=\ + $(OBJ)$/npwrap.obj \ + $(OBJ)$/npnapi.obj \ + $(OBJ)$/mediator.obj \ + $(OBJ)$/plugcon.obj + +APP1TARGET=pluginapp.bin +APP1OBJS=$(OBJFILES) +APP1STDLIBS=\ + $(VOSLIB) \ + $(SALLIB) +.IF "$(OS)"=="SOLARIS" || "$(OS)"=="SCO" || "$(OS)"=="HPUX" +APP1STDLIBS+=-lXm -lXt $(X11LINK_DYNAMIC) -ldl +.ELSE +.IF "$(DISABLE_XAW)" != "TRUE" +APP1STDLIBS+=-lXaw +.ENDIF +.IF "$(OS)"=="FREEBSD" || "$(OS)"=="NETBSD" +APP1STDLIBS+= -lXt -lXext -lX11 +.ELSE +APP1STDLIBS+= -lXt $(X11LINK_DYNAMIC) -ldl +.ENDIF +.ENDIF + +.IF "$(ENABLE_GTK)" == "TRUE" +# libs for gtk plugin +APP1STDLIBS+=$(PKGCONFIG_LIBS:s/ -lpangoxft-1.0//) +# hack for faked SO environment +.IF "$(PKGCONFIG_ROOT)"!="" +.IF "$(OS)" == "SOLARIS" +# don't ask, it's ugly +DIRECT :=-z nodefs $(DIRECT) +.ENDIF +.ENDIF # "$(PKGCONFIG_ROOT)"!="" +.ENDIF + + +APP1DEF= $(MISC)$/$(TARGET).def + +.ENDIF # $(WITH_MOZILLA) != "NO" + +.ENDIF # $(GUIBASE)==aqua + +# --- Targets ------------------------------------------------------ + +.INCLUDE : target.mk + --- a/main/extensions/source/plugin/unx/mediator.cxx +++ a/main/extensions/source/plugin/unx/mediator.cxx @@ -0,0 +1,305 @@ +/************************************************************** + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + *************************************************************/ + + + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_extensions.hxx" +#include +#include + +#include +#include + +#define MEDIATOR_MAGIC 0xf7a8d2f4 + +Mediator::Mediator( int nSocket ) : + m_nSocket( nSocket ), + m_pListener( NULL ), + m_nCurrentID( 1 ), + m_bValid( true ) +{ + m_pListener = new MediatorListener( this ); + m_pListener->create(); +} + +Mediator::~Mediator() +{ + if( m_pListener ) + { + { + ::vos::OGuard aGuard( m_pListener->m_aMutex ); + m_pListener->m_pMediator = NULL; + } + m_pListener = NULL; + if( m_bValid ) + { + sal_uLong aHeader[3]; + aHeader[0] = 0; + aHeader[1] = 0; + aHeader[2] = MEDIATOR_MAGIC; + write( m_nSocket, aHeader, sizeof( aHeader ) ); + } + // kick the thread out of its run method; it deletes itself + close( m_nSocket ); + } + else + close( m_nSocket ); + for( std::vector< MediatorMessage* >::iterator it = m_aMessageQueue.begin(); + it != m_aMessageQueue.end(); ++it ) + { + delete *it; + } +} + + +sal_uLong Mediator::SendMessage( sal_uLong nBytes, const char* pBytes, sal_uLong nMessageID ) +{ + if( ! m_pListener ) + return 0; + + vos::OGuard aGuard( m_aSendMutex ); + if( ! nMessageID ) + nMessageID = m_nCurrentID; + + m_nCurrentID++; + if( m_nCurrentID >= 1 << 24 ) // protection against overflow + m_nCurrentID = 1; + + if( ! m_bValid ) + return nMessageID; + + sal_uLong* pBuffer = new sal_uLong[ (nBytes/sizeof(sal_uLong)) + 4 ]; + pBuffer[ 0 ] = nMessageID; + pBuffer[ 1 ] = nBytes; + pBuffer[ 2 ] = MEDIATOR_MAGIC; + memcpy( &pBuffer[3], pBytes, (size_t)nBytes ); + write( m_nSocket, pBuffer, nBytes + 3*sizeof( sal_uLong ) ); + delete [] pBuffer; + + return nMessageID; +} + +sal_Bool Mediator::WaitForMessage( sal_uLong nTimeOut ) +{ + if( ! m_pListener ) + return sal_False; + + size_t nItems = m_aMessageQueue.size(); + + if( ! nTimeOut && nItems > 0 ) + return sal_True; + + TimeValue aValue; + aValue.Seconds = nTimeOut/1000; + aValue.Nanosec = ( nTimeOut % 1000 ) * 1000; + + while( m_aMessageQueue.size() == nItems ) + { + m_aNewMessageCdtn.wait( & aValue ); + m_aNewMessageCdtn.reset(); + if( nTimeOut && m_aMessageQueue.size() == nItems ) + return sal_False; + } + return sal_True; +} + +MediatorMessage* Mediator::WaitForAnswer( sal_uLong nMessageID ) +{ + nMessageID &= 0x00ffffff; + while( m_pListener ) + { + { + vos::OGuard aGuard( m_aQueueMutex ); + for( size_t i = 0; i < m_aMessageQueue.size(); i++ ) + { + MediatorMessage* pMessage = m_aMessageQueue[ i ]; + sal_uLong nID = pMessage->m_nID; + if( ( nID & 0xff000000 ) && + ( ( nID & 0x00ffffff ) == nMessageID ) ) + { + m_aMessageQueue.erase( m_aMessageQueue.begin() + i ); + return pMessage; + } + } + } + WaitForMessage( 10 ); + } + return NULL; +} + +MediatorMessage* Mediator::GetNextMessage( sal_Bool bWait ) +{ + while( m_pListener ) + { + { + // guard must be after WaitForMessage, else the listener + // cannot insert a new one -> deadlock + vos::OGuard aGuard( m_aQueueMutex ); + for( size_t i = 0; i < m_aMessageQueue.size(); i++ ) + { + MediatorMessage* pMessage = m_aMessageQueue[ i ]; + if( ! ( pMessage->m_nID & 0xff000000 ) ) + { + m_aMessageQueue.erase( m_aMessageQueue.begin() + i ); + return pMessage; + } + } + if( ! bWait ) + return NULL; + } + WaitForMessage(); + } + return NULL; +} + +MediatorMessage* Mediator::TransactMessage( sal_uLong nBytes, char* pBytes ) +{ + sal_uLong nID = SendMessage( nBytes, pBytes ); + return WaitForAnswer( nID ); +} + +MediatorListener::MediatorListener( Mediator* pMediator ) : + m_pMediator( pMediator ) +{ +} + +MediatorListener::~MediatorListener() +{ +} + +void MediatorListener::run() +{ + bool bRun = true; + while( schedule() && m_pMediator && bRun ) + { + sal_uLong nHeader[ 3 ]; + int nBytes; + + if( m_pMediator && ( nBytes = read( m_pMediator->m_nSocket, nHeader, sizeof( nHeader ) ) ) == sizeof( nHeader ) && nHeader[2] == MEDIATOR_MAGIC) + { + if( nHeader[ 0 ] == 0 && nHeader[ 1 ] == 0 ) + return; + char* pBuffer = new char[ nHeader[ 1 ] ]; + if( m_pMediator && (sal_uLong)read( m_pMediator->m_nSocket, pBuffer, nHeader[ 1 ] ) == nHeader[ 1 ] ) + { + ::vos::OGuard aMyGuard( m_aMutex ); + { + vos::OGuard + aGuard( m_pMediator->m_aQueueMutex ); + MediatorMessage* pMessage = + new MediatorMessage( nHeader[ 0 ], nHeader[ 1 ], pBuffer ); + m_pMediator->m_aMessageQueue.push_back( pMessage ); + } + m_pMediator->m_aNewMessageCdtn.set(); + m_pMediator->m_aNewMessageHdl.Call( m_pMediator ); + } + else + { + medDebug( 1, "got incomplete MediatorMessage: { %d, %d, %*s }\n", + nHeader[0], nHeader[1], nHeader[1], pBuffer ); + bRun = false; + } + delete [] pBuffer; + } + else + { + medDebug( 1, "got incomplete message header of %d bytes ( nHeader = [ %u, %u ] ), errno is %d\n", + nBytes, nHeader[ 0 ], nHeader[ 1 ], (int)errno ); + bRun = false; + } + } +} + +void MediatorListener::onTerminated() +{ + if( m_pMediator ) + { + m_pMediator->m_aConnectionLostHdl.Call( m_pMediator ); + m_pMediator->m_pListener = NULL; + } + delete this; +} + +sal_uLong MediatorMessage::ExtractULONG() +{ + if( ! m_pRun ) + m_pRun = m_pBytes; + + medDebug( (sal_uLong)(m_pRun - m_pBytes) >= m_nBytes, "Overflow in MediatorMessage::ExtractULONG\n" ); + sal_uLong nCount; + memcpy( &nCount, m_pRun, sizeof( sal_uLong ) ); + m_pRun += sizeof( sal_uLong ); + return nCount; +} + +void* MediatorMessage::GetBytes( sal_uLong& rBytes ) +{ + if( ! m_pRun ) + m_pRun = m_pBytes; + + medDebug( (sal_uLong)(m_pRun - m_pBytes) >= m_nBytes, "Overflow in MediatorMessage::GetBytes\n" ); + sal_uLong nBytes = ExtractULONG(); + + if( nBytes == 0 ) + return NULL; + + medDebug( (sal_uLong)(m_pRun - m_pBytes) >= m_nBytes, "Overflow in MediatorMessage::GetBytes\n" ); + char* pBuffer = new char[ nBytes ]; + memcpy( pBuffer, m_pRun, nBytes ); + m_pRun += nBytes; + rBytes = nBytes; + return pBuffer; +} + +char* MediatorMessage::GetString() +{ + if( ! m_pRun ) + m_pRun = m_pBytes; + + medDebug( (sal_uLong)(m_pRun - m_pBytes) >= m_nBytes, "Overflow in MediatorMessage::GetString\n" ); + sal_uLong nBytes = ExtractULONG(); + + if( nBytes == 0 ) + return NULL; + + medDebug( (sal_uLong)(m_pRun - m_pBytes) >= m_nBytes, "Overflow in MediatorMessage::GetString\n" ); + char* pBuffer = new char[ nBytes+1 ]; + memcpy( pBuffer, m_pRun, nBytes ); + pBuffer[ nBytes ] = 0; + m_pRun += nBytes; + return pBuffer; +} + +sal_uInt32 MediatorMessage::GetUINT32() +{ + if( ! m_pRun ) + m_pRun = m_pBytes; + + medDebug( (sal_uLong)(m_pRun - m_pBytes) >= m_nBytes, "Overflow in MediatorMessage::GetUINT32\n" ); + sal_uLong nBytes = ExtractULONG(); + medDebug( nBytes != sizeof( sal_uInt32 ), "No sal_uInt32 in MediatorMessage::GetUINT32\n" ); + medDebug( (sal_uLong)(m_pRun - m_pBytes) >= m_nBytes, "Overflow in MediatorMessage::GetUINT32\n" ); + sal_uInt32 nRet; + memcpy( &nRet, m_pRun, sizeof( nRet ) ); + m_pRun += sizeof( sal_uInt32 ); + return nRet; +} --- a/main/extensions/source/plugin/unx/npnapi.cxx +++ a/main/extensions/source/plugin/unx/npnapi.cxx @@ -0,0 +1,913 @@ +/************************************************************** + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + *************************************************************/ + + + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_extensions.hxx" +#include + +#include +#include + +#include + +extern PluginConnector* pConnector; +extern XtAppContext app_context; +extern int wakeup_fd[]; +extern Widget topLevel, topBox; +extern Display* pAppDisplay; +extern Display* pXtAppDisplay; +extern int nAppArguments; +extern char** pAppArguments; + +void* CreateNewShell( void**, XLIB_Window ); + +// begin Netscape plugin api calls +extern "C" { + +static void* l_NPN_MemAlloc( uint32 nBytes ) +{ + void* pMem = new char[nBytes]; + return pMem; +} + +static void l_NPN_MemFree( void* pMem ) +{ + delete [] (char*)pMem; +} + +static uint32 l_NPN_MemFlush( uint32 /*nSize*/ ) +{ + return 0; +} + +static NPError l_NPN_DestroyStream( NPP instance, NPStream* stream, NPError reason ) +{ + sal_uInt32 nInstance = pConnector->GetNPPID( instance ); + if( nInstance == PluginConnector::UnknownNPPID ) + return NPERR_GENERIC_ERROR; + + sal_uInt32 nFileID = pConnector->GetStreamID( stream ); + MediatorMessage* pMes= + pConnector-> + Transact( eNPN_DestroyStream, + &nInstance, sizeof( nInstance ), + &nFileID, sizeof( nFileID ), + POST_STRING( stream->url ), + &reason, sizeof( reason ), + NULL ); + + if( ! pMes ) + return NPERR_GENERIC_ERROR; + + for( std::vector< NPStream* >::iterator it = pConnector->getStreamList().begin(); + it != pConnector->getStreamList().end(); ++it ) + { + if( *it == stream ) + { + pConnector->getStreamList().erase( it ); + break; + } + } + delete [] stream->url; + delete stream; + // returns NPError + NPError aRet = pConnector->GetNPError( pMes ); + delete pMes; + return aRet; +} + +#ifdef OJI +static JRIEnv* l_NPN_GetJavaEnv() +{ + // no java in this program + medDebug( 1, "SNI: NPN_GetJavaEnv\n" ); + return NULL; +} + +static jref l_NPN_GetJavaPeer( NPP /*instance*/ ) +{ + medDebug( 1, "SNI: NPN_GetJavaPeer\n" ); + return NULL; +} +#endif + +static NPError l_NPN_GetURL( NPP instance, const char* url, const char* window ) +{ + sal_uInt32 nInstance = pConnector->GetNPPID( instance ); + if( nInstance == PluginConnector::UnknownNPPID ) + return NPERR_GENERIC_ERROR; + + MediatorMessage* pMes= + pConnector-> + Transact( eNPN_GetURL, + &nInstance, sizeof( nInstance ), + POST_STRING(url), + POST_STRING(window), + NULL ); + medDebug( !pMes, "geturl: message unaswered\n" ); + if( ! pMes ) + return NPERR_GENERIC_ERROR; + + // returns NPError + NPError aRet = pConnector->GetNPError( pMes ); + medDebug( aRet, "geturl returns %d\n", (int)aRet ); + delete pMes; + return aRet; +} + +static NPError l_NPN_GetURLNotify( NPP instance, const char* url, const char* target, + void* notifyData ) +{ + sal_uInt32 nInstance = pConnector->GetNPPID( instance ); + if( nInstance == PluginConnector::UnknownNPPID ) + return NPERR_GENERIC_ERROR; + + MediatorMessage* pMes= + pConnector-> + Transact( eNPN_GetURLNotify, + &nInstance, sizeof( nInstance ), + POST_STRING(url), + POST_STRING(target), + ¬ifyData, sizeof( void* ), // transmit the actual pointer + // since it is a pointer to private data fed back + // by NPP_URLNotify; this can be thought of as an ID + NULL ); + if( ! pMes ) + return NPERR_GENERIC_ERROR; + + // returns NPError + NPError aRet = pConnector->GetNPError( pMes ); + delete pMes; + return aRet; +} + +static NPError l_NPN_NewStream( NPP instance, NPMIMEType type, const char* target, + NPStream** stream ) + // stream is a return value +{ + sal_uInt32 nInstance = pConnector->GetNPPID( instance ); + if( nInstance == PluginConnector::UnknownNPPID ) + return NPERR_GENERIC_ERROR; + + MediatorMessage* pMes= + pConnector-> + Transact( eNPN_NewStream, + &nInstance, sizeof( nInstance ), + POST_STRING(type), + POST_STRING(target), + NULL ); + if( ! pMes ) + return NPERR_GENERIC_ERROR; + + // returns a new NPStream and an error + NPError aRet = pConnector->GetNPError( pMes ); + if( ! aRet ) + { + NPStream* pStream = new NPStream; + pStream->url = pMes->GetString(); + pStream->end = pMes->GetUINT32(); + pStream->lastmodified = pMes->GetUINT32(); + pStream->ndata = pStream->pdata = pStream->notifyData = NULL; + + pConnector->getStreamList().push_back( pStream ); + *stream = pStream; + } + + delete pMes; + return aRet; +} + +static NPError l_NPN_PostURLNotify( NPP instance, const char* url, const char* target, uint32 len, const char* buf, NPBool file, void* notifyData ) +{ + sal_uInt32 nInstance = pConnector->GetNPPID( instance ); + if( nInstance == PluginConnector::UnknownNPPID ) + return NPERR_GENERIC_ERROR; + + MediatorMessage* pMes = pConnector-> + Transact( eNPN_PostURLNotify, + &nInstance, sizeof( nInstance ), + POST_STRING( url ), + POST_STRING( target ), + &len, sizeof( len ), + buf, len, + &file, sizeof( NPBool ), + ¬ifyData, sizeof( void* ), // send the real pointer + NULL ); + + if( ! pMes ) + return NPERR_GENERIC_ERROR; + + NPError aRet = pConnector->GetNPError( pMes ); + delete pMes; + return aRet; +} + +static NPError l_NPN_PostURL( NPP instance, const char* url, const char* window, uint32 len, const char* buf, NPBool file ) +{ + sal_uInt32 nInstance = pConnector->GetNPPID( instance ); + if( nInstance == PluginConnector::UnknownNPPID ) + return NPERR_GENERIC_ERROR; + + MediatorMessage* pMes = pConnector-> + Transact( eNPN_PostURL, + &nInstance, sizeof( nInstance ), + POST_STRING( url ), + POST_STRING( window ), + &len, sizeof( len ), + buf, len, + &file, sizeof( NPBool ), + NULL ); + if( ! pMes ) + return NPERR_GENERIC_ERROR; + + NPError aRet = pConnector->GetNPError( pMes ); + delete pMes; + return aRet; +} + +static NPError l_NPN_RequestRead( NPStream* stream, NPByteRange* rangeList ) +{ + medDebug( 1, "pluginapp: NPN_RequestRead\n" ); + + NPByteRange* pRange = rangeList; + sal_uInt32 nRanges = 0; + while( pRange ) + { + nRanges++; + pRange = pRange->next; + } + + sal_uInt32* pArray = new sal_uInt32[ 2 * nRanges ]; + pRange = rangeList; + sal_uInt32 n = 0; + while( pRange ) + { + pArray[ 2*n ] = (sal_uInt32)pRange->offset; + pArray[ 2*n + 1] = (sal_uInt32)pRange->length; + n++; + pRange = pRange->next; + } + sal_uInt32 nFileID = pConnector->GetStreamID( stream ); + MediatorMessage* pMes = pConnector-> + Transact( eNPN_RequestRead, + &nFileID, sizeof( nFileID ), + &nRanges, sizeof( nRanges ), + pArray, sizeof( sal_uInt32 ) * 2 * nRanges, + NULL ); + + if( ! pMes ) + return NPERR_GENERIC_ERROR; + + NPError aRet = pConnector->GetNPError( pMes ); + delete [] pArray; + delete pMes; + return aRet; +} + +static void l_NPN_Status( NPP instance, const char* message ) +{ + sal_uInt32 nInstance = pConnector->GetNPPID( instance ); + if( nInstance == PluginConnector::UnknownNPPID ) + return; + + pConnector->Send( eNPN_Status, + &nInstance, sizeof( nInstance ), + POST_STRING( message ), + NULL ); +} + +static const char* l_NPN_UserAgent( NPP instance ) +{ + static char* pAgent = NULL; + + sal_uInt32 nInstance = pConnector->GetNPPID( instance ); + if( nInstance == PluginConnector::UnknownNPPID ) + { + if( instance ) + return "Mozilla 3.0"; + else // e.g. flashplayer calls NPN_UserAgent with NULL + nInstance = 0; + } + + MediatorMessage* pMes = pConnector-> + Transact( eNPN_UserAgent, + &nInstance, sizeof( nInstance ), + NULL ); + + if( ! pMes ) + return pAgent; + + if( pAgent ) + delete [] pAgent; + pAgent = pMes->GetString(); + + delete pMes; + + medDebug( 1, "NPN_UserAgent returns %s\n", pAgent ); + + return pAgent; +} + +#if 0 +static void l_NPN_Version( int* major, int* minor, int* net_major, int* net_minor ) +{ + MediatorMessage* pMes = pConnector-> + Transact( eNPN_Version, + NULL ); + + if( ! pMes ) + return; + + *major = pMes->GetUINT32(); + *minor = pMes->GetUINT32(); + *net_major = pMes->GetUINT32(); + *net_minor = pMes->GetUINT32(); + + medDebug( 1, "pluginapp: NPN_Version: results %d %d, %d %d\n", *major, *minor, *net_major, *net_minor ); + + delete pMes; +} +#endif + +static int32 l_NPN_Write( NPP instance, NPStream* stream, int32 len, void* buffer ) +{ + sal_uInt32 nFileID = pConnector->GetStreamID( stream ); + if( nFileID == PluginConnector::UnknownStreamID ) + return NPERR_GENERIC_ERROR; + sal_uInt32 nInstance = pConnector->GetNPPID( instance ); + if( nInstance == PluginConnector::UnknownNPPID ) + return NPERR_GENERIC_ERROR; + + MediatorMessage* pMes = pConnector-> + Transact( eNPN_Write, + &nInstance, sizeof( nInstance ), + &nFileID, sizeof( nFileID ), + &len, sizeof( len ), + buffer, len, + NULL ); + + if( ! pMes ) + return 0; + + sal_Int32 nRet = pMes->GetUINT32(); + return nRet; +} + +static void l_NPN_ReloadPlugins( NPBool /*reloadPages*/ ) +{ + medDebug( 1, "NPN_ReloadPlugins: SNI\n" ); +} + +static NPError l_NPN_GetValue( NPP, NPNVariable variable, void* value ) +{ + /* + * We want to handle values injected into a NPNVariable which aren't in + * the old enum we build against, but that we know are in the new enum + * we want to support + */ + switch( (int)variable ) + { + case NPNVxDisplay: + *((Display**)value) = pXtAppDisplay; + medDebug( 1, "Display requested\n" ); + break; + case NPNVxtAppContext: + *((XtAppContext*)value) = app_context; + medDebug( 1, "AppContext requested\n" ); + break; + case NPNVjavascriptEnabledBool: + // no javascript + *(NPBool*)value = false; + medDebug( 1, "javascript enabled requested\n" ); + break; + case NPNVasdEnabledBool: + // no SmartUpdate + *(NPBool*)value = false; + medDebug( 1, "smart update enabled requested\n" ); + break; + case NPNVisOfflineBool: + // no offline browsing + *(NPBool*)value = false; + medDebug( 1, "offline browsing requested\n" ); + break; + case NPNVSupportsXEmbedBool: + // asking xembed + *(int*)value = true; + medDebug( 1, "xembed requested\n" ); + break; + case NPNVToolkit: +# ifdef ENABLE_GTK + *(int*)value = NPNVGtk2; +# else + *(int*)value = 0; +# endif + medDebug( 1, "toolkit requested\n" ); + break; + default: + medDebug( 1, "unknown NPNVariable %x requested\n", variable ); + return NPERR_INVALID_PARAM; + } + return NPERR_NO_ERROR; +} + +static NPError l_NPN_SetValue(NPP /*instance*/, NPPVariable variable, void *value) +{ + medDebug( 1, "NPN_SetValue %d=%p\n", variable, value ); + return 0; +} + +static void l_NPN_InvalidateRect(NPP /*instance*/, NPRect* /*invalidRect*/) +{ + medDebug( 1, "NPN_InvalidateRect\n" ); +} + +static void l_NPN_InvalidateRegion(NPP /*instance*/, NPRegion /*invalidRegion*/) +{ + medDebug( 1, "NPN_InvalidateRegion\n" ); +} + +static void l_NPN_ForceRedraw(NPP /*instance*/) +{ + medDebug( 1, "NPN_ForceRedraw\n" ); +} + +} + +static NPNetscapeFuncs aNetscapeFuncs = +{ + sizeof(aNetscapeFuncs), + (NP_VERSION_MAJOR << 8) | NP_VERSION_MINOR, + l_NPN_GetURL, + l_NPN_PostURL, + l_NPN_RequestRead, + l_NPN_NewStream, + l_NPN_Write, + l_NPN_DestroyStream, + l_NPN_Status, + l_NPN_UserAgent, + l_NPN_MemAlloc, + l_NPN_MemFree, + l_NPN_MemFlush, + l_NPN_ReloadPlugins, +# ifdef OJI + l_NPN_GetJavaEnv, + l_NPN_GetJavaPeer, +# else + NULL, + NULL, +# endif + l_NPN_GetURLNotify, + l_NPN_PostURLNotify, + l_NPN_GetValue, + l_NPN_SetValue, + l_NPN_InvalidateRect, + l_NPN_InvalidateRegion, + l_NPN_ForceRedraw +}; + +static NPPluginFuncs aPluginFuncs = +{ + sizeof(aPluginFuncs), + (NP_VERSION_MAJOR << 8) | NP_VERSION_MINOR, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL +}; + + +oslModule pPluginLib = NULL; +char*(*pNPP_GetMIMEDescription)() = NULL; +NPError (*pNP_Initialize)(NPNetscapeFuncs*,NPPluginFuncs*) = NULL; +NPError (*pNP_Shutdown)() = NULL; + +std::vector< PluginConnector* > PluginConnector::allConnectors; + +PluginConnector::PluginConnector( int nSocket ) : + Mediator( nSocket ) +{ + SetNewMessageHdl( LINK( this, PluginConnector, NewMessageHdl ) ); +} + +PluginConnector::~PluginConnector() +{ +} + +IMPL_LINK( PluginConnector, WorkOnNewMessageHdl, Mediator*, /*pMediator*/ ) +{ + MediatorMessage* pMessage; + CommandAtoms nCommand; + while( (pMessage = GetNextMessage( sal_False )) ) + { + nCommand = (CommandAtoms)pMessage->GetUINT32(); + medDebug( 1, "pluginapp: %s\n", GetCommandName( nCommand ) ); + switch( nCommand ) + { + case eNPP_DestroyStream: + { + sal_uInt32 nInstance = pMessage->GetUINT32(); + NPP instance = m_aInstances[ nInstance ]->instance; + sal_uInt32 nFileID = pMessage->GetUINT32(); + NPStream* pStream = m_aNPWrapStreams[ nFileID ]; + NPError aReason = GetNPError( pMessage ); + m_aNPWrapStreams.erase( m_aNPWrapStreams.begin() + nFileID ); + + aReason = aPluginFuncs.destroystream( instance, pStream, aReason ); + Respond( pMessage->m_nID, + (char*)&aReason, sizeof( aReason ), + NULL ); + + delete [] pStream->url; + delete pStream; + } + break; + case eNPP_Destroy: + { + sal_uInt32 nInstance = pMessage->GetUINT32(); + ConnectorInstance* pInst= m_aInstances[ nInstance ]; + + // some plugin rely on old netscapes behaviour + // to first destroy the widget and then destroy + // the instance, so mimic that behaviour here + if( pInst->pShell ) + XtDestroyWidget( (Widget)pInst->pShell ); + + pInst->pWidget = pInst->pShell = NULL; + + // the other side will call eNPP_DestroyPhase2 after this + NPError aReason = NPERR_NO_ERROR; + Respond( pMessage->m_nID, (char*)&aReason, sizeof( aReason ), NULL ); + } + break; + case eNPP_DestroyPhase2: + { + // now really destroy the instance + sal_uInt32 nInstance = pMessage->GetUINT32(); + ConnectorInstance* pInst= m_aInstances[ nInstance ]; + NPP instance = pInst->instance; + NPSavedData* pSave = NULL; + + NPError aRet = aPluginFuncs.destroy( instance, &pSave ); + if( pSave ) + { + Respond( pMessage->m_nID, + (char*)&aRet, sizeof( aRet ), + pSave->buf, pSave->len, + NULL ); + delete [] (char*)pSave->buf; + } + else + Respond( pMessage->m_nID, + (char*)&aRet, sizeof( aRet ), + "0000", 4, + NULL ); + + #ifdef ENABLE_GTK + if( pInst->pGtkWindow ) + g_object_unref( G_OBJECT(pInst->pGtkWindow) ); + if( pInst->pGtkWidget ) + g_object_unref( G_OBJECT(pInst->pGtkWidget) ); + #endif + + m_aInstances.erase( m_aInstances.begin() + nInstance ); + delete pInst; + delete instance; + medDebug( 1, "destroyed instance (returning %d)\n", aRet ); + } + break; + case eNPP_NewStream: + { + sal_uInt32 nInstance = pMessage->GetUINT32(); + NPP instance = m_aInstances[ nInstance ]->instance; + char* pType = pMessage->GetString(); + NPStream* pStream = new NPStream; + pStream->url = pMessage->GetString(); + pStream->end = pMessage->GetUINT32(); + pStream->lastmodified = pMessage->GetUINT32(); + pStream->pdata = pStream->ndata = pStream->notifyData = NULL; + NPBool* pSeekable = (NPBool*)pMessage->GetBytes(); + m_aNPWrapStreams.push_back( pStream ); + uint16 nStype = NP_ASFILE; + NPError aRet = aPluginFuncs.newstream( instance, pType, pStream, + *pSeekable, &nStype ); + medDebug( 1, "pluginapp: NPP_NewStream( %p, %s, %p, %s, %p ) returns %d\n" + "stream = { pdata = %p, ndata = %p, url = %s, end = %d, lastmodified = %d, notifyData = %p }\n", + instance, pType, pStream, *pSeekable ? "seekable" : "not seekable", &nStype, (int)aRet, + pStream->pdata, pStream->ndata, pStream->url, pStream->end, pStream->lastmodified, pStream->notifyData ); + Respond( pMessage->m_nID, + (char*)&aRet, sizeof( aRet ), + &nStype, sizeof( nStype ), + NULL ); + delete [] pType; + delete [] pSeekable; + } + break; + case eNPP_New: + { + char* pType = pMessage->GetString(); + uint16* pMode = (uint16*)pMessage->GetBytes(); + int16* pArgc = (int16*)pMessage->GetBytes(); + NPP instance = new NPP_t; + instance->pdata = instance->ndata = NULL; + sal_uLong nArgnBytes, nArgvBytes; + char* pArgn = (char*)pMessage->GetBytes( nArgnBytes ); + char* pArgv = (char*)pMessage->GetBytes( nArgvBytes ); + sal_uLong nSaveBytes; + char* pSavedData = (char*)pMessage->GetBytes( nSaveBytes ); + ConnectorInstance* pInst = + new ConnectorInstance( instance, pType, + *pArgc, + pArgn, nArgnBytes, + pArgv, nArgvBytes, + pSavedData, nSaveBytes ); + m_aInstances.push_back( pInst ); + NPError aRet; + aRet = aPluginFuncs.newp( pInst->pMimeType, instance, *pMode, *pArgc, + pInst->nArg ? pInst->argn : NULL, + pInst->nArg ? pInst->argv : NULL, + ( nSaveBytes == 4 && *(sal_uInt32*)pSavedData == 0 ) ? + &(pInst->aData) : NULL ); + medDebug( 1, "pluginapp: NPP_New( %s, %p, %d, %d, %p, %p, %p ) returns %d\n", + pInst->pMimeType, + instance, *pMode, pInst->nArg, pInst->argn, pInst->argv, &pInst->aData, + (int) aRet ); +#if OSL_DEBUG_LEVEL > 1 + for( int i = 0; i < pInst->nArg; i++ ) + medDebug( 1, " \"%s\"=\"%s\"\n", pInst->argn[i], pInst->argv[i] ); +#endif + + #ifdef ENABLE_GTK + // check if XEMBED is to be used + // ask for Bool. there seems to be no clear definition whether the + // return value should be an int or unsigned char + // int can hold both and will be nonzero in case of "true" + if( aPluginFuncs.getvalue ) + { + int bNeedsXEmbed = 0; + NPError error = aPluginFuncs.getvalue( instance, NPPVpluginNeedsXEmbed, (void *)&bNeedsXEmbed ); + if( error == NPERR_NO_ERROR ) + pInst->bShouldUseXEmbed = (bNeedsXEmbed != 0); + medDebug( 1, "should use xembed = %s\n", pInst->bShouldUseXEmbed ? "true" : "false" ); + } + #endif + + Respond( pMessage->m_nID, + (char*)&aRet, sizeof( aRet ), + NULL ); + delete [] pMode; + delete [] pArgc; + delete [] pType; + } + break; + case eNPP_SetWindow: + { + sal_uInt32 nInstance = pMessage->GetUINT32(); + ConnectorInstance* pInst= m_aInstances[ nInstance ]; + NPWindow* pWindow = (NPWindow*)pMessage->GetBytes(); + + if( pWindow->width < 1 ) + pWindow->width = 1; + if( pWindow->height < 1 ) + pWindow->height = 1; + + #ifdef ENABLE_GTK + if( pInst->bShouldUseXEmbed ) + { + if( ! pInst->pGtkWidget ) + { + medDebug( 1, "creating gtk plug and socket\n" ); + + pInst->pGtkWindow = gtk_plug_new((GdkNativeWindow)reinterpret_cast(pWindow->window)); + gtk_widget_show( pInst->pGtkWindow ); + pInst->pGtkWidget = gtk_socket_new(); + gtk_widget_show( pInst->pGtkWidget ); + gtk_container_add( GTK_CONTAINER(pInst->pGtkWindow), pInst->pGtkWidget ); + gtk_widget_show_all( pInst->pGtkWindow ); + pInst->window.window = (void *)gtk_socket_get_id( GTK_SOCKET(pInst->pGtkWidget ) ); + + XSync( pAppDisplay, False ); + + XMapWindow( pAppDisplay, GDK_WINDOW_XWINDOW(pInst->pGtkWindow->window) ); + + XSync( pAppDisplay, False ); + } + + // update widget size; alas out parent is not yet really XEMBED conformant + gtk_widget_set_size_request( pInst->pGtkWidget, pWindow->width, pWindow->height ); + gtk_window_resize( GTK_WINDOW(pInst->pGtkWindow), pWindow->width, pWindow->height ); + + GdkScreen* pGdkScreen = gtk_widget_get_screen( pInst->pGtkWidget ); + Screen* pScreen = ScreenOfDisplay( pAppDisplay, gdk_screen_get_number( pGdkScreen ) ); + + pInst->window.x = 0; + pInst->window.y = 0; + pInst->window.width = pWindow->width; + pInst->window.height = pWindow->height; + pInst->window.clipRect.left = 0; + pInst->window.clipRect.top = 0; + pInst->window.clipRect.right = pWindow->width; + pInst->window.clipRect.bottom = pWindow->height; + pInst->window.ws_info = &pInst->ws_info; + pInst->window.type = NPWindowTypeWindow; + pInst->ws_info.type = NP_SETWINDOW; + pInst->ws_info.display = pAppDisplay; + pInst->ws_info.visual = DefaultVisualOfScreen( pScreen ); + pInst->ws_info.colormap = DefaultColormapOfScreen( pScreen ); + pInst->ws_info.depth = DefaultDepthOfScreen( pScreen ); + } + else + #endif + { + if( ! pInst->pWidget ) + { + pInst->pWidget = CreateNewShell( &(pInst->pShell), (XLIB_Window)pWindow->window ); + } + + // fill in NPWindow and NPCallbackStruct + pInst->window.window = (void*)XtWindow( (Widget)pInst->pWidget ); + pInst->window.x = 0; + pInst->window.y = 0; + pInst->window.width = pWindow->width; + pInst->window.height = pWindow->height; + pInst->window.clipRect.left = 0; + pInst->window.clipRect.top = 0; + pInst->window.clipRect.right = pWindow->width; + pInst->window.clipRect.bottom = pWindow->height; + pInst->window.ws_info = &pInst->ws_info; + pInst->window.type = NPWindowTypeWindow; + pInst->ws_info.type = NP_SETWINDOW; + pInst->ws_info.display = XtDisplay( (Widget)pInst->pWidget ); + pInst->ws_info.visual = DefaultVisualOfScreen( XtScreen( (Widget)pInst->pWidget ) ); + pInst->ws_info.colormap = DefaultColormapOfScreen( XtScreen( (Widget)pInst->pWidget ) ); + pInst->ws_info.depth = DefaultDepthOfScreen( XtScreen( (Widget)pInst->pWidget ) ); + + XtResizeWidget( (Widget)pInst->pShell, + pInst->window.width, + pInst->window.height, + 0 ); + XtResizeWidget( (Widget)pInst->pWidget, + pInst->window.width, + pInst->window.height, + 0 ); + } + + NPError aRet = aPluginFuncs.setwindow( pInst->instance, &pInst->window ); + medDebug( 1, "pluginapp: NPP_SetWindow returns %d\n", (int) aRet ); + Respond( pMessage->m_nID, + (char*)&aRet, sizeof( aRet ), + NULL ); + delete [] (char*)pWindow; + } + break; + case eNPP_StreamAsFile: + { + sal_uInt32 nInstance = pMessage->GetUINT32(); + NPP instance = m_aInstances[ nInstance ]->instance; + sal_uInt32 nFileID = pMessage->GetUINT32(); + NPStream* pStream = m_aNPWrapStreams[ nFileID ]; + char* fname = pMessage->GetString(); + medDebug( 1, "pluginapp: NPP_StreamAsFile %s\n", fname ); + aPluginFuncs.asfile( instance, pStream, fname ); + delete [] fname; + } + break; + case eNPP_URLNotify: + { + sal_uInt32 nInstance = pMessage->GetUINT32(); + NPP instance = m_aInstances[ nInstance ]->instance; + char* url = pMessage->GetString(); + NPReason* pReason = (NPReason*)pMessage->GetBytes(); + void** notifyData = (void**)pMessage->GetBytes(); + aPluginFuncs.urlnotify( instance, url, *pReason, *notifyData ); + delete [] url; + delete [] pReason; + delete [] notifyData; + } + break; + case eNPP_WriteReady: + { + sal_uInt32 nInstance = pMessage->GetUINT32(); + NPP instance = m_aInstances[ nInstance ]->instance; + sal_uInt32 nFileID = pMessage->GetUINT32(); + NPStream* pStream = m_aNPWrapStreams[ nFileID ]; + int32 nRet = aPluginFuncs.writeready( instance, pStream ); + + medDebug( 1, "pluginapp: NPP_WriteReady( %p, %p ) (stream id = %d) returns %d\n", + instance, pStream, nFileID, nRet ); + + Respond( pMessage->m_nID, + (char*)&nRet, sizeof( nRet ), + NULL ); + } + break; + case eNPP_Write: + { + sal_uInt32 nInstance = pMessage->GetUINT32(); + NPP instance = m_aInstances[ nInstance ]->instance; + sal_uInt32 nFileID = pMessage->GetUINT32(); + NPStream* pStream = m_aNPWrapStreams[ nFileID ]; + int32 offset = pMessage->GetUINT32(); + sal_uLong len; + char* buffer = (char*)pMessage->GetBytes( len ); + int32 nRet = aPluginFuncs.write( instance, pStream, offset, len, buffer ); + + medDebug( 1,"pluginapp: NPP_Write( %p, %p, %d, %d, %p ) returns %d\n" + "stream = { pdata = %p, ndata = %p, url = %s, end = %d, lastmodified = %d, notifyData = %p }\n", + instance, pStream, offset, len, buffer, nRet, + pStream->pdata, pStream->ndata, pStream->url, pStream->end, pStream->lastmodified, pStream->notifyData ); + + Respond( pMessage->m_nID, + (char*)&nRet, sizeof( nRet ), + NULL ); + delete [] buffer; + } + break; + case eNPP_GetMIMEDescription: + { + if( ! pNPP_GetMIMEDescription ) + pNPP_GetMIMEDescription = (char*(*)()) + osl_getAsciiFunctionSymbol( pPluginLib, "NPP_GetMIMEDescription" ); + char* pMIME = pNPP_GetMIMEDescription(); + Respond( pMessage->m_nID, + POST_STRING( pMIME ), + NULL ); + } + break; + case eNPP_Initialize: + { + + pNP_Initialize = + (NPError(*)(NPNetscapeFuncs*, NPPluginFuncs*)) + osl_getAsciiFunctionSymbol( pPluginLib, "NP_Initialize" ); + medDebug( !pNP_Initialize, "no NP_Initialize, %s\n", dlerror() ); + pNP_Shutdown = (NPError(*)()) + osl_getAsciiFunctionSymbol( pPluginLib, "NP_Shutdown" ); + medDebug( !pNP_Initialize, "no NP_Shutdown, %s\n", dlerror() ); + + medDebug( 1, "entering NP_Initialize\n" ); + NPError aRet = pNP_Initialize( &aNetscapeFuncs, &aPluginFuncs ); + medDebug( 1, "pluginapp: NP_Initialize returns %d\n", (int) aRet ); + Respond( pMessage->m_nID, (char*)&aRet, sizeof( aRet ), NULL ); + } + break; + case eNPP_Shutdown: + { + write( wakeup_fd[1], "xxxx", 4 ); + } + break; + default: + medDebug( 1, "caught unknown NPP request %d\n", nCommand ); + break; + } + delete pMessage; + } + return 0; +} + +void LoadAdditionalLibs( const char* _pPluginLib ) +{ + medDebug( 1, "LoadAdditionalLibs %s\n", _pPluginLib ); + + if( ! strncmp( _pPluginLib, "libflashplayer.so", 17 ) ) + { + /* #b4951312# flash 7 implicitly assumes a gtk application + * if the API version is greater or equal to 12 (probably + * because they think they run in mozilla then). In that + * case they try to find gtk within the process and crash + * when they don't find it. + */ + aNetscapeFuncs.version = 11; + aPluginFuncs.version = 11; + } +} + --- a/main/extensions/source/plugin/unx/nppapi.cxx +++ a/main/extensions/source/plugin/unx/nppapi.cxx @@ -0,0 +1,617 @@ +/************************************************************** + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + *************************************************************/ + + + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_extensions.hxx" + +#if STLPORT_VERSION>=321 +#include +#endif + +#include +#include + +std::vector PluginConnector::allConnectors; + +PluginConnector::PluginConnector( int nSocket ) : + Mediator( nSocket ) +{ + allConnectors.push_back( this ); + SetNewMessageHdl( LINK( this, PluginConnector, NewMessageHdl ) ); +} + +PluginConnector::~PluginConnector() +{ + vos::OGuard aGuard( m_aUserEventMutex ); + for( std::vector< PluginConnector* >::iterator it = allConnectors.begin(); + it != allConnectors.end(); ++it ) + { + if( *it == this ) + { + allConnectors.erase( it ); + break; + } + } +} + +IMPL_LINK( PluginConnector, NewMessageHdl, Mediator*, /*pMediator*/ ) +{ + vos::OGuard aGuard( m_aUserEventMutex ); + bool bFound = false; + for( std::vector< PluginConnector* >::iterator it = allConnectors.begin(); + it != allConnectors.end() && bFound == false; ++it ) + { + if( *it == this ) + bFound = true; + } + if( ! bFound ) + return 0; + Application::PostUserEvent( LINK( this, PluginConnector, WorkOnNewMessageHdl ) ); + return 0; +} + +IMPL_LINK( PluginConnector, WorkOnNewMessageHdl, Mediator*, /*pMediator*/ ) +{ + bool bFound = false; + for( std::vector< PluginConnector* >::iterator it = allConnectors.begin(); + it != allConnectors.end() && bFound == false; ++it ) + { + if( *it == this ) + bFound = true; + } + if( ! bFound ) + return 0; +/* + { + vos::OGuard aGuard( m_aUserEventMutex ); + m_aUserEventIDs.pop_front(); + } +*/ + + MediatorMessage* pMessage; + CommandAtoms nCommand; + while( (pMessage = GetNextMessage( sal_False )) ) + { + nCommand = (CommandAtoms)pMessage->GetUINT32(); + medDebug( 1, "%s\n", GetCommandName( nCommand ) ); + switch( nCommand ) + { + case eNPN_GetURL: + { + sal_uInt32 nInstance = pMessage->GetUINT32(); + NPP instance = m_aInstances[ nInstance ]->instance; + char* pUrl = pMessage->GetString(); + char* pWindow = pMessage->GetString(); + NPError aRet = NPN_GetURL( instance, pUrl, pWindow ); + Respond( pMessage->m_nID, + (char*)(&aRet), sizeof( NPError ), NULL ); + delete [] pUrl; + delete [] pWindow; + } + break; + case eNPN_GetURLNotify: + { + sal_uInt32 nInstance = pMessage->GetUINT32(); + NPP instance = m_aInstances[ nInstance ]->instance; + char* pUrl = pMessage->GetString(); + char* pWindow = pMessage->GetString(); + void** pNotifyData = (void**)pMessage->GetBytes(); + NPError aRet = NPN_GetURLNotify( instance, pUrl, pWindow, + *pNotifyData ); + Respond( pMessage->m_nID, + (char*)(&aRet), sizeof( NPError ), NULL ); + delete [] pUrl; + delete [] pWindow; + delete [] pNotifyData; + } + break; + case eNPN_DestroyStream: + { + sal_uInt32 nInstance = pMessage->GetUINT32(); + NPP instance = m_aInstances[ nInstance ]->instance; + sal_uInt32 nFileID = pMessage->GetUINT32(); + char* pUrl = pMessage->GetString(); + NPError* pReason = (NPError*)pMessage->GetBytes(); + NPError aRet = NPERR_FILE_NOT_FOUND; + if( nFileID < static_cast(m_aNPWrapStreams.size()) ) + { + if( ! strcmp( m_aNPWrapStreams[ nFileID ]->url, pUrl ) ) + { + aRet = + NPN_DestroyStream( instance, m_aNPWrapStreams[ nFileID ], + *pReason ); + m_aNPWrapStreams.erase( m_aNPWrapStreams.begin() + nFileID ); + } + else + medDebug( 1, "StreamID %d has incoherent urls %s and %s\n", + nFileID, pUrl, m_aNPWrapStreams[ nFileID ]->url ); + } + else + medDebug( 1, "Nonexistent StreamID %d\n", nFileID ); + + Respond( pMessage->m_nID, + (char*)(&aRet), sizeof( NPError ), NULL ); + + delete [] pUrl; + delete [] pReason; + } + break; + case eNPN_NewStream: + { + sal_uInt32 nInstance = pMessage->GetUINT32(); + NPP instance = m_aInstances[ nInstance ]->instance; + NPMIMEType pType = pMessage->GetString(); + char* pTarget = pMessage->GetString(); + + NPStream* pStream = NULL; + + NPError aRet = NPN_NewStream( instance, pType, pTarget, &pStream ); + + if( aRet != NPERR_NO_ERROR ) + { + sal_uInt32 nDummy = 0; + Respond( pMessage->m_nID, + (char*)&aRet, sizeof( aRet ), + "", 0, + &nDummy, sizeof(sal_uInt32), + &nDummy, sizeof(sal_uInt32), + NULL ); + } + else + { + m_aNPWrapStreams.push_back( pStream ); + + sal_uLong nLen = strlen( pStream->url ); + Respond( pMessage->m_nID, + (char*)&aRet, sizeof( aRet ), + pStream->url, nLen, + &pStream->end, sizeof(sal_uInt32), + &pStream->lastmodified, sizeof(sal_uInt32), + NULL ); + } + + delete [] pTarget; + delete [] pType; + } + break; + case eNPN_PostURLNotify: + { + sal_uInt32 nInstance = pMessage->GetUINT32(); + NPP instance = m_aInstances[ nInstance ]->instance; + char* pUrl = pMessage->GetString(); + char* pTarget = pMessage->GetString(); + sal_uInt32 nLen = pMessage->GetUINT32(); + char* pBuf = (char*)pMessage->GetBytes(); + NPBool* pFile = (NPBool*)pMessage->GetBytes(); + void** pNData = (void**)pMessage->GetBytes(); + NPError aRet = + NPN_PostURLNotify( instance, pUrl, pTarget, nLen, pBuf, *pFile, *pNData ); + Respond( pMessage->m_nID, (char*)&aRet, sizeof( aRet ), NULL ); + delete [] pUrl; + delete [] pTarget; + delete [] pBuf; + delete [] pFile; + delete [] pNData; + } + break; + case eNPN_PostURL: + { + sal_uInt32 nInstance = pMessage->GetUINT32(); + NPP instance = m_aInstances[ nInstance ]->instance; + char* pUrl = pMessage->GetString(); + char* pWindow = pMessage->GetString(); + sal_uInt32 nLen = pMessage->GetUINT32(); + char* pBuf = (char*)pMessage->GetBytes(); + NPBool* pFile = (NPBool*)pMessage->GetBytes(); + NPError aRet = + NPN_PostURL( instance, pUrl, pWindow, nLen, pBuf, *pFile ); + Respond( pMessage->m_nID, (char*)&aRet, sizeof( aRet ), NULL ); + delete [] pUrl; + delete [] pWindow; + delete [] pBuf; + delete [] pFile; + } + break; + case eNPN_RequestRead: + { + sal_uInt32 nFileID = pMessage->GetUINT32(); + NPStream* pStream = m_aNPWrapStreams[ nFileID ]; + sal_uInt32 nRanges = pMessage->GetUINT32(); + sal_uInt32* pArray = (sal_uInt32*)pMessage->GetBytes(); + // build ranges table + NPByteRange* pFirst = new NPByteRange; + NPByteRange* pRun = pFirst; + for( sal_uInt32 n = 0; n < nRanges; n++ ) + { + pRun->offset = pArray[ 2*n ]; + pRun->length = pArray[ 2*n+1 ]; + pRun->next = n < nRanges-1 ? new NPByteRange : NULL; + pRun = pRun->next; + } + NPError aRet = NPN_RequestRead( pStream, pFirst ); + Respond( pMessage->m_nID, (char*)&aRet, sizeof( aRet ), NULL ); + while( pFirst ) + { + pRun = pFirst->next; + delete pFirst; + pFirst = pRun; + } + delete [] pArray; + } + break; + case eNPN_Status: + { + sal_uInt32 nInstance = pMessage->GetUINT32(); + NPP instance = m_aInstances[ nInstance ]->instance; + char* pString = pMessage->GetString(); + NPN_Status( instance, pString ); + delete [] pString; + } + break; + case eNPN_Version: + { + int major, minor, net_major, net_minor; + NPN_Version( &major, &minor, &net_major, &net_minor ); + Respond( pMessage->m_nID, + (char*)&major, sizeof( int ), + &minor, sizeof( int ), + &net_major, sizeof( int ), + &net_minor, sizeof( int ), + NULL ); + } + break; + case eNPN_Write: + { + sal_uInt32 nInstance = pMessage->GetUINT32(); + NPP instance = m_aInstances[ nInstance ]->instance; + sal_uInt32 nFileID = pMessage->GetUINT32(); + NPStream* pStream = m_aNPWrapStreams[ nFileID ]; + sal_Int32 nLen = pMessage->GetUINT32(); + void* pBuffer = pMessage->GetBytes(); + sal_Int32 nRet = NPN_Write( instance, pStream, nLen, pBuffer ); + Respond( pMessage->m_nID, + (char*)&nRet, sizeof( nRet ), + NULL ); + delete [] (char*)pBuffer; + delete instance; + } + break; + case eNPN_UserAgent: + { + sal_uInt32 nInstance = pMessage->GetUINT32(); + NPP instance = m_aInstances[ nInstance ]->instance; + const char* pAnswer = NPN_UserAgent( instance ); + Respond( pMessage->m_nID, + (char*)pAnswer, strlen( pAnswer ), + NULL ); + } + break; + default: + medDebug( 1, "caught unknown NPN request %d\n", nCommand ); + } + + delete pMessage; + } + return 0; +} + +#define GET_INSTANCE() \ + sal_uInt32 nInstance; \ + nInstance = GetNPPID( instance ); + +#define GET_INSTANCE_RET( err ) \ + GET_INSTANCE() \ + if( nInstance == PluginConnector::UnknownNPPID ) \ + return err + + +#define POST_INSTANCE() (char*)&nInstance, sizeof( nInstance ) + +NPError UnxPluginComm::NPP_Destroy( NPP instance, NPSavedData** save ) +{ + NPError aRet = NPERR_GENERIC_ERROR; + GET_INSTANCE_RET( aRet ); + MediatorMessage* pMes = + Transact( eNPP_Destroy, + POST_INSTANCE(), + NULL ); + if( ! pMes ) + return NPERR_GENERIC_ERROR; + delete pMes; + + pMes = Transact( eNPP_DestroyPhase2, + POST_INSTANCE(), + NULL ); + if( ! pMes ) + return NPERR_GENERIC_ERROR; + + aRet = GetNPError( pMes ); + sal_uLong nSaveBytes; + void* pSaveData = pMes->GetBytes( nSaveBytes ); + if( nSaveBytes == 4 && *(sal_uInt32*)pSaveData == 0 ) + *save = NULL; + else + { + *save = new NPSavedData; + (*save)->len = nSaveBytes; + (*save)->buf = pSaveData; + } + delete pMes; + + return aRet; +} + +NPError UnxPluginComm::NPP_DestroyStream( NPP instance, NPStream* stream, NPError reason ) +{ + NPError aRet = NPERR_GENERIC_ERROR; + GET_INSTANCE_RET( aRet ); + sal_uInt32 nFileID = GetStreamID( stream ); + if( nFileID == PluginConnector::UnknownStreamID ) + return NPERR_GENERIC_ERROR; + + MediatorMessage* pMes = + Transact( eNPP_DestroyStream, + POST_INSTANCE(), + &nFileID, sizeof( nFileID ), + &reason, sizeof( reason ), + NULL ); + m_aNPWrapStreams.erase( m_aNPWrapStreams.begin() + nFileID ); + if( ! pMes ) + return NPERR_GENERIC_ERROR; + + aRet = GetNPError( pMes ); + delete pMes; + return aRet; +} + +void* UnxPluginComm::NPP_GetJavaClass() +{ + return NULL; +} + +NPError UnxPluginComm::NPP_Initialize() +{ + MediatorMessage* pMes = + Transact( eNPP_Initialize, + NULL ); + if( ! pMes ) + return NPERR_GENERIC_ERROR; + + NPError aRet = GetNPError( pMes ); + delete pMes; + return aRet; +} + +NPError UnxPluginComm::NPP_New( NPMIMEType pluginType, NPP instance, uint16 mode, int16 argc, + char* argn[], char* argv[], NPSavedData *saved ) +{ + m_aInstances.push_back( + new ConnectorInstance( instance, pluginType, 0, + NULL, 0, NULL, 0, + saved ? (char*)saved->buf : NULL, + saved ? saved->len : 0 ) ); + + char *pArgnBuf, *pArgvBuf; + size_t nArgnLen = 0, nArgvLen = 0; + int i; + for( i = 0; i < argc; i++ ) + { + nArgnLen += strlen( argn[i] ) +1; + nArgvLen += strlen( argv[i] ) +1; + } + pArgnBuf = new char[ nArgnLen ]; + pArgvBuf = new char[ nArgvLen ]; + char* pRunArgn = pArgnBuf; + char* pRunArgv = pArgvBuf; + for( i = 0; i < argc; i++ ) + { + strcpy( pRunArgn, argn[i] ); + strcpy( pRunArgv, argv[i] ); + pRunArgn += strlen( argn[i] ) +1; + pRunArgv += strlen( argv[i] ) +1; + } + + MediatorMessage* pMes; + if( saved ) + pMes = + Transact( eNPP_New, + pluginType, strlen( pluginType ), + &mode, sizeof( mode ), + &argc, sizeof( argc ), + pArgnBuf, nArgnLen, + pArgvBuf, nArgvLen, + saved->buf, static_cast(saved->len), + NULL ); + else + pMes = + Transact( eNPP_New, + pluginType, strlen( pluginType ), + &mode, sizeof( mode ), + &argc, sizeof( argc ), + pArgnBuf, nArgnLen, + pArgvBuf, nArgvLen, + "0000", size_t(4), + NULL ); + delete [] pArgnBuf; + delete [] pArgvBuf; + if( ! pMes ) + return NPERR_GENERIC_ERROR; + + NPError aRet = GetNPError( pMes ); + delete pMes; + + return aRet; +} + +NPError UnxPluginComm::NPP_NewStream( NPP instance, NPMIMEType type, NPStream* stream, + NPBool seekable, uint16* stype ) +{ + NPError aRet = NPERR_GENERIC_ERROR; + GET_INSTANCE_RET( aRet ); + + m_aNPWrapStreams.push_back( stream ); + MediatorMessage* pMes = + Transact( eNPP_NewStream, + POST_INSTANCE(), + type, strlen( type ), + stream->url, strlen( stream->url ), + &stream->end, sizeof( stream->end ), + &stream->lastmodified, sizeof( stream->lastmodified ), + &seekable, sizeof( seekable ), + NULL ); + + if( ! pMes ) + return NPERR_GENERIC_ERROR; + + aRet = GetNPError( pMes ); + uint16* pSType = (uint16*)pMes->GetBytes(); + *stype = *pSType; + + delete [] pSType; + delete pMes; + return aRet; +} + +void UnxPluginComm::NPP_Print( NPP /*instance*/, NPPrint* /*platformPrint*/ ) +{ +} + +NPError UnxPluginComm::NPP_SetWindow( NPP instance, NPWindow* window ) +{ + NPError aRet = NPERR_GENERIC_ERROR; + GET_INSTANCE_RET( aRet ); + + MediatorMessage* pMes = + Transact( eNPP_SetWindow, + POST_INSTANCE(), + window, sizeof( NPWindow ), + NULL ); + if( ! pMes ) + return NPERR_GENERIC_ERROR; + + aRet = GetNPError( pMes ); + delete pMes; + return aRet; +} + +void UnxPluginComm::NPP_Shutdown() +{ + Send( eNPP_Shutdown, NULL ); +} + +void UnxPluginComm::NPP_StreamAsFile( NPP instance, NPStream* stream, const char* fname ) +{ + GET_INSTANCE(); + sal_uInt32 nFileID = GetStreamID( stream ); + if( nFileID == PluginConnector::UnknownStreamID ) + return; + + Send( eNPP_StreamAsFile, + POST_INSTANCE(), + &nFileID, sizeof( nFileID ), + fname, strlen( fname ), + NULL ); +} + +void UnxPluginComm::NPP_URLNotify( NPP instance, const char* url, NPReason reason, void* notifyData ) +{ + GET_INSTANCE(); + + Send( eNPP_URLNotify, + POST_INSTANCE(), + url, strlen( url ), + &reason, sizeof( reason ), + ¬ifyData, sizeof( void* ), + NULL ); +} + +int32 UnxPluginComm::NPP_Write( NPP instance, NPStream* stream, int32 offset, int32 len, void* buffer ) +{ + GET_INSTANCE_RET( -1 ); + sal_uInt32 nFileID = GetStreamID( stream ); + if( nFileID == PluginConnector::UnknownStreamID ) + return -1; + + MediatorMessage* pMes = + Transact( eNPP_Write, + POST_INSTANCE(), + &nFileID, sizeof( nFileID ), + &offset, sizeof( offset ), + buffer, static_cast(len), + NULL ); + if( ! pMes ) + return 0; + + int32 aRet = pMes->GetUINT32(); + delete pMes; + + return aRet; +} + +int32 UnxPluginComm::NPP_WriteReady( NPP instance, NPStream* stream ) +{ + GET_INSTANCE_RET( -1 ); + sal_uInt32 nFileID = GetStreamID( stream ); + if( nFileID == PluginConnector::UnknownStreamID ) + return -1; + + MediatorMessage* pMes = + Transact( eNPP_WriteReady, + POST_INSTANCE(), + &nFileID, sizeof( nFileID ), + NULL ); + + if( ! pMes ) + return 0; + + int32 aRet = pMes->GetUINT32(); + delete pMes; + + return aRet; +} + +char* UnxPluginComm::NPP_GetMIMEDescription() +{ + static char* pDesc = NULL; + MediatorMessage* pMes = + Transact( eNPP_GetMIMEDescription, + NULL ); + if( ! pMes ) + return (char*)""; + + if( pDesc ) + delete [] pDesc; + pDesc = pMes->GetString(); + delete pMes; + return pDesc; +} + +NPError UnxPluginComm::NPP_GetValue( NPP /*instance*/, NPPVariable /*variable*/, void* /*value*/ ) +{ + return 0; +} + +NPError UnxPluginComm::NPP_SetValue( NPP /*instance*/, NPNVariable /*variable*/, void* /*value*/ ) +{ + return 0; +} --- a/main/extensions/source/plugin/unx/npwrap.cxx +++ a/main/extensions/source/plugin/unx/npwrap.cxx @@ -0,0 +1,511 @@ +/************************************************************** + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + *************************************************************/ + + + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_extensions.hxx" +#include +#include +#include +#include +#include +#include + +#include + +#include +#include + +PluginConnector* pConnector = NULL; + +int nAppArguments = 0; +char** pAppArguments = NULL; +Display* pAppDisplay = NULL; +Display* pXtAppDisplay = NULL; + +extern oslModule pPluginLib; +extern NPError (*pNP_Shutdown)(); + +void LoadAdditionalLibs(const char*); + +XtAppContext app_context; +Widget topLevel = NULL, topBox = NULL; +int wakeup_fd[2] = { 0, 0 }; +static bool bPluginAppQuit = false; + +static long GlobalConnectionLostHdl( void* /*pInst*/, void* /*pArg*/ ) +{ + medDebug( 1, "pluginapp exiting due to connection lost\n" ); + + write( wakeup_fd[1], "xxxx", 4 ); + return 0; +} + +extern "C" +{ + static int plugin_x_error_handler( Display*, XErrorEvent* ) + { + return 0; + } + + #ifndef ENABLE_GTK + static void ThreadEventHandler( XtPointer /*client_data*/, int* /*source*/, XtInputId* id ) + { + char buf[256]; + // clear pipe + int len, nLast = -1; + + while( (len = read( wakeup_fd[0], buf, sizeof( buf ) ) ) > 0 ) + nLast = len-1; + if( ! bPluginAppQuit ) + { + if( ( nLast == -1 || buf[nLast] != 'x' ) && pConnector ) + pConnector->CallWorkHandler(); + else + { + // it seems you can use XtRemoveInput only + // safely from within the callback + // why is that ? + medDebug( 1, "removing wakeup pipe\n" ); + XtRemoveInput( *id ); + XtAppSetExitFlag( app_context ); + bPluginAppQuit = true; + + delete pConnector; + pConnector = NULL; + } + } + } + #endif +} + + +IMPL_LINK( PluginConnector, NewMessageHdl, Mediator*, /*pMediator*/ ) +{ + medDebug( 1, "new message handler\n" ); + write( wakeup_fd[1], "cccc", 4 ); + return 0; + +} + +Widget createSubWidget( char* /*pPluginText*/, Widget shell, XLIB_Window aParentWindow ) +{ + Widget newWidget = XtVaCreateManagedWidget( +#if defined USE_MOTIF + "drawingArea", + xmDrawingAreaWidgetClass, +#else + "", +# if defined DISABLE_XAW + compositeWidgetClass, +# else + labelWidgetClass, +# endif +#endif + shell, + XtNwidth, 200, + XtNheight, 200, + (char *)NULL ); + XtRealizeWidget( shell ); + XtRealizeWidget( newWidget ); + + medDebug( 1, "Reparenting new widget %x to %x\n", XtWindow( newWidget ), aParentWindow ); + XReparentWindow( pXtAppDisplay, + XtWindow( shell ), + aParentWindow, + 0, 0 ); + XtMapWidget( shell ); + XtMapWidget( newWidget ); + XRaiseWindow( pXtAppDisplay, XtWindow( shell ) ); + XSync( pXtAppDisplay, False ); + + return newWidget; +} + +void* CreateNewShell( void** pShellReturn, XLIB_Window aParentWindow ) +{ + XLIB_String n, c; + XtGetApplicationNameAndClass(pXtAppDisplay, &n, &c); + + Widget newShell = + XtVaAppCreateShell( "pane", c, + topLevelShellWidgetClass, + pXtAppDisplay, + XtNwidth, 200, + XtNheight, 200, + XtNoverrideRedirect, True, + (char *)NULL ); + *pShellReturn = newShell; + + char pText[1024]; + sprintf( pText, "starting plugin %s ...", pAppArguments[2] ); + + Widget newWidget = createSubWidget( pText, newShell, aParentWindow ); + + return newWidget; +} + +static oslModule LoadModule( const char* pPath ) +{ + ::rtl::OUString sSystemPath( ::rtl::OUString::createFromAscii( pPath ) ); + ::rtl::OUString sFileURL; + osl_getFileURLFromSystemPath( sSystemPath.pData, &sFileURL.pData ); + + oslModule pLib = osl_loadModule( sFileURL.pData, SAL_LOADMODULE_LAZY ); + if( ! pLib ) + { + medDebug( 1, "could not open %s: %s\n", pPath, dlerror() ); + } + return pLib; +} + +// Unix specific implementation +static void CheckPlugin( const char* pPath ) +{ + oslModule pLib = LoadModule( pPath ); + + char*(*pNP_GetMIMEDescription)() = (char*(*)()) + osl_getAsciiFunctionSymbol( pLib, "NP_GetMIMEDescription" ); + if( pNP_GetMIMEDescription ) + printf( "%s\n", pNP_GetMIMEDescription() ); + else + medDebug( 1, "could not get symbol NP_GetMIMEDescription %s\n", dlerror() ); + + osl_unloadModule( pLib ); +} + +#if OSL_DEBUG_LEVEL > 1 && defined LINUX +#include +#endif + +extern "C" { + +static void signal_handler( int nSig ) +{ +#if OSL_DEBUG_LEVEL > 1 + fprintf( stderr, "caught signal %d, exiting\n", nSig ); +#ifdef LINUX + void* pStack[64]; + int nStackLevels = backtrace( pStack, sizeof(pStack)/sizeof(pStack[0]) ); + backtrace_symbols_fd( pStack, nStackLevels, STDERR_FILENO ); +#endif +#endif + if( pConnector ) + { + // ensure that a read on the other side will wakeup + delete pConnector; + pConnector = NULL; + } + + _exit(nSig); +} + +#ifdef ENABLE_GTK + +static gboolean noClosure( gpointer ) +{ + return sal_True; +} + +// Xt events +static gboolean prepareXtEvent( GSource*, gint* ) +{ + int nMask = XtAppPending( app_context ); + return (nMask & XtIMAll) != 0; +} + +static gboolean checkXtEvent( GSource* ) +{ + int nMask = XtAppPending( app_context ); + return (nMask & XtIMAll) != 0; +} + +static gboolean dispatchXtEvent( GSource*, GSourceFunc, gpointer ) +{ + XtAppProcessEvent( app_context, XtIMAll ); + return sal_True; +} + +static GSourceFuncs aXtEventFuncs = +{ + prepareXtEvent, + checkXtEvent, + dispatchXtEvent, + NULL, + noClosure, + NULL +}; + +static gboolean pollXtTimerCallback(gpointer) +{ + for(int i = 0; i < 5; i++) + { + if( (XtAppPending(app_context) & (XtIMAll & ~XtIMXEvent)) == 0 ) + break; + XtAppProcessEvent(app_context, XtIMAll & ~XtIMXEvent); + } + return sal_True; +} + +static gboolean prepareWakeupEvent( GSource*, gint* ) +{ + struct pollfd aPoll = { wakeup_fd[0], POLLIN, 0 }; + poll( &aPoll, 1, 0 ); + return (aPoll.revents & POLLIN ) != 0; +} + +static gboolean checkWakeupEvent( GSource* pSource ) +{ + gint nDum = 0; + return prepareWakeupEvent( pSource, &nDum ); +} + +static gboolean dispatchWakeupEvent( GSource*, GSourceFunc, gpointer ) +{ + char buf[256]; + // clear pipe + int len, nLast = -1; + + while( (len = read( wakeup_fd[0], buf, sizeof( buf ) ) ) > 0 ) + nLast = len-1; + if( ( nLast == -1 || buf[nLast] != 'x' ) && pConnector ) + pConnector->CallWorkHandler(); + else + { + XtAppSetExitFlag( app_context ); + bPluginAppQuit = true; + + delete pConnector; + pConnector = NULL; + } + + return sal_True; +} + +static GSourceFuncs aWakeupEventFuncs = { + prepareWakeupEvent, + checkWakeupEvent, + dispatchWakeupEvent, + NULL, + noClosure, + NULL +}; + +#endif // GTK + +} + +int main( int argc, char **argv) +{ + struct sigaction aSigAction; + aSigAction.sa_handler = signal_handler; + sigemptyset( &aSigAction.sa_mask ); + aSigAction.sa_flags = SA_NOCLDSTOP; + sigaction( SIGSEGV, &aSigAction, NULL ); + sigaction( SIGBUS, &aSigAction, NULL ); + sigaction( SIGABRT, &aSigAction, NULL ); + sigaction( SIGTERM, &aSigAction, NULL ); + sigaction( SIGILL, &aSigAction, NULL ); + + int nArg = (argc < 3) ? 1 : 2; + char* pBaseName = argv[nArg] + strlen(argv[nArg]); + while( pBaseName > argv[nArg] && pBaseName[-1] != '/' ) + pBaseName--; + LoadAdditionalLibs( pBaseName ); + + if( argc == 2 ) + { + CheckPlugin(argv[1]); + exit(0); + } + nAppArguments = argc; + pAppArguments = argv; + + XSetErrorHandler( plugin_x_error_handler ); + + if( pipe( wakeup_fd ) ) + { + medDebug( 1, "could not pipe()\n" ); + return 1; + } + // initialize 'wakeup' pipe. + int flags; + + // set close-on-exec descriptor flag. + if ((flags = fcntl (wakeup_fd[0], F_GETFD)) != -1) + { + flags |= FD_CLOEXEC; + fcntl (wakeup_fd[0], F_SETFD, flags); + } + if ((flags = fcntl (wakeup_fd[1], F_GETFD)) != -1) + { + flags |= FD_CLOEXEC; + fcntl (wakeup_fd[1], F_SETFD, flags); + } + + // set non-blocking I/O flag. + if ((flags = fcntl (wakeup_fd[0], F_GETFL)) != -1) + { + flags |= O_NONBLOCK; + fcntl (wakeup_fd[0], F_SETFL, flags); + } + if ((flags = fcntl (wakeup_fd[1], F_GETFL)) != -1) + { + flags |= O_NONBLOCK; + fcntl (wakeup_fd[1], F_SETFL, flags); + } + + pPluginLib = LoadModule( argv[2] ); + if( ! pPluginLib ) + { + exit(255); + } + int nSocket = atol( argv[1] ); + + #ifdef ENABLE_GTK + g_thread_init(NULL); + gtk_init(&argc, &argv); + #endif + + pConnector = new PluginConnector( nSocket ); + pConnector->SetConnectionLostHdl( Link( NULL, GlobalConnectionLostHdl ) ); + + XtSetLanguageProc( NULL, NULL, NULL ); + + XtToolkitInitialize(); + app_context = XtCreateApplicationContext(); + pXtAppDisplay = XtOpenDisplay( app_context, NULL, "SOPlugin", "SOPlugin", NULL, 0, &argc, argv ); + + + #ifdef ENABLE_GTK + // integrate Xt events into GTK event loop + GPollFD aXtPollDesc, aWakeupPollDesc; + + GSource* pXTSource = g_source_new( &aXtEventFuncs, sizeof(GSource) ); + if( !pXTSource ) + { + medDebug( 1, "could not get Xt GSource" ); + return 1; + } + + g_source_set_priority( pXTSource, GDK_PRIORITY_EVENTS ); + g_source_set_can_recurse( pXTSource, sal_True ); + g_source_attach( pXTSource, NULL ); + aXtPollDesc.fd = ConnectionNumber( pXtAppDisplay ); + aXtPollDesc.events = G_IO_IN; + aXtPollDesc.revents = 0; + g_source_add_poll( pXTSource, &aXtPollDesc ); + + gint xt_polling_timer_id = g_timeout_add( 25, pollXtTimerCallback, NULL); + // Initialize wakeup events listener + GSource *pWakeupSource = g_source_new( &aWakeupEventFuncs, sizeof(GSource) ); + if ( pWakeupSource == NULL ) + { + medDebug( 1, "could not get wakeup source" ); + return 1; + } + g_source_set_priority( pWakeupSource, GDK_PRIORITY_EVENTS); + g_source_attach( pWakeupSource, NULL ); + aWakeupPollDesc.fd = wakeup_fd[0]; + aWakeupPollDesc.events = G_IO_IN; + aWakeupPollDesc.revents = 0; + g_source_add_poll( pWakeupSource, &aWakeupPollDesc ); + + pAppDisplay = gdk_x11_display_get_xdisplay( gdk_display_get_default() ); + #else + pAppDisplay = pXtAppDisplay; + XtAppAddInput( app_context, + wakeup_fd[0], + (XtPointer)XtInputReadMask, + ThreadEventHandler, NULL ); + #endif + + // send that we are ready to go + MediatorMessage* pMessage = + pConnector->Transact( "init req", 8, + NULL ); + delete pMessage; + +#if OSL_DEBUG_LEVEL > 3 + int nPID = getpid(); + int nChild = fork(); + if( nChild == 0 ) + { + char pidbuf[16]; + char* pArgs[] = { "xterm", "-sl", "2000", "-sb", "-e", "gdb", "pluginapp.bin", pidbuf, NULL }; + sprintf( pidbuf, "%d", nPID ); + execvp( pArgs[0], pArgs ); + _exit(255); + } + else + sleep( 10 ); +#endif + + /* + * Loop for events. + */ + // for some reason XtAppSetExitFlag won't quit the application + // in ThreadEventHandler most of times; Xt will hang in select + // (hat is in XtAppNextEvent). Have our own mainloop instead + // of XtAppMainLoop + do + { + #ifdef ENABLE_GTK + g_main_context_iteration( NULL, sal_True ); + #else + XtAppProcessEvent( app_context, XtIMAll ); + #endif + } while( ! XtAppGetExitFlag( app_context ) && ! bPluginAppQuit ); + + medDebug( 1, "left plugin app main loop\n" ); + + #ifdef ENABLE_GTK + g_source_remove(xt_polling_timer_id); + #endif + + pNP_Shutdown(); + medDebug( 1, "NP_Shutdown done\n" ); + osl_unloadModule( pPluginLib ); + medDebug( 1, "plugin close\n" ); + + close( wakeup_fd[0] ); + close( wakeup_fd[1] ); + + return 0; +} + +#ifdef GCC +extern "C" { + void __pure_virtual() + {} + + void* __builtin_new( int nBytes ) + { return malloc(nBytes); } + void* __builtin_vec_new( int nBytes ) + { return malloc(nBytes); } + void __builtin_delete( char* pMem ) + { free(pMem); } + void __builtin_vec_delete( char* pMem ) + { free(pMem); } +} +#endif + --- a/main/extensions/source/plugin/unx/plugcon.cxx +++ a/main/extensions/source/plugin/unx/plugcon.cxx @@ -0,0 +1,278 @@ +/************************************************************** + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + *************************************************************/ + + + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_extensions.hxx" +#include + +#include +#include + +sal_uInt32 PluginConnector::GetStreamID( NPStream* pStream ) +{ + size_t nLen = m_aNPWrapStreams.size(); + for( size_t i = 0; i < nLen; i++ ) + if( m_aNPWrapStreams[ i ] == pStream ) + return static_cast(i); + medDebug( 1, "Error: NPStream has no ID\n" ); + return UnknownStreamID; +} + +sal_uInt32 PluginConnector::GetNPPID( NPP instance ) +{ + size_t nLen = m_aInstances.size(); + for( size_t i=0; i instance == instance ) + return static_cast(i); + medDebug( 1, "Error: NPP has no ID\n" ); + + return UnknownNPPID; +} + +ConnectorInstance* PluginConnector::getInstance( NPP instance ) +{ + size_t nLen = m_aInstances.size(); + for( size_t i=0; i instance == instance ) + return pInst; + } + return NULL; +} + +ConnectorInstance* PluginConnector::getInstanceById( sal_uInt32 nInstanceID ) +{ + return nInstanceID < static_cast(m_aInstances.size()) ? m_aInstances[ nInstanceID ] : NULL; +} + +struct PtrStruct +{ + char* pData; + sal_uLong nBytes; + + PtrStruct( char* i_pData, sal_uLong i_nBytes ) + : pData( i_pData ), nBytes( i_nBytes ) {} +}; + +sal_uLong PluginConnector::FillBuffer( char*& rpBuffer, + const char* pFunction, + sal_uLong nFunctionLen, + va_list ap ) +{ + std::vector< PtrStruct > aList; + aList.reserve( 5 ); + + sal_uLong nDataSize = nFunctionLen + sizeof( sal_uLong ); + char* pNext; + + do { + pNext = va_arg( ap, char* ); + if( pNext ) + { + aList.push_back( PtrStruct( pNext, va_arg( ap, sal_uLong ) ) ); + nDataSize += aList.back().nBytes + sizeof(sal_uLong); + } + } while( pNext ); + + rpBuffer = new char[ nDataSize ]; + char* pRun = rpBuffer; + memcpy( pRun, &nFunctionLen, sizeof( nFunctionLen ) ); + pRun += sizeof( nFunctionLen ); + memcpy( pRun, pFunction, nFunctionLen ); + pRun += nFunctionLen; + + for( std::vector::const_iterator it = aList.begin(); it != aList.end(); ++it ) + { + memcpy( pRun, &it->nBytes, sizeof( sal_uLong ) ); + pRun += sizeof( sal_uLong ); + memcpy( pRun, it->pData, it->nBytes ); + pRun += it->nBytes; + } + return nDataSize; +} + +MediatorMessage* PluginConnector::Transact( const char* pFunction, + sal_uLong nFunctionLen, ... ) +{ + va_list ap; + char* pBuffer; + + va_start( ap, nFunctionLen ); + sal_uLong nSize = FillBuffer( pBuffer, pFunction, nFunctionLen, ap ); + va_end( ap ); + return TransactMessage( nSize, pBuffer ); +} + +MediatorMessage* PluginConnector::Transact( sal_uInt32 nFunction, ... ) +{ + va_list ap; + char* pBuffer; + + va_start( ap, nFunction ); + sal_uLong nSize = FillBuffer( pBuffer, (char*)&nFunction, sizeof( nFunction ), ap ); + va_end( ap ); + return TransactMessage( nSize, pBuffer ); +} + +sal_uLong PluginConnector::Send( sal_uInt32 nFunction, ... ) +{ + va_list ap; + char* pBuffer; + + va_start( ap, nFunction ); + sal_uLong nSize = FillBuffer( pBuffer, (char*)&nFunction, sizeof( nFunction ), ap ); + va_end( ap ); + return SendMessage( nSize, pBuffer ); +} + +void PluginConnector::Respond( sal_uLong nID, + char* pFunction, + sal_uLong nFunctionLen, ... ) +{ + va_list ap; + char* pBuffer; + + va_start( ap, nFunctionLen ); + sal_uLong nSize = FillBuffer( pBuffer, pFunction, nFunctionLen, ap ); + va_end( ap ); + SendMessage( nSize, pBuffer, nID | ( 1 << 24 ) ); +} + +MediatorMessage* PluginConnector::WaitForAnswer( sal_uLong nMessageID ) +{ + if( ! m_bValid ) + return NULL; + + nMessageID &= 0x00ffffff; + while( m_pListener ) + { + { + vos::OGuard aGuard( m_aQueueMutex ); + for( size_t i = 0; i < m_aMessageQueue.size(); i++ ) + { + MediatorMessage* pMessage = m_aMessageQueue[ i ]; + sal_uLong nID = pMessage->m_nID; + if( ( nID & 0xff000000 ) && + ( ( nID & 0x00ffffff ) == nMessageID ) ) + { + m_aMessageQueue.erase( m_aMessageQueue.begin() + i ); + return pMessage; + } + } + } + if( ! m_aMessageQueue.empty() ) + CallWorkHandler(); + WaitForMessage( 2000 ); + } + return NULL; +} + +ConnectorInstance::ConnectorInstance( NPP inst, char* type, + int args, char* pargnbuf, sal_uLong nargnbytes, + char* pargvbuf, sal_uLong nargvbytes, + char* savedata, sal_uLong savebytes ) : + instance( inst ), + pShell( NULL ), + pWidget( NULL ), + pForm( NULL ), + pGtkWindow( NULL ), + pGtkWidget( NULL ), + bShouldUseXEmbed( false ), + nArg( args ), + pArgnBuf( pargnbuf ), + pArgvBuf( pargvbuf ) +{ + memset( &window, 0, sizeof(window) ); + pMimeType = new char[ strlen( type ) + 1 ]; + strcpy( pMimeType, type ); + aData.len = savebytes; + aData.buf = savedata; + argn = new char*[ nArg ]; + argv = new char*[ nArg ]; + int i; + char* pRun = pArgnBuf; + for( i = 0; i < nArg; i++ ) + { + argn[i] = pRun; + while( *pRun != 0 && (sal_uLong)(pRun - pArgnBuf) < nargnbytes ) + pRun++; + if( (sal_uLong)(pRun - pArgnBuf) < nargnbytes ) + pRun++; + } + pRun = pArgvBuf; + for( i = 0; i < nArg; i++ ) + { + argv[i] = pRun; + while( *pRun != 0 && (sal_uLong)(pRun - pArgvBuf) < nargvbytes ) + pRun++; + if( (sal_uLong)(pRun - pArgvBuf) < nargvbytes ) + pRun++; + } +} + +ConnectorInstance::~ConnectorInstance() +{ + delete [] pMimeType; + delete [] argn; + delete [] argv; + delete [] pArgnBuf; + delete [] pArgvBuf; + delete [] (char*)aData.buf; +} + +const char* GetCommandName( CommandAtoms eCommand ) +{ + switch( eCommand ) + { + case eNPN_GetURL: return "NPN_GetURL"; + case eNPN_GetURLNotify: return "NPN_GetURLNotify"; + case eNPN_DestroyStream: return "NPN_DestroyStream"; + case eNPN_NewStream: return "NPN_NewStream"; + case eNPN_PostURLNotify: return "NPN_PostURLNotify"; + case eNPN_PostURL: return "NPN_PostURL"; + case eNPN_RequestRead: return "NPN_RequestRead"; + case eNPN_Status: return "NPN_Status"; + case eNPN_Version: return "NPN_Version"; + case eNPN_Write: return "NPN_Write"; + case eNPN_UserAgent: return "NPN_UserAgent"; + + case eNPP_DestroyStream: return "NPP_DestroyStream"; + case eNPP_Destroy: return "NPP_Destroy"; + case eNPP_DestroyPhase2: return "NPP_DestroyPhase2"; + case eNPP_NewStream: return "NPP_NewStream"; + case eNPP_New: return "NPP_New"; + case eNPP_SetWindow: return "NPP_SetWindow"; + case eNPP_StreamAsFile: return "NPP_StreamAsFile"; + case eNPP_URLNotify: return "NPP_URLNotify"; + case eNPP_WriteReady: return "NPP_WriteReady"; + case eNPP_Write: return "NPP_Write"; + case eNPP_GetMIMEDescription: return "NPP_GetMIMEDescription"; + case eNPP_Initialize: return "NPP_Initialize"; + case eNPP_Shutdown: return "NPP_Shutdown"; + + case eMaxCommand: return "eMaxCommand"; + default: return "unknown command"; + } + return NULL; +} --- a/main/extensions/source/plugin/unx/sysplug.cxx +++ a/main/extensions/source/plugin/unx/sysplug.cxx @@ -0,0 +1,127 @@ +/************************************************************** + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + *************************************************************/ + + + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_extensions.hxx" +#include + +#include +#include +#include +#include +#include +#include + +#include + +int UnxPluginComm::nConnCounter = 0; + +UnxPluginComm::UnxPluginComm( + const String& /*mimetype*/, + const String& library, + XLIB_Window aParent, + int nDescriptor1, + int nDescriptor2 + ) : + PluginComm( ::rtl::OUStringToOString( library, osl_getThreadTextEncoding() ), false ), + PluginConnector( nDescriptor2 ) +{ + char pDesc[32]; + char pWindow[32]; + sprintf( pWindow, "%d", (int)aParent ); + sprintf( pDesc, "%d", nDescriptor1 ); + ByteString aLib( library, osl_getThreadTextEncoding() ); + rtl::OString path; + if (!getPluginappPath(&path)) { + fprintf( stderr, "cannot construct path to pluginapp.bin\n" ); + m_nCommPID = -1; + return; + } + + char const* pArgs[5]; + pArgs[0] = path.getStr(); + pArgs[1] = pDesc; + pArgs[2] = aLib.GetBuffer(); + pArgs[3] = pWindow; + pArgs[4] = NULL; + +#if OSL_DEBUG_LEVEL > 1 + m_nCommPID = 10; + fprintf( stderr, "Try to launch: %s %s %s %s, descriptors are %d, %d\n", pArgs[0], pArgs[1], pArgs[2], pArgs[3], nDescriptor1, nDescriptor2 ); +#endif + + if( ! ( m_nCommPID = fork() ) ) + { + execvp( pArgs[0], const_cast< char ** >(pArgs) ); + fprintf( stderr, "Error: could not exec %s\n", pArgs[0] ); + _exit(255); + } + + if( m_nCommPID != -1 ) + { + // wait for pluginapp.bin to start up + if( ! WaitForMessage( 5000 ) ) + { + fprintf( stderr, "Timeout on command: %s %s %s %s\n", pArgs[0], pArgs[1], pArgs[2], pArgs[3] ); + invalidate(); + } + else + { + MediatorMessage* pMessage = GetNextMessage( sal_True ); + Respond( pMessage->m_nID, + const_cast("init ack"),8, + NULL ); + delete pMessage; + NPP_Initialize(); + } + } +} + +UnxPluginComm::~UnxPluginComm() +{ + NPP_Shutdown(); + if( m_nCommPID != -1 && m_nCommPID != 0 ) + { + int status = 16777216; + pid_t nExit = waitpid( m_nCommPID, &status, WUNTRACED ); +#if OSL_DEBUG_LEVEL > 1 + fprintf( stderr, "child %d (plugin app child %d) exited with status %d\n", (int)nExit, (int)m_nCommPID, (int)WEXITSTATUS(status) ); +#else + (void)nExit; +#endif + } +} + +bool UnxPluginComm::getPluginappPath(rtl::OString * path) { + OSL_ASSERT(path != NULL); + rtl::OUString p( + RTL_CONSTASCII_USTRINGPARAM("$OOO_BASE_DIR/program/pluginapp.bin")); + rtl::Bootstrap::expandMacros(p); + return + (osl::FileBase::getSystemPathFromFileURL(p, p) == + osl::FileBase::E_None) && + p.convertToString( + path, osl_getThreadTextEncoding(), + (RTL_UNICODETOTEXT_FLAGS_UNDEFINED_ERROR | + RTL_UNICODETOTEXT_FLAGS_INVALID_ERROR)); +} --- a/main/extensions/source/plugin/unx/unxmgr.cxx +++ a/main/extensions/source/plugin/unx/unxmgr.cxx @@ -0,0 +1,311 @@ +/************************************************************** + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + *************************************************************/ + + + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_extensions.hxx" +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +using namespace rtl; +using namespace std; +using namespace com::sun::star::uno; +using namespace com::sun::star::plugin; + +// Unix specific implementation +static bool CheckPlugin( const ByteString& rPath, list< PluginDescription* >& rDescriptions ) +{ +#if OSL_DEBUG_LEVEL > 1 + fprintf( stderr, "Trying plugin %s ... ", rPath.GetBuffer() ); +#endif + + xub_StrLen nPos = rPath.SearchBackward( '/' ); + if( nPos == STRING_NOTFOUND ) + { +#if OSL_DEBUG_LEVEL > 1 + fprintf( stderr, "no absolute path to plugin\n" ); +#endif + return false; + } + + ByteString aBaseName = rPath.Copy( nPos+1 ); + if( aBaseName.Equals( "libnullplugin.so" ) ) + { +#if OSL_DEBUG_LEVEL > 1 + fprintf( stderr, "don't like %s\n", aBaseName.GetBuffer() ); +#endif + return false; + } + + struct stat aStat; + if( stat( rPath.GetBuffer(), &aStat ) || ! S_ISREG( aStat.st_mode ) ) + { +#if OSL_DEBUG_LEVEL > 1 + fprintf( stderr, "%s is not a regular file\n", rPath.GetBuffer() ); +#endif + return false; + } + + + rtl_TextEncoding aEncoding = osl_getThreadTextEncoding(); + + rtl::OString path; + if (!UnxPluginComm::getPluginappPath(&path)) { +#if OSL_DEBUG_LEVEL > 1 + fprintf( stderr, "cannot construct path to pluginapp.bin\n" ); +#endif + return false; + } + rtl::OStringBuffer cmd; + tools::appendUnixShellWord(&cmd, path); + cmd.append(' '); + tools::appendUnixShellWord(&cmd, rPath); + rtl::OString aCommand(cmd.makeStringAndClear()); + + FILE* pResult = popen( aCommand.getStr(), "r" ); + int nDescriptions = 0; + if( pResult ) + { + OStringBuffer aMIME; + char buf[256]; + while( fgets( buf, sizeof( buf ), pResult ) ) + { + for( size_t i = 0; i < sizeof(buf) && buf[i]; ++i ) + { + if( buf[i] == '\n' ) + buf[i] = ';'; + } + aMIME.append( buf ); + } + pclose( pResult ); + + if( aMIME.getLength() > 0 ) + { + OString aLine = aMIME.makeStringAndClear(); + + sal_Int32 nIndex = 0; + while( nIndex != -1 ) + { + OString aType = aLine.getToken( 0, ';', nIndex ); + + sal_Int32 nTypeIndex = 0; + OString aMimetype = aType.getToken( 0, ':', nTypeIndex ); + OString aExtLine = aType.getToken( 0, ':', nTypeIndex ); + if( nTypeIndex < 0 ) // ensure at least three tokens + continue; + OString aDesc = aType.getToken( 0, ':', nTypeIndex ); + + // create extension list string + sal_Int32 nExtIndex = 0; + OStringBuffer aExtension; + while( nExtIndex != -1 ) + { + OString aExt = aExtLine.getToken( 0, ',', nExtIndex); + if( aExt.indexOf( "*." ) != 0 ) + aExtension.append( "*." ); + aExtension.append( aExt ); + if( nExtIndex != -1 ) + aExtension.append( ';' ); + } + + PluginDescription* pNew = new PluginDescription; + // set plugin name (path to library) + pNew->PluginName = OStringToOUString( rPath, aEncoding ); + // set mimetype + pNew->Mimetype = OStringToOUString( aMimetype, aEncoding ); + // set extension line + pNew->Extension = OStringToOUString( aExtension.makeStringAndClear(), aEncoding ); + // set description + pNew->Description= OStringToOUString( aDesc, aEncoding ); + rDescriptions.push_back( pNew ); +#if OSL_DEBUG_LEVEL > 1 + fprintf( stderr, "Mimetype: %s\nExtension: %s\n" + "Description: %s\n", + OUStringToOString( pNew->Mimetype, aEncoding ).getStr(), + OUStringToOString( pNew->Extension, aEncoding ).getStr(), + OUStringToOString( pNew->Description, aEncoding ).getStr() + ); +#endif + } + } +#if OSL_DEBUG_LEVEL > 1 + else + fprintf( stderr, "result of \"%s\" contains no mimtype\n", + aCommand.getStr() ); +#endif + } +#if OSL_DEBUG_LEVEL > 1 + else + fprintf( stderr, "command \"%s\" failed\n", aCommand.getStr() ); +#endif + return nDescriptions > 0; +} + +union maxDirent +{ + char aBuffer[ sizeof( struct dirent ) + _PC_NAME_MAX +1 ]; + struct dirent asDirent; +}; + +static void CheckPluginRegistryFiles( const rtl::OString& rPath, list< PluginDescription* >& rDescriptions ) +{ + rtl::OStringBuffer aPath( 1024 ); + aPath.append( rPath ); + aPath.append( "/pluginreg.dat" ); + FILE* fp = fopen( aPath.getStr(), "r" ); + if( fp ) + { +#if OSL_DEBUG_LEVEL > 1 + fprintf( stderr, "parsing %s\n", aPath.getStr() ); +#endif + char aLine[1024]; + while( fgets( aLine, sizeof( aLine ), fp ) ) + { + int nLineLen = strlen( aLine ); + int nDotPos; + for( nDotPos = nLineLen-1; nDotPos > 0 && aLine[nDotPos] != ':'; nDotPos-- ) + ; + if( aLine[0] == '/' && aLine[nDotPos] == ':' && aLine[nDotPos+1] == '$' ) + CheckPlugin( ByteString( aLine, nDotPos ), rDescriptions ); + } + fclose( fp ); + } + + // check subdirectories + DIR* pDIR = opendir( rPath.getStr() ); + struct dirent* pDirEnt = NULL; + struct stat aStat; + maxDirent u; + while( pDIR && ! readdir_r( pDIR, &u.asDirent, &pDirEnt ) && pDirEnt ) + { + char* pBaseName = u.asDirent.d_name; + if( rtl_str_compare( ".", pBaseName ) && rtl_str_compare( "..", pBaseName ) ) + { + rtl::OStringBuffer aBuf( 1024 ); + aBuf.append( rPath ); + aBuf.append( '/' ); + aBuf.append( pBaseName ); + + if( ! stat( aBuf.getStr(), &aStat ) ) + { + if( S_ISDIR( aStat.st_mode ) ) + CheckPluginRegistryFiles( aBuf.makeStringAndClear(), rDescriptions ); + } + } + } + if( pDIR ) + closedir( pDIR ); +} + +Sequence XPluginManager_Impl::impl_getPluginDescriptions() throw() +{ + static Sequence aDescriptions; + static sal_Bool bHavePlugins = sal_False; + if( ! bHavePlugins ) + { + rtl_TextEncoding aEncoding = osl_getThreadTextEncoding(); + list aPlugins; + int i; + + // unix: search for plugins in /usr/lib/netscape/plugins, + // ~/.netscape/plugins und NPX_PLUGIN_PATH + // additionally: search in PluginsPath + static const char* pHome = getenv( "HOME" ); + static const char* pNPXPluginPath = getenv( "NPX_PLUGIN_PATH" ); + + ByteString aSearchPath( "/usr/lib/netscape/plugins" ); + if( pHome ) + { + aSearchPath.Append( ':' ); + aSearchPath.Append( pHome ); + aSearchPath += "/.netscape/plugins"; + } + if( pNPXPluginPath ) + { + aSearchPath.Append( ':' ); + aSearchPath += pNPXPluginPath; + } + + const Sequence< ::rtl::OUString >& rPaths( PluginManager::getAdditionalSearchPaths() ); + for( i = 0; i < rPaths.getLength(); i++ ) + { + aSearchPath += ":"; + aSearchPath += ByteString( String( rPaths.getConstArray()[i] ), aEncoding ); + } + + int nPaths = aSearchPath.GetTokenCount( ':' ); + maxDirent u; + for( i = 0; i < nPaths; i++ ) + { + ByteString aPath( aSearchPath.GetToken( i, ':' ) ); + if( aPath.Len() ) + { + DIR* pDIR = opendir( aPath.GetBuffer() ); + struct dirent* pDirEnt = NULL; + while( pDIR && ! readdir_r( pDIR, &u.asDirent, &pDirEnt ) && pDirEnt ) + { + char* pBaseName = u.asDirent.d_name; + if( pBaseName[0] != '.' || + pBaseName[1] != '.' || + pBaseName[2] != 0 ) + { + ByteString aFileName( aPath ); + aFileName += "/"; + aFileName += pBaseName; + CheckPlugin( aFileName, aPlugins ); + } + } + if( pDIR ) + closedir( pDIR ); + } + } + + // try ~/.mozilla/pluginreg.dat + rtl::OStringBuffer aBuf(256); + aBuf.append( pHome ); + aBuf.append( "/.mozilla" ); + CheckPluginRegistryFiles( aBuf.makeStringAndClear(), aPlugins ); + + // create return value + aDescriptions = Sequence( aPlugins.size() ); +#if OSL_DEBUG_LEVEL > 1 + fprintf( stderr, "found %d plugins\n", (int)aPlugins.size() ); +#endif + list::iterator iter; + for( iter = aPlugins.begin(), i=0; iter != aPlugins.end(); ++iter ,i++ ) + { + aDescriptions.getArray()[ i ] = **iter; + delete *iter; + } + aPlugins.clear(); + bHavePlugins = sal_True; + } + return aDescriptions; +} --- a/main/extensions/source/plugin/util/makefile.mk +++ a/main/extensions/source/plugin/util/makefile.mk @@ -0,0 +1,113 @@ +#************************************************************** +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# +#************************************************************** + + +PRJ=..$/..$/.. + +PRJNAME=extensions +TARGET=pl +TARGETTYPE=GUI + +# --- Settings ----------------------------------------------------- + +.INCLUDE : settings.mk + +# --- Files -------------------------------------------------------- + +.IF "$(WITH_MOZILLA)" != "NO" + +LIB1TARGET = $(SLB)$/plall.lib +LIB1FILES = \ + $(SLB)$/plbase.lib \ + $(SHL1LINKLIB) + +.IF "$(GUI)" == "UNX" +.IF "$(GUIBASE)"=="aqua" +.IF "$(WITH_MOZILLA)"=="YES" +SHL1LINKLIB = $(SLB)$/plaqua.lib +.ENDIF +.ELSE +SHL1LINKLIB = $(SLB)$/plunx.lib +.ENDIF # $(GUIBASE)==aqua +.IF "$(OS)" == "SOLARIS" +SHL1OWNLIBS = -lsocket +.ENDIF # SOLARIS +.ENDIF # UNX + +.IF "$(GUI)" == "WNT" +SHL1LINKLIB = $(SLB)$/plwin.lib +SHL1OWNLIBS = \ + $(VERSIONLIB) \ + $(OLE32LIB) \ + $(ADVAPI32LIB) +.ENDIF # WNT + +SHL1TARGET= $(TARGET)$(DLLPOSTFIX) +SHL1IMPLIB= i$(TARGET) + +SHL1VERSIONMAP=$(SOLARENV)/src/component.map +SHL1DEF=$(MISC)$/$(SHL1TARGET).def +DEF1NAME=$(SHL1TARGET) + +SHL1LIBS=$(LIB1TARGET) + +.IF "$(OS)"=="MACOSX" +SHL1STDLIBS= \ + $(LIBSTLPORT) \ + $(TKLIB) +.ELSE +SHL1STDLIBS= \ + $(TKLIB) +.ENDIF + +SHL1STDLIBS+= \ + $(VCLLIB) \ + $(SVLLIB) \ + $(UNOTOOLSLIB) \ + $(TOOLSLIB) \ + $(VOSLIB) \ + $(UCBHELPERLIB) \ + $(CPPUHELPERLIB) \ + $(CPPULIB) \ + $(SALLIB) + +.IF "$(GUIBASE)"=="unx" +SHL1STDLIBS+=$(X11LINK_DYNAMIC) +.ENDIF + +SHL1STDLIBS+=$(SHL1OWNLIBS) + +.ENDIF # $(WITH_MOZILLA) != "NO" + +# --- Targets ------------------------------------------------------ + +.INCLUDE : target.mk + + + + +ALLTAR : $(MISC)/pl.component + +$(MISC)/pl.component .ERRREMOVE : $(SOLARENV)/bin/createcomponent.xslt \ + pl.component + $(XSLTPROC) --nonet --stringparam uri \ + '$(COMPONENTPREFIX_BASIS_NATIVE)$(SHL1TARGETN:f)' -o $@ \ + $(SOLARENV)/bin/createcomponent.xslt pl.component --- a/main/extensions/source/plugin/util/makefile.pmk +++ a/main/extensions/source/plugin/util/makefile.pmk @@ -0,0 +1,44 @@ +#************************************************************** +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# +#************************************************************** + + +NOUNODOC=true + +.INCLUDE : settings.mk + +.IF "$(SYSTEM_MOZILLA)" == "YES" +CFLAGS+=-DSYSTEM_MOZILLA +PKGCONFIG_MODULES+=$(MOZ_FLAVOUR)-plugin +.ENDIF + +.IF "$(GUIBASE)" == "unx" && "$(ENABLE_GTK)" == "TRUE" +CDEFS+=-DENABLE_GTK +PKGCONFIG_MODULES+=gtk+-2.0 gthread-2.0 +.ENDIF + +.IF "$(GUIBASE)" == "aqua" +CFLAGS += -I$(FRAMEWORKSHOME)/ApplicationServices.framework/Versions/Current/Frameworks/QD.framework/Headers\ + -I$(FRAMEWORKSHOME)/Carbon.framework/Versions/Current/Frameworks/HIToolbox.framework/Versions/Current/Headers +.ENDIF + +.IF "$(PKGCONFIG_MODULES)" != "" +.INCLUDE : pkg_config.mk +.ENDIF --- a/main/extensions/source/plugin/util/pl.component +++ a/main/extensions/source/plugin/util/pl.component @@ -0,0 +1,33 @@ + + + + + + + + + + + + + --- a/main/extensions/source/plugin/win/makefile.mk +++ a/main/extensions/source/plugin/win/makefile.mk @@ -0,0 +1,61 @@ +#************************************************************** +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# +#************************************************************** + + + +PRJ=..$/..$/.. + +PRJNAME=extensions +TARGET=plwin +ENABLE_EXCEPTIONS=TRUE + +# --- Settings ----------------------------------------------------- +.IF "$(GUI)" == "WNT" + +.INCLUDE : ..$/util$/makefile.pmk + +INCPRE+=-I$(SOLARINCDIR)$/mozilla$/plugin +.IF "$(SOLAR_JAVA)" != "" +INCPRE+=-I$(SOLARINCDIR)$/mozilla$/java +INCPRE+=-I$(SOLARINCDIR)$/mozilla$/nspr +CDEFS+=-DOJI +.ENDIF + +# --- Types ------------------------------------- + +.IF "$(WITH_MOZILLA)" != "NO" + +#UNOUCROUT=$(OUT)$/inc$/$(PRJNAME) +#INCPRE+=$(UNOUCROUT) + +# --- Types ------------------------------------- + +SLOFILES = $(SLO)$/winmgr.obj \ + $(SLO)$/sysplug.obj + +.ENDIF # $(WITH_MOZILLA) != "NO" +.ENDIF + +# ------------------------------------------------------------------ + + +.INCLUDE : target.mk + --- a/main/extensions/source/plugin/win/sysplug.cxx +++ a/main/extensions/source/plugin/win/sysplug.cxx @@ -0,0 +1,439 @@ +/************************************************************** + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + *************************************************************/ + + + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_extensions.hxx" + +#include + +#pragma warning (push,1) +#pragma warning (disable:4005) + + #include + + #include + #include + #include + #include + #include + #include + + #include + +#pragma warning (pop) + +#include +#include +#include + + +extern NPNetscapeFuncs aNPNFuncs; + +#include + +using namespace rtl; + +#if OSL_DEBUG_LEVEL > 1 +void TRACE( char const * s ); +void TRACEN( char const * s, long n ); +#else +#define TRACE(x) +#define TRACEN(x,n) +#endif + + +//-------------------------------------------------------------------------------------------------- +PluginComm_Impl::PluginComm_Impl( const OUString& /*rMIME*/, const OUString& rName, HWND /*hWnd*/ ) + : PluginComm( OUStringToOString( rName, RTL_TEXTENCODING_MS_1252 ) ) +{ + // initialize plugin function table + memset( &_NPPfuncs, 0, sizeof( _NPPfuncs ) ); +#ifdef UNICODE + _plDLL = ::LoadLibrary( rName.getStr() ); +#else + OString aStr( OUStringToOString( rName, RTL_TEXTENCODING_MS_1252 ) ); + _plDLL = ::LoadLibrary( aStr.getStr() ); +#endif + DBG_ASSERT( _plDLL, "### loading plugin dll failed!" ); + + NPError nErr = NPERR_NO_ERROR; + NPError (WINAPI * pEntry)( NPPluginFuncs* ); + retrieveFunction( _T("NP_GetEntryPoints"), (void**)&pEntry ); + + _NPPfuncs.size = sizeof( _NPPfuncs ); + _NPPfuncs.version = 0; + nErr = (*pEntry)( &_NPPfuncs ); + + DBG_ASSERT( nErr == NPERR_NO_ERROR, "### NP_GetEntryPoints() failed!" ); + DBG_ASSERT( (_NPPfuncs.version >> 8) >= NP_VERSION_MAJOR, + "### version failure!" ); + + m_eCall = eNP_Initialize; + execute(); +} + +//-------------------------------------------------------------------------------------------------- +PluginComm_Impl::~PluginComm_Impl() +{ + if (_plDLL) + { +// NPP_Shutdown(); + + NPError (WINAPI * pShutdown)(); + if (retrieveFunction( _T("NP_Shutdown"), (void**)&pShutdown )) + { + NPError nErr = (*pShutdown)(); (void)nErr; + DBG_ASSERT( nErr == NPERR_NO_ERROR, "### NP_Shutdown() failed!" ); + } + + BOOL bRet = (BOOL)::FreeLibrary( _plDLL ); (void)bRet; + DBG_ASSERT( bRet, "### unloading plugin dll failed!" ); + _plDLL = NULL; + } +} + +//-------------------------------------------------------------------------------------------------- +BOOL PluginComm_Impl::retrieveFunction( TCHAR* pName, void** ppFunc ) const +{ + if( ! _plDLL ) + return FALSE; + + *ppFunc = (void*)::GetProcAddress( _plDLL, pName ); + + return (*ppFunc != NULL); +} + +//-------------------------------------------------------------------------------------------------- + +long PluginComm_Impl::doIt() +{ + long nRet = 0; + switch( m_eCall ) + { + case eNP_Initialize: + { + TRACE( "eNP_Initialize" ); + NPError (WINAPI * pInit)( NPNetscapeFuncs* ); + if ((_NPPfuncs.version >> 8) >= NP_VERSION_MAJOR && + (retrieveFunction( _T("NP_Initialize"), (void**)&pInit ) || + retrieveFunction( _T("NP_PluginInit"), (void**)&pInit ))) + { + nRet = (*pInit)( &aNPNFuncs ); + } + else + { + nRet = NPERR_GENERIC_ERROR; + } + DBG_ASSERT( nRet == NPERR_NO_ERROR, "### NP_Initialize() failed!" ); + } + break; + case eNPP_Destroy: + TRACE( "eNPP_Destroy" ); + nRet = (_NPPfuncs.destroy + ? (*_NPPfuncs.destroy)( + (NPP)m_aArgs[0], + (NPSavedData**)m_aArgs[1] ) + : NPERR_GENERIC_ERROR); + break; + case eNPP_DestroyStream: + TRACE( "eNPP_DestroyStream" ); + nRet = (_NPPfuncs.destroystream + ? (*_NPPfuncs.destroystream)( + (NPP)m_aArgs[0], + (NPStream*)m_aArgs[1], + (NPError)(sal_IntPtr)m_aArgs[2] ) + : NPERR_GENERIC_ERROR); + break; + case eNPP_New: + TRACE( "eNPP_New" ); + nRet = (_NPPfuncs.newp + ? (*_NPPfuncs.newp)( + (NPMIMEType)m_aArgs[0], + (NPP)m_aArgs[1], + (uint16)(sal_IntPtr)m_aArgs[2], + (int16)(sal_IntPtr)m_aArgs[3], + (char**)m_aArgs[4], + (char**)m_aArgs[5], + (NPSavedData*)m_aArgs[6] ) + : NPERR_GENERIC_ERROR); + break; + case eNPP_NewStream: + TRACE( "eNPP_NewStream" ); + nRet = (_NPPfuncs.newstream + ? (*_NPPfuncs.newstream)( + (NPP)m_aArgs[0], + (NPMIMEType)m_aArgs[1], + (NPStream*)m_aArgs[2], + (NPBool)(sal_IntPtr)m_aArgs[3], + (uint16*)m_aArgs[4] ) + : NPERR_GENERIC_ERROR); + break; + case eNPP_Print: + TRACE( "eNPP_Print" ); + if (_NPPfuncs.print) + (*_NPPfuncs.print)( + (NPP)m_aArgs[0], + (NPPrint*)m_aArgs[1] ); + break; + case eNPP_SetWindow: + { + TRACE( "eNPP_SetWindow" ); + nRet = (_NPPfuncs.setwindow + ? (*_NPPfuncs.setwindow)( + (NPP)m_aArgs[0], + (NPWindow*)m_aArgs[1] ) + : NPERR_GENERIC_ERROR); + break; + } + case eNPP_StreamAsFile: + TRACE( "eNPP_StreamAsFile" ); + if (_NPPfuncs.asfile) + (*_NPPfuncs.asfile)( + (NPP)m_aArgs[0], + (NPStream*)m_aArgs[1], + (char*)m_aArgs[2] ); + break; + case eNPP_URLNotify: + TRACE( "eNPP_URLNotify" ); + if (_NPPfuncs.urlnotify) + (*_NPPfuncs.urlnotify)( + (NPP)m_aArgs[0], + (char*)m_aArgs[1], + (NPReason)(sal_IntPtr)m_aArgs[2], + m_aArgs[3] ); + break; + case eNPP_Write: + TRACEN( "eNPP_Write n=", (int32)m_aArgs[3] ); + nRet = (_NPPfuncs.write + ? (*_NPPfuncs.write)( + (NPP)m_aArgs[0], + (NPStream*)m_aArgs[1], + (int32)m_aArgs[2], + (int32)m_aArgs[3], + m_aArgs[4] ) + : 0); + break; + case eNPP_WriteReady: + TRACE( "eNPP_WriteReady" ); + nRet = (_NPPfuncs.writeready + ? (*_NPPfuncs.writeready)( + (NPP)m_aArgs[0], + (NPStream*)m_aArgs[1] ) + : 0); + break; + case eNPP_GetValue: + TRACE( "eNPP_GetValue" ); + nRet = (_NPPfuncs.getvalue + ? (*_NPPfuncs.getvalue)( + (NPP)m_aArgs[0], + (NPPVariable)(int)m_aArgs[1], + m_aArgs[2] ) + : NPERR_GENERIC_ERROR); + break; + case eNPP_SetValue: + TRACE( "eNPP_SetValue" ); + nRet = (_NPPfuncs.setvalue + ? (*_NPPfuncs.setvalue)( + (NPP)m_aArgs[0], + (NPNVariable)(int)m_aArgs[1], + m_aArgs[2] ) + : NPERR_GENERIC_ERROR); + break; + case eNPP_Shutdown: + { + TRACE( "eNPP_Shutdown" ); + NPP_ShutdownUPP pFunc; + if (retrieveFunction( _T("NPP_Shutdown"), (void**)&pFunc )) + (*pFunc)(); + } + break; + case eNPP_Initialize: + TRACE( "eNPP_Initialize" ); + OSL_ENSURE( false, "NPP_Initialize: not implemented!" ); + break; + case eNPP_GetJavaClass: + TRACE( "eNPP_GetJavaClass" ); + OSL_ENSURE( false, "NPP_GetJavaClass: not implemented!" ); + break; + } + return nRet; +} + +//-------------------------------------------------------------------------------------------------- +NPError PluginComm_Impl::NPP_Destroy( NPP instance, NPSavedData** save ) +{ + DBG_ASSERT( _NPPfuncs.destroy, "### NPP_Destroy(): null pointer in NPP functions table!" ); + m_eCall = eNPP_Destroy; + m_aArgs[0] = (void*)instance; + m_aArgs[1] = (void*)save; + return (NPError)execute(); +} + +//-------------------------------------------------------------------------------------------------- +NPError PluginComm_Impl::NPP_DestroyStream( NPP instance, NPStream* stream, NPError reason ) +{ + DBG_ASSERT( _NPPfuncs.destroystream, "### NPP_DestroyStream(): null pointer in NPP functions table!" ); + m_eCall = eNPP_DestroyStream; + m_aArgs[0] = (void*)instance; + m_aArgs[1] = (void*)stream; + m_aArgs[2] = (void*)reason; + return (NPError)execute(); +} + +//-------------------------------------------------------------------------------------------------- +NPError PluginComm_Impl::NPP_New( NPMIMEType pluginType, NPP instance, uint16 mode, int16 argc, + char* argn[], char* argv[], NPSavedData *saved ) +{ + DBG_ASSERT( _NPPfuncs.newp, "### NPP_New(): null pointer in NPP functions table!" ); + m_eCall = eNPP_New; + m_aArgs[0] = (void*)pluginType; + m_aArgs[1] = (void*)instance; + m_aArgs[2] = (void*)mode; + m_aArgs[3] = (void*)argc; + m_aArgs[4] = (void*)argn; + m_aArgs[5] = (void*)argv; + m_aArgs[6] = (void*)saved; + return (NPError)execute(); +} + +//-------------------------------------------------------------------------------------------------- +NPError PluginComm_Impl::NPP_NewStream( NPP instance, NPMIMEType type, NPStream* stream, + NPBool seekable, uint16* stype ) +{ + DBG_ASSERT( _NPPfuncs.newstream, "### NPP_NewStream(): null pointer in NPP functions table!" ); + m_eCall = eNPP_NewStream; + m_aArgs[0] = (void*)instance; + m_aArgs[1] = (void*)type; + m_aArgs[2] = (void*)stream; + m_aArgs[3] = (void*)seekable; + m_aArgs[4] = (void*)stype; + return (NPError)execute(); +} + +//-------------------------------------------------------------------------------------------------- +void PluginComm_Impl::NPP_Print( NPP instance, NPPrint* platformPrint ) +{ + DBG_ASSERT( _NPPfuncs.print, "### NPP_Print(): null pointer in NPP functions table!" ); + m_eCall = eNPP_Print; + m_aArgs[0] = (void*)instance; + m_aArgs[1] = (void*)platformPrint; + execute(); +} + +//-------------------------------------------------------------------------------------------------- +NPError PluginComm_Impl::NPP_SetWindow( NPP instance, NPWindow* window ) +{ + DBG_ASSERT( _NPPfuncs.setwindow, "### NPP_SetWindow(): null pointer in NPP functions table!" ); + m_eCall = eNPP_SetWindow; + m_aArgs[0] = (void*)instance; + m_aArgs[1] = (void*)window; + return (NPError)execute(); +} + +//-------------------------------------------------------------------------------------------------- +void PluginComm_Impl::NPP_StreamAsFile( NPP instance, NPStream* stream, const char* fname ) +{ + DBG_ASSERT( _NPPfuncs.asfile, "### NPP_StreamAsFile(): null pointer in NPP functions table!" ); + m_eCall = eNPP_StreamAsFile; + m_aArgs[0] = (void*)instance; + m_aArgs[1] = (void*)stream; + m_aArgs[2] = (void*)fname; + execute(); +} + +//-------------------------------------------------------------------------------------------------- +void PluginComm_Impl::NPP_URLNotify( NPP instance, const char* url, NPReason reason, void* notifyData ) +{ + DBG_ASSERT( _NPPfuncs.urlnotify, "### NPP_URLNotify(): null pointer in NPP functions table!" ); + m_eCall = eNPP_URLNotify; + m_aArgs[0] = (void*)instance; + m_aArgs[1] = (void*)url; + m_aArgs[2] = (void*)reason; + m_aArgs[3] = notifyData; + execute(); +} + +//-------------------------------------------------------------------------------------------------- +int32 PluginComm_Impl::NPP_Write( NPP instance, NPStream* stream, int32 offset, int32 len, void* buffer ) +{ + DBG_ASSERT( _NPPfuncs.write, "### NPP_Write(): null pointer in NPP functions table!" ); + m_eCall = eNPP_Write; + m_aArgs[0] = (void*)instance; + m_aArgs[1] = (void*)stream; + m_aArgs[2] = (void*)offset; + m_aArgs[3] = (void*)len; + m_aArgs[4] = buffer; + return (NPError)execute(); +} + +//-------------------------------------------------------------------------------------------------- +int32 PluginComm_Impl::NPP_WriteReady( NPP instance, NPStream* stream ) +{ + DBG_ASSERT( _NPPfuncs.writeready, "### NPP_WriteReady(): null pointer in NPP functions table!" ); + m_eCall = eNPP_WriteReady; + m_aArgs[0] = (void*)instance; + m_aArgs[1] = (void*)stream; + return execute(); +} + +//-------------------------------------------------------------------------------------------------- +NPError PluginComm_Impl::NPP_GetValue( NPP instance, NPPVariable variable, void *ret_value ) +{ + DBG_ASSERT( _NPPfuncs.getvalue, "### NPP_GetValue(): null pointer in NPP functions table!" ); + m_eCall = eNPP_GetValue; + m_aArgs[0] = (void*)instance; + m_aArgs[1] = (void*)variable; + m_aArgs[2] = ret_value; + return (NPError)execute(); +} + +//-------------------------------------------------------------------------------------------------- +NPError PluginComm_Impl::NPP_SetValue( NPP instance, NPNVariable variable, void *set_value ) +{ + DBG_ASSERT( _NPPfuncs.setvalue, "### NPP_SetValue(): null pointer in NPP functions table!" ); + m_eCall = eNPP_SetValue; + m_aArgs[0] = (void*)instance; + m_aArgs[1] = (void*)variable; + m_aArgs[2] = set_value; + return (NPError)execute(); +} + +//-------------------------------------------------------------------------------------------------- +void * PluginComm_Impl::NPP_GetJavaClass() +{ + DBG_ERROR( "no java class available!" ); + return 0; +} + +//-------------------------------------------------------------------------------------------------- +NPError PluginComm_Impl::NPP_Initialize() +{ + return NPERR_NO_ERROR; +} + +//-------------------------------------------------------------------------------------------------- +void PluginComm_Impl::NPP_Shutdown() +{ + m_eCall = eNPP_Shutdown; + execute(); +} --- a/main/extensions/source/plugin/win/winmgr.cxx +++ a/main/extensions/source/plugin/win/winmgr.cxx @@ -0,0 +1,479 @@ +/************************************************************** + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + *************************************************************/ + + + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_extensions.hxx" + +#include "vcl/svapp.hxx" +#include "tools/fsys.hxx" +#include "tools/urlobj.hxx" +#include "osl/mutex.hxx" + +#include "rtl/string.hxx" +#include "rtl/ustring.hxx" +#include "rtl/ustrbuf.hxx" + +#include "plugin/impl.hxx" + +#pragma warning (push,1) +#pragma warning (disable:4005) + + #include "tools/prewin.h" + + #include + #include + #include + #include + #include + #include + + #include "tools/postwin.h" + +#pragma warning (pop) + +#include +#include +#include + + +using namespace rtl; +using namespace std; +using namespace osl; +using namespace com::sun::star::uno; +using namespace com::sun::star::plugin; + +typedef map< OString, OUString, less< OString > > PluginLocationMap; + + +#if OSL_DEBUG_LEVEL > 1 +#include + +static void logPlugin( OUString const & path_ ) +{ + static FILE * pFile = 0; + if (! pFile) + { + WCHAR sFile[MAX_PATH]; + if ( SUCCEEDED( SHGetFolderPathW( NULL, CSIDL_PROFILE, NULL, 0, sFile ) ) + { + if ( SUCCEEDED( StringCchCatW( sFile, MAX_PATH, L"plugins.log" ) ) ) + { + pFile = _wfopen( sFile, L"a+" ); + } + } + } + + if ( pFile ) + { + OString path( OUStringToOString( path_, RTL_TEXTENCODING_ASCII_US ) ); + fprintf( pFile, "%s\n", path.getStr() ); + } +} +#endif + +//__________________________________________________________________________________________________ +static void addPluginsFromPath( const TCHAR * pPluginsPath, PluginLocationMap & rPlugins ) +{ + // append dll name pattern we are looking for + TCHAR arPluginsPath[MAX_PATH]; + arPluginsPath[0] = 0; + + if (::rtl_str_indexOfStr( pPluginsPath, "%programfiles%" ) == 0) + { + const char * p = ::getenv( "ProgramFiles" ); + if (p) + { + ::lstrcpy( arPluginsPath, p ); + pPluginsPath += 14; + } + } + ::lstrcat( arPluginsPath, pPluginsPath ); + ::lstrcat( arPluginsPath, _T("\\") ); + + TCHAR arPluginsPattern[MAX_PATH]; + ::lstrcpy( arPluginsPattern, arPluginsPath ); + ::lstrcat( arPluginsPattern, _T("NP*.DLL") ); + + WIN32_FIND_DATA aFindData; + HANDLE hFind = ::FindFirstFile( arPluginsPattern, &aFindData ); + + while (hFind != INVALID_HANDLE_VALUE) + { + OString aName( aFindData.cFileName ); + aName.toAsciiLowerCase(); + + // no netscape default plugin anymore... + // and no double plugin dlls + if ( !aName.equals( "npnul32.dll" ) && + ! aName.equals( "npnrvp.dll" ) && + rPlugins.find( aName ) == rPlugins.end()) + { + TCHAR arComplete[MAX_PATH]; + ::lstrcpy( arComplete, arPluginsPath ); + ::lstrcat( arComplete, aFindData.cFileName ); + + OUString path( OStringToOUString( arComplete, RTL_TEXTENCODING_MS_1252 ) ); + rPlugins[ aName ] = path; +#if OSL_DEBUG_LEVEL > 1 + logPlugin( path ); +#endif + } + + if (! ::FindNextFile( hFind, &aFindData )) + break; + } + + if (hFind != INVALID_HANDLE_VALUE) + ::FindClose( hFind ); +} +//__________________________________________________________________________________________________ +static void addPluginsFromPath( const OUString & rPath, PluginLocationMap & rPlugins ) +{ + TCHAR arPluginsPath[MAX_PATH]; + DWORD dwPluginsPathSize = sizeof(arPluginsPath); + arPluginsPath[dwPluginsPathSize-1] = 0; + + OString aStr( OUStringToOString( rPath, RTL_TEXTENCODING_MS_1252 ) ); + ::strncpy( arPluginsPath, aStr.getStr(), dwPluginsPathSize ); + + addPluginsFromPath( arPluginsPath, rPlugins ); +} + + +//__________________________________________________________________________________________________ +static void add_IE_Plugins( PluginLocationMap & rPlugins ) +{ + HKEY hKey; + TCHAR arCurrent[MAX_PATH]; + DWORD dwType, dwCurrentSize = sizeof(arCurrent); + + if (::RegOpenKeyEx( HKEY_LOCAL_MACHINE, _T("Software\\Microsoft\\IE4\\SETUP"), + 0, KEY_READ, &hKey ) == ERROR_SUCCESS) + { + if (::RegQueryValueEx( hKey, _T("Path"), NULL, &dwType, + (LPBYTE)arCurrent, &dwCurrentSize ) == ERROR_SUCCESS && + (dwType == REG_SZ || dwType == REG_EXPAND_SZ)) + { + // add \\Plugins + ::lstrcat( arCurrent, _T("\\Plugins") ); + + addPluginsFromPath( arCurrent, rPlugins ); + } + ::RegCloseKey( hKey ); + } +} + +//-------------------------------------------------------------------------------------------------- +static void add_NS_keys( HKEY hKey, PluginLocationMap & rPlugins ) +{ + TCHAR value[MAX_PATH]; + DWORD dwType, size = sizeof(value); + + // 4.7 + size = sizeof(value); + if (::RegQueryValueEx( + hKey, _T("Plugins Directory"), NULL, &dwType, + (LPBYTE)value, &size ) == ERROR_SUCCESS && + (dwType == REG_SZ || dwType == REG_EXPAND_SZ)) + { + addPluginsFromPath( value, rPlugins ); + } + // 6 + size = sizeof(value); + if (::RegQueryValueEx( + hKey, _T("Install Directory"), NULL, &dwType, + (LPBYTE)value, &size ) == ERROR_SUCCESS && + (dwType == REG_SZ || dwType == REG_EXPAND_SZ)) + { + int n = size / sizeof (TCHAR); + if ('\\' != value[ n -2 ]) + { + value[ n -1 ] = '\\'; + value[ n ] = 0; + } + addPluginsFromPath( ::lstrcat( value, _T("Plugins") ), rPlugins ); + } + size = sizeof(value); + if (::RegQueryValueEx( + hKey, _T("Plugins"), NULL, &dwType, + (LPBYTE)value, &size ) == ERROR_SUCCESS && + (dwType == REG_SZ || dwType == REG_EXPAND_SZ)) + { + addPluginsFromPath( value, rPlugins ); + } +} +//-------------------------------------------------------------------------------------------------- +static void add_NS_lookupRecursive( HKEY hKey, PluginLocationMap & rPlugins ) +{ + add_NS_keys( hKey, rPlugins ); + + TCHAR keyName[MAX_PATH]; + DWORD dwIndex = 0, size = sizeof (keyName); + + while (::RegEnumKeyEx( hKey, dwIndex, keyName, &size, NULL, NULL, NULL, NULL ) == ERROR_SUCCESS) + { + size = sizeof (keyName); + HKEY hSubKey; + if (::RegOpenKeyEx( hKey, keyName, 0, KEY_READ, &hSubKey ) == ERROR_SUCCESS) + { + add_NS_lookupRecursive( hSubKey, rPlugins ); + ::RegCloseKey( hSubKey ); + } + ++dwIndex; + } +} +//__________________________________________________________________________________________________ +static void add_MozPlugin( HKEY hKey, PluginLocationMap & rPlugins ) +{ + TCHAR value[MAX_PATH]; + DWORD dwType, size = sizeof(value); + + size = sizeof(value); + if (::RegQueryValueEx( + hKey, _T("Path"), NULL, &dwType, + (LPBYTE)value, &size ) == ERROR_SUCCESS && + (dwType == REG_SZ || dwType == REG_EXPAND_SZ)) + { + OUString aUPath( OStringToOUString( value, RTL_TEXTENCODING_MS_1252 ) ); + INetURLObject aURL( aUPath ); + OString aName( OUStringToOString( aURL.GetName().toAsciiLowerCase(), RTL_TEXTENCODING_MS_1252 ) ); + + // no netscape default plugin anymore... + // and no double plugin dlls + if ( !aName.equals( "npnul32.dll" ) && + ! aName.equals( "npnrvp.dll" ) && + rPlugins.find( aName ) == rPlugins.end()) + { + rPlugins[ aName ] = aUPath; +#if OSL_DEBUG_LEVEL > 1 + logPlugin( aUPath ); +#endif + } + } +} +static void add_MozillaPlugin( HKEY hKey, PluginLocationMap & rPlugins ) +{ + TCHAR keyName[MAX_PATH]; + DWORD dwIndex = 0, size = sizeof (keyName); + + while (::RegEnumKeyEx( hKey, dwIndex, keyName, &size, NULL, NULL, NULL, NULL ) == ERROR_SUCCESS) + { + size = sizeof (keyName); + HKEY hSubKey; + if (::RegOpenKeyEx( hKey, keyName, 0, KEY_READ, &hSubKey ) == ERROR_SUCCESS) + { + add_MozPlugin( hSubKey, rPlugins ); + ::RegCloseKey( hSubKey ); + } + ++dwIndex; + } +} +//__________________________________________________________________________________________________ +static void add_NS_Plugins( PluginLocationMap & rPlugins ) +{ + HKEY hKey; + // Netscape + if (::RegOpenKeyEx( + HKEY_LOCAL_MACHINE, _T("Software\\Netscape"), + 0, KEY_READ, &hKey ) == ERROR_SUCCESS) + { + add_NS_lookupRecursive( hKey, rPlugins ); + ::RegCloseKey( hKey ); + } + // Mozilla + if (::RegOpenKeyEx( + HKEY_LOCAL_MACHINE, _T("Software\\Mozilla"), + 0, KEY_READ, &hKey ) == ERROR_SUCCESS) + { + add_NS_lookupRecursive( hKey, rPlugins ); + ::RegCloseKey( hKey ); + } + // Mozilla - plugins + if (::RegOpenKeyEx( + HKEY_LOCAL_MACHINE, _T("Software\\MozillaPlugins"), + 0, KEY_READ, &hKey ) == ERROR_SUCCESS) + { + add_MozillaPlugin( hKey, rPlugins ); + ::RegCloseKey( hKey ); + } +} + +//__________________________________________________________________________________________________ +static void add_SO_Plugins( PluginLocationMap & rPlugins ) +{ + const Sequence< OUString > & rPaths = PluginManager::getAdditionalSearchPaths(); + + const OUString * pPaths = rPaths.getConstArray(); + for ( UINT32 nPos = rPaths.getLength(); nPos--; ) + { + addPluginsFromPath( pPaths[nPos], rPlugins ); + } +} + +//__________________________________________________________________________________________________ +Sequence< PluginDescription > XPluginManager_Impl::impl_getPluginDescriptions(void) throw() +{ + Guard< Mutex > aGuard( Mutex::getGlobalMutex() ); + static Sequence s_aDescriptions( 0 ); + static bool s_bInit = FALSE; + + if (! s_bInit) + { + // collect all distinct plugin dlls + PluginLocationMap aPlugins; + add_SO_Plugins( aPlugins ); + add_NS_Plugins( aPlugins ); + add_IE_Plugins( aPlugins ); + + // collect mime types of plugin dlls + for ( PluginLocationMap::iterator iPos( aPlugins.begin() ); + iPos != aPlugins.end(); + ++iPos ) + { + TCHAR arFileName[MAX_PATH]; + DWORD dwDummy, dwSize; + + // DLL name + OUString aName( (*iPos).second.getStr() ); + + OString aStr( OUStringToOString( aName, RTL_TEXTENCODING_MS_1252 ) ); + ::strcpy( arFileName, aStr.getStr() ); + dwSize = ::GetFileVersionInfoSize( arFileName, &dwDummy ); + + if ( !dwSize ) + continue; + + char * pVersionData = new char[dwSize]; + if (pVersionData && ::GetFileVersionInfo( arFileName, 0, dwSize, pVersionData )) + { + // optional comment + OUString aComment; + + TCHAR * pInfo = NULL, * pInfo2 = NULL; + UINT nSize = 0; + if (::VerQueryValue( pVersionData, _T("\\StringFileInfo\\040904E4\\ProductName"), + (void**)&pInfo, &nSize ) && pInfo) + { + aComment.operator=( OStringToOUString( OString(pInfo), RTL_TEXTENCODING_MS_1252 ) ); + } + + // mandatory mime type and file extensions + if (::VerQueryValue( pVersionData, _T("\\StringFileInfo\\040904E4\\MIMEType"), + (void**)&pInfo, &nSize ) && pInfo && + ::VerQueryValue( pVersionData, _T("\\StringFileInfo\\040904E4\\FileExtents"), + (void**)&pInfo2, &nSize ) && pInfo2) + { + OString aStr2( pInfo2 ); + OString aExt( aStr2 ); + OString aStr( pInfo ); + OString aMIME( aStr ); + aMIME.trim(); + + // count mime tokens + USHORT nToken = 0; + if (aMIME.getLength()) + { + ++nToken; + for ( sal_Int32 n = aMIME.getLength(); n--; ) + { + if (aMIME[ n ] == '|') + { + ++nToken; + } + } + } + sal_Int32 nIndex = 0, nIndex2 = 0; + + UINT32 nStart = s_aDescriptions.getLength(); + s_aDescriptions.realloc( nStart + nToken ); + PluginDescription* pDescriptions = s_aDescriptions.getArray(); + // for every MIME Type + sal_Int32 nTok = 0; + while (true) + { + if (nIndex < 0 || nIndex2 < 0) + break; + + PluginDescription & rDescr = pDescriptions[nStart+nTok]; + OString aMIMEToken( aMIME.getToken( 0, '|', nIndex ) ); + OString aExtToken2( aExt.getToken( 0, '|', nIndex2 ) ); + if( aMIMEToken.getLength() == 0 || aExtToken2.getLength() == 0 ) + continue; + + rDescr.Mimetype = OUString( + aMIMEToken.getStr(), aMIMEToken.getLength(), RTL_TEXTENCODING_MS_1252 ); + if (! rDescr.Mimetype.getLength()) + break; + + OUString aExtToken( aExtToken2.getStr(), aExtToken2.getLength(), RTL_TEXTENCODING_MS_1252 ); + rDescr.PluginName = aName; + rDescr.Description = aComment; + + sal_Int32 nPos = 0, nLen = aExtToken.getLength(); + OUString aExtensions( OUString::createFromAscii( nLen ? "*." : "*.*" ) ); + + for ( ; nPos < nLen; ++nPos ) + { + sal_Unicode c = aExtToken[nPos]; + switch (c) + { + case ',': + case ';': + aExtensions += OUString::createFromAscii( ";*." ); + case ' ': + break; + case '*': + if (nPos < (nLen-1) && aExtToken[ nPos+1 ] == '.') + { + ++nPos; + break; + } + default: + aExtensions += OUString( &c, 1 ); + } + } + rDescr.Extension = aExtensions; + + ++nTok; + } + + if (nToken != nTok) + { + s_aDescriptions.realloc( nTok ); + } + } +#if OSL_DEBUG_LEVEL > 1 + else + DBG_ERROR( "### cannot get MIME type or extensions!" ); +#endif + } + if (pVersionData) + delete[] pVersionData; + } + + s_bInit = TRUE; + } + return s_aDescriptions; +} + + --- a/main/postprocess/packcomponents/makefile.mk +++ a/main/postprocess/packcomponents/makefile.mk @@ -288,6 +288,7 @@ my_components += ldapbe2 .IF "$(WITH_MOZILLA)" != "NO" my_components += \ + pl \ xmlsecurity \ xsec_fw \ xsec_xmlsec --- a/main/scp2/source/ooo/file_library_ooo.scp +++ a/main/scp2/source/ooo/file_library_ooo.scp @@ -1144,6 +1144,12 @@ STD_LIB_FILE(gid_File_Lib_DeploymentMisc, deplmisc) STD_LIB_FILE(gid_File_Lib_DeploymentMisc, deploymentmisc) #endif + +#ifndef WITHOUT_MOZILLA +STD_LIB_FILE( gid_File_Lib_Pl , pl) +#endif + + #ifdef OS2 STD_LIB_FILE( gid_File_Lib_Preload, preloadg) #else --