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 |
94 | static 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 | |
108 | static NSP_Mute_Obj send_lock = NSP_New_Mute_Obj(); |
109 | static NSP_PIPE_FD write_fd = (NSP_PIPE_FD)-1; |
110 | |
111 | |
112 | long 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 |
129 | static 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 | |
137 | namespace { |
138 | |
139 | bool 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 |
210 | int 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 | |
305 | bool 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 | |
345 | extern "C" |
346 | { |
347 | char* 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;" |
366 | MIMETYPE_VND_SUN_XML_CALC_ASCII ":sxc:StarOffice 6.0/7 Spreadsheet;" |
367 | MIMETYPE_VND_SUN_XML_CALC_TEMPLATE_ASCII":stc:StarOffice 6.0/7 Spreadsheet Template;" |
368 | MIMETYPE_VND_SUN_XML_DRAW_ASCII ":sxd:StarOffice 6.0/7 Drawing;" |
369 | MIMETYPE_VND_SUN_XML_DRAW_TEMPLATE_ASCII ":std:StarOffice 6.0/7 Drawing Template;" |
370 | MIMETYPE_VND_SUN_XML_IMPRESS_ASCII ":sxi:StarOffice 6.0/7 Presentation;" |
371 | MIMETYPE_VND_SUN_XML_IMPRESS_TEMPLATE_ASCII ":sti:StarOffice 6.0/7 Presentation Template;" |
372 | MIMETYPE_VND_SUN_XML_MATH_ASCII ":sxm:StarOffice 6.0/7 Formula;" |
373 | MIMETYPE_VND_SUN_XML_WRITER_ASCII ":sxw:StarOffice 6.0/7 Text Document;" |
374 | MIMETYPE_VND_SUN_XML_WRITER_GLOBAL_ASCII ":sxg:StarOffice 6.0/7 Master Document;" |
375 | MIMETYPE_VND_SUN_XML_WRITER_TEMPLATE_ASCII ":stw:StarOffice 6.0/7 Text Document Template;" |
376 | MIMETYPE_OASIS_OPENDOCUMENT_TEXT_ASCII ":odt:OpenDocument Text;" |
377 | MIMETYPE_OASIS_OPENDOCUMENT_TEXT_ASCII "-flat-xml:fodt:OpenDocument Text Flat XML;" |
378 | MIMETYPE_OASIS_OPENDOCUMENT_TEXT_TEMPLATE_ASCII ":ott:OpenDocument Text Template;" |
379 | MIMETYPE_OASIS_OPENDOCUMENT_TEXT_GLOBAL_ASCII ":odm:OpenDocument Master Document;" |
380 | MIMETYPE_OASIS_OPENDOCUMENT_TEXT_WEB_ASCII ":oth:HTML Document Template;" |
381 | MIMETYPE_OASIS_OPENDOCUMENT_SPREADSHEET_ASCII ":ods:OpenDocument Spreadsheet;" |
382 | MIMETYPE_OASIS_OPENDOCUMENT_SPREADSHEET_ASCII "-flat-xml:fods:OpenDocument Spreadsheet Flat XML;" |
383 | MIMETYPE_OASIS_OPENDOCUMENT_SPREADSHEET_TEMPLATE_ASCII ":ots:OpenDocument Spreadsheet Template;" |
384 | MIMETYPE_OASIS_OPENDOCUMENT_DRAWING_ASCII ":odg:OpenDocument Drawing;" |
385 | MIMETYPE_OASIS_OPENDOCUMENT_DRAWING_ASCII "-flat-xml:fodg:OpenDocument Drawing Flat XML;" |
386 | MIMETYPE_OASIS_OPENDOCUMENT_DRAWING_TEMPLATE_ASCII ":otg:OpenDocument Drawing Template;" |
387 | MIMETYPE_OASIS_OPENDOCUMENT_PRESENTATION_ASCII ":odp:OpenDocument Presentation;" |
388 | MIMETYPE_OASIS_OPENDOCUMENT_PRESENTATION_ASCII "-flat-xml:fodp:OpenDocument Presentation Flat XML;" |
389 | MIMETYPE_OASIS_OPENDOCUMENT_PRESENTATION_TEMPLATE_ASCII ":otp:OpenDocument Presentation Template;" |
390 | MIMETYPE_OASIS_OPENDOCUMENT_FORMULA_ASCII ":odf:OpenDocument Formula;" ); |
391 | |
392 | NP_DLLPUBLIC |
393 | #ifndef HAVE_NON_CONST_NPP_GETMIMEDESCRIPTION |
394 | const |
395 | #endif |
396 | char* |
397 | NPP_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 |
404 | NP_DLLPUBLIC NPError |
405 | NPP_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 | |
426 | NPMIMEType |
427 | dupMimeType(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 | |
437 | NPError |
438 | NPP_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 |
445 | NP_DLLPUBLIC jref |
446 | NPP_GetJavaClass() |
447 | { |
448 | return NULL; |
449 | } |
450 | #endif |
451 | |
452 | void |
453 | NPP_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 | |
468 | NP_DLLPUBLIC NPError NP_LOADDS |
469 | NPP_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 | |
520 | NP_DLLPUBLIC NPError NP_LOADDS |
521 | NPP_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 | |
565 | NP_DLLPUBLIC NPError NP_LOADDS |
566 | NPP_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 | |
659 | NP_DLLPUBLIC NPError NP_LOADDS |
660 | NPP_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 | |
676 | int32_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 | |
681 | NP_DLLPUBLIC int32_t NP_LOADDS |
682 | NPP_WriteReady(NPP /*instance*/, NPStream* /*stream*/) |
683 | { |
684 | return STREAMBUFSIZE; |
685 | } |
686 | |
687 | |
688 | NP_DLLPUBLIC int32_t NP_LOADDS |
689 | NPP_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 | |
695 | NP_DLLPUBLIC NPError NP_LOADDS |
696 | NPP_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 |
704 | NP_DLLPUBLIC void NP_LOADDS |
705 | NPP_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 | |
853 | NP_DLLPUBLIC void NP_LOADDS |
854 | NPP_URLNotify(NPP /*instance*/, const char* /*url*/, |
855 | NPReason /*reason*/, void* /*notifyData*/) |
856 | { |
857 | } |
858 | |
859 | |
860 | NP_DLLPUBLIC void NP_LOADDS |
861 | NPP_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 | |