Commit c8679593 authored by Damien Fouilleul's avatar Damien Fouilleul

activex: UrlCombine() API is actually buggy, use replacement API already...

activex: UrlCombine() API is actually buggy, use replacement API already present on mozilla (needs loads of testing)
parent 02e15f16
......@@ -638,25 +638,20 @@ HRESULT VLCPlugin::getVLC(libvlc_instance_t** pp_libvlc)
char *psz_mrl = NULL;
if( SysStringLen(_bstr_baseurl) > 0 )
{
DWORD len = INTERNET_MAX_URL_LENGTH;
LPOLESTR abs_url = (LPOLESTR)CoTaskMemAlloc(sizeof(OLECHAR)*len);
if( NULL != abs_url )
{
/*
** if the MRL a relative URL, we should end up with an absolute URL
*/
if( SUCCEEDED(UrlCombineW(_bstr_baseurl, _bstr_mrl, abs_url, &len,
URL_ESCAPE_UNSAFE|URL_PLUGGABLE_PROTOCOL)) )
LPWSTR abs_url = CombineURL(_bstr_baseurl, _bstr_mrl);
if( NULL != abs_url )
{
psz_mrl = CStrFromBSTR(CP_UTF8, abs_url);
psz_mrl = CStrFromWSTR(CP_UTF8, abs_url, wcslen(abs_url));
CoTaskMemFree(abs_url);
}
else
{
psz_mrl = CStrFromBSTR(CP_UTF8, _bstr_mrl);
}
CoTaskMemFree(abs_url);
}
}
else
{
......
......@@ -22,24 +22,26 @@
#include "utils.h"
#include <wchar.h>
#include <wctype.h>
/*
** conversion facilities
*/
using namespace std;
char *CStrFromBSTR(UINT codePage, BSTR bstr)
char *CStrFromWSTR(UINT codePage, LPCWSTR wstr, UINT len)
{
UINT len = SysStringLen(bstr);
if( len > 0 )
{
size_t mblen = WideCharToMultiByte(codePage,
0, bstr, len, NULL, 0, NULL, NULL);
0, wstr, len, NULL, 0, NULL, NULL);
if( mblen > 0 )
{
char *buffer = (char *)CoTaskMemAlloc(mblen+1);
ZeroMemory(buffer, mblen+1);
if( WideCharToMultiByte(codePage, 0, bstr, len, buffer, mblen, NULL, NULL) )
if( WideCharToMultiByte(codePage, 0, wstr, len, buffer, mblen, NULL, NULL) )
{
buffer[mblen] = '\0';
return buffer;
......@@ -49,6 +51,11 @@ char *CStrFromBSTR(UINT codePage, BSTR bstr)
return NULL;
};
char *CStrFromBSTR(UINT codePage, BSTR bstr)
{
return CStrFromWSTR(codePage, bstr, SysStringLen(bstr));
};
BSTR BSTRFromCStr(UINT codePage, LPCSTR s)
{
int wideLen = MultiByteToWideChar(codePage, 0, s, -1, NULL, 0);
......@@ -184,3 +191,156 @@ void HimetricFromDP(HDC hdc, LPPOINT pt, int count)
++pt;
}
};
LPWSTR CombineURL(LPCWSTR baseUrl, LPCWSTR url)
{
if( NULL != url )
{
// check whether URL is already absolute
const wchar_t *end=wcschr(url, L':');
if( (NULL != end) && (end != url) )
{
// validate protocol header
const wchar_t *start = url;
while( start != end ) {
wchar_t c = towlower(*start);
if( (c < L'a') || (c > L'z') )
// not a valid protocol header, assume relative URL
goto relativeurl;
++start;
}
/* we have a protocol header, therefore URL is absolute */
UINT len = wcslen(url);
wchar_t *href = (LPWSTR)CoTaskMemAlloc((len+1)*sizeof(wchar_t));
if( href )
{
memcpy(href, url, len*sizeof(wchar_t));
href[len] = L'\0';
}
return href;
}
relativeurl:
if( baseUrl )
{
size_t baseLen = wcslen(baseUrl);
wchar_t *href = (LPWSTR)CoTaskMemAlloc((baseLen+wcslen(url)+1)*sizeof(wchar_t));
if( href )
{
/* prepend base URL */
wcscpy(href, baseUrl);
/*
** relative url could be empty,
** in which case return base URL
*/
if( L'\0' == *url )
return href;
/*
** locate pathname part of base URL
*/
/* skip over protocol part */
wchar_t *pathstart = wcschr(href, L':');
wchar_t *pathend;
if( pathstart )
{
if( L'/' == *(++pathstart) )
{
if( L'/' == *(++pathstart) )
{
++pathstart;
}
}
/* skip over host part */
pathstart = wcschr(pathstart, L'/');
pathend = href+baseLen;
if( ! pathstart )
{
// no path, add a / past end of url (over '\0')
pathstart = pathend;
*pathstart = L'/';
}
}
else
{
/* baseURL is just a UNIX file path */
if( L'/' != *href )
{
/* baseURL is not an absolute path */
return NULL;
}
pathstart = href;
pathend = href+baseLen;
}
/* relative URL made of an absolute path ? */
if( L'/' == *url )
{
/* replace path completely */
wcscpy(pathstart, url);
return href;
}
/* find last path component and replace it */
while( L'/' != *pathend )
--pathend;
/*
** if relative url path starts with one or more './' or '../',
** factor them out of href so that we return a
** normalized URL
*/
while( pathend > pathstart )
{
const wchar_t *p = url;
if( L'.' != *p )
break;
++p;
if( L'\0' == *p )
{
/* relative url is just '.' */
url = p;
break;
}
if( L'/' == *p )
{
/* relative url starts with './' */
url = ++p;
continue;
}
if( L'.' != *p )
break;
++p;
if( L'\0' == *p )
{
/* relative url is '..' */
}
else
{
if( L'/' != *p )
break;
/* relative url starts with '../' */
++p;
}
url = p;
do
{
--pathend;
}
while( L'/' != *pathend );
}
/* skip over '/' separator */
++pathend;
/* concatenate remaining base URL and relative URL */
wcscpy(pathend, url);
}
return href;
}
}
return NULL;
}
......@@ -28,6 +28,7 @@
#include <vector>
// utilities
extern char *CStrFromWSTR(UINT codePage, LPCWSTR wstr, UINT len);
extern char *CStrFromBSTR(UINT codePage, BSTR bstr);
extern BSTR BSTRFromCStr(UINT codePage, LPCSTR s);
......@@ -41,6 +42,9 @@ extern HDC CreateDevDC(DVTARGETDEVICE *ptd);
extern void DPFromHimetric(HDC hdc, LPPOINT pt, int count);
extern void HimetricFromDP(HDC hdc, LPPOINT pt, int count);
// URL
extern LPWSTR CombineURL(LPCWSTR baseUrl, LPCWSTR url);
/**************************************************************************************************/
/* this function object is used to dereference the iterator into a value */
......
......@@ -1499,25 +1499,20 @@ STDMETHODIMP VLCPlaylist::add(BSTR uri, VARIANT name, VARIANT options, long* ite
char *psz_uri = NULL;
if( SysStringLen(_p_instance->getBaseURL()) > 0 )
{
DWORD len = INTERNET_MAX_URL_LENGTH;
LPOLESTR abs_url = (LPOLESTR)CoTaskMemAlloc(sizeof(OLECHAR)*len);
if( NULL != abs_url )
{
/*
** if the MRL a relative URL, we should end up with an absolute URL
*/
if( SUCCEEDED(UrlCombineW(_p_instance->getBaseURL(), uri, abs_url, &len,
URL_ESCAPE_UNSAFE|URL_PLUGGABLE_PROTOCOL)) )
LPWSTR abs_url = CombineURL(_p_instance->getBaseURL(), uri);
if( NULL != abs_url )
{
psz_uri = CStrFromBSTR(CP_UTF8, abs_url);
psz_uri = CStrFromWSTR(CP_UTF8, abs_url, wcslen(abs_url));
CoTaskMemFree(abs_url);
}
else
{
psz_uri = CStrFromBSTR(CP_UTF8, uri);
}
CoTaskMemFree(abs_url);
}
}
else
{
......
......@@ -1313,10 +1313,11 @@ RuntimeNPObject::InvokeResult LibvlcPlaylistNPObject::invoke(int index, const NP
if( s )
{
url = p_plugin->getAbsoluteURL(s);
if( url )
delete s;
if( ! url )
// what happened ?
return INVOKERESULT_GENERIC_ERROR;
else
// problem with combining url, use argument
url = s;
}
else
return INVOKERESULT_OUT_OF_MEMORY;
......
......@@ -35,6 +35,8 @@
#include "control/npovlc.h"
#include "control/npolibvlc.h"
#include <ctype.h>
/*****************************************************************************
* VlcPlugin constructor and destructor
*****************************************************************************/
......@@ -226,7 +228,8 @@ NPError VlcPlugin::init(int argc, char* const argn[], char* const argv[])
if( psz_target )
{
// get absolute URL from src
psz_target = getAbsoluteURL(psz_target);
char *psz_absurl = getAbsoluteURL(psz_target);
psz_target = psz_absurl ? psz_absurl : strdup(psz_target);
}
/* assign plugin script root class */
......@@ -304,16 +307,18 @@ char *VlcPlugin::getAbsoluteURL(const char *url)
// validate protocol header
const char *start = url;
while( start != end ) {
char c = *start | 0x20;
char c = tolower(*start);
if( (c < 'a') || (c > 'z') )
// not valid protocol header, assume relative URL
break;
goto relativeurl;
++start;
}
/* we have a protocol header, therefore URL is absolute */
return strdup(url);
}
relativeurl:
if( psz_baseURL )
{
size_t baseLen = strlen(psz_baseURL);
......@@ -358,7 +363,12 @@ char *VlcPlugin::getAbsoluteURL(const char *url)
}
else
{
/* baseURL is just a path */
/* baseURL is just a UNIX path */
if( '/' != *href )
{
/* baseURL is not an absolute path */
return NULL;
}
pathstart = href;
pathend = href+baseLen;
}
......@@ -372,7 +382,8 @@ char *VlcPlugin::getAbsoluteURL(const char *url)
}
/* find last path component and replace it */
while( '/' != *pathend) --pathend;
while( '/' != *pathend)
--pathend;
/*
** if relative url path starts with one or more '../',
......@@ -385,17 +396,42 @@ char *VlcPlugin::getAbsoluteURL(const char *url)
if( '.' != *p )
break;
++p;
if( '\0' == *p )
{
/* relative url is just '.' */
url = p;
break;
}
if( '/' == *p )
{
/* relative url starts with './' */
url = ++p;
continue;
}
if( '.' != *p )
break;
++p;
if( '\0' == *p )
{
/* relative url is '..' */
}
else
{
if( '/' != *p )
break;
/* relative url starts with '../' */
++p;
}
url = p;
while( '/' != *pathend ) --pathend;
do
{
--pathend;
}
while( '/' != *pathend );
}
/* skip over '/' separator */
++pathend;
/* concatenate remaining base URL and relative URL */
strcpy(pathend+1, url);
strcpy(pathend, url);
}
return href;
}
......
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