NPAPI向Javascript传输中文的问题(二)

NPAPI向Javascript传输中文的问题(二)

 

  在上一篇文章《NPAPI向Javascript传输中文的问题(一)》(http://www.cnblogs.com/wliu6V/p/3245684.html)中,我们可以在NPAPI内部新建一字符串,并将其传到Javascript中进行显示。但后来发现仍有一些其他问题:当Javascript将字符串传递到NPAPI插件时,若NPAPI插件用上一篇文章所介绍的方式进行输出的话,就会出现一些编码问题。

  问题当然是出在我们自己写的encodeURI方法上。因为这个encodeURI是从网上抄来的,当时也没太仔细研究。这个encodeURI方法中有这么一句:

MultiByteToWideChar(CP_ACP,
      NULL,
      Str,
      -1,
      Bufw,
      needSize);

与这么一句:

WideCharToMultiByte(CP_UTF8,
      NULL,
      Bufw,
      -1,
      Bufc,
      needSize,
      NULL,
      NULL);

  当时刚看到这两句的时候感觉很不解,为什么要将传入的字符串先从MultiByte转到WideChar,然后再从WideChar转回MultiByte。但稍一留意,发现这两个方法的第一个参数是不同的。既然第二句话参数是UTF8,那么第一句话的参数想必是ANSI编码了。上网查了一下ANSI编码转为UTF8编码的方法,果然是走的这么一个步骤。所以这个encodeURI方法自然就是先将ANSI编码的字符串转为UTF8编码,然后再进行%.2X,将其转为十六进制。

  知道了这个方法是如何对字符串进行处理的,我们就不难发现刚才的问题所在了。在NPAPI插件内部用的是ANSI编码,因此必须要有这么一步,将其转为UTF8然后发给Javascript。但是从Javascript那里得到的字符串应该已经是UTF8编码的了,如果再用同样的encodeURI执行一遍的话,自然就会出现问题。因此我们应该跳过encodeURI前面那些ANSI转UTF8的步骤,直接进行%.2X,将其转为十六进制即可。因此我们需要先对字符串进行判断,根据其编码方式采用不同的处理方式。

  判断字符串编码的方法也是在网上扒来的,来自《判断字符串是否UTF8编码》(http://it.114study.com/ncre/article411272.html) 并有小幅修改(修改后的方法见文末)。这个方法可以判断传入的字符串是否为UTF8格式的。然后我们在encodeURI的时候先调用这个方法对字符串进行判断,若是的话就直接编码为16进制,若否的话就先从ANSI转为UTF8。其他的部分与之前的encodeURI保持相似即可。

  上篇文章说过,encodeURI之后还要将”%”替换为”%25”,才能正常的通过NPN_GetURL方法传给Javascript代码。之前是单独写了一个ReplaceAll方法来进行此步骤,后来想了想,针对此插件的特定用途,我们可以直接把这个替换的过程整合到encodeURI中。也就是将原先的”%%%.2X”改成”%%25%.2X”即可,这样输出的结果就是 “%”+”25”+16进制编码 了。  

  最终我们得到的方法如下所示(需包含<stdio.h>与<malloc.h>):

  

  1 /*******************************************************************************
  2 * encodeURI
  3 * 来自 http://zhidao.baidu.com/question/113953665.html 并有修改。
  4 * 以C的方式实现了Javascript中的encodeURI方法。
  5 * 其结果可以被Javascript通过DecodeURIComponent解码。
  6 * 能够自动识别传入的参数是否为UTF8编码,并采取不同的encode方式。
  7 *******************************************************************************/
  8 char* CScriptPluginObject::encodeURI(const char *Str) {
  9 
 10     if(isEncodeUTF8(Str)) {
 11         char* RTV = (char*)malloc(strlen(Str) *5 +1);
 12         memset(RTV, 0x0, strlen(Str));
 13         unsigned char *pWork = (unsigned char *)Str;
 14         while(*pWork != 0x0) {
 15             sprintf(RTV + strlen(RTV), "%%25%.2X", *pWork);
 16             pWork++;
 17         }
 18         return RTV;
 19 
 20     } else {
 21 
 22         // 先将ANSI转成UTF8
 23         wchar_t *Bufw = NULL;
 24         char *Bufc = NULL;
 25         long needSize = MultiByteToWideChar(CP_ACP,
 26             NULL,
 27             Str,
 28             -1,
 29             NULL,
 30             0);
 31         if ( 0 == needSize ) goto ERROR_HANDLE;
 32 
 33         Bufw = new wchar_t[needSize];
 34         if ( NULL == Bufw ) goto ERROR_HANDLE;
 35 
 36         memset(Bufw,0x0,needSize*2);
 37         MultiByteToWideChar(CP_ACP,
 38             NULL,
 39             Str,
 40             -1,
 41             Bufw,
 42             needSize);
 43 
 44 
 45         needSize = WideCharToMultiByte(CP_UTF8,
 46             NULL,
 47             Bufw,
 48             -1,
 49             NULL,
 50             0,
 51             NULL,
 52             NULL);
 53         if ( 0 == needSize ) goto ERROR_HANDLE;
 54 
 55         Bufc = new char[needSize];
 56         if ( NULL == Bufc ) goto ERROR_HANDLE;
 57 
 58         memset(Bufc,0x0,needSize);
 59         WideCharToMultiByte(CP_UTF8,
 60             NULL,
 61             Bufw,
 62             -1,
 63             Bufc,
 64             needSize,
 65             NULL,
 66             NULL);
 67 
 68         // 进行转码
 69 
 70         char* RTV = (char*)malloc(needSize *5 +1);    // 一个字符转码变成五个字符
 71         memset(RTV,0x0,(needSize *5 +1));
 72         unsigned char *pWork = (unsigned char *)Bufc;
 73         if ( strlen(Bufc) > 5120 ) { goto ERROR_HANDLE; }
 74 
 75         while( *pWork != 0x0 ) {
 76             sprintf(RTV+strlen(RTV),"%%25%.2X",*pWork);
 77             pWork++;
 78         }
 79 
 80         if ( NULL != Bufw ) {
 81             delete [] Bufw;
 82             Bufw = NULL;
 83         }
 84         if ( NULL != Bufc ) {
 85             delete [] Bufc;
 86             Bufc = NULL;
 87         }
 88         return RTV;
 89 
 90     ERROR_HANDLE:
 91         if ( NULL != Bufw ) {
 92             delete [] Bufw;
 93             Bufw = NULL;
 94         }
 95         if ( NULL != Bufc ) {
 96             delete [] Bufc;
 97             Bufc = NULL;
 98         }
 99         return NULL;
100     }
101 }

 

修改后的 isEncodeUTF8() 方法如下:

 1 /*******************************************************************************
 2 * isEncodeUTF8
 3 * 来自 http://it.114study.com/ncre/article411272.html 并有小幅修改。
 4 * 可以判断一个字符串是UTF8还是ANSI编码。
 5 * 通常来说,在插件内部写的一般是ANSI编码,从JS代码传来的一般是UTF8编码。
 6 *******************************************************************************/
 7 bool CScriptPluginObject::isEncodeUTF8(const char* str) {
 8     int i;
 9     DWORD nBytes = 0;    // UTF8使用1~6个字节进行编码,而ASCII只用一个字节
10     UCHAR ch;
11     BOOL bAllAscii = true;    // 若全部字符都是ASCII,则说明不是UTF-8
12 
13     for(i = 0; i < strlen(str); i++) {
14         ch = *(str + i);
15         if( (ch & 0x80) != 0)    // 判断是否为ASCII编码。如果不是,则有可能是UTF8。ASCII用7位编码,但使用一个字节存。最高位标记为0,即0xxxxxxx
16             bAllAscii = FALSE;
17         if (nBytes == 0) {    // 若不是ASCII码,则应该是多字节符。计算字节数
18             if (ch >= 0x80) {
19                 if ( (ch >= 0xFC) && (ch <= 0xFD) )
20                     nBytes = 6;
21                 else if (ch >= 0xF8)
22                     nBytes = 5;
23                 else if (ch >= 0xF0)
24                     nBytes = 4;
25                 else if (ch >= 0xE0)
26                     nBytes = 3;
27                 else if (ch >= 0xC0)
28                     nBytes = 2;
29                 else
30                     return false;
31                 nBytes--;
32             }
33         } else {    // nBytes != 0    多字节符的非首字节,应为10xxxxxx
34             if ( (ch & 0xC0) != 0x80)
35                 return false;
36             nBytes--;
37         }
38     }
39 
40     if (nBytes > 0)    // 违反规则
41         return false;
42 
43     if (bAllAscii)    // 若全部为ASCII,则说明不是UTF8
44         return false;
45 
46     return true;
47 }

 

调用时如下所示:

 1 /*****************************************************************************************
 2 * popJavascriptAlert
 3 * 将传入的CString以Alert的形式弹出在浏览器窗口。
 4 * 会先对传入的字符串进行一系列处理
 5 *****************************************************************************************/
 6 void CScriptPluginObject::popJavascriptAlert(const char* str){
 7     char* tmpStr = encodeURI(str);
 8     char* prevStr = "javascript:alert(decodeURIComponent('";
 9     char* postStr =  "'));";
10     int mlen = strlen(prevStr) + strlen(tmpStr) + strlen(postStr) + 1;
11     char *command = (char*)malloc(mlen);
12     memset(command, 0, mlen);
13     sprintf(command, "%s%s%s", prevStr, tmpStr, postStr);
14 
15     NPN_GetURL(m_npp, command, "_self");
16 }

 

以上。

PS. 今天突然发现前一篇文章被另一个网站给抄过去了。第一次自己写了东西被其他网站抄袭,感觉颇是心情愉快。话说那个网站还巧妙地把大部分词语都替换为近义词了,读起来颇为费劲= =

转载于:https://www.cnblogs.com/wliu6V/p/3258962.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值