Piotr Caban : urlmon: Reorganize FindMimeFromData implementation.

Alexandre Julliard julliard at winehq.org
Fri Mar 9 12:34:20 CST 2012


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

Author: Piotr Caban <piotr at codeweavers.com>
Date:   Fri Mar  9 12:38:20 2012 +0100

urlmon: Reorganize FindMimeFromData implementation.

---

 dlls/urlmon/urlmon_main.c |  128 ++++++++++++++++++++++++++++----------------
 1 files changed, 81 insertions(+), 47 deletions(-)

diff --git a/dlls/urlmon/urlmon_main.c b/dlls/urlmon/urlmon_main.c
index b02ddd0..836ef12 100644
--- a/dlls/urlmon/urlmon_main.c
+++ b/dlls/urlmon/urlmon_main.c
@@ -626,42 +626,33 @@ static BOOL text_richtext_filter(const BYTE *b, DWORD size)
 
 static BOOL text_html_filter(const BYTE *b, DWORD size)
 {
-    DWORD i;
-
-    if(size < 5)
+    if(size < 6)
         return FALSE;
 
-    for(i = 0; i < size-5; i++) {
-        if((b[i] == '<'
-            && (b[i+1] == 'h' || b[i+1] == 'H')
-            && (b[i+2] == 't' || b[i+2] == 'T')
-            && (b[i+3] == 'm' || b[i+3] == 'M')
-            && (b[i+4] == 'l' || b[i+4] == 'L')) ||
-           (b[i] == '<'
-            && (b[i+1] == 'h' || b[i+1] == 'H')
-            && (b[i+2] == 'e' || b[i+2] == 'E')
-            && (b[i+3] == 'a' || b[i+3] == 'A')
-            && (b[i+4] == 'd' || b[i+4] == 'D')
-            &&  b[i+5] == '>')) return TRUE;
-    }
+    if((b[0] == '<'
+                && (b[1] == 'h' || b[1] == 'H')
+                && (b[2] == 't' || b[2] == 'T')
+                && (b[3] == 'm' || b[3] == 'M')
+                && (b[4] == 'l' || b[4] == 'L'))
+            || (b[0] == '<'
+                && (b[1] == 'h' || b[1] == 'H')
+                && (b[2] == 'e' || b[2] == 'E')
+                && (b[3] == 'a' || b[3] == 'A')
+                && (b[4] == 'd' || b[4] == 'D'))) return TRUE;
 
     return FALSE;
 }
 
 static BOOL text_xml_filter(const BYTE *b, DWORD size)
 {
-    DWORD i;
-
-    if(size < 6)
+    if(size < 7)
         return FALSE;
 
-    for(i=0; i<size-6; i++) {
-        if(b[i] == '<' && b[i+1] == '?'
-            && (b[i+2] == 'x' || b[i+2] == 'X')
-            && (b[i+3] == 'm' || b[i+3] == 'M')
-            && (b[i+4] == 'l' || b[i+4] == 'L')
-            && b[i+5] == ' ') return TRUE;
-    }
+    if(b[0] == '<' && b[1] == '?'
+            && (b[2] == 'x' || b[2] == 'X')
+            && (b[3] == 'm' || b[3] == 'M')
+            && (b[4] == 'l' || b[4] == 'L')
+            && b[5] == ' ') return TRUE;
 
     return FALSE;
 }
@@ -760,12 +751,19 @@ static BOOL application_xmsdownload(const BYTE *b, DWORD size)
     return size > 2 && b[0] == 'M' && b[1] == 'Z';
 }
 
+static inline BOOL is_text_plain_char(BYTE b)
+{
+    if(b < 0x20 && b != '\n' && b != '\r' && b != '\t')
+        return FALSE;
+    return TRUE;
+}
+
 static BOOL text_plain_filter(const BYTE *b, DWORD size)
 {
     const BYTE *ptr;
 
     for(ptr = b; ptr < b+size-1; ptr++) {
-        if(*ptr < 0x20 && *ptr != '\n' && *ptr != '\r' && *ptr != '\t')
+        if(!is_text_plain_char(*ptr))
             return FALSE;
     }
 
@@ -780,7 +778,7 @@ static BOOL application_octet_stream_filter(const BYTE *b, DWORD size)
 static HRESULT find_mime_from_buffer(const BYTE *buf, DWORD size, const WCHAR *proposed_mime, WCHAR **ret_mime)
 {
     LPCWSTR ret = NULL;
-    DWORD len, i;
+    int len, i, any_pos_mime = -1;
 
     static const WCHAR text_htmlW[] = {'t','e','x','t','/','h','t','m','l',0};
     static const WCHAR text_richtextW[] = {'t','e','x','t','/','r','i','c','h','t','e','x','t',0};
@@ -812,9 +810,10 @@ static HRESULT find_mime_from_buffer(const BYTE *buf, DWORD size, const WCHAR *p
     static const struct {
         LPCWSTR mime;
         BOOL (*filter)(const BYTE *,DWORD);
-    } mime_filters[] = {
+    } mime_filters_any_pos[] = {
         {text_htmlW,       text_html_filter},
-        {text_xmlW,        text_xml_filter},
+        {text_xmlW,        text_xml_filter}
+    }, mime_filters[] = {
         {text_richtextW,   text_richtext_filter},
      /* {audio_xaiffW,     audio_xaiff_filter}, */
         {audio_basicW,     audio_basic_filter},
@@ -856,20 +855,47 @@ static HRESULT find_mime_from_buffer(const BYTE *buf, DWORD size, const WCHAR *p
         return S_OK;
     }
 
-    if(proposed_mime && strcmpW(proposed_mime, app_octetstreamW)) {
-        for(i=0; i < sizeof(mime_filters)/sizeof(*mime_filters); i++) {
-            if(!strcmpW(proposed_mime, mime_filters[i].mime))
+    if(proposed_mime && (!strcmpW(proposed_mime, app_octetstreamW)
+                || !strcmpW(proposed_mime, text_plainW)))
+        proposed_mime = NULL;
+
+    if(proposed_mime) {
+        ret = proposed_mime;
+
+        for(i=0; i < sizeof(mime_filters_any_pos)/sizeof(*mime_filters_any_pos); i++) {
+            if(!strcmpW(proposed_mime, mime_filters_any_pos[i].mime)) {
+                any_pos_mime = i;
+                for(len=size; len>0; len--) {
+                    if(mime_filters_any_pos[i].filter(buf+size-len, len))
+                        break;
+                }
+                if(!len)
+                    ret = NULL;
                 break;
+            }
         }
 
-        if(i == sizeof(mime_filters)/sizeof(*mime_filters) || mime_filters[i].filter(buf, size)) {
-            len = strlenW(proposed_mime)+1;
-            *ret_mime = CoTaskMemAlloc(len*sizeof(WCHAR));
-            if(!*ret_mime)
-                return E_OUTOFMEMORY;
+        if(i == sizeof(mime_filters_any_pos)/sizeof(*mime_filters_any_pos)) {
+            for(i=0; i < sizeof(mime_filters)/sizeof(*mime_filters); i++) {
+                if(!strcmpW(proposed_mime, mime_filters[i].mime)) {
+                    if(!mime_filters[i].filter(buf, size))
+                        ret = NULL;
+                    break;
+                }
+            }
+        }
+    }
 
-            memcpy(*ret_mime, proposed_mime, len*sizeof(WCHAR));
-            return S_OK;
+    /* Looks like a bug in native implementation, html and xml mimes
+     * are not looked for if none of them was proposed */
+    if(!proposed_mime || any_pos_mime!=-1) {
+        for(len=size; !ret && len>0; len--) {
+            for(i=0; i<sizeof(mime_filters_any_pos)/sizeof(*mime_filters_any_pos); i++) {
+                if(mime_filters_any_pos[i].filter(buf+size-len, len)) {
+                    ret = mime_filters_any_pos[i].mime;
+                    break;
+                }
+            }
         }
     }
 
@@ -880,16 +906,24 @@ static HRESULT find_mime_from_buffer(const BYTE *buf, DWORD size, const WCHAR *p
         i++;
     }
 
-    TRACE("found %s for %s\n", debugstr_w(ret), debugstr_an((const char*)buf, min(32, size)));
+    if(any_pos_mime!=-1 && ret==text_plainW)
+        ret = mime_filters_any_pos[any_pos_mime].mime;
+    else if(proposed_mime && ret==app_octetstreamW) {
+        for(len=size; ret==app_octetstreamW && len>0; len--) {
+            if(!is_text_plain_char(buf[size-len]))
+                break;
+            for(i=0; i<sizeof(mime_filters_any_pos)/sizeof(*mime_filters_any_pos); i++) {
+                if(mime_filters_any_pos[i].filter(buf+size-len, len)) {
+                    ret = text_plainW;
+                    break;
+                }
+            }
+        }
 
-    if(proposed_mime) {
-        if(i == sizeof(mime_filters)/sizeof(*mime_filters))
+        if(ret == app_octetstreamW)
             ret = proposed_mime;
-
-        /* text/html is a special case */
-        if(!strcmpW(proposed_mime, text_htmlW) && !strcmpW(ret, text_plainW))
-            ret = text_htmlW;
     }
+    TRACE("found %s for %s\n", debugstr_w(ret), debugstr_an((const char*)buf, min(32, size)));
 
     len = strlenW(ret)+1;
     *ret_mime = CoTaskMemAlloc(len*sizeof(WCHAR));




More information about the wine-cvs mailing list