Commit 3573c13e authored by Piotr Caban's avatar Piotr Caban Committed by Alexandre Julliard

urlmon: Reorganize FindMimeFromData implementation.

parent f0e5fa46
......@@ -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));
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment