~ubuntu-branches/ubuntu/lucid/icedtea-web/lucid-updates

« back to all changes in this revision

Viewing changes to .pc/icedtea-web-CVE-2012-3423.patch/plugin/icedteanp/IcedTeaPluginUtils.cc

  • Committer: Package Import Robot
  • Author(s): Jamie Strandboge, Matthias Klose, Jamie Strandboge
  • Date: 2013-04-17 17:57:13 UTC
  • mfrom: (1.1.20) (19.1.25 precise-security)
  • Revision ID: package-import@ubuntu.com-20130417175713-shac0w2uah1i3i77
Tags: 1.2.3-0ubuntu0.10.04.1
[ Matthias Klose ]
* IcedTea-Web 1.2.3 release.
* Security Updates:
  - CVE-2013-1927: fixed gifar vulnerability.
  - CVE-2013-1926: Class-loader incorrectly shared for applets with same
    relative-path.
* Common:
  - PR1161: X509VariableTrustManager does not work correctly with OpenJDK7.
* NetX:
  - PR580: http://www.horaoficial.cl/ loads improperly.
* Plugin:
  - PR1157: Applets can hang browser after fatal exception.

[ Jamie Strandboge ]
* debian/rules: generate icedtea-plugin meta package
* debian/control.in: update icedtea-netx replace/conflicts to avoid
  javaws conflict with openjdk-6-jre
* debian/icedtea-netx.postinst.in: skip update-alternatives on
  openjdk-7 binaries if they don't exist
* Regenerate the control file.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* IcedTeaPluginUtils.cc
2
 
 
3
 
   Copyright (C) 2009, 2010  Red Hat
4
 
 
5
 
This file is part of IcedTea.
6
 
 
7
 
IcedTea is free software; you can redistribute it and/or modify
8
 
it under the terms of the GNU General Public License as published by
9
 
the Free Software Foundation; either version 2, or (at your option)
10
 
any later version.
11
 
 
12
 
IcedTea is distributed in the hope that it will be useful, but
13
 
WITHOUT ANY WARRANTY; without even the implied warranty of
14
 
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15
 
General Public License for more details.
16
 
 
17
 
You should have received a copy of the GNU General Public License
18
 
along with IcedTea; see the file COPYING.  If not, write to the
19
 
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
20
 
02110-1301 USA.
21
 
 
22
 
Linking this library statically or dynamically with other modules is
23
 
making a combined work based on this library.  Thus, the terms and
24
 
conditions of the GNU General Public License cover the whole
25
 
combination.
26
 
 
27
 
As a special exception, the copyright holders of this library give you
28
 
permission to link this library with independent modules to produce an
29
 
executable, regardless of the license terms of these independent
30
 
modules, and to copy and distribute the resulting executable under
31
 
terms of your choice, provided that you also meet, for each linked
32
 
independent module, the terms and conditions of the license of that
33
 
module.  An independent module is a module which is not derived from
34
 
or based on this library.  If you modify this library, you may extend
35
 
this exception to your version of the library, but you are not
36
 
obligated to do so.  If you do not wish to do so, delete this
37
 
exception statement from your version. */
38
 
 
39
 
#include "IcedTeaNPPlugin.h"
40
 
#include "IcedTeaScriptablePluginObject.h"
41
 
#include "IcedTeaPluginUtils.h"
42
 
 
43
 
/**
44
 
 * Misc. utility functions used by the plugin
45
 
 */
46
 
 
47
 
/***********************************************
48
 
 * Begin IcedTeaPluginUtilities implementation *
49
 
************************************************/
50
 
 
51
 
// Initialize static variables
52
 
int IcedTeaPluginUtilities::reference = -1;
53
 
pthread_mutex_t IcedTeaPluginUtilities::reference_mutex = PTHREAD_MUTEX_INITIALIZER;
54
 
std::map<void*, NPP>* IcedTeaPluginUtilities::instance_map = new std::map<void*, NPP>();
55
 
std::map<std::string, NPObject*>* IcedTeaPluginUtilities::object_map = new std::map<std::string, NPObject*>();
56
 
 
57
 
/* Plugin async call queue */
58
 
static std::vector< PluginThreadCall* >* pendingPluginThreadRequests = new std::vector< PluginThreadCall* >();
59
 
 
60
 
/**
61
 
 * Given a context number, constructs a message prefix to send to Java
62
 
 *
63
 
 * @param context The context of the request
64
 
 * @return The string prefix (allocated on heap)
65
 
 */
66
 
 
67
 
void
68
 
IcedTeaPluginUtilities::constructMessagePrefix(int context, std::string *result)
69
 
{
70
 
        std::string context_str = std::string();
71
 
 
72
 
        itoa(context, &context_str);
73
 
 
74
 
        result->append("context ");
75
 
        result->append(context_str);
76
 
        result->append(" reference -1");
77
 
 
78
 
}
79
 
 
80
 
/**
81
 
 * Given a context number, and reference number, constructs a message prefix to
82
 
 * send to Java
83
 
 *
84
 
 * @param context The context of the request
85
 
 * @param rerefence The reference number of the request
86
 
 * @param result The message
87
 
 */
88
 
 
89
 
void
90
 
IcedTeaPluginUtilities::constructMessagePrefix(int context, int reference, std::string* result)
91
 
{
92
 
    // Until security is implemented, use file:// source for _everything_
93
 
 
94
 
        std::string context_str = std::string();
95
 
        std::string reference_str = std::string();
96
 
 
97
 
        itoa(context, &context_str);
98
 
        itoa(reference, &reference_str);
99
 
 
100
 
        *result += "context ";
101
 
        result->append(context_str);
102
 
        *result += " reference ";
103
 
        result->append(reference_str);
104
 
}
105
 
 
106
 
/**
107
 
 * Given a context number, reference number, and source location, constructs
108
 
 * a message prefix to send to Java
109
 
 *
110
 
 * @param context The context of the request
111
 
 * @param rerefence The reference number of the request
112
 
 * @param address The address for the script that made the request
113
 
 * @param result The message
114
 
 */
115
 
 
116
 
void
117
 
IcedTeaPluginUtilities::constructMessagePrefix(int context, int reference,
118
 
                                                       std::string address,
119
 
                                                       std::string* result)
120
 
{
121
 
        std::string context_str = std::string();
122
 
        std::string reference_str = std::string();
123
 
 
124
 
        itoa(context, &context_str);
125
 
        itoa(reference, &reference_str);
126
 
 
127
 
        *result += "context ";
128
 
        result->append(context_str);
129
 
        *result += " reference ";
130
 
        result->append(reference_str);
131
 
 
132
 
        if (address.length() > 0)
133
 
        {
134
 
            *result += " src ";
135
 
        result->append(address);
136
 
        }
137
 
}
138
 
 
139
 
/**
140
 
 * Returns a string representation of a void pointer
141
 
 *
142
 
 * @param id The pointer
143
 
 * @param result The string representation
144
 
 */
145
 
 
146
 
void
147
 
IcedTeaPluginUtilities::JSIDToString(void* id, std::string* result)
148
 
{
149
 
 
150
 
        char* id_str = (char*) malloc(sizeof(char)*20); // max = long long = 8446744073709551615 == 19 chars
151
 
 
152
 
        if (sizeof(void*) == sizeof(long long))
153
 
        {
154
 
                sprintf(id_str, "%llu", id);
155
 
        }
156
 
        else
157
 
        {
158
 
                sprintf(id_str, "%lu", id); // else use long
159
 
        }
160
 
 
161
 
        result->append(id_str);
162
 
 
163
 
        PLUGIN_DEBUG("Converting pointer %p to %s\n", id, id_str);
164
 
        free(id_str);
165
 
}
166
 
 
167
 
/**
168
 
 * Returns a void pointer from a string representation
169
 
 *
170
 
 * @param id_str The string representation
171
 
 * @return The pointer
172
 
 */
173
 
 
174
 
void*
175
 
IcedTeaPluginUtilities::stringToJSID(std::string id_str)
176
 
{
177
 
        void* ptr;
178
 
        if (sizeof(void*) == sizeof(long long))
179
 
        {
180
 
                PLUGIN_DEBUG("Casting (long long) \"%s\" -- %llu\n", id_str.c_str(), strtoull(id_str.c_str(), NULL, 0));
181
 
                ptr = reinterpret_cast <void*> ((unsigned long long) strtoull(id_str.c_str(), NULL, 0));
182
 
        } else
183
 
        {
184
 
                PLUGIN_DEBUG("Casting (long) \"%s\" -- %lu\n", id_str.c_str(), strtoul(id_str.c_str(), NULL, 0));
185
 
                ptr = reinterpret_cast <void*> ((unsigned long)  strtoul(id_str.c_str(), NULL, 0));
186
 
        }
187
 
 
188
 
        PLUGIN_DEBUG("Casted: %p\n", ptr);
189
 
 
190
 
        return ptr;
191
 
}
192
 
 
193
 
/**
194
 
 * Returns a void pointer from a string representation
195
 
 *
196
 
 * @param id_str The pointer to the string representation
197
 
 * @return The pointer
198
 
 */
199
 
 
200
 
void*
201
 
IcedTeaPluginUtilities::stringToJSID(std::string* id_str)
202
 
{
203
 
    void* ptr;
204
 
    if (sizeof(void*) == sizeof(long long))
205
 
    {
206
 
        PLUGIN_DEBUG("Casting (long long) \"%s\" -- %llu\n", id_str->c_str(), strtoull(id_str->c_str(), NULL, 0));
207
 
        ptr = reinterpret_cast <void*> ((unsigned long long) strtoull(id_str->c_str(), NULL, 0));
208
 
    } else
209
 
    {
210
 
        PLUGIN_DEBUG("Casting (long) \"%s\" -- %lu\n", id_str->c_str(), strtoul(id_str->c_str(), NULL, 0));
211
 
        ptr = reinterpret_cast <void*> ((unsigned long)  strtoul(id_str->c_str(), NULL, 0));
212
 
    }
213
 
 
214
 
    PLUGIN_DEBUG("Casted: %p\n", ptr);
215
 
 
216
 
    return ptr;
217
 
}
218
 
 
219
 
/**
220
 
 * Increments the global reference number and returns it.
221
 
 *
222
 
 * This function is thread-safe.
223
 
 */
224
 
int
225
 
IcedTeaPluginUtilities::getReference()
226
 
{
227
 
        pthread_mutex_lock(&reference_mutex);
228
 
 
229
 
        // If we are nearing the max, reset
230
 
        if (reference < -0x7FFFFFFF + 10) {
231
 
            reference = -1;
232
 
        }
233
 
 
234
 
        reference--;
235
 
        pthread_mutex_unlock(&reference_mutex);
236
 
 
237
 
        return reference;
238
 
}
239
 
 
240
 
/**
241
 
 * Decrements the global reference number.
242
 
 *
243
 
 * This function is thread-safe.
244
 
 */
245
 
void
246
 
IcedTeaPluginUtilities::releaseReference()
247
 
{
248
 
    // do nothing for now
249
 
}
250
 
 
251
 
/**
252
 
 * Converts integer to char*
253
 
 *
254
 
 * @param i The integer to convert to ascii
255
 
 * @param result The resulting string
256
 
 */
257
 
void
258
 
IcedTeaPluginUtilities::itoa(int i, std::string* result)
259
 
{
260
 
        // largest possible integer is 10 digits long
261
 
        char* int_str = (char*) malloc(sizeof(char)*11);
262
 
        sprintf(int_str, "%d", i);
263
 
        result->append(int_str);
264
 
 
265
 
        free(int_str);
266
 
}
267
 
 
268
 
/**
269
 
 * Frees memory from a string* vector
270
 
 *
271
 
 * The vector deconstructor will only delete string pointers upon being
272
 
 * called. This function frees the associated string memory as well.
273
 
 *
274
 
 * @param v The vector whose strings are to be freed
275
 
 */
276
 
void
277
 
IcedTeaPluginUtilities::freeStringPtrVector(std::vector<std::string*>* v)
278
 
{
279
 
        if (v)
280
 
        {
281
 
                for (int i=0; i < v->size(); i++) {
282
 
                        delete v->at(i);
283
 
                }
284
 
 
285
 
                delete v;
286
 
        }
287
 
 
288
 
}
289
 
 
290
 
/**
291
 
 * Given a string, splits it on the given delimiters.
292
 
 *
293
 
 * @param str The string to split
294
 
 * @param The delimiters to split on
295
 
 * @return A string vector containing the aplit components
296
 
 */
297
 
 
298
 
std::vector<std::string*>*
299
 
IcedTeaPluginUtilities::strSplit(const char* str, const char* delim)
300
 
{
301
 
        std::vector<std::string*>* v = new std::vector<std::string*>();
302
 
        v->reserve(strlen(str)/2);
303
 
        char* copy;
304
 
 
305
 
        // Tokening is done on a copy
306
 
        copy = (char*) malloc (sizeof(char)*strlen(str) + 1);
307
 
        strcpy(copy, str);
308
 
 
309
 
        char* tok_ptr;
310
 
        tok_ptr = strtok (copy, delim);
311
 
 
312
 
        while (tok_ptr != NULL)
313
 
        {
314
 
            // Allocation on heap since caller has no way to knowing how much will
315
 
            // be needed. Make sure caller cleans up!
316
 
                std::string* s = new std::string();
317
 
                s->append(tok_ptr);
318
 
                v->push_back(s);
319
 
                tok_ptr = strtok (NULL, " ");
320
 
        }
321
 
 
322
 
        return v;
323
 
}
324
 
 
325
 
/**
326
 
 * Given a unicode byte array, converts it to a UTF8 string
327
 
 *
328
 
 * The actual contents in the array may be surrounded by other data.
329
 
 *
330
 
 * e.g. with length 5, begin = 3,
331
 
 * unicode_byte_array = "37 28 5 48 45 4c 4c 4f 9e 47":
332
 
 *
333
 
 * We'd start at 3 i.e. "48" and go on for 5 i.e. upto and including "4f".
334
 
 * So we convert "48 45 4c 4c 4f" which is "hello"
335
 
 *
336
 
 * @param length The length of the string
337
 
 * @param begin Where in the array to begin conversion
338
 
 * @param result_unicode_str The return variable in which the
339
 
 *        converted string is placed
340
 
 */
341
 
 
342
 
void
343
 
IcedTeaPluginUtilities::getUTF8String(int length, int begin, std::vector<std::string*>* unicode_byte_array, std::string* result_unicode_str)
344
 
{
345
 
        result_unicode_str->clear();
346
 
        result_unicode_str->reserve(unicode_byte_array->size()/2);
347
 
        for (int i = begin; i < begin+length; i++)
348
 
            result_unicode_str->push_back((char) strtol(unicode_byte_array->at(i)->c_str(), NULL, 16));
349
 
 
350
 
        PLUGIN_DEBUG("Converted UTF-8 string: %s. Length=%d\n", result_unicode_str->c_str(), result_unicode_str->length());
351
 
}
352
 
 
353
 
/**
354
 
 * Given a UTF8 string, converts it to a space delimited string of hex characters
355
 
 *
356
 
 * The first element in the return array is the length of the string
357
 
 *
358
 
 * e.g. "hello" would convert to: "5 48 45 4c 4c 4f"
359
 
 *
360
 
 * @param str The string to convert
361
 
 * @param urt_str The result
362
 
 */
363
 
 
364
 
void
365
 
IcedTeaPluginUtilities::convertStringToUTF8(std::string* str, std::string* utf_str)
366
 
{
367
 
        std::ostringstream ostream;
368
 
 
369
 
        std::string length = std::string();
370
 
        itoa(str->length(), &length);
371
 
 
372
 
        ostream << length;
373
 
 
374
 
        // UTF-8 characters are 4-bytes max + space + '\0'
375
 
        char* hex_value = (char*) malloc(sizeof(char)*10);
376
 
 
377
 
        for (int i = 0; i < str->length(); i++)
378
 
        {
379
 
                sprintf(hex_value, " %hx", str->at(i));
380
 
                ostream << hex_value;
381
 
        }
382
 
 
383
 
        utf_str->clear();
384
 
        *utf_str = ostream.str();
385
 
 
386
 
        free(hex_value);
387
 
        PLUGIN_DEBUG("Converted %s to UTF-8 string %s\n", str->c_str(), utf_str->c_str());
388
 
}
389
 
 
390
 
/**
391
 
 * Given a unicode byte array, converts it to a UTF16LE/UCS-2 string
392
 
 *
393
 
 * This works in a manner similar to getUTF8String, except that it reads 2
394
 
 * slots for each byte.
395
 
 *
396
 
 * @param length The length of the string
397
 
 * @param begin Where in the array to begin conversion
398
 
 * @param result_unicode_str The return variable in which the
399
 
 *        converted string is placed
400
 
 */
401
 
void
402
 
IcedTeaPluginUtilities::getUTF16LEString(int length, int begin, std::vector<std::string*>* unicode_byte_array, std::wstring* result_unicode_str)
403
 
{
404
 
 
405
 
        wchar_t c;
406
 
 
407
 
        if (plugin_debug) printf("Converted UTF-16LE string: ");
408
 
 
409
 
        result_unicode_str->clear();
410
 
        for (int i = begin; i < begin+length; i+=2)
411
 
        {
412
 
                int low = strtol(unicode_byte_array->at(i)->c_str(), NULL, 16);
413
 
                int high = strtol(unicode_byte_array->at(i+1)->c_str(), NULL, 16);
414
 
 
415
 
        c = ((high << 8) | low);
416
 
 
417
 
        if ((c >= 'a' && c <= 'z') ||
418
 
                (c >= 'A' && c <= 'Z') ||
419
 
                (c >= '0' && c <= '9'))
420
 
        {
421
 
                if (plugin_debug) printf("%c", c);
422
 
        }
423
 
 
424
 
        result_unicode_str->push_back(c);
425
 
        }
426
 
 
427
 
        // not routing via debug print macros due to wide-string issues
428
 
        if (plugin_debug) printf(". Length=%d\n", result_unicode_str->length());
429
 
}
430
 
 
431
 
/*
432
 
 * Prints the given string vector (if debug is true)
433
 
 *
434
 
 * @param prefix The prefix to print before printing the vector contents
435
 
 * @param cv The string vector whose contents are to be printed
436
 
 */
437
 
void
438
 
IcedTeaPluginUtilities::printStringVector(const char* prefix, std::vector<std::string>* str_vector)
439
 
{
440
 
 
441
 
        // This is a CPU intensive function. Run only if debugging
442
 
        if (!plugin_debug)
443
 
            return;
444
 
 
445
 
        std::string* str = new std::string();
446
 
        *str += "{ ";
447
 
        for (int i=0; i < str_vector->size(); i++)
448
 
        {
449
 
                *str += str_vector->at(i);
450
 
 
451
 
                if (i != str_vector->size() - 1)
452
 
                        *str += ", ";
453
 
        }
454
 
 
455
 
        *str += " }";
456
 
 
457
 
        PLUGIN_DEBUG("%s %s\n", prefix, str->c_str());
458
 
 
459
 
        delete str;
460
 
}
461
 
 
462
 
const gchar*
463
 
IcedTeaPluginUtilities::getSourceFromInstance(NPP instance)
464
 
{
465
 
    // At the moment, src cannot be securely fetched via NPAPI
466
 
    // See:
467
 
    // http://www.mail-archive.com/chromium-dev@googlegroups.com/msg04872.html
468
 
 
469
 
    // Since we use the insecure window.location.href attribute to compute
470
 
    // source, we cannot use it to make security decisions. Therefore,
471
 
    // instance associated source will always return empty
472
 
 
473
 
    //ITNPPluginData* data = (ITNPPluginData*) instance->pdata;
474
 
    //return (data->source) ? data->source : "";
475
 
 
476
 
    return "http://null.null";
477
 
}
478
 
 
479
 
/**
480
 
 * Stores a window pointer <-> instance mapping
481
 
 *
482
 
 * @param member_ptr The pointer key
483
 
 * @param instance The instance to associate with this pointer
484
 
 */
485
 
 
486
 
void
487
 
IcedTeaPluginUtilities::storeInstanceID(void* member_ptr, NPP instance)
488
 
{
489
 
    PLUGIN_DEBUG("Storing instance %p with key %p\n", instance, member_ptr);
490
 
    instance_map->insert(std::make_pair(member_ptr, instance));
491
 
}
492
 
 
493
 
/**
494
 
 * Removes a window pointer <-> instance mapping
495
 
 *
496
 
 * @param member_ptr The key to remove
497
 
 */
498
 
 
499
 
void
500
 
IcedTeaPluginUtilities::removeInstanceID(void* member_ptr)
501
 
{
502
 
    PLUGIN_DEBUG("Removing key %p from instance map\n", member_ptr);
503
 
    instance_map->erase(member_ptr);
504
 
}
505
 
 
506
 
/**
507
 
 * Removes all mappings to a given instance, and all associated objects
508
 
 */
509
 
void
510
 
IcedTeaPluginUtilities::invalidateInstance(NPP instance)
511
 
{
512
 
    PLUGIN_DEBUG("Invalidating instance %p\n", instance);
513
 
 
514
 
    std::map<void*,NPP>::iterator iterator;
515
 
 
516
 
    for (iterator = instance_map->begin(); iterator != instance_map->end(); )
517
 
    {
518
 
        if ((*iterator).second == instance)
519
 
        {
520
 
            instance_map->erase(iterator++);
521
 
        }
522
 
        else
523
 
        {
524
 
            ++iterator;
525
 
        }
526
 
    }
527
 
}
528
 
 
529
 
/**
530
 
 * Given the window pointer, returns the instance associated with it
531
 
 *
532
 
 * @param member_ptr The pointer key
533
 
 * @return The associated instance
534
 
 */
535
 
 
536
 
NPP
537
 
IcedTeaPluginUtilities::getInstanceFromMemberPtr(void* member_ptr)
538
 
{
539
 
 
540
 
    NPP instance = NULL;
541
 
    PLUGIN_DEBUG("getInstanceFromMemberPtr looking for %p\n", member_ptr);
542
 
 
543
 
    std::map<void*, NPP>::iterator iterator = instance_map->find(member_ptr);
544
 
 
545
 
    if (iterator != instance_map->end())
546
 
    {
547
 
        instance = instance_map->find(member_ptr)->second;
548
 
        PLUGIN_DEBUG("getInstanceFromMemberPtr found %p. Instance = %p\n", member_ptr, instance);
549
 
    }
550
 
 
551
 
    return instance;
552
 
}
553
 
 
554
 
/**
555
 
 * Given a java id key ('classid:instanceid'), returns the associated valid NPObject, if any
556
 
 *
557
 
 * @param key the key
558
 
 * @return The associated active NPObject, NULL otherwise
559
 
 */
560
 
 
561
 
NPObject*
562
 
IcedTeaPluginUtilities::getNPObjectFromJavaKey(std::string key)
563
 
{
564
 
 
565
 
    NPObject* object = NULL;
566
 
    PLUGIN_DEBUG("getNPObjectFromJavaKey looking for %s\n", key.c_str());
567
 
 
568
 
    std::map<std::string, NPObject*>::iterator iterator = object_map->find(key);
569
 
 
570
 
    if (iterator != object_map->end())
571
 
    {
572
 
        NPObject* mapped_object = object_map->find(key)->second;
573
 
 
574
 
        if (getInstanceFromMemberPtr(mapped_object) != NULL)
575
 
        {
576
 
            object = mapped_object;
577
 
            PLUGIN_DEBUG("getNPObjectFromJavaKey found %s. NPObject = %p\n", key.c_str(), object);
578
 
        }
579
 
    }
580
 
 
581
 
    return object;
582
 
}
583
 
 
584
 
/**
585
 
 * Stores a java id key <-> NPObject mapping
586
 
 *
587
 
 * @param key The Java ID Key
588
 
 * @param object The object to map to
589
 
 */
590
 
 
591
 
void
592
 
IcedTeaPluginUtilities::storeObjectMapping(std::string key, NPObject* object)
593
 
{
594
 
    PLUGIN_DEBUG("Storing object %p with key %s\n", object, key.c_str());
595
 
    object_map->insert(std::make_pair(key, object));
596
 
}
597
 
 
598
 
/**
599
 
 * Removes a java id key <-> NPObject mapping
600
 
 *
601
 
 * @param key The key to remove
602
 
 */
603
 
 
604
 
void
605
 
IcedTeaPluginUtilities::removeObjectMapping(std::string key)
606
 
{
607
 
    PLUGIN_DEBUG("Removing key %s from object map\n", key.c_str());
608
 
    object_map->erase(key);
609
 
}
610
 
 
611
 
/*
612
 
 * Similar to printStringVector, but takes a vector of string pointers instead
613
 
 *
614
 
 * @param prefix The prefix to print before printing the vector contents
615
 
 * @param cv The string* vector whose contents are to be printed
616
 
 */
617
 
 
618
 
void
619
 
IcedTeaPluginUtilities::printStringPtrVector(const char* prefix, std::vector<std::string*>* str_ptr_vector)
620
 
{
621
 
        // This is a CPU intensive function. Run only if debugging
622
 
        if (!plugin_debug)
623
 
            return;
624
 
 
625
 
        std::string* str = new std::string();
626
 
        *str += "{ ";
627
 
        for (int i=0; i < str_ptr_vector->size(); i++)
628
 
        {
629
 
                *str += *(str_ptr_vector->at(i));
630
 
 
631
 
                if (i != str_ptr_vector->size() - 1)
632
 
                        *str += ", ";
633
 
        }
634
 
 
635
 
        *str += " }";
636
 
 
637
 
        PLUGIN_DEBUG("%s %s\n", prefix, str->c_str());
638
 
 
639
 
        delete str;
640
 
}
641
 
 
642
 
void
643
 
IcedTeaPluginUtilities::printNPVariant(NPVariant variant)
644
 
{
645
 
    // This is a CPU intensive function. Run only if debugging
646
 
    if (!plugin_debug)
647
 
        return;
648
 
 
649
 
    if (NPVARIANT_IS_VOID(variant))
650
 
    {
651
 
        PLUGIN_DEBUG("VOID %d\n", variant);
652
 
    }
653
 
    else if (NPVARIANT_IS_NULL(variant))
654
 
    {
655
 
        PLUGIN_DEBUG("NULL\n", variant);
656
 
    }
657
 
    else if (NPVARIANT_IS_BOOLEAN(variant))
658
 
    {
659
 
        PLUGIN_DEBUG("BOOL: %d\n", NPVARIANT_TO_BOOLEAN(variant));
660
 
    }
661
 
    else if (NPVARIANT_IS_INT32(variant))
662
 
    {
663
 
        PLUGIN_DEBUG("INT32: %d\n", NPVARIANT_TO_INT32(variant));
664
 
    }
665
 
    else if (NPVARIANT_IS_DOUBLE(variant))
666
 
    {
667
 
        PLUGIN_DEBUG("DOUBLE: %f\n", NPVARIANT_TO_DOUBLE(variant));
668
 
    }
669
 
    else if (NPVARIANT_IS_STRING(variant))
670
 
    {
671
 
#if MOZILLA_VERSION_COLLAPSED < 1090200
672
 
        PLUGIN_DEBUG("STRING: %s\n", NPVARIANT_TO_STRING(variant).utf8characters);
673
 
#else
674
 
        PLUGIN_DEBUG("STRING: %s\n", NPVARIANT_TO_STRING(variant).UTF8Characters);
675
 
#endif
676
 
    }
677
 
    else
678
 
    {
679
 
        PLUGIN_DEBUG("OBJ: %p\n", NPVARIANT_TO_OBJECT(variant));
680
 
    }
681
 
}
682
 
 
683
 
void
684
 
IcedTeaPluginUtilities::NPVariantToString(NPVariant variant, std::string* result)
685
 
{
686
 
        char* str = (char*) malloc(sizeof(char)*32); // enough for everything except string
687
 
 
688
 
    if (NPVARIANT_IS_VOID(variant))
689
 
    {
690
 
        sprintf(str, "%p", variant);
691
 
    }
692
 
    else if (NPVARIANT_IS_NULL(variant))
693
 
    {
694
 
        sprintf(str, "NULL");
695
 
    }
696
 
    else if (NPVARIANT_IS_BOOLEAN(variant))
697
 
    {
698
 
        if (NPVARIANT_TO_BOOLEAN(variant))
699
 
                sprintf(str, "true");
700
 
        else
701
 
                sprintf(str, "false");
702
 
    }
703
 
    else if (NPVARIANT_IS_INT32(variant))
704
 
    {
705
 
        sprintf(str, "%d", NPVARIANT_TO_INT32(variant));
706
 
    }
707
 
    else if (NPVARIANT_IS_DOUBLE(variant))
708
 
    {
709
 
        sprintf(str, "%f", NPVARIANT_TO_DOUBLE(variant));;
710
 
    }
711
 
    else if (NPVARIANT_IS_STRING(variant))
712
 
    {
713
 
        free(str);
714
 
#if MOZILLA_VERSION_COLLAPSED < 1090200
715
 
        str = (char*) malloc(sizeof(char)*NPVARIANT_TO_STRING(variant).utf8length);
716
 
        sprintf(str, "%s", NPVARIANT_TO_STRING(variant).utf8characters);
717
 
#else
718
 
        str = (char*) malloc(sizeof(char)*NPVARIANT_TO_STRING(variant).UTF8Length);
719
 
        sprintf(str, "%s", NPVARIANT_TO_STRING(variant).UTF8Characters);
720
 
#endif
721
 
    }
722
 
    else
723
 
    {
724
 
        sprintf(str, "[Object %p]", variant);
725
 
    }
726
 
 
727
 
    result->append(str);
728
 
    free(str);
729
 
}
730
 
 
731
 
bool
732
 
IcedTeaPluginUtilities::javaResultToNPVariant(NPP instance,
733
 
                                              std::string* java_value,
734
 
                                              NPVariant* variant)
735
 
{
736
 
    JavaRequestProcessor java_request = JavaRequestProcessor();
737
 
    JavaResultData* java_result;
738
 
 
739
 
    if (java_value->find("literalreturn") == 0)
740
 
    {
741
 
        // 'literalreturn ' == 14 to skip
742
 
        std::string value = java_value->substr(14);
743
 
 
744
 
        // VOID/BOOLEAN/NUMBER
745
 
 
746
 
        if (value == "void")
747
 
        {
748
 
            PLUGIN_DEBUG("Method call returned void\n");
749
 
            VOID_TO_NPVARIANT(*variant);
750
 
        } else if (value == "null")
751
 
        {
752
 
            PLUGIN_DEBUG("Method call returned null\n");
753
 
            NULL_TO_NPVARIANT(*variant);
754
 
        }else if (value == "true")
755
 
        {
756
 
            PLUGIN_DEBUG("Method call returned a boolean (true)\n");
757
 
            BOOLEAN_TO_NPVARIANT(true, *variant);
758
 
        } else if (value == "false")
759
 
        {
760
 
            PLUGIN_DEBUG("Method call returned a boolean (false)\n");
761
 
            BOOLEAN_TO_NPVARIANT(false, *variant);
762
 
        } else
763
 
        {
764
 
            double d = strtod(value.c_str(), NULL);
765
 
 
766
 
            // See if it is convertible to int
767
 
            if (value.find(".") != std::string::npos ||
768
 
                d < -(0x7fffffffL - 1L) ||
769
 
                d > 0x7fffffffL)
770
 
            {
771
 
                PLUGIN_DEBUG("Method call returned a double %f\n", d);
772
 
                DOUBLE_TO_NPVARIANT(d, *variant);
773
 
            } else
774
 
            {
775
 
                int32_t i = (int32_t) d;
776
 
                PLUGIN_DEBUG("Method call returned an int %d\n", i);
777
 
                INT32_TO_NPVARIANT(i, *variant);
778
 
            }
779
 
        }
780
 
    } else {
781
 
        // Else this is a complex java object
782
 
 
783
 
        // To keep code a little bit cleaner, we create variables with proper descriptive names
784
 
        std::string return_obj_instance_id = std::string();
785
 
        std::string return_obj_class_id = std::string();
786
 
        std::string return_obj_class_name = std::string();
787
 
        return_obj_instance_id.append(*java_value);
788
 
 
789
 
        // Find out the class name first, because string is a special case
790
 
        java_result = java_request.getClassName(return_obj_instance_id);
791
 
 
792
 
        if (java_result->error_occurred)
793
 
        {
794
 
            return false;
795
 
        }
796
 
 
797
 
        return_obj_class_name.append(*(java_result->return_string));
798
 
 
799
 
        if (return_obj_class_name == "java.lang.String")
800
 
        {
801
 
            // String is a special case as NPVariant can handle it directly
802
 
            java_result = java_request.getString(return_obj_instance_id);
803
 
 
804
 
            if (java_result->error_occurred)
805
 
            {
806
 
                return false;
807
 
            }
808
 
 
809
 
            // needs to be on the heap
810
 
            NPUTF8* return_str = (NPUTF8*) malloc(sizeof(NPUTF8)*java_result->return_string->size() + 1);
811
 
            strcpy(return_str, java_result->return_string->c_str());
812
 
 
813
 
            PLUGIN_DEBUG("Method call returned a string: \"%s\"\n", return_str);
814
 
            STRINGZ_TO_NPVARIANT(return_str, *variant);
815
 
 
816
 
        } else {
817
 
 
818
 
            // Else this is a regular class. Reference the class object so
819
 
            // we can construct an NPObject with it and the instance
820
 
            java_result = java_request.getClassID(return_obj_instance_id);
821
 
 
822
 
            if (java_result->error_occurred)
823
 
            {
824
 
                return false;
825
 
            }
826
 
 
827
 
            return_obj_class_id.append(*(java_result->return_string));
828
 
 
829
 
            NPObject* obj;
830
 
 
831
 
            if (return_obj_class_name.find('[') == 0) // array
832
 
                obj = IcedTeaScriptableJavaPackageObject::get_scriptable_java_object(
833
 
                                instance,
834
 
                                return_obj_class_id, return_obj_instance_id, true);
835
 
            else
836
 
                obj = IcedTeaScriptableJavaPackageObject::get_scriptable_java_object(
837
 
                                                instance,
838
 
                                                return_obj_class_id, return_obj_instance_id, false);
839
 
 
840
 
            OBJECT_TO_NPVARIANT(obj, *variant);
841
 
        }
842
 
    }
843
 
 
844
 
    return true;
845
 
}
846
 
 
847
 
bool
848
 
IcedTeaPluginUtilities::isObjectJSArray(NPP instance, NPObject* object)
849
 
{
850
 
 
851
 
    NPVariant constructor_v = NPVariant();
852
 
    NPIdentifier constructor_id = browser_functions.getstringidentifier("constructor");
853
 
    browser_functions.getproperty(instance, object, constructor_id, &constructor_v);
854
 
    IcedTeaPluginUtilities::printNPVariant(constructor_v);
855
 
 
856
 
    // void constructor => not an array
857
 
    if (NPVARIANT_IS_VOID(constructor_v))
858
 
        return false;
859
 
 
860
 
    NPObject* constructor = NPVARIANT_TO_OBJECT(constructor_v);
861
 
 
862
 
    NPVariant constructor_str;
863
 
    NPIdentifier toString = browser_functions.getstringidentifier("toString");
864
 
    browser_functions.invoke(instance, constructor, toString, NULL, 0, &constructor_str);
865
 
    IcedTeaPluginUtilities::printNPVariant(constructor_str);
866
 
 
867
 
    std::string constructor_name = std::string();
868
 
 
869
 
#if MOZILLA_VERSION_COLLAPSED < 1090200
870
 
    constructor_name.append(NPVARIANT_TO_STRING(constructor_str).utf8characters);
871
 
#else
872
 
    constructor_name.append(NPVARIANT_TO_STRING(constructor_str).UTF8Characters);
873
 
#endif
874
 
 
875
 
    PLUGIN_DEBUG("Constructor for NPObject is %s\n", constructor_name.c_str());
876
 
 
877
 
    return constructor_name.find("function Array") == 0;
878
 
}
879
 
 
880
 
void
881
 
IcedTeaPluginUtilities::decodeURL(const gchar* url, gchar** decoded_url)
882
 
{
883
 
 
884
 
    PLUGIN_DEBUG("GOT URL: %s -- %s\n", url, *decoded_url);
885
 
    int length = strlen(url);
886
 
    for (int i=0; i < length; i++)
887
 
    {
888
 
        if (url[i] == '%' && i < length - 2)
889
 
        {
890
 
            unsigned char code1 = (unsigned char) url[i+1];
891
 
            unsigned char code2 = (unsigned char) url[i+2];
892
 
 
893
 
            if (!IS_VALID_HEX(&code1) || !IS_VALID_HEX(&code2))
894
 
                continue;
895
 
 
896
 
            // Convert hex value to integer
897
 
            int converted1 = HEX_TO_INT(&code1);
898
 
            int converted2 = HEX_TO_INT(&code2);
899
 
 
900
 
            // bitshift 4 to simulate *16
901
 
            int value = (converted1 << 4) + converted2;
902
 
            char decoded = value;
903
 
 
904
 
            strncat(*decoded_url, &decoded, 1);
905
 
 
906
 
            i += 2;
907
 
        } else
908
 
        {
909
 
            strncat(*decoded_url, &url[i], 1);
910
 
        }
911
 
    }
912
 
 
913
 
    PLUGIN_DEBUG("SENDING URL: %s\n", *decoded_url);
914
 
}
915
 
 
916
 
 
917
 
/**
918
 
 * Posts a function for execution on the plug-in thread and wait for result.
919
 
 *
920
 
 * @param instance The NPP instance
921
 
 * @param func The function to post
922
 
 * @param data Arguments to *func
923
 
 */
924
 
void
925
 
IcedTeaPluginUtilities::callAndWaitForResult(NPP instance, void (*func) (void *), AsyncCallThreadData* data)
926
 
{
927
 
 
928
 
    struct timespec t;
929
 
    struct timespec curr_t;
930
 
    clock_gettime(CLOCK_REALTIME, &t);
931
 
    t.tv_sec += REQUESTTIMEOUT; // timeout
932
 
 
933
 
    // post request
934
 
    postPluginThreadAsyncCall(instance, func, data);
935
 
 
936
 
    do
937
 
    {
938
 
        clock_gettime(CLOCK_REALTIME, &curr_t);
939
 
        if (data != NULL && !data->result_ready && (curr_t.tv_sec < t.tv_sec))
940
 
        {
941
 
            usleep(2000);
942
 
        } else
943
 
        {
944
 
            break;
945
 
        }
946
 
    } while (1);
947
 
}
948
 
 
949
 
 
950
 
/**
951
 
 * Posts a request that needs to be handled in a plugin thread.
952
 
 *
953
 
 * @param instance The plugin instance
954
 
 * @param func The function to execute
955
 
 * @param userData The userData for the function to consume/write to
956
 
 * @return if the call was posted successfully
957
 
 */
958
 
 
959
 
bool
960
 
IcedTeaPluginUtilities::postPluginThreadAsyncCall(NPP instance, void (*func) (void *), void* data)
961
 
{
962
 
    if (instance)
963
 
    {
964
 
        PluginThreadCall* call = new PluginThreadCall();
965
 
        call->instance = instance;
966
 
        call->func = func;
967
 
        call->userData = data;
968
 
 
969
 
        pthread_mutex_lock(&pluginAsyncCallMutex);
970
 
        pendingPluginThreadRequests->push_back(call);
971
 
        pthread_mutex_unlock(&pluginAsyncCallMutex);
972
 
 
973
 
        browser_functions.pluginthreadasynccall(instance, &processAsyncCallQueue, NULL); // Always returns immediately
974
 
 
975
 
        PLUGIN_DEBUG("Pushed back call evt %p\n", call);
976
 
 
977
 
        return true;
978
 
    }
979
 
 
980
 
    // Else
981
 
    PLUGIN_DEBUG("Instance is not active. Call rejected.\n");
982
 
    return false;
983
 
}
984
 
 
985
 
/**
986
 
 * Runs through the async call wait queue and executes all calls
987
 
 *
988
 
 * @param param Ignored -- required to conform to NPN_PluginThreadAsynCall API
989
 
 */
990
 
void
991
 
processAsyncCallQueue(void* param /* ignored */)
992
 
{
993
 
    do {
994
 
        PluginThreadCall* call = NULL;
995
 
 
996
 
        pthread_mutex_lock(&pluginAsyncCallMutex);
997
 
        if (pendingPluginThreadRequests->size() > 0)
998
 
        {
999
 
            call = pendingPluginThreadRequests->front();
1000
 
            pendingPluginThreadRequests->erase(pendingPluginThreadRequests->begin());
1001
 
        }
1002
 
        pthread_mutex_unlock(&pluginAsyncCallMutex);
1003
 
 
1004
 
        if (call)
1005
 
        {
1006
 
            PLUGIN_DEBUG("Processing call evt %p\n", call);
1007
 
            call->func(call->userData);
1008
 
            PLUGIN_DEBUG("Call evt %p processed\n", call);
1009
 
 
1010
 
            delete call;
1011
 
        } else
1012
 
        {
1013
 
            break;
1014
 
        }
1015
 
    } while(1);
1016
 
}
1017
 
 
1018
 
/******************************************
1019
 
 * Begin JavaMessageSender implementation *
1020
 
 ******************************************
1021
 
 *
1022
 
 * This implementation is very simple and is therefore folded into this file
1023
 
 * rather than a new one.
1024
 
 */
1025
 
 
1026
 
/**
1027
 
 * Sends to the Java side
1028
 
 *
1029
 
 * @param message The message to send.
1030
 
 * @param returns whether the message was consumable (always true)
1031
 
 */
1032
 
 
1033
 
bool
1034
 
JavaMessageSender::newMessageOnBus(const char* message)
1035
 
{
1036
 
        char* msg = (char*) malloc(sizeof(char)*strlen(message) + 1);
1037
 
        strcpy(msg, message);
1038
 
        plugin_send_message_to_appletviewer(msg);
1039
 
 
1040
 
        free(msg);
1041
 
        msg = NULL;
1042
 
 
1043
 
        // Always successful
1044
 
        return true;
1045
 
}
1046
 
 
1047
 
/***********************************
1048
 
 * Begin MessageBus implementation *
1049
 
 ***********************************/
1050
 
 
1051
 
/**
1052
 
 * Constructor.
1053
 
 *
1054
 
 * Initializes the mutexes needed by the other functions.
1055
 
 */
1056
 
MessageBus::MessageBus()
1057
 
{
1058
 
        int ret;
1059
 
 
1060
 
        ret = pthread_mutex_init(&subscriber_mutex, NULL);
1061
 
 
1062
 
        if(ret)
1063
 
                PLUGIN_DEBUG("Error: Unable to initialize subscriber mutex: %d\n", ret);
1064
 
 
1065
 
        ret = pthread_mutex_init(&msg_queue_mutex, NULL);
1066
 
        if(ret)
1067
 
                PLUGIN_DEBUG("Error: Unable to initialize message queue mutex: %d\n", ret);
1068
 
 
1069
 
        PLUGIN_DEBUG("Mutexs %p and %p initialized\n", &subscriber_mutex, &msg_queue_mutex);
1070
 
}
1071
 
 
1072
 
/**
1073
 
 * Destructor.
1074
 
 *
1075
 
 * Destroy the mutexes initialized by the constructor.
1076
 
 */
1077
 
 
1078
 
MessageBus::~MessageBus()
1079
 
{
1080
 
    PLUGIN_DEBUG("MessageBus::~MessageBus\n");
1081
 
 
1082
 
        int ret;
1083
 
 
1084
 
        ret = pthread_mutex_destroy(&subscriber_mutex);
1085
 
        if(ret)
1086
 
                PLUGIN_DEBUG("Error: Unable to destroy subscriber mutex: %d\n", ret);
1087
 
 
1088
 
        ret = pthread_mutex_destroy(&msg_queue_mutex);
1089
 
        if(ret)
1090
 
                        PLUGIN_DEBUG("Error: Unable to destroy message queue mutex: %d\n", ret);
1091
 
}
1092
 
 
1093
 
/**
1094
 
 * Adds the given BusSubscriber as a subscriber to self
1095
 
 *
1096
 
 * @param b The BusSubscriber to subscribe
1097
 
 */
1098
 
void
1099
 
MessageBus::subscribe(BusSubscriber* b)
1100
 
{
1101
 
    // Applets may initialize in parallel. So lock before pushing.
1102
 
 
1103
 
        PLUGIN_DEBUG("Subscribing %p to bus %p\n", b, this);
1104
 
    pthread_mutex_lock(&subscriber_mutex);
1105
 
    subscribers.push_back(b);
1106
 
    pthread_mutex_unlock(&subscriber_mutex);
1107
 
}
1108
 
 
1109
 
/**
1110
 
 * Removes the given BusSubscriber from the subscriber list
1111
 
 *
1112
 
 * @param b The BusSubscriber to ubsubscribe
1113
 
 */
1114
 
void
1115
 
MessageBus::unSubscribe(BusSubscriber* b)
1116
 
{
1117
 
    // Applets may initialize in parallel. So lock before pushing.
1118
 
 
1119
 
        PLUGIN_DEBUG("Un-subscribing %p from bus %p\n", b, this);
1120
 
    pthread_mutex_lock(&subscriber_mutex);
1121
 
    subscribers.remove(b);
1122
 
    pthread_mutex_unlock(&subscriber_mutex);
1123
 
}
1124
 
 
1125
 
/**
1126
 
 * Notifies all subscribers with the given message
1127
 
 *
1128
 
 * @param message The message to send to the subscribers
1129
 
 */
1130
 
void
1131
 
MessageBus::post(const char* message)
1132
 
{
1133
 
        char* msg = (char*) malloc(sizeof(char)*strlen(message) + 1);
1134
 
        bool message_consumed = false;
1135
 
 
1136
 
        // consumer frees this memory
1137
 
        strcpy(msg, message);
1138
 
 
1139
 
        PLUGIN_DEBUG("Trying to lock %p...\n", &msg_queue_mutex);
1140
 
        pthread_mutex_lock(&subscriber_mutex);
1141
 
 
1142
 
    PLUGIN_DEBUG("Message %s received on bus. Notifying subscribers.\n", msg);
1143
 
 
1144
 
    std::list<BusSubscriber*>::const_iterator i;
1145
 
    for( i = subscribers.begin(); i != subscribers.end() && !message_consumed; ++i ) {
1146
 
        PLUGIN_DEBUG("Notifying subscriber %p of %s\n", *i, msg);
1147
 
        message_consumed = ((BusSubscriber*) *i)->newMessageOnBus(msg);
1148
 
    }
1149
 
 
1150
 
    pthread_mutex_unlock(&subscriber_mutex);
1151
 
 
1152
 
    if (!message_consumed)
1153
 
        PLUGIN_DEBUG("Warning: No consumer found for message %s\n", msg);
1154
 
 
1155
 
    PLUGIN_DEBUG("%p unlocked...\n", &msg_queue_mutex);
1156
 
}