1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*************************************************************************
3 *
4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 *
6 * Copyright 2000, 2010 Oracle and/or its affiliates.
7 *
8 * OpenOffice.org - a multi-platform office productivity suite
9 *
10 * This file is part of OpenOffice.org.
11 *
12 * OpenOffice.org is free software: you can redistribute it and/or modify
13 * it under the terms of the GNU Lesser General Public License version 3
14 * only, as published by the Free Software Foundation.
15 *
16 * OpenOffice.org is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU Lesser General Public License version 3 for more details
20 * (a copy is included in the LICENSE file that accompanied this code).
21 *
22 * You should have received a copy of the GNU Lesser General Public License
23 * version 3 along with OpenOffice.org. If not, see
24 * <http://www.openoffice.org/license.html>
25 * for a copy of the LGPLv3 License.
26 *
27 ************************************************************************/
28
29#ifdef UNIX
30
31#define XP_UNIX 1
32
33#include <strings.h>
34#include <arpa/inet.h>
35#include <netinet/in.h>
36#include <sys/types.h>
37#include <sys/socket.h>
38#include <sys/stat.h>
39#include <sys/wait.h>
40#include <unistd.h>
41#include <fcntl.h>
42
43#endif //end of UNIX
44
45#ifdef WNT
46
47#ifdef _MSC_VER
48#pragma warning (push,1)
49#pragma warning (disable:4668)
50#endif
51
52#include <windows.h>
53#include <direct.h>
54#include <stdlib.h>
55#include <io.h>
56#include <sys/types.h>
57#include <fcntl.h>
58
59#ifdef _MSC_VER
60#pragma warning (pop)
61#endif
62
63#include "tools/pathutils.hxx"
64
65#endif //end of WNT
66
67
68#include <stdio.h>
69
70#include <string.h>
71#include <errno.h>
72#include "boost/scoped_array.hpp"
73
74#include "npapi.h"
75#include "npshell.hxx"
76#include "so_env.hxx"
77#include "so_msg.hxx"
78#include "ns_debug.hxx"
79
80
81#include "nsp_func.hxx"
82
83#include "npsdk/plugin.h"
84
85#include <comphelper/documentconstants.hxx>
86
87#ifdef _MSC_VER
88#define NP_DLLPUBLIC
89#else
90#define NP_DLLPUBLIC SAL_DLLPUBLIC_EXPORT
91#endif
92
93#if defined WNT
94static SECURITY_ATTRIBUTES NSP_pipe_access = {
95 sizeof (SECURITY_ATTRIBUTES), NULL, TRUE };
96#define NSP_Inherited_Pipe(fd) \
97 (!CreatePipe(&fd[0], &fd[1], &NSP_pipe_access, 1024 * 10))
98#else
99#define NSP_Inherited_Pipe(fp) pipe(fd)
100#endif
101
102/***********************************************************************
103 *
104 * Implementations of plugin API functions
105 *
106 ***********************************************************************/
107
108static NSP_Mute_Obj send_lock = NSP_New_Mute_Obj();
109static NSP_PIPE_FD write_fd = (NSP_PIPE_FD)-1;
110
111
112long int NSP_WriteToPipe(NSP_PIPE_FD fp, void* buf, unsigned long int len)
113{
114 unsigned long int len_unix = 0, len_wnt = 0;
115
116 len_unix = NSP_Write_Pipe(fp, buf, len, &len_wnt);
117#ifdef UNIX
118 (void)len_wnt;
119 return len_unix;
120#endif //end of UNIX
121#ifdef WNT
122 (void)len_unix;
123 return len_wnt;
124#endif //end of WNT
125
126}
127
128#ifdef UNIX
129static pid_t nChildPID = 0;
130#endif
131
132#if defined WNT
133
134#define MY_LENGTH(s) (sizeof (s) / sizeof *(s) - 1)
135#define MY_STRING(s) (s), MY_LENGTH(s)
136
137namespace {
138
139bool extendEnvironment(boost::scoped_array< WCHAR > * environment) {
140 WCHAR path[MAX_PATH];
141 int len = MultiByteToWideChar(
142 CP_ACP, MB_PRECOMPOSED, findInstallDir(), -1, path, MAX_PATH);
143 //TODO: conversion errors
144 if (len == 0 ||
145 (tools::buildPath(path, path, path + len - 1, MY_STRING(L"\\ure-link"))
146 == NULL))
147 {
148 return false;
149 }
150 WCHAR * pathEnd = tools::resolveLink(path);
151 if (pathEnd == NULL) {
152 return false;
153 }
154 pathEnd = tools::buildPath(path, path, pathEnd, MY_STRING(L"\\bin"));
155 if (pathEnd == NULL) {
156 return false;
157 }
158 WCHAR const * env = GetEnvironmentStringsW();
159 if (env == NULL) {
160 return false;
161 }
162 WCHAR const * p = env;
163 WCHAR const * p1 = NULL;
164 while (*p != L'\0') {
165 size_t n = wcslen(p);
166 if (p1 == NULL && n >= MY_LENGTH(L"PATH=") &&
167 (p[0] == L'P' || p[0] == L'p') &&
168 (p[1] == L'A' || p[1] == L'a') &&
169 (p[2] == L'T' || p[2] == L't') &&
170 (p[3] == L'H' || p[3] == L'h') && p[4] == L'=')
171 {
172 p1 = p + MY_LENGTH(L"PATH=");
173 //TODO: check whether the path is already present in PATH (at the
174 // beginning of PATH?)
175 }
176 p += n + 1;
177 }
178 ++p;
179 if (p1 == NULL) {
180 environment->reset(
181 new WCHAR[MY_LENGTH(L"PATH=") + (pathEnd - path) + 1 + (p - env)]);
182 //TODO: overflow
183 memcpy(environment->get(), MY_STRING(L"PATH=") * sizeof (WCHAR));
184 memcpy(
185 environment->get() + MY_LENGTH(L"PATH="), path,
186 ((pathEnd - path) + 1) * sizeof (WCHAR));
187 memcpy(
188 environment->get() + MY_LENGTH(L"PATH=") + (pathEnd - path) + 1,
189 env, (p - env) * sizeof (WCHAR));
190 } else {
191 environment->reset(
192 new WCHAR[(p - env) + (pathEnd - path) + MY_LENGTH(L";")]);
193 //TODO: overflow
194 memcpy(environment->get(), env, (p1 - env) * sizeof (WCHAR));
195 memcpy(
196 environment->get() + (p1 - env), path,
197 (pathEnd - path) * sizeof (WCHAR));
198 environment->get()[(p1 - env) + (pathEnd - path)] = L';';
199 memcpy(
200 environment->get() + (p1 - env) + (pathEnd - path) + 1, p1,
201 (p - p1) * sizeof (WCHAR));
202 }
203 return true;
204}
205
206}
207#endif
208
209// start nspluin executable in child process, and use pipe to talk with it
210int do_init_pipe()
211{
212 debug_fprintf(NSP_LOG_APPEND, "enter do_init_pipe 1\n");
213 NSP_PIPE_FD fd[2];
214
215 if( 0 != NSP_Inherited_Pipe(fd) )
216 return NPERR_GENERIC_ERROR;
217
218 write_fd = fd[1]; // write fd
219#ifdef UNIX
220 // the parent process will wait for the child process in NPP_Shutdown code
221 nChildPID = fork();
222
223 if( ! nChildPID ) // child process
224#endif //end of UNIX
225 {
226#ifdef UNIX
227 char s_read_fd[16] = {0};
228 char s_write_fd[16] = {0};
229 sprintf(s_read_fd, "%d", fd[0]);
230 sprintf(s_write_fd, "%d", fd[1]);
231 char const * progdir = findProgramDir();
232 boost::scoped_array< char > exepath(
233 new char[strlen(progdir) + RTL_CONSTASCII_LENGTH("/nsplugin") + 1]);
234 sprintf(exepath.get(), "%s/nsplugin", progdir);
235 boost::scoped_array< char > inifilepath(
236 new char[
237 RTL_CONSTASCII_LENGTH(
238 "-env:INIFILENAME=vnd.sun.star.pathname:") +
239 strlen(progdir) + RTL_CONSTASCII_LENGTH("/redirectrc") + 1]);
240 //TODO: overflow
241 sprintf(
242 inifilepath.get(),
243 "-env:INIFILENAME=vnd.sun.star.pathname:%s/redirectrc", progdir);
244 execl(
245 exepath.get(), exepath.get(), s_read_fd, s_write_fd,
246 inifilepath.get(), progdir, NULL);
247 _exit(255);
248#endif //end of UNIX
249#ifdef WNT
250 WCHAR s_read_fd[16] = {0};
251 WCHAR s_write_fd[16] = {0};
252 wsprintfW(s_read_fd, L"%d", fd[0]);
253 wsprintfW(s_write_fd, L"%d", fd[1]);
254 boost::scoped_array< WCHAR > env;
255 if (!extendEnvironment(&env)) {
256 return NPERR_GENERIC_ERROR;
257 }
258 WCHAR path[MAX_PATH];
259 int pathLen = MultiByteToWideChar(
260 CP_ACP, MB_PRECOMPOSED, findProgramDir(), -1, path, MAX_PATH);
261 //TODO: conversion errors
262 if (pathLen == 0) {
263 return NPERR_GENERIC_ERROR;
264 }
265 WCHAR exe[MAX_PATH];
266 WCHAR * exeEnd = tools::buildPath(
267 exe, path, path + pathLen - 1, MY_STRING(L"\\nsplugin.exe"));
268 if (exeEnd == NULL) {
269 return NPERR_GENERIC_ERROR;
270 }
271 WCHAR ini[MAX_PATH];
272 WCHAR * iniEnd = tools::buildPath(
273 ini, path, path + pathLen - 1, MY_STRING(L"\\redirect.ini"));
274 if (iniEnd == NULL) {
275 return NPERR_GENERIC_ERROR;
276 }
277 size_t len = MY_LENGTH(L"\"") + (exeEnd - exe) + MY_LENGTH(L"\" ") +
278 wcslen(s_read_fd) + MY_LENGTH(L" ") + wcslen(s_write_fd) +
279 MY_LENGTH(L" \"-env:INIFILENAME=vnd.sun.star.pathname:") +
280 (iniEnd - ini) + MY_LENGTH(L"\"") + 1; //TODO: overflow
281 boost::scoped_array< WCHAR > args(new WCHAR[len]);
282 _snwprintf(
283 args.get(), len,
284 L"\"%s\" %s %s \"-env:INIFILENAME=vnd.sun.star.pathname:%s\"", exe,
285 s_read_fd, s_write_fd, ini);
286 STARTUPINFOW NSP_StarInfo;
287 memset((void*) &NSP_StarInfo, 0, sizeof(STARTUPINFOW));
288 NSP_StarInfo.cb = sizeof(STARTUPINFOW);
289 PROCESS_INFORMATION NSP_ProcessInfo;
290 memset((void*)&NSP_ProcessInfo, 0, sizeof(PROCESS_INFORMATION));
291 if(!CreateProcessW(
292 exe, args.get(), NULL, NULL, TRUE,
293 CREATE_NO_WINDOW | CREATE_UNICODE_ENVIRONMENT, env.get(), path,
294 &NSP_StarInfo, &NSP_ProcessInfo))
295 {
296 DWORD Err = GetLastError();
297 (void)Err;
298 }
299#endif //end of WNT
300 }
301 NSP_Close_Pipe(fd[0]);
302 return NPERR_NO_ERROR;
303}
304
305bool sendMsg( PLUGIN_MSG* pMsg, size_t len, int iEnsure)
306{
307 NSP_Lock_Mute_Obj(send_lock);
308 size_t len_w = 0;
309
310 debug_fprintf(NSP_LOG_APPEND, "try to send message type:%d; len: %d\n", pMsg->msg_id, len);
311 /*
312 debug_fprintf(NSP_LOG_APPEND, "NSPlugin Message: msg_id:%d; instance_id:%d;
313 wnd_id:%d;wnd_x:%d;wnd_y:%d;wnd_w:%d;wnd_h:%d; url:%s\n",
314 pMsg->msg_id, pMsg->instance_id, pMsg->wnd_id,
315 pMsg->wnd_x, pMsg->wnd_y, pMsg->wnd_w, pMsg->wnd_h, pMsg->url);*/
316 len_w = NSP_WriteToPipe(write_fd, (void*) pMsg, len);
317 if (len_w != len){
318 if(errno == EPIPE) // If pipe breaks, then init pipe again and resend the msg
319 {
320 if(iEnsure){
321 debug_fprintf(NSP_LOG_APPEND, "send message error, plugin exec need to be restart\n");
322 NSP_Close_Pipe(write_fd);
323 do_init_pipe();
324 len_w = NSP_WriteToPipe(write_fd, (void*) pMsg, len);
325 }
326 }
327 else if(errno == EINTR) // If interrupted by signal, then continue to send
328 {
329 long new_len;
330 debug_fprintf(NSP_LOG_APPEND, "send message error, send intrrupted by singal, resend again\n");
331 new_len = NSP_WriteToPipe(write_fd, (char*)pMsg+len_w, len-len_w);
332 len_w = len_w + new_len;
333 }
334 else // else return error
335 {
336 debug_fprintf(NSP_LOG_APPEND, "send message error :%s.\n", strerror(errno));
337 len_w = 0;
338 }
339 }
340 NSP_Unlock_Mute_Obj(send_lock);
341 debug_fprintf(NSP_LOG_APPEND, "send message success!\n");
342 return len_w == len;
343}
344
345extern "C"
346{
347char* pMimeTypes = const_cast< char* >( "application/msword:doc:MS Word 97-2003 document;"
348"application/msword:dot:MS Word 97-2003 document template;"
349"application/vnd.openxmlformats-officedocument.wordprocessingml.document:docx:MS Word document;"
350"application/vnd.ms-word.document.macroenabled.12:docm:MS Word document with macros;"
351"application/vnd.openxmlformats-officedocument.wordprocessingml.template:dotx:MS Word document template;"
352"application/vnd.ms-word.template.macroenabled.12:dotm:MS Word document template with macros;"
353"application/rtf:rtf:Rich Text Format;"
354"application/vnd.ms-excel:xls:MS Excel 97-2003 spreadsheet;"
355"application/vnd.ms-excel:xlt:MS Excel 97-2003 spreadsheet template;"
356"application/vnd.ms-excel:xla:MS Excel 97-2003 spreadsheet;"
357"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet:xlsx:MS Excel spreadsheet;"
358"application/vnd.ms-excel.sheet.macroenabled.12:xlsm:MS Excel spreadsheet with macros;"
359"application/vnd.openxmlformats-officedocument.spreadsheetml.template:xltx:MS Excel spreadsheet template;"
360"application/vnd.ms-excel.template.macroenabled.12:xltm:MS Excel spreadsheet template with macros;"
361"application/vnd.ms-powerpoint:ppt:MS PowerPoint 97-2003 presentation;"
362"application/vnd.openxmlformats-officedocument.presentationml.presentation:pptx:MS PowerPoint presentation;"
363"application/vnd.ms-powerpoint.presentation.macroenabled.12:pptm:MS PowerPoint presentation with macros;"
364"application/vnd.openxmlformats-officedocument.presentationml.template:potx:MS PowerPoint presentation template;"
365"application/vnd.ms-powerpoint.template.macroenabled.12:potm:MS PowerPoint presentation template with macros;"
366MIMETYPE_VND_SUN_XML_CALC_ASCII ":sxc:StarOffice 6.0/7 Spreadsheet;"
367MIMETYPE_VND_SUN_XML_CALC_TEMPLATE_ASCII":stc:StarOffice 6.0/7 Spreadsheet Template;"
368MIMETYPE_VND_SUN_XML_DRAW_ASCII ":sxd:StarOffice 6.0/7 Drawing;"
369MIMETYPE_VND_SUN_XML_DRAW_TEMPLATE_ASCII ":std:StarOffice 6.0/7 Drawing Template;"
370MIMETYPE_VND_SUN_XML_IMPRESS_ASCII ":sxi:StarOffice 6.0/7 Presentation;"
371MIMETYPE_VND_SUN_XML_IMPRESS_TEMPLATE_ASCII ":sti:StarOffice 6.0/7 Presentation Template;"
372MIMETYPE_VND_SUN_XML_MATH_ASCII ":sxm:StarOffice 6.0/7 Formula;"
373MIMETYPE_VND_SUN_XML_WRITER_ASCII ":sxw:StarOffice 6.0/7 Text Document;"
374MIMETYPE_VND_SUN_XML_WRITER_GLOBAL_ASCII ":sxg:StarOffice 6.0/7 Master Document;"
375MIMETYPE_VND_SUN_XML_WRITER_TEMPLATE_ASCII ":stw:StarOffice 6.0/7 Text Document Template;"
376MIMETYPE_OASIS_OPENDOCUMENT_TEXT_ASCII ":odt:OpenDocument Text;"
377MIMETYPE_OASIS_OPENDOCUMENT_TEXT_ASCII "-flat-xml:fodt:OpenDocument Text Flat XML;"
378MIMETYPE_OASIS_OPENDOCUMENT_TEXT_TEMPLATE_ASCII ":ott:OpenDocument Text Template;"
379MIMETYPE_OASIS_OPENDOCUMENT_TEXT_GLOBAL_ASCII ":odm:OpenDocument Master Document;"
380MIMETYPE_OASIS_OPENDOCUMENT_TEXT_WEB_ASCII ":oth:HTML Document Template;"
381MIMETYPE_OASIS_OPENDOCUMENT_SPREADSHEET_ASCII ":ods:OpenDocument Spreadsheet;"
382MIMETYPE_OASIS_OPENDOCUMENT_SPREADSHEET_ASCII "-flat-xml:fods:OpenDocument Spreadsheet Flat XML;"
383MIMETYPE_OASIS_OPENDOCUMENT_SPREADSHEET_TEMPLATE_ASCII ":ots:OpenDocument Spreadsheet Template;"
384MIMETYPE_OASIS_OPENDOCUMENT_DRAWING_ASCII ":odg:OpenDocument Drawing;"
385MIMETYPE_OASIS_OPENDOCUMENT_DRAWING_ASCII "-flat-xml:fodg:OpenDocument Drawing Flat XML;"
386MIMETYPE_OASIS_OPENDOCUMENT_DRAWING_TEMPLATE_ASCII ":otg:OpenDocument Drawing Template;"
387MIMETYPE_OASIS_OPENDOCUMENT_PRESENTATION_ASCII ":odp:OpenDocument Presentation;"
388MIMETYPE_OASIS_OPENDOCUMENT_PRESENTATION_ASCII "-flat-xml:fodp:OpenDocument Presentation Flat XML;"
389MIMETYPE_OASIS_OPENDOCUMENT_PRESENTATION_TEMPLATE_ASCII ":otp:OpenDocument Presentation Template;"
390MIMETYPE_OASIS_OPENDOCUMENT_FORMULA_ASCII ":odf:OpenDocument Formula;" );
391
392NP_DLLPUBLIC
393#ifndef HAVE_NON_CONST_NPP_GETMIMEDESCRIPTION
394const
395#endif
396char*
397NPP_GetMIMEDescription(void)
398{
399 debug_fprintf(NSP_LOG_APPEND, "print by Netscape Plugin, NPP_GetMIMEDescription:%s.\n", pMimeTypes);
400 return(pMimeTypes);
401}
402
403#ifdef UNIX
404NP_DLLPUBLIC NPError
405NPP_GetValue(NPP /*instance*/, NPPVariable variable, void *value)
406{
407 NPError err = NPERR_NO_ERROR;
408
409 switch (variable) {
410 case NPPVpluginNameString:
411 // add here, for dynamic productname
412 *((char **)value) = NSP_getPluginName();
413 break;
414 case NPPVpluginDescriptionString:
415 // add here, for dynamic product description
416 *((char **)value) = NSP_getPluginDesc();
417 break;
418 default:
419 err = NPERR_GENERIC_ERROR;
420 }
421 debug_fprintf(NSP_LOG_APPEND, "print by Netscape Plugin, NPP_GetValue return %d.\n", err);
422 return err;
423}
424
425
426NPMIMEType
427dupMimeType(NPMIMEType type)
428{
429 NPMIMEType mimetype = (NPMIMEType) NPN_MemAlloc(strlen(type)+1);
430 mimetype[strlen(type)] = 0;
431 if (mimetype)
432 strcpy(mimetype, type);
433 return(mimetype);
434}
435#endif // end of UNIX
436
437NPError
438NPP_Initialize(void)
439{
440 debug_fprintf(NSP_LOG_NEW, "NS Plugin begin initialize.\n");
441 return (NPError)do_init_pipe();
442}
443
444#ifdef OJI
445NP_DLLPUBLIC jref
446NPP_GetJavaClass()
447{
448 return NULL;
449}
450#endif
451
452void
453NPP_Shutdown(void)
454{
455 PLUGIN_MSG msg;
456 memset((char*)&msg, 0, sizeof(PLUGIN_MSG));
457 msg.msg_id = SO_SHUTDOWN;
458 sendMsg(&msg, sizeof(PLUGIN_MSG), 0);
459 NSP_Close_Pipe(write_fd);
460
461#ifdef UNIX
462 // on Unix we should wait till the child process is dead
463 int nStatus;
464 waitpid( nChildPID, &nStatus, 0 );
465#endif
466}
467
468NP_DLLPUBLIC NPError NP_LOADDS
469NPP_New(NPMIMEType pluginType,
470 NPP instance,
471 uint16_t mode,
472 int16_t /*argc*/,
473 char* /*argn*/[],
474 char* /*argv*/[],
475 NPSavedData* /*saved*/)
476{
477 PluginInstance* This;
478
479 debug_fprintf(NSP_LOG_APPEND, "print by Netscape Plugin, enter NPP_New.\n");
480 if (instance == NULL)
481 return NPERR_INVALID_INSTANCE_ERROR;
482
483 instance->pdata = (PluginInstance*)NPN_MemAlloc(sizeof(PluginInstance));
484
485 memset(instance->pdata, 0 , sizeof(PluginInstance));
486 This = (PluginInstance*) instance->pdata;
487
488 if (This == NULL)
489 {
490 return NPERR_OUT_OF_MEMORY_ERROR;
491 }
492
493 memset(This, 0, sizeof(PluginInstance));
494
495 /* mode is NP_EMBED, NP_FULL, or NP_BACKGROUND (see npapi.h) */
496#ifdef UNIX
497 This->mode = mode;
498 This->type = dupMimeType(pluginType);
499 This->instance = instance;
500 This->pluginsPageUrl = NULL;
501 This->exists = FALSE;
502#endif //end of UNIX
503#ifdef WNT
504 (void)pluginType;
505 This->fWindow = (NPWindow*)NPN_MemAlloc(sizeof(NPWindow));
506 memset(This->fWindow, 0, sizeof (NPWindow));
507 This->fMode = mode;
508#endif //end of WNT
509 PLUGIN_MSG msg;
510 memset((char*)&msg, 0, sizeof(PLUGIN_MSG));
511 msg.msg_id = SO_NEW_INSTANCE;
512 msg.instance_id = (plugin_Int32)instance;
513 if (!sendMsg(&msg, sizeof(PLUGIN_MSG), 1))
514 return NPERR_GENERIC_ERROR;
515
516 NPN_Status(instance, "......");
517 return NPERR_NO_ERROR;
518}
519
520NP_DLLPUBLIC NPError NP_LOADDS
521NPP_Destroy(NPP instance, NPSavedData** /*save*/)
522{
523 debug_fprintf(NSP_LOG_APPEND, "print by Nsplugin, enter NPP_Destroy.\n");
524 PluginInstance* This;
525
526 if (instance == NULL)
527 return NPERR_INVALID_INSTANCE_ERROR;
528
529 // Send destroy message
530 PLUGIN_MSG msg;
531 memset((char*)&msg, 0, sizeof(PLUGIN_MSG));
532 msg.msg_id = SO_DESTROY;
533 msg.instance_id = (plugin_Int32)instance;
534#ifdef UNIX
535 msg.wnd_id =(plugin_Int32)((PluginInstance*) instance->pdata)->window;
536#endif //end of UNIX
537#ifdef WNT
538 msg.wnd_id =(plugin_Int32)((PluginInstance*) instance->pdata)->fhWnd;
539#endif //end of WNT
540 sendMsg(&msg, sizeof(PLUGIN_MSG), 0);
541
542 // Free the instance space
543 This = (PluginInstance*) instance->pdata;
544 if (This != NULL) {
545#ifdef UNIX
546 if (This->type)
547 NPN_MemFree(This->type);
548 if (This->pluginsPageUrl)
549 NPN_MemFree(This->pluginsPageUrl);
550 if (This->pluginsFileUrl)
551 NPN_MemFree(This->pluginsFileUrl);
552#endif //end of UNIX
553#ifdef WNT
554 if(This->fWindow)
555 NPN_MemFree(This->fWindow);
556#endif //end of WNT
557 NPN_MemFree(instance->pdata);
558 instance->pdata = NULL;
559 }
560
561 return NPERR_NO_ERROR;
562}
563
564
565NP_DLLPUBLIC NPError NP_LOADDS
566NPP_SetWindow(NPP instance, NPWindow* window)
567{
568 PluginInstance* This;
569#ifdef UNIX
570 NPSetWindowCallbackStruct *ws_info;
571#endif //end of UNIX
572
573 debug_fprintf(NSP_LOG_APPEND, "print by Netscape Plugin, received window resize.\n");
574 if (instance == NULL)
575 return NPERR_INVALID_INSTANCE_ERROR;
576
577 This = (PluginInstance*) instance->pdata;
578 if (This == NULL)
579 return NPERR_INVALID_INSTANCE_ERROR;
580
581 // Prepare the general part of the SET_WINDOW message
582 PLUGIN_MSG msg;
583 memset((char*)&msg, 0, sizeof(msg));
584 msg.msg_id = SO_SET_WINDOW;
585 msg.instance_id = (plugin_Int32)instance;
586
587 if ( window )
588 {
589 // Set window info for instance
590#ifdef UNIX
591 ws_info = (NPSetWindowCallbackStruct *)window->ws_info;
592 This->window = (Window) window->window;
593 This->x = window->x;
594 This->y = window->y;
595 This->width = window->width;
596 This->height = window->height;
597 This->display = ws_info->display;
598 This->visual = ws_info->visual;
599 This->depth = ws_info->depth;
600 This->colormap = ws_info->colormap;
601#endif //end of UNIX
602#ifdef WNT
603 This->fhWnd = (HWND) window->window;
604 This->fWindow->x = window->x;
605 This->fWindow->y = window->y;
606 This->fWindow->width = window->width;
607 This->fWindow->height = window->height;
608#endif //end of WNT
609 debug_fprintf(NSP_LOG_APPEND, "begin Set window of Office\n");
610 debug_fprintf(NSP_LOG_APPEND, "W=(%d) H=(%d)\n", window->width, window->height);
611
612 // fill the window dependent part of the message
613 msg.wnd_id = (plugin_Int32) window->window;
614 msg.wnd_x = window->x;
615 msg.wnd_y = window->y;
616 msg.wnd_w = window->width;
617 msg.wnd_h = window->height;
618 }
619 else
620 {
621 // empty window pointer usually means closing of the parent window
622#ifdef UNIX
623 ws_info = NULL;
624 This->window = (Window) NULL;
625 This->x = 0;
626 This->y = 0;
627 This->width = 0;
628 This->height = 0;
629 This->display = NULL;
630 This->visual = NULL;
631#endif //end of UNIX
632#ifdef WNT
633 This->fhWnd = (HWND) NULL;
634 This->fWindow->x = 0;
635 This->fWindow->y = 0;
636 This->fWindow->width = 0;
637 This->fWindow->height = 0;
638#endif //end of WNT
639 debug_fprintf(NSP_LOG_APPEND, "Empty window pointer is provided\n");
640
641 // fill the window dependent part of the message
642 msg.wnd_id = (plugin_Int32) NULL;
643 msg.wnd_x = 0;
644 msg.wnd_y = 0;
645 msg.wnd_w = 0;
646 msg.wnd_h = 0;
647 }
648
649 if(!sendMsg(&msg, sizeof(PLUGIN_MSG), 1))
650 {
651 debug_fprintf(NSP_LOG_APPEND, "NPP_SetWindow return failure \n");
652 return NPERR_GENERIC_ERROR;
653 }
654
655 return NPERR_NO_ERROR;
656}
657
658
659NP_DLLPUBLIC NPError NP_LOADDS
660NPP_NewStream(NPP instance,
661 NPMIMEType /*type*/,
662 NPStream* /*stream*/,
663 NPBool /*seekable*/,
664 uint16_t *stype)
665{
666 if (instance == NULL)
667 return NPERR_INVALID_INSTANCE_ERROR;
668
669 // Notify Mozilla to fetch the remote file into local cache directory
670 *stype=NP_ASFILEONLY;
671
672 return NPERR_NO_ERROR;
673}
674
675
676int32_t STREAMBUFSIZE = 0X0FFFFFFF;
677/* If we are reading from a file in NPAsFile
678 * mode so we can take any size stream in our
679 * write call (since we ignore it) */
680
681NP_DLLPUBLIC int32_t NP_LOADDS
682NPP_WriteReady(NPP /*instance*/, NPStream* /*stream*/)
683{
684 return STREAMBUFSIZE;
685}
686
687
688NP_DLLPUBLIC int32_t NP_LOADDS
689NPP_Write(NPP /*instance*/, NPStream* /*stream*/, int32_t /*offset*/, int32_t len, void* /*buffer*/)
690{
691 return len; /* The number of bytes accepted */
692}
693
694
695NP_DLLPUBLIC NPError NP_LOADDS
696NPP_DestroyStream(NPP instance, NPStream* /*stream*/, NPError /*reason*/)
697{
698 if (instance == NULL)
699 return NPERR_INVALID_INSTANCE_ERROR;
700 return NPERR_NO_ERROR;
701}
702
703// save fname to another file with the original file name
704NP_DLLPUBLIC void NP_LOADDS
705NPP_StreamAsFile(NPP instance, NPStream *stream, const char* fname)
706{
707 debug_fprintf(NSP_LOG_APPEND, "Into Stream\n");
708 char* url = (char*)stream->url;
709 char filename[1024] = {0};
710 char* pfilename = NULL;
711 if (NULL != (pfilename = strrchr(url, '/')))
712 {
713 strcpy(filename, pfilename+1);
714 } else {
715 return;
716 }
717
718 int length = strlen(url);
719 debug_fprintf(NSP_LOG_APPEND, "url: %s; length: %d\n", url, length);
720 PluginInstance* This;
721 This = (PluginInstance*) instance->pdata;
722
723 debug_fprintf(NSP_LOG_APPEND, "NPP_StreamAsFile\n");
724
725 // copy cached file to another file with original name
726 char localPathNew[NPP_PATH_MAX] = {0};
727 char localFileNew[NPP_PATH_MAX] = {0};
728 // if the file is from local
729 if (0 == STRNICMP(url, "file:///", strlen("file:///")))
730 {
731 sprintf(localPathNew, "%s", fname);
732 char* pAskSymbol = NULL;
733 if(NULL != (pAskSymbol = strrchr(localPathNew, '?')))
734 *pAskSymbol = 0;
735 }
736 else // from network, on windows, fname is c:\abc123
737 {
738 strncpy(localPathNew, fname, NPP_PATH_MAX - 1);
739 char* pRandomFilename = NULL;
740
741#ifdef UNIX
742 if(NULL != (pRandomFilename = strrchr(localPathNew, '/')))
743#endif //end of UNIX
744#ifdef WNT
745 if(NULL != (pRandomFilename = strrchr(localPathNew, '\\')))
746#endif //end of WNT
747 {
748 pRandomFilename[1] = 0;
749 } else {
750 return;
751 }
752 strcat(localPathNew, filename);
753 char* pAskSymbol = NULL;
754 if(NULL != (pAskSymbol = strrchr(localPathNew, '?')))
755 *pAskSymbol = 0;
756
757 sprintf(localFileNew, "file://%s", localPathNew);
758 UnixToDosPath(localFileNew);
759 debug_fprintf(NSP_LOG_APPEND, "fname: %s\n localPathNew: %s\nlocalFileNew: %s\n",
760 fname, localPathNew, localFileNew);
761
762 restoreUTF8(localPathNew);
763 restoreUTF8(localFileNew);
764 if(0 != strcmp(fname, localPathNew)) {
765
766#ifdef WNT
767 if(FALSE == CopyFile(fname, localPathNew, FALSE))
768 return;
769#endif //end of WNT
770
771#ifdef UNIX
772 int fdSrc, fdDst;
773 if((0 > (fdSrc = open(fname, O_RDONLY)))){
774 return;
775 }
776 remove(localPathNew);
777 umask(0);
778 if (0 > (fdDst = open(localPathNew, O_WRONLY|O_CREAT,
779 S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH))){
780 close( fdSrc);
781 debug_fprintf(NSP_LOG_APPEND, "NPP_StreamAsFile:can not create cache file %s. error: %s \n",
782 localPathNew, strerror(errno));
783 return;
784 }
785 char buffer[NPP_BUFFER_SIZE] = {0};
786 ssize_t ret;
787 while(0 <= (ret = read(fdSrc, buffer, NPP_BUFFER_SIZE)))
788 {
789 if (0 == ret)
790 {
791 if(EINTR == errno)
792 continue;
793 else
794
795 break;
796 }
797 ssize_t written_bytes = write(fdDst, buffer, ret);
798 if (written_bytes != ret)
799 {
800 debug_fprintf(NSP_LOG_APPEND, "NPP_StreamAsFile:short write to %s. error: %s \n",
801 localPathNew, strerror(errno));
802 close(fdSrc);
803 close(fdDst);
804 return;
805 }
806 }
807 close(fdSrc);
808 close(fdDst);
809#endif //end of UNIX
810
811 debug_fprintf(NSP_LOG_APPEND, "NPP_StreamAsFile:before SetURL\n");
812 }
813 }
814
815 // send SO_SET_URl message to inform the new URL
816 PLUGIN_MSG msg;
817 memset((char*)&msg, 0, sizeof(PLUGIN_MSG));
818 msg.msg_id = SO_SET_URL;
819 msg.instance_id = (plugin_Int32)instance;
820#ifdef UNIX
821 msg.wnd_id =(plugin_Int32)(This->window);
822 sprintf(msg.url, "file://%s", localPathNew);
823#endif //end of UNIX
824#ifdef WNT
825 msg.wnd_id =(plugin_Int32)(This->fhWnd);
826 sprintf(msg.url, "file:///%s", localPathNew);
827 DosToUnixPath(msg.url);
828#endif //endof WNT
829 if(!sendMsg(&msg, sizeof(PLUGIN_MSG), 1))
830 debug_fprintf(NSP_LOG_APPEND, "NPP_StreamAsFile send SO_SET_URL return failure \n");
831
832 // send SO_SET_WINDOW message
833// memset((char*)&msg, 0, sizeof(PLUGIN_MSG));
834 msg.msg_id = SO_SET_WINDOW;
835 msg.instance_id = (plugin_Int32)instance;
836// msg.wnd_id =(plugin_Int32)((PluginInstance*) instance->pdata)->window;
837#ifdef UNIX
838 msg.wnd_x = This->x;
839 msg.wnd_y = This->y;
840 msg.wnd_w = This->width;
841 msg.wnd_h = This->height;
842#endif //end of UNIX
843#ifdef WNT
844 msg.wnd_x = This->fWindow->x;
845 msg.wnd_y = This->fWindow->y;
846 msg.wnd_w = This->fWindow->width;
847 msg.wnd_h = This->fWindow->height;
848#endif //endof WNT
849 if(!sendMsg(&msg, sizeof(PLUGIN_MSG), 1))
850 debug_fprintf(NSP_LOG_APPEND, "NPP_StreamAsFile send SO_SET_WINDOW return failure \n");
851}
852
853NP_DLLPUBLIC void NP_LOADDS
854NPP_URLNotify(NPP /*instance*/, const char* /*url*/,
855 NPReason /*reason*/, void* /*notifyData*/)
856{
857}
858
859
860NP_DLLPUBLIC void NP_LOADDS
861NPP_Print(NPP instance, NPPrint* printInfo)
862{
863 if(printInfo == NULL)
864 return;
865
866 if (instance != NULL) {
867 /***** Insert NPP_Print code here *****/
868 PluginInstance* This = (PluginInstance*) instance->pdata;
869 (void)This;
870 PLUGIN_MSG msg;
871 memset((char*)&msg, 0, sizeof(PLUGIN_MSG));
872 msg.msg_id = SO_PRINT;
873 msg.instance_id = (plugin_Int32)instance;
874 if(!sendMsg(&msg, sizeof(PLUGIN_MSG), 1))
875 debug_fprintf(NSP_LOG_APPEND, "NPP_StreamAsFile send SO_SET_WINDOW return failure \n");
876 /**************************************/
877
878 if (printInfo->mode == NP_FULL) {
879 /*
880 * PLUGIN DEVELOPERS:
881 * If your plugin would like to take over
882 * printing completely when it is in full-screen mode,
883 * set printInfo->pluginPrinted to TRUE and print your
884 * plugin as you see fit. If your plugin wants Netscape
885 * to handle printing in this case, set
886 * printInfo->pluginPrinted to FALSE (the default) and
887 * do nothing. If you do want to handle printing
888 * yourself, printOne is true if the print button
889 * (as opposed to the print menu) was clicked.
890 * On the Macintosh, platformPrint is a THPrint; on
891 * Windows, platformPrint is a structure
892 * (defined in npapi.h) containing the printer name, port,
893 * etc.
894 */
895
896 /***** Insert NPP_Print code here *****\
897 void* platformPrint =
898 printInfo->print.fullPrint.platformPrint;
899 NPBool printOne =
900 printInfo->print.fullPrint.printOne;
901 \**************************************/
902
903 /* Do the default*/
904 printInfo->print.fullPrint.pluginPrinted = FALSE;
905 }
906 else { /* If not fullscreen, we must be embedded */
907 /*
908 * PLUGIN DEVELOPERS:
909 * If your plugin is embedded, or is full-screen
910 * but you returned false in pluginPrinted above, NPP_Print
911 * will be called with mode == NP_EMBED. The NPWindow
912 * in the printInfo gives the location and dimensions of
913 * the embedded plugin on the printed page. On the
914 * Macintosh, platformPrint is the printer port; on
915 * Windows, platformPrint is the handle to the printing
916 * device context.
917 */
918
919 /***** Insert NPP_Print code here *****\
920 NPWindow* printWindow =
921 &(printInfo->print.embedPrint.window);
922 void* platformPrint =
923 printInfo->print.embedPrint.platformPrint;
924 \**************************************/
925 }
926 }
927}
928
929}// end of extern "C"
930
931/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
932