1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/* ***** BEGIN LICENSE BLOCK *****
3 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
4 *
5 * The contents of this file are subject to the Mozilla Public License Version
6 * 1.1 (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 * http://www.mozilla.org/MPL/
9 *
10 * Software distributed under the License is distributed on an "AS IS" basis,
11 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 * for the specific language governing rights and limitations under the
13 * License.
14 *
15 * The Original Code is mozilla.org code.
16 *
17 * The Initial Developer of the Original Code is
18 * Netscape Communications Corporation.
19 * Portions created by the Initial Developer are Copyright (C) 1998
20 * the Initial Developer. All Rights Reserved.
21 *
22 * Contributor(s):
23 *
24 * Alternatively, the contents of this file may be used under the terms of
25 * either the GNU General Public License Version 2 or later (the "GPL"), or
26 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
27 * in which case the provisions of the GPL or the LGPL are applicable instead
28 * of those above. If you wish to allow use of your version of this file only
29 * under the terms of either the GPL or the LGPL, and not to allow others to
30 * use your version of this file under the terms of the MPL, indicate your
31 * decision by deleting the provisions above and replace them with the notice
32 * and other provisions required by the GPL or the LGPL. If you do not delete
33 * the provisions above, a recipient may use your version of this file under
34 * the terms of any one of the MPL, the GPL or the LGPL.
35 *
36 * ***** END LICENSE BLOCK ***** */
37
38#include <string>
39#include <vector>
40#include <errno.h>
41
42
43#include "xp.h"
44
45#include "format.h"
46#include "logger.h"
47
48extern Logger * logger;
49
50////////////////////////////////////////////////////////////////////////////////
51// From Google Chrome's string_util.cc
52
53// It's possible for functions that use a va_list, such as StringPrintf, to
54// invalidate the data in it upon use.  The fix is to make a copy of the
55// structure before using it and use that copy instead.  va_copy is provided
56// for this purpose.  MSVC does not provide va_copy, so define an
57// implementation here.  It is not guaranteed that assignment is a copy, so the
58// StringUtil.__GNUC__ unit test tests this capability.
59#if defined(COMPILER_GCC)
60#define GG_VA_COPY(a, b) (va_copy(a, b))
61#elif defined(_MSC_VER)
62#define GG_VA_COPY(a, b) (a = b)
63#endif
64
65
66// The arraysize(arr) macro returns the # of elements in an array arr.
67// The expression is a compile-time constant, and therefore can be
68// used in defining new arrays, for example.  If you use arraysize on
69// a pointer by mistake, you will get a compile-time error.
70//
71// One caveat is that arraysize() doesn't accept any array of an
72// anonymous type or a type defined inside a function.  In these rare
73// cases, you have to use the unsafe ARRAYSIZE_UNSAFE() macro below.  This is
74// due to a limitation in C++'s template system.  The limitation might
75// eventually be removed, but it hasn't happened yet.
76
77// This template function declaration is used in defining arraysize.
78// Note that the function doesn't need an implementation, as we only
79// use its type.
80template <typename T, size_t N>
81char (&ArraySizeHelper(T (&array)[N]))[N];
82
83// That gcc wants both of these prototypes seems mysterious. VC, for
84// its part, can't decide which to use (another mystery). Matching of
85// template overloads: the final frontier.
86#ifndef _MSC_VER
87template <typename T, size_t N>
88char (&ArraySizeHelper(const T (&array)[N]))[N];
89#endif
90
91#define arraysize(array) (sizeof(ArraySizeHelper(array)))
92
93#if defined(_WIN32)
94inline int vsnprintf(char* buffer, size_t size,
95                     const char* format, va_list arguments) {
96  int length = vsnprintf_s(buffer, size, size - 1, format, arguments);
97  if (length < 0)
98    return _vscprintf(format, arguments);
99  return length;
100}
101#else
102inline int vsnprintf(char* buffer, size_t size,
103                     const char* format, va_list arguments) {
104  return ::vsnprintf(buffer, size, format, arguments);
105}
106#endif
107
108
109// Templatized backend for StringPrintF/StringAppendF. This does not finalize
110// the va_list, the caller is expected to do that.
111template <class StringType>
112static void StringAppendVT(StringType* dst,
113                           const typename StringType::value_type* format,
114                           va_list ap) {
115  // First try with a small fixed size buffer.
116  // This buffer size should be kept in sync with StringUtilTest.GrowBoundary
117  // and StringUtilTest.StringPrintfBounds.
118  typename StringType::value_type stack_buf[1024];
119
120  va_list ap_copy;
121  GG_VA_COPY(ap_copy, ap);
122
123#if !defined(_WIN32)
124  errno = 0;
125#endif
126  int result = vsnprintf(stack_buf, arraysize(stack_buf), format, ap_copy);
127  va_end(ap_copy);
128
129  if (result >= 0 && result < static_cast<int>(arraysize(stack_buf))) {
130    // It fit.
131    dst->append(stack_buf, result);
132    return;
133  }
134
135  // Repeatedly increase buffer size until it fits.
136  int mem_length = arraysize(stack_buf);
137  while (true) {
138    if (result < 0) {
139#if !defined(_WIN32)
140      // On Windows, vsnprintf always returns the number of characters in a
141      // fully-formatted string, so if we reach this point, something else is
142      // wrong and no amount of buffer-doubling is going to fix it.
143      if (errno != 0 && errno != EOVERFLOW)
144#endif
145      {
146        // If an error other than overflow occurred, it's never going to work.
147        return;
148      }
149      // Try doubling the buffer size.
150      mem_length *= 2;
151    } else {
152      // We need exactly "result + 1" characters.
153      mem_length = result + 1;
154    }
155
156    if (mem_length > 32 * 1024 * 1024) {
157      // That should be plenty, don't try anything larger.  This protects
158      // against huge allocations when using vsnprintf implementations that
159      // return -1 for reasons other than overflow without setting errno.
160      return;
161    }
162
163    std::vector<typename StringType::value_type> mem_buf(mem_length);
164
165    // NOTE: You can only use a va_list once.  Since we're in a while loop, we
166    // need to make a new copy each time so we don't use up the original.
167    GG_VA_COPY(ap_copy, ap);
168    result = vsnprintf(&mem_buf[0], mem_length, format, ap_copy);
169    va_end(ap_copy);
170
171    if ((result >= 0) && (result < mem_length)) {
172      // It fit.
173      dst->append(&mem_buf[0], result);
174      return;
175    }
176  }
177}
178
179std::string StringPrintf(const char* format, ...) {
180  va_list ap;
181  va_start(ap, format);
182  std::string result;
183  StringAppendVT(&result, format, ap);
184  va_end(ap);
185  return result;
186}
187
188////////////////////////////////////////////////////////////////////////////////
189
190
191char * FormatNPAPIError(int iError)
192{
193  static char szError[64];
194  switch (iError)
195  {
196    case NPERR_NO_ERROR:
197      sprintf(szError, "NPERR_NO_ERROR");
198      break;
199    case NPERR_GENERIC_ERROR:
200      sprintf(szError, "NPERR_GENERIC_ERROR");
201      break;
202    case NPERR_INVALID_INSTANCE_ERROR:
203      sprintf(szError, "NPERR_INVALID_INSTANCE_ERROR");
204      break;
205    case NPERR_INVALID_FUNCTABLE_ERROR:
206      sprintf(szError, "NPERR_INVALID_FUNCTABLE_ERROR");
207      break;
208    case NPERR_MODULE_LOAD_FAILED_ERROR:
209      sprintf(szError, "NPERR_MODULE_LOAD_FAILED_ERROR");
210      break;
211    case NPERR_OUT_OF_MEMORY_ERROR:
212      sprintf(szError, "NPERR_OUT_OF_MEMORY_ERROR");
213      break;
214    case NPERR_INVALID_PLUGIN_ERROR:
215      sprintf(szError, "NPERR_INVALID_PLUGIN_ERROR");
216      break;
217    case NPERR_INVALID_PLUGIN_DIR_ERROR:
218      sprintf(szError, "NPERR_INVALID_PLUGIN_DIR_ERROR");
219      break;
220    case NPERR_INCOMPATIBLE_VERSION_ERROR:
221      sprintf(szError, "NPERR_INCOMPATIBLE_VERSION_ERROR");
222      break;
223    case NPERR_INVALID_PARAM:
224      sprintf(szError, "NPERR_INVALID_PARAM");
225      break;
226    case NPERR_INVALID_URL:
227      sprintf(szError, "NPERR_INVALID_URL");
228      break;
229    case NPERR_FILE_NOT_FOUND:
230      sprintf(szError, "NPERR_FILE_NOT_FOUND");
231      break;
232    case NPERR_NO_DATA:
233      sprintf(szError, "NPERR_NO_DATA");
234      break;
235    case NPERR_STREAM_NOT_SEEKABLE:
236      sprintf(szError, "NPERR_STREAM_NOT_SEEKABLE");
237      break;
238    default:
239      sprintf(szError, "Unlisted error");
240      break;
241  }
242  return &szError[0];
243}
244
245char * FormatNPAPIReason(int iReason)
246{
247  static char szReason[64];
248  switch (iReason)
249  {
250    case NPRES_DONE:
251      sprintf(szReason, "NPRES_DONE");
252      break;
253    case NPRES_NETWORK_ERR:
254      sprintf(szReason, "NPRES_NETWORK_ERR");
255      break;
256    case NPRES_USER_BREAK:
257      sprintf(szReason, "NPRES_USER_BREAK");
258      break;
259    default:
260      sprintf(szReason, "Unlisted reason");
261      break;
262  }
263  return &szReason[0];
264}
265
266char * FormatNPNVariable(NPNVariable var)
267{
268  static char szVar[80];
269  switch (var)
270  {
271    case NPNVxDisplay:
272      sprintf(szVar, "%i -- NPNVxDisplay", var);
273      break;
274    case NPNVxtAppContext:
275      sprintf(szVar, "%i -- NPNVxtAppContext", var);
276      break;
277    case NPNVnetscapeWindow:
278      sprintf(szVar, "%i -- NPNVnetscapeWindow", var);
279      break;
280    case NPNVjavascriptEnabledBool:
281      sprintf(szVar, "%i -- NPNVjavascriptEnabledBool", var);
282      break;
283    case NPNVasdEnabledBool:
284      sprintf(szVar, "%i -- NPNVasdEnabledBool", var);
285      break;
286    case NPNVisOfflineBool:
287      sprintf(szVar, "%i -- NPNVisOfflineBool", var);
288      break;
289    default:
290      sprintf(szVar, "%i -- Unlisted variable", var);
291      break;
292  }
293  return &szVar[0];
294}
295
296char * FormatNPPVariable(NPPVariable var)
297{
298  static char szVar[80];
299  switch (var)
300  {
301    case NPPVpluginNameString:
302      sprintf(szVar, "%i -- NPPVpluginNameString", var);
303      break;
304    case NPPVpluginDescriptionString:
305      sprintf(szVar, "%i -- NPPVpluginDescriptionString?", var);
306      break;
307    case NPPVpluginWindowBool:
308      sprintf(szVar, "%i -- NPPVpluginWindowBool?", var);
309      break;
310    case NPPVpluginTransparentBool:
311      sprintf(szVar, "%i -- NPPVpluginTransparentBool?", var);
312      break;
313    case NPPVjavaClass:
314      sprintf(szVar, "%i -- NPPVjavaClass?", var);
315      break;
316    case NPPVpluginWindowSize:
317      sprintf(szVar, "%i -- NPPVpluginWindowSize?", var);
318      break;
319    case NPPVpluginTimerInterval:
320      sprintf(szVar, "%i -- NPPVpluginTimerInterval?", var);
321      break;
322    case NPPVpluginScriptableInstance:
323      sprintf(szVar, "%i -- NPPVpluginScriptableInstance?", var);
324      break;
325    case NPPVpluginScriptableIID:
326      sprintf(szVar, "%i -- NPPVpluginScriptableIID?", var);
327      break;
328    default:
329      sprintf(szVar, "%i -- Unlisted variable?", var);
330      break;
331  }
332  return &szVar[0];
333}
334
335BOOL FormatPCHARArgument(char * szBuf, int iLength, LogArgumentStruct * parg)
336{
337  if(iLength <= parg->iLength)
338    return FALSE;
339
340  if(parg->pData == NULL)
341    sprintf(szBuf, "%#08lx", parg->dwArg);
342  else
343    sprintf(szBuf, "%#08lx(\"%s\")", parg->dwArg, (char *)parg->pData);
344  return TRUE;
345}
346
347BOOL FormatBOOLArgument(char * szBuf, int iLength, LogArgumentStruct * parg)
348{
349  if(iLength <= 8)
350    return FALSE;
351
352  sprintf(szBuf, "%s", ((NPBool)parg->dwArg == TRUE) ? "TRUE" : "FALSE");
353  return TRUE;
354}
355
356BOOL FormatPBOOLArgument(char * szBuf, int iLength, LogArgumentStruct * parg)
357{
358  if(iLength <= 8)
359    return FALSE;
360
361  sprintf(szBuf, "%#08lx(%s)", parg->dwArg, (*((NPBool *)parg->pData) == TRUE) ? "TRUE" : "FALSE");
362  return TRUE;
363}
364
365static void makeAbbreviatedString(char * szBuf, int iSize, DWORD dwArg, int iLength, int iWrap)
366{
367  if(dwArg == 0L)
368  {
369    szBuf[0] = '\0';
370    return;
371  }
372
373  if(iLength > iWrap)
374  {
375    int iRealWrap = (iSize > iWrap) ? iWrap : (iSize - 4);
376    memcpy((LPVOID)&szBuf[0], (LPVOID)dwArg, iRealWrap);
377    szBuf[iRealWrap]     = '.';
378    szBuf[iRealWrap + 1] = '.';
379    szBuf[iRealWrap + 2] = '.';
380    szBuf[iRealWrap + 3] = '\0';
381  }
382  else
383  {
384    if(iLength >= iSize)
385    {
386      memcpy((LPVOID)&szBuf[0], (LPVOID)dwArg, iSize - 4);
387      szBuf[iSize]     = '.';
388      szBuf[iSize + 1] = '.';
389      szBuf[iSize + 2] = '.';
390      szBuf[iSize + 3] = '\0';
391    }
392    else
393    {
394      memcpy((LPVOID)&szBuf[0], (LPVOID)dwArg, iLength);
395      szBuf[iLength] = '\0';
396    }
397  }
398}
399
400LogItemStruct * makeLogItemStruct(NPAPI_Action action,
401                                  DWORD dw1, DWORD dw2, DWORD dw3, DWORD dw4,
402                                  DWORD dw5, DWORD dw6, DWORD dw7, BOOL bShort)
403{
404  int iWrap = 64;
405
406  LogItemStruct * plis = new LogItemStruct;
407  if(plis == NULL)
408    return NULL;
409
410  plis->action = action;
411  plis->arg1.dwArg = dw1;
412  plis->arg2.dwArg = dw2;
413  plis->arg3.dwArg = dw3;
414  plis->arg4.dwArg = dw4;
415  plis->arg5.dwArg = dw5;
416  plis->arg6.dwArg = dw6;
417  plis->arg7.dwArg = dw7;
418
419  char szTarget[1024] = {'\0'};
420  char szBuf[1024] = {'\0'};
421
422  if(bShort)
423    return plis;
424
425  switch (action)
426  {
427    case action_invalid:
428      break;
429
430    // NPN action
431    case action_npn_version:
432      plis->arg1.pData = new int[1];
433      *(int*)(plis->arg1.pData) = *((int*)dw1);
434      plis->arg1.iLength = sizeof(int);
435
436      plis->arg2.pData = new int[1];
437      *(int*)(plis->arg2.pData) = *((int*)dw2);
438      plis->arg2.iLength = sizeof(int);
439
440      plis->arg3.pData = new int[1];
441      *(int*)(plis->arg3.pData) = *((int*)dw3);
442      plis->arg3.iLength = sizeof(int);
443
444      plis->arg4.pData = new int[1];
445      *(int*)(plis->arg4.pData) = *((int*)dw4);
446      plis->arg4.iLength = sizeof(int);
447
448      break;
449    case action_npn_get_url_notify:
450      if(dw2 != 0L)
451      {
452        plis->arg2.iLength = strlen((char *)dw2) + 1;
453        plis->arg2.pData = new char[plis->arg2.iLength];
454        memcpy(plis->arg2.pData, (LPVOID)dw2, plis->arg2.iLength);
455      }
456
457      if(dw3 != 0L)
458      {
459        makeAbbreviatedString(szTarget, sizeof(szTarget), dw3, strlen((char *)dw3), iWrap);
460        plis->arg3.iLength = strlen(szTarget) + 1;
461        plis->arg3.pData = new char[plis->arg3.iLength];
462        memcpy(plis->arg3.pData, (LPVOID)&szTarget[0], plis->arg3.iLength);
463      }
464      break;
465    case action_npn_get_url:
466    {
467      if(dw2 != 0L)
468      {
469        plis->arg2.iLength = strlen((char *)dw2) + 1;
470        plis->arg2.pData = new char[plis->arg2.iLength];
471        memcpy(plis->arg2.pData, (LPVOID)dw2, plis->arg2.iLength);
472      }
473
474      if(dw3 != 0L)
475      {
476        makeAbbreviatedString(szTarget, sizeof(szTarget), dw3, strlen((char *)dw3), iWrap);
477        plis->arg3.iLength = strlen(szTarget) + 1;
478        plis->arg3.pData = new char[plis->arg3.iLength];
479        memcpy(plis->arg3.pData, (LPVOID)&szTarget[0], plis->arg3.iLength);
480      }
481      break;
482    }
483    case action_npn_post_url_notify:
484    {
485      if(dw2 != 0L)
486      {
487        plis->arg2.iLength = strlen((char *)dw2) + 1;
488        plis->arg2.pData = new char[plis->arg2.iLength];
489        memcpy(plis->arg2.pData, (LPVOID)dw2, plis->arg2.iLength);
490      }
491
492      if(dw3 != 0L)
493      {
494        makeAbbreviatedString(szTarget, sizeof(szTarget), dw3, strlen((char *)dw3), iWrap);
495        plis->arg3.iLength = strlen(szTarget) + 1;
496        plis->arg3.pData = new char[plis->arg3.iLength];
497        memcpy(plis->arg3.pData, (LPVOID)&szTarget[0], plis->arg3.iLength);
498      }
499
500      makeAbbreviatedString(szBuf, sizeof(szBuf), dw5, strlen((char *)dw5), iWrap);
501      plis->arg5.iLength = (int)dw4 + 1;
502      plis->arg5.pData = new char[plis->arg5.iLength];
503      memcpy(plis->arg5.pData, (LPVOID)&szBuf[0], plis->arg5.iLength);
504
505      break;
506    }
507    case action_npn_post_url:
508    {
509      if(dw2 != 0L)
510      {
511        plis->arg2.iLength = strlen((char *)dw2) + 1;
512        plis->arg2.pData = new char[plis->arg2.iLength];
513        memcpy(plis->arg2.pData, (LPVOID)dw2, plis->arg2.iLength);
514      }
515
516      if(dw3 != 0L)
517      {
518        makeAbbreviatedString(szTarget, sizeof(szTarget), dw3, strlen((char *)dw3), iWrap);
519        plis->arg3.iLength = strlen(szTarget) + 1;
520        plis->arg3.pData = new char[plis->arg3.iLength];
521        memcpy(plis->arg3.pData, (LPVOID)&szTarget[0], plis->arg3.iLength);
522      }
523
524      makeAbbreviatedString(szBuf, sizeof(szBuf), dw5, strlen((char *)dw5), iWrap);
525      plis->arg5.iLength = (int)dw4 + 1;
526      plis->arg5.pData = new char[plis->arg5.iLength];
527      memcpy(plis->arg5.pData, (LPVOID)&szBuf[0], plis->arg5.iLength);
528
529      break;
530    }
531    case action_npn_new_stream:
532    {
533      if(dw2 != 0L)
534      {
535        plis->arg2.iLength = strlen((char *)dw2) + 1;
536        plis->arg2.pData = new char[plis->arg2.iLength];
537        memcpy(plis->arg2.pData, (LPVOID)dw2, plis->arg2.iLength);
538      }
539
540      makeAbbreviatedString(szTarget, sizeof(szTarget), dw3, strlen((char *)dw3), iWrap);
541      plis->arg3.iLength = strlen(szTarget) + 1;
542      plis->arg3.pData = new char[plis->arg3.iLength];
543      memcpy(plis->arg3.pData, (LPVOID)&szTarget[0], plis->arg3.iLength);
544
545      plis->arg4.pData = new char[sizeof(DWORD)];
546      plis->arg4.iLength = sizeof(DWORD);
547      memcpy(plis->arg4.pData, (LPVOID)dw4, plis->arg4.iLength);
548
549      break;
550    }
551    case action_npn_destroy_stream:
552      break;
553    case action_npn_request_read:
554      break;
555    case action_npn_write:
556    {
557      makeAbbreviatedString(szBuf, sizeof(szBuf), dw4, strlen((char *)dw4), iWrap);
558      plis->arg4.iLength = strlen(szBuf) + 1;
559      plis->arg4.pData = new char[plis->arg4.iLength];
560      memcpy(plis->arg4.pData, (LPVOID)&szBuf[0], plis->arg4.iLength);
561      break;
562    }
563    case action_npn_status:
564      if(dw2 != 0L)
565      {
566        plis->arg2.iLength = strlen((char *)dw2) + 1;
567        plis->arg2.pData = new char[plis->arg2.iLength];
568        memcpy(plis->arg2.pData, (LPVOID)dw2, plis->arg2.iLength);
569      }
570      break;
571    case action_npn_user_agent:
572      break;
573    case action_npn_mem_alloc:
574      break;
575    case action_npn_mem_free:
576      break;
577    case action_npn_mem_flush:
578      break;
579    case action_npn_reload_plugins:
580      break;
581    case action_npn_get_java_env:
582      break;
583    case action_npn_get_java_peer:
584      break;
585    case action_npn_get_value:
586      plis->arg3.iLength = sizeof(DWORD);
587      plis->arg3.pData = new char[plis->arg3.iLength];
588      memcpy(plis->arg3.pData, (LPVOID)dw3, plis->arg3.iLength);
589      break;
590    case action_npn_set_value:
591      if(((NPPVariable)dw2 == NPPVpluginNameString) || ((NPPVariable)dw2 == NPPVpluginDescriptionString))
592      {
593        makeAbbreviatedString(szBuf, sizeof(szBuf), dw3, strlen((char *)dw3), iWrap);
594        plis->arg3.iLength = strlen(szBuf) + 1;
595        plis->arg3.pData = new char[plis->arg3.iLength];
596        memcpy(plis->arg3.pData, (LPVOID)&szBuf[0], plis->arg3.iLength);
597      }
598      else if(((NPPVariable)dw2 == NPPVpluginWindowBool) || ((NPPVariable)dw2 == NPPVpluginTransparentBool))
599      {
600        plis->arg3.iLength = sizeof(NPBool);
601        plis->arg3.pData = new char[plis->arg3.iLength];
602        memcpy(plis->arg3.pData, (LPVOID)&dw3, plis->arg3.iLength);
603      }
604      else if((NPPVariable)dw2 == NPPVpluginWindowSize)
605      {
606        plis->arg3.iLength = sizeof(NPSize);
607        plis->arg3.pData = new char[plis->arg3.iLength];
608        memcpy(plis->arg3.pData, (LPVOID)dw3, plis->arg3.iLength);
609      }
610      break;
611    case action_npn_invalidate_rect:
612    {
613      plis->arg2.iLength = sizeof(NPRect);
614      plis->arg2.pData = new char[plis->arg2.iLength];
615      memcpy(plis->arg2.pData, (LPVOID)dw2, plis->arg2.iLength);
616      break;
617    }
618    case action_npn_invalidate_region:
619      break;
620    case action_npn_force_redraw:
621      break;
622
623    // NPP action
624    case action_npp_new:
625      plis->arg1.iLength = strlen((char *)dw1) + 1;
626      plis->arg1.pData = new char[plis->arg1.iLength];
627      memcpy(plis->arg1.pData, (LPVOID)dw1, plis->arg1.iLength);
628      break;
629    case action_npp_destroy:
630      plis->arg2.iLength = sizeof(DWORD);
631      plis->arg2.pData = new char[plis->arg2.iLength];
632      memcpy(plis->arg2.pData, (LPVOID)dw2, plis->arg2.iLength);
633      break;
634    case action_npp_set_window:
635      plis->arg2.iLength = sizeof(NPWindow);
636      plis->arg2.pData = new char[plis->arg2.iLength];
637      memcpy(plis->arg2.pData, (LPVOID)dw2, plis->arg2.iLength);
638      break;
639    case action_npp_new_stream:
640      plis->arg2.iLength = strlen((char *)dw2) + 1;
641      plis->arg2.pData = new char[plis->arg2.iLength];
642      memcpy(plis->arg2.pData, (LPVOID)dw2, plis->arg2.iLength);
643
644      plis->arg5.iLength = sizeof(uint16);
645      plis->arg5.pData = new char[plis->arg5.iLength];
646      memcpy(plis->arg5.pData, (LPVOID)dw5, plis->arg5.iLength);
647      break;
648    case action_npp_destroy_stream:
649      break;
650    case action_npp_stream_as_file:
651      plis->arg3.iLength = strlen((char *)dw3) + 1;
652      plis->arg3.pData = new char[plis->arg3.iLength];
653      memcpy(plis->arg3.pData, (LPVOID)dw3, plis->arg3.iLength);
654      break;
655    case action_npp_write_ready:
656      break;
657    case action_npp_write:
658    {
659      if(dw5 != 0L)
660      {
661        makeAbbreviatedString(szBuf, sizeof(szBuf), dw5, strlen((char *)dw5), iWrap);
662        plis->arg5.iLength = strlen(szBuf) + 1;
663        plis->arg5.pData = new char[plis->arg5.iLength];
664        memcpy(plis->arg5.pData, (LPVOID)&szBuf[0], plis->arg5.iLength);
665      }
666      break;
667    }
668    case action_npp_print:
669      break;
670    case action_npp_handle_event:
671      break;
672    case action_npp_url_notify:
673      plis->arg2.iLength = strlen((char *)dw2) + 1;
674      plis->arg2.pData = new char[plis->arg2.iLength];
675      memcpy(plis->arg2.pData, (LPVOID)dw2, plis->arg2.iLength);
676      break;
677    case action_npp_get_java_class:
678      break;
679    case action_npp_get_value:
680      break;
681    case action_npp_set_value:
682      break;
683
684    default:
685      break;
686  }
687
688  return plis;
689}
690
691void freeLogItemStruct(LogItemStruct * lis)
692{
693  if(lis)
694    delete lis;
695}
696
697void formatLogItem(LogItemStruct * plis, std::string* output, BOOL bDOSStyle)
698{
699  static char szEOL[8];
700  static char szEOI[256];
701  static char szEndOfItem[] = "";
702
703  if(bDOSStyle)
704  {
705    strcpy(szEOL, "\r\n");
706    //strcpy(szEOI, szEndOfItem);
707    //strcat(szEOI, "\r\n");
708  }
709  else
710  {
711    strcpy(szEOL, "\n");
712    //strcpy(szEOI, szEndOfItem);
713    //strcat(szEOI, "\n");
714  }
715
716  DWORD dw1 = plis->arg1.dwArg;
717  DWORD dw2 = plis->arg2.dwArg;
718  DWORD dw3 = plis->arg3.dwArg;
719  DWORD dw4 = plis->arg4.dwArg;
720  DWORD dw5 = plis->arg5.dwArg;
721  DWORD dw6 = plis->arg6.dwArg;
722  DWORD dw7 = plis->arg7.dwArg;
723
724  char sz1[1024] = {'\0'};
725  char sz2[1024] = {'\0'};
726  char sz3[1024] = {'\0'};
727  char sz4[1024] = {'\0'};
728  char sz5[1024] = {'\0'};
729  char sz6[1024] = {'\0'};
730
731  switch (plis->action)
732  {
733    case action_invalid:
734      break;
735
736    // NPN action
737    case action_npn_version:
738      if((plis->arg1.pData != NULL)&&(plis->arg2.pData != NULL)&&(plis->arg3.pData != NULL)&&(plis->arg4.pData != NULL))
739        *output = StringPrintf("NPN_Version(%#08lx, %#08lx, %#08lx, %#08lx)", dw1,dw2,dw3,dw4);
740      else
741        *output = StringPrintf("NPN_Version(%#08lx, %#08lx, %#08lx, %#08lx)", dw1,dw2,dw3,dw4);
742      break;
743    case action_npn_get_url_notify:
744    {
745      FormatPCHARArgument(sz2, sizeof(sz2), &plis->arg2);
746      FormatPCHARArgument(sz3, sizeof(sz3), &plis->arg3);
747      *output = StringPrintf("NPN_GetURLNotify(%#08lx, %s, %s, %#08lx)", dw1,sz2,sz3,dw4);
748      break;
749    }
750    case action_npn_get_url:
751    {
752      FormatPCHARArgument(sz2, sizeof(sz2), &plis->arg2);
753      FormatPCHARArgument(sz3, sizeof(sz3), &plis->arg3);
754      *output = StringPrintf("NPN_GetURL(%#08lx, %s, %s)", dw1,sz2,sz3);
755      break;
756    }
757    case action_npn_post_url_notify:
758    {
759      FormatPCHARArgument(sz2, sizeof(sz2), &plis->arg2);
760      FormatPCHARArgument(sz3, sizeof(sz3), &plis->arg3);
761      FormatPCHARArgument(sz5, sizeof(sz5), &plis->arg5);
762      FormatBOOLArgument(sz6, sizeof(sz6), &plis->arg6);
763
764      *output = StringPrintf("NPN_PostURLNotify(%#08lx, %s, %s, %li, %s, %s, %#08lx)",
765               dw1,sz2,sz3,(uint32)dw4,sz5,sz6,dw7);
766      break;
767    }
768    case action_npn_post_url:
769    {
770      FormatPCHARArgument(sz2, sizeof(sz2), &plis->arg2);
771      FormatPCHARArgument(sz3, sizeof(sz3), &plis->arg3);
772      FormatPCHARArgument(sz5, sizeof(sz5), &plis->arg5);
773      FormatBOOLArgument(sz6, sizeof(sz6), &plis->arg6);
774
775      *output = StringPrintf("NPN_PostURL(%#08lx, %s, %s, %li, %s, %s)",
776               dw1,sz2,sz3,(uint32)dw4,sz5,sz6);
777      break;
778    }
779    case action_npn_new_stream:
780    {
781      FormatPCHARArgument(sz2, sizeof(sz2), &plis->arg2);
782      FormatPCHARArgument(sz3, sizeof(sz3), &plis->arg3);
783      if(plis->arg4.pData != NULL)
784        *output = StringPrintf("NPN_NewStream(%#08lx, %s, %s, %#08lx(%#08lx))",
785                 dw1, sz2,sz3,dw4,*(DWORD *)plis->arg4.pData);
786      else
787        *output = StringPrintf("NPN_NewStream(%#08lx, \"%s\", \"%s\", %#08lx)", dw1, sz2,sz3,dw4);
788      break;
789    }
790    case action_npn_destroy_stream:
791      *output = StringPrintf("NPN_DestroyStream(%#08lx, %#08lx, %s)", dw1,dw2,FormatNPAPIReason((int)dw3));
792      break;
793    case action_npn_request_read:
794      *output = StringPrintf("NPN_RequestRead(%#08lx, %#08lx)", dw1, dw2);
795      break;
796    case action_npn_write:
797    {
798      FormatPCHARArgument(sz4, sizeof(sz4), &plis->arg4);
799      *output = StringPrintf("NPN_Write(%#08lx, %#08lx, %li, %s)", dw1, dw2, (int32)dw3, sz4);
800      break;
801    }
802    case action_npn_status:
803    {
804      FormatPCHARArgument(sz2, sizeof(sz2), &plis->arg2);
805      *output = StringPrintf("NPN_Status(%#08lx, %s)", dw1, sz2);
806      break;
807    }
808    case action_npn_user_agent:
809      *output = StringPrintf("NPN_UserAgent(%#08lx)", dw1);
810      break;
811    case action_npn_mem_alloc:
812      *output = StringPrintf("NPN_MemAlloc(%li)", dw1);
813      break;
814    case action_npn_mem_free:
815      *output = StringPrintf("NPN_MemFree(%#08lx)", dw1);
816      break;
817    case action_npn_mem_flush:
818      *output = StringPrintf("NPN_MemFlush(%li)", dw1);
819      break;
820    case action_npn_reload_plugins:
821    {
822      FormatBOOLArgument(sz1, sizeof(sz1), &plis->arg1);
823      *output = StringPrintf("NPN_ReloadPlugins(%s)", sz1);
824      break;
825    }
826    case action_npn_get_java_env:
827      *output = StringPrintf("NPN_GetJavaEnv()");
828      break;
829    case action_npn_get_java_peer:
830      *output = StringPrintf("NPN_GetJavaPeer(%#08lx)", dw1);
831      break;
832    case action_npn_get_value:
833    {
834      switch(dw2)
835      {
836        case NPNVxDisplay:
837        case NPNVxtAppContext:
838        case NPNVnetscapeWindow:
839          if(dw3 != 0L)
840            *output = StringPrintf("NPN_GetValue(%#08lx, %s, %#08lx(%#08lx))",dw1,FormatNPNVariable((NPNVariable)dw2),dw3,*(DWORD *)dw3);
841          else
842            *output = StringPrintf("NPN_GetValue(%#08lx, %s, %#08lx)",dw1,FormatNPNVariable((NPNVariable)dw2),dw3);
843          break;
844        case NPNVjavascriptEnabledBool:
845        case NPNVasdEnabledBool:
846        case NPNVisOfflineBool:
847          if(dw3 != 0L)
848            *output = StringPrintf("NPN_GetValue(%#08lx, %s, %#08lx(%s))",
849                     dw1,FormatNPNVariable((NPNVariable)dw2),dw3,
850                     (((NPBool)*(DWORD *)dw3) == TRUE) ? "TRUE" : "FALSE");
851          else
852            *output = StringPrintf("NPN_GetValue(%#08lx, %s, %#08lx)",dw1,FormatNPNVariable((NPNVariable)dw2),dw3);
853          break;
854        default:
855          break;
856      }
857      break;
858    }
859    case action_npn_set_value:
860
861      if(((NPPVariable)dw2 == NPPVpluginNameString) || ((NPPVariable)dw2 == NPPVpluginDescriptionString))
862      {
863        FormatPCHARArgument(sz3, sizeof(sz3), &plis->arg3);
864        *output = StringPrintf("NPN_SetValue(%#08lx, %s, %s)", dw1,FormatNPPVariable((NPPVariable)dw2),sz3);
865      }
866      else if(((NPPVariable)dw2 == NPPVpluginWindowBool) || ((NPPVariable)dw2 == NPPVpluginTransparentBool))
867      {
868        FormatPBOOLArgument(sz3, sizeof(sz3), &plis->arg3);
869        *output = StringPrintf("NPN_SetValue(%#08lx, %s, %s)",
870                 dw1,FormatNPPVariable((NPPVariable)dw2),sz3);
871      }
872      else if((NPPVariable)dw2 == NPPVpluginWindowSize)
873      {
874        if(plis->arg3.pData != NULL)
875        {
876          int32 iWidth = ((NPSize *)plis->arg3.pData)->width;
877          int32 iHeight = ((NPSize *)plis->arg3.pData)->height;
878          *output = StringPrintf("NPN_SetValue(%#08lx, %s, %#08lx(%li,%li))",
879                   dw1,FormatNPPVariable((NPPVariable)dw2),dw3,iWidth,iHeight);
880        }
881        else
882          *output = StringPrintf("NPN_SetValue(%#08lx, %s, %#08lx(?,?))",
883                   dw1,FormatNPPVariable((NPPVariable)dw2),dw3);
884      }
885      else
886        *output = StringPrintf("NPN_SetValue(%#08lx, %s, %#08lx(What is it?))", dw1,FormatNPPVariable((NPPVariable)dw2),dw3);
887      break;
888    case action_npn_invalidate_rect:
889    {
890      if(plis->arg2.pData != NULL)
891      {
892        uint16 top    = ((NPRect *)plis->arg2.pData)->top;
893        uint16 left   = ((NPRect *)plis->arg2.pData)->left;
894        uint16 bottom = ((NPRect *)plis->arg2.pData)->bottom;
895        uint16 right  = ((NPRect *)plis->arg2.pData)->right;
896        *output = StringPrintf("NPN_InvalidateRect(%#08lx, %#08lx(%u,%u;%u,%u)", dw1,dw2,top,left,bottom,right);
897      }
898      else
899        *output = StringPrintf("NPN_InvalidateRect(%#08lx, %#08lx(?,?,?,?)", dw1,dw2);
900      break;
901    }
902    case action_npn_invalidate_region:
903      *output = StringPrintf("NPN_InvalidateRegion(%#08lx, %#08lx)", dw1,dw2);
904      break;
905    case action_npn_force_redraw:
906      *output = StringPrintf("NPN_ForceRedraw(%#08lx)", dw1);
907      break;
908    case action_npn_enumerate:
909      *output = StringPrintf("NPN_Enumerate()");
910      break;
911    case action_npn_pop_popups_enabled_state:
912      *output = StringPrintf("NPN_PopPopupsEnabledState()");
913      break;
914    case action_npn_push_popups_enabled_state:
915      *output = StringPrintf("NPN_PushPopupsEnabledState()");
916      break;
917    case action_npn_set_exception:
918      *output = StringPrintf("NPN_SetException(%s)", dw1);
919      break;
920    case action_npn_has_method:
921      *output = StringPrintf("NPN_HasMethod(%d)", dw1);
922      break;
923    case action_npn_has_property:
924      *output = StringPrintf("NPN_HasProperty(%d)", dw1);
925      break;
926    case action_npn_remove_property:
927      *output = StringPrintf("NPN_RemoveProperty(%d)", dw1);
928      break;
929    case action_npn_set_property:
930      *output = StringPrintf("NPN_SetProperty(%d)", dw1);
931      break;
932    case action_npn_get_property:
933      *output = StringPrintf("NPN_GetProperty(%d)", dw1);
934      break;
935    case action_npn_evaluate:
936      *output = StringPrintf("NPN_Evaluate(%s)", dw1);
937      break;
938    case action_npn_invoke_default:
939      *output = StringPrintf("NPN_InvokeDefault(%#08lx)", dw1);
940      break;
941    case action_npn_invoke:
942      *output = StringPrintf("NPN_Invoke(%#08lx)", dw1);
943      break;
944    case action_npn_release_object:
945      *output = StringPrintf("NPN_ReleaseObject(%d)", dw1);
946      break;
947    case action_npn_retain_object:
948      *output = StringPrintf("NPN_RetainObject(%d)", dw1);
949      break;
950    case action_npn_create_object:
951      *output = StringPrintf("NPN_CreateObject(%#08lx)", dw1);
952      break;
953    case action_npn_int_from_identifier:
954      *output = StringPrintf("NPN_IntFromIdentifier(%d)", dw1);
955      break;
956    case action_npn_utf8_from_identifier:
957      *output = StringPrintf("NPN_UTF8FromIdentifier(%d)", dw1);
958      break;
959    case action_npn_identifier_is_string:
960      *output = StringPrintf("NPN_IdentifierIsString(%d)", dw1);
961      break;
962    case action_npn_get_int_identifer:
963      *output = StringPrintf("NPN_GetIntIdentifier(%d)", dw1);
964      break;
965    case action_npn_get_string_identifiers:
966      *output = StringPrintf("NPN_GetStringIdentifier()");
967      break;
968
969    // NPP action
970    case action_npp_new:
971    {
972      char szMode[16];
973      switch (dw3)
974      {
975        case NP_EMBED:
976          strcpy(szMode, "NP_EMBED");
977          break;
978        case NP_FULL:
979          strcpy(szMode, "NP_FULL");
980          break;
981        default:
982          strcpy(szMode, "[Invalid mode]");
983          break;
984      }
985      *output = StringPrintf("NPP_New(\"%s\", %#08lx, %s, %i, %#08lx, %#08lx, %#08lx)",
986               (char *)dw1,dw2,szMode,(int)dw4,dw5,dw6,dw7);
987      break;
988    }
989    case action_npp_destroy:
990      *output = StringPrintf("NPP_Destroy(%#08lx, %#08lx(%#08lx))", dw1, dw2, *(DWORD *)plis->arg2.pData);
991      break;
992    case action_npp_set_window:
993    {
994      char szWindow[512];
995
996      if(plis->arg2.pData != NULL)
997      {
998        char szType[80];
999        switch (((NPWindow*)plis->arg2.pData)->type)
1000        {
1001          case NPWindowTypeWindow:
1002            sprintf(szType, "NPWindowTypeWindow");
1003            break;
1004          case NPWindowTypeDrawable:
1005            sprintf(szType, "NPWindowTypeDrawable");
1006            break;
1007          default:
1008            sprintf(szType, "[Unlisted type]");
1009            break;
1010        }
1011        sprintf(szWindow, "NPWindow: %#08lx, (%li,%li), (%li,%li), (%i,%i,%i,%i), %s",
1012                 ((NPWindow*)plis->arg2.pData)->window,
1013                 ((NPWindow*)plis->arg2.pData)->x,
1014                 ((NPWindow*)plis->arg2.pData)->y,
1015                 ((NPWindow*)plis->arg2.pData)->width,
1016                 ((NPWindow*)plis->arg2.pData)->height,
1017                 ((NPWindow*)plis->arg2.pData)->clipRect.top,
1018                 ((NPWindow*)plis->arg2.pData)->clipRect.left,
1019                 ((NPWindow*)plis->arg2.pData)->clipRect.bottom,
1020                 ((NPWindow*)plis->arg2.pData)->clipRect.right, szType);
1021        *output = StringPrintf("NPP_SetWindow(%#08lx, %#08lx) %s", dw1,dw2,szWindow);
1022      }
1023      else
1024        *output = StringPrintf("NPP_SetWindow(%#08lx, %#08lx)", dw1,dw2);
1025
1026      break;
1027    }
1028    case action_npp_new_stream:
1029    {
1030      switch (*(int16 *)plis->arg5.pData)
1031      {
1032        case NP_NORMAL:
1033          sprintf(sz5, "NP_NORMAL");
1034          break;
1035        case NP_ASFILEONLY:
1036          sprintf(sz5, "NP_ASFILEONLY");
1037          break;
1038        case NP_ASFILE:
1039          sprintf(sz5, "NP_ASFILE");
1040          break;
1041        default:
1042          sprintf(sz5, "[Unlisted type]");
1043          break;
1044      }
1045      FormatPCHARArgument(sz2, sizeof(sz2), &plis->arg2);
1046      *output = StringPrintf("NPP_NewStream(%#08lx, %s, %#08lx (%s), %s, %s)", dw1, sz2, dw3,
1047               ((NPStream*)dw3)->url, ((NPBool)dw4 == TRUE) ? "TRUE" : "FALSE", sz5);
1048      break;
1049    }
1050    case action_npp_destroy_stream:
1051      *output = StringPrintf("NPP_DestroyStream(%#08lx, %#08lx, %s)", dw1,dw2,FormatNPAPIReason((int)dw3));
1052      break;
1053    case action_npp_stream_as_file:
1054      FormatPCHARArgument(sz3, sizeof(sz3), &plis->arg3);
1055      *output = StringPrintf("NPP_StreamAsFile(%#08lx, %#08lx, %s)", dw1,dw2,sz3);
1056      break;
1057    case action_npp_write_ready:
1058      *output = StringPrintf("NPP_WriteReady(%#08lx, %#08lx)", dw1,dw2);
1059      break;
1060    case action_npp_write:
1061    {
1062      FormatPCHARArgument(sz5, sizeof(sz5), &plis->arg5);
1063      *output = StringPrintf("NPP_Write(%#08lx, %#08lx, %li, %li, %s))",dw1,dw2,dw3,dw4,sz5);
1064      break;
1065    }
1066    case action_npp_print:
1067      *output = StringPrintf("NPP_Print(%#08lx, %#08lx)", dw1, dw2);
1068      break;
1069    case action_npp_handle_event:
1070    {
1071      NPEvent *event = (NPEvent*)dw2;
1072      *output = StringPrintf("NPP_HandleEvent(%#08lx, %#08lx {event=%d, wParam=%#08lx lParam=%#08lx)", dw1,dw2,event->event, event->wParam, event->lParam);
1073      break;
1074    }
1075    case action_npp_url_notify:
1076    {
1077      FormatPCHARArgument(sz2, sizeof(sz2), &plis->arg2);
1078      *output = StringPrintf("NPP_URLNotify(%#08lx, %s, %s, %#08lx)", dw1,sz2,FormatNPAPIReason((int)dw3),dw4);
1079      break;
1080    }
1081    case action_npp_get_java_class:
1082      *output = StringPrintf("NPP_GetJavaClass()");
1083      break;
1084    case action_npp_get_value:
1085      *output = StringPrintf("NPP_GetValue(%#08lx, %s, %#08lx)", dw1,FormatNPPVariable((NPPVariable)dw2),dw3);
1086      break;
1087    case action_npp_set_value:
1088      *output = StringPrintf("NPP_SetValue(%#08lx, %s, %#08lx)", dw1,FormatNPNVariable((NPNVariable)dw2),dw3);
1089      break;
1090
1091    default:
1092      *output = StringPrintf("Unknown action");
1093      break;
1094  }
1095  *output += szEOL;
1096  *output += szEOI;
1097}
1098