Module: wine Branch: master Commit: 3573c13eaa38f5457b6e69fd88849d72dac2b0f5 URL: http://source.winehq.org/git/wine.git/?a=commit;h=3573c13eaa38f5457b6e69fd88...
Author: Piotr Caban piotr@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));