NPAPI を使用して Linux アプリケーションに Flash SWF ファイルを埋め込んでいます。すべて正常に動作しますが、Flash が「fscommand」を呼び出すと、セキュリティ サンドボックス違反が発生します。いくつかの Linux ディストリビューションといくつかのバージョンの Flash Player (9、10、11) でこのプログラムを試しましたが、うまくいきませんでした。
これが Linux プラットフォームの Flash Player の制限であるかどうかは誰にもわかりませんか?
この投稿SWF 終了時に gtk アプリケーションを閉じる (NPAPI)では、Javascript イベントを受け取ることができたようです。
これは私が使用しているコードです:
#include <stdio.h>
#include <stdlib.h>
#include <dlfcn.h>
#include <string.h>
#include <unistd.h>
#include <ctype.h>
#include <gtk/gtk.h>
#include <gdk/gdkx.h>
//#include "npupp.h"
#include "npapi.h"
#include "npfunctions.h"
//#ifdef __i386__
#define FLASH_PLUGIN_SO "./flash/libflashplayer32.so"
//#else
//#define FLASH_PLUGIN_SO "./flash/libflashplayer64.so"
//#endif
#define PR_TRUE 1
#define PR_FALSE 0
#define WINDOW_XSIZE 1600/2
#define WINDOW_YSIZE 900/2
#define NO_IDENTIFIER ((NPIdentifier)0)
#define SPECIAL_IDENTIFIER 0x0FEEBBCC
#define SPECIAL_METHOD_NAME "swhxCall"
#define FLASH_REQUEST "__flash__request"
#define FSCMD "_DoFSCommand"
#define INVOKE_RESPONSE "<invoke name=\"%s\" returntype=\"javascript\"><arguments><null/></arguments></invoke>"
typedef intptr_t int_val;
void *flash_plugin_handle;
NPNetscapeFuncs browserFuncs;
NPPluginFuncs pluginFuncs;
GtkWidget *main_window;
char* URL;
NPStream * stream;
const char * uagent = "Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2.13) Gecko/20101206 Ubuntu/10.10 (maverick) Firefox/3.6.13";
NPError (*iNP_Initialize)(NPNetscapeFuncs* bFuncs, NPPluginFuncs* pFuncs);
NPError (*iNP_Shutdown)();
char* (*iNP_GetMIMEDescription)();
// --- Property IDs
static char **np_ids = NULL;
static int_val np_id_count = 0;
static NPIdentifier resolveNPId( const char *id ) {
int_val i;
for(i=0;i<np_id_count;i++)
if( strcmp(np_ids[i],id) == 0 )
return (NPIdentifier)(i+1);
if( strcmp(id,SPECIAL_METHOD_NAME) == 0 )
return (NPIdentifier)SPECIAL_IDENTIFIER;
return NO_IDENTIFIER;
}
static NPIdentifier addNPId( const char *id ) {
NPIdentifier newid = resolveNPId(id);
if( newid == NO_IDENTIFIER ) {
np_id_count++;
printf("New npid added: %i == %s\n",np_id_count, id);
np_ids = realloc(np_ids,np_id_count*sizeof(char*));
np_ids[np_id_count-1] = strdup(id);
return (NPIdentifier)np_id_count;
}
return newid;
}
static const char *getNPId( NPIdentifier id ) {
int_val index = ((int_val)id)-1;
if( index >= 0 && index < np_id_count )
return np_ids[index];
if( id == (NPIdentifier)SPECIAL_IDENTIFIER )
return SPECIAL_METHOD_NAME;
return NULL;
}
static int matchNPId(NPIdentifier id, const char *str) {
const char *strid = getNPId(id);
return ( strid != NULL && strcmp(strid,str) == 0 );
}
void freeNPIds() {
while( np_id_count )
free(np_ids[--np_id_count]);
free(np_ids);
}
static bool NPN_InvokeProc( NPP npp, NPObject *npobj, NPIdentifier methodName, const NPVariant *args, uint32_t argCount, NPVariant *result ) ;
static bool NPN_InvokeDefaultProc( NPP npp, NPObject *npobj, const NPVariant *args, uint32_t argCount, NPVariant *result ) ;
static bool NPN_GetPropertyProc( NPP npp, NPObject *npobj, NPIdentifier propertyName, NPVariant *result ) ;
static bool NPN_SetPropertyProc( NPP npp, NPObject *npobj, NPIdentifier propertyName, const NPVariant *value ) ;
static bool NPN_RemovePropertyProc( NPP npp, NPObject *npobj, NPIdentifier propertyName ) ;
static bool NPN_HasPropertyProc( NPP npp, NPObject *npobj, NPIdentifier propertyName ) ;
static bool NPN_HasMethodProc( NPP npp, NPObject *npobj, NPIdentifier methodName ) ;
static NPObject *NPN_CreateObjectProc( NPP npp, NPClass *aClass );
static NPObject *NPN_RetainObjectProc( NPObject *npobj );
// Window class;
static NPClass __gen_class =
{ NP_CLASS_STRUCT_VERSION
, (NPAllocateFunctionPtr) malloc
, (NPDeallocateFunctionPtr) free
, 0
, (NPHasMethodFunctionPtr) NPN_HasMethodProc
, (NPInvokeFunctionPtr) NPN_InvokeProc
, (NPInvokeDefaultFunctionPtr)NPN_InvokeDefaultProc
, (NPHasPropertyFunctionPtr) NPN_HasPropertyProc
, (NPGetPropertyFunctionPtr) NPN_GetPropertyProc
, (NPSetPropertyFunctionPtr) NPN_SetPropertyProc
, (NPRemovePropertyFunctionPtr) NPN_RemovePropertyProc
};
static NPObject __window = { &__gen_class, 1 };
static NPObject __location = { &__gen_class, 1};
static NPObject __top = { &__gen_class, 1 };
static NPObject __top_location = { &__gen_class, 1 };
static void traceObjectOnCall(const char *f, NPObject *o){
if (o == &__top) printf("DOM object 'top': %s\n",f);
else if (o == &__window) printf("DOM object 'window': %s\n",f);
else if (o == &__location) printf("DOM object 'location': %s\n",f);
else if (o == &__top_location) printf("DOM object 'top.location': %s\n",f);
}
static void checkError(const char* str, NPError err) {
if(err == NPERR_NO_ERROR)
printf("[+] %s: success\n", str);
else
printf("[-] %s: failed (%d)\n", str, err);
fflush (stdout);
}
void* loadFlashPluginSo() {
void *handle;
handle = dlopen(FLASH_PLUGIN_SO, RTLD_LAZY | RTLD_LOCAL);
if(!handle) {
fprintf(stderr, "[-] error loading libflasplayer.so: %s\n", dlerror());
exit(1);
}
puts("[+] loaded libflashplayer.so");
return handle;
}
void* loadSymbol(void *handle, const char *name) {
char *error;
void *ret;
ret = dlsym(handle, name);
if((error = dlerror()) != NULL) {
fprintf(stderr, "[-] error loading symbol %s: %s\n", name, error);
exit(1);
} else {
printf("[+] loaded symbol %s, address: %p\n", name, ret);
}
return ret;
}
void loadNPEntryPoints(void *handle) {
iNP_Initialize=(NPError (*)(NPNetscapeFuncs* bFuncs, NPPluginFuncs* pFuncs))loadSymbol(handle, "NP_Initialize");
iNP_Shutdown=(NPError (*)())loadSymbol(handle, "NP_Shutdown");
iNP_GetMIMEDescription = (char*(*)())loadSymbol(handle,"NP_GetMIMEDescription");
}
void printPluginEntrypoints(NPPluginFuncs* pFuncs) {
printf("[*] NPP struct:\n");
printf("\t- NPP_size: %8d\n",pFuncs->size);
printf("\t- NPP_version: %8d\n",pFuncs->version);
printf("\t- NPP_NewProcPtr: %p\n", pFuncs->newp);
printf("\t- NPP_DestroyProcPtr: %p\n", pFuncs->destroy);
printf("\t- NPP_SetWindowProcPtr: %p\n", pFuncs->setwindow);
printf("\t- NPP_NewStreamProcPtr: %p\n", pFuncs->newstream);
printf("\t- NPP_DestroyStreamProcPtr: %p\n", pFuncs->destroystream);
printf("\t- NPP_StreamAsFileProcPtr: %p\n", pFuncs->asfile);
printf("\t- NPP_WriteReadyProcPtr: %p\n", pFuncs->writeready);
printf("\t- NPP_WriteProcPtr: %p\n", pFuncs->write);
printf("\t- NPP_PrintProcPtr: %p\n", pFuncs->print);
printf("\t- NPP_HandleEventProcPtr: %p\n", pFuncs->event);
printf("\t- NPP_URLNotifyProcPtr: %p\n", pFuncs->urlnotify);
printf("\t- javaClass: %p\n", pFuncs->javaClass);
printf("\t- NPP_GetValueProcPtr: %p\n", pFuncs->getvalue);
printf("\t- NPP_SetValueProcPtr: %p\n", pFuncs->setvalue);
}
NPError NPN_SetValueProc(NPP instance, NPPVariable variable, void *value)
{
switch(variable) {
case NPPVpluginWindowBool:
printf( "NPPVpluginWindowBool - %p\n", value);
break;
default:
printf( "SetValue %i\n", variable );
break;
}
return NPERR_NO_ERROR;
}
NPError NPN_GetValueProc(NPP instance, NPNVariable variable, void *ret_value) {
printf("[D] NPN_GetValueProc instance:%p, variable:%d, abi_mask:%d\n", instance, variable, 0);
switch (variable) {
case NPNVSupportsXEmbedBool:
*((int*)ret_value)= PR_TRUE;
break;
case NPNVToolkit:
*((int*)ret_value)= NPNVGtk2;
break;
case NPNVnetscapeWindow:
*((int*)ret_value)= PR_TRUE;
break;
default:
*((int*)ret_value)=PR_FALSE;
break;
}
return NPERR_NO_ERROR;
}
const char* NPN_UserAgentProc(NPP instance) {
return uagent;
}
static void Status_( NPP instance, const char* message ) {
printf( "Status\n" );
}
uint32_t MemFlush( uint32_t size ) {
return 0;
}
void ReloadPlugins( NPBool reloadPages ) {
}
void * GetJavaEnv(void) {
return NULL;
}
void * GetJavaPeer( NPP instance ) {
return NULL;
}
NPIdentifier NPN_GetStringIdentifierProc(const NPUTF8* name) {
return addNPId(name);
}
void GetStringIdentifiers( const NPUTF8 **names, int32_t nameCount, NPIdentifier *identifiers ) {
}
NPIdentifier GetIntIdentifier( int32_t intid ) {
return NO_IDENTIFIER;
}
bool IdentifierIsString( NPIdentifier id ) {
return getNPId(id) != NULL;
}
NPUTF8* UTF8FromIdentifier( NPIdentifier identifier ) {
const char *result = getNPId(identifier);
return result ? strdup(result) : NULL;
}
int32_t IntFromIdentifier( NPIdentifier id ) {
return 0;
}
static gboolean plug_removed_cb (GtkWidget *widget, gpointer data) {
printf("[!] plug_removed_cb\n");
return TRUE;
}
static void socket_unrealize_cb(GtkWidget *widget, gpointer data) {
printf("[!] socket_unrealize_cb\n");
}
static NPWindow * npwindow_construct (GtkWidget *widget) {
NPWindow *npwindow;
NPSetWindowCallbackStruct *ws_info = NULL;
GdkWindow *parent_win = widget->window;
GtkWidget *socketWidget = gtk_socket_new();
gtk_widget_set_parent_window(socketWidget, parent_win);
g_signal_connect(socketWidget, "plug_removed", G_CALLBACK(plug_removed_cb), NULL);
g_signal_connect(socketWidget, "unrealize", G_CALLBACK(socket_unrealize_cb), NULL);
g_signal_connect(socketWidget, "destroy", G_CALLBACK(gtk_widget_destroyed), &socketWidget);
gpointer user_data = NULL;
gdk_window_get_user_data(parent_win, &user_data);
GtkContainer *container = GTK_CONTAINER(user_data);
gtk_container_add(container, socketWidget);
gtk_widget_realize(socketWidget);
GtkAllocation new_allocation;
new_allocation.x = 0;
new_allocation.y = 0;
new_allocation.width = WINDOW_XSIZE;
new_allocation.height = WINDOW_YSIZE;
gtk_widget_size_allocate(socketWidget, &new_allocation);
gtk_widget_show(socketWidget);
gdk_flush();
GdkNativeWindow ww = gtk_socket_get_id(GTK_SOCKET(socketWidget));
GdkWindow *w = gdk_window_lookup(ww);
npwindow = (NPWindow*) malloc (sizeof (NPWindow));
npwindow->window = (void*)(unsigned long)ww;
npwindow->x = 0;
npwindow->y = 0;
npwindow->width = WINDOW_XSIZE;
npwindow->height = WINDOW_YSIZE;
ws_info = (NPSetWindowCallbackStruct*) malloc(sizeof (NPSetWindowCallbackStruct));
ws_info->type = NP_SETWINDOW;
ws_info->display = GDK_WINDOW_XDISPLAY(w);
ws_info->colormap = GDK_COLORMAP_XCOLORMAP(gdk_drawable_get_colormap(w));
GdkVisual* gdkVisual = gdk_drawable_get_visual(w);
ws_info->visual = GDK_VISUAL_XVISUAL(gdkVisual);
ws_info->depth = gdkVisual->depth;
npwindow->ws_info = ws_info;
npwindow->type = NPWindowTypeWindow;
return npwindow;
}
static NPStream * npstream_construct() {
NPStream *stream = (NPStream *) malloc(sizeof(NPStream));
stream->url=strdup(URL);
stream->ndata = 0;
stream->end = 99782;
stream->lastmodified= 1201822722;
stream->notifyData = 0x00000000;
stream->headers = (char*)malloc(200);
return stream;
}
bool NPN_InvokeProc( NPP npp, NPObject *npobj, NPIdentifier npid, const NPVariant *args, uint32_t argCount, NPVariant *result ) {
traceObjectOnCall(__FUNCTION__,npobj);
if( matchNPId(npid,FLASH_REQUEST) && argCount == 1 && args[0].type == NPVariantType_String ) {
return 1;
}
if( matchNPId(npid,FLASH_REQUEST) && argCount == 3 &&
args[0].type == NPVariantType_String &&
args[1].type == NPVariantType_String &&
args[2].type == NPVariantType_String
) {
return 1;
}
if( matchNPId(npid,"_DoFSCommand") && argCount == 2 && args[0].type == NPVariantType_String && args[1].type == NPVariantType_String ) {
printf("[D] FSCOMMAND\n");
return 1;
}
if( npobj == &__top_location ) {
if( matchNPId(npid,"toString") ) {
result->type = NPVariantType_String;
// "chrome://global/content/console.xul" is what Firefox returns for 'top.location.toString()';
result->value.stringValue.UTF8Characters = strdup("chrome://global/content/console.xul");
result->value.stringValue.UTF8Length = (int)strlen(result->value.stringValue.UTF8Characters);
printf("[D] Returned %s\n", result->value.stringValue.UTF8Characters);
}
return 1;
}
//On OSX, Flash retreives locations by injected functions:
if( matchNPId(npid,"__flash_getWindowLocation") ) {
// return the location object:
result->type = NPVariantType_Object;
result->value.objectValue = &__location;
NPN_RetainObjectProc(&__location);
return 1;
}
if( matchNPId(npid,"__flash_getTopLocation") ) {
// return the top_location object:
result->type = NPVariantType_Object;
result->value.objectValue = &__top_location;
NPN_RetainObjectProc(&__top_location);
return 1;
}
return 0;
}
static bool NPN_InvokeDefaultProc( NPP npp, NPObject *npobj, const NPVariant *args, uint32_t argCount, NPVariant *result ) {
return 0;
}
static bool NPN_GetPropertyProc( NPP npp, NPObject *npobj, NPIdentifier npid, NPVariant *result ) {
if (npobj == &__window) {
if( matchNPId(npid,"location") ) {
result->type = NPVariantType_Object;
result->value.objectValue = &__location;
NPN_RetainObjectProc(&__location);
return 1;
}
if( matchNPId(npid,"top") ) {
result->type = NPVariantType_Object;
result->value.objectValue = &__top;
NPN_RetainObjectProc(&__top);
return 1;
}
} else if (npobj == &__top) {
if ( matchNPId(npid,"location") ) {
result->type = NPVariantType_Object;
result->value.objectValue = &__top_location;
NPN_RetainObjectProc(&__top_location);
return 1;
}
}
return 0;
}
static bool NPN_SetPropertyProc( NPP npp, NPObject *npobj, NPIdentifier propertyName, const NPVariant *value ) {
return 0;
}
static bool NPN_RemovePropertyProc( NPP npp, NPObject *npobj, NPIdentifier propertyName ) {
return 0;
}
static bool NPN_HasPropertyProc( NPP npp, NPObject *npobj, NPIdentifier propertyName ) {
return 0;
}
static bool NPN_HasMethodProc( NPP npp, NPObject *npobj, NPIdentifier methodName ) {
return 0;
}
static int unescape( char *str, int *ssize ) {
int k = 0, esc = 0;
// UNESCAPE the string
while( k < *ssize ) {
if( !esc ) {
if( str[k++] == '\\' )
esc = 1;
} else {
char c;
switch( str[k] ) {
case '"': c = '"'; break;
case '\\': c = '\\'; break;
case 'r': c = '\r'; break;
case 'n': c = '\n'; break;
case 't': c = '\t'; break;
default:
return 0;
}
(*ssize)--;
memcpy(str+k,str+k+1,*ssize-k);
str[k-1] = c;
esc = 0;
}
}
str[*ssize] = 0;
return 1;
}
static const char *end_of_string( const char *send ) {
int esc = 0;
while( *send ) {
switch( *send ) {
case '"':
if( !esc )
return send;
esc = 0;
break;
case '\\':
esc = !esc;
break;
default:
esc = 0;
break;
}
send++;
}
return NULL;
}
#define JS_CALL_START "try { __flash__toXML("
#define JS_RESULT_START "var __flash_temp = \""
bool Evaluate( NPP npp, NPObject *npobj, NPString *script, NPVariant *result ) {
printf( "Evaluate %s\n", script->UTF8Characters );
if( memcmp(script->UTF8Characters,JS_CALL_START,strlen(JS_CALL_START)) == 0 ) {
const char *p = script->UTF8Characters + strlen(JS_CALL_START);
const char *s = p;
const char *send;
while( *s && *s != '(' )
s++;
if( !*s || s[1] != '"' )
return 0;
s += 2;
send = end_of_string(s);
if( send == NULL || send[1] != ')' )
return 0;
{
int isize = (int)(s - p) - 2;
int ssize = (int)(send - s);
char *ident = (char*)malloc(isize+1);
char *str = (char*)malloc(ssize+1);
memcpy(ident,p,isize);
memcpy(str,s,ssize);
ident[isize] = 0;
if( !unescape(str,&ssize) ) {
free(ident);
free(str);
return 0;
}
// CALLBACK
{
printf("CALLBACK\n");
int size = 0;
const char *res = "callback";
free(ident);
free(str);
if( res == NULL )
return 0;
result->type = NPVariantType_String;
result->value.stringValue.UTF8Characters = strdup(res);
result->value.stringValue.UTF8Length = size;
return 1;
}
}
}
if( memcmp(script->UTF8Characters,JS_RESULT_START,strlen(JS_RESULT_START)) == 0 ) {
const char *s = script->UTF8Characters + strlen(JS_RESULT_START);
const char *send = end_of_string(s);
char *str;
int ssize;
if( send == NULL || send[1] != ';' )
return 0;
ssize = (int)(send - s);
str = (char*)malloc(ssize+1);
memcpy(str,s,ssize);
if( !unescape(str,&ssize) ) {
free(str);
return 0;
}
result->type = NPVariantType_String;
result->value.stringValue.UTF8Characters = str;
result->value.stringValue.UTF8Length = ssize;
return 1;
}
result->type = NPVariantType_Void;
return 1;
}
void NPN_ReleaseObjectProc(NPObject *npobj) {
if( npobj == NULL )
return;
npobj->referenceCount--;
if( npobj->referenceCount != 0 )
return;
if( npobj->_class->deallocate ) {
npobj->_class->deallocate(npobj);
return;
}
if( npobj->_class->invalidate )
npobj->_class->invalidate(npobj);
free(npobj);
}
NPObject* NPN_CreateObjectProc(NPP npp, NPClass *aClass) {
NPObject *o;
if( aClass->allocate )
o = aClass->allocate(npp,aClass);
else
o = (NPObject*)malloc(sizeof(NPObject));
o->_class = aClass;
o->referenceCount = 1;
return o;
}
NPObject* NPN_RetainObjectProc(NPObject *npobj) {
if( npobj == NULL )
return NULL;
npobj->referenceCount++;
return npobj;
}
void NPN_ReleaseVariantValueProc(NPVariant *variant) {
//printf("ReleaseVariantValueProc\n");
switch( variant->type ) {
case NPVariantType_Null:
case NPVariantType_Void:
break;
case NPVariantType_String:
free( (char*)variant->value.stringValue.UTF8Characters );
variant->type = NPVariantType_Void;
break;
case NPVariantType_Object:
NPN_ReleaseObjectProc(variant->value.objectValue);
variant->type = NPVariantType_Void;
break;
default:
break;
}
}
void SetException( NPObject *npobj, const NPUTF8 *message ) {
printf("SetException %s\n",message);
}
NPError NPN_GetURLNotifyProc(NPP instance, const char* url, const char* window, void* notifyData) {
printf("[D] NPN_GetURLNotifyProc:%p, url: %s, window: %s\n", instance, url, window);
if (window && strlen(window)==6 && memcmp("_blank",window,6)==0) {
//system_launch_url(url);
pluginFuncs.urlnotify(instance,url,NPRES_DONE,notifyData);
} else if( memcmp(url,"javascript:",11) == 0 ) {
NPStream s;
uint16_t stype;
int success;
memset(&s,0,sizeof(NPStream));
s.url = strdup(url);
success = (pluginFuncs.newstream(instance,"text/html",&s,0,&stype) == NPERR_NO_ERROR);
if( success ) {
int pos = 0;
int size;
char buf[256];
sprintf(buf,"%X__flashplugin_unique__",(int_val)instance);
size = (int)strlen(buf);
s.end = size;
while( pos < size ) {
int len = pluginFuncs.writeready(instance,&s);
if( len <= 0 )
break;
if( len > size - pos )
len = size - pos;
len = pluginFuncs.write(instance,&s,pos,len,buf+pos);
if( len <= 0 )
break;
pos += len;
}
success = (pos == size);
}
pluginFuncs.urlnotify(instance,url,success?NPRES_DONE:NPRES_NETWORK_ERR,notifyData);
pluginFuncs.destroystream(instance,&s,NPRES_DONE);
free((void*)s.url);
} else {
NPStream stream;
uint16_t stype;// = NP_NORMAL;
memset(&stream,0,sizeof(NPStream));
stream.url = strdup(url);
stream.notifyData = notifyData;
pluginFuncs.newstream(instance,"application/x-shockwave-flash",&stream, 0, &stype);
//fprintf(stderr, "NPP: %p URL: %s\n", instance, url);
FILE *pp;
char buffer[8192];
pp = fopen(url,"rb");
int len;
while((len=fread(buffer, 1, sizeof(buffer), pp)) != 0) {
pluginFuncs.writeready(instance, &stream);
pluginFuncs.write(instance, &stream, 0, len, buffer);
}
fclose(pp);
pluginFuncs.destroystream(instance, &stream, NPRES_DONE);
free((void*)stream.url);
//pluginFuncs.urlnotify(instance, url, NPRES_DONE, notifyData);
}
return NPERR_NO_ERROR;
}
NPError NPN_GetURL( NPP instance, const char* url, const char* target ) {
printf( "GetURL %s\n", url );
if (target && strlen(target)==6 && memcmp("_blank",target,6)==0) {
//system_launch_url(url);
return NPERR_NO_ERROR;
}
return NPERR_NO_ERROR;
}
NPError NPN_PostURLNotify( NPP instance, const char* url, const char* target, uint32_t len, const char* buf, NPBool file, void* notifyData) {
printf( "PostURLNotify (url) %s (target) %s (buf) %s[%d] (file) %i (nd) %p\n", url, target, buf, len, file, notifyData);
//url_process(instance,url,buf,len,notifyData);
return NPERR_NO_ERROR;
}
NPError NPN_PostURL( NPP instance, const char* url, const char* target, uint32_t len, const char* buf, NPBool file ) {
printf( "PostURL" );
return NPERR_NO_ERROR;
}
NPError NPN_RequestRead(NPStream* stream, NPByteRange* range_list) {
printf("[D] NPN_RequestRead\n");
return NPERR_NO_ERROR;
}
NPError NewStream( NPP instance, NPMIMEType type, const char* target, NPStream** stream ) {
printf( "NewStream\n" );
return NPERR_NO_ERROR;
}
int32_t Write( NPP instance, NPStream* stream, int32_t len, void* buffer ) {
printf( "Write\n" );
return 0;
}
NPError DestroyStream( NPP instance, NPStream* stream, NPReason reason ) {
printf( "DestroyStream\n" );
return NPERR_NO_ERROR;
}
void _InvalidateRect( NPP instance, NPRect *invalidRect ) {
printf( "InvalidateRect\n" );
}
void InvalidateRegion( NPP instance, NPRegion invalidRegion ) {
printf( "InvalidateRegion\n" );
}
void ForceRedraw( NPP instance ) {
printf( "ForceRedraw\n" );
}
void initNPNetscapeFuncs(NPNetscapeFuncs *bFuncs) {
int i=0;
for(i=1; i<sizeof(*bFuncs)/sizeof(ssize_t); i++)
*(((ssize_t*)bFuncs)+i)=i+1000;
bFuncs->geturl=NPN_GetURL;
bFuncs->posturl=NPN_PostURL;
bFuncs->requestread=NPN_RequestRead;
bFuncs->newstream=NewStream;
bFuncs->write=Write;
bFuncs->destroystream=DestroyStream;
bFuncs->status=Status_;
bFuncs->uagent=NPN_UserAgentProc;
bFuncs->memalloc=malloc;
bFuncs->memfree=free;
bFuncs->memflush=MemFlush;
bFuncs->reloadplugins=ReloadPlugins;
bFuncs->getJavaEnv=GetJavaEnv;
bFuncs->getJavaPeer=GetJavaPeer;
bFuncs->geturlnotify=NPN_GetURLNotifyProc;
bFuncs->posturlnotify=NPN_PostURLNotify;
bFuncs->getvalue=NPN_GetValueProc;
bFuncs->setvalue=NPN_SetValueProc;
bFuncs->invalidaterect=_InvalidateRect;
bFuncs->invalidateregion=InvalidateRegion;
bFuncs->forceredraw=ForceRedraw;
bFuncs->getstringidentifier=NPN_GetStringIdentifierProc;
bFuncs->getstringidentifiers=GetStringIdentifiers;
bFuncs->getintidentifier=GetIntIdentifier;
bFuncs->identifierisstring=IdentifierIsString;
bFuncs->utf8fromidentifier=UTF8FromIdentifier;
bFuncs->intfromidentifier=IntFromIdentifier;
bFuncs->createobject=NPN_CreateObjectProc;
bFuncs->retainobject=NPN_RetainObjectProc;
bFuncs->releaseobject=NPN_ReleaseObjectProc;
bFuncs->invoke=NPN_InvokeProc;
bFuncs->invokeDefault=NPN_InvokeDefaultProc;
bFuncs->evaluate=Evaluate;
bFuncs->getproperty=NPN_GetPropertyProc;
bFuncs->setproperty=NPN_SetPropertyProc;
bFuncs->removeproperty=NPN_RemovePropertyProc;
bFuncs->hasproperty=NPN_HasPropertyProc;
bFuncs->hasmethod=NPN_HasMethodProc;
bFuncs->releasevariantvalue=NPN_ReleaseVariantValueProc;
bFuncs->setexception=SetException;
bFuncs->size= sizeof(bFuncs);
// bFuncs->version=(NP_VERSION_MAJOR << 8) + NP_VERSION_MINOR;
bFuncs->version=20;
}
static void destroy(GtkWidget *widget, gpointer data) {
gtk_main_quit ();
}
int main(int argc, char **argv)
{
if(argc < 2) {
printf("[-] Usage: %s <swfuri>\n", argv[0]);
exit(-1);
}
URL = argv[1];
gtk_init (&argc, &argv);
main_window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_widget_set_usize (main_window, WINDOW_XSIZE, WINDOW_YSIZE);
g_signal_connect (G_OBJECT (main_window), "destroy", G_CALLBACK (destroy), NULL);
gtk_widget_realize(main_window);
//gtk_window_fullscreen((GtkWindow *)main_window);
gtk_widget_show_all(main_window);
printf("[+] created GTK widget\n");
flash_plugin_handle = loadFlashPluginSo();
loadNPEntryPoints(flash_plugin_handle);
printf("[+] initialized flash plugin entry points\n");
initNPNetscapeFuncs(&browserFuncs);
printf("[+] initialized browser functions\n");
checkError("NP_Initialize", iNP_Initialize(&browserFuncs, &pluginFuncs));
printPluginEntrypoints(&pluginFuncs);
printBrowserEntrypoints(&browserFuncs);
NPWindow *npwin = npwindow_construct(main_window);
printf("[+] created NPWindow widget\n");
NPP_t *instancep = (NPP_t *) malloc(sizeof(NPP_t));
memset(instancep,0,sizeof(sizeof(NPP_t)));
NPP instance = instancep;
NPSavedData* saved = (NPSavedData*) malloc(sizeof(NPSavedData));
memset(saved,0,sizeof(sizeof(NPSavedData)));
stream = npstream_construct();
uint16_t stype;
NPObject object;
char *xargv[]= {"allowscriptaccess", "quality", "wmode"};
char *xargm[]= {"always", "best", "direct"};
checkError("NPN_New", pluginFuncs.newp("application/x-shockwave-flash", instance, NP_EMBED, 3, xargv, xargm, 0));
checkError("NPN_GetValue NPPVpluginScriptableNPObject", pluginFuncs.getvalue(instance, NPPVpluginScriptableNPObject, &object));
checkError("NPN_SetWindow", pluginFuncs.setwindow(instance, npwin));
checkError("NPN_NewStream", pluginFuncs.newstream(instance, "application/x-shockwave-flash", stream, 0, &stype));
FILE *pp;
char buffer[8192];
pp = fopen(argv[1],"rb");
int len;
while((len=fread(buffer, 1, sizeof(buffer), pp)) != 0) {
pluginFuncs.writeready(instance, stream);
pluginFuncs.write(instance, stream, 0, len, buffer);
}
fclose(pp);
checkError("NPN_DestroyStream",pluginFuncs.destroystream(instance, stream, NPRES_DONE));
free(stream);
gtk_main();
checkError("NPN_Destroy",pluginFuncs.destroy(instance, &saved));
checkError("NP_Shutdown", iNP_Shutdown());
dlclose(flash_plugin_handle);
return 0;
}