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