Jacek Caban : mshtml: Added support for BOM in bind_mon_to_wstr.

Alexandre Julliard julliard at winehq.org
Fri Jul 27 13:13:55 CDT 2012


Module: wine
Branch: master
Commit: f98c3bbd9c121d1f427022faf6fb9645de635e7a
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=f98c3bbd9c121d1f427022faf6fb9645de635e7a

Author: Jacek Caban <jacek at codeweavers.com>
Date:   Fri Jul 27 10:51:39 2012 +0200

mshtml: Added support for BOM in bind_mon_to_wstr.

---

 dlls/mshtml/binding.h  |    1 +
 dlls/mshtml/navigate.c |   88 +++++++++++++++++++++++++++++++++++++++---------
 2 files changed, 73 insertions(+), 16 deletions(-)

diff --git a/dlls/mshtml/binding.h b/dlls/mshtml/binding.h
index 892a114..eef6053 100644
--- a/dlls/mshtml/binding.h
+++ b/dlls/mshtml/binding.h
@@ -67,6 +67,7 @@ struct BSCallback {
     ULONG readed;
     DWORD bindf;
     BOOL bindinfo_ready;
+    int bom;
 
     IMoniker *mon;
     IBinding *binding;
diff --git a/dlls/mshtml/navigate.c b/dlls/mshtml/navigate.c
index 3827e47..878117f 100644
--- a/dlls/mshtml/navigate.c
+++ b/dlls/mshtml/navigate.c
@@ -50,6 +50,12 @@ WINE_DEFAULT_DEBUG_CHANNEL(mshtml);
 static const WCHAR emptyW[] = {0};
 static const WCHAR text_htmlW[] = {'t','e','x','t','/','h','t','m','l',0};
 
+enum {
+    BOM_NONE,
+    BOM_UTF8,
+    BOM_UTF16
+};
+
 struct nsProtocolStream {
     nsIInputStream nsIInputStream_iface;
 
@@ -607,6 +613,7 @@ static void init_bscallback(BSCallback *This, const BSCallbackVtbl *vtbl, IMonik
     This->vtbl = vtbl;
     This->ref = 1;
     This->bindf = bindf;
+    This->bom = BOM_NONE;
 
     list_init(&This->entry);
 
@@ -617,11 +624,29 @@ static void init_bscallback(BSCallback *This, const BSCallbackVtbl *vtbl, IMonik
 
 static HRESULT read_stream(BSCallback *This, IStream *stream, void *buf, DWORD size, DWORD *ret_size)
 {
-    DWORD read_size = 0;
+    DWORD read_size = 0, skip=0;
+    BYTE *data = buf;
     HRESULT hres;
 
     hres = IStream_Read(stream, buf, size, &read_size);
-    This->readed += (*ret_size = read_size);
+
+    if(!This->readed && This->bom == BOM_NONE) {
+        if(read_size >= 2 && data[0] == 0xff && data[1] == 0xfe) {
+            This->bom = BOM_UTF16;
+            skip = 2;
+        }else if(read_size >= 3 && data[0] == 0xef && data[1] == 0xbb && data[2] == 0xbf) {
+            This->bom = BOM_UTF8;
+            skip = 3;
+        }
+        if(skip) {
+            read_size -= skip;
+            if(read_size)
+                memmove(data, data+skip, read_size);
+        }
+    }
+
+    This->readed += read_size;
+    *ret_size = read_size;
     return hres;
 }
 
@@ -878,8 +903,8 @@ static BufferBSC *create_bufferbsc(IMoniker *mon)
 HRESULT bind_mon_to_wstr(HTMLInnerWindow *window, IMoniker *mon, WCHAR **ret)
 {
     BufferBSC *bsc = create_bufferbsc(mon);
+    int cp = CP_ACP;
     WCHAR *text;
-    DWORD len;
     HRESULT hres;
 
     hres = start_binding(window, &bsc->bsc, NULL);
@@ -890,14 +915,47 @@ HRESULT bind_mon_to_wstr(HTMLInnerWindow *window, IMoniker *mon, WCHAR **ret)
         return hres;
     }
 
-    len = MultiByteToWideChar(CP_ACP, 0, bsc->buf, bsc->bsc.readed, NULL, 0);
-    text = heap_alloc((len+1)*sizeof(WCHAR));
-    if(text) {
+    if(!bsc->bsc.readed) {
+        *ret = NULL;
+        return S_OK;
+    }
+
+    switch(bsc->bsc.bom) {
+    case BOM_UTF16:
+        if(bsc->bsc.readed % sizeof(WCHAR)) {
+            FIXME("The buffer is not a valid utf16 string\n");
+            hres = E_FAIL;
+            break;
+        }
+
+        text = heap_alloc(bsc->bsc.readed+sizeof(WCHAR));
+        if(!text) {
+            hres = E_OUTOFMEMORY;
+            break;
+        }
+
+        memcpy(text, bsc->buf, bsc->bsc.readed);
+        text[bsc->bsc.readed/sizeof(WCHAR)] = 0;
+        break;
+
+    case BOM_UTF8:
+        cp = CP_UTF8;
+        /* fallthrough */
+    default: {
+        DWORD len;
+
+        len = MultiByteToWideChar(cp, 0, bsc->buf, bsc->bsc.readed, NULL, 0);
+        text = heap_alloc((len+1)*sizeof(WCHAR));
+        if(!text) {
+            hres = E_OUTOFMEMORY;
+            break;
+        }
+
         MultiByteToWideChar(CP_ACP, 0, bsc->buf, bsc->bsc.readed, text, len);
         text[len] = 0;
-    }else {
-        hres = E_OUTOFMEMORY;
     }
+    }
+
     IBindStatusCallback_Release(&bsc->bsc.IBindStatusCallback_iface);
     if(FAILED(hres))
         return hres;
@@ -1076,15 +1134,13 @@ static HRESULT read_stream_data(nsChannelBSC *This, IStream *stream)
         This->nsstream->buf_size += read;
 
         if(first_read) {
-            if(This->nsstream->buf_size >= 2
-               && (BYTE)This->nsstream->buf[0] == 0xff
-               && (BYTE)This->nsstream->buf[1] == 0xfe)
-                This->nschannel->charset = heap_strdupA(UTF16_STR);
-            if(This->nsstream->buf_size >= 3
-               && (BYTE)This->nsstream->buf[0] == 0xef
-               && (BYTE)This->nsstream->buf[1] == 0xbb
-               && (BYTE)This->nsstream->buf[2] == 0xbf)
+            switch(This->bsc.bom) {
+            case BOM_UTF8:
                 This->nschannel->charset = heap_strdupA(UTF8_STR);
+                break;
+            case BOM_UTF16:
+                This->nschannel->charset = heap_strdupA(UTF16_STR);
+            }
 
             if(!This->nschannel->content_type) {
                 WCHAR *mime;




More information about the wine-cvs mailing list