Home | History | Annotate | Download | only in common
      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 
     48 extern 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.
     80 template <typename T, size_t N>
     81 char (&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
     87 template <typename T, size_t N>
     88 char (&ArraySizeHelper(const T (&array)[N]))[N];
     89 #endif
     90 
     91 #define arraysize(array) (sizeof(ArraySizeHelper(array)))
     92 
     93 #if defined(_WIN32)
     94 inline 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
    102 inline 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.
    111 template <class StringType>
    112 static 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 
    179 std::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 
    191 char * 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 
    245 char * 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 
    266 char * 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 
    296 char * 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 
    335 BOOL 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 
    347 BOOL 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 
    356 BOOL 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 
    365 static 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 
    400 LogItemStruct * 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 
    691 void freeLogItemStruct(LogItemStruct * lis)
    692 {
    693   if(lis)
    694     delete lis;
    695 }
    696 
    697 void 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