~ubuntu-branches/ubuntu/lucid/kdebase/lucid

« back to all changes in this revision

Viewing changes to nsplugins/viewer/nsplugin.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Ana Beatriz Guerrero Lopez
  • Date: 2009-04-05 05:22:13 UTC
  • mfrom: (0.4.2 experimental) (0.2.2 upstream)
  • mto: This revision was merged to the branch mainline in revision 235.
  • Revision ID: james.westby@ubuntu.com-20090405052213-39thr4l6p2ss07uj
Tags: 4:4.2.2-1
* New upstream release:
  - khtml fixes. (Closes: #290285, #359680)
  - Default konsole sessions can be deleted. (Closes: #286342)
  - Tag widget uses standard application palette. (Closes: #444800)
  - ... and surely many more but we have lost track...

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 
3
 
  This is an encapsulation of the  Netscape plugin API.
4
 
 
5
 
 
6
 
  Copyright (c) 2000 Matthias Hoelzer-Kluepfel <hoelzer@kde.org>
7
 
                     Stefan Schimanski <1Stein@gmx.de>
8
 
                2003-2005 George Staikos <staikos@kde.org>
9
 
 
10
 
  This program is free software; you can redistribute it and/or modify
11
 
  it under the terms of the GNU General Public License as published by
12
 
  the Free Software Foundation; either version 2 of the License, or
13
 
  (at your option) any later version.
14
 
 
15
 
  This program is distributed in the hope that it will be useful,
16
 
  but WITHOUT ANY WARRANTY; without even the implied warranty of
17
 
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18
 
  GNU General Public License for more details.
19
 
 
20
 
  You should have received a copy of the GNU General Public License
21
 
  along with this program; if not, write to the Free Software
22
 
  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
23
 
 
24
 
*/
25
 
 
26
 
 
27
 
#include "NSPluginCallbackIface_stub.h"
28
 
 
29
 
 
30
 
#include <stdlib.h>
31
 
#include <unistd.h>
32
 
 
33
 
#include <qdict.h>
34
 
#include <qdir.h>
35
 
#include <qfile.h>
36
 
#include <qtimer.h>
37
 
 
38
 
#include "kxt.h"
39
 
#include "nsplugin.h"
40
 
#include "resolve.h"
41
 
 
42
 
#ifdef Bool
43
 
#undef Bool
44
 
#endif
45
 
 
46
 
#include <dcopclient.h>
47
 
#include <kconfig.h>
48
 
#include <kdebug.h>
49
 
#include <kglobal.h>
50
 
#include <kio/netaccess.h>
51
 
#include <klibloader.h>
52
 
#include <klocale.h>
53
 
#include <kprocess.h>
54
 
#include <kprotocolmanager.h>
55
 
#include <kstandarddirs.h>
56
 
#include <ktempfile.h>
57
 
#include <kurl.h>
58
 
 
59
 
#include <X11/Intrinsic.h>
60
 
#include <X11/Composite.h>
61
 
#include <X11/Constraint.h>
62
 
#include <X11/Shell.h>
63
 
#include <X11/StringDefs.h>
64
 
 
65
 
// provide these symbols when compiling with gcc 3.x
66
 
 
67
 
#if defined __GNUC__ && defined __GNUC_MINOR__
68
 
# define KDE_GNUC_PREREQ(maj, min) \
69
 
  ((__GNUC__ << 16) + __GNUC_MINOR__ >= ((maj) << 16) + (min))
70
 
#else
71
 
# define KDE_GNUC_PREREQ(maj, min) 0
72
 
#endif
73
 
 
74
 
 
75
 
#if defined(__GNUC__) && KDE_GNUC_PREREQ(3,0)
76
 
extern "C" void* __builtin_new(size_t s)
77
 
{
78
 
   return operator new(s);
79
 
}
80
 
 
81
 
extern "C" void __builtin_delete(void* p)
82
 
{
83
 
   operator delete(p);
84
 
}
85
 
 
86
 
extern "C" void* __builtin_vec_new(size_t s)
87
 
{
88
 
   return operator new[](s);
89
 
}
90
 
 
91
 
extern "C" void __builtin_vec_delete(void* p)
92
 
{
93
 
   operator delete[](p);
94
 
}
95
 
 
96
 
extern "C" void __pure_virtual()
97
 
{
98
 
   abort();
99
 
}
100
 
#endif
101
 
 
102
 
// server side functions -----------------------------------------------------
103
 
 
104
 
// allocate memory
105
 
void *g_NPN_MemAlloc(uint32 size)
106
 
{
107
 
   void *mem = ::malloc(size);
108
 
 
109
 
   //kdDebug(1431) << "g_NPN_MemAlloc(), size=" << size << " allocated at " << mem << endl;
110
 
 
111
 
   return mem;
112
 
}
113
 
 
114
 
 
115
 
// free memory
116
 
void g_NPN_MemFree(void *ptr)
117
 
{
118
 
   //kdDebug(1431) << "g_NPN_MemFree() at " << ptr << endl;
119
 
   if (ptr)
120
 
     ::free(ptr);
121
 
}
122
 
 
123
 
uint32 g_NPN_MemFlush(uint32 size)
124
 
{
125
 
   Q_UNUSED(size);
126
 
   //kdDebug(1431) << "g_NPN_MemFlush()" << endl;
127
 
   // MAC OS only..  we don't use this
128
 
   return 0;
129
 
}
130
 
 
131
 
 
132
 
// redraw
133
 
void g_NPN_ForceRedraw(NPP /*instance*/)
134
 
{
135
 
   // http://devedge.netscape.com/library/manuals/2002/plugin/1.0/npn_api3.html#999401
136
 
   // FIXME
137
 
   kdDebug(1431) << "g_NPN_ForceRedraw() [unimplemented]" << endl;
138
 
}
139
 
 
140
 
 
141
 
// invalidate rect
142
 
void g_NPN_InvalidateRect(NPP /*instance*/, NPRect* /*invalidRect*/)
143
 
{
144
 
   // http://devedge.netscape.com/library/manuals/2002/plugin/1.0/npn_api7.html#999503
145
 
   // FIXME
146
 
   kdDebug(1431) << "g_NPN_InvalidateRect() [unimplemented]" << endl;
147
 
}
148
 
 
149
 
 
150
 
// invalidate region
151
 
void g_NPN_InvalidateRegion(NPP /*instance*/, NPRegion /*invalidRegion*/)
152
 
{
153
 
   // http://devedge.netscape.com/library/manuals/2002/plugin/1.0/npn_api8.html#999528
154
 
   // FIXME
155
 
   kdDebug(1431) << "g_NPN_InvalidateRegion() [unimplemented]" << endl;
156
 
}
157
 
 
158
 
 
159
 
// get value
160
 
NPError g_NPN_GetValue(NPP /*instance*/, NPNVariable variable, void *value)
161
 
{
162
 
   kdDebug(1431) << "g_NPN_GetValue(), variable=" << static_cast<int>(variable) << endl;
163
 
 
164
 
   switch (variable)
165
 
   {
166
 
      case NPNVxDisplay:
167
 
         *(void**)value = qt_xdisplay();
168
 
         return NPERR_NO_ERROR;
169
 
      case NPNVxtAppContext:
170
 
         *(void**)value = XtDisplayToApplicationContext(qt_xdisplay());
171
 
         return NPERR_NO_ERROR;
172
 
      case NPNVjavascriptEnabledBool:
173
 
         *(bool*)value = true;
174
 
         return NPERR_NO_ERROR;
175
 
      case NPNVasdEnabledBool:
176
 
         // SmartUpdate - we don't do this
177
 
         *(bool*)value = false;
178
 
         return NPERR_NO_ERROR;
179
 
      case NPNVisOfflineBool:
180
 
         // Offline browsing - no thanks
181
 
         *(bool*)value = false;
182
 
         return NPERR_NO_ERROR;
183
 
      case NPNVToolkit:
184
 
         *(NPNToolkitType*)value = NPNVGtk2;
185
 
         return NPERR_NO_ERROR;
186
 
      case NPNVSupportsXEmbedBool:
187
 
         *(bool*)value = true;
188
 
         return NPERR_NO_ERROR;
189
 
      default:
190
 
         return NPERR_INVALID_PARAM;
191
 
   }
192
 
}
193
 
 
194
 
 
195
 
NPError g_NPN_DestroyStream(NPP instance, NPStream* stream,
196
 
                          NPReason reason)
197
 
{
198
 
   // FIXME: is this correct?  I imagine it is not.  (GS)
199
 
   kdDebug(1431) << "g_NPN_DestroyStream()" << endl;
200
 
 
201
 
   NSPluginInstance *inst = (NSPluginInstance*) instance->ndata;
202
 
   inst->streamFinished( (NSPluginStream *)stream->ndata );
203
 
 
204
 
   switch (reason) {
205
 
   case NPRES_DONE:
206
 
      return NPERR_NO_ERROR;
207
 
   case NPRES_USER_BREAK:
208
 
      // FIXME: notify the user
209
 
   case NPRES_NETWORK_ERR:
210
 
      // FIXME: notify the user
211
 
   default:
212
 
      return NPERR_GENERIC_ERROR;
213
 
   }
214
 
}
215
 
 
216
 
 
217
 
NPError g_NPN_RequestRead(NPStream* /*stream*/, NPByteRange* /*rangeList*/)
218
 
{
219
 
   // http://devedge.netscape.com/library/manuals/2002/plugin/1.0/npn_api16.html#999734
220
 
   kdDebug(1431) << "g_NPN_RequestRead() [unimplemented]" << endl;
221
 
 
222
 
   // FIXME
223
 
   return NPERR_GENERIC_ERROR;
224
 
}
225
 
 
226
 
NPError g_NPN_NewStream(NPP /*instance*/, NPMIMEType /*type*/,
227
 
                      const char* /*target*/, NPStream** /*stream*/)
228
 
{
229
 
   // http://devedge.netscape.com/library/manuals/2002/plugin/1.0/npn_api12.html#999628
230
 
   kdDebug(1431) << "g_NPN_NewStream() [unimplemented]" << endl;
231
 
 
232
 
   // FIXME
233
 
   // This creates a stream from the plugin to the browser of type "type" to
234
 
   // display in "target"
235
 
   return NPERR_GENERIC_ERROR;
236
 
}
237
 
 
238
 
int32 g_NPN_Write(NPP /*instance*/, NPStream* /*stream*/, int32 /*len*/, void* /*buf*/)
239
 
{
240
 
   // http://devedge.netscape.com/library/manuals/2002/plugin/1.0/npn_api21.html#999859
241
 
   kdDebug(1431) << "g_NPN_Write() [unimplemented]" << endl;
242
 
 
243
 
   // FIXME
244
 
   return 0;
245
 
}
246
 
 
247
 
 
248
 
// URL functions
249
 
NPError g_NPN_GetURL(NPP instance, const char *url, const char *target)
250
 
{
251
 
   kdDebug(1431) << "g_NPN_GetURL: url=" << url << " target=" << target << endl;
252
 
 
253
 
   NSPluginInstance *inst = static_cast<NSPluginInstance*>(instance->ndata);
254
 
   if (inst) {
255
 
      inst->requestURL( QString::fromLatin1(url), QString::null,
256
 
                        QString::fromLatin1(target), 0 );
257
 
   }
258
 
 
259
 
   return NPERR_NO_ERROR;
260
 
}
261
 
 
262
 
 
263
 
NPError g_NPN_GetURLNotify(NPP instance, const char *url, const char *target,
264
 
                         void* notifyData)
265
 
{
266
 
    kdDebug(1431) << "g_NPN_GetURLNotify: url=" << url << " target=" << target << " inst=" << (void*)instance << endl;
267
 
   NSPluginInstance *inst = static_cast<NSPluginInstance*>(instance->ndata);
268
 
   if (inst) {
269
 
      kdDebug(1431) << "g_NPN_GetURLNotify: ndata=" << (void*)inst << endl;
270
 
      inst->requestURL( QString::fromLatin1(url), QString::null,
271
 
                        QString::fromLatin1(target), notifyData, true );
272
 
   }
273
 
 
274
 
   return NPERR_NO_ERROR;
275
 
}
276
 
 
277
 
 
278
 
NPError g_NPN_PostURLNotify(NPP instance, const char* url, const char* target,
279
 
                     uint32 len, const char* buf, NPBool file, void* notifyData)
280
 
{
281
 
// http://devedge.netscape.com/library/manuals/2002/plugin/1.0/npn_api14.html
282
 
   kdDebug(1431) << "g_NPN_PostURLNotify() [incomplete]" << endl;
283
 
   kdDebug(1431) << "url=[" << url << "] target=[" << target << "]" << endl;
284
 
   QByteArray postdata;
285
 
   KParts::URLArgs args;
286
 
 
287
 
   if (len == 0) {
288
 
      return NPERR_NO_DATA;
289
 
   }
290
 
 
291
 
   if (file) { // buf is a filename
292
 
      QFile f(buf);
293
 
      if (!f.open(IO_ReadOnly)) {
294
 
         return NPERR_FILE_NOT_FOUND;
295
 
      }
296
 
 
297
 
      // FIXME: this will not work because we need to strip the header out!
298
 
      postdata = f.readAll();
299
 
      f.close();
300
 
   } else {    // buf is raw data
301
 
      // First strip out the header
302
 
      const char *previousStart = buf;
303
 
      uint32 l;
304
 
      bool previousCR = true;
305
 
 
306
 
      for (l = 1;; l++) {
307
 
         if (l == len) {
308
 
            break;
309
 
         }
310
 
 
311
 
         if (buf[l-1] == '\n' || (previousCR && buf[l-1] == '\r')) {
312
 
            if (previousCR) { // header is done!
313
 
               if ((buf[l-1] == '\r' && buf[l] == '\n') ||
314
 
                   (buf[l-1] == '\n' &&  buf[l] == '\r'))
315
 
                  l++;
316
 
               l++;
317
 
               previousStart = &buf[l-1];
318
 
               break;
319
 
            }
320
 
 
321
 
            QString thisLine = QString::fromLatin1(previousStart, &buf[l-1] - previousStart).stripWhiteSpace();
322
 
 
323
 
            previousStart = &buf[l];
324
 
            previousCR = true;
325
 
 
326
 
            kdDebug(1431) << "Found header line: [" << thisLine << "]" << endl;
327
 
            if (thisLine.startsWith("Content-Type: ")) {
328
 
               args.setContentType(thisLine);
329
 
            }
330
 
         } else {
331
 
            previousCR = false;
332
 
         }
333
 
      }
334
 
 
335
 
      postdata.duplicate(previousStart, len - l + 1);
336
 
   }
337
 
 
338
 
   kdDebug(1431) << "Post data: " << postdata.size() << " bytes" << endl;
339
 
#if 0
340
 
   QFile f("/tmp/nspostdata");
341
 
   f.open(IO_WriteOnly);
342
 
   f.writeBlock(postdata);
343
 
   f.close();
344
 
#endif
345
 
 
346
 
   if (!target || !*target) {
347
 
      // Send the results of the post to the plugin
348
 
      // (works by default)
349
 
   } else if (!strcmp(target, "_current") || !strcmp(target, "_self") ||
350
 
              !strcmp(target, "_top")) {
351
 
      // Unload the plugin, put the results in the frame/window that the
352
 
      // plugin was loaded in
353
 
      // FIXME
354
 
   } else if (!strcmp(target, "_new") || !strcmp(target, "_blank")){
355
 
      // Open a new browser window and write the results there
356
 
      // FIXME
357
 
   } else {
358
 
      // Write the results to the specified frame
359
 
      // FIXME
360
 
   }
361
 
 
362
 
   NSPluginInstance *inst = static_cast<NSPluginInstance*>(instance->ndata);
363
 
   if (inst && !inst->normalizedURL(QString::fromLatin1(url)).isNull()) {
364
 
      inst->postURL( QString::fromLatin1(url), postdata, args.contentType(),
365
 
                     QString::fromLatin1(target), notifyData, args, true );
366
 
   } else {
367
 
      // Unsupported / insecure
368
 
      return NPERR_INVALID_URL;
369
 
   }
370
 
 
371
 
   return NPERR_NO_ERROR;
372
 
}
373
 
 
374
 
 
375
 
NPError g_NPN_PostURL(NPP instance, const char* url, const char* target,
376
 
                    uint32 len, const char* buf, NPBool file)
377
 
{
378
 
// http://devedge.netscape.com/library/manuals/2002/plugin/1.0/npn_api13.html
379
 
   kdDebug(1431) << "g_NPN_PostURL()" << endl;
380
 
   kdDebug(1431) << "url=[" << url << "] target=[" << target << "]" << endl;
381
 
   QByteArray postdata;
382
 
   KParts::URLArgs args;
383
 
 
384
 
   if (len == 0) {
385
 
      return NPERR_NO_DATA;
386
 
   }
387
 
 
388
 
   if (file) { // buf is a filename
389
 
      QFile f(buf);
390
 
      if (!f.open(IO_ReadOnly)) {
391
 
         return NPERR_FILE_NOT_FOUND;
392
 
      }
393
 
 
394
 
      // FIXME: this will not work because we need to strip the header out!
395
 
      postdata = f.readAll();
396
 
      f.close();
397
 
   } else {    // buf is raw data
398
 
      // First strip out the header
399
 
      const char *previousStart = buf;
400
 
      uint32 l;
401
 
      bool previousCR = true;
402
 
 
403
 
      for (l = 1;; l++) {
404
 
         if (l == len) {
405
 
            break;
406
 
         }
407
 
 
408
 
         if (buf[l-1] == '\n' || (previousCR && buf[l-1] == '\r')) {
409
 
            if (previousCR) { // header is done!
410
 
               if ((buf[l-1] == '\r' && buf[l] == '\n') ||
411
 
                   (buf[l-1] == '\n' &&  buf[l] == '\r'))
412
 
                  l++;
413
 
               l++;
414
 
               previousStart = &buf[l-1];
415
 
               break;
416
 
            }
417
 
 
418
 
            QString thisLine = QString::fromLatin1(previousStart, &buf[l-1] - previousStart).stripWhiteSpace();
419
 
 
420
 
            previousStart = &buf[l];
421
 
            previousCR = true;
422
 
 
423
 
            kdDebug(1431) << "Found header line: [" << thisLine << "]" << endl;
424
 
            if (thisLine.startsWith("Content-Type: ")) {
425
 
               args.setContentType(thisLine);
426
 
            }
427
 
         } else {
428
 
            previousCR = false;
429
 
         }
430
 
      }
431
 
 
432
 
      postdata.duplicate(previousStart, len - l + 1);
433
 
   }
434
 
 
435
 
   kdDebug(1431) << "Post data: " << postdata.size() << " bytes" << endl;
436
 
#if 0
437
 
   QFile f("/tmp/nspostdata");
438
 
   f.open(IO_WriteOnly);
439
 
   f.writeBlock(postdata);
440
 
   f.close();
441
 
#endif
442
 
 
443
 
   if (!target || !*target) {
444
 
      // Send the results of the post to the plugin
445
 
      // (works by default)
446
 
   } else if (!strcmp(target, "_current") || !strcmp(target, "_self") ||
447
 
              !strcmp(target, "_top")) {
448
 
      // Unload the plugin, put the results in the frame/window that the
449
 
      // plugin was loaded in
450
 
      // FIXME
451
 
   } else if (!strcmp(target, "_new") || !strcmp(target, "_blank")){
452
 
      // Open a new browser window and write the results there
453
 
      // FIXME
454
 
   } else {
455
 
      // Write the results to the specified frame
456
 
      // FIXME
457
 
   }
458
 
 
459
 
   NSPluginInstance *inst = static_cast<NSPluginInstance*>(instance->ndata);
460
 
   if (inst && !inst->normalizedURL(QString::fromLatin1(url)).isNull()) {
461
 
      inst->postURL( QString::fromLatin1(url), postdata, args.contentType(),
462
 
                     QString::fromLatin1(target), 0L, args, false );
463
 
   } else {
464
 
      // Unsupported / insecure
465
 
      return NPERR_INVALID_URL;
466
 
   }
467
 
 
468
 
   return NPERR_NO_ERROR;
469
 
}
470
 
 
471
 
 
472
 
// display status message
473
 
void g_NPN_Status(NPP instance, const char *message)
474
 
{
475
 
   kdDebug(1431) << "g_NPN_Status(): " << message << endl;
476
 
 
477
 
   if (!instance)
478
 
      return;
479
 
 
480
 
   // turn into an instance signal
481
 
   NSPluginInstance *inst = (NSPluginInstance*) instance->ndata;
482
 
 
483
 
   inst->emitStatus(message);
484
 
}
485
 
 
486
 
 
487
 
// inquire user agent
488
 
const char *g_NPN_UserAgent(NPP /*instance*/)
489
 
{
490
 
    KProtocolManager kpm;
491
 
    QString agent = kpm.userAgentForHost("nspluginviewer");
492
 
    kdDebug(1431) << "g_NPN_UserAgent() = " << agent << endl;
493
 
    // flash crashes without Firefox UA
494
 
    agent = "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.8.1.10) Gecko/2007101500 Firefox/2.0.0.10";
495
 
    return agent.latin1();
496
 
}
497
 
 
498
 
 
499
 
// inquire version information
500
 
void g_NPN_Version(int *plugin_major, int *plugin_minor, int *browser_major, int *browser_minor)
501
 
{
502
 
   kdDebug(1431) << "g_NPN_Version()" << endl;
503
 
 
504
 
   // FIXME: Use the sensible values
505
 
   *browser_major = NP_VERSION_MAJOR;
506
 
   *browser_minor = NP_VERSION_MINOR;
507
 
 
508
 
   *plugin_major = NP_VERSION_MAJOR;
509
 
   *plugin_minor = NP_VERSION_MINOR;
510
 
}
511
 
 
512
 
 
513
 
void g_NPN_ReloadPlugins(NPBool reloadPages)
514
 
{
515
 
   // http://devedge.netscape.com/library/manuals/2002/plugin/1.0/npn_api15.html#999713
516
 
   kdDebug(1431) << "g_NPN_ReloadPlugins()" << endl;
517
 
   KProcess p;
518
 
   p << KGlobal::dirs()->findExe("nspluginscan");
519
 
 
520
 
   if (reloadPages) {
521
 
      // This is the proper way, but it cannot be done because we have no
522
 
      // handle to the caller!  How stupid!  We cannot force all konqi windows
523
 
      // to reload - that would be evil.
524
 
      //p.start(KProcess::Block);
525
 
      // Let's only allow the caller to be reloaded, not everything.
526
 
      //if (_callback)
527
 
      //   _callback->reloadPage();
528
 
      p.start(KProcess::DontCare);
529
 
   } else {
530
 
      p.start(KProcess::DontCare);
531
 
   }
532
 
}
533
 
 
534
 
 
535
 
// JAVA functions
536
 
JRIEnv *g_NPN_GetJavaEnv()
537
 
{
538
 
   kdDebug(1431) << "g_NPN_GetJavaEnv() [unimplemented]" << endl;
539
 
   // FIXME - what do these do?  I can't find docs, and even Mozilla doesn't
540
 
   //         implement them
541
 
   return 0;
542
 
}
543
 
 
544
 
 
545
 
jref g_NPN_GetJavaPeer(NPP /*instance*/)
546
 
{
547
 
   kdDebug(1431) << "g_NPN_GetJavaPeer() [unimplemented]" << endl;
548
 
   // FIXME - what do these do?  I can't find docs, and even Mozilla doesn't
549
 
   //         implement them
550
 
   return 0;
551
 
}
552
 
 
553
 
 
554
 
NPError g_NPN_SetValue(NPP /*instance*/, NPPVariable variable, void* /*value*/)
555
 
{
556
 
   kdDebug(1431) << "g_NPN_SetValue() [unimplemented]" << endl;
557
 
   switch (variable) {
558
 
   case NPPVpluginWindowBool:
559
 
      // FIXME
560
 
      // If true, the plugin is windowless.  If false, it is in a window.
561
 
   case NPPVpluginTransparentBool:
562
 
      // FIXME
563
 
      // If true, the plugin is displayed transparent
564
 
   default:
565
 
      return NPERR_GENERIC_ERROR;
566
 
   }
567
 
}
568
 
 
569
 
 
570
 
 
571
 
 
572
 
 
573
 
/******************************************************************/
574
 
 
575
 
void
576
 
NSPluginInstance::forwarder(Widget w, XtPointer cl_data, XEvent * event, Boolean * cont)
577
 
{
578
 
  Q_UNUSED(w);
579
 
  NSPluginInstance *inst = (NSPluginInstance*)cl_data;
580
 
  *cont = True;
581
 
  if (inst->_form == 0 || event->xkey.window == XtWindow(inst->_form))
582
 
    return;
583
 
  *cont = False;
584
 
  event->xkey.window = XtWindow(inst->_form);
585
 
  event->xkey.subwindow = None;
586
 
  XtDispatchEvent(event);
587
 
}
588
 
 
589
 
 
590
 
NSPluginInstance::NSPluginInstance(NPP privateData, NPPluginFuncs *pluginFuncs,
591
 
                                   KLibrary *handle, int width, int height,
592
 
                                   QString src, QString /*mime*/,
593
 
                                   QString appId, QString callbackId,
594
 
                                   bool embed, WId xembed,
595
 
                                   QObject *parent, const char* name )
596
 
   : DCOPObject(), QObject( parent, name ) 
597
 
{
598
 
    Q_UNUSED(embed);
599
 
   _visible = false;
600
 
   _npp = privateData;
601
 
   _npp->ndata = this;
602
 
   _destroyed = false;
603
 
   _handle = handle;
604
 
   _width = width;
605
 
   _height = height;
606
 
   _tempFiles.setAutoDelete( true );
607
 
   _streams.setAutoDelete( true );
608
 
   _waitingRequests.setAutoDelete( true );
609
 
   _callback = new NSPluginCallbackIface_stub( appId.latin1(), callbackId.latin1() );
610
 
   _xembed_window = xembed;
611
 
   _toplevel = _form = 0;
612
 
 
613
 
   KURL base(src);
614
 
   base.setFileName( QString::null );
615
 
   _baseURL = base.url();
616
 
 
617
 
   memcpy(&_pluginFuncs, pluginFuncs, sizeof(_pluginFuncs));
618
 
 
619
 
   _timer = new QTimer( this );
620
 
   connect( _timer, SIGNAL(timeout()), SLOT(timer()) );
621
 
 
622
 
   kdDebug(1431) << "NSPluginInstance::NSPluginInstance" << endl;
623
 
   kdDebug(1431) << "pdata = " << _npp->pdata << endl;
624
 
   kdDebug(1431) << "ndata = " << _npp->ndata << endl;
625
 
 
626
 
   if (width == 0)
627
 
      width = 1600;
628
 
 
629
 
   if (height == 0)
630
 
      height = 1200;
631
 
 
632
 
   if( _xembed_window == 0 ) {
633
 
      // create drawing area
634
 
      Arg args[7];
635
 
      Cardinal nargs = 0;
636
 
      XtSetArg(args[nargs], XtNwidth, width); nargs++;
637
 
      XtSetArg(args[nargs], XtNheight, height); nargs++;
638
 
      XtSetArg(args[nargs], XtNborderWidth, 0); nargs++;
639
 
 
640
 
      String n, c;
641
 
      XtGetApplicationNameAndClass(qt_xdisplay(), &n, &c);
642
 
 
643
 
      _toplevel = XtAppCreateShell("drawingArea", c, applicationShellWidgetClass,
644
 
                                   qt_xdisplay(), args, nargs);
645
 
 
646
 
      // What exactly does widget mapping mean? Without this call the widget isn't
647
 
      // embedded correctly. With it the viewer doesn't show anything in standalone mode.
648
 
      //if (embed)
649
 
         XtSetMappedWhenManaged(_toplevel, False);
650
 
      XtRealizeWidget(_toplevel);
651
 
 
652
 
      // Create form window that is searched for by flash plugin
653
 
      _form = XtVaCreateWidget("form", compositeWidgetClass, _toplevel, NULL);
654
 
      XtSetArg(args[nargs], XtNvisual, QPaintDevice::x11AppVisual()); nargs++;
655
 
      XtSetArg(args[nargs], XtNdepth, QPaintDevice::x11AppDepth()); nargs++;
656
 
      XtSetArg(args[nargs], XtNcolormap, QPaintDevice::x11AppColormap()); nargs++;
657
 
      XtSetValues(_form, args, nargs);
658
 
      XSync(qt_xdisplay(), false);
659
 
 
660
 
      // From mozilla - not sure if it's needed yet, nor what to use for embedder
661
 
#if 0
662
 
      /* this little trick seems to finish initializing the widget */
663
 
#if XlibSpecificationRelease >= 6
664
 
      XtRegisterDrawable(qt_xdisplay(), embedderid, _toplevel);
665
 
#else
666
 
      _XtRegisterWindow(embedderid, _toplevel);
667
 
#endif
668
 
#endif
669
 
      XtRealizeWidget(_form);
670
 
      XtManageChild(_form);
671
 
 
672
 
      // Register forwarder
673
 
      XtAddEventHandler(_toplevel, (KeyPressMask|KeyReleaseMask), 
674
 
                        False, forwarder, (XtPointer)this );
675
 
      XtAddEventHandler(_form, (KeyPressMask|KeyReleaseMask), 
676
 
                        False, forwarder, (XtPointer)this );
677
 
      XSync(qt_xdisplay(), false);
678
 
   }
679
 
}
680
 
 
681
 
NSPluginInstance::~NSPluginInstance()
682
 
{
683
 
   kdDebug(1431) << "-> ~NSPluginInstance" << endl;
684
 
   destroy();
685
 
   kdDebug(1431) << "<- ~NSPluginInstance" << endl;
686
 
}
687
 
 
688
 
 
689
 
void NSPluginInstance::destroy()
690
 
{
691
 
    if ( !_destroyed ) {
692
 
 
693
 
        kdDebug(1431) << "delete streams" << endl;
694
 
        _waitingRequests.clear();
695
 
 
696
 
        shutdown();
697
 
 
698
 
        for( NSPluginStreamBase *s=_streams.first(); s!=0; ) {
699
 
            NSPluginStreamBase *next = _streams.next();
700
 
            s->stop();
701
 
            s = next;
702
 
        }
703
 
 
704
 
        _streams.clear();
705
 
 
706
 
        kdDebug(1431) << "delete callbacks" << endl;
707
 
        delete _callback;
708
 
        _callback = 0;
709
 
 
710
 
        kdDebug(1431) << "destroy plugin" << endl;
711
 
        NPSavedData *saved = 0;
712
 
 
713
 
        // As of 7/31/01, nsplugin crashes when used with Qt
714
 
        // linked with libGL if the destroy function is called.
715
 
        // A patch on that date hacked out the following call.
716
 
        // On 11/17/01, Jeremy White has reenabled this destroy
717
 
        // in a an attempt to better understand why this crash
718
 
        // occurs so that the real problem can be found and solved.
719
 
        // It's possible that a flaw in the SetWindow call
720
 
        // caused the crash and it is now fixed.
721
 
        if ( _pluginFuncs.destroy )
722
 
            _pluginFuncs.destroy( _npp, &saved );
723
 
 
724
 
        if (saved && saved->len && saved->buf)
725
 
          g_NPN_MemFree(saved->buf);
726
 
        if (saved)
727
 
          g_NPN_MemFree(saved);
728
 
 
729
 
        if( _form != 0 ) {
730
 
            XtRemoveEventHandler(_form, (KeyPressMask|KeyReleaseMask), 
731
 
                                 False, forwarder, (XtPointer)this);
732
 
            XtRemoveEventHandler(_toplevel, (KeyPressMask|KeyReleaseMask), 
733
 
                                 False, forwarder, (XtPointer)this);
734
 
            XtDestroyWidget(_form);
735
 
            _form = 0;
736
 
            XtDestroyWidget(_toplevel);
737
 
            _toplevel = 0;
738
 
        }
739
 
 
740
 
        if (_npp) {
741
 
            ::free(_npp);   // matched with malloc() in newInstance
742
 
        }
743
 
 
744
 
        _destroyed = true;
745
 
    }
746
 
}
747
 
 
748
 
 
749
 
void NSPluginInstance::shutdown()
750
 
{
751
 
    NSPluginClass *cls = dynamic_cast<NSPluginClass*>(parent());
752
 
    //destroy();
753
 
    if (cls) {
754
 
        cls->destroyInstance( this );
755
 
    }
756
 
}
757
 
 
758
 
 
759
 
void NSPluginInstance::timer()
760
 
{
761
 
    if (!_visible) {
762
 
         _timer->start( 100, true );
763
 
         return;
764
 
    }
765
 
 
766
 
    //_streams.clear();
767
 
 
768
 
    // start queued requests
769
 
    kdDebug(1431) << "looking for waiting requests" << endl;
770
 
    while ( _waitingRequests.head() ) {
771
 
        kdDebug(1431) << "request found" << endl;
772
 
        Request req( *_waitingRequests.head() );
773
 
        _waitingRequests.remove();
774
 
 
775
 
        QString url;
776
 
 
777
 
        // make absolute url
778
 
        if ( req.url.left(11).lower()=="javascript:" )
779
 
            url = req.url;
780
 
        else if ( KURL::isRelativeURL(req.url) ) {
781
 
            KURL bu( _baseURL );
782
 
            KURL absUrl( bu, req.url );
783
 
            url = absUrl.url();
784
 
        } else if ( req.url[0]=='/' && KURL(_baseURL).hasHost() ) {
785
 
            KURL absUrl( _baseURL );
786
 
            absUrl.setPath( req.url );
787
 
            url = absUrl.url();
788
 
        } else
789
 
            url = req.url;
790
 
 
791
 
        // non empty target = frame target
792
 
        if ( !req.target.isEmpty())
793
 
        {
794
 
            if (_callback)
795
 
            {
796
 
                if ( req.post ) {
797
 
                    _callback->postURL( url, req.target, req.data, req.mime );
798
 
                } else {
799
 
                    _callback->requestURL( url, req.target );
800
 
                }
801
 
                if ( req.notify ) {
802
 
                    NPURLNotify( req.url, NPRES_DONE, req.notify );
803
 
                }
804
 
            }
805
 
        } else {
806
 
            if (!url.isEmpty())
807
 
            {
808
 
                kdDebug(1431) << "Starting new stream " << req.url << endl;
809
 
 
810
 
                if (req.post) {
811
 
                    // create stream
812
 
                    NSPluginStream *s = new NSPluginStream( this );
813
 
                    connect( s, SIGNAL(finished(NSPluginStreamBase*)),
814
 
                             SLOT(streamFinished(NSPluginStreamBase*)) );
815
 
                    _streams.append( s );
816
 
 
817
 
                    kdDebug() << "posting to " << url << endl;
818
 
 
819
 
                    emitStatus( i18n("Submitting data to %1").arg(url) );
820
 
                    s->post( url, req.data, req.mime, req.notify, req.args );
821
 
                } else if (url.lower().startsWith("javascript:")){
822
 
                    if (_callback) {
823
 
                        static Q_INT32 _jsrequestid = 0;
824
 
                        _jsrequests.insert(_jsrequestid, new Request(req));
825
 
                        _callback->evalJavaScript(_jsrequestid++, url.mid(11));
826
 
                    } else {
827
 
                        kdDebug() << "No callback for javascript: url!" << endl;
828
 
                    }
829
 
                } else {
830
 
                    // create stream
831
 
                    NSPluginStream *s = new NSPluginStream( this );
832
 
                    connect( s, SIGNAL(finished(NSPluginStreamBase*)),
833
 
                             SLOT(streamFinished(NSPluginStreamBase*)) );
834
 
                    _streams.append( s );
835
 
 
836
 
                    kdDebug() << "getting " << url << endl;
837
 
 
838
 
                    emitStatus( i18n("Requesting %1").arg(url) );
839
 
                    s->get( url, req.mime, req.notify, req.reload );
840
 
                }
841
 
 
842
 
                //break;
843
 
            }
844
 
        }
845
 
    }
846
 
}
847
 
 
848
 
 
849
 
QString NSPluginInstance::normalizedURL(const QString& url) const {
850
 
    KURL bu( _baseURL );
851
 
    KURL inURL(bu, url);
852
 
    KConfig cfg("kcmnspluginrc", true);
853
 
    cfg.setGroup("Misc");
854
 
 
855
 
    if (!cfg.readBoolEntry("HTTP URLs Only", false) ||
856
 
        inURL.protocol() == "http" ||
857
 
        inURL.protocol() == "https" ||
858
 
        inURL.protocol() == "javascript") {
859
 
        return inURL.url();
860
 
    }
861
 
 
862
 
    // Allow: javascript:, http, https, or no protocol (match loading)
863
 
    kdDebug(1431) << "NSPluginInstance::normalizedURL - I don't think so.  http or https only!" << endl;
864
 
    return QString::null;
865
 
}
866
 
 
867
 
 
868
 
void NSPluginInstance::requestURL( const QString &url, const QString &mime,
869
 
                                   const QString &target, void *notify, bool forceNotify, bool reload )
870
 
{
871
 
    // Generally this should already be done, but let's be safe for now.
872
 
    QString nurl = normalizedURL(url);
873
 
    if (nurl.isNull()) {
874
 
        return;
875
 
    }
876
 
 
877
 
    kdDebug(1431) << "NSPluginInstance::requestURL url=" << nurl << " target=" << target << " notify=" << notify << endl;
878
 
    _waitingRequests.enqueue( new Request( nurl, mime, target, notify, forceNotify, reload ) );
879
 
    _timer->start( 100, true );
880
 
}
881
 
 
882
 
 
883
 
void NSPluginInstance::postURL( const QString &url, const QByteArray& data,
884
 
                                const QString &mime,
885
 
                                const QString &target, void *notify,
886
 
                                const KParts::URLArgs& args, bool forceNotify )
887
 
{
888
 
    // Generally this should already be done, but let's be safe for now.
889
 
    QString nurl = normalizedURL(url);
890
 
    if (nurl.isNull()) {
891
 
        return;
892
 
    }
893
 
 
894
 
    kdDebug(1431) << "NSPluginInstance::postURL url=" << nurl << " target=" << target << " notify=" << notify << endl;
895
 
    _waitingRequests.enqueue( new Request( nurl, data, mime, target, notify, args, forceNotify) );
896
 
    _timer->start( 100, true );
897
 
}
898
 
 
899
 
 
900
 
void NSPluginInstance::emitStatus(const QString &message)
901
 
{
902
 
    if( _callback )
903
 
      _callback->statusMessage( message );
904
 
}
905
 
 
906
 
 
907
 
void NSPluginInstance::streamFinished( NSPluginStreamBase* strm )
908
 
{
909
 
   kdDebug(1431) << "-> NSPluginInstance::streamFinished" << endl;
910
 
   emitStatus( QString::null );
911
 
   _streams.setAutoDelete(false); // Don't delete it yet!!  we get called from
912
 
                                  // its slot!
913
 
   _streams.remove(strm);
914
 
   _streams.setAutoDelete(true);
915
 
   strm->deleteLater();
916
 
   _timer->start( 100, true );
917
 
}
918
 
 
919
 
int NSPluginInstance::setWindow(Q_INT8 remove)
920
 
{
921
 
   if (remove)
922
 
   {
923
 
      NPSetWindow(0);
924
 
      return NPERR_NO_ERROR;
925
 
   }
926
 
 
927
 
   kdDebug(1431) << "-> NSPluginInstance::setWindow" << endl;
928
 
 
929
 
   _win.x = 0;
930
 
   _win.y = 0;
931
 
   _win.height = _height;
932
 
   _win.width = _width;
933
 
   _win.type = NPWindowTypeWindow;
934
 
 
935
 
   // Well, the docu says sometimes, this is only used on the
936
 
   // MAC, but sometimes it says it's always. Who knows...
937
 
   _win.clipRect.top = 0;
938
 
   _win.clipRect.left = 0;
939
 
   _win.clipRect.bottom = _height;
940
 
   _win.clipRect.right = _width;
941
 
 
942
 
   if( _xembed_window ) {
943
 
      _win.window = (void*) _xembed_window;
944
 
      _win_info.type = NP_SETWINDOW;
945
 
      _win_info.display = qt_xdisplay();
946
 
      _win_info.visual = DefaultVisualOfScreen(DefaultScreenOfDisplay(qt_xdisplay()));
947
 
      _win_info.colormap = DefaultColormapOfScreen(DefaultScreenOfDisplay(qt_xdisplay()));
948
 
      _win_info.depth = DefaultDepthOfScreen(DefaultScreenOfDisplay(qt_xdisplay()));
949
 
   } else {
950
 
      _win.window = (void*) XtWindow(_form);
951
 
 
952
 
      _win_info.type = NP_SETWINDOW;
953
 
      _win_info.display = XtDisplay(_form);
954
 
      _win_info.visual = DefaultVisualOfScreen(XtScreen(_form));
955
 
      _win_info.colormap = DefaultColormapOfScreen(XtScreen(_form));
956
 
      _win_info.depth = DefaultDepthOfScreen(XtScreen(_form));
957
 
   }
958
 
 
959
 
   kdDebug(1431) << "Window ID = " << _win.window << endl;
960
 
 
961
 
   _win.ws_info = &_win_info;
962
 
 
963
 
   NPError error = NPSetWindow( &_win );
964
 
 
965
 
   kdDebug(1431) << "<- NSPluginInstance::setWindow = " << error << endl;
966
 
   return error;
967
 
}
968
 
 
969
 
 
970
 
static void resizeWidgets(Window w, int width, int height) {
971
 
   Window rroot, parent, *children;
972
 
   unsigned int nchildren = 0;
973
 
 
974
 
   if (XQueryTree(qt_xdisplay(), w, &rroot, &parent, &children, &nchildren)) {
975
 
      for (unsigned int i = 0; i < nchildren; i++) {
976
 
         XResizeWindow(qt_xdisplay(), children[i], width, height);
977
 
      }
978
 
      XFree(children);
979
 
   }
980
 
}
981
 
 
982
 
 
983
 
void NSPluginInstance::resizePlugin(Q_INT32 w, Q_INT32 h)
984
 
{
985
 
   if (w == _width && h == _height)
986
 
      return;
987
 
 
988
 
   kdDebug(1431) << "-> NSPluginInstance::resizePlugin( w=" << w << ", h=" << h << " ) " << endl;
989
 
 
990
 
   _width = w;
991
 
   _height = h;
992
 
 
993
 
   if( _form != 0 ) {
994
 
      XResizeWindow(qt_xdisplay(), XtWindow(_form), w, h);
995
 
      XResizeWindow(qt_xdisplay(), XtWindow(_toplevel), w, h);
996
 
 
997
 
      Arg args[7];
998
 
      Cardinal nargs = 0;
999
 
      XtSetArg(args[nargs], XtNwidth, _width); nargs++;
1000
 
      XtSetArg(args[nargs], XtNheight, _height); nargs++;
1001
 
      XtSetArg(args[nargs], XtNvisual, QPaintDevice::x11AppVisual()); nargs++;
1002
 
      XtSetArg(args[nargs], XtNdepth, QPaintDevice::x11AppDepth()); nargs++;
1003
 
      XtSetArg(args[nargs], XtNcolormap, QPaintDevice::x11AppColormap()); nargs++;
1004
 
      XtSetArg(args[nargs], XtNborderWidth, 0); nargs++;
1005
 
 
1006
 
      XtSetValues(_toplevel, args, nargs);
1007
 
      XtSetValues(_form, args, nargs);
1008
 
 
1009
 
      resizeWidgets(XtWindow(_form), _width, _height);
1010
 
   }
1011
 
 
1012
 
   // If not visible yet, displayWindow() will call setWindow() again anyway, so avoid this.
1013
 
   // This also handled plugins that are broken and cannot handle repeated setWindow() calls
1014
 
   // very well.
1015
 
   if (!_visible)
1016
 
      return;
1017
 
 
1018
 
   setWindow();
1019
 
 
1020
 
   kdDebug(1431) << "<- NSPluginInstance::resizePlugin" << endl;
1021
 
}
1022
 
 
1023
 
 
1024
 
void NSPluginInstance::javascriptResult(Q_INT32 id, QString result) {
1025
 
    QMap<int, Request*>::iterator i = _jsrequests.find( id );
1026
 
    if (i != _jsrequests.end()) {
1027
 
        Request *req = i.data();
1028
 
        _jsrequests.remove( i );
1029
 
        NSPluginStream *s = new NSPluginStream( this );
1030
 
        connect( s, SIGNAL(finished(NSPluginStreamBase*)),
1031
 
                 SLOT(streamFinished(NSPluginStreamBase*)) );
1032
 
        _streams.append( s );
1033
 
 
1034
 
        int len = result.length();
1035
 
        s->create( req->url, QString("text/plain"), req->notify, req->forceNotify );
1036
 
        kdDebug(1431) << "javascriptResult has been called with: "<<result<<endl;
1037
 
        if (len > 0) {
1038
 
            QByteArray data(len + 1);
1039
 
            memcpy(data.data(), result.latin1(), len);
1040
 
            data[len] = 0;
1041
 
            s->process(data, 0);
1042
 
        } else {
1043
 
            len = 7; //  "unknown"
1044
 
            QByteArray data(len + 1);
1045
 
            memcpy(data.data(), "unknown", len);
1046
 
            data[len] = 0;
1047
 
            s->process(data, 0);
1048
 
        }
1049
 
        s->finish(false);
1050
 
 
1051
 
        delete req;
1052
 
    }
1053
 
}
1054
 
 
1055
 
 
1056
 
NPError NSPluginInstance::NPGetValue(NPPVariable variable, void *value)
1057
 
{
1058
 
    if( value==0 ) {
1059
 
        kdDebug() << "FIXME: value==0 in NSPluginInstance::NPGetValue" << endl;
1060
 
        return NPERR_GENERIC_ERROR;
1061
 
    }
1062
 
 
1063
 
    if (!_pluginFuncs.getvalue)
1064
 
        return NPERR_GENERIC_ERROR;
1065
 
 
1066
 
    NPError error = _pluginFuncs.getvalue(_npp, variable, value);
1067
 
 
1068
 
    CHECK(GetValue,error);
1069
 
}
1070
 
 
1071
 
 
1072
 
NPError NSPluginInstance::NPSetValue(NPNVariable variable, void *value)
1073
 
{
1074
 
    if( value==0 ) {
1075
 
        kdDebug() << "FIXME: value==0 in NSPluginInstance::NPSetValue" << endl;
1076
 
        return NPERR_GENERIC_ERROR;
1077
 
    }
1078
 
 
1079
 
    if (!_pluginFuncs.setvalue)
1080
 
        return NPERR_GENERIC_ERROR;
1081
 
 
1082
 
    NPError error = _pluginFuncs.setvalue(_npp, variable, value);
1083
 
 
1084
 
    CHECK(SetValue,error);
1085
 
}
1086
 
 
1087
 
 
1088
 
NPError NSPluginInstance::NPSetWindow(NPWindow *window)
1089
 
{
1090
 
    if( window==0 ) {
1091
 
        kdDebug() << "FIXME: window==0 in NSPluginInstance::NPSetWindow" << endl;
1092
 
        return NPERR_GENERIC_ERROR;
1093
 
    }
1094
 
 
1095
 
    if (!_pluginFuncs.setwindow)
1096
 
        return NPERR_GENERIC_ERROR;
1097
 
 
1098
 
    NPError error = _pluginFuncs.setwindow(_npp, window);
1099
 
 
1100
 
    CHECK(SetWindow,error);
1101
 
}
1102
 
 
1103
 
 
1104
 
NPError NSPluginInstance::NPDestroyStream(NPStream *stream, NPReason reason)
1105
 
{
1106
 
    if( stream==0 ) {
1107
 
        kdDebug() << "FIXME: stream==0 in NSPluginInstance::NPDestroyStream" << endl;
1108
 
        return NPERR_GENERIC_ERROR;
1109
 
    }
1110
 
 
1111
 
    if (!_pluginFuncs.destroystream)
1112
 
        return NPERR_GENERIC_ERROR;
1113
 
 
1114
 
    NPError error = _pluginFuncs.destroystream(_npp, stream, reason);
1115
 
 
1116
 
    CHECK(DestroyStream,error);
1117
 
}
1118
 
 
1119
 
 
1120
 
NPError NSPluginInstance::NPNewStream(NPMIMEType type, NPStream *stream, NPBool seekable, uint16 *stype)
1121
 
{
1122
 
    if( stream==0 ) {
1123
 
        kdDebug() << "FIXME: stream==0 in NSPluginInstance::NPNewStream" << endl;
1124
 
        return NPERR_GENERIC_ERROR;
1125
 
    }
1126
 
 
1127
 
    if( stype==0 ) {
1128
 
        kdDebug() << "FIXME: stype==0 in NSPluginInstance::NPNewStream" << endl;
1129
 
        return NPERR_GENERIC_ERROR;
1130
 
    }
1131
 
 
1132
 
    if (!_pluginFuncs.newstream)
1133
 
        return NPERR_GENERIC_ERROR;
1134
 
 
1135
 
    NPError error = _pluginFuncs.newstream(_npp, type, stream, seekable, stype);
1136
 
 
1137
 
    CHECK(NewStream,error);
1138
 
}
1139
 
 
1140
 
 
1141
 
void NSPluginInstance::NPStreamAsFile(NPStream *stream, const char *fname)
1142
 
{
1143
 
    if( stream==0 ) {
1144
 
        kdDebug() << "FIXME: stream==0 in NSPluginInstance::NPStreamAsFile" << endl;
1145
 
        return;
1146
 
    }
1147
 
 
1148
 
    if( fname==0 ) {
1149
 
        kdDebug() << "FIXME: fname==0 in NSPluginInstance::NPStreamAsFile" << endl;
1150
 
        return;
1151
 
    }
1152
 
 
1153
 
    if (!_pluginFuncs.asfile)
1154
 
        return;
1155
 
 
1156
 
    _pluginFuncs.asfile(_npp, stream, fname);
1157
 
}
1158
 
 
1159
 
 
1160
 
int32 NSPluginInstance::NPWrite(NPStream *stream, int32 offset, int32 len, void *buf)
1161
 
{
1162
 
    if( stream==0 ) {
1163
 
        kdDebug() << "FIXME: stream==0 in NSPluginInstance::NPWrite" << endl;
1164
 
        return 0;
1165
 
    }
1166
 
 
1167
 
    if( buf==0 ) {
1168
 
        kdDebug() << "FIXME: buf==0 in NSPluginInstance::NPWrite" << endl;
1169
 
        return 0;
1170
 
    }
1171
 
 
1172
 
    if (!_pluginFuncs.write)
1173
 
        return 0;
1174
 
 
1175
 
    return _pluginFuncs.write(_npp, stream, offset, len, buf);
1176
 
}
1177
 
 
1178
 
 
1179
 
int32 NSPluginInstance::NPWriteReady(NPStream *stream)
1180
 
{
1181
 
    if( stream==0 ) {
1182
 
        kdDebug() << "FIXME: stream==0 in NSPluginInstance::NPWriteReady" << endl;
1183
 
        return 0;
1184
 
    }
1185
 
 
1186
 
    if (!_pluginFuncs.writeready)
1187
 
        return 0;
1188
 
 
1189
 
    return _pluginFuncs.writeready(_npp, stream);
1190
 
}
1191
 
 
1192
 
 
1193
 
void NSPluginInstance::NPURLNotify(QString url, NPReason reason, void *notifyData)
1194
 
{
1195
 
   if (!_pluginFuncs.urlnotify)
1196
 
      return;
1197
 
 
1198
 
   _pluginFuncs.urlnotify(_npp, url.ascii(), reason, notifyData);
1199
 
}
1200
 
 
1201
 
 
1202
 
void NSPluginInstance::addTempFile(KTempFile *tmpFile)
1203
 
{
1204
 
   _tempFiles.append(tmpFile);
1205
 
}
1206
 
 
1207
 
/*
1208
 
 *   We have to call this after we reparent the widget otherwise some plugins
1209
 
 *   like the ones based on WINE get very confused. (their coordinates are not
1210
 
 *   adjusted for the mouse at best)
1211
 
 */
1212
 
void NSPluginInstance::displayPlugin()
1213
 
{
1214
 
   // display plugin
1215
 
   setWindow();
1216
 
 
1217
 
   _visible = true;
1218
 
   kdDebug(1431) << "<- NSPluginInstance::displayPlugin = " << (void*)this << endl;
1219
 
}
1220
 
 
1221
 
static bool has_focus = false;
1222
 
 
1223
 
void NSPluginInstance::gotFocusIn()
1224
 
{
1225
 
  has_focus = true;
1226
 
}
1227
 
 
1228
 
void NSPluginInstance::gotFocusOut()
1229
 
{
1230
 
  has_focus = false;
1231
 
}
1232
 
 
1233
 
#include <dlfcn.h>
1234
 
// Prevent plugins from polling the keyboard regardless of focus.
1235
 
static int (*real_xquerykeymap)( Display*, char[32] ) = NULL;
1236
 
 
1237
 
extern "C" KDE_EXPORT
1238
 
int XQueryKeymap( Display* dpy, char k[32] )
1239
 
{
1240
 
    if( real_xquerykeymap == NULL )
1241
 
        real_xquerykeymap = (int (*)( Display*, char[32] )) dlsym( RTLD_NEXT, "XQueryKeymap" );
1242
 
    if( has_focus )
1243
 
        return real_xquerykeymap( dpy, k );
1244
 
    memset( k, 0, 32 );
1245
 
    return 1;
1246
 
}
1247
 
 
1248
 
 
1249
 
 
1250
 
/***************************************************************************/
1251
 
 
1252
 
NSPluginViewer::NSPluginViewer( QCString dcopId,
1253
 
                                QObject *parent, const char *name )
1254
 
   : DCOPObject(dcopId), QObject( parent, name ) 
1255
 
{
1256
 
    _classes.setAutoDelete( true );
1257
 
    connect(KApplication::dcopClient(),
1258
 
            SIGNAL(applicationRemoved(const QCString&)),
1259
 
            this,
1260
 
            SLOT(appUnregistered(const QCString&)));
1261
 
}
1262
 
 
1263
 
 
1264
 
NSPluginViewer::~NSPluginViewer()
1265
 
{
1266
 
   kdDebug(1431) << "NSPluginViewer::~NSPluginViewer" << endl;
1267
 
}
1268
 
 
1269
 
 
1270
 
void NSPluginViewer::appUnregistered(const QCString& id) {
1271
 
   if (id.isEmpty()) {
1272
 
      return;
1273
 
   }
1274
 
 
1275
 
   QDictIterator<NSPluginClass> it(_classes);
1276
 
   NSPluginClass *c;
1277
 
   while ( (c = it.current()) ) {
1278
 
      QString key = it.currentKey();
1279
 
      ++it;
1280
 
      if (c->app() == id) {
1281
 
         _classes.remove(key);
1282
 
      }
1283
 
   }
1284
 
 
1285
 
   if (_classes.isEmpty()) {
1286
 
      shutdown();
1287
 
   }
1288
 
}
1289
 
 
1290
 
 
1291
 
void NSPluginViewer::shutdown()
1292
 
{
1293
 
   kdDebug(1431) << "NSPluginViewer::shutdown" << endl;
1294
 
   _classes.clear();
1295
 
#if QT_VERSION < 0x030100
1296
 
   quitXt();
1297
 
#else
1298
 
   qApp->quit();
1299
 
#endif
1300
 
}
1301
 
 
1302
 
 
1303
 
DCOPRef NSPluginViewer::newClass( QString plugin )
1304
 
{
1305
 
   kdDebug(1431) << "NSPluginViewer::NewClass( " << plugin << ")" << endl;
1306
 
 
1307
 
   // search existing class
1308
 
   NSPluginClass *cls = _classes[ plugin ];
1309
 
   if ( !cls ) {
1310
 
       // create new class
1311
 
       cls = new NSPluginClass( plugin, this );
1312
 
       QCString id = "";
1313
 
       DCOPClient *dc = callingDcopClient();
1314
 
       if (dc) {
1315
 
          id = dc->senderId();
1316
 
       }
1317
 
       cls->setApp(id);
1318
 
       if ( cls->error() ) {
1319
 
           kdError(1431) << "Can't create plugin class" << endl;
1320
 
           delete cls;
1321
 
           return DCOPRef();
1322
 
       }
1323
 
 
1324
 
       _classes.insert( plugin, cls );
1325
 
   }
1326
 
 
1327
 
   return DCOPRef( kapp->dcopClient()->appId(), cls->objId() );
1328
 
}
1329
 
 
1330
 
 
1331
 
/****************************************************************************/
1332
 
 
1333
 
 
1334
 
NSPluginClass::NSPluginClass( const QString &library,
1335
 
                              QObject *parent, const char *name )
1336
 
   : DCOPObject(), QObject( parent, name ) 
1337
 
{
1338
 
    // initialize members
1339
 
    _handle = KLibLoader::self()->library(QFile::encodeName(library));
1340
 
    _libname = library;
1341
 
    _constructed = false;
1342
 
    _error = true;
1343
 
    _instances.setAutoDelete( true );
1344
 
    _NP_GetMIMEDescription = 0;
1345
 
    _NP_Initialize = 0;
1346
 
    _NP_Shutdown = 0;
1347
 
 
1348
 
    _timer = new QTimer( this );
1349
 
    connect( _timer, SIGNAL(timeout()), SLOT(timer()) );
1350
 
 
1351
 
    // check lib handle
1352
 
    if (!_handle) {
1353
 
        kdDebug(1431) << "Could not dlopen " << library << endl;
1354
 
        return;
1355
 
    }
1356
 
 
1357
 
    // get exported lib functions
1358
 
    _NP_GetMIMEDescription = (NP_GetMIMEDescriptionUPP *)_handle->symbol("NP_GetMIMEDescription");
1359
 
    _NP_Initialize = (NP_InitializeUPP *)_handle->symbol("NP_Initialize");
1360
 
    _NP_Shutdown = (NP_ShutdownUPP *)_handle->symbol("NP_Shutdown");
1361
 
 
1362
 
    // check for valid returned ptrs
1363
 
    if (!_NP_GetMIMEDescription) {
1364
 
        kdDebug(1431) << "Could not get symbol NP_GetMIMEDescription" << endl;
1365
 
        return;
1366
 
    }
1367
 
 
1368
 
    if (!_NP_Initialize) {
1369
 
        kdDebug(1431) << "Could not get symbol NP_Initialize" << endl;
1370
 
        return;
1371
 
    }
1372
 
 
1373
 
    if (!_NP_Shutdown) {
1374
 
        kdDebug(1431) << "Could not get symbol NP_Shutdown" << endl;
1375
 
        return;
1376
 
    }
1377
 
 
1378
 
    // initialize plugin
1379
 
    kdDebug(1431) << "Plugin library " << library << " loaded!" << endl;
1380
 
    _constructed = true;
1381
 
    _error = initialize()!=NPERR_NO_ERROR;
1382
 
}
1383
 
 
1384
 
 
1385
 
NSPluginClass::~NSPluginClass()
1386
 
{
1387
 
    _instances.clear();
1388
 
    _trash.clear();
1389
 
    shutdown();
1390
 
    if (_handle)
1391
 
      _handle->unload();
1392
 
}
1393
 
 
1394
 
 
1395
 
void NSPluginClass::timer()
1396
 
{
1397
 
    // delete instances
1398
 
    for ( NSPluginInstance *it=_trash.first(); it!=0; it=_trash.next() )
1399
 
        _instances.remove(it);
1400
 
 
1401
 
    _trash.clear();
1402
 
}
1403
 
 
1404
 
 
1405
 
int NSPluginClass::initialize()
1406
 
{
1407
 
   kdDebug(1431) << "NSPluginClass::Initialize()" << endl;
1408
 
 
1409
 
   if ( !_constructed )
1410
 
      return NPERR_GENERIC_ERROR;
1411
 
 
1412
 
   // initialize nescape exported functions
1413
 
   memset(&_pluginFuncs, 0, sizeof(_pluginFuncs));
1414
 
   memset(&_nsFuncs, 0, sizeof(_nsFuncs));
1415
 
 
1416
 
   _pluginFuncs.size = sizeof(_pluginFuncs);
1417
 
   _nsFuncs.size = sizeof(_nsFuncs);
1418
 
   _nsFuncs.version = (NP_VERSION_MAJOR << 8) + NP_VERSION_MINOR;
1419
 
   _nsFuncs.geturl = g_NPN_GetURL;
1420
 
   _nsFuncs.posturl = g_NPN_PostURL;
1421
 
   _nsFuncs.requestread = g_NPN_RequestRead;
1422
 
   _nsFuncs.newstream = g_NPN_NewStream;
1423
 
   _nsFuncs.write = g_NPN_Write;
1424
 
   _nsFuncs.destroystream = g_NPN_DestroyStream;
1425
 
   _nsFuncs.status = g_NPN_Status;
1426
 
   _nsFuncs.uagent = g_NPN_UserAgent;
1427
 
   _nsFuncs.memalloc = g_NPN_MemAlloc;
1428
 
   _nsFuncs.memfree = g_NPN_MemFree;
1429
 
   _nsFuncs.memflush = g_NPN_MemFlush;
1430
 
   _nsFuncs.reloadplugins = g_NPN_ReloadPlugins;
1431
 
   _nsFuncs.getJavaEnv = g_NPN_GetJavaEnv;
1432
 
   _nsFuncs.getJavaPeer = g_NPN_GetJavaPeer;
1433
 
   _nsFuncs.geturlnotify = g_NPN_GetURLNotify;
1434
 
   _nsFuncs.posturlnotify = g_NPN_PostURLNotify;
1435
 
   _nsFuncs.getvalue = g_NPN_GetValue;
1436
 
   _nsFuncs.setvalue = g_NPN_SetValue;
1437
 
   _nsFuncs.invalidaterect = g_NPN_InvalidateRect;
1438
 
   _nsFuncs.invalidateregion = g_NPN_InvalidateRegion;
1439
 
   _nsFuncs.forceredraw = g_NPN_ForceRedraw;
1440
 
 
1441
 
   // initialize plugin
1442
 
   NPError error = _NP_Initialize(&_nsFuncs, &_pluginFuncs);
1443
 
   CHECK(Initialize,error);
1444
 
}
1445
 
 
1446
 
 
1447
 
QString NSPluginClass::getMIMEDescription()
1448
 
{
1449
 
   return _NP_GetMIMEDescription();
1450
 
}
1451
 
 
1452
 
 
1453
 
void NSPluginClass::shutdown()
1454
 
{
1455
 
    kdDebug(1431) << "NSPluginClass::shutdown error=" << _error << endl;
1456
 
    if( _NP_Shutdown && !_error )
1457
 
        _NP_Shutdown();
1458
 
}
1459
 
 
1460
 
 
1461
 
DCOPRef NSPluginClass::newInstance( QString url, QString mimeType, Q_INT8 embed,
1462
 
                                    QStringList argn, QStringList argv,
1463
 
                                    QString appId, QString callbackId,
1464
 
                                    Q_INT8 reload, Q_INT8 doPost, QByteArray postData, Q_UINT32 xembed )
1465
 
{
1466
 
   kdDebug(1431) << "-> NSPluginClass::NewInstance" << endl;
1467
 
 
1468
 
   if ( !_constructed )
1469
 
       return DCOPRef();
1470
 
 
1471
 
   // copy parameters over
1472
 
   unsigned int argc = argn.count();
1473
 
   char **_argn = new char*[argc];
1474
 
   char **_argv = new char*[argc];
1475
 
   QString src = url;
1476
 
   int width = 0;
1477
 
   int height = 0;
1478
 
   QString baseURL = url;
1479
 
 
1480
 
   for (unsigned int i=0; i<argc; i++)
1481
 
   {
1482
 
      QCString encN = argn[i].utf8();
1483
 
      QCString encV = argv[i].utf8();
1484
 
 
1485
 
      const char *n = encN;
1486
 
      const char *v = encV;
1487
 
 
1488
 
      _argn[i] = strdup(n);
1489
 
      _argv[i] = strdup(v);
1490
 
 
1491
 
      if (!strcasecmp(_argn[i], "WIDTH")) width = argv[i].toInt();
1492
 
      if (!strcasecmp(_argn[i], "HEIGHT")) height = argv[i].toInt();
1493
 
      if (!strcasecmp(_argn[i], "__KHTML__PLUGINBASEURL")) baseURL = _argv[i];
1494
 
      kdDebug(1431) << "argn=" << _argn[i] << " argv=" << _argv[i] << endl;
1495
 
   }
1496
 
 
1497
 
   // create plugin instance
1498
 
   char mime[256];
1499
 
   strncpy(mime, mimeType.ascii(), 255);
1500
 
   mime[255] = 0;
1501
 
   NPP npp = (NPP)malloc(sizeof(NPP_t));   // I think we should be using
1502
 
                                           // malloc here, just to be safe,
1503
 
                                           // since the nsplugin plays with
1504
 
                                           // this thing
1505
 
   memset(npp, 0, sizeof(NPP_t));
1506
 
   npp->ndata = NULL;
1507
 
 
1508
 
   // create plugin instance
1509
 
   NPError error = _pluginFuncs.newp(mime, npp, embed ? NP_EMBED : NP_FULL,
1510
 
                                     argc, _argn, _argv, 0);
1511
 
   kdDebug(1431) << "NPP_New = " << (int)error << endl;
1512
 
 
1513
 
   // don't use bool here, it can be 1 byte, but some plugins write it as int, and I can't find what the spec says
1514
 
   int wants_xembed = false;
1515
 
   if (_pluginFuncs.getvalue) {
1516
 
      NPError error = _pluginFuncs.getvalue(npp, (NPPVariable)14/*NPPVpluginNeedsXEmbed*/, &wants_xembed );
1517
 
      if( error != NPERR_NO_ERROR )
1518
 
         wants_xembed = false;
1519
 
   }
1520
 
   kdDebug(1431) << "Plugin requires XEmbed:" << (bool)wants_xembed << endl;
1521
 
 
1522
 
   // Create plugin instance object
1523
 
   NSPluginInstance *inst = new NSPluginInstance( npp, &_pluginFuncs, _handle,
1524
 
                                                  width, height, baseURL, mimeType,
1525
 
                                                  appId, callbackId, embed, wants_xembed ? xembed : 0, this );
1526
 
 
1527
 
   // free arrays with arguments
1528
 
   delete [] _argn;
1529
 
   delete [] _argv;
1530
 
 
1531
 
   // check for error
1532
 
   if ( error!=NPERR_NO_ERROR)
1533
 
   {
1534
 
      delete inst;
1535
 
      //delete npp;    double delete!
1536
 
      kdDebug(1431) << "<- PluginClass::NewInstance = 0" << endl;
1537
 
      return DCOPRef();
1538
 
   }
1539
 
 
1540
 
   // create source stream
1541
 
   if ( !src.isEmpty() ) {
1542
 
       if (doPost) {
1543
 
           inst->postURL(src, postData, mimeType, QString::null, 0, KParts::URLArgs(), false);
1544
 
       } else {
1545
 
           inst->requestURL( src, mimeType, QString::null, 0, false, reload );
1546
 
       }
1547
 
   }
1548
 
 
1549
 
   _instances.append( inst );
1550
 
   return DCOPRef(kapp->dcopClient()->appId(), inst->objId());
1551
 
}
1552
 
 
1553
 
 
1554
 
void NSPluginClass::destroyInstance( NSPluginInstance* inst )
1555
 
{
1556
 
    // mark for destruction
1557
 
    _trash.append( inst );
1558
 
    timer(); //_timer->start( 0, TRUE );
1559
 
}
1560
 
 
1561
 
/****************************************************************************/
1562
 
 
1563
 
NSPluginStreamBase::NSPluginStreamBase( NSPluginInstance *instance )
1564
 
   : QObject( instance ), _instance(instance), _stream(0), _tempFile(0L),
1565
 
     _pos(0), _queue(0), _queuePos(0), _error(false)
1566
 
{
1567
 
   _informed = false;
1568
 
}
1569
 
 
1570
 
 
1571
 
NSPluginStreamBase::~NSPluginStreamBase()
1572
 
{
1573
 
   if (_stream) {
1574
 
      _instance->NPDestroyStream( _stream, NPRES_USER_BREAK );
1575
 
      if (_stream && _stream->url)
1576
 
          free(const_cast<char*>(_stream->url));
1577
 
      delete _stream;
1578
 
      _stream = 0;
1579
 
   }
1580
 
 
1581
 
   delete _tempFile;
1582
 
   _tempFile = 0;
1583
 
}
1584
 
 
1585
 
 
1586
 
void NSPluginStreamBase::stop()
1587
 
{
1588
 
    finish( true );
1589
 
}
1590
 
 
1591
 
void NSPluginStreamBase::inform()
1592
 
{
1593
 
 
1594
 
    if (! _informed)
1595
 
    {
1596
 
        KURL src(_url);
1597
 
 
1598
 
        _informed = true;
1599
 
 
1600
 
        // inform the plugin
1601
 
        _instance->NPNewStream( _mimeType.isEmpty() ? (char *) "text/plain" :  (char*)_mimeType.ascii(),
1602
 
                    _stream, false, &_streamType );
1603
 
        kdDebug(1431) << "NewStream stype=" << _streamType << " url=" << _url << " mime=" << _mimeType << endl;
1604
 
 
1605
 
        // prepare data transfer
1606
 
        _tempFile = 0L;
1607
 
 
1608
 
        if ( _streamType==NP_ASFILE || _streamType==NP_ASFILEONLY ) {
1609
 
            _onlyAsFile = _streamType==NP_ASFILEONLY;
1610
 
            if ( KURL(_url).isLocalFile() )  {
1611
 
                kdDebug(1431) << "local file" << endl;
1612
 
                // local file can be passed directly
1613
 
                _fileURL = KURL(_url).path();
1614
 
 
1615
 
                // without streaming stream is finished already
1616
 
                if ( _onlyAsFile ) {
1617
 
                    kdDebug() << "local file AS_FILE_ONLY" << endl;
1618
 
                    finish( false );
1619
 
                }
1620
 
            } else {
1621
 
                kdDebug() << "remote file" << endl;
1622
 
 
1623
 
                // stream into temporary file (use lower() in case the
1624
 
                // filename as an upper case X in it)
1625
 
                _tempFile = new KTempFile;
1626
 
                _tempFile->setAutoDelete( TRUE );
1627
 
                _fileURL = _tempFile->name();
1628
 
                kdDebug() << "saving into " << _fileURL << endl;
1629
 
            }
1630
 
        }
1631
 
    }
1632
 
 
1633
 
}
1634
 
 
1635
 
bool NSPluginStreamBase::create( const QString& url, const QString& mimeType, void *notify, bool forceNotify)
1636
 
{
1637
 
    if ( _stream )
1638
 
        return false;
1639
 
 
1640
 
    _url = url;
1641
 
    _notifyData = notify;
1642
 
    _pos = 0;
1643
 
    _tries = 0;
1644
 
    _onlyAsFile = false;
1645
 
    _streamType = NP_NORMAL;
1646
 
    _informed = false;
1647
 
    _forceNotify = forceNotify;
1648
 
 
1649
 
    // create new stream
1650
 
    _stream = new NPStream;
1651
 
    _stream->ndata = this;
1652
 
    _stream->url = strdup(url.ascii());
1653
 
    _stream->end = 0;
1654
 
    _stream->pdata = 0;
1655
 
    _stream->lastmodified = 0;
1656
 
    _stream->notifyData = _notifyData;
1657
 
 
1658
 
    _mimeType = mimeType;
1659
 
 
1660
 
    return true;
1661
 
}
1662
 
 
1663
 
void NSPluginStreamBase::updateURL( const KURL& newURL )
1664
 
{
1665
 
    _url = newURL;
1666
 
    free(const_cast<char*>(_stream->url));
1667
 
    _stream->url = strdup(_url.url().ascii());
1668
 
}
1669
 
 
1670
 
int NSPluginStreamBase::process( const QByteArray &data, int start )
1671
 
{
1672
 
   int32 max, sent, to_sent, len;
1673
 
   char *d = data.data() + start;
1674
 
 
1675
 
   to_sent = data.size() - start;
1676
 
   while (to_sent > 0)
1677
 
   {
1678
 
      inform();
1679
 
 
1680
 
      max = _instance->NPWriteReady(_stream);
1681
 
      //kdDebug(1431) << "to_sent == " << to_sent << " and max = " << max << endl;
1682
 
      len = QMIN(max, to_sent);
1683
 
 
1684
 
      //kdDebug(1431) << "-> Feeding stream to plugin: offset=" << _pos << ", len=" << len << endl;
1685
 
      sent = _instance->NPWrite( _stream, _pos, len, d );
1686
 
      //kdDebug(1431) << "<- Feeding stream: sent = " << sent << endl;
1687
 
 
1688
 
      if (sent == 0) // interrupt the stream for a few ms
1689
 
          break;
1690
 
 
1691
 
      if (sent < 0) {
1692
 
          // stream data rejected/error
1693
 
          kdDebug(1431) << "stream data rejected/error" << endl;
1694
 
          _error = true;
1695
 
          break;
1696
 
      }
1697
 
 
1698
 
      if (_tempFile) {
1699
 
          _tempFile->dataStream()->writeRawBytes(d, sent);
1700
 
      }
1701
 
 
1702
 
      to_sent -= sent;
1703
 
      _pos += sent;
1704
 
      d += sent;
1705
 
   }
1706
 
 
1707
 
   return data.size() - to_sent;
1708
 
}
1709
 
 
1710
 
 
1711
 
bool NSPluginStreamBase::pump()
1712
 
{
1713
 
    //kdDebug(1431) << "queue pos " << _queuePos << ", size " << _queue.size() << endl;
1714
 
 
1715
 
    inform();
1716
 
 
1717
 
    if ( _queuePos<_queue.size() ) {
1718
 
        unsigned newPos;
1719
 
 
1720
 
        // handle AS_FILE_ONLY streams
1721
 
        if ( _onlyAsFile ) {
1722
 
            if (_tempFile) {
1723
 
                _tempFile->dataStream()->writeRawBytes( _queue, _queue.size() );
1724
 
            }
1725
 
            newPos = _queuePos+_queue.size();
1726
 
        } else {
1727
 
            // normal streams
1728
 
            newPos = process( _queue, _queuePos );
1729
 
        }
1730
 
 
1731
 
        // count tries
1732
 
        if ( newPos==_queuePos )
1733
 
            _tries++;
1734
 
        else
1735
 
            _tries = 0;
1736
 
 
1737
 
        _queuePos = newPos;
1738
 
    }
1739
 
 
1740
 
    // return true if queue finished
1741
 
    return _queuePos>=_queue.size();
1742
 
}
1743
 
 
1744
 
 
1745
 
void NSPluginStreamBase::queue( const QByteArray &data )
1746
 
{
1747
 
    _queue = data;
1748
 
    _queue.detach();
1749
 
    _queuePos = 0;
1750
 
    _tries = 0;
1751
 
 
1752
 
/*
1753
 
    kdDebug(1431) << "new queue size=" << data.size()
1754
 
                  << " data=" << (void*)data.data() 
1755
 
                  << " queue=" << (void*)_queue.data() << " qsize="
1756
 
                  << _queue.size() << endl;
1757
 
*/
1758
 
}
1759
 
 
1760
 
 
1761
 
void NSPluginStreamBase::finish( bool err )
1762
 
{
1763
 
    kdDebug(1431) << "finish error=" << err << endl;
1764
 
 
1765
 
    _queue.resize( 0 );
1766
 
    _pos = 0;
1767
 
    _queuePos = 0;
1768
 
 
1769
 
    inform();
1770
 
 
1771
 
    if ( !err ) {
1772
 
        if ( _tempFile ) {
1773
 
            _tempFile->close();
1774
 
            _instance->addTempFile( _tempFile );
1775
 
            _tempFile = 0;
1776
 
        }
1777
 
 
1778
 
        if ( !_fileURL.isEmpty() ) {
1779
 
            kdDebug() << "stream as file " << _fileURL << endl;
1780
 
             _instance->NPStreamAsFile( _stream, _fileURL.ascii() );
1781
 
        }
1782
 
 
1783
 
        _instance->NPDestroyStream( _stream, NPRES_DONE );
1784
 
        if (_notifyData || _forceNotify)
1785
 
            _instance->NPURLNotify( _url.url(), NPRES_DONE, _notifyData );
1786
 
    } else {
1787
 
        // close temp file
1788
 
        if ( _tempFile ) {
1789
 
            _tempFile->close();
1790
 
        }
1791
 
 
1792
 
        // destroy stream
1793
 
        _instance->NPDestroyStream( _stream, NPRES_NETWORK_ERR );
1794
 
        if (_notifyData || _forceNotify)
1795
 
            _instance->NPURLNotify( _url.url(), NPRES_NETWORK_ERR, _notifyData );
1796
 
    }
1797
 
 
1798
 
    // delete stream
1799
 
    if (_stream && _stream->url)
1800
 
        free(const_cast<char *>(_stream->url));
1801
 
    delete _stream;
1802
 
    _stream = 0;
1803
 
 
1804
 
    // destroy NSPluginStream object
1805
 
    emit finished( this );
1806
 
}
1807
 
 
1808
 
 
1809
 
/****************************************************************************/
1810
 
 
1811
 
NSPluginBufStream::NSPluginBufStream( class NSPluginInstance *instance )
1812
 
    : NSPluginStreamBase( instance )
1813
 
{
1814
 
    _timer = new QTimer( this );
1815
 
    connect( _timer, SIGNAL(timeout()), this, SLOT(timer()) );
1816
 
}
1817
 
 
1818
 
 
1819
 
NSPluginBufStream::~NSPluginBufStream()
1820
 
{
1821
 
 
1822
 
}
1823
 
 
1824
 
 
1825
 
bool NSPluginBufStream::get( const QString& url, const QString& mimeType,
1826
 
                             const QByteArray &buf, void *notifyData,
1827
 
                             bool singleShot )
1828
 
{
1829
 
    _singleShot = singleShot;
1830
 
    if ( create( url, mimeType, notifyData ) ) {
1831
 
        queue( buf );
1832
 
        _timer->start( 100, true );
1833
 
    }
1834
 
 
1835
 
    return false;
1836
 
}
1837
 
 
1838
 
 
1839
 
void NSPluginBufStream::timer()
1840
 
{
1841
 
    bool finished = pump();
1842
 
    if ( _singleShot )
1843
 
        finish( false );
1844
 
    else {
1845
 
 
1846
 
        if ( !finished && tries()<=8 )
1847
 
            _timer->start( 100, true );
1848
 
        else
1849
 
            finish( error() || tries()>8 );
1850
 
    }
1851
 
}
1852
 
 
1853
 
 
1854
 
 
1855
 
/****************************************************************************/
1856
 
 
1857
 
NSPluginStream::NSPluginStream( NSPluginInstance *instance )
1858
 
    : NSPluginStreamBase( instance ), _job(0)
1859
 
{
1860
 
   _resumeTimer = new QTimer( this );
1861
 
   connect(_resumeTimer, SIGNAL(timeout()), this, SLOT(resume()));
1862
 
}
1863
 
 
1864
 
 
1865
 
NSPluginStream::~NSPluginStream()
1866
 
{
1867
 
    if ( _job )
1868
 
        _job->kill( true );
1869
 
}
1870
 
 
1871
 
 
1872
 
bool NSPluginStream::get( const QString& url, const QString& mimeType,
1873
 
                          void *notify, bool reload )
1874
 
{
1875
 
    // create new stream
1876
 
    if ( create( url, mimeType, notify ) ) {
1877
 
        // start the kio job
1878
 
        _job = KIO::get(KURL( url ), false, false);
1879
 
        _job->addMetaData("errorPage", "false");
1880
 
        _job->addMetaData("AllowCompressedPage", "false");
1881
 
        if (reload) {
1882
 
            _job->addMetaData("cache", "reload");
1883
 
        }
1884
 
        connect(_job, SIGNAL(data(KIO::Job *, const QByteArray &)),
1885
 
                SLOT(data(KIO::Job *, const QByteArray &)));
1886
 
        connect(_job, SIGNAL(result(KIO::Job *)), SLOT(result(KIO::Job *)));
1887
 
        connect(_job, SIGNAL(totalSize(KIO::Job *, KIO::filesize_t )),
1888
 
                SLOT(totalSize(KIO::Job *, KIO::filesize_t)));
1889
 
        connect(_job, SIGNAL(mimetype(KIO::Job *, const QString &)),
1890
 
                SLOT(mimetype(KIO::Job *, const QString &)));
1891
 
        connect(_job, SIGNAL(redirection(KIO::Job *, const KURL&)),
1892
 
                SLOT(redirection(KIO::Job *, const KURL&)));
1893
 
    }
1894
 
 
1895
 
    return false;
1896
 
}
1897
 
 
1898
 
 
1899
 
bool NSPluginStream::post( const QString& url, const QByteArray& data, 
1900
 
           const QString& mimeType, void *notify, const KParts::URLArgs& args )
1901
 
{
1902
 
    // create new stream
1903
 
    if ( create( url, mimeType, notify ) ) {
1904
 
        // start the kio job
1905
 
        _job = KIO::http_post(KURL( url ), data, false);
1906
 
        _job->addMetaData("content-type", args.contentType());
1907
 
        _job->addMetaData("errorPage", "false");
1908
 
        _job->addMetaData("AllowCompressedPage", "false");
1909
 
        connect(_job, SIGNAL(data(KIO::Job *, const QByteArray &)),
1910
 
                SLOT(data(KIO::Job *, const QByteArray &)));
1911
 
        connect(_job, SIGNAL(result(KIO::Job *)), SLOT(result(KIO::Job *)));
1912
 
        connect(_job, SIGNAL(totalSize(KIO::Job *, KIO::filesize_t )),
1913
 
                SLOT(totalSize(KIO::Job *, KIO::filesize_t)));
1914
 
        connect(_job, SIGNAL(mimetype(KIO::Job *, const QString &)),
1915
 
                SLOT(mimetype(KIO::Job *, const QString &)));
1916
 
        connect(_job, SIGNAL(redirection(KIO::Job *, const KURL&)),
1917
 
                SLOT(redirection(KIO::Job *, const KURL&)));
1918
 
    }
1919
 
 
1920
 
    return false;
1921
 
}
1922
 
 
1923
 
 
1924
 
void NSPluginStream::data(KIO::Job * job, const QByteArray &data)
1925
 
{
1926
 
    //kdDebug(1431) << "NSPluginStream::data - job=" << (void*)job << " data size=" << data.size() << endl;
1927
 
    queue( data );
1928
 
    if ( !pump() ) {
1929
 
        _job->suspend();
1930
 
        _resumeTimer->start( 100, TRUE );
1931
 
    }
1932
 
}
1933
 
 
1934
 
void NSPluginStream::redirection(KIO::Job * /*job*/, const KURL& url)
1935
 
{
1936
 
    updateURL( url );
1937
 
}
1938
 
 
1939
 
void NSPluginStream::totalSize(KIO::Job * job, KIO::filesize_t size)
1940
 
{
1941
 
    kdDebug(1431) << "NSPluginStream::totalSize - job=" << (void*)job << " size=" << KIO::number(size) << endl;
1942
 
    _stream->end = size;
1943
 
}
1944
 
 
1945
 
void NSPluginStream::mimetype(KIO::Job * job, const QString &mimeType)
1946
 
{
1947
 
    kdDebug(1431) << "NSPluginStream::QByteArray - job=" << (void*)job << " mimeType=" << mimeType << endl;
1948
 
    _mimeType = mimeType;
1949
 
}
1950
 
 
1951
 
 
1952
 
 
1953
 
 
1954
 
void NSPluginStream::resume()
1955
 
{
1956
 
   if ( error() || tries()>8 ) {
1957
 
       _job->kill( true );
1958
 
       finish( true );
1959
 
       return;
1960
 
   }
1961
 
 
1962
 
   if ( pump() ) {
1963
 
      kdDebug(1431) << "resume job" << endl;
1964
 
      _job->resume();
1965
 
   } else {
1966
 
       kdDebug(1431) << "restart timer" << endl;
1967
 
       _resumeTimer->start( 100, TRUE );
1968
 
   }
1969
 
}
1970
 
 
1971
 
 
1972
 
void NSPluginStream::result(KIO::Job *job)
1973
 
{
1974
 
   int err = job->error();
1975
 
   _job = 0;
1976
 
   finish( err!=0 || error() );
1977
 
}
1978
 
 
1979
 
#include "nsplugin.moc"
1980
 
// vim: ts=4 sw=4 et