mirror of
https://github.com/netsurf-browser/netsurf
synced 2024-11-25 07:49:38 +03:00
1e6e665e35
Make plugins work on WIMP versions below 4.00 svn path=/import/netsurf/; revision=250
1550 lines
55 KiB
C
1550 lines
55 KiB
C
/*
|
|
* This file is part of NetSurf, http://netsurf.sourceforge.net/
|
|
* Licensed under the GNU General Public License,
|
|
* http://www.opensource.org/licenses/gpl-license
|
|
* Copyright 2003 John M Bell <jmb202@ecs.soton.ac.uk>
|
|
*/
|
|
|
|
/*
|
|
* TODO:
|
|
* - Reshaping plugin (ie. call plugin_reshape_instance from somewhere)
|
|
* [Plugin_Reshape (&4d544), Plugin_Reshape_Request (&4d545)]
|
|
* - Finish off stream protocol implementation
|
|
* [Plugin_Stream_Write (&4d54a), Plugin_Stream_Written (&4d54b)]
|
|
* - Parse and act upon the rest of the Plugin_Opening flags
|
|
* - Handle death of Plugin Task
|
|
* - Implement remaining messages [Plugin_URL_Access, Plugin_Focus,
|
|
* Plugin_Notify, Plugin_Busy, Plugin_Action, Plugin_Abort,
|
|
* Plugin_Inform(ed)?]
|
|
* - Handle standalone objects
|
|
*/
|
|
|
|
#define NDEBUG
|
|
|
|
#include <assert.h>
|
|
#include <ctype.h>
|
|
#include <stdbool.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
#include "netsurf/content/content.h"
|
|
#include "netsurf/desktop/browser.h"
|
|
#include "netsurf/desktop/gui.h"
|
|
#include "netsurf/render/html.h"
|
|
#include "netsurf/render/box.h"
|
|
#include "netsurf/riscos/gui.h"
|
|
#include "netsurf/riscos/plugin.h"
|
|
#include "netsurf/utils/log.h"
|
|
#include "netsurf/utils/utils.h"
|
|
|
|
#include "oslib/mimemap.h"
|
|
#include "oslib/os.h"
|
|
#include "oslib/osfile.h"
|
|
#include "oslib/osfind.h"
|
|
#include "oslib/osgbpb.h"
|
|
#include "oslib/plugin.h"
|
|
#include "oslib/wimp.h"
|
|
|
|
/* parameters file creation */
|
|
void plugin_write_parameters_file(struct object_params *params);
|
|
void plugin_populate_pdata(int rsize, byte *pdata);
|
|
|
|
/* stream handling */
|
|
void plugin_create_stream(struct browser_window *bw,
|
|
struct object_params *params, struct content *c);
|
|
void plugin_write_stream_as_file(struct browser_window *bw,
|
|
struct object_params *params,
|
|
struct content *c);
|
|
void plugin_destroy_stream(struct browser_window *bw,
|
|
struct object_params *params, struct content *c);
|
|
|
|
/* linked list handling */
|
|
struct plugin_message *plugin_add_message_to_linked_list(plugin_b browser,
|
|
plugin_p plugin,
|
|
wimp_message *m,
|
|
struct plugin_message *reply);
|
|
void plugin_remove_message_from_linked_list(struct plugin_message* m);
|
|
struct plugin_message *plugin_get_message_from_linked_list(int ref);
|
|
void plugin_add_instance_to_list(struct content *c,
|
|
struct browser_window *bw,
|
|
struct content *page, struct box *box,
|
|
struct object_params *params, void **state);
|
|
void plugin_remove_instance_from_list(struct object_params *params);
|
|
struct plugin_list *plugin_get_instance_from_list(plugin_b browser,
|
|
plugin_p plugin);
|
|
|
|
/* message handling */
|
|
void plugin_open(wimp_message *message);
|
|
void plugin_opening(wimp_message *message);
|
|
void plugin_close(wimp_message *message);
|
|
void plugin_closed(wimp_message *message);
|
|
void plugin_reshape_request(wimp_message *message);
|
|
void plugin_stream_new(wimp_message *message);
|
|
void plugin_status(wimp_message *message);
|
|
char *plugin_get_string_value(os_string_value string, char *msg);
|
|
|
|
/* others */
|
|
void plugin_create_sysvar(const char *mime_type, char *sysvar);
|
|
int plugin_process_opening(struct object_params *params,
|
|
struct plugin_message *message);
|
|
|
|
/*-------------------------------------------------------------------------*/
|
|
/* Linked List pointers */
|
|
/*-------------------------------------------------------------------------*/
|
|
|
|
static struct plugin_message pm = {0, 0, 0, 0, 0, &pm, &pm};
|
|
static struct plugin_message *pmlist = ±
|
|
|
|
static struct plugin_list pl = {0, 0, 0, 0, 0, 0, &pl, &pl};
|
|
static struct plugin_list *plist = &pl;
|
|
|
|
/*-------------------------------------------------------------------------*/
|
|
/* Externally visible functions */
|
|
/*-------------------------------------------------------------------------*/
|
|
|
|
/**
|
|
* plugin_create
|
|
* initialises plugin system in readiness for receiving object data
|
|
*/
|
|
void plugin_create(struct content *c)
|
|
{
|
|
c->data.plugin.data = xcalloc(0, 1);
|
|
c->data.plugin.length = 0;
|
|
/* we can't create the plugin here, because this is only called
|
|
* once, even if the object appears several times */
|
|
}
|
|
|
|
/**
|
|
* plugin_add_instance
|
|
*
|
|
* The content has been added to a page somewhere: launch the plugin.
|
|
* This may be called anytime after plugin_create any number of times.
|
|
* Each must launch a new plugin.
|
|
*
|
|
* bw is the window which the plugin is in
|
|
* page, box, params are 0 if the object is standalone
|
|
* state may be use to store a pointer to state data
|
|
*/
|
|
void plugin_add_instance(struct content *c, struct browser_window *bw,
|
|
struct content *page, struct box *box,
|
|
struct object_params *params, void **state)
|
|
{
|
|
char sysvar[40];
|
|
char *varval;
|
|
int size;
|
|
os_var_type var;
|
|
os_error *e;
|
|
// wimp_message *m = xcalloc(256, sizeof(char));
|
|
wimp_message m;
|
|
plugin_message_open *pmo;
|
|
os_box b;
|
|
struct plugin_message *npm = xcalloc(1, sizeof(*npm));
|
|
struct plugin_message *temp;
|
|
struct plugin_list *npl = xcalloc(1, sizeof(*npl));
|
|
int offset;
|
|
unsigned char *pchar = (unsigned char*)&m.data;
|
|
int flags = 0;
|
|
|
|
if (params == 0) {
|
|
fprintf(stderr,
|
|
"Cannot handle standalone objects at this time");
|
|
gui_window_set_status(bw->window,
|
|
"Plugin Error: Cannot handle standalone objects at this time");
|
|
// xfree(m);
|
|
xfree(npm);
|
|
xfree(npl);
|
|
return;
|
|
}
|
|
|
|
/* write parameters file */
|
|
plugin_write_parameters_file(params);
|
|
|
|
/* Get contents of Alias$@PlugInType_xxx system variable. */
|
|
plugin_create_sysvar(c->mime_type, sysvar);
|
|
xos_read_var_val_size(sysvar, 0, 0, &size, NULL, &var);
|
|
if(var != 3)
|
|
size = ~(size);
|
|
varval = xcalloc((unsigned int)size, sizeof(char));
|
|
xos_read_var_val(sysvar, varval, size, 0, var, NULL, NULL, NULL);
|
|
|
|
LOG(("%s: %s", sysvar, varval));
|
|
|
|
/* Broadcast Message_PlugIn_Open (&4D540) and listen for response
|
|
* Message_PlugIn_Opening (&4D541). If no response, try to launch
|
|
* plugin by Wimp_StartTask(sysvar). Then re-broadcast Message_PlugIn_Open
|
|
* and listen for response. If there is still no response, give up.
|
|
* NB: For the bounding box in Message_PlugIn_Open, we choose arbitrary
|
|
* values outside the area displayed. This is corrected when
|
|
* plugin_redraw is called.
|
|
*/
|
|
/* Initialise bounding box */
|
|
b.x0 = 100;
|
|
b.x1 = 1000;
|
|
b.y0 = 100;
|
|
b.y1 = 1000;
|
|
|
|
/* populate plugin_message_open struct */
|
|
pmo = (plugin_message_open*)&m.data;
|
|
pmo->flags = 0;
|
|
pmo->reserved = 0;
|
|
pmo->browser = (plugin_b)params->browser;
|
|
pmo->parent_window = bw->window->data.browser.window;
|
|
pmo->bbox = b;
|
|
xmimemaptranslate_mime_type_to_filetype(c->mime_type, &pmo->file_type);
|
|
|
|
offset = 56;
|
|
pmo->filename.offset = offset;
|
|
strncpy((char*)&pchar[offset], params->filename, (unsigned int)236-offset);
|
|
offset = offset + strlen(params->filename) + 1;
|
|
if (offset > 235) {
|
|
LOG(("filename too long"));
|
|
// xfree(m);
|
|
xfree(npm);
|
|
xfree(npl);
|
|
xfree(varval);
|
|
return;
|
|
}
|
|
|
|
m.size = ((20 + offset + 3) / 4) * 4;
|
|
m.your_ref = 0;
|
|
m.action = message_PLUG_IN_OPEN;
|
|
|
|
/* add message to list */
|
|
temp = plugin_add_message_to_linked_list((plugin_b)params->browser, (plugin_p)0, &m, (struct plugin_message*)0);
|
|
|
|
LOG(("Sending Message: &4D540"));
|
|
LOG(("Message Size: %d", m.size));
|
|
e = xwimp_send_message(wimp_USER_MESSAGE_RECORDED, &m, wimp_BROADCAST);
|
|
|
|
if(e) LOG(("Error: %s", e->errmess));
|
|
|
|
/* wait for wimp poll */
|
|
while(temp->poll == 0)
|
|
gui_poll();
|
|
|
|
if(temp->plugin != 0 && temp->reply != 0) {
|
|
|
|
/* ok, we got a reply */
|
|
LOG(("Reply to message %p: %p", temp, temp->reply));
|
|
flags = plugin_process_opening(params, temp);
|
|
plugin_remove_message_from_linked_list(temp->reply);
|
|
plugin_remove_message_from_linked_list(temp);
|
|
xfree(varval);
|
|
// xfree(m);
|
|
xfree(npm);
|
|
xfree(npl);
|
|
} else {
|
|
|
|
/* no reply so issue Wimp_StartTask(varval) */
|
|
LOG(("No reply to message %p", temp));
|
|
plugin_remove_message_from_linked_list(temp);
|
|
|
|
LOG(("Starting task: %s", varval));
|
|
e = xwimp_start_task((char const*)varval, NULL);
|
|
|
|
if(e) LOG(("Error: %s", e->errmess));
|
|
|
|
/* hmm, deja-vu */
|
|
temp = plugin_add_message_to_linked_list((plugin_b)params->browser, (plugin_p)0, &m, (struct plugin_message*)0);
|
|
LOG(("Re-Sending Message &4D540"));
|
|
xwimp_send_message(wimp_USER_MESSAGE_RECORDED, &m,
|
|
wimp_BROADCAST);
|
|
|
|
while(temp->poll == 0)
|
|
gui_poll();
|
|
|
|
if(temp->plugin != 0 && temp->reply != 0) {
|
|
|
|
/* ok, we got a reply */
|
|
LOG(("Reply to message %p: %p", temp, temp->reply));
|
|
flags = plugin_process_opening(params, temp);
|
|
plugin_remove_message_from_linked_list(temp->reply);
|
|
plugin_remove_message_from_linked_list(temp);
|
|
// xfree(m);
|
|
xfree(varval);
|
|
xfree(npm);
|
|
xfree(npl);
|
|
} else {
|
|
|
|
/* no reply so give up */
|
|
LOG(("No reply to message %p", temp));
|
|
plugin_remove_message_from_linked_list(temp);
|
|
// xfree(m);
|
|
xfree(varval);
|
|
xfree(npm);
|
|
xfree(npl);
|
|
return;
|
|
}
|
|
}
|
|
|
|
/* At this point, it's certain that we can handle this object so
|
|
* add it to the list of plugin instances.
|
|
*/
|
|
plugin_add_instance_to_list(c, bw, page, box, params, state);
|
|
|
|
/* TODO - handle other flags (see below) */
|
|
if(flags & 0x4)
|
|
plugin_create_stream(bw, params, c);
|
|
|
|
plugin_destroy_stream(bw, params, c);
|
|
|
|
}
|
|
|
|
/**
|
|
* plugin_process_opening
|
|
* process plugin_opening message flags
|
|
* NB: this is NOT externally visible.
|
|
* it's just here because it's referred to in the TODO above
|
|
*/
|
|
int plugin_process_opening(struct object_params *params,
|
|
struct plugin_message *message) {
|
|
|
|
plugin_message_opening *pmo;
|
|
|
|
params->plugin = (int)message->reply->plugin;
|
|
params->plugin_task = (unsigned int)message->reply->m->sender;
|
|
|
|
pmo = (plugin_message_opening*)&message->reply->m->data;
|
|
/* LOG(("pmo->flags = %x", pmo->flags));
|
|
if(pmo->flags & 0x1)
|
|
LOG(("accepts input focus"));
|
|
if(pmo->flags & 0x2)
|
|
LOG(("wants code fetching"));
|
|
if(pmo->flags & 0x4)
|
|
LOG(("wants data fetching"));
|
|
if(pmo->flags & 0x8)
|
|
LOG(("will delete parameters"));
|
|
if(pmo->flags & 0x10)
|
|
LOG(("still busy"));
|
|
if(pmo->flags & 0x20)
|
|
LOG(("supports extended actions"));
|
|
if(pmo->flags & 0x40)
|
|
LOG(("has helper window"));
|
|
*/
|
|
return (int)pmo->flags;
|
|
}
|
|
|
|
/**
|
|
* plugin_remove_instance
|
|
*
|
|
* A plugin is no longer required, eg. the page containing it has
|
|
* been closed.
|
|
*
|
|
* Any storage associated with state must be freed.
|
|
*/
|
|
void plugin_remove_instance(struct content *c, struct browser_window *bw,
|
|
struct content *page, struct box *box,
|
|
struct object_params *params, void **state)
|
|
{
|
|
// wimp_message *m = xcalloc(256, sizeof(char));
|
|
wimp_message m;
|
|
plugin_message_close *pmc;
|
|
struct plugin_message *temp;
|
|
char *p, *filename = strdup(params->filename);
|
|
|
|
if (params == 0) {
|
|
|
|
// xfree(m);
|
|
return;
|
|
}
|
|
|
|
pmc = (plugin_message_close*)&m.data;
|
|
pmc->flags = 0;
|
|
pmc->plugin = (plugin_p)params->plugin;
|
|
pmc->browser = (plugin_b)params->browser;
|
|
m.size = 32;
|
|
m.your_ref = 0;
|
|
m.action = message_PLUG_IN_CLOSE;
|
|
|
|
temp = plugin_add_message_to_linked_list(pmc->browser, pmc->plugin, &m, 0);
|
|
LOG(("Sending message &4D542"));
|
|
xwimp_send_message(wimp_USER_MESSAGE_RECORDED, &m,
|
|
(wimp_t)params->plugin_task);
|
|
|
|
// xfree(m);
|
|
|
|
while (temp == 0)
|
|
gui_poll();
|
|
|
|
if (temp->reply != 0){
|
|
|
|
plugin_remove_message_from_linked_list(temp->reply);
|
|
plugin_remove_message_from_linked_list(temp);
|
|
}
|
|
else {
|
|
LOG(("message_PLUG_IN_CLOSE bounced"));
|
|
plugin_remove_message_from_linked_list(temp);
|
|
}
|
|
|
|
/* delete parameters file */
|
|
xosfile_delete((char const*)params->filename, NULL, NULL, NULL, NULL, NULL);
|
|
p = strrchr((const char*)filename, 'p');
|
|
filename[(p-filename)] = 'd';
|
|
xosfile_delete((char const*)filename, NULL, NULL, NULL, NULL, NULL);
|
|
|
|
/* delete instance from list */
|
|
plugin_remove_instance_from_list(params);
|
|
}
|
|
|
|
/**
|
|
* plugin_reshape_instance
|
|
*
|
|
* The box containing the plugin has moved or resized,
|
|
* or the window containing the plugin has resized if standalone.
|
|
*/
|
|
void plugin_reshape_instance(struct content *c, struct browser_window *bw,
|
|
struct content *page, struct box *box,
|
|
struct object_params *params, void **state)
|
|
{
|
|
/* By now, we've got the plugin up and running in a nested window
|
|
* off the viewable page area. Now we want to display it in its place.
|
|
* Therefore, broadcast a Message_PlugIn_Reshape (&4D544) with the values
|
|
* given to us.
|
|
*/
|
|
// wimp_message *m = xcalloc(256, sizeof(char));
|
|
wimp_message m;
|
|
plugin_message_reshape *pmr;
|
|
os_box bbox;
|
|
|
|
bbox.x0 = box->x;
|
|
bbox.y0 = box->y;
|
|
bbox.x1 = (box->x + box->width);
|
|
bbox.y1 = (box->y + box->height);
|
|
|
|
pmr = (plugin_message_reshape*)&m.data;
|
|
pmr->flags = 0;
|
|
pmr->plugin = (plugin_p) params->plugin;
|
|
pmr->browser = (plugin_b) params->browser;
|
|
pmr->parent_window = (wimp_w) bw->window->data.browser.window;
|
|
pmr->bbox = bbox;
|
|
|
|
m.size = 36;
|
|
m.your_ref = 0;
|
|
m.action = message_PLUG_IN_RESHAPE;
|
|
|
|
LOG(("Sending Message &4D544"));
|
|
xwimp_send_message(wimp_USER_MESSAGE, &m, (wimp_t)params->plugin_task);
|
|
|
|
// xfree(m);
|
|
|
|
LOG(("plugin_reshape_instance"));
|
|
}
|
|
|
|
|
|
static const char * const ALIAS_PREFIX = "Alias$@PlugInType_";
|
|
|
|
/**
|
|
* plugin_create_sysvar
|
|
* creates system variable from mime type
|
|
* NB: this is NOT externally visible
|
|
* it just makes sense to keep it with the ALIAS_PREFIX definition above.
|
|
*/
|
|
void plugin_create_sysvar(const char *mime_type, char* sysvar)
|
|
{
|
|
unsigned int *fv;
|
|
os_error *e;
|
|
|
|
e = xmimemaptranslate_mime_type_to_filetype(mime_type, (bits *) &fv);
|
|
|
|
sprintf(sysvar, "%s%x", ALIAS_PREFIX, fv);
|
|
}
|
|
|
|
/**
|
|
* plugin_handleable
|
|
* Tests whether we can handle an object using a browser plugin
|
|
* returns true if we can handle it, false if we can't.
|
|
*/
|
|
bool plugin_handleable(const char *mime_type)
|
|
{
|
|
char sysvar[40];
|
|
unsigned int *fv;
|
|
os_error *e;
|
|
|
|
e = xmimemaptranslate_mime_type_to_filetype(mime_type, (bits *) &fv);
|
|
if (e) {
|
|
LOG(("xmimemaptranslate_mime_type_to_filetype failed: %s", e->errmess));
|
|
return false;
|
|
}
|
|
|
|
sprintf(sysvar, "%s%x", ALIAS_PREFIX, fv);
|
|
LOG(("%s, %s", mime_type, sysvar));
|
|
if (getenv(sysvar) == 0)
|
|
return false;
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* plugin_process_data
|
|
* processes data retrieved by the fetch process
|
|
*/
|
|
void plugin_process_data(struct content *c, char *data, unsigned long size)
|
|
{
|
|
|
|
/* If the plugin requests, we send the data to it via the
|
|
* plugin stream protocol.
|
|
* Also, we should listen for Message_PlugIn_URL_Access (&4D54D)
|
|
* as the plugin may need us to retrieve URLs for it.
|
|
* We should also listen for Message_PlugIn_Closed (&4D543).
|
|
* If this occurs, the plugin has exited with an error.
|
|
* Therefore, we need to stop the fetch and exit.
|
|
*/
|
|
|
|
/* I think we should just buffer the data here, in case the
|
|
* plugin requests it sometime in the future. - James */
|
|
|
|
c->data.plugin.data = xrealloc(c->data.plugin.data, c->data.plugin.length + size);
|
|
memcpy(c->data.plugin.data + c->data.plugin.length, data, size);
|
|
c->data.plugin.length += size;
|
|
c->size += size;
|
|
}
|
|
|
|
/**
|
|
* plugin_convert
|
|
* This isn't needed by the plugin system as all the data processing is done
|
|
* externally. Therefore, just tell NetSurf that everything's OK.
|
|
*/
|
|
int plugin_convert(struct content *c, unsigned int width, unsigned int height)
|
|
{
|
|
c->status=CONTENT_STATUS_DONE;
|
|
return 0;
|
|
}
|
|
|
|
void plugin_revive(struct content *c, unsigned int width, unsigned int height)
|
|
{
|
|
}
|
|
|
|
void plugin_reformat(struct content *c, unsigned int width, unsigned int height)
|
|
{
|
|
}
|
|
|
|
/**
|
|
* plugin_destroy
|
|
*/
|
|
void plugin_destroy(struct content *c)
|
|
{
|
|
/* simply free buffered data */
|
|
xfree(c->data.plugin.data);
|
|
}
|
|
|
|
/**
|
|
* plugin_redraw
|
|
* redraw plugin on page.
|
|
*/
|
|
void plugin_redraw(struct content *c, long x, long y,
|
|
unsigned long width, unsigned long height)
|
|
{
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------*/
|
|
/* Parameters file handling functions */
|
|
/*-------------------------------------------------------------------------*/
|
|
|
|
/**
|
|
* plugin_write_parameters_file
|
|
* Writes the parameters file.
|
|
* Beware, this function is long and nasty. It appears to work, however.
|
|
*/
|
|
void plugin_write_parameters_file(struct object_params *params)
|
|
{
|
|
struct plugin_params* temp;
|
|
int *time;
|
|
os_fw pfile;
|
|
int j, rsize = 0;
|
|
char *tstr;
|
|
byte pdata[4] = {0, 0, 0, 0};
|
|
|
|
/* Create the file */
|
|
xosfile_create_dir("<Wimp$ScrapDir>.WWW", 77);
|
|
xosfile_create_dir("<Wimp$ScrapDir>.WWW.NetSurf", 77);
|
|
/* path + filename + terminating NUL */
|
|
params->filename = xcalloc(strlen(getenv("Wimp$ScrapDir"))+13+10+1,
|
|
sizeof(char));
|
|
xos_read_monotonic_time((int*)&time);
|
|
tstr = xcalloc(40, sizeof(char));
|
|
sprintf(tstr, "%01u", (unsigned int)time<<8);
|
|
sprintf(params->filename, "%s.WWW.NetSurf.p%1.9s",
|
|
getenv("Wimp$ScrapDir"), tstr);
|
|
params->browser = (unsigned int)time<<8;
|
|
xfree(tstr);
|
|
LOG(("filename: %s", params->filename));
|
|
|
|
xosfind_openoutw(osfind_NO_PATH, params->filename, NULL, &pfile);
|
|
|
|
/* Write object attributes first */
|
|
|
|
/* classid is checked first */
|
|
if(params->classid != 0 && params->codetype != 0) {
|
|
|
|
/* Record Type */
|
|
plugin_populate_pdata(1, (byte *)&pdata);
|
|
xosgbpb_writew(pfile, pdata, 4, NULL);
|
|
|
|
/* Record size */
|
|
rsize = 0;
|
|
rsize += (4 + 7 + 1);
|
|
rsize += (4 + strlen(params->classid));
|
|
if((strlen(params->classid)%4) != 0)
|
|
rsize += (4-(strlen(params->classid)%4));
|
|
rsize += (4 + strlen(params->codetype));
|
|
if((strlen(params->codetype)%4) != 0)
|
|
rsize += (4-(strlen(params->codetype)%4));
|
|
|
|
plugin_populate_pdata(rsize, (byte *)&pdata);
|
|
xosgbpb_writew(pfile, pdata, 4, NULL);
|
|
|
|
/* name */
|
|
/* size */
|
|
rsize = strlen("CLASSID");
|
|
plugin_populate_pdata(rsize, (byte *)&pdata);
|
|
xosgbpb_writew(pfile, pdata, 4, NULL);
|
|
|
|
/* name */
|
|
xosgbpb_writew(pfile, (byte const*)"CLASSID", rsize, NULL);
|
|
|
|
/* pad to word boundary */
|
|
plugin_populate_pdata(0, (byte *)&pdata);
|
|
xosgbpb_writew(pfile, pdata,
|
|
(4 - ((rsize%4) == 0 ? 4 : (rsize%4))), NULL);
|
|
|
|
/* value */
|
|
/* size */
|
|
rsize = strlen(params->classid);
|
|
plugin_populate_pdata(rsize, (byte *)&pdata);
|
|
xosgbpb_writew(pfile, pdata, 4, NULL);
|
|
|
|
/* name */
|
|
xosgbpb_writew(pfile, (byte const*)params->classid, rsize, NULL);
|
|
|
|
/* pad to word boundary */
|
|
plugin_populate_pdata(0, (byte *)&pdata);
|
|
xosgbpb_writew(pfile, pdata,
|
|
(4 - ((rsize%4) == 0 ? 4 : (rsize%4))), NULL);
|
|
|
|
/* type */
|
|
/* size */
|
|
rsize = strlen(params->codetype);
|
|
plugin_populate_pdata(rsize, (byte *)&pdata);
|
|
xosgbpb_writew(pfile, pdata, 4, NULL);
|
|
|
|
/* name */
|
|
xosgbpb_writew(pfile, (byte const*)params->codetype, rsize, NULL);
|
|
|
|
/* pad to word boundary */
|
|
plugin_populate_pdata(rsize, (byte *)&pdata);
|
|
xosgbpb_writew(pfile, pdata,
|
|
(4 - ((rsize%4) == 0 ? 4 : (rsize%4))), NULL);
|
|
|
|
}
|
|
/* otherwise, we check the data attribute */
|
|
else if(params->data !=0 && params->type != 0) {
|
|
|
|
/* Record Type */
|
|
plugin_populate_pdata(1, (byte *)&pdata);
|
|
xosgbpb_writew(pfile, pdata, 4, NULL);
|
|
|
|
/* Record size */
|
|
rsize = 0;
|
|
rsize += (4 + 4);
|
|
rsize += (4 + strlen(params->data));
|
|
if((strlen(params->data)%4) != 0)
|
|
rsize += (4-(strlen(params->data)%4));
|
|
rsize += (4 + strlen(params->type));
|
|
if((strlen(params->type)%4) != 0)
|
|
rsize += (4-(strlen(params->type)%4));
|
|
|
|
plugin_populate_pdata(rsize, (byte *)&pdata);
|
|
xosgbpb_writew(pfile, pdata, 4, NULL);
|
|
|
|
/* name */
|
|
/* size */
|
|
rsize = strlen("DATA");
|
|
plugin_populate_pdata(rsize, (byte *)&pdata);
|
|
xosgbpb_writew(pfile, pdata, 4, NULL);
|
|
|
|
/* name */
|
|
xosgbpb_writew(pfile, (byte const*)"DATA", rsize, NULL);
|
|
|
|
/* pad to word boundary */
|
|
plugin_populate_pdata(0, (byte *)&pdata);
|
|
xosgbpb_writew(pfile, pdata,
|
|
(4 - ((rsize%4) == 0 ? 4 : (rsize%4))), NULL);
|
|
|
|
/* value */
|
|
/* size */
|
|
rsize = strlen(params->data);
|
|
plugin_populate_pdata(rsize, (byte *)&pdata);
|
|
xosgbpb_writew(pfile, pdata, 4, NULL);
|
|
|
|
/* name */
|
|
xosgbpb_writew(pfile, (byte const*)params->data, rsize, NULL);
|
|
|
|
/* pad to word boundary */
|
|
plugin_populate_pdata(0, (byte *)&pdata);
|
|
xosgbpb_writew(pfile, pdata,
|
|
(4 - ((rsize%4) == 0 ? 4 : (rsize%4))), NULL);
|
|
|
|
/* type */
|
|
/* size */
|
|
rsize = strlen(params->type);
|
|
plugin_populate_pdata(rsize, (byte *)&pdata);
|
|
xosgbpb_writew(pfile, pdata, 4, NULL);
|
|
|
|
/* name */
|
|
xosgbpb_writew(pfile, (byte const*)params->type, rsize, NULL);
|
|
|
|
/* pad to word boundary */
|
|
plugin_populate_pdata(0, (byte *)&pdata);
|
|
xosgbpb_writew(pfile, pdata,
|
|
(4 - ((rsize%4) == 0 ? 4 : (rsize%4))), NULL);
|
|
}
|
|
|
|
/* if codebase is specified, write it as well */
|
|
if(params->codebase != 0) {
|
|
|
|
/* Record Type */
|
|
plugin_populate_pdata(1, (byte *)&pdata);
|
|
xosgbpb_writew(pfile, pdata, 4, NULL);
|
|
|
|
/* Record size */
|
|
rsize = 0;
|
|
rsize += (4 + 8);
|
|
rsize += (4 + strlen(params->codebase));
|
|
if((strlen(params->codebase)%4) != 0)
|
|
rsize += (4-(strlen(params->codebase)%4));
|
|
rsize += 4;
|
|
plugin_populate_pdata(rsize, (byte *)&pdata);
|
|
xosgbpb_writew(pfile, pdata, 4, NULL);
|
|
|
|
/* name */
|
|
/* size */
|
|
rsize = strlen("CODEBASE");
|
|
plugin_populate_pdata(rsize, (byte *)&pdata);
|
|
xosgbpb_writew(pfile, pdata, 4, NULL);
|
|
|
|
/* name */
|
|
xosgbpb_writew(pfile, (byte const*)"CODEBASE", rsize, NULL);
|
|
|
|
/* pad to word boundary */
|
|
plugin_populate_pdata(0, (byte *)&pdata);
|
|
xosgbpb_writew(pfile, pdata,
|
|
(4 - ((rsize%4) == 0 ? 4 : (rsize%4))), NULL);
|
|
|
|
/* value */
|
|
/* size */
|
|
rsize = strlen(params->codebase);
|
|
plugin_populate_pdata(rsize, (byte *)&pdata);
|
|
xosgbpb_writew(pfile, pdata, 4, NULL);
|
|
|
|
/* name */
|
|
xosgbpb_writew(pfile, (byte const*)params->codebase, rsize, NULL);
|
|
|
|
/* pad to word boundary */
|
|
plugin_populate_pdata(0, (byte *)&pdata);
|
|
xosgbpb_writew(pfile, pdata,
|
|
(4 - ((rsize%4) == 0 ? 4 : (rsize%4))), NULL);
|
|
|
|
/* type */
|
|
/* size */
|
|
plugin_populate_pdata(0, (byte *)&pdata);
|
|
xosgbpb_writew(pfile, pdata, 4, NULL);
|
|
|
|
}
|
|
|
|
/* Iterate through the parameter list, creating the parameters
|
|
* file as we go. We can free up the memory as we go.
|
|
*/
|
|
while(params->params != 0) {
|
|
|
|
LOG(("name: %s", params->params->name == 0 ? "not set" : params->params->name));
|
|
LOG(("value: %s", params->params->value == 0 ? "not set" : params->params->value));
|
|
LOG(("type: %s", params->params->type == 0 ? "not set" : params->params->type));
|
|
LOG(("valuetype: %s", params->params->valuetype));
|
|
|
|
|
|
/* Record Type */
|
|
if(strcasecmp(params->params->valuetype, "data") == 0)
|
|
rsize = 1;
|
|
if(strcasecmp(params->params->valuetype, "ref") == 0)
|
|
rsize = 2;
|
|
if(strcasecmp(params->params->valuetype, "object") == 0)
|
|
rsize = 3;
|
|
plugin_populate_pdata(rsize, (byte *)&pdata);
|
|
xosgbpb_writew(pfile, pdata, 4, NULL);
|
|
|
|
/* Record Size */
|
|
rsize = 0;
|
|
if(params->params->name != 0) {
|
|
rsize += 4;
|
|
rsize += strlen(params->params->name);
|
|
if((strlen(params->params->name) % 4) != 0)
|
|
rsize += (4 - (strlen(params->params->name) % 4));
|
|
}
|
|
if(params->params->value != 0) {
|
|
rsize += 4;
|
|
rsize += strlen(params->params->value);
|
|
if((strlen(params->params->value) % 4) != 0)
|
|
rsize += 4 - ((strlen(params->params->value) % 4));
|
|
}
|
|
if(params->params->type != 0) {
|
|
rsize += 4;
|
|
rsize += strlen(params->params->type);
|
|
if((strlen(params->params->type) % 4) != 0)
|
|
rsize += (4 - (strlen(params->params->type) % 4));
|
|
} else {
|
|
rsize += 4;
|
|
}
|
|
plugin_populate_pdata(rsize, (byte *)&pdata);
|
|
xosgbpb_writew(pfile, pdata, 4, NULL);
|
|
|
|
/* Record Name */
|
|
if(params->params->name != 0) {
|
|
|
|
/* Size */
|
|
rsize = strlen(params->params->name);
|
|
plugin_populate_pdata(rsize, (byte *)&pdata);
|
|
xosgbpb_writew(pfile, pdata, 4, NULL);
|
|
|
|
/* Name */
|
|
xosgbpb_writew(pfile, (byte const*)params->params->name, rsize, NULL);
|
|
|
|
/* Pad to word boundary */
|
|
plugin_populate_pdata(0, (byte *)&pdata);
|
|
xosgbpb_writew(pfile, pdata, (4 - ((rsize%4) == 0 ? 4 : (rsize%4))), NULL);
|
|
}
|
|
|
|
/* Record Value */
|
|
if(params->params->value != 0) {
|
|
|
|
/* Size */
|
|
rsize = strlen(params->params->value);
|
|
plugin_populate_pdata(rsize, (byte *)&pdata);
|
|
xosgbpb_writew(pfile, pdata, 4, NULL);
|
|
|
|
/* Name */
|
|
xosgbpb_writew(pfile, (byte const*)params->params->value, rsize, NULL);
|
|
|
|
/* Pad to word boundary */
|
|
plugin_populate_pdata(0, (byte *)&pdata);
|
|
xosgbpb_writew(pfile, pdata, (4 - ((rsize%4) == 0 ? 4 : (rsize%4))), NULL);
|
|
}
|
|
|
|
/* Record Type */
|
|
if(params->params->type != 0) {
|
|
|
|
/* Size */
|
|
rsize = strlen(params->params->type);
|
|
plugin_populate_pdata(rsize, (byte *)&pdata);
|
|
xosgbpb_writew(pfile, pdata, 4, NULL);
|
|
|
|
/* Name */
|
|
xosgbpb_writew(pfile, (byte const*)params->params->type, rsize, NULL);
|
|
|
|
/* Pad to word boundary */
|
|
plugin_populate_pdata(0, (byte *)&pdata);
|
|
xosgbpb_writew(pfile, pdata, (4 - ((rsize%4) == 0 ? 4 : (rsize%4))), NULL);
|
|
} else {
|
|
plugin_populate_pdata(0, (byte *)&pdata);
|
|
xosgbpb_writew(pfile, pdata, 4, NULL);
|
|
}
|
|
|
|
temp = params->params;
|
|
params->params = params->params->next;
|
|
xfree(temp);
|
|
}
|
|
|
|
/* Now write mandatory special parameters
|
|
*
|
|
* Case: Parameter:
|
|
*
|
|
* 0 BASEHREF
|
|
* 1 USERAGENT
|
|
* 2 UAVERSION
|
|
* 3 APIVERSION
|
|
* 4 BGCOLOR - needs fixing to work properly.
|
|
* Currently, it assumes FFFFFF00 (BBGGRR00)
|
|
*/
|
|
for(j=0; j!=5; j++) {
|
|
|
|
plugin_populate_pdata(4, (byte *)&pdata);
|
|
xosgbpb_writew(pfile, pdata, 4, NULL);
|
|
|
|
switch(j) {
|
|
|
|
case 0: rsize = 0;
|
|
rsize += (4 + 8);
|
|
rsize += (4 + strlen(params->basehref));
|
|
if((strlen(params->basehref)%4) != 0)
|
|
rsize += (4-(strlen(params->basehref)%4));
|
|
rsize += 4;
|
|
plugin_populate_pdata(rsize, (byte *)&pdata);
|
|
xosgbpb_writew(pfile, pdata, 4, NULL);
|
|
|
|
rsize = strlen("BASEHREF");
|
|
plugin_populate_pdata(rsize, (byte *)&pdata);
|
|
xosgbpb_writew(pfile, pdata, 4, NULL);
|
|
|
|
xosgbpb_writew(pfile, (byte const*)"BASEHREF", rsize, NULL);
|
|
plugin_populate_pdata(0, (byte *)&pdata);
|
|
xosgbpb_writew(pfile, pdata, (4 - ((rsize%4) == 0 ? 4 : (rsize%4))), NULL);
|
|
|
|
rsize = strlen(params->basehref);
|
|
plugin_populate_pdata(rsize, (byte *)&pdata);
|
|
xosgbpb_writew(pfile, pdata, 4, NULL);
|
|
|
|
xosgbpb_writew(pfile, (byte const*)params->basehref, rsize, NULL);
|
|
|
|
plugin_populate_pdata(0, (byte *)&pdata);
|
|
xosgbpb_writew(pfile, pdata, (4 - ((rsize%4) == 0 ? 4 : (rsize%4))), NULL);
|
|
plugin_populate_pdata(0, (byte *)&pdata);
|
|
xosgbpb_writew(pfile, pdata, 4, NULL);
|
|
|
|
break;
|
|
|
|
case 1: rsize = 0;
|
|
rsize += (4 + 9 + 3);
|
|
rsize += (4 + strlen("NetSurf"));
|
|
if((strlen("NetSurf")%4) != 0)
|
|
rsize += (4-(strlen("NetSurf")%4));
|
|
rsize += 4;
|
|
plugin_populate_pdata(rsize, (byte *)&pdata);
|
|
xosgbpb_writew(pfile, pdata, 4, NULL);
|
|
|
|
rsize = strlen("USERAGENT");
|
|
plugin_populate_pdata(rsize, (byte *)&pdata);
|
|
xosgbpb_writew(pfile, pdata, 4, NULL);
|
|
|
|
xosgbpb_writew(pfile, (byte const*)"USERAGENT", rsize, NULL);
|
|
plugin_populate_pdata(0, (byte *)&pdata);
|
|
xosgbpb_writew(pfile, pdata, (4 - ((rsize%4) == 0 ? 4 : (rsize%4))), NULL);
|
|
|
|
rsize = strlen("NetSurf");
|
|
plugin_populate_pdata(rsize, (byte *)&pdata);
|
|
xosgbpb_writew(pfile, pdata, 4, NULL);
|
|
|
|
xosgbpb_writew(pfile, (byte const*)"NetSurf", rsize, NULL);
|
|
plugin_populate_pdata(0, (byte *)&pdata);
|
|
xosgbpb_writew(pfile, pdata, (4 - ((rsize%4) == 0 ? 4 : (rsize%4))), NULL);
|
|
plugin_populate_pdata(0, (byte *)&pdata);
|
|
xosgbpb_writew(pfile, pdata, 4, NULL);
|
|
break;
|
|
|
|
case 2: rsize = 0;
|
|
rsize += (4 + 9 + 3);
|
|
rsize += (4 + strlen("0.01"));
|
|
if((strlen("0.01")%4) != 0)
|
|
rsize += (4-(strlen("0.01")%4));
|
|
rsize += 4;
|
|
plugin_populate_pdata(rsize, (byte *)&pdata);
|
|
xosgbpb_writew(pfile, pdata, 4, NULL);
|
|
|
|
rsize = strlen("UAVERSION");
|
|
plugin_populate_pdata(rsize, (byte *)&pdata);
|
|
xosgbpb_writew(pfile, pdata, 4, NULL);
|
|
|
|
xosgbpb_writew(pfile, (byte const*)"UAVERSION", rsize, NULL);
|
|
plugin_populate_pdata(0, (byte *)&pdata);
|
|
xosgbpb_writew(pfile, pdata, (4 - ((rsize%4) == 0 ? 4 : (rsize%4))), NULL);
|
|
|
|
rsize = strlen("0.01");
|
|
plugin_populate_pdata(rsize, (byte *)&pdata);
|
|
xosgbpb_writew(pfile, pdata, 4, NULL);
|
|
|
|
xosgbpb_writew(pfile, (byte const*)"0.01", rsize, NULL);
|
|
plugin_populate_pdata(0, (byte *)&pdata);
|
|
xosgbpb_writew(pfile, pdata, (4 - ((rsize%4) == 0 ? 4 : (rsize%4))), NULL);
|
|
plugin_populate_pdata(0, (byte *)&pdata);
|
|
xosgbpb_writew(pfile, pdata, 4, NULL);
|
|
break;
|
|
|
|
case 3: rsize = 0;
|
|
rsize += (4 + 10 + 2);
|
|
rsize += (4 + strlen("1.10"));
|
|
if((strlen("1.10")%4) != 0)
|
|
rsize += (4-(strlen("1.10")%4));
|
|
rsize += 4;
|
|
plugin_populate_pdata(rsize, (byte *)&pdata);
|
|
xosgbpb_writew(pfile, pdata, 4, NULL);
|
|
|
|
rsize = strlen("APIVERSION");
|
|
plugin_populate_pdata(rsize, (byte *)&pdata);
|
|
xosgbpb_writew(pfile, pdata, 4, NULL);
|
|
|
|
xosgbpb_writew(pfile, (byte const*)"APIVERSION", rsize, NULL);
|
|
plugin_populate_pdata(0, (byte *)&pdata);
|
|
xosgbpb_writew(pfile, pdata, (4 - ((rsize%4) == 0 ? 4 : (rsize%4))), NULL);
|
|
|
|
rsize = strlen("1.10");
|
|
plugin_populate_pdata(rsize, (byte *)&pdata);
|
|
xosgbpb_writew(pfile, pdata, 4, NULL);
|
|
|
|
xosgbpb_writew(pfile, (byte const*)"1.10", rsize, NULL);
|
|
plugin_populate_pdata(0, (byte *)&pdata);
|
|
xosgbpb_writew(pfile, pdata, (4 - ((rsize%4) == 0 ? 4 : (rsize%4))), NULL);
|
|
plugin_populate_pdata(0, (byte *)&pdata);
|
|
xosgbpb_writew(pfile, pdata, 4, NULL);
|
|
break;
|
|
case 4: rsize = 0;
|
|
rsize += (4 + 7 + 1);
|
|
rsize += (4 + strlen("FFFFFF00"));
|
|
if((strlen("FFFFFF00")%4) != 0)
|
|
rsize += (4-(strlen("FFFFFF00")%4));
|
|
rsize += 4;
|
|
plugin_populate_pdata(rsize, (byte *)&pdata);
|
|
xosgbpb_writew(pfile, pdata, 4, NULL);
|
|
|
|
rsize = strlen("BGCOLOR");
|
|
plugin_populate_pdata(rsize, (byte *)&pdata);
|
|
xosgbpb_writew(pfile, pdata, 4, NULL);
|
|
|
|
xosgbpb_writew(pfile, (byte const*)"BGCOLOR", rsize, NULL);
|
|
plugin_populate_pdata(0, (byte *)&pdata);
|
|
xosgbpb_writew(pfile, pdata, (4 - ((rsize%4) == 0 ? 4 : (rsize%4))), NULL);
|
|
|
|
rsize = strlen("FFFFFF00");
|
|
plugin_populate_pdata(rsize, (byte *)&pdata);
|
|
xosgbpb_writew(pfile, pdata, 4, NULL);
|
|
|
|
xosgbpb_writew(pfile, (byte const*)"FFFFFF00", rsize, NULL);
|
|
plugin_populate_pdata(0, (byte *)&pdata);
|
|
xosgbpb_writew(pfile, pdata, (4 - ((rsize%4) == 0 ? 4 : (rsize%4))), NULL);
|
|
plugin_populate_pdata(0, (byte *)&pdata);
|
|
xosgbpb_writew(pfile, pdata, 4, NULL);
|
|
break;
|
|
}
|
|
|
|
}
|
|
|
|
/* Write terminator */
|
|
plugin_populate_pdata(0, (byte *)&pdata);
|
|
xosgbpb_writew(pfile, pdata, 4, NULL);
|
|
xosfind_closew(pfile);
|
|
}
|
|
|
|
/**
|
|
* plugin_populate_pdata
|
|
* helper function for plugin_write_parameters_file
|
|
*/
|
|
void plugin_populate_pdata(int rsize, byte *pdata) {
|
|
|
|
pdata[0] = rsize & 0xff;
|
|
pdata[1] = (rsize >> 0x08) & 0xff;
|
|
pdata[2] = (rsize >> 0x10) & 0xff;
|
|
pdata[3] = (rsize >> 0x18) & 0xff;
|
|
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------*/
|
|
/* Plugin Stream handling functions */
|
|
/*-------------------------------------------------------------------------*/
|
|
|
|
/**
|
|
* plugin_create_stream
|
|
* creates a plugin stream
|
|
*/
|
|
void plugin_create_stream(struct browser_window *bw, struct object_params *params, struct content *c) {
|
|
|
|
// wimp_message *m = xcalloc(256, sizeof(char));
|
|
wimp_message m;
|
|
plugin_message_stream_new *pmsn;
|
|
struct plugin_message *temp;
|
|
int offset = 0;
|
|
unsigned char *pchar = (unsigned char*)&m.data;
|
|
|
|
pmsn = (plugin_message_stream_new*)&m.data;
|
|
pmsn->flags = 2;
|
|
pmsn->plugin = (plugin_p)params->plugin;
|
|
pmsn->browser = (plugin_b)params->browser;
|
|
pmsn->browser_stream = (plugin_bs)params->browser;
|
|
pmsn->end = c->data.plugin.length;
|
|
pmsn->last_modified_date = 0;
|
|
pmsn->notify_data = 0;
|
|
|
|
offset = 64;
|
|
pmsn->url.offset = offset;
|
|
strncpy((char*)&pchar[offset], c->url, (unsigned int)236-offset);
|
|
offset = offset + strlen(c->url) + 1;
|
|
if (offset > 235) {
|
|
LOG(("URL too long"));
|
|
// xfree(m);
|
|
return;
|
|
}
|
|
|
|
offset = (offset + 3) / 4 * 4;
|
|
pmsn->mime_type.offset = offset;
|
|
strncpy((char*)&pchar[offset], c->mime_type, (unsigned int)236-offset);
|
|
offset = offset + strlen(c->mime_type) + 1;
|
|
if (offset > 235) {
|
|
LOG(("mime_type too long"));
|
|
// xfree(m);
|
|
return;
|
|
}
|
|
pmsn->target_window.offset = 0;
|
|
|
|
m.size = (20 + offset + 3) / 4 * 4;
|
|
m.your_ref = 0;
|
|
m.action = message_PLUG_IN_STREAM_NEW;
|
|
|
|
temp = plugin_add_message_to_linked_list(pmsn->browser, pmsn->plugin, &m, 0);
|
|
|
|
LOG(("message length = %d", m.size));
|
|
|
|
LOG(("Sending message &4D548"));
|
|
xwimp_send_message(wimp_USER_MESSAGE_RECORDED, &m, (wimp_t)params->plugin_task);
|
|
|
|
while(temp->poll == 0)
|
|
gui_poll();
|
|
|
|
pmsn = (plugin_message_stream_new*)&temp->reply->m->data;
|
|
params->browser_stream = params->browser;
|
|
params->plugin_stream = (int)pmsn->stream;
|
|
LOG(("%d, %d, %d", (int)pmsn->stream, params->plugin_stream, params->browser_stream));
|
|
if((pmsn->flags & 0x02) | (pmsn->flags & 0x03)) {
|
|
plugin_write_stream_as_file(bw, params, c);
|
|
}
|
|
|
|
/* clean up */
|
|
plugin_remove_message_from_linked_list(temp->reply);
|
|
plugin_remove_message_from_linked_list(temp);
|
|
// xfree(m);
|
|
}
|
|
|
|
/**
|
|
* plugin_write_stream_as_file
|
|
* writes a stream as a file
|
|
*/
|
|
void plugin_write_stream_as_file(struct browser_window *bw, struct object_params *params, struct content *c) {
|
|
|
|
// wimp_message *m = xcalloc(256, sizeof(char));
|
|
wimp_message m;
|
|
plugin_message_stream_as_file *pmsaf;
|
|
int offset = 0;
|
|
unsigned int filetype;
|
|
unsigned char *pchar = (unsigned char*)&m.data;
|
|
char *filename = strdup(params->filename), *p;
|
|
|
|
pmsaf = (plugin_message_stream_as_file*)&m.data;
|
|
|
|
pmsaf->flags = 0;
|
|
pmsaf->plugin = (plugin_p)params->plugin;
|
|
pmsaf->browser = (plugin_b)params->browser;
|
|
pmsaf->stream = (plugin_s)params->plugin_stream;
|
|
pmsaf->browser_stream = (plugin_bs)params->browser_stream;
|
|
pmsaf->end = 0;
|
|
pmsaf->last_modified_date = 0;
|
|
pmsaf->notify_data = 0;
|
|
|
|
offset = 60;
|
|
pmsaf->url.offset = offset;
|
|
strncpy((char*)&pchar[offset], c->url, (unsigned int)236-offset);
|
|
offset = offset + strlen(c->url) + 1;
|
|
if (offset > 235) {
|
|
LOG(("URL too long"));
|
|
// xfree(m);
|
|
return;
|
|
}
|
|
|
|
offset = (offset + 3) / 4 * 4;
|
|
pmsaf->filename.offset = offset;
|
|
p = strrchr((const char*)filename, 'p');
|
|
filename[(p-filename)] = 'd';
|
|
strncpy((char*)&pchar[offset], filename, (unsigned int)236-offset);
|
|
offset = offset + strlen(filename) + 1;
|
|
if (offset > 235) {
|
|
LOG(("filename too long"));
|
|
// xfree(m);
|
|
return;
|
|
}
|
|
|
|
m.size = (20 + offset + 3) / 4 * 4;
|
|
m.your_ref = 0;
|
|
m.action = message_PLUG_IN_STREAM_AS_FILE;
|
|
|
|
xmimemaptranslate_mime_type_to_filetype(c->mime_type, (bits *) &filetype);
|
|
xosfile_save_stamped((char const*)filename, filetype, c->data.plugin.data, c->data.plugin.data + c->data.plugin.length);
|
|
|
|
LOG(("message length = %d", m.size));
|
|
|
|
LOG(("Sending message &4D54C"));
|
|
xwimp_send_message(wimp_USER_MESSAGE, &m, (wimp_t)params->plugin_task);
|
|
// xfree(m);
|
|
}
|
|
|
|
/**
|
|
* plugin_destroy_stream
|
|
* destroys a plugin stream
|
|
*/
|
|
void plugin_destroy_stream(struct browser_window *bw, struct object_params *params, struct content *c) {
|
|
|
|
// wimp_message *m = xcalloc(256, sizeof(char));
|
|
wimp_message m;
|
|
plugin_message_stream_destroy *pmsd;
|
|
int offset = 0;
|
|
unsigned char *pchar = (unsigned char*)&m.data;
|
|
|
|
pmsd = (plugin_message_stream_destroy*)&m.data;
|
|
|
|
pmsd->flags = 0;
|
|
pmsd->plugin = (plugin_p)params->plugin;
|
|
pmsd->browser = (plugin_b)params->browser;
|
|
pmsd->stream = (plugin_s)params->plugin_stream;
|
|
pmsd->browser_stream = (plugin_bs)params->browser_stream;
|
|
pmsd->end = 0;
|
|
pmsd->last_modified_date = 0;
|
|
pmsd->notify_data = 0;
|
|
pmsd->reason = plugin_STREAM_DESTROY_FINISHED;
|
|
|
|
offset = 60;
|
|
pmsd->url.offset = offset;
|
|
strncpy((char*)&pchar[offset], c->url, (unsigned int)236-offset);
|
|
offset = offset + strlen(c->url) + 1;
|
|
if (offset > 235) {
|
|
LOG(("URL too long"));
|
|
// xfree(m);
|
|
return;
|
|
}
|
|
|
|
m.size = (20 + offset + 3) / 4 * 4;
|
|
m.your_ref = 0;
|
|
m.action = message_PLUG_IN_STREAM_DESTROY;
|
|
|
|
LOG(("Sending message &4D549"));
|
|
xwimp_send_message(wimp_USER_MESSAGE, &m, (wimp_t)params->plugin_task);
|
|
// xfree(m);
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------*/
|
|
/* Linked List handling functions */
|
|
/*-------------------------------------------------------------------------*/
|
|
|
|
/**
|
|
* plugin_add_message_to_linked_list
|
|
* adds a message to the list
|
|
*/
|
|
struct plugin_message *plugin_add_message_to_linked_list(plugin_b browser, plugin_p plugin, wimp_message *m, struct plugin_message *reply) {
|
|
|
|
struct plugin_message *npm = xcalloc(1, sizeof(*npm));
|
|
|
|
npm->poll = 0;
|
|
npm->browser = browser;
|
|
npm->plugin = plugin;
|
|
npm->m = m;
|
|
npm->reply = reply;
|
|
npm->prev = pmlist->prev;
|
|
npm->next = pmlist;
|
|
pmlist->prev->next = npm;
|
|
pmlist->prev = npm;
|
|
|
|
LOG(("Added Message: %p", npm));
|
|
|
|
return pmlist->prev;
|
|
}
|
|
|
|
/**
|
|
* plugin_remove_message_from_linked_list
|
|
* removes a message from the list
|
|
*/
|
|
void plugin_remove_message_from_linked_list(struct plugin_message* m) {
|
|
|
|
m->prev->next = m->next;
|
|
m->next->prev = m->prev;
|
|
LOG(("Deleted Message: %p", m));
|
|
xfree(m);
|
|
}
|
|
|
|
/**
|
|
* plugin_get_message_from_linked_list
|
|
* retrieves a message from the list
|
|
* returns NULL if no message is found
|
|
*/
|
|
struct plugin_message *plugin_get_message_from_linked_list(int ref) {
|
|
|
|
struct plugin_message *npm;
|
|
|
|
for(npm = pmlist->next; npm != pmlist && npm->m->my_ref != ref;
|
|
npm = npm->next)
|
|
LOG(("my_ref: %d, ref: %d", npm->m->my_ref, ref));
|
|
|
|
LOG(("my_ref: %d, ref: %d", npm->m->my_ref, ref));
|
|
if(npm != pmlist) {
|
|
LOG(("Got message: %p", npm));
|
|
return npm;
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
/**
|
|
* plugin_add_instance_to_list
|
|
* Adds a plugin instance to the list of plugin instances.
|
|
*/
|
|
void plugin_add_instance_to_list(struct content *c, struct browser_window *bw, struct content *page, struct box *box, struct object_params *params, void **state) {
|
|
|
|
struct plugin_list *npl = xcalloc(1, sizeof(*npl));
|
|
|
|
npl->c = c;
|
|
npl->bw = bw;
|
|
npl->page = page;
|
|
npl->box = box;
|
|
npl->params = params;
|
|
npl->state = state;
|
|
npl->prev = plist->prev;
|
|
npl->next = plist;
|
|
plist->prev->next = npl;
|
|
plist->prev = npl;
|
|
}
|
|
|
|
/**
|
|
* plugin_remove_instance_from_list
|
|
* Removes a plugin instance from the list
|
|
*/
|
|
void plugin_remove_instance_from_list(struct object_params *params) {
|
|
|
|
struct plugin_list *temp =
|
|
plugin_get_instance_from_list((plugin_b)params->browser,
|
|
(plugin_p)params->plugin);
|
|
if(temp != NULL) {
|
|
|
|
temp->prev->next = temp->next;
|
|
temp->next->prev = temp->prev;
|
|
xfree(temp);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* plugin_get_instance_from_list
|
|
* retrieves an instance of a plugin from the list
|
|
* returns NULL if no instance is found
|
|
*/
|
|
struct plugin_list *plugin_get_instance_from_list(plugin_b browser, plugin_p plugin) {
|
|
|
|
struct plugin_list *npl;
|
|
|
|
for(npl = plist->next; (npl != plist)
|
|
&& (((plugin_b)npl->params->browser != browser)
|
|
&& ((plugin_p)npl->params->plugin != plugin));
|
|
npl = npl->next)
|
|
;
|
|
|
|
if(npl != plist)
|
|
return npl;
|
|
|
|
return NULL;
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------*/
|
|
/* WIMP Message processing functions */
|
|
/*-------------------------------------------------------------------------*/
|
|
|
|
/**
|
|
* plugin_msg_parse
|
|
* parses wimp messages
|
|
*/
|
|
void plugin_msg_parse(wimp_message *message, int ack)
|
|
{
|
|
LOG(("Parsing message"));
|
|
switch(message->action) {
|
|
|
|
case message_PLUG_IN_OPENING:
|
|
plugin_opening(message);
|
|
break;
|
|
case message_PLUG_IN_CLOSED:
|
|
plugin_closed(message);
|
|
break;
|
|
case message_PLUG_IN_RESHAPE_REQUEST:
|
|
plugin_reshape_request(message);
|
|
break;
|
|
case message_PLUG_IN_FOCUS:
|
|
// plugin_focus();
|
|
break;
|
|
case message_PLUG_IN_URL_ACCESS:
|
|
// plugin_url_access();
|
|
break;
|
|
case message_PLUG_IN_STATUS:
|
|
plugin_status(message);
|
|
break;
|
|
case message_PLUG_IN_BUSY:
|
|
// plugin_busy();
|
|
break;
|
|
/* OSLib doesn't provide this, as it's
|
|
* reasonably new and not obviously documented.
|
|
* We ignore it for now.
|
|
|
|
case message_PLUG_IN_INFORMED:
|
|
*/
|
|
case message_PLUG_IN_STREAM_NEW:
|
|
plugin_stream_new(message);
|
|
break;
|
|
case message_PLUG_IN_STREAM_WRITE:
|
|
// plugin_stream_write();
|
|
break;
|
|
case message_PLUG_IN_STREAM_WRITTEN:
|
|
// plugin_stream_written();
|
|
break;
|
|
case message_PLUG_IN_STREAM_DESTROY:
|
|
// plugin_stream_destroy();
|
|
break;
|
|
|
|
/* These cases occur when a message is bounced
|
|
* For simplicity, we do nothing unless the message came in
|
|
* a wimp_USER_MESSAGE_ACKNOWLEDGE (ie ack = 1)
|
|
*/
|
|
case message_PLUG_IN_OPEN:
|
|
if(ack)
|
|
plugin_open(message);
|
|
break;
|
|
case message_PLUG_IN_CLOSE:
|
|
if(ack)
|
|
plugin_close(message);
|
|
break;
|
|
case message_PLUG_IN_RESHAPE:
|
|
case message_PLUG_IN_STREAM_AS_FILE:
|
|
case message_PLUG_IN_NOTIFY:
|
|
case message_PLUG_IN_ABORT:
|
|
case message_PLUG_IN_ACTION:
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* plugin_open
|
|
* handles receipt of plugin_open messages
|
|
*/
|
|
void plugin_open(wimp_message *message) {
|
|
|
|
struct plugin_message *npm = plugin_get_message_from_linked_list(message->my_ref);
|
|
|
|
LOG(("Acknowledgement of %p", npm));
|
|
/* notify plugin_open message entry in list */
|
|
if (npm != NULL)
|
|
npm->poll = 1;
|
|
}
|
|
|
|
/**
|
|
* plugin_opening
|
|
* handles receipt of plugin_open messages
|
|
*/
|
|
void plugin_opening(wimp_message *message) {
|
|
|
|
struct plugin_message *npm = plugin_get_message_from_linked_list(message->your_ref);
|
|
struct plugin_message *reply;
|
|
plugin_message_opening *pmo = (plugin_message_opening*)&message->data;
|
|
|
|
/* add this message to linked list */
|
|
reply = plugin_add_message_to_linked_list(pmo->browser, pmo->plugin, message, 0);
|
|
|
|
/* notify plugin_open message entry in list */
|
|
if (npm != NULL) {
|
|
|
|
npm->poll = 1;
|
|
npm->plugin = pmo->plugin;
|
|
npm->reply = reply;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* plugin_close
|
|
* handles receipt of plugin_close messages
|
|
*/
|
|
void plugin_close(wimp_message *message) {
|
|
|
|
struct plugin_message *npm = plugin_get_message_from_linked_list(message->my_ref);
|
|
|
|
/* notify plugin_open message entry in list */
|
|
if (npm != NULL)
|
|
npm->poll = 1;
|
|
}
|
|
|
|
/**
|
|
* plugin_closed
|
|
* handles receipt of plugin_closed messages
|
|
*/
|
|
void plugin_closed(wimp_message *message) {
|
|
|
|
struct plugin_message *npm = plugin_get_message_from_linked_list(message->your_ref);
|
|
struct plugin_message *reply;
|
|
plugin_message_closed *pmc = (plugin_message_closed*)&message->data;
|
|
|
|
/* add this message to linked list */
|
|
reply = plugin_add_message_to_linked_list(pmc->browser, pmc->plugin, message, 0);
|
|
|
|
/* notify plugin_open message entry in list */
|
|
if (npm != NULL) {
|
|
|
|
npm->poll = 1;
|
|
npm->reply = reply;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* plugin_reshape_request
|
|
* handles receipt of plugin_reshape_request messages
|
|
*/
|
|
void plugin_reshape_request(wimp_message *message) {
|
|
|
|
struct plugin_message *npm;
|
|
struct plugin_list *npl;
|
|
plugin_message_reshape_request *pmrr = (plugin_message_reshape_request*)&message->data;
|
|
|
|
/* add this message to linked list */
|
|
npm = plugin_add_message_to_linked_list(pmrr->browser, pmrr->plugin, message, 0);
|
|
|
|
/* TODO - need to find a way of forcing the browser to resize the
|
|
* box containing this object. Then issue a Plugin_Reshape.
|
|
*/
|
|
npl = plugin_get_instance_from_list(pmrr->browser, pmrr->plugin);
|
|
plugin_remove_message_from_linked_list(npm); /* lose this later */
|
|
|
|
LOG(("requested (width, height): (%d, %d)", pmrr->size.x, pmrr->size.y));
|
|
}
|
|
|
|
/**
|
|
* plugin_stream_new
|
|
* handles receipt of plugin_stream_new messages
|
|
*/
|
|
void plugin_stream_new(wimp_message *message) {
|
|
|
|
struct plugin_message *npm = plugin_get_message_from_linked_list(message->your_ref);
|
|
struct plugin_message *reply;
|
|
plugin_message_stream_new *pmsn = (plugin_message_stream_new*)&message->data;
|
|
|
|
/* add this message to linked list */
|
|
reply = plugin_add_message_to_linked_list(pmsn->browser, pmsn->plugin, message, 0);
|
|
|
|
/* notify plugin_open message entry in list */
|
|
if(npm != NULL) {
|
|
|
|
npm->poll = 1;
|
|
npm->plugin = pmsn->plugin;
|
|
npm->reply = reply;
|
|
}
|
|
|
|
}
|
|
|
|
/**
|
|
* plugin_status
|
|
* handles receipt of plugin_status messages
|
|
*/
|
|
void plugin_status(wimp_message *message) {
|
|
|
|
plugin_message_status *pms = (plugin_message_status*)&message->data;
|
|
struct plugin_list *npl = plugin_get_instance_from_list(pms->browser, pms->plugin);
|
|
|
|
gui_window_set_status(npl->bw->window,
|
|
(const char*)plugin_get_string_value(pms->message,
|
|
(char*)pms));
|
|
}
|
|
|
|
/**
|
|
* plugin_get_string_value
|
|
* utility function to grab string data from plugin message blocks
|
|
*/
|
|
char *plugin_get_string_value(os_string_value string, char *msg) {
|
|
|
|
if(string.offset == 0 || string.offset > 256) {
|
|
return string.pointer;
|
|
}
|
|
return &msg[string.offset];
|
|
}
|