2010-03-04 15:24:17 +00:00
|
|
|
/*
|
|
|
|
* Copyright 2010 Jacek Caban for CodeWeavers
|
2010-05-30 10:20:31 +00:00
|
|
|
* Copyright 2010 Thomas Mullaly
|
2010-03-04 15:24:17 +00:00
|
|
|
*
|
|
|
|
* This library is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
|
|
* License as published by the Free Software Foundation; either
|
|
|
|
* version 2.1 of the License, or (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This library is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
* Lesser General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
|
|
* License along with this library; if not, write to the Free Software
|
|
|
|
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
|
|
|
|
*/
|
|
|
|
|
2018-03-23 11:35:23 +00:00
|
|
|
#include <limits.h>
|
|
|
|
|
2010-03-04 15:24:17 +00:00
|
|
|
#include "urlmon_main.h"
|
2018-03-23 11:35:23 +00:00
|
|
|
#include "wine/debug.h"
|
|
|
|
|
|
|
|
#define NO_SHLWAPI_REG
|
|
|
|
#include "shlwapi.h"
|
Finish the Wine sync. These components are not just rc file changes
atl, comctl32, comdlg32, dwmapi, fusion, gdiplus, jscript, mpr, mshtml, msi, msimtf, msxml3, ole32, oleaut32, riched20, shdocvw, shlwapi, urlmon, usp10, version and windowscodecs
Seems to build and boot. /me hides
svn path=/trunk/; revision=48273
2010-07-26 02:26:04 +00:00
|
|
|
|
2018-03-23 11:35:23 +00:00
|
|
|
#include "strsafe.h"
|
2010-12-20 21:29:55 +00:00
|
|
|
|
|
|
|
#define URI_DISPLAY_NO_ABSOLUTE_URI 0x1
|
|
|
|
#define URI_DISPLAY_NO_DEFAULT_PORT_AUTH 0x2
|
|
|
|
|
2010-10-09 21:52:25 +00:00
|
|
|
#define ALLOW_NULL_TERM_SCHEME 0x01
|
|
|
|
#define ALLOW_NULL_TERM_USER_NAME 0x02
|
|
|
|
#define ALLOW_NULL_TERM_PASSWORD 0x04
|
|
|
|
#define ALLOW_BRACKETLESS_IP_LITERAL 0x08
|
|
|
|
#define SKIP_IP_FUTURE_CHECK 0x10
|
|
|
|
#define IGNORE_PORT_DELIMITER 0x20
|
Finish the Wine sync. These components are not just rc file changes
atl, comctl32, comdlg32, dwmapi, fusion, gdiplus, jscript, mpr, mshtml, msi, msimtf, msxml3, ole32, oleaut32, riched20, shdocvw, shlwapi, urlmon, usp10, version and windowscodecs
Seems to build and boot. /me hides
svn path=/trunk/; revision=48273
2010-07-26 02:26:04 +00:00
|
|
|
|
2010-12-20 21:29:55 +00:00
|
|
|
#define RAW_URI_FORCE_PORT_DISP 0x1
|
|
|
|
#define RAW_URI_CONVERT_TO_DOS_PATH 0x2
|
|
|
|
|
|
|
|
#define COMBINE_URI_FORCE_FLAG_USE 0x1
|
|
|
|
|
2018-03-23 11:35:23 +00:00
|
|
|
WINE_DEFAULT_DEBUG_CHANNEL(urlmon);
|
|
|
|
|
2010-10-09 21:52:25 +00:00
|
|
|
static const IID IID_IUriObj = {0x4b364760,0x9f51,0x11df,{0x98,0x1c,0x08,0x00,0x20,0x0c,0x9a,0x66}};
|
|
|
|
|
2010-03-04 15:24:17 +00:00
|
|
|
typedef struct {
|
2010-12-20 21:29:55 +00:00
|
|
|
IUri IUri_iface;
|
|
|
|
IUriBuilderFactory IUriBuilderFactory_iface;
|
2013-03-22 14:29:11 +00:00
|
|
|
IPersistStream IPersistStream_iface;
|
|
|
|
IMarshal IMarshal_iface;
|
2010-12-20 21:29:55 +00:00
|
|
|
|
2010-03-04 15:24:17 +00:00
|
|
|
LONG ref;
|
Finish the Wine sync. These components are not just rc file changes
atl, comctl32, comdlg32, dwmapi, fusion, gdiplus, jscript, mpr, mshtml, msi, msimtf, msxml3, ole32, oleaut32, riched20, shdocvw, shlwapi, urlmon, usp10, version and windowscodecs
Seems to build and boot. /me hides
svn path=/trunk/; revision=48273
2010-07-26 02:26:04 +00:00
|
|
|
|
|
|
|
BSTR raw_uri;
|
|
|
|
|
|
|
|
/* Information about the canonicalized URI's buffer. */
|
|
|
|
WCHAR *canon_uri;
|
|
|
|
DWORD canon_size;
|
|
|
|
DWORD canon_len;
|
2010-12-20 21:29:55 +00:00
|
|
|
BOOL display_modifiers;
|
2010-10-09 21:52:25 +00:00
|
|
|
DWORD create_flags;
|
Finish the Wine sync. These components are not just rc file changes
atl, comctl32, comdlg32, dwmapi, fusion, gdiplus, jscript, mpr, mshtml, msi, msimtf, msxml3, ole32, oleaut32, riched20, shdocvw, shlwapi, urlmon, usp10, version and windowscodecs
Seems to build and boot. /me hides
svn path=/trunk/; revision=48273
2010-07-26 02:26:04 +00:00
|
|
|
|
|
|
|
INT scheme_start;
|
|
|
|
DWORD scheme_len;
|
|
|
|
URL_SCHEME scheme_type;
|
|
|
|
|
|
|
|
INT userinfo_start;
|
|
|
|
DWORD userinfo_len;
|
|
|
|
INT userinfo_split;
|
|
|
|
|
|
|
|
INT host_start;
|
|
|
|
DWORD host_len;
|
|
|
|
Uri_HOST_TYPE host_type;
|
2010-10-09 21:52:25 +00:00
|
|
|
|
2010-12-20 21:29:55 +00:00
|
|
|
INT port_offset;
|
|
|
|
DWORD port;
|
2010-10-09 21:52:25 +00:00
|
|
|
BOOL has_port;
|
|
|
|
|
|
|
|
INT authority_start;
|
|
|
|
DWORD authority_len;
|
|
|
|
|
|
|
|
INT domain_offset;
|
|
|
|
|
|
|
|
INT path_start;
|
|
|
|
DWORD path_len;
|
|
|
|
INT extension_offset;
|
|
|
|
|
|
|
|
INT query_start;
|
|
|
|
DWORD query_len;
|
|
|
|
|
|
|
|
INT fragment_start;
|
|
|
|
DWORD fragment_len;
|
2010-03-04 15:24:17 +00:00
|
|
|
} Uri;
|
|
|
|
|
2010-03-21 17:43:25 +00:00
|
|
|
typedef struct {
|
2010-12-20 21:29:55 +00:00
|
|
|
IUriBuilder IUriBuilder_iface;
|
2010-03-21 17:43:25 +00:00
|
|
|
LONG ref;
|
2010-10-09 21:52:25 +00:00
|
|
|
|
|
|
|
Uri *uri;
|
|
|
|
DWORD modified_props;
|
|
|
|
|
|
|
|
WCHAR *fragment;
|
|
|
|
DWORD fragment_len;
|
|
|
|
|
|
|
|
WCHAR *host;
|
|
|
|
DWORD host_len;
|
|
|
|
|
|
|
|
WCHAR *password;
|
|
|
|
DWORD password_len;
|
|
|
|
|
|
|
|
WCHAR *path;
|
|
|
|
DWORD path_len;
|
|
|
|
|
|
|
|
BOOL has_port;
|
|
|
|
DWORD port;
|
|
|
|
|
|
|
|
WCHAR *query;
|
|
|
|
DWORD query_len;
|
|
|
|
|
|
|
|
WCHAR *scheme;
|
|
|
|
DWORD scheme_len;
|
|
|
|
|
|
|
|
WCHAR *username;
|
|
|
|
DWORD username_len;
|
2010-03-21 17:43:25 +00:00
|
|
|
} UriBuilder;
|
|
|
|
|
2010-10-09 21:52:25 +00:00
|
|
|
typedef struct {
|
|
|
|
const WCHAR *str;
|
|
|
|
DWORD len;
|
|
|
|
} h16;
|
|
|
|
|
|
|
|
typedef struct {
|
|
|
|
/* IPv6 addresses can hold up to 8 h16 components. */
|
|
|
|
h16 components[8];
|
|
|
|
DWORD h16_count;
|
|
|
|
|
|
|
|
/* An IPv6 can have 1 elision ("::"). */
|
|
|
|
const WCHAR *elision;
|
|
|
|
|
|
|
|
/* An IPv6 can contain 1 IPv4 address as the last 32bits of the address. */
|
|
|
|
const WCHAR *ipv4;
|
|
|
|
DWORD ipv4_len;
|
|
|
|
|
|
|
|
INT components_size;
|
|
|
|
INT elision_size;
|
|
|
|
} ipv6_address;
|
|
|
|
|
Finish the Wine sync. These components are not just rc file changes
atl, comctl32, comdlg32, dwmapi, fusion, gdiplus, jscript, mpr, mshtml, msi, msimtf, msxml3, ole32, oleaut32, riched20, shdocvw, shlwapi, urlmon, usp10, version and windowscodecs
Seems to build and boot. /me hides
svn path=/trunk/; revision=48273
2010-07-26 02:26:04 +00:00
|
|
|
typedef struct {
|
|
|
|
BSTR uri;
|
|
|
|
|
|
|
|
BOOL is_relative;
|
|
|
|
BOOL is_opaque;
|
|
|
|
BOOL has_implicit_scheme;
|
|
|
|
BOOL has_implicit_ip;
|
|
|
|
UINT implicit_ipv4;
|
2013-03-22 14:29:11 +00:00
|
|
|
BOOL must_have_path;
|
Finish the Wine sync. These components are not just rc file changes
atl, comctl32, comdlg32, dwmapi, fusion, gdiplus, jscript, mpr, mshtml, msi, msimtf, msxml3, ole32, oleaut32, riched20, shdocvw, shlwapi, urlmon, usp10, version and windowscodecs
Seems to build and boot. /me hides
svn path=/trunk/; revision=48273
2010-07-26 02:26:04 +00:00
|
|
|
|
|
|
|
const WCHAR *scheme;
|
|
|
|
DWORD scheme_len;
|
|
|
|
URL_SCHEME scheme_type;
|
|
|
|
|
2010-10-09 21:52:25 +00:00
|
|
|
const WCHAR *username;
|
|
|
|
DWORD username_len;
|
|
|
|
|
|
|
|
const WCHAR *password;
|
|
|
|
DWORD password_len;
|
Finish the Wine sync. These components are not just rc file changes
atl, comctl32, comdlg32, dwmapi, fusion, gdiplus, jscript, mpr, mshtml, msi, msimtf, msxml3, ole32, oleaut32, riched20, shdocvw, shlwapi, urlmon, usp10, version and windowscodecs
Seems to build and boot. /me hides
svn path=/trunk/; revision=48273
2010-07-26 02:26:04 +00:00
|
|
|
|
|
|
|
const WCHAR *host;
|
|
|
|
DWORD host_len;
|
|
|
|
Uri_HOST_TYPE host_type;
|
2010-10-09 21:52:25 +00:00
|
|
|
|
|
|
|
BOOL has_ipv6;
|
|
|
|
ipv6_address ipv6_address;
|
|
|
|
|
|
|
|
BOOL has_port;
|
|
|
|
const WCHAR *port;
|
|
|
|
DWORD port_len;
|
|
|
|
DWORD port_value;
|
|
|
|
|
|
|
|
const WCHAR *path;
|
|
|
|
DWORD path_len;
|
|
|
|
|
|
|
|
const WCHAR *query;
|
|
|
|
DWORD query_len;
|
|
|
|
|
|
|
|
const WCHAR *fragment;
|
|
|
|
DWORD fragment_len;
|
Finish the Wine sync. These components are not just rc file changes
atl, comctl32, comdlg32, dwmapi, fusion, gdiplus, jscript, mpr, mshtml, msi, msimtf, msxml3, ole32, oleaut32, riched20, shdocvw, shlwapi, urlmon, usp10, version and windowscodecs
Seems to build and boot. /me hides
svn path=/trunk/; revision=48273
2010-07-26 02:26:04 +00:00
|
|
|
} parse_data;
|
|
|
|
|
|
|
|
static const CHAR hexDigits[] = "0123456789ABCDEF";
|
|
|
|
|
|
|
|
/* List of scheme types/scheme names that are recognized by the IUri interface as of IE 7. */
|
|
|
|
static const struct {
|
|
|
|
URL_SCHEME scheme;
|
|
|
|
WCHAR scheme_name[16];
|
|
|
|
} recognized_schemes[] = {
|
|
|
|
{URL_SCHEME_FTP, {'f','t','p',0}},
|
|
|
|
{URL_SCHEME_HTTP, {'h','t','t','p',0}},
|
|
|
|
{URL_SCHEME_GOPHER, {'g','o','p','h','e','r',0}},
|
|
|
|
{URL_SCHEME_MAILTO, {'m','a','i','l','t','o',0}},
|
|
|
|
{URL_SCHEME_NEWS, {'n','e','w','s',0}},
|
|
|
|
{URL_SCHEME_NNTP, {'n','n','t','p',0}},
|
|
|
|
{URL_SCHEME_TELNET, {'t','e','l','n','e','t',0}},
|
|
|
|
{URL_SCHEME_WAIS, {'w','a','i','s',0}},
|
|
|
|
{URL_SCHEME_FILE, {'f','i','l','e',0}},
|
|
|
|
{URL_SCHEME_MK, {'m','k',0}},
|
|
|
|
{URL_SCHEME_HTTPS, {'h','t','t','p','s',0}},
|
|
|
|
{URL_SCHEME_SHELL, {'s','h','e','l','l',0}},
|
|
|
|
{URL_SCHEME_SNEWS, {'s','n','e','w','s',0}},
|
|
|
|
{URL_SCHEME_LOCAL, {'l','o','c','a','l',0}},
|
|
|
|
{URL_SCHEME_JAVASCRIPT, {'j','a','v','a','s','c','r','i','p','t',0}},
|
|
|
|
{URL_SCHEME_VBSCRIPT, {'v','b','s','c','r','i','p','t',0}},
|
|
|
|
{URL_SCHEME_ABOUT, {'a','b','o','u','t',0}},
|
|
|
|
{URL_SCHEME_RES, {'r','e','s',0}},
|
|
|
|
{URL_SCHEME_MSSHELLROOTED, {'m','s','-','s','h','e','l','l','-','r','o','o','t','e','d',0}},
|
|
|
|
{URL_SCHEME_MSSHELLIDLIST, {'m','s','-','s','h','e','l','l','-','i','d','l','i','s','t',0}},
|
|
|
|
{URL_SCHEME_MSHELP, {'h','c','p',0}},
|
|
|
|
{URL_SCHEME_WILDCARD, {'*',0}}
|
|
|
|
};
|
|
|
|
|
2010-10-09 21:52:25 +00:00
|
|
|
/* List of default ports Windows recognizes. */
|
|
|
|
static const struct {
|
|
|
|
URL_SCHEME scheme;
|
|
|
|
USHORT port;
|
|
|
|
} default_ports[] = {
|
|
|
|
{URL_SCHEME_FTP, 21},
|
|
|
|
{URL_SCHEME_HTTP, 80},
|
|
|
|
{URL_SCHEME_GOPHER, 70},
|
|
|
|
{URL_SCHEME_NNTP, 119},
|
|
|
|
{URL_SCHEME_TELNET, 23},
|
|
|
|
{URL_SCHEME_WAIS, 210},
|
|
|
|
{URL_SCHEME_HTTPS, 443},
|
|
|
|
};
|
|
|
|
|
2013-03-22 14:29:11 +00:00
|
|
|
/* List of 3-character top level domain names Windows seems to recognize.
|
2010-10-09 21:52:25 +00:00
|
|
|
* There might be more, but, these are the only ones I've found so far.
|
|
|
|
*/
|
|
|
|
static const struct {
|
|
|
|
WCHAR tld_name[4];
|
|
|
|
} recognized_tlds[] = {
|
|
|
|
{{'c','o','m',0}},
|
|
|
|
{{'e','d','u',0}},
|
|
|
|
{{'g','o','v',0}},
|
|
|
|
{{'i','n','t',0}},
|
|
|
|
{{'m','i','l',0}},
|
|
|
|
{{'n','e','t',0}},
|
|
|
|
{{'o','r','g',0}}
|
|
|
|
};
|
|
|
|
|
|
|
|
static Uri *get_uri_obj(IUri *uri)
|
|
|
|
{
|
|
|
|
Uri *ret;
|
|
|
|
HRESULT hres;
|
|
|
|
|
|
|
|
hres = IUri_QueryInterface(uri, &IID_IUriObj, (void**)&ret);
|
|
|
|
return SUCCEEDED(hres) ? ret : NULL;
|
|
|
|
}
|
|
|
|
|
Finish the Wine sync. These components are not just rc file changes
atl, comctl32, comdlg32, dwmapi, fusion, gdiplus, jscript, mpr, mshtml, msi, msimtf, msxml3, ole32, oleaut32, riched20, shdocvw, shlwapi, urlmon, usp10, version and windowscodecs
Seems to build and boot. /me hides
svn path=/trunk/; revision=48273
2010-07-26 02:26:04 +00:00
|
|
|
static inline BOOL is_alpha(WCHAR val) {
|
2011-06-05 21:29:41 +00:00
|
|
|
return ((val >= 'a' && val <= 'z') || (val >= 'A' && val <= 'Z'));
|
Finish the Wine sync. These components are not just rc file changes
atl, comctl32, comdlg32, dwmapi, fusion, gdiplus, jscript, mpr, mshtml, msi, msimtf, msxml3, ole32, oleaut32, riched20, shdocvw, shlwapi, urlmon, usp10, version and windowscodecs
Seems to build and boot. /me hides
svn path=/trunk/; revision=48273
2010-07-26 02:26:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static inline BOOL is_num(WCHAR val) {
|
2011-06-05 21:29:41 +00:00
|
|
|
return (val >= '0' && val <= '9');
|
Finish the Wine sync. These components are not just rc file changes
atl, comctl32, comdlg32, dwmapi, fusion, gdiplus, jscript, mpr, mshtml, msi, msimtf, msxml3, ole32, oleaut32, riched20, shdocvw, shlwapi, urlmon, usp10, version and windowscodecs
Seems to build and boot. /me hides
svn path=/trunk/; revision=48273
2010-07-26 02:26:04 +00:00
|
|
|
}
|
|
|
|
|
2010-10-09 21:52:25 +00:00
|
|
|
static inline BOOL is_drive_path(const WCHAR *str) {
|
|
|
|
return (is_alpha(str[0]) && (str[1] == ':' || str[1] == '|'));
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline BOOL is_unc_path(const WCHAR *str) {
|
2013-03-22 14:29:11 +00:00
|
|
|
return (str[0] == '\\' && str[1] == '\\');
|
2010-10-09 21:52:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static inline BOOL is_forbidden_dos_path_char(WCHAR val) {
|
|
|
|
return (val == '>' || val == '<' || val == '\"');
|
|
|
|
}
|
|
|
|
|
Finish the Wine sync. These components are not just rc file changes
atl, comctl32, comdlg32, dwmapi, fusion, gdiplus, jscript, mpr, mshtml, msi, msimtf, msxml3, ole32, oleaut32, riched20, shdocvw, shlwapi, urlmon, usp10, version and windowscodecs
Seems to build and boot. /me hides
svn path=/trunk/; revision=48273
2010-07-26 02:26:04 +00:00
|
|
|
/* A URI is implicitly a file path if it begins with
|
2013-03-22 14:29:11 +00:00
|
|
|
* a drive letter (e.g. X:) or starts with "\\" (UNC path).
|
Finish the Wine sync. These components are not just rc file changes
atl, comctl32, comdlg32, dwmapi, fusion, gdiplus, jscript, mpr, mshtml, msi, msimtf, msxml3, ole32, oleaut32, riched20, shdocvw, shlwapi, urlmon, usp10, version and windowscodecs
Seems to build and boot. /me hides
svn path=/trunk/; revision=48273
2010-07-26 02:26:04 +00:00
|
|
|
*/
|
|
|
|
static inline BOOL is_implicit_file_path(const WCHAR *str) {
|
2010-10-09 21:52:25 +00:00
|
|
|
return (is_unc_path(str) || (is_alpha(str[0]) && str[1] == ':'));
|
Finish the Wine sync. These components are not just rc file changes
atl, comctl32, comdlg32, dwmapi, fusion, gdiplus, jscript, mpr, mshtml, msi, msimtf, msxml3, ole32, oleaut32, riched20, shdocvw, shlwapi, urlmon, usp10, version and windowscodecs
Seems to build and boot. /me hides
svn path=/trunk/; revision=48273
2010-07-26 02:26:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Checks if the URI is a hierarchical URI. A hierarchical
|
|
|
|
* URI is one that has "//" after the scheme.
|
|
|
|
*/
|
|
|
|
static BOOL check_hierarchical(const WCHAR **ptr) {
|
|
|
|
const WCHAR *start = *ptr;
|
|
|
|
|
|
|
|
if(**ptr != '/')
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
++(*ptr);
|
|
|
|
if(**ptr != '/') {
|
|
|
|
*ptr = start;
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
++(*ptr);
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~" */
|
|
|
|
static inline BOOL is_unreserved(WCHAR val) {
|
|
|
|
return (is_alpha(val) || is_num(val) || val == '-' || val == '.' ||
|
|
|
|
val == '_' || val == '~');
|
|
|
|
}
|
|
|
|
|
|
|
|
/* sub-delims = "!" / "$" / "&" / "'" / "(" / ")"
|
|
|
|
* / "*" / "+" / "," / ";" / "="
|
|
|
|
*/
|
|
|
|
static inline BOOL is_subdelim(WCHAR val) {
|
|
|
|
return (val == '!' || val == '$' || val == '&' ||
|
|
|
|
val == '\'' || val == '(' || val == ')' ||
|
|
|
|
val == '*' || val == '+' || val == ',' ||
|
|
|
|
val == ';' || val == '=');
|
|
|
|
}
|
|
|
|
|
|
|
|
/* gen-delims = ":" / "/" / "?" / "#" / "[" / "]" / "@" */
|
|
|
|
static inline BOOL is_gendelim(WCHAR val) {
|
|
|
|
return (val == ':' || val == '/' || val == '?' ||
|
|
|
|
val == '#' || val == '[' || val == ']' ||
|
|
|
|
val == '@');
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Characters that delimit the end of the authority
|
|
|
|
* section of a URI. Sometimes a '\\' is considered
|
2013-03-22 14:29:11 +00:00
|
|
|
* an authority delimiter.
|
Finish the Wine sync. These components are not just rc file changes
atl, comctl32, comdlg32, dwmapi, fusion, gdiplus, jscript, mpr, mshtml, msi, msimtf, msxml3, ole32, oleaut32, riched20, shdocvw, shlwapi, urlmon, usp10, version and windowscodecs
Seems to build and boot. /me hides
svn path=/trunk/; revision=48273
2010-07-26 02:26:04 +00:00
|
|
|
*/
|
|
|
|
static inline BOOL is_auth_delim(WCHAR val, BOOL acceptSlash) {
|
|
|
|
return (val == '#' || val == '/' || val == '?' ||
|
|
|
|
val == '\0' || (acceptSlash && val == '\\'));
|
|
|
|
}
|
|
|
|
|
|
|
|
/* reserved = gen-delims / sub-delims */
|
|
|
|
static inline BOOL is_reserved(WCHAR val) {
|
|
|
|
return (is_subdelim(val) || is_gendelim(val));
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline BOOL is_hexdigit(WCHAR val) {
|
|
|
|
return ((val >= 'a' && val <= 'f') ||
|
|
|
|
(val >= 'A' && val <= 'F') ||
|
|
|
|
(val >= '0' && val <= '9'));
|
|
|
|
}
|
|
|
|
|
2014-09-25 15:39:47 +00:00
|
|
|
static inline BOOL is_path_delim(URL_SCHEME scheme, WCHAR val) {
|
|
|
|
return (!val || (val == '#' && scheme != URL_SCHEME_FILE) || val == '?');
|
2010-10-09 21:52:25 +00:00
|
|
|
}
|
|
|
|
|
2011-06-05 21:29:41 +00:00
|
|
|
static inline BOOL is_slash(WCHAR c)
|
|
|
|
{
|
|
|
|
return c == '/' || c == '\\';
|
|
|
|
}
|
|
|
|
|
2018-03-23 11:35:23 +00:00
|
|
|
static inline BOOL is_ascii(WCHAR c)
|
|
|
|
{
|
|
|
|
return c < 0x80;
|
|
|
|
}
|
|
|
|
|
2010-12-20 21:29:55 +00:00
|
|
|
static BOOL is_default_port(URL_SCHEME scheme, DWORD port) {
|
|
|
|
DWORD i;
|
|
|
|
|
2019-02-04 12:04:30 +00:00
|
|
|
for(i = 0; i < ARRAY_SIZE(default_ports); ++i) {
|
2010-12-20 21:29:55 +00:00
|
|
|
if(default_ports[i].scheme == scheme && default_ports[i].port)
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
2010-10-09 21:52:25 +00:00
|
|
|
/* List of schemes types Windows seems to expect to be hierarchical. */
|
|
|
|
static inline BOOL is_hierarchical_scheme(URL_SCHEME type) {
|
|
|
|
return(type == URL_SCHEME_HTTP || type == URL_SCHEME_FTP ||
|
|
|
|
type == URL_SCHEME_GOPHER || type == URL_SCHEME_NNTP ||
|
|
|
|
type == URL_SCHEME_TELNET || type == URL_SCHEME_WAIS ||
|
|
|
|
type == URL_SCHEME_FILE || type == URL_SCHEME_HTTPS ||
|
|
|
|
type == URL_SCHEME_RES);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Checks if 'flags' contains an invalid combination of Uri_CREATE flags. */
|
|
|
|
static inline BOOL has_invalid_flag_combination(DWORD flags) {
|
|
|
|
return((flags & Uri_CREATE_DECODE_EXTRA_INFO && flags & Uri_CREATE_NO_DECODE_EXTRA_INFO) ||
|
|
|
|
(flags & Uri_CREATE_CANONICALIZE && flags & Uri_CREATE_NO_CANONICALIZE) ||
|
|
|
|
(flags & Uri_CREATE_CRACK_UNKNOWN_SCHEMES && flags & Uri_CREATE_NO_CRACK_UNKNOWN_SCHEMES) ||
|
|
|
|
(flags & Uri_CREATE_PRE_PROCESS_HTML_URI && flags & Uri_CREATE_NO_PRE_PROCESS_HTML_URI) ||
|
|
|
|
(flags & Uri_CREATE_IE_SETTINGS && flags & Uri_CREATE_NO_IE_SETTINGS));
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Applies each default Uri_CREATE flags to 'flags' if it
|
|
|
|
* doesn't cause a flag conflict.
|
|
|
|
*/
|
|
|
|
static void apply_default_flags(DWORD *flags) {
|
|
|
|
if(!(*flags & Uri_CREATE_NO_CANONICALIZE))
|
|
|
|
*flags |= Uri_CREATE_CANONICALIZE;
|
|
|
|
if(!(*flags & Uri_CREATE_NO_DECODE_EXTRA_INFO))
|
|
|
|
*flags |= Uri_CREATE_DECODE_EXTRA_INFO;
|
|
|
|
if(!(*flags & Uri_CREATE_NO_CRACK_UNKNOWN_SCHEMES))
|
|
|
|
*flags |= Uri_CREATE_CRACK_UNKNOWN_SCHEMES;
|
|
|
|
if(!(*flags & Uri_CREATE_NO_PRE_PROCESS_HTML_URI))
|
|
|
|
*flags |= Uri_CREATE_PRE_PROCESS_HTML_URI;
|
|
|
|
if(!(*flags & Uri_CREATE_IE_SETTINGS))
|
|
|
|
*flags |= Uri_CREATE_NO_IE_SETTINGS;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Determines if the URI is hierarchical using the information already parsed into
|
|
|
|
* data and using the current location of parsing in the URI string.
|
|
|
|
*
|
2013-03-22 14:29:11 +00:00
|
|
|
* Windows considers a URI hierarchical if one of the following is true:
|
2010-10-09 21:52:25 +00:00
|
|
|
* A.) It's a wildcard scheme.
|
|
|
|
* B.) It's an implicit file scheme.
|
|
|
|
* C.) It's a known hierarchical scheme and it has two '\\' after the scheme name.
|
|
|
|
* (the '\\' will be converted into "//" during canonicalization).
|
2013-03-22 14:29:11 +00:00
|
|
|
* D.) "//" appears after the scheme name (or at the beginning if no scheme is given).
|
2010-10-09 21:52:25 +00:00
|
|
|
*/
|
|
|
|
static inline BOOL is_hierarchical_uri(const WCHAR **ptr, const parse_data *data) {
|
|
|
|
const WCHAR *start = *ptr;
|
|
|
|
|
|
|
|
if(data->scheme_type == URL_SCHEME_WILDCARD)
|
|
|
|
return TRUE;
|
|
|
|
else if(data->scheme_type == URL_SCHEME_FILE && data->has_implicit_scheme)
|
|
|
|
return TRUE;
|
|
|
|
else if(is_hierarchical_scheme(data->scheme_type) && (*ptr)[0] == '\\' && (*ptr)[1] == '\\') {
|
|
|
|
*ptr += 2;
|
|
|
|
return TRUE;
|
2013-09-28 15:08:52 +00:00
|
|
|
} else if(data->scheme_type != URL_SCHEME_MAILTO && check_hierarchical(ptr))
|
2010-10-09 21:52:25 +00:00
|
|
|
return TRUE;
|
|
|
|
|
|
|
|
*ptr = start;
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Computes the size of the given IPv6 address.
|
2013-03-22 14:29:11 +00:00
|
|
|
* Each h16 component is 16 bits. If there is an IPv4 address, it's
|
|
|
|
* 32 bits. If there's an elision it can be 16 to 128 bits, depending
|
2010-10-09 21:52:25 +00:00
|
|
|
* on the number of other components.
|
|
|
|
*
|
|
|
|
* Modeled after google-url's CheckIPv6ComponentsSize function
|
|
|
|
*/
|
|
|
|
static void compute_ipv6_comps_size(ipv6_address *address) {
|
|
|
|
address->components_size = address->h16_count * 2;
|
|
|
|
|
|
|
|
if(address->ipv4)
|
|
|
|
/* IPv4 address is 4 bytes. */
|
|
|
|
address->components_size += 4;
|
|
|
|
|
|
|
|
if(address->elision) {
|
|
|
|
/* An elision can be anywhere from 2 bytes up to 16 bytes.
|
2013-03-22 14:29:11 +00:00
|
|
|
* Its size depends on the size of the h16 and IPv4 components.
|
2010-10-09 21:52:25 +00:00
|
|
|
*/
|
|
|
|
address->elision_size = 16 - address->components_size;
|
|
|
|
if(address->elision_size < 2)
|
|
|
|
address->elision_size = 2;
|
|
|
|
} else
|
|
|
|
address->elision_size = 0;
|
|
|
|
}
|
|
|
|
|
Finish the Wine sync. These components are not just rc file changes
atl, comctl32, comdlg32, dwmapi, fusion, gdiplus, jscript, mpr, mshtml, msi, msimtf, msxml3, ole32, oleaut32, riched20, shdocvw, shlwapi, urlmon, usp10, version and windowscodecs
Seems to build and boot. /me hides
svn path=/trunk/; revision=48273
2010-07-26 02:26:04 +00:00
|
|
|
/* Taken from dlls/jscript/lex.c */
|
|
|
|
static int hex_to_int(WCHAR val) {
|
|
|
|
if(val >= '0' && val <= '9')
|
|
|
|
return val - '0';
|
|
|
|
else if(val >= 'a' && val <= 'f')
|
|
|
|
return val - 'a' + 10;
|
|
|
|
else if(val >= 'A' && val <= 'F')
|
|
|
|
return val - 'A' + 10;
|
|
|
|
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Helper function for converting a percent encoded string
|
|
|
|
* representation of a WCHAR value into its actual WCHAR value. If
|
|
|
|
* the two characters following the '%' aren't valid hex values then
|
|
|
|
* this function returns the NULL character.
|
|
|
|
*
|
2013-03-22 14:29:11 +00:00
|
|
|
* E.g.
|
Finish the Wine sync. These components are not just rc file changes
atl, comctl32, comdlg32, dwmapi, fusion, gdiplus, jscript, mpr, mshtml, msi, msimtf, msxml3, ole32, oleaut32, riched20, shdocvw, shlwapi, urlmon, usp10, version and windowscodecs
Seems to build and boot. /me hides
svn path=/trunk/; revision=48273
2010-07-26 02:26:04 +00:00
|
|
|
* "%2E" will result in '.' being returned by this function.
|
|
|
|
*/
|
|
|
|
static WCHAR decode_pct_val(const WCHAR *ptr) {
|
|
|
|
WCHAR ret = '\0';
|
|
|
|
|
|
|
|
if(*ptr == '%' && is_hexdigit(*(ptr + 1)) && is_hexdigit(*(ptr + 2))) {
|
|
|
|
INT a = hex_to_int(*(ptr + 1));
|
|
|
|
INT b = hex_to_int(*(ptr + 2));
|
|
|
|
|
|
|
|
ret = a << 4;
|
|
|
|
ret += b;
|
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Helper function for percent encoding a given character
|
|
|
|
* and storing the encoded value into a given buffer (dest).
|
|
|
|
*
|
|
|
|
* It's up to the calling function to ensure that there is
|
|
|
|
* at least enough space in 'dest' for the percent encoded
|
|
|
|
* value to be stored (so dest + 3 spaces available).
|
|
|
|
*/
|
|
|
|
static inline void pct_encode_val(WCHAR val, WCHAR *dest) {
|
|
|
|
dest[0] = '%';
|
|
|
|
dest[1] = hexDigits[(val >> 4) & 0xf];
|
|
|
|
dest[2] = hexDigits[val & 0xf];
|
|
|
|
}
|
|
|
|
|
2010-10-09 21:52:25 +00:00
|
|
|
/* Attempts to parse the domain name from the host.
|
|
|
|
*
|
|
|
|
* This function also includes the Top-level Domain (TLD) name
|
|
|
|
* of the host when it tries to find the domain name. If it finds
|
|
|
|
* a valid domain name it will assign 'domain_start' the offset
|
|
|
|
* into 'host' where the domain name starts.
|
|
|
|
*
|
2011-06-05 21:29:41 +00:00
|
|
|
* It's implied that if there is a domain name its range is:
|
2010-10-09 21:52:25 +00:00
|
|
|
* [host+domain_start, host+host_len).
|
|
|
|
*/
|
2011-06-05 21:29:41 +00:00
|
|
|
void find_domain_name(const WCHAR *host, DWORD host_len,
|
2010-10-09 21:52:25 +00:00
|
|
|
INT *domain_start) {
|
|
|
|
const WCHAR *last_tld, *sec_last_tld, *end;
|
|
|
|
|
|
|
|
end = host+host_len-1;
|
|
|
|
|
|
|
|
*domain_start = -1;
|
|
|
|
|
|
|
|
/* There has to be at least enough room for a '.' followed by a
|
2013-03-22 14:29:11 +00:00
|
|
|
* 3-character TLD for a domain to even exist in the host name.
|
2010-10-09 21:52:25 +00:00
|
|
|
*/
|
|
|
|
if(host_len < 4)
|
|
|
|
return;
|
|
|
|
|
2011-06-05 21:29:41 +00:00
|
|
|
last_tld = memrchrW(host, '.', host_len);
|
2010-10-09 21:52:25 +00:00
|
|
|
if(!last_tld)
|
|
|
|
/* http://hostname -> has no domain name. */
|
|
|
|
return;
|
|
|
|
|
2011-06-05 21:29:41 +00:00
|
|
|
sec_last_tld = memrchrW(host, '.', last_tld-host);
|
2010-10-09 21:52:25 +00:00
|
|
|
if(!sec_last_tld) {
|
|
|
|
/* If the '.' is at the beginning of the host there
|
|
|
|
* has to be at least 3 characters in the TLD for it
|
|
|
|
* to be valid.
|
|
|
|
* Ex: .com -> .com as the domain name.
|
|
|
|
* .co -> has no domain name.
|
|
|
|
*/
|
|
|
|
if(last_tld-host == 0) {
|
|
|
|
if(end-(last_tld-1) < 3)
|
|
|
|
return;
|
|
|
|
} else if(last_tld-host == 3) {
|
|
|
|
DWORD i;
|
|
|
|
|
2013-03-22 14:29:11 +00:00
|
|
|
/* If there are three characters in front of last_tld and
|
2010-10-09 21:52:25 +00:00
|
|
|
* they are on the list of recognized TLDs, then this
|
|
|
|
* host doesn't have a domain (since the host only contains
|
|
|
|
* a TLD name.
|
|
|
|
* Ex: edu.uk -> has no domain name.
|
|
|
|
* foo.uk -> foo.uk as the domain name.
|
|
|
|
*/
|
2019-02-04 12:04:30 +00:00
|
|
|
for(i = 0; i < ARRAY_SIZE(recognized_tlds); ++i) {
|
2010-10-09 21:52:25 +00:00
|
|
|
if(!StrCmpNIW(host, recognized_tlds[i].tld_name, 3))
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
} else if(last_tld-host < 3)
|
|
|
|
/* Anything less than 3 characters is considered part
|
|
|
|
* of the TLD name.
|
|
|
|
* Ex: ak.uk -> Has no domain name.
|
|
|
|
*/
|
|
|
|
return;
|
|
|
|
|
|
|
|
/* Otherwise the domain name is the whole host name. */
|
|
|
|
*domain_start = 0;
|
|
|
|
} else if(end+1-last_tld > 3) {
|
|
|
|
/* If the last_tld has more than 3 characters, then it's automatically
|
|
|
|
* considered the TLD of the domain name.
|
|
|
|
* Ex: www.winehq.org.uk.test -> uk.test as the domain name.
|
|
|
|
*/
|
|
|
|
*domain_start = (sec_last_tld+1)-host;
|
|
|
|
} else if(last_tld - (sec_last_tld+1) < 4) {
|
|
|
|
DWORD i;
|
|
|
|
/* If the sec_last_tld is 3 characters long it HAS to be on the list of
|
|
|
|
* recognized to still be considered part of the TLD name, otherwise
|
2014-04-23 17:35:17 +00:00
|
|
|
* it's considered the domain name.
|
2010-10-09 21:52:25 +00:00
|
|
|
* Ex: www.google.com.uk -> google.com.uk as the domain name.
|
|
|
|
* www.google.foo.uk -> foo.uk as the domain name.
|
|
|
|
*/
|
|
|
|
if(last_tld - (sec_last_tld+1) == 3) {
|
2019-02-04 12:04:30 +00:00
|
|
|
for(i = 0; i < ARRAY_SIZE(recognized_tlds); ++i) {
|
2010-10-09 21:52:25 +00:00
|
|
|
if(!StrCmpNIW(sec_last_tld+1, recognized_tlds[i].tld_name, 3)) {
|
2011-06-05 21:29:41 +00:00
|
|
|
const WCHAR *domain = memrchrW(host, '.', sec_last_tld-host);
|
2010-10-09 21:52:25 +00:00
|
|
|
|
|
|
|
if(!domain)
|
|
|
|
*domain_start = 0;
|
|
|
|
else
|
|
|
|
*domain_start = (domain+1) - host;
|
|
|
|
TRACE("Found domain name %s\n", debugstr_wn(host+*domain_start,
|
|
|
|
(host+host_len)-(host+*domain_start)));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
*domain_start = (sec_last_tld+1)-host;
|
|
|
|
} else {
|
|
|
|
/* Since the sec_last_tld is less than 3 characters it's considered
|
|
|
|
* part of the TLD.
|
|
|
|
* Ex: www.google.fo.uk -> google.fo.uk as the domain name.
|
|
|
|
*/
|
2011-06-05 21:29:41 +00:00
|
|
|
const WCHAR *domain = memrchrW(host, '.', sec_last_tld-host);
|
2010-10-09 21:52:25 +00:00
|
|
|
|
|
|
|
if(!domain)
|
|
|
|
*domain_start = 0;
|
|
|
|
else
|
|
|
|
*domain_start = (domain+1) - host;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
/* The second to last TLD has more than 3 characters making it
|
|
|
|
* the domain name.
|
|
|
|
* Ex: www.google.test.us -> test.us as the domain name.
|
|
|
|
*/
|
|
|
|
*domain_start = (sec_last_tld+1)-host;
|
|
|
|
}
|
|
|
|
|
|
|
|
TRACE("Found domain name %s\n", debugstr_wn(host+*domain_start,
|
|
|
|
(host+host_len)-(host+*domain_start)));
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Removes the dot segments from a hierarchical URIs path component. This
|
|
|
|
* function performs the removal in place.
|
|
|
|
*
|
|
|
|
* This function returns the new length of the path string.
|
|
|
|
*/
|
|
|
|
static DWORD remove_dot_segments(WCHAR *path, DWORD path_len) {
|
|
|
|
WCHAR *out = path;
|
|
|
|
const WCHAR *in = out;
|
|
|
|
const WCHAR *end = out + path_len;
|
|
|
|
DWORD len;
|
|
|
|
|
|
|
|
while(in < end) {
|
2011-06-05 21:29:41 +00:00
|
|
|
/* Move the first path segment in the input buffer to the end of
|
|
|
|
* the output buffer, and any subsequent characters up to, including
|
|
|
|
* the next "/" character (if any) or the end of the input buffer.
|
2010-10-09 21:52:25 +00:00
|
|
|
*/
|
2011-06-05 21:29:41 +00:00
|
|
|
while(in < end && !is_slash(*in))
|
|
|
|
*out++ = *in++;
|
|
|
|
if(in == end)
|
2010-10-09 21:52:25 +00:00
|
|
|
break;
|
2011-06-05 21:29:41 +00:00
|
|
|
*out++ = *in++;
|
2010-10-09 21:52:25 +00:00
|
|
|
|
2011-06-05 21:29:41 +00:00
|
|
|
while(in < end) {
|
|
|
|
if(*in != '.')
|
|
|
|
break;
|
2010-10-09 21:52:25 +00:00
|
|
|
|
2011-06-05 21:29:41 +00:00
|
|
|
/* Handle ending "/." */
|
|
|
|
if(in + 1 == end) {
|
|
|
|
++in;
|
|
|
|
break;
|
|
|
|
}
|
2010-10-09 21:52:25 +00:00
|
|
|
|
2011-06-05 21:29:41 +00:00
|
|
|
/* Handle "/./" */
|
|
|
|
if(is_slash(in[1])) {
|
|
|
|
in += 2;
|
|
|
|
continue;
|
|
|
|
}
|
2010-10-09 21:52:25 +00:00
|
|
|
|
2011-06-05 21:29:41 +00:00
|
|
|
/* If we don't have "/../" or ending "/.." */
|
|
|
|
if(in[1] != '.' || (in + 2 != end && !is_slash(in[2])))
|
|
|
|
break;
|
2010-10-09 21:52:25 +00:00
|
|
|
|
2011-06-05 21:29:41 +00:00
|
|
|
/* Find the slash preceding out pointer and move out pointer to it */
|
|
|
|
if(out > path+1 && is_slash(*--out))
|
|
|
|
--out;
|
|
|
|
while(out > path && !is_slash(*(--out)));
|
|
|
|
if(is_slash(*out))
|
|
|
|
++out;
|
|
|
|
in += 2;
|
|
|
|
if(in != end)
|
|
|
|
++in;
|
|
|
|
}
|
2010-10-09 21:52:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
len = out - path;
|
|
|
|
TRACE("(%p %d): Path after dot segments removed %s len=%d\n", path, path_len,
|
|
|
|
debugstr_wn(path, len), len);
|
|
|
|
return len;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Attempts to find the file extension in a given path. */
|
|
|
|
static INT find_file_extension(const WCHAR *path, DWORD path_len) {
|
|
|
|
const WCHAR *end;
|
|
|
|
|
|
|
|
for(end = path+path_len-1; end >= path && *end != '/' && *end != '\\'; --end) {
|
|
|
|
if(*end == '.')
|
|
|
|
return end-path;
|
|
|
|
}
|
|
|
|
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Computes the location where the elision should occur in the IPv6
|
|
|
|
* address using the numerical values of each component stored in
|
|
|
|
* 'values'. If the address shouldn't contain an elision then 'index'
|
2013-03-22 14:29:11 +00:00
|
|
|
* is assigned -1 as its value. Otherwise 'index' will contain the
|
2010-10-09 21:52:25 +00:00
|
|
|
* starting index (into values) where the elision should be, and 'count'
|
|
|
|
* will contain the number of cells the elision covers.
|
|
|
|
*
|
|
|
|
* NOTES:
|
2013-03-22 14:29:11 +00:00
|
|
|
* Windows will expand an elision if the elision only represents one h16
|
2011-06-05 21:29:41 +00:00
|
|
|
* component of the address.
|
2010-10-09 21:52:25 +00:00
|
|
|
*
|
|
|
|
* Ex: [1::2:3:4:5:6:7] -> [1:0:2:3:4:5:6:7]
|
|
|
|
*
|
|
|
|
* If the IPv6 address contains an IPv4 address, the IPv4 address is also
|
2011-06-05 21:29:41 +00:00
|
|
|
* considered for being included as part of an elision if all its components
|
2010-10-09 21:52:25 +00:00
|
|
|
* are zeros.
|
|
|
|
*
|
|
|
|
* Ex: [1:2:3:4:5:6:0.0.0.0] -> [1:2:3:4:5:6::]
|
|
|
|
*/
|
|
|
|
static void compute_elision_location(const ipv6_address *address, const USHORT values[8],
|
|
|
|
INT *index, DWORD *count) {
|
|
|
|
DWORD i, max_len, cur_len;
|
|
|
|
INT max_index, cur_index;
|
|
|
|
|
|
|
|
max_len = cur_len = 0;
|
|
|
|
max_index = cur_index = -1;
|
|
|
|
for(i = 0; i < 8; ++i) {
|
|
|
|
BOOL check_ipv4 = (address->ipv4 && i == 6);
|
|
|
|
BOOL is_end = (check_ipv4 || i == 7);
|
|
|
|
|
|
|
|
if(check_ipv4) {
|
|
|
|
/* Check if the IPv4 address contains only zeros. */
|
|
|
|
if(values[i] == 0 && values[i+1] == 0) {
|
|
|
|
if(cur_index == -1)
|
|
|
|
cur_index = i;
|
|
|
|
|
|
|
|
cur_len += 2;
|
|
|
|
++i;
|
|
|
|
}
|
|
|
|
} else if(values[i] == 0) {
|
|
|
|
if(cur_index == -1)
|
|
|
|
cur_index = i;
|
|
|
|
|
|
|
|
++cur_len;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(is_end || values[i] != 0) {
|
|
|
|
/* We only consider it for an elision if it's
|
|
|
|
* more than 1 component long.
|
|
|
|
*/
|
|
|
|
if(cur_len > 1 && cur_len > max_len) {
|
|
|
|
/* Found the new elision location. */
|
|
|
|
max_len = cur_len;
|
|
|
|
max_index = cur_index;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Reset the current range for the next range of zeros. */
|
|
|
|
cur_index = -1;
|
|
|
|
cur_len = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
*index = max_index;
|
|
|
|
*count = max_len;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Removes all the leading and trailing white spaces or
|
|
|
|
* control characters from the URI and removes all control
|
|
|
|
* characters inside of the URI string.
|
|
|
|
*/
|
|
|
|
static BSTR pre_process_uri(LPCWSTR uri) {
|
2013-03-22 14:29:11 +00:00
|
|
|
const WCHAR *start, *end, *ptr;
|
|
|
|
WCHAR *ptr2;
|
2010-10-09 21:52:25 +00:00
|
|
|
DWORD len;
|
2013-03-22 14:29:11 +00:00
|
|
|
BSTR ret;
|
2010-10-09 21:52:25 +00:00
|
|
|
|
|
|
|
start = uri;
|
|
|
|
/* Skip leading controls and whitespace. */
|
2013-03-22 14:29:11 +00:00
|
|
|
while(*start && (iscntrlW(*start) || isspaceW(*start))) ++start;
|
2010-10-09 21:52:25 +00:00
|
|
|
|
2013-03-22 14:29:11 +00:00
|
|
|
/* URI consisted only of control/whitespace. */
|
|
|
|
if(!*start)
|
|
|
|
return SysAllocStringLen(NULL, 0);
|
2010-10-09 21:52:25 +00:00
|
|
|
|
2013-03-22 14:29:11 +00:00
|
|
|
end = start + strlenW(start);
|
|
|
|
while(--end > start && (iscntrlW(*end) || isspaceW(*end)));
|
2010-10-09 21:52:25 +00:00
|
|
|
|
2013-03-22 14:29:11 +00:00
|
|
|
len = ++end - start;
|
|
|
|
for(ptr = start; ptr < end; ptr++) {
|
|
|
|
if(iscntrlW(*ptr))
|
|
|
|
len--;
|
|
|
|
}
|
2010-10-09 21:52:25 +00:00
|
|
|
|
2013-03-22 14:29:11 +00:00
|
|
|
ret = SysAllocStringLen(NULL, len);
|
|
|
|
if(!ret)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
for(ptr = start, ptr2=ret; ptr < end; ptr++) {
|
|
|
|
if(!iscntrlW(*ptr))
|
|
|
|
*ptr2++ = *ptr;
|
2010-10-09 21:52:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Converts the specified IPv4 address into an uint value.
|
|
|
|
*
|
|
|
|
* This function assumes that the IPv4 address has already been validated.
|
|
|
|
*/
|
|
|
|
static UINT ipv4toui(const WCHAR *ip, DWORD len) {
|
|
|
|
UINT ret = 0;
|
|
|
|
DWORD comp_value = 0;
|
|
|
|
const WCHAR *ptr;
|
|
|
|
|
|
|
|
for(ptr = ip; ptr < ip+len; ++ptr) {
|
|
|
|
if(*ptr == '.') {
|
|
|
|
ret <<= 8;
|
|
|
|
ret += comp_value;
|
|
|
|
comp_value = 0;
|
|
|
|
} else
|
|
|
|
comp_value = comp_value*10 + (*ptr-'0');
|
|
|
|
}
|
|
|
|
|
|
|
|
ret <<= 8;
|
|
|
|
ret += comp_value;
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2013-03-22 14:29:11 +00:00
|
|
|
/* Converts an IPv4 address in numerical form into its fully qualified
|
Finish the Wine sync. These components are not just rc file changes
atl, comctl32, comdlg32, dwmapi, fusion, gdiplus, jscript, mpr, mshtml, msi, msimtf, msxml3, ole32, oleaut32, riched20, shdocvw, shlwapi, urlmon, usp10, version and windowscodecs
Seems to build and boot. /me hides
svn path=/trunk/; revision=48273
2010-07-26 02:26:04 +00:00
|
|
|
* string form. This function returns the number of characters written
|
|
|
|
* to 'dest'. If 'dest' is NULL this function will return the number of
|
|
|
|
* characters that would have been written.
|
|
|
|
*
|
|
|
|
* It's up to the caller to ensure there's enough space in 'dest' for the
|
|
|
|
* address.
|
|
|
|
*/
|
|
|
|
static DWORD ui2ipv4(WCHAR *dest, UINT address) {
|
|
|
|
static const WCHAR formatW[] =
|
|
|
|
{'%','u','.','%','u','.','%','u','.','%','u',0};
|
|
|
|
DWORD ret = 0;
|
|
|
|
UCHAR digits[4];
|
|
|
|
|
|
|
|
digits[0] = (address >> 24) & 0xff;
|
|
|
|
digits[1] = (address >> 16) & 0xff;
|
|
|
|
digits[2] = (address >> 8) & 0xff;
|
|
|
|
digits[3] = address & 0xff;
|
|
|
|
|
|
|
|
if(!dest) {
|
|
|
|
WCHAR tmp[16];
|
|
|
|
ret = sprintfW(tmp, formatW, digits[0], digits[1], digits[2], digits[3]);
|
|
|
|
} else
|
|
|
|
ret = sprintfW(dest, formatW, digits[0], digits[1], digits[2], digits[3]);
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2010-12-20 21:29:55 +00:00
|
|
|
static DWORD ui2str(WCHAR *dest, UINT value) {
|
|
|
|
static const WCHAR formatW[] = {'%','u',0};
|
|
|
|
DWORD ret = 0;
|
|
|
|
|
|
|
|
if(!dest) {
|
|
|
|
WCHAR tmp[11];
|
|
|
|
ret = sprintfW(tmp, formatW, value);
|
|
|
|
} else
|
|
|
|
ret = sprintfW(dest, formatW, value);
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2013-03-22 14:29:11 +00:00
|
|
|
/* Converts a h16 component (from an IPv6 address) into its
|
2010-10-09 21:52:25 +00:00
|
|
|
* numerical value.
|
|
|
|
*
|
|
|
|
* This function assumes that the h16 component has already been validated.
|
|
|
|
*/
|
|
|
|
static USHORT h16tous(h16 component) {
|
|
|
|
DWORD i;
|
|
|
|
USHORT ret = 0;
|
|
|
|
|
|
|
|
for(i = 0; i < component.len; ++i) {
|
|
|
|
ret <<= 4;
|
|
|
|
ret += hex_to_int(component.str[i]);
|
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2011-06-05 21:29:41 +00:00
|
|
|
/* Converts an IPv6 address into its 128 bits (16 bytes) numerical value.
|
2010-10-09 21:52:25 +00:00
|
|
|
*
|
|
|
|
* This function assumes that the ipv6_address has already been validated.
|
|
|
|
*/
|
|
|
|
static BOOL ipv6_to_number(const ipv6_address *address, USHORT number[8]) {
|
|
|
|
DWORD i, cur_component = 0;
|
|
|
|
BOOL already_passed_elision = FALSE;
|
|
|
|
|
|
|
|
for(i = 0; i < address->h16_count; ++i) {
|
|
|
|
if(address->elision) {
|
|
|
|
if(address->components[i].str > address->elision && !already_passed_elision) {
|
2011-06-05 21:29:41 +00:00
|
|
|
/* Means we just passed the elision and need to add its values to
|
2010-10-09 21:52:25 +00:00
|
|
|
* 'number' before we do anything else.
|
|
|
|
*/
|
2013-03-22 14:29:11 +00:00
|
|
|
INT j;
|
2010-10-09 21:52:25 +00:00
|
|
|
for(j = 0; j < address->elision_size; j+=2)
|
|
|
|
number[cur_component++] = 0;
|
|
|
|
|
|
|
|
already_passed_elision = TRUE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
number[cur_component++] = h16tous(address->components[i]);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Case when the elision appears after the h16 components. */
|
|
|
|
if(!already_passed_elision && address->elision) {
|
2013-03-22 14:29:11 +00:00
|
|
|
INT j;
|
|
|
|
for(j = 0; j < address->elision_size; j+=2)
|
2010-10-09 21:52:25 +00:00
|
|
|
number[cur_component++] = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(address->ipv4) {
|
|
|
|
UINT value = ipv4toui(address->ipv4, address->ipv4_len);
|
|
|
|
|
|
|
|
if(cur_component != 6) {
|
|
|
|
ERR("(%p %p): Failed sanity check with %d\n", address, number, cur_component);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
number[cur_component++] = (value >> 16) & 0xffff;
|
|
|
|
number[cur_component] = value & 0xffff;
|
|
|
|
}
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
Finish the Wine sync. These components are not just rc file changes
atl, comctl32, comdlg32, dwmapi, fusion, gdiplus, jscript, mpr, mshtml, msi, msimtf, msxml3, ole32, oleaut32, riched20, shdocvw, shlwapi, urlmon, usp10, version and windowscodecs
Seems to build and boot. /me hides
svn path=/trunk/; revision=48273
2010-07-26 02:26:04 +00:00
|
|
|
/* Checks if the characters pointed to by 'ptr' are
|
|
|
|
* a percent encoded data octet.
|
|
|
|
*
|
|
|
|
* pct-encoded = "%" HEXDIG HEXDIG
|
|
|
|
*/
|
|
|
|
static BOOL check_pct_encoded(const WCHAR **ptr) {
|
|
|
|
const WCHAR *start = *ptr;
|
|
|
|
|
|
|
|
if(**ptr != '%')
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
++(*ptr);
|
|
|
|
if(!is_hexdigit(**ptr)) {
|
|
|
|
*ptr = start;
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
++(*ptr);
|
|
|
|
if(!is_hexdigit(**ptr)) {
|
|
|
|
*ptr = start;
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
++(*ptr);
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* dec-octet = DIGIT ; 0-9
|
|
|
|
* / %x31-39 DIGIT ; 10-99
|
|
|
|
* / "1" 2DIGIT ; 100-199
|
|
|
|
* / "2" %x30-34 DIGIT ; 200-249
|
|
|
|
* / "25" %x30-35 ; 250-255
|
|
|
|
*/
|
|
|
|
static BOOL check_dec_octet(const WCHAR **ptr) {
|
|
|
|
const WCHAR *c1, *c2, *c3;
|
|
|
|
|
|
|
|
c1 = *ptr;
|
|
|
|
/* A dec-octet must be at least 1 digit long. */
|
|
|
|
if(*c1 < '0' || *c1 > '9')
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
++(*ptr);
|
|
|
|
|
|
|
|
c2 = *ptr;
|
2013-03-22 14:29:11 +00:00
|
|
|
/* Since the 1-digit requirement was met, it doesn't
|
Finish the Wine sync. These components are not just rc file changes
atl, comctl32, comdlg32, dwmapi, fusion, gdiplus, jscript, mpr, mshtml, msi, msimtf, msxml3, ole32, oleaut32, riched20, shdocvw, shlwapi, urlmon, usp10, version and windowscodecs
Seems to build and boot. /me hides
svn path=/trunk/; revision=48273
2010-07-26 02:26:04 +00:00
|
|
|
* matter if this is a DIGIT value, it's considered a
|
|
|
|
* dec-octet.
|
|
|
|
*/
|
|
|
|
if(*c2 < '0' || *c2 > '9')
|
|
|
|
return TRUE;
|
|
|
|
|
|
|
|
++(*ptr);
|
|
|
|
|
|
|
|
c3 = *ptr;
|
|
|
|
/* Same explanation as above. */
|
|
|
|
if(*c3 < '0' || *c3 > '9')
|
|
|
|
return TRUE;
|
|
|
|
|
|
|
|
/* Anything > 255 isn't a valid IP dec-octet. */
|
|
|
|
if(*c1 >= '2' && *c2 >= '5' && *c3 >= '5') {
|
|
|
|
*ptr = c1;
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
++(*ptr);
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Checks if there is an implicit IPv4 address in the host component of the URI.
|
|
|
|
* The max value of an implicit IPv4 address is UINT_MAX.
|
|
|
|
*
|
|
|
|
* Ex:
|
|
|
|
* "234567" would be considered an implicit IPv4 address.
|
|
|
|
*/
|
|
|
|
static BOOL check_implicit_ipv4(const WCHAR **ptr, UINT *val) {
|
|
|
|
const WCHAR *start = *ptr;
|
|
|
|
ULONGLONG ret = 0;
|
|
|
|
*val = 0;
|
|
|
|
|
|
|
|
while(is_num(**ptr)) {
|
|
|
|
ret = ret*10 + (**ptr - '0');
|
|
|
|
|
|
|
|
if(ret > UINT_MAX) {
|
|
|
|
*ptr = start;
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
++(*ptr);
|
|
|
|
}
|
|
|
|
|
|
|
|
if(*ptr == start)
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
*val = ret;
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Checks if the string contains an IPv4 address.
|
|
|
|
*
|
|
|
|
* This function has a strict mode or a non-strict mode of operation
|
|
|
|
* When 'strict' is set to FALSE this function will return TRUE if
|
|
|
|
* the string contains at least 'dec-octet "." dec-octet' since partial
|
|
|
|
* IPv4 addresses will be normalized out into full IPv4 addresses. When
|
|
|
|
* 'strict' is set this function expects there to be a full IPv4 address.
|
|
|
|
*
|
|
|
|
* IPv4address = dec-octet "." dec-octet "." dec-octet "." dec-octet
|
|
|
|
*/
|
|
|
|
static BOOL check_ipv4address(const WCHAR **ptr, BOOL strict) {
|
|
|
|
const WCHAR *start = *ptr;
|
|
|
|
|
|
|
|
if(!check_dec_octet(ptr)) {
|
|
|
|
*ptr = start;
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(**ptr != '.') {
|
|
|
|
*ptr = start;
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
++(*ptr);
|
|
|
|
if(!check_dec_octet(ptr)) {
|
|
|
|
*ptr = start;
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(**ptr != '.') {
|
|
|
|
if(strict) {
|
|
|
|
*ptr = start;
|
|
|
|
return FALSE;
|
|
|
|
} else
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
++(*ptr);
|
|
|
|
if(!check_dec_octet(ptr)) {
|
|
|
|
*ptr = start;
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(**ptr != '.') {
|
|
|
|
if(strict) {
|
|
|
|
*ptr = start;
|
|
|
|
return FALSE;
|
|
|
|
} else
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
++(*ptr);
|
|
|
|
if(!check_dec_octet(ptr)) {
|
|
|
|
*ptr = start;
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Found a four digit ip address. */
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
/* Tries to parse the scheme name of the URI.
|
|
|
|
*
|
|
|
|
* scheme = ALPHA *(ALPHA | NUM | '+' | '-' | '.') as defined by RFC 3896.
|
|
|
|
* NOTE: Windows accepts a number as the first character of a scheme.
|
|
|
|
*/
|
2010-10-09 21:52:25 +00:00
|
|
|
static BOOL parse_scheme_name(const WCHAR **ptr, parse_data *data, DWORD extras) {
|
Finish the Wine sync. These components are not just rc file changes
atl, comctl32, comdlg32, dwmapi, fusion, gdiplus, jscript, mpr, mshtml, msi, msimtf, msxml3, ole32, oleaut32, riched20, shdocvw, shlwapi, urlmon, usp10, version and windowscodecs
Seems to build and boot. /me hides
svn path=/trunk/; revision=48273
2010-07-26 02:26:04 +00:00
|
|
|
const WCHAR *start = *ptr;
|
|
|
|
|
|
|
|
data->scheme = NULL;
|
|
|
|
data->scheme_len = 0;
|
|
|
|
|
|
|
|
while(**ptr) {
|
|
|
|
if(**ptr == '*' && *ptr == start) {
|
|
|
|
/* Might have found a wildcard scheme. If it is the next
|
|
|
|
* char has to be a ':' for it to be a valid URI
|
|
|
|
*/
|
|
|
|
++(*ptr);
|
|
|
|
break;
|
|
|
|
} else if(!is_num(**ptr) && !is_alpha(**ptr) && **ptr != '+' &&
|
|
|
|
**ptr != '-' && **ptr != '.')
|
|
|
|
break;
|
|
|
|
|
|
|
|
(*ptr)++;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(*ptr == start)
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
/* Schemes must end with a ':' */
|
2010-10-09 21:52:25 +00:00
|
|
|
if(**ptr != ':' && !((extras & ALLOW_NULL_TERM_SCHEME) && !**ptr)) {
|
Finish the Wine sync. These components are not just rc file changes
atl, comctl32, comdlg32, dwmapi, fusion, gdiplus, jscript, mpr, mshtml, msi, msimtf, msxml3, ole32, oleaut32, riched20, shdocvw, shlwapi, urlmon, usp10, version and windowscodecs
Seems to build and boot. /me hides
svn path=/trunk/; revision=48273
2010-07-26 02:26:04 +00:00
|
|
|
*ptr = start;
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
data->scheme = start;
|
|
|
|
data->scheme_len = *ptr - start;
|
|
|
|
|
|
|
|
++(*ptr);
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Tries to deduce the corresponding URL_SCHEME for the given URI. Stores
|
|
|
|
* the deduced URL_SCHEME in data->scheme_type.
|
|
|
|
*/
|
|
|
|
static BOOL parse_scheme_type(parse_data *data) {
|
|
|
|
/* If there's scheme data then see if it's a recognized scheme. */
|
|
|
|
if(data->scheme && data->scheme_len) {
|
|
|
|
DWORD i;
|
|
|
|
|
2019-02-04 12:04:30 +00:00
|
|
|
for(i = 0; i < ARRAY_SIZE(recognized_schemes); ++i) {
|
Finish the Wine sync. These components are not just rc file changes
atl, comctl32, comdlg32, dwmapi, fusion, gdiplus, jscript, mpr, mshtml, msi, msimtf, msxml3, ole32, oleaut32, riched20, shdocvw, shlwapi, urlmon, usp10, version and windowscodecs
Seems to build and boot. /me hides
svn path=/trunk/; revision=48273
2010-07-26 02:26:04 +00:00
|
|
|
if(lstrlenW(recognized_schemes[i].scheme_name) == data->scheme_len) {
|
|
|
|
/* Has to be a case insensitive compare. */
|
|
|
|
if(!StrCmpNIW(recognized_schemes[i].scheme_name, data->scheme, data->scheme_len)) {
|
|
|
|
data->scheme_type = recognized_schemes[i].scheme;
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* If we get here it means it's not a recognized scheme. */
|
|
|
|
data->scheme_type = URL_SCHEME_UNKNOWN;
|
|
|
|
return TRUE;
|
|
|
|
} else if(data->is_relative) {
|
|
|
|
/* Relative URI's have no scheme. */
|
|
|
|
data->scheme_type = URL_SCHEME_UNKNOWN;
|
|
|
|
return TRUE;
|
|
|
|
} else {
|
|
|
|
/* Should never reach here! what happened... */
|
|
|
|
FIXME("(%p): Unable to determine scheme type for URI %s\n", data, debugstr_w(data->uri));
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Tries to parse (or deduce) the scheme_name of a URI. If it can't
|
|
|
|
* parse a scheme from the URI it will try to deduce the scheme_name and scheme_type
|
|
|
|
* using the flags specified in 'flags' (if any). Flags that affect how this function
|
|
|
|
* operates are the Uri_CREATE_ALLOW_* flags.
|
|
|
|
*
|
|
|
|
* All parsed/deduced information will be stored in 'data' when the function returns.
|
|
|
|
*
|
|
|
|
* Returns TRUE if it was able to successfully parse the information.
|
|
|
|
*/
|
2010-10-09 21:52:25 +00:00
|
|
|
static BOOL parse_scheme(const WCHAR **ptr, parse_data *data, DWORD flags, DWORD extras) {
|
Finish the Wine sync. These components are not just rc file changes
atl, comctl32, comdlg32, dwmapi, fusion, gdiplus, jscript, mpr, mshtml, msi, msimtf, msxml3, ole32, oleaut32, riched20, shdocvw, shlwapi, urlmon, usp10, version and windowscodecs
Seems to build and boot. /me hides
svn path=/trunk/; revision=48273
2010-07-26 02:26:04 +00:00
|
|
|
static const WCHAR fileW[] = {'f','i','l','e',0};
|
|
|
|
static const WCHAR wildcardW[] = {'*',0};
|
|
|
|
|
|
|
|
/* First check to see if the uri could implicitly be a file path. */
|
|
|
|
if(is_implicit_file_path(*ptr)) {
|
|
|
|
if(flags & Uri_CREATE_ALLOW_IMPLICIT_FILE_SCHEME) {
|
|
|
|
data->scheme = fileW;
|
|
|
|
data->scheme_len = lstrlenW(fileW);
|
|
|
|
data->has_implicit_scheme = TRUE;
|
|
|
|
|
|
|
|
TRACE("(%p %p %x): URI is an implicit file path.\n", ptr, data, flags);
|
|
|
|
} else {
|
2013-03-22 14:29:11 +00:00
|
|
|
/* Windows does not consider anything that can implicitly be a file
|
Finish the Wine sync. These components are not just rc file changes
atl, comctl32, comdlg32, dwmapi, fusion, gdiplus, jscript, mpr, mshtml, msi, msimtf, msxml3, ole32, oleaut32, riched20, shdocvw, shlwapi, urlmon, usp10, version and windowscodecs
Seems to build and boot. /me hides
svn path=/trunk/; revision=48273
2010-07-26 02:26:04 +00:00
|
|
|
* path to be a valid URI if the ALLOW_IMPLICIT_FILE_SCHEME flag is not set...
|
|
|
|
*/
|
|
|
|
TRACE("(%p %p %x): URI is implicitly a file path, but, the ALLOW_IMPLICIT_FILE_SCHEME flag wasn't set.\n",
|
|
|
|
ptr, data, flags);
|
|
|
|
return FALSE;
|
|
|
|
}
|
2010-10-09 21:52:25 +00:00
|
|
|
} else if(!parse_scheme_name(ptr, data, extras)) {
|
2013-03-22 14:29:11 +00:00
|
|
|
/* No scheme was found, this means it could be:
|
Finish the Wine sync. These components are not just rc file changes
atl, comctl32, comdlg32, dwmapi, fusion, gdiplus, jscript, mpr, mshtml, msi, msimtf, msxml3, ole32, oleaut32, riched20, shdocvw, shlwapi, urlmon, usp10, version and windowscodecs
Seems to build and boot. /me hides
svn path=/trunk/; revision=48273
2010-07-26 02:26:04 +00:00
|
|
|
* a) an implicit Wildcard scheme
|
|
|
|
* b) a relative URI
|
2013-03-22 14:29:11 +00:00
|
|
|
* c) an invalid URI.
|
Finish the Wine sync. These components are not just rc file changes
atl, comctl32, comdlg32, dwmapi, fusion, gdiplus, jscript, mpr, mshtml, msi, msimtf, msxml3, ole32, oleaut32, riched20, shdocvw, shlwapi, urlmon, usp10, version and windowscodecs
Seems to build and boot. /me hides
svn path=/trunk/; revision=48273
2010-07-26 02:26:04 +00:00
|
|
|
*/
|
|
|
|
if(flags & Uri_CREATE_ALLOW_IMPLICIT_WILDCARD_SCHEME) {
|
|
|
|
data->scheme = wildcardW;
|
|
|
|
data->scheme_len = lstrlenW(wildcardW);
|
|
|
|
data->has_implicit_scheme = TRUE;
|
|
|
|
|
|
|
|
TRACE("(%p %p %x): URI is an implicit wildcard scheme.\n", ptr, data, flags);
|
|
|
|
} else if (flags & Uri_CREATE_ALLOW_RELATIVE) {
|
|
|
|
data->is_relative = TRUE;
|
|
|
|
TRACE("(%p %p %x): URI is relative.\n", ptr, data, flags);
|
|
|
|
} else {
|
|
|
|
TRACE("(%p %p %x): Malformed URI found. Unable to deduce scheme name.\n", ptr, data, flags);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if(!data->is_relative)
|
|
|
|
TRACE("(%p %p %x): Found scheme=%s scheme_len=%d\n", ptr, data, flags,
|
|
|
|
debugstr_wn(data->scheme, data->scheme_len), data->scheme_len);
|
|
|
|
|
|
|
|
if(!parse_scheme_type(data))
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
TRACE("(%p %p %x): Assigned %d as the URL_SCHEME.\n", ptr, data, flags, data->scheme_type);
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
2010-10-09 21:52:25 +00:00
|
|
|
static BOOL parse_username(const WCHAR **ptr, parse_data *data, DWORD flags, DWORD extras) {
|
|
|
|
data->username = *ptr;
|
|
|
|
|
|
|
|
while(**ptr != ':' && **ptr != '@') {
|
|
|
|
if(**ptr == '%') {
|
|
|
|
if(!check_pct_encoded(ptr)) {
|
|
|
|
if(data->scheme_type != URL_SCHEME_UNKNOWN) {
|
|
|
|
*ptr = data->username;
|
|
|
|
data->username = NULL;
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
} else
|
|
|
|
continue;
|
|
|
|
} else if(extras & ALLOW_NULL_TERM_USER_NAME && !**ptr)
|
|
|
|
break;
|
|
|
|
else if(is_auth_delim(**ptr, data->scheme_type != URL_SCHEME_UNKNOWN)) {
|
|
|
|
*ptr = data->username;
|
|
|
|
data->username = NULL;
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
++(*ptr);
|
|
|
|
}
|
|
|
|
|
|
|
|
data->username_len = *ptr - data->username;
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static BOOL parse_password(const WCHAR **ptr, parse_data *data, DWORD flags, DWORD extras) {
|
|
|
|
data->password = *ptr;
|
|
|
|
|
|
|
|
while(**ptr != '@') {
|
|
|
|
if(**ptr == '%') {
|
|
|
|
if(!check_pct_encoded(ptr)) {
|
|
|
|
if(data->scheme_type != URL_SCHEME_UNKNOWN) {
|
2010-12-20 21:29:55 +00:00
|
|
|
*ptr = data->password;
|
2010-10-09 21:52:25 +00:00
|
|
|
data->password = NULL;
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
} else
|
|
|
|
continue;
|
|
|
|
} else if(extras & ALLOW_NULL_TERM_PASSWORD && !**ptr)
|
|
|
|
break;
|
|
|
|
else if(is_auth_delim(**ptr, data->scheme_type != URL_SCHEME_UNKNOWN)) {
|
2010-12-20 21:29:55 +00:00
|
|
|
*ptr = data->password;
|
2010-10-09 21:52:25 +00:00
|
|
|
data->password = NULL;
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
++(*ptr);
|
|
|
|
}
|
|
|
|
|
|
|
|
data->password_len = *ptr - data->password;
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Parses the userinfo part of the URI (if it exists). The userinfo field of
|
|
|
|
* a URI can consist of "username:password@", or just "username@".
|
|
|
|
*
|
|
|
|
* RFC def:
|
|
|
|
* userinfo = *( unreserved / pct-encoded / sub-delims / ":" )
|
Finish the Wine sync. These components are not just rc file changes
atl, comctl32, comdlg32, dwmapi, fusion, gdiplus, jscript, mpr, mshtml, msi, msimtf, msxml3, ole32, oleaut32, riched20, shdocvw, shlwapi, urlmon, usp10, version and windowscodecs
Seems to build and boot. /me hides
svn path=/trunk/; revision=48273
2010-07-26 02:26:04 +00:00
|
|
|
*
|
|
|
|
* NOTES:
|
|
|
|
* 1) If there is more than one ':' in the userinfo part of the URI Windows
|
2010-10-09 21:52:25 +00:00
|
|
|
* uses the first occurrence of ':' to delimit the username and password
|
Finish the Wine sync. These components are not just rc file changes
atl, comctl32, comdlg32, dwmapi, fusion, gdiplus, jscript, mpr, mshtml, msi, msimtf, msxml3, ole32, oleaut32, riched20, shdocvw, shlwapi, urlmon, usp10, version and windowscodecs
Seems to build and boot. /me hides
svn path=/trunk/; revision=48273
2010-07-26 02:26:04 +00:00
|
|
|
* components.
|
|
|
|
*
|
|
|
|
* ex:
|
|
|
|
* ftp://user:pass:word@winehq.org
|
|
|
|
*
|
2013-03-22 14:29:11 +00:00
|
|
|
* would yield "user" as the username and "pass:word" as the password.
|
Finish the Wine sync. These components are not just rc file changes
atl, comctl32, comdlg32, dwmapi, fusion, gdiplus, jscript, mpr, mshtml, msi, msimtf, msxml3, ole32, oleaut32, riched20, shdocvw, shlwapi, urlmon, usp10, version and windowscodecs
Seems to build and boot. /me hides
svn path=/trunk/; revision=48273
2010-07-26 02:26:04 +00:00
|
|
|
*
|
|
|
|
* 2) Windows allows any character to appear in the "userinfo" part of
|
2013-03-22 14:29:11 +00:00
|
|
|
* a URI, as long as it's not an authority delimiter character set.
|
Finish the Wine sync. These components are not just rc file changes
atl, comctl32, comdlg32, dwmapi, fusion, gdiplus, jscript, mpr, mshtml, msi, msimtf, msxml3, ole32, oleaut32, riched20, shdocvw, shlwapi, urlmon, usp10, version and windowscodecs
Seems to build and boot. /me hides
svn path=/trunk/; revision=48273
2010-07-26 02:26:04 +00:00
|
|
|
*/
|
|
|
|
static void parse_userinfo(const WCHAR **ptr, parse_data *data, DWORD flags) {
|
2010-10-09 21:52:25 +00:00
|
|
|
const WCHAR *start = *ptr;
|
Finish the Wine sync. These components are not just rc file changes
atl, comctl32, comdlg32, dwmapi, fusion, gdiplus, jscript, mpr, mshtml, msi, msimtf, msxml3, ole32, oleaut32, riched20, shdocvw, shlwapi, urlmon, usp10, version and windowscodecs
Seems to build and boot. /me hides
svn path=/trunk/; revision=48273
2010-07-26 02:26:04 +00:00
|
|
|
|
2010-10-09 21:52:25 +00:00
|
|
|
if(!parse_username(ptr, data, flags, 0)) {
|
|
|
|
TRACE("(%p %p %x): URI contained no userinfo.\n", ptr, data, flags);
|
|
|
|
return;
|
|
|
|
}
|
Finish the Wine sync. These components are not just rc file changes
atl, comctl32, comdlg32, dwmapi, fusion, gdiplus, jscript, mpr, mshtml, msi, msimtf, msxml3, ole32, oleaut32, riched20, shdocvw, shlwapi, urlmon, usp10, version and windowscodecs
Seems to build and boot. /me hides
svn path=/trunk/; revision=48273
2010-07-26 02:26:04 +00:00
|
|
|
|
2010-12-20 21:29:55 +00:00
|
|
|
if(**ptr == ':') {
|
|
|
|
++(*ptr);
|
|
|
|
if(!parse_password(ptr, data, flags, 0)) {
|
|
|
|
*ptr = start;
|
|
|
|
data->username = NULL;
|
|
|
|
data->username_len = 0;
|
|
|
|
TRACE("(%p %p %x): URI contained no userinfo.\n", ptr, data, flags);
|
|
|
|
return;
|
|
|
|
}
|
Finish the Wine sync. These components are not just rc file changes
atl, comctl32, comdlg32, dwmapi, fusion, gdiplus, jscript, mpr, mshtml, msi, msimtf, msxml3, ole32, oleaut32, riched20, shdocvw, shlwapi, urlmon, usp10, version and windowscodecs
Seems to build and boot. /me hides
svn path=/trunk/; revision=48273
2010-07-26 02:26:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if(**ptr != '@') {
|
2010-10-09 21:52:25 +00:00
|
|
|
*ptr = start;
|
|
|
|
data->username = NULL;
|
|
|
|
data->username_len = 0;
|
|
|
|
data->password = NULL;
|
|
|
|
data->password_len = 0;
|
Finish the Wine sync. These components are not just rc file changes
atl, comctl32, comdlg32, dwmapi, fusion, gdiplus, jscript, mpr, mshtml, msi, msimtf, msxml3, ole32, oleaut32, riched20, shdocvw, shlwapi, urlmon, usp10, version and windowscodecs
Seems to build and boot. /me hides
svn path=/trunk/; revision=48273
2010-07-26 02:26:04 +00:00
|
|
|
|
|
|
|
TRACE("(%p %p %x): URI contained no userinfo.\n", ptr, data, flags);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2010-10-09 21:52:25 +00:00
|
|
|
if(data->username)
|
|
|
|
TRACE("(%p %p %x): Found username %s len=%d.\n", ptr, data, flags,
|
|
|
|
debugstr_wn(data->username, data->username_len), data->username_len);
|
|
|
|
|
|
|
|
if(data->password)
|
|
|
|
TRACE("(%p %p %x): Found password %s len=%d.\n", ptr, data, flags,
|
|
|
|
debugstr_wn(data->password, data->password_len), data->password_len);
|
|
|
|
|
Finish the Wine sync. These components are not just rc file changes
atl, comctl32, comdlg32, dwmapi, fusion, gdiplus, jscript, mpr, mshtml, msi, msimtf, msxml3, ole32, oleaut32, riched20, shdocvw, shlwapi, urlmon, usp10, version and windowscodecs
Seems to build and boot. /me hides
svn path=/trunk/; revision=48273
2010-07-26 02:26:04 +00:00
|
|
|
++(*ptr);
|
|
|
|
}
|
|
|
|
|
2010-10-09 21:52:25 +00:00
|
|
|
/* Attempts to parse a port from the URI.
|
|
|
|
*
|
|
|
|
* NOTES:
|
|
|
|
* Windows seems to have a cap on what the maximum value
|
|
|
|
* for a port can be. The max value is USHORT_MAX.
|
|
|
|
*
|
|
|
|
* port = *DIGIT
|
|
|
|
*/
|
|
|
|
static BOOL parse_port(const WCHAR **ptr, parse_data *data, DWORD flags) {
|
|
|
|
UINT port = 0;
|
|
|
|
data->port = *ptr;
|
|
|
|
|
|
|
|
while(!is_auth_delim(**ptr, data->scheme_type != URL_SCHEME_UNKNOWN)) {
|
|
|
|
if(!is_num(**ptr)) {
|
|
|
|
*ptr = data->port;
|
|
|
|
data->port = NULL;
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
port = port*10 + (**ptr-'0');
|
|
|
|
|
2013-03-22 14:29:11 +00:00
|
|
|
if(port > USHRT_MAX) {
|
2010-10-09 21:52:25 +00:00
|
|
|
*ptr = data->port;
|
|
|
|
data->port = NULL;
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
++(*ptr);
|
|
|
|
}
|
|
|
|
|
|
|
|
data->has_port = TRUE;
|
|
|
|
data->port_value = port;
|
|
|
|
data->port_len = *ptr - data->port;
|
|
|
|
|
|
|
|
TRACE("(%p %p %x): Found port %s len=%d value=%u\n", ptr, data, flags,
|
|
|
|
debugstr_wn(data->port, data->port_len), data->port_len, data->port_value);
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
Finish the Wine sync. These components are not just rc file changes
atl, comctl32, comdlg32, dwmapi, fusion, gdiplus, jscript, mpr, mshtml, msi, msimtf, msxml3, ole32, oleaut32, riched20, shdocvw, shlwapi, urlmon, usp10, version and windowscodecs
Seems to build and boot. /me hides
svn path=/trunk/; revision=48273
2010-07-26 02:26:04 +00:00
|
|
|
/* Attempts to parse a IPv4 address from the URI.
|
|
|
|
*
|
|
|
|
* NOTES:
|
2013-03-22 14:29:11 +00:00
|
|
|
* Windows normalizes IPv4 addresses, This means there are three
|
Finish the Wine sync. These components are not just rc file changes
atl, comctl32, comdlg32, dwmapi, fusion, gdiplus, jscript, mpr, mshtml, msi, msimtf, msxml3, ole32, oleaut32, riched20, shdocvw, shlwapi, urlmon, usp10, version and windowscodecs
Seems to build and boot. /me hides
svn path=/trunk/; revision=48273
2010-07-26 02:26:04 +00:00
|
|
|
* possibilities for the URI to contain an IPv4 address.
|
|
|
|
* 1) A well formed address (ex. 192.2.2.2).
|
|
|
|
* 2) A partially formed address. For example "192.0" would
|
|
|
|
* normalize to "192.0.0.0" during canonicalization.
|
|
|
|
* 3) An implicit IPv4 address. For example "256" would
|
|
|
|
* normalize to "0.0.1.0" during canonicalization. Also
|
|
|
|
* note that the maximum value for an implicit IP address
|
|
|
|
* is UINT_MAX, if the value in the URI exceeds this then
|
|
|
|
* it is not considered an IPv4 address.
|
|
|
|
*/
|
|
|
|
static BOOL parse_ipv4address(const WCHAR **ptr, parse_data *data, DWORD flags) {
|
|
|
|
const BOOL is_unknown = data->scheme_type == URL_SCHEME_UNKNOWN;
|
|
|
|
data->host = *ptr;
|
|
|
|
|
|
|
|
if(!check_ipv4address(ptr, FALSE)) {
|
|
|
|
if(!check_implicit_ipv4(ptr, &data->implicit_ipv4)) {
|
|
|
|
TRACE("(%p %p %x): URI didn't contain anything looking like an IPv4 address.\n",
|
|
|
|
ptr, data, flags);
|
|
|
|
*ptr = data->host;
|
|
|
|
data->host = NULL;
|
|
|
|
return FALSE;
|
|
|
|
} else
|
|
|
|
data->has_implicit_ip = TRUE;
|
|
|
|
}
|
|
|
|
|
2013-03-22 14:29:11 +00:00
|
|
|
data->host_len = *ptr - data->host;
|
|
|
|
data->host_type = Uri_HOST_IPV4;
|
|
|
|
|
Finish the Wine sync. These components are not just rc file changes
atl, comctl32, comdlg32, dwmapi, fusion, gdiplus, jscript, mpr, mshtml, msi, msimtf, msxml3, ole32, oleaut32, riched20, shdocvw, shlwapi, urlmon, usp10, version and windowscodecs
Seems to build and boot. /me hides
svn path=/trunk/; revision=48273
2010-07-26 02:26:04 +00:00
|
|
|
/* Check if what we found is the only part of the host name (if it isn't
|
|
|
|
* we don't have an IPv4 address).
|
|
|
|
*/
|
2010-10-09 21:52:25 +00:00
|
|
|
if(**ptr == ':') {
|
|
|
|
++(*ptr);
|
|
|
|
if(!parse_port(ptr, data, flags)) {
|
|
|
|
*ptr = data->host;
|
|
|
|
data->host = NULL;
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
} else if(!is_auth_delim(**ptr, !is_unknown)) {
|
2013-03-22 14:29:11 +00:00
|
|
|
/* Found more data which belongs to the host, so this isn't an IPv4. */
|
Finish the Wine sync. These components are not just rc file changes
atl, comctl32, comdlg32, dwmapi, fusion, gdiplus, jscript, mpr, mshtml, msi, msimtf, msxml3, ole32, oleaut32, riched20, shdocvw, shlwapi, urlmon, usp10, version and windowscodecs
Seems to build and boot. /me hides
svn path=/trunk/; revision=48273
2010-07-26 02:26:04 +00:00
|
|
|
*ptr = data->host;
|
|
|
|
data->host = NULL;
|
|
|
|
data->has_implicit_ip = FALSE;
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
TRACE("(%p %p %x): IPv4 address found. host=%s host_len=%d host_type=%d\n",
|
|
|
|
ptr, data, flags, debugstr_wn(data->host, data->host_len),
|
|
|
|
data->host_len, data->host_type);
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
2010-10-09 21:52:25 +00:00
|
|
|
/* Attempts to parse the reg-name from the URI.
|
Finish the Wine sync. These components are not just rc file changes
atl, comctl32, comdlg32, dwmapi, fusion, gdiplus, jscript, mpr, mshtml, msi, msimtf, msxml3, ole32, oleaut32, riched20, shdocvw, shlwapi, urlmon, usp10, version and windowscodecs
Seems to build and boot. /me hides
svn path=/trunk/; revision=48273
2010-07-26 02:26:04 +00:00
|
|
|
*
|
2010-10-09 21:52:25 +00:00
|
|
|
* Because of the way Windows handles ':' this function also
|
|
|
|
* handles parsing the port.
|
Finish the Wine sync. These components are not just rc file changes
atl, comctl32, comdlg32, dwmapi, fusion, gdiplus, jscript, mpr, mshtml, msi, msimtf, msxml3, ole32, oleaut32, riched20, shdocvw, shlwapi, urlmon, usp10, version and windowscodecs
Seems to build and boot. /me hides
svn path=/trunk/; revision=48273
2010-07-26 02:26:04 +00:00
|
|
|
*
|
2010-10-09 21:52:25 +00:00
|
|
|
* reg-name = *( unreserved / pct-encoded / sub-delims )
|
Finish the Wine sync. These components are not just rc file changes
atl, comctl32, comdlg32, dwmapi, fusion, gdiplus, jscript, mpr, mshtml, msi, msimtf, msxml3, ole32, oleaut32, riched20, shdocvw, shlwapi, urlmon, usp10, version and windowscodecs
Seems to build and boot. /me hides
svn path=/trunk/; revision=48273
2010-07-26 02:26:04 +00:00
|
|
|
*
|
2010-10-09 21:52:25 +00:00
|
|
|
* NOTE:
|
|
|
|
* Windows allows everything, but, the characters in "auth_delims" and ':'
|
|
|
|
* to appear in a reg-name, unless it's an unknown scheme type then ':' is
|
|
|
|
* allowed to appear (even if a valid port isn't after it).
|
Finish the Wine sync. These components are not just rc file changes
atl, comctl32, comdlg32, dwmapi, fusion, gdiplus, jscript, mpr, mshtml, msi, msimtf, msxml3, ole32, oleaut32, riched20, shdocvw, shlwapi, urlmon, usp10, version and windowscodecs
Seems to build and boot. /me hides
svn path=/trunk/; revision=48273
2010-07-26 02:26:04 +00:00
|
|
|
*
|
2010-10-09 21:52:25 +00:00
|
|
|
* Windows doesn't like host names which start with '[' and end with ']'
|
|
|
|
* and don't contain a valid IP literal address in between them.
|
Finish the Wine sync. These components are not just rc file changes
atl, comctl32, comdlg32, dwmapi, fusion, gdiplus, jscript, mpr, mshtml, msi, msimtf, msxml3, ole32, oleaut32, riched20, shdocvw, shlwapi, urlmon, usp10, version and windowscodecs
Seems to build and boot. /me hides
svn path=/trunk/; revision=48273
2010-07-26 02:26:04 +00:00
|
|
|
*
|
2013-03-22 14:29:11 +00:00
|
|
|
* On Windows if a '[' is encountered in the host name the ':' no longer
|
|
|
|
* counts as a delimiter until you reach the next ']' or an "authority delimiter".
|
Finish the Wine sync. These components are not just rc file changes
atl, comctl32, comdlg32, dwmapi, fusion, gdiplus, jscript, mpr, mshtml, msi, msimtf, msxml3, ole32, oleaut32, riched20, shdocvw, shlwapi, urlmon, usp10, version and windowscodecs
Seems to build and boot. /me hides
svn path=/trunk/; revision=48273
2010-07-26 02:26:04 +00:00
|
|
|
*
|
2010-10-09 21:52:25 +00:00
|
|
|
* A reg-name CAN be empty.
|
Finish the Wine sync. These components are not just rc file changes
atl, comctl32, comdlg32, dwmapi, fusion, gdiplus, jscript, mpr, mshtml, msi, msimtf, msxml3, ole32, oleaut32, riched20, shdocvw, shlwapi, urlmon, usp10, version and windowscodecs
Seems to build and boot. /me hides
svn path=/trunk/; revision=48273
2010-07-26 02:26:04 +00:00
|
|
|
*/
|
2010-10-09 21:52:25 +00:00
|
|
|
static BOOL parse_reg_name(const WCHAR **ptr, parse_data *data, DWORD flags, DWORD extras) {
|
|
|
|
const BOOL has_start_bracket = **ptr == '[';
|
|
|
|
const BOOL known_scheme = data->scheme_type != URL_SCHEME_UNKNOWN;
|
2010-12-20 21:29:55 +00:00
|
|
|
const BOOL is_res = data->scheme_type == URL_SCHEME_RES;
|
2010-10-09 21:52:25 +00:00
|
|
|
BOOL inside_brackets = has_start_bracket;
|
2010-12-20 21:29:55 +00:00
|
|
|
|
|
|
|
/* res URIs don't have ports. */
|
|
|
|
BOOL ignore_col = (extras & IGNORE_PORT_DELIMITER) || is_res;
|
2010-10-09 21:52:25 +00:00
|
|
|
|
|
|
|
/* We have to be careful with file schemes. */
|
|
|
|
if(data->scheme_type == URL_SCHEME_FILE) {
|
|
|
|
/* This is because an implicit file scheme could be "C:\\test" and it
|
|
|
|
* would trick this function into thinking the host is "C", when after
|
|
|
|
* canonicalization the host would end up being an empty string. A drive
|
|
|
|
* path can also have a '|' instead of a ':' after the drive letter.
|
Finish the Wine sync. These components are not just rc file changes
atl, comctl32, comdlg32, dwmapi, fusion, gdiplus, jscript, mpr, mshtml, msi, msimtf, msxml3, ole32, oleaut32, riched20, shdocvw, shlwapi, urlmon, usp10, version and windowscodecs
Seems to build and boot. /me hides
svn path=/trunk/; revision=48273
2010-07-26 02:26:04 +00:00
|
|
|
*/
|
2010-10-09 21:52:25 +00:00
|
|
|
if(is_drive_path(*ptr)) {
|
2013-03-22 14:29:11 +00:00
|
|
|
/* Regular old drive paths have no host type (or host name). */
|
2010-10-09 21:52:25 +00:00
|
|
|
data->host_type = Uri_HOST_UNKNOWN;
|
|
|
|
data->host = *ptr;
|
|
|
|
data->host_len = 0;
|
|
|
|
return TRUE;
|
|
|
|
} else if(is_unc_path(*ptr))
|
|
|
|
/* Skip past the "\\" of a UNC path. */
|
|
|
|
*ptr += 2;
|
|
|
|
}
|
Finish the Wine sync. These components are not just rc file changes
atl, comctl32, comdlg32, dwmapi, fusion, gdiplus, jscript, mpr, mshtml, msi, msimtf, msxml3, ole32, oleaut32, riched20, shdocvw, shlwapi, urlmon, usp10, version and windowscodecs
Seems to build and boot. /me hides
svn path=/trunk/; revision=48273
2010-07-26 02:26:04 +00:00
|
|
|
|
2010-10-09 21:52:25 +00:00
|
|
|
data->host = *ptr;
|
|
|
|
|
2010-12-20 21:29:55 +00:00
|
|
|
/* For res URIs, everything before the first '/' is
|
|
|
|
* considered the host.
|
|
|
|
*/
|
|
|
|
while((!is_res && !is_auth_delim(**ptr, known_scheme)) ||
|
|
|
|
(is_res && **ptr && **ptr != '/')) {
|
2010-10-09 21:52:25 +00:00
|
|
|
if(**ptr == ':' && !ignore_col) {
|
2016-03-05 10:27:46 +00:00
|
|
|
/* We can ignore ':' if we are inside brackets.*/
|
2010-10-09 21:52:25 +00:00
|
|
|
if(!inside_brackets) {
|
|
|
|
const WCHAR *tmp = (*ptr)++;
|
|
|
|
|
|
|
|
/* Attempt to parse the port. */
|
|
|
|
if(!parse_port(ptr, data, flags)) {
|
|
|
|
/* Windows expects there to be a valid port for known scheme types. */
|
|
|
|
if(data->scheme_type != URL_SCHEME_UNKNOWN) {
|
|
|
|
*ptr = data->host;
|
|
|
|
data->host = NULL;
|
|
|
|
TRACE("(%p %p %x %x): Expected valid port\n", ptr, data, flags, extras);
|
|
|
|
return FALSE;
|
|
|
|
} else
|
|
|
|
/* Windows gives up on trying to parse a port when it
|
2013-03-22 14:29:11 +00:00
|
|
|
* encounters an invalid port.
|
2010-10-09 21:52:25 +00:00
|
|
|
*/
|
|
|
|
ignore_col = TRUE;
|
|
|
|
} else {
|
|
|
|
data->host_len = tmp - data->host;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2010-12-20 21:29:55 +00:00
|
|
|
} else if(**ptr == '%' && (known_scheme && !is_res)) {
|
2010-10-09 21:52:25 +00:00
|
|
|
/* Has to be a legit % encoded value. */
|
|
|
|
if(!check_pct_encoded(ptr)) {
|
|
|
|
*ptr = data->host;
|
|
|
|
data->host = NULL;
|
Finish the Wine sync. These components are not just rc file changes
atl, comctl32, comdlg32, dwmapi, fusion, gdiplus, jscript, mpr, mshtml, msi, msimtf, msxml3, ole32, oleaut32, riched20, shdocvw, shlwapi, urlmon, usp10, version and windowscodecs
Seems to build and boot. /me hides
svn path=/trunk/; revision=48273
2010-07-26 02:26:04 +00:00
|
|
|
return FALSE;
|
2010-10-09 21:52:25 +00:00
|
|
|
} else
|
|
|
|
continue;
|
2010-12-20 21:29:55 +00:00
|
|
|
} else if(is_res && is_forbidden_dos_path_char(**ptr)) {
|
|
|
|
*ptr = data->host;
|
|
|
|
data->host = NULL;
|
|
|
|
return FALSE;
|
2010-10-09 21:52:25 +00:00
|
|
|
} else if(**ptr == ']')
|
|
|
|
inside_brackets = FALSE;
|
|
|
|
else if(**ptr == '[')
|
|
|
|
inside_brackets = TRUE;
|
Finish the Wine sync. These components are not just rc file changes
atl, comctl32, comdlg32, dwmapi, fusion, gdiplus, jscript, mpr, mshtml, msi, msimtf, msxml3, ole32, oleaut32, riched20, shdocvw, shlwapi, urlmon, usp10, version and windowscodecs
Seems to build and boot. /me hides
svn path=/trunk/; revision=48273
2010-07-26 02:26:04 +00:00
|
|
|
|
2010-10-09 21:52:25 +00:00
|
|
|
++(*ptr);
|
|
|
|
}
|
|
|
|
|
|
|
|
if(has_start_bracket) {
|
|
|
|
/* Make sure the last character of the host wasn't a ']'. */
|
|
|
|
if(*(*ptr-1) == ']') {
|
|
|
|
TRACE("(%p %p %x %x): Expected an IP literal inside of the host\n",
|
|
|
|
ptr, data, flags, extras);
|
|
|
|
*ptr = data->host;
|
|
|
|
data->host = NULL;
|
|
|
|
return FALSE;
|
Finish the Wine sync. These components are not just rc file changes
atl, comctl32, comdlg32, dwmapi, fusion, gdiplus, jscript, mpr, mshtml, msi, msimtf, msxml3, ole32, oleaut32, riched20, shdocvw, shlwapi, urlmon, usp10, version and windowscodecs
Seems to build and boot. /me hides
svn path=/trunk/; revision=48273
2010-07-26 02:26:04 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-10-09 21:52:25 +00:00
|
|
|
/* Don't overwrite our length if we found a port earlier. */
|
|
|
|
if(!data->port)
|
|
|
|
data->host_len = *ptr - data->host;
|
Finish the Wine sync. These components are not just rc file changes
atl, comctl32, comdlg32, dwmapi, fusion, gdiplus, jscript, mpr, mshtml, msi, msimtf, msxml3, ole32, oleaut32, riched20, shdocvw, shlwapi, urlmon, usp10, version and windowscodecs
Seems to build and boot. /me hides
svn path=/trunk/; revision=48273
2010-07-26 02:26:04 +00:00
|
|
|
|
2010-10-09 21:52:25 +00:00
|
|
|
/* If the host is empty, then it's an unknown host type. */
|
2010-12-20 21:29:55 +00:00
|
|
|
if(data->host_len == 0 || is_res)
|
2010-10-09 21:52:25 +00:00
|
|
|
data->host_type = Uri_HOST_UNKNOWN;
|
|
|
|
else
|
|
|
|
data->host_type = Uri_HOST_DNS;
|
Finish the Wine sync. These components are not just rc file changes
atl, comctl32, comdlg32, dwmapi, fusion, gdiplus, jscript, mpr, mshtml, msi, msimtf, msxml3, ole32, oleaut32, riched20, shdocvw, shlwapi, urlmon, usp10, version and windowscodecs
Seems to build and boot. /me hides
svn path=/trunk/; revision=48273
2010-07-26 02:26:04 +00:00
|
|
|
|
2010-10-09 21:52:25 +00:00
|
|
|
TRACE("(%p %p %x %x): Parsed reg-name. host=%s len=%d\n", ptr, data, flags, extras,
|
|
|
|
debugstr_wn(data->host, data->host_len), data->host_len);
|
Finish the Wine sync. These components are not just rc file changes
atl, comctl32, comdlg32, dwmapi, fusion, gdiplus, jscript, mpr, mshtml, msi, msimtf, msxml3, ole32, oleaut32, riched20, shdocvw, shlwapi, urlmon, usp10, version and windowscodecs
Seems to build and boot. /me hides
svn path=/trunk/; revision=48273
2010-07-26 02:26:04 +00:00
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
2010-10-09 21:52:25 +00:00
|
|
|
/* Attempts to parse an IPv6 address out of the URI.
|
Finish the Wine sync. These components are not just rc file changes
atl, comctl32, comdlg32, dwmapi, fusion, gdiplus, jscript, mpr, mshtml, msi, msimtf, msxml3, ole32, oleaut32, riched20, shdocvw, shlwapi, urlmon, usp10, version and windowscodecs
Seems to build and boot. /me hides
svn path=/trunk/; revision=48273
2010-07-26 02:26:04 +00:00
|
|
|
*
|
2010-10-09 21:52:25 +00:00
|
|
|
* IPv6address = 6( h16 ":" ) ls32
|
|
|
|
* / "::" 5( h16 ":" ) ls32
|
|
|
|
* / [ h16 ] "::" 4( h16 ":" ) ls32
|
|
|
|
* / [ *1( h16 ":" ) h16 ] "::" 3( h16 ":" ) ls32
|
|
|
|
* / [ *2( h16 ":" ) h16 ] "::" 2( h16 ":" ) ls32
|
|
|
|
* / [ *3( h16 ":" ) h16 ] "::" h16 ":" ls32
|
|
|
|
* / [ *4( h16 ":" ) h16 ] "::" ls32
|
|
|
|
* / [ *5( h16 ":" ) h16 ] "::" h16
|
|
|
|
* / [ *6( h16 ":" ) h16 ] "::"
|
|
|
|
*
|
|
|
|
* ls32 = ( h16 ":" h16 ) / IPv4address
|
|
|
|
* ; least-significant 32 bits of address.
|
|
|
|
*
|
|
|
|
* h16 = 1*4HEXDIG
|
|
|
|
* ; 16 bits of address represented in hexadecimal.
|
|
|
|
*
|
|
|
|
* Modeled after google-url's 'DoParseIPv6' function.
|
Finish the Wine sync. These components are not just rc file changes
atl, comctl32, comdlg32, dwmapi, fusion, gdiplus, jscript, mpr, mshtml, msi, msimtf, msxml3, ole32, oleaut32, riched20, shdocvw, shlwapi, urlmon, usp10, version and windowscodecs
Seems to build and boot. /me hides
svn path=/trunk/; revision=48273
2010-07-26 02:26:04 +00:00
|
|
|
*/
|
2010-10-09 21:52:25 +00:00
|
|
|
static BOOL parse_ipv6address(const WCHAR **ptr, parse_data *data, DWORD flags) {
|
|
|
|
const WCHAR *start, *cur_start;
|
|
|
|
ipv6_address ip;
|
Finish the Wine sync. These components are not just rc file changes
atl, comctl32, comdlg32, dwmapi, fusion, gdiplus, jscript, mpr, mshtml, msi, msimtf, msxml3, ole32, oleaut32, riched20, shdocvw, shlwapi, urlmon, usp10, version and windowscodecs
Seems to build and boot. /me hides
svn path=/trunk/; revision=48273
2010-07-26 02:26:04 +00:00
|
|
|
|
2010-10-09 21:52:25 +00:00
|
|
|
start = cur_start = *ptr;
|
|
|
|
memset(&ip, 0, sizeof(ipv6_address));
|
Finish the Wine sync. These components are not just rc file changes
atl, comctl32, comdlg32, dwmapi, fusion, gdiplus, jscript, mpr, mshtml, msi, msimtf, msxml3, ole32, oleaut32, riched20, shdocvw, shlwapi, urlmon, usp10, version and windowscodecs
Seems to build and boot. /me hides
svn path=/trunk/; revision=48273
2010-07-26 02:26:04 +00:00
|
|
|
|
2010-10-09 21:52:25 +00:00
|
|
|
for(;; ++(*ptr)) {
|
|
|
|
/* Check if we're on the last character of the host. */
|
|
|
|
BOOL is_end = (is_auth_delim(**ptr, data->scheme_type != URL_SCHEME_UNKNOWN)
|
|
|
|
|| **ptr == ']');
|
Finish the Wine sync. These components are not just rc file changes
atl, comctl32, comdlg32, dwmapi, fusion, gdiplus, jscript, mpr, mshtml, msi, msimtf, msxml3, ole32, oleaut32, riched20, shdocvw, shlwapi, urlmon, usp10, version and windowscodecs
Seems to build and boot. /me hides
svn path=/trunk/; revision=48273
2010-07-26 02:26:04 +00:00
|
|
|
|
2010-10-09 21:52:25 +00:00
|
|
|
BOOL is_split = (**ptr == ':');
|
|
|
|
BOOL is_elision = (is_split && !is_end && *(*ptr+1) == ':');
|
Finish the Wine sync. These components are not just rc file changes
atl, comctl32, comdlg32, dwmapi, fusion, gdiplus, jscript, mpr, mshtml, msi, msimtf, msxml3, ole32, oleaut32, riched20, shdocvw, shlwapi, urlmon, usp10, version and windowscodecs
Seems to build and boot. /me hides
svn path=/trunk/; revision=48273
2010-07-26 02:26:04 +00:00
|
|
|
|
2010-10-09 21:52:25 +00:00
|
|
|
/* Check if we're at the end of a component, or
|
|
|
|
* if we're at the end of the IPv6 address.
|
|
|
|
*/
|
|
|
|
if(is_split || is_end) {
|
|
|
|
DWORD cur_len = 0;
|
Finish the Wine sync. These components are not just rc file changes
atl, comctl32, comdlg32, dwmapi, fusion, gdiplus, jscript, mpr, mshtml, msi, msimtf, msxml3, ole32, oleaut32, riched20, shdocvw, shlwapi, urlmon, usp10, version and windowscodecs
Seems to build and boot. /me hides
svn path=/trunk/; revision=48273
2010-07-26 02:26:04 +00:00
|
|
|
|
2010-10-09 21:52:25 +00:00
|
|
|
cur_len = *ptr - cur_start;
|
Finish the Wine sync. These components are not just rc file changes
atl, comctl32, comdlg32, dwmapi, fusion, gdiplus, jscript, mpr, mshtml, msi, msimtf, msxml3, ole32, oleaut32, riched20, shdocvw, shlwapi, urlmon, usp10, version and windowscodecs
Seems to build and boot. /me hides
svn path=/trunk/; revision=48273
2010-07-26 02:26:04 +00:00
|
|
|
|
2010-10-09 21:52:25 +00:00
|
|
|
/* h16 can't have a length > 4. */
|
|
|
|
if(cur_len > 4) {
|
|
|
|
*ptr = start;
|
Finish the Wine sync. These components are not just rc file changes
atl, comctl32, comdlg32, dwmapi, fusion, gdiplus, jscript, mpr, mshtml, msi, msimtf, msxml3, ole32, oleaut32, riched20, shdocvw, shlwapi, urlmon, usp10, version and windowscodecs
Seems to build and boot. /me hides
svn path=/trunk/; revision=48273
2010-07-26 02:26:04 +00:00
|
|
|
|
2010-10-09 21:52:25 +00:00
|
|
|
TRACE("(%p %p %x): h16 component to long.\n",
|
|
|
|
ptr, data, flags);
|
|
|
|
return FALSE;
|
|
|
|
}
|
Finish the Wine sync. These components are not just rc file changes
atl, comctl32, comdlg32, dwmapi, fusion, gdiplus, jscript, mpr, mshtml, msi, msimtf, msxml3, ole32, oleaut32, riched20, shdocvw, shlwapi, urlmon, usp10, version and windowscodecs
Seems to build and boot. /me hides
svn path=/trunk/; revision=48273
2010-07-26 02:26:04 +00:00
|
|
|
|
2010-10-09 21:52:25 +00:00
|
|
|
if(cur_len == 0) {
|
|
|
|
/* An h16 component can't have the length of 0 unless
|
|
|
|
* the elision is at the beginning of the address, or
|
|
|
|
* at the end of the address.
|
|
|
|
*/
|
|
|
|
if(!((*ptr == start && is_elision) ||
|
|
|
|
(is_end && (*ptr-2) == ip.elision))) {
|
|
|
|
*ptr = start;
|
|
|
|
TRACE("(%p %p %x): IPv6 component cannot have a length of 0.\n",
|
|
|
|
ptr, data, flags);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
}
|
Finish the Wine sync. These components are not just rc file changes
atl, comctl32, comdlg32, dwmapi, fusion, gdiplus, jscript, mpr, mshtml, msi, msimtf, msxml3, ole32, oleaut32, riched20, shdocvw, shlwapi, urlmon, usp10, version and windowscodecs
Seems to build and boot. /me hides
svn path=/trunk/; revision=48273
2010-07-26 02:26:04 +00:00
|
|
|
|
2010-10-09 21:52:25 +00:00
|
|
|
if(cur_len > 0) {
|
|
|
|
/* An IPv6 address can have no more than 8 h16 components. */
|
|
|
|
if(ip.h16_count >= 8) {
|
|
|
|
*ptr = start;
|
2014-04-23 17:35:17 +00:00
|
|
|
TRACE("(%p %p %x): Not a IPv6 address, too many h16 components.\n",
|
2010-10-09 21:52:25 +00:00
|
|
|
ptr, data, flags);
|
|
|
|
return FALSE;
|
|
|
|
}
|
Finish the Wine sync. These components are not just rc file changes
atl, comctl32, comdlg32, dwmapi, fusion, gdiplus, jscript, mpr, mshtml, msi, msimtf, msxml3, ole32, oleaut32, riched20, shdocvw, shlwapi, urlmon, usp10, version and windowscodecs
Seems to build and boot. /me hides
svn path=/trunk/; revision=48273
2010-07-26 02:26:04 +00:00
|
|
|
|
2010-10-09 21:52:25 +00:00
|
|
|
ip.components[ip.h16_count].str = cur_start;
|
|
|
|
ip.components[ip.h16_count].len = cur_len;
|
Finish the Wine sync. These components are not just rc file changes
atl, comctl32, comdlg32, dwmapi, fusion, gdiplus, jscript, mpr, mshtml, msi, msimtf, msxml3, ole32, oleaut32, riched20, shdocvw, shlwapi, urlmon, usp10, version and windowscodecs
Seems to build and boot. /me hides
svn path=/trunk/; revision=48273
2010-07-26 02:26:04 +00:00
|
|
|
|
2010-10-09 21:52:25 +00:00
|
|
|
TRACE("(%p %p %x): Found h16 component %s, len=%d, h16_count=%d\n",
|
|
|
|
ptr, data, flags, debugstr_wn(cur_start, cur_len), cur_len,
|
|
|
|
ip.h16_count);
|
|
|
|
++ip.h16_count;
|
|
|
|
}
|
|
|
|
}
|
Finish the Wine sync. These components are not just rc file changes
atl, comctl32, comdlg32, dwmapi, fusion, gdiplus, jscript, mpr, mshtml, msi, msimtf, msxml3, ole32, oleaut32, riched20, shdocvw, shlwapi, urlmon, usp10, version and windowscodecs
Seems to build and boot. /me hides
svn path=/trunk/; revision=48273
2010-07-26 02:26:04 +00:00
|
|
|
|
2010-10-09 21:52:25 +00:00
|
|
|
if(is_end)
|
|
|
|
break;
|
|
|
|
|
|
|
|
if(is_elision) {
|
|
|
|
/* A IPv6 address can only have 1 elision ('::'). */
|
|
|
|
if(ip.elision) {
|
|
|
|
*ptr = start;
|
|
|
|
|
|
|
|
TRACE("(%p %p %x): IPv6 address cannot have 2 elisions.\n",
|
|
|
|
ptr, data, flags);
|
|
|
|
return FALSE;
|
Finish the Wine sync. These components are not just rc file changes
atl, comctl32, comdlg32, dwmapi, fusion, gdiplus, jscript, mpr, mshtml, msi, msimtf, msxml3, ole32, oleaut32, riched20, shdocvw, shlwapi, urlmon, usp10, version and windowscodecs
Seems to build and boot. /me hides
svn path=/trunk/; revision=48273
2010-07-26 02:26:04 +00:00
|
|
|
}
|
|
|
|
|
2010-10-09 21:52:25 +00:00
|
|
|
ip.elision = *ptr;
|
|
|
|
++(*ptr);
|
|
|
|
}
|
|
|
|
|
|
|
|
if(is_split)
|
|
|
|
cur_start = *ptr+1;
|
|
|
|
else {
|
|
|
|
if(!check_ipv4address(ptr, TRUE)) {
|
|
|
|
if(!is_hexdigit(**ptr)) {
|
|
|
|
/* Not a valid character for an IPv6 address. */
|
|
|
|
*ptr = start;
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
/* Found an IPv4 address. */
|
|
|
|
ip.ipv4 = cur_start;
|
|
|
|
ip.ipv4_len = *ptr - cur_start;
|
|
|
|
|
|
|
|
TRACE("(%p %p %x): Found an attached IPv4 address %s len=%d.\n",
|
|
|
|
ptr, data, flags, debugstr_wn(ip.ipv4, ip.ipv4_len),
|
|
|
|
ip.ipv4_len);
|
|
|
|
|
|
|
|
/* IPv4 addresses can only appear at the end of a IPv6. */
|
|
|
|
break;
|
Finish the Wine sync. These components are not just rc file changes
atl, comctl32, comdlg32, dwmapi, fusion, gdiplus, jscript, mpr, mshtml, msi, msimtf, msxml3, ole32, oleaut32, riched20, shdocvw, shlwapi, urlmon, usp10, version and windowscodecs
Seems to build and boot. /me hides
svn path=/trunk/; revision=48273
2010-07-26 02:26:04 +00:00
|
|
|
}
|
|
|
|
}
|
2010-10-09 21:52:25 +00:00
|
|
|
}
|
Finish the Wine sync. These components are not just rc file changes
atl, comctl32, comdlg32, dwmapi, fusion, gdiplus, jscript, mpr, mshtml, msi, msimtf, msxml3, ole32, oleaut32, riched20, shdocvw, shlwapi, urlmon, usp10, version and windowscodecs
Seems to build and boot. /me hides
svn path=/trunk/; revision=48273
2010-07-26 02:26:04 +00:00
|
|
|
|
2010-10-09 21:52:25 +00:00
|
|
|
compute_ipv6_comps_size(&ip);
|
Finish the Wine sync. These components are not just rc file changes
atl, comctl32, comdlg32, dwmapi, fusion, gdiplus, jscript, mpr, mshtml, msi, msimtf, msxml3, ole32, oleaut32, riched20, shdocvw, shlwapi, urlmon, usp10, version and windowscodecs
Seems to build and boot. /me hides
svn path=/trunk/; revision=48273
2010-07-26 02:26:04 +00:00
|
|
|
|
2010-10-09 21:52:25 +00:00
|
|
|
/* Make sure the IPv6 address adds up to 16 bytes. */
|
|
|
|
if(ip.components_size + ip.elision_size != 16) {
|
|
|
|
*ptr = start;
|
|
|
|
TRACE("(%p %p %x): Invalid IPv6 address, did not add up to 16 bytes.\n",
|
|
|
|
ptr, data, flags);
|
|
|
|
return FALSE;
|
Finish the Wine sync. These components are not just rc file changes
atl, comctl32, comdlg32, dwmapi, fusion, gdiplus, jscript, mpr, mshtml, msi, msimtf, msxml3, ole32, oleaut32, riched20, shdocvw, shlwapi, urlmon, usp10, version and windowscodecs
Seems to build and boot. /me hides
svn path=/trunk/; revision=48273
2010-07-26 02:26:04 +00:00
|
|
|
}
|
|
|
|
|
2010-10-09 21:52:25 +00:00
|
|
|
if(ip.elision_size == 2) {
|
|
|
|
/* For some reason on Windows if an elision that represents
|
2013-03-22 14:29:11 +00:00
|
|
|
* only one h16 component is encountered at the very begin or
|
2010-10-09 21:52:25 +00:00
|
|
|
* end of an IPv6 address, Windows does not consider it a
|
|
|
|
* valid IPv6 address.
|
|
|
|
*
|
|
|
|
* Ex: [::2:3:4:5:6:7] is not valid, even though the sum
|
|
|
|
* of all the components == 128bits.
|
|
|
|
*/
|
|
|
|
if(ip.elision < ip.components[0].str ||
|
|
|
|
ip.elision > ip.components[ip.h16_count-1].str) {
|
|
|
|
*ptr = start;
|
|
|
|
TRACE("(%p %p %x): Invalid IPv6 address. Detected elision of 2 bytes at the beginning or end of the address.\n",
|
|
|
|
ptr, data, flags);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
}
|
Finish the Wine sync. These components are not just rc file changes
atl, comctl32, comdlg32, dwmapi, fusion, gdiplus, jscript, mpr, mshtml, msi, msimtf, msxml3, ole32, oleaut32, riched20, shdocvw, shlwapi, urlmon, usp10, version and windowscodecs
Seems to build and boot. /me hides
svn path=/trunk/; revision=48273
2010-07-26 02:26:04 +00:00
|
|
|
|
2010-10-09 21:52:25 +00:00
|
|
|
data->host_type = Uri_HOST_IPV6;
|
|
|
|
data->has_ipv6 = TRUE;
|
|
|
|
data->ipv6_address = ip;
|
Finish the Wine sync. These components are not just rc file changes
atl, comctl32, comdlg32, dwmapi, fusion, gdiplus, jscript, mpr, mshtml, msi, msimtf, msxml3, ole32, oleaut32, riched20, shdocvw, shlwapi, urlmon, usp10, version and windowscodecs
Seems to build and boot. /me hides
svn path=/trunk/; revision=48273
2010-07-26 02:26:04 +00:00
|
|
|
|
2010-10-09 21:52:25 +00:00
|
|
|
TRACE("(%p %p %x): Found valid IPv6 literal %s len=%d\n",
|
|
|
|
ptr, data, flags, debugstr_wn(start, *ptr-start),
|
2011-06-05 21:29:41 +00:00
|
|
|
(int)(*ptr-start));
|
Finish the Wine sync. These components are not just rc file changes
atl, comctl32, comdlg32, dwmapi, fusion, gdiplus, jscript, mpr, mshtml, msi, msimtf, msxml3, ole32, oleaut32, riched20, shdocvw, shlwapi, urlmon, usp10, version and windowscodecs
Seems to build and boot. /me hides
svn path=/trunk/; revision=48273
2010-07-26 02:26:04 +00:00
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
2010-10-09 21:52:25 +00:00
|
|
|
/* IPvFuture = "v" 1*HEXDIG "." 1*( unreserved / sub-delims / ":" ) */
|
|
|
|
static BOOL parse_ipvfuture(const WCHAR **ptr, parse_data *data, DWORD flags) {
|
|
|
|
const WCHAR *start = *ptr;
|
|
|
|
|
|
|
|
/* IPvFuture has to start with a 'v' or 'V'. */
|
|
|
|
if(**ptr != 'v' && **ptr != 'V')
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
/* Following the v there must be at least 1 hex digit. */
|
|
|
|
++(*ptr);
|
|
|
|
if(!is_hexdigit(**ptr)) {
|
|
|
|
*ptr = start;
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
++(*ptr);
|
|
|
|
while(is_hexdigit(**ptr))
|
|
|
|
++(*ptr);
|
|
|
|
|
|
|
|
/* End of the hexdigit sequence must be a '.' */
|
|
|
|
if(**ptr != '.') {
|
|
|
|
*ptr = start;
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
++(*ptr);
|
|
|
|
if(!is_unreserved(**ptr) && !is_subdelim(**ptr) && **ptr != ':') {
|
|
|
|
*ptr = start;
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
++(*ptr);
|
|
|
|
while(is_unreserved(**ptr) || is_subdelim(**ptr) || **ptr == ':')
|
|
|
|
++(*ptr);
|
|
|
|
|
|
|
|
data->host_type = Uri_HOST_UNKNOWN;
|
|
|
|
|
|
|
|
TRACE("(%p %p %x): Parsed IPvFuture address %s len=%d\n", ptr, data, flags,
|
2011-06-05 21:29:41 +00:00
|
|
|
debugstr_wn(start, *ptr-start), (int)(*ptr-start));
|
2010-10-09 21:52:25 +00:00
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* IP-literal = "[" ( IPv6address / IPvFuture ) "]" */
|
|
|
|
static BOOL parse_ip_literal(const WCHAR **ptr, parse_data *data, DWORD flags, DWORD extras) {
|
|
|
|
data->host = *ptr;
|
|
|
|
|
|
|
|
if(**ptr != '[' && !(extras & ALLOW_BRACKETLESS_IP_LITERAL)) {
|
|
|
|
data->host = NULL;
|
|
|
|
return FALSE;
|
|
|
|
} else if(**ptr == '[')
|
|
|
|
++(*ptr);
|
|
|
|
|
|
|
|
if(!parse_ipv6address(ptr, data, flags)) {
|
|
|
|
if(extras & SKIP_IP_FUTURE_CHECK || !parse_ipvfuture(ptr, data, flags)) {
|
|
|
|
*ptr = data->host;
|
|
|
|
data->host = NULL;
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if(**ptr != ']' && !(extras & ALLOW_BRACKETLESS_IP_LITERAL)) {
|
|
|
|
*ptr = data->host;
|
|
|
|
data->host = NULL;
|
|
|
|
return FALSE;
|
|
|
|
} else if(!**ptr && extras & ALLOW_BRACKETLESS_IP_LITERAL) {
|
|
|
|
/* The IP literal didn't contain brackets and was followed by
|
|
|
|
* a NULL terminator, so no reason to even check the port.
|
|
|
|
*/
|
|
|
|
data->host_len = *ptr - data->host;
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
++(*ptr);
|
|
|
|
if(**ptr == ':') {
|
|
|
|
++(*ptr);
|
|
|
|
/* If a valid port is not found, then let it trickle down to
|
|
|
|
* parse_reg_name.
|
|
|
|
*/
|
|
|
|
if(!parse_port(ptr, data, flags)) {
|
|
|
|
*ptr = data->host;
|
|
|
|
data->host = NULL;
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
} else
|
|
|
|
data->host_len = *ptr - data->host;
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Parses the host information from the URI.
|
|
|
|
*
|
|
|
|
* host = IP-literal / IPv4address / reg-name
|
|
|
|
*/
|
|
|
|
static BOOL parse_host(const WCHAR **ptr, parse_data *data, DWORD flags, DWORD extras) {
|
|
|
|
if(!parse_ip_literal(ptr, data, flags, extras)) {
|
|
|
|
if(!parse_ipv4address(ptr, data, flags)) {
|
|
|
|
if(!parse_reg_name(ptr, data, flags, extras)) {
|
|
|
|
TRACE("(%p %p %x %x): Malformed URI, Unknown host type.\n",
|
|
|
|
ptr, data, flags, extras);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Parses the authority information from the URI.
|
|
|
|
*
|
|
|
|
* authority = [ userinfo "@" ] host [ ":" port ]
|
|
|
|
*/
|
|
|
|
static BOOL parse_authority(const WCHAR **ptr, parse_data *data, DWORD flags) {
|
|
|
|
parse_userinfo(ptr, data, flags);
|
|
|
|
|
|
|
|
/* Parsing the port will happen during one of the host parsing
|
|
|
|
* routines (if the URI has a port).
|
|
|
|
*/
|
|
|
|
if(!parse_host(ptr, data, flags, 0))
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Attempts to parse the path information of a hierarchical URI. */
|
|
|
|
static BOOL parse_path_hierarchical(const WCHAR **ptr, parse_data *data, DWORD flags) {
|
|
|
|
const WCHAR *start = *ptr;
|
|
|
|
static const WCHAR slash[] = {'/',0};
|
|
|
|
const BOOL is_file = data->scheme_type == URL_SCHEME_FILE;
|
|
|
|
|
2014-09-25 15:39:47 +00:00
|
|
|
if(is_path_delim(data->scheme_type, **ptr)) {
|
2013-03-22 14:29:11 +00:00
|
|
|
if(data->scheme_type == URL_SCHEME_WILDCARD && !data->must_have_path) {
|
2010-10-09 21:52:25 +00:00
|
|
|
data->path = NULL;
|
|
|
|
data->path_len = 0;
|
|
|
|
} else if(!(flags & Uri_CREATE_NO_CANONICALIZE)) {
|
|
|
|
/* If the path component is empty, then a '/' is added. */
|
|
|
|
data->path = slash;
|
|
|
|
data->path_len = 1;
|
|
|
|
}
|
|
|
|
} else {
|
2014-09-25 15:39:47 +00:00
|
|
|
while(!is_path_delim(data->scheme_type, **ptr)) {
|
2010-10-09 21:52:25 +00:00
|
|
|
if(**ptr == '%' && data->scheme_type != URL_SCHEME_UNKNOWN && !is_file) {
|
|
|
|
if(!check_pct_encoded(ptr)) {
|
|
|
|
*ptr = start;
|
|
|
|
return FALSE;
|
|
|
|
} else
|
|
|
|
continue;
|
|
|
|
} else if(is_forbidden_dos_path_char(**ptr) && is_file &&
|
|
|
|
(flags & Uri_CREATE_FILE_USE_DOS_PATH)) {
|
|
|
|
/* File schemes with USE_DOS_PATH set aren't allowed to have
|
|
|
|
* a '<' or '>' or '\"' appear in them.
|
|
|
|
*/
|
|
|
|
*ptr = start;
|
|
|
|
return FALSE;
|
|
|
|
} else if(**ptr == '\\') {
|
|
|
|
/* Not allowed to have a backslash if NO_CANONICALIZE is set
|
|
|
|
* and the scheme is known type (but not a file scheme).
|
|
|
|
*/
|
|
|
|
if(flags & Uri_CREATE_NO_CANONICALIZE) {
|
|
|
|
if(data->scheme_type != URL_SCHEME_FILE &&
|
|
|
|
data->scheme_type != URL_SCHEME_UNKNOWN) {
|
|
|
|
*ptr = start;
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
++(*ptr);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* The only time a URI doesn't have a path is when
|
|
|
|
* the NO_CANONICALIZE flag is set and the raw URI
|
|
|
|
* didn't contain one.
|
|
|
|
*/
|
|
|
|
if(*ptr == start) {
|
|
|
|
data->path = NULL;
|
|
|
|
data->path_len = 0;
|
|
|
|
} else {
|
|
|
|
data->path = start;
|
|
|
|
data->path_len = *ptr - start;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if(data->path)
|
|
|
|
TRACE("(%p %p %x): Parsed path %s len=%d\n", ptr, data, flags,
|
|
|
|
debugstr_wn(data->path, data->path_len), data->path_len);
|
|
|
|
else
|
|
|
|
TRACE("(%p %p %x): The URI contained no path\n", ptr, data, flags);
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
2014-04-23 17:35:17 +00:00
|
|
|
/* Parses the path of an opaque URI (much less strict than the parser
|
2010-10-09 21:52:25 +00:00
|
|
|
* for a hierarchical URI).
|
|
|
|
*
|
|
|
|
* NOTE:
|
|
|
|
* Windows allows invalid % encoded data to appear in opaque URI paths
|
|
|
|
* for unknown scheme types.
|
|
|
|
*
|
|
|
|
* File schemes with USE_DOS_PATH set aren't allowed to have '<', '>', or '\"'
|
|
|
|
* appear in them.
|
|
|
|
*/
|
|
|
|
static BOOL parse_path_opaque(const WCHAR **ptr, parse_data *data, DWORD flags) {
|
|
|
|
const BOOL known_scheme = data->scheme_type != URL_SCHEME_UNKNOWN;
|
|
|
|
const BOOL is_file = data->scheme_type == URL_SCHEME_FILE;
|
2013-09-28 15:08:52 +00:00
|
|
|
const BOOL is_mailto = data->scheme_type == URL_SCHEME_MAILTO;
|
2010-10-09 21:52:25 +00:00
|
|
|
|
2013-09-28 15:08:52 +00:00
|
|
|
if (is_mailto && (*ptr)[0] == '/' && (*ptr)[1] == '/')
|
|
|
|
{
|
|
|
|
if ((*ptr)[2]) data->path = *ptr + 2;
|
|
|
|
else data->path = NULL;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
data->path = *ptr;
|
2010-10-09 21:52:25 +00:00
|
|
|
|
2014-09-25 15:39:47 +00:00
|
|
|
while(!is_path_delim(data->scheme_type, **ptr)) {
|
2010-10-09 21:52:25 +00:00
|
|
|
if(**ptr == '%' && known_scheme) {
|
|
|
|
if(!check_pct_encoded(ptr)) {
|
|
|
|
*ptr = data->path;
|
|
|
|
data->path = NULL;
|
|
|
|
return FALSE;
|
|
|
|
} else
|
|
|
|
continue;
|
|
|
|
} else if(is_forbidden_dos_path_char(**ptr) && is_file &&
|
|
|
|
(flags & Uri_CREATE_FILE_USE_DOS_PATH)) {
|
|
|
|
*ptr = data->path;
|
|
|
|
data->path = NULL;
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
++(*ptr);
|
|
|
|
}
|
|
|
|
|
2013-09-28 15:08:52 +00:00
|
|
|
if (data->path) data->path_len = *ptr - data->path;
|
2010-10-09 21:52:25 +00:00
|
|
|
TRACE("(%p %p %x): Parsed opaque URI path %s len=%d\n", ptr, data, flags,
|
|
|
|
debugstr_wn(data->path, data->path_len), data->path_len);
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Determines how the URI should be parsed after the scheme information.
|
|
|
|
*
|
2013-03-22 14:29:11 +00:00
|
|
|
* If the scheme is followed by "//", then it is treated as a hierarchical URI
|
2010-10-09 21:52:25 +00:00
|
|
|
* which then the authority and path information will be parsed out. Otherwise, the
|
|
|
|
* URI will be treated as an opaque URI which the authority information is not parsed
|
|
|
|
* out.
|
|
|
|
*
|
|
|
|
* RFC 3896 definition of hier-part:
|
|
|
|
*
|
|
|
|
* hier-part = "//" authority path-abempty
|
|
|
|
* / path-absolute
|
|
|
|
* / path-rootless
|
|
|
|
* / path-empty
|
|
|
|
*
|
|
|
|
* MSDN opaque URI definition:
|
|
|
|
* scheme ":" path [ "#" fragment ]
|
|
|
|
*
|
|
|
|
* NOTES:
|
|
|
|
* If the URI is of an unknown scheme type and has a "//" following the scheme then it
|
|
|
|
* is treated as a hierarchical URI, but, if the CREATE_NO_CRACK_UNKNOWN_SCHEMES flag is
|
2013-03-22 14:29:11 +00:00
|
|
|
* set then it is considered an opaque URI regardless of what follows the scheme information
|
2010-10-09 21:52:25 +00:00
|
|
|
* (per MSDN documentation).
|
|
|
|
*/
|
|
|
|
static BOOL parse_hierpart(const WCHAR **ptr, parse_data *data, DWORD flags) {
|
|
|
|
const WCHAR *start = *ptr;
|
|
|
|
|
2013-03-22 14:29:11 +00:00
|
|
|
data->must_have_path = FALSE;
|
|
|
|
|
|
|
|
/* For javascript: URIs, simply set everything as a path */
|
|
|
|
if(data->scheme_type == URL_SCHEME_JAVASCRIPT) {
|
|
|
|
data->path = *ptr;
|
|
|
|
data->path_len = strlenW(*ptr);
|
|
|
|
data->is_opaque = TRUE;
|
|
|
|
*ptr += data->path_len;
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
2010-10-09 21:52:25 +00:00
|
|
|
/* Checks if the authority information needs to be parsed. */
|
|
|
|
if(is_hierarchical_uri(ptr, data)) {
|
|
|
|
/* Only treat it as a hierarchical URI if the scheme_type is known or
|
|
|
|
* the Uri_CREATE_NO_CRACK_UNKNOWN_SCHEMES flag is not set.
|
|
|
|
*/
|
|
|
|
if(data->scheme_type != URL_SCHEME_UNKNOWN ||
|
|
|
|
!(flags & Uri_CREATE_NO_CRACK_UNKNOWN_SCHEMES)) {
|
|
|
|
TRACE("(%p %p %x): Treating URI as an hierarchical URI.\n", ptr, data, flags);
|
|
|
|
data->is_opaque = FALSE;
|
|
|
|
|
2013-03-22 14:29:11 +00:00
|
|
|
if(data->scheme_type == URL_SCHEME_WILDCARD && !data->has_implicit_scheme) {
|
|
|
|
if(**ptr == '/' && *(*ptr+1) == '/') {
|
|
|
|
data->must_have_path = TRUE;
|
|
|
|
*ptr += 2;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-10-09 21:52:25 +00:00
|
|
|
/* TODO: Handle hierarchical URI's, parse authority then parse the path. */
|
|
|
|
if(!parse_authority(ptr, data, flags))
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
return parse_path_hierarchical(ptr, data, flags);
|
|
|
|
} else
|
2013-03-22 14:29:11 +00:00
|
|
|
/* Reset ptr to its starting position so opaque path parsing
|
2010-10-09 21:52:25 +00:00
|
|
|
* begins at the correct location.
|
|
|
|
*/
|
|
|
|
*ptr = start;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* If it reaches here, then the URI will be treated as an opaque
|
|
|
|
* URI.
|
|
|
|
*/
|
|
|
|
|
|
|
|
TRACE("(%p %p %x): Treating URI as an opaque URI.\n", ptr, data, flags);
|
|
|
|
|
|
|
|
data->is_opaque = TRUE;
|
|
|
|
if(!parse_path_opaque(ptr, data, flags))
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Attempts to parse the query string from the URI.
|
|
|
|
*
|
|
|
|
* NOTES:
|
|
|
|
* If NO_DECODE_EXTRA_INFO flag is set, then invalid percent encoded
|
2013-03-22 14:29:11 +00:00
|
|
|
* data is allowed to appear in the query string. For unknown scheme types
|
|
|
|
* invalid percent encoded data is allowed to appear regardless.
|
2010-10-09 21:52:25 +00:00
|
|
|
*/
|
|
|
|
static BOOL parse_query(const WCHAR **ptr, parse_data *data, DWORD flags) {
|
|
|
|
const BOOL known_scheme = data->scheme_type != URL_SCHEME_UNKNOWN;
|
|
|
|
|
|
|
|
if(**ptr != '?') {
|
|
|
|
TRACE("(%p %p %x): URI didn't contain a query string.\n", ptr, data, flags);
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
data->query = *ptr;
|
|
|
|
|
|
|
|
++(*ptr);
|
|
|
|
while(**ptr && **ptr != '#') {
|
|
|
|
if(**ptr == '%' && known_scheme &&
|
|
|
|
!(flags & Uri_CREATE_NO_DECODE_EXTRA_INFO)) {
|
|
|
|
if(!check_pct_encoded(ptr)) {
|
|
|
|
*ptr = data->query;
|
|
|
|
data->query = NULL;
|
|
|
|
return FALSE;
|
|
|
|
} else
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
++(*ptr);
|
|
|
|
}
|
|
|
|
|
|
|
|
data->query_len = *ptr - data->query;
|
|
|
|
|
|
|
|
TRACE("(%p %p %x): Parsed query string %s len=%d\n", ptr, data, flags,
|
|
|
|
debugstr_wn(data->query, data->query_len), data->query_len);
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Attempts to parse the fragment from the URI.
|
|
|
|
*
|
|
|
|
* NOTES:
|
|
|
|
* If NO_DECODE_EXTRA_INFO flag is set, then invalid percent encoded
|
2013-03-22 14:29:11 +00:00
|
|
|
* data is allowed to appear in the query string. For unknown scheme types
|
|
|
|
* invalid percent encoded data is allowed to appear regardless.
|
2010-10-09 21:52:25 +00:00
|
|
|
*/
|
|
|
|
static BOOL parse_fragment(const WCHAR **ptr, parse_data *data, DWORD flags) {
|
|
|
|
const BOOL known_scheme = data->scheme_type != URL_SCHEME_UNKNOWN;
|
|
|
|
|
|
|
|
if(**ptr != '#') {
|
|
|
|
TRACE("(%p %p %x): URI didn't contain a fragment.\n", ptr, data, flags);
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
data->fragment = *ptr;
|
|
|
|
|
|
|
|
++(*ptr);
|
|
|
|
while(**ptr) {
|
|
|
|
if(**ptr == '%' && known_scheme &&
|
|
|
|
!(flags & Uri_CREATE_NO_DECODE_EXTRA_INFO)) {
|
|
|
|
if(!check_pct_encoded(ptr)) {
|
|
|
|
*ptr = data->fragment;
|
|
|
|
data->fragment = NULL;
|
|
|
|
return FALSE;
|
|
|
|
} else
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
++(*ptr);
|
|
|
|
}
|
|
|
|
|
|
|
|
data->fragment_len = *ptr - data->fragment;
|
|
|
|
|
|
|
|
TRACE("(%p %p %x): Parsed fragment %s len=%d\n", ptr, data, flags,
|
|
|
|
debugstr_wn(data->fragment, data->fragment_len), data->fragment_len);
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Parses and validates the components of the specified by data->uri
|
|
|
|
* and stores the information it parses into 'data'.
|
|
|
|
*
|
|
|
|
* Returns TRUE if it successfully parsed the URI. False otherwise.
|
|
|
|
*/
|
|
|
|
static BOOL parse_uri(parse_data *data, DWORD flags) {
|
|
|
|
const WCHAR *ptr;
|
|
|
|
const WCHAR **pptr;
|
|
|
|
|
|
|
|
ptr = data->uri;
|
|
|
|
pptr = &ptr;
|
|
|
|
|
|
|
|
TRACE("(%p %x): BEGINNING TO PARSE URI %s.\n", data, flags, debugstr_w(data->uri));
|
|
|
|
|
|
|
|
if(!parse_scheme(pptr, data, flags, 0))
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
if(!parse_hierpart(pptr, data, flags))
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
if(!parse_query(pptr, data, flags))
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
if(!parse_fragment(pptr, data, flags))
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
TRACE("(%p %x): FINISHED PARSING URI.\n", data, flags);
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static BOOL canonicalize_username(const parse_data *data, Uri *uri, DWORD flags, BOOL computeOnly) {
|
|
|
|
const WCHAR *ptr;
|
|
|
|
|
|
|
|
if(!data->username) {
|
|
|
|
uri->userinfo_start = -1;
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
uri->userinfo_start = uri->canon_len;
|
|
|
|
for(ptr = data->username; ptr < data->username+data->username_len; ++ptr) {
|
|
|
|
if(*ptr == '%') {
|
|
|
|
/* Only decode % encoded values for known scheme types. */
|
|
|
|
if(data->scheme_type != URL_SCHEME_UNKNOWN) {
|
2013-03-22 14:29:11 +00:00
|
|
|
/* See if the value really needs decoding. */
|
2010-10-09 21:52:25 +00:00
|
|
|
WCHAR val = decode_pct_val(ptr);
|
|
|
|
if(is_unreserved(val)) {
|
|
|
|
if(!computeOnly)
|
|
|
|
uri->canon_uri[uri->canon_len] = val;
|
|
|
|
|
|
|
|
++uri->canon_len;
|
|
|
|
|
|
|
|
/* Move pass the hex characters. */
|
|
|
|
ptr += 2;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
2018-03-23 11:35:23 +00:00
|
|
|
} else if(is_ascii(*ptr) && !is_reserved(*ptr) && !is_unreserved(*ptr) && *ptr != '\\') {
|
2010-10-09 21:52:25 +00:00
|
|
|
/* Only percent encode forbidden characters if the NO_ENCODE_FORBIDDEN_CHARACTERS flag
|
|
|
|
* is NOT set.
|
|
|
|
*/
|
|
|
|
if(!(flags & Uri_CREATE_NO_ENCODE_FORBIDDEN_CHARACTERS)) {
|
|
|
|
if(!computeOnly)
|
|
|
|
pct_encode_val(*ptr, uri->canon_uri + uri->canon_len);
|
|
|
|
|
|
|
|
uri->canon_len += 3;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if(!computeOnly)
|
|
|
|
/* Nothing special, so just copy the character over. */
|
|
|
|
uri->canon_uri[uri->canon_len] = *ptr;
|
|
|
|
++uri->canon_len;
|
|
|
|
}
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static BOOL canonicalize_password(const parse_data *data, Uri *uri, DWORD flags, BOOL computeOnly) {
|
|
|
|
const WCHAR *ptr;
|
|
|
|
|
|
|
|
if(!data->password) {
|
|
|
|
uri->userinfo_split = -1;
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(uri->userinfo_start == -1)
|
|
|
|
/* Has a password, but, doesn't have a username. */
|
|
|
|
uri->userinfo_start = uri->canon_len;
|
|
|
|
|
|
|
|
uri->userinfo_split = uri->canon_len - uri->userinfo_start;
|
|
|
|
|
|
|
|
/* Add the ':' to the userinfo component. */
|
|
|
|
if(!computeOnly)
|
|
|
|
uri->canon_uri[uri->canon_len] = ':';
|
|
|
|
++uri->canon_len;
|
|
|
|
|
|
|
|
for(ptr = data->password; ptr < data->password+data->password_len; ++ptr) {
|
|
|
|
if(*ptr == '%') {
|
|
|
|
/* Only decode % encoded values for known scheme types. */
|
|
|
|
if(data->scheme_type != URL_SCHEME_UNKNOWN) {
|
2013-03-22 14:29:11 +00:00
|
|
|
/* See if the value really needs decoding. */
|
2010-10-09 21:52:25 +00:00
|
|
|
WCHAR val = decode_pct_val(ptr);
|
|
|
|
if(is_unreserved(val)) {
|
|
|
|
if(!computeOnly)
|
|
|
|
uri->canon_uri[uri->canon_len] = val;
|
|
|
|
|
|
|
|
++uri->canon_len;
|
|
|
|
|
|
|
|
/* Move pass the hex characters. */
|
|
|
|
ptr += 2;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
2018-03-23 11:35:23 +00:00
|
|
|
} else if(is_ascii(*ptr) && !is_reserved(*ptr) && !is_unreserved(*ptr) && *ptr != '\\') {
|
2010-10-09 21:52:25 +00:00
|
|
|
/* Only percent encode forbidden characters if the NO_ENCODE_FORBIDDEN_CHARACTERS flag
|
|
|
|
* is NOT set.
|
|
|
|
*/
|
|
|
|
if(!(flags & Uri_CREATE_NO_ENCODE_FORBIDDEN_CHARACTERS)) {
|
|
|
|
if(!computeOnly)
|
|
|
|
pct_encode_val(*ptr, uri->canon_uri + uri->canon_len);
|
|
|
|
|
|
|
|
uri->canon_len += 3;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if(!computeOnly)
|
|
|
|
/* Nothing special, so just copy the character over. */
|
|
|
|
uri->canon_uri[uri->canon_len] = *ptr;
|
|
|
|
++uri->canon_len;
|
|
|
|
}
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Canonicalizes the userinfo of the URI represented by the parse_data.
|
|
|
|
*
|
|
|
|
* Canonicalization of the userinfo is a simple process. If there are any percent
|
|
|
|
* encoded characters that fall in the "unreserved" character set, they are decoded
|
|
|
|
* to their actual value. If a character is not in the "unreserved" or "reserved" sets
|
|
|
|
* then it is percent encoded. Other than that the characters are copied over without
|
|
|
|
* change.
|
|
|
|
*/
|
|
|
|
static BOOL canonicalize_userinfo(const parse_data *data, Uri *uri, DWORD flags, BOOL computeOnly) {
|
|
|
|
uri->userinfo_start = uri->userinfo_split = -1;
|
|
|
|
uri->userinfo_len = 0;
|
|
|
|
|
|
|
|
if(!data->username && !data->password)
|
|
|
|
/* URI doesn't have userinfo, so nothing to do here. */
|
|
|
|
return TRUE;
|
|
|
|
|
|
|
|
if(!canonicalize_username(data, uri, flags, computeOnly))
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
if(!canonicalize_password(data, uri, flags, computeOnly))
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
uri->userinfo_len = uri->canon_len - uri->userinfo_start;
|
|
|
|
if(!computeOnly)
|
|
|
|
TRACE("(%p %p %x %d): Canonicalized userinfo, userinfo_start=%d, userinfo=%s, userinfo_split=%d userinfo_len=%d.\n",
|
|
|
|
data, uri, flags, computeOnly, uri->userinfo_start, debugstr_wn(uri->canon_uri + uri->userinfo_start, uri->userinfo_len),
|
|
|
|
uri->userinfo_split, uri->userinfo_len);
|
|
|
|
|
|
|
|
/* Now insert the '@' after the userinfo. */
|
|
|
|
if(!computeOnly)
|
|
|
|
uri->canon_uri[uri->canon_len] = '@';
|
|
|
|
++uri->canon_len;
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Attempts to canonicalize a reg_name.
|
|
|
|
*
|
|
|
|
* Things that happen:
|
|
|
|
* 1) If Uri_CREATE_NO_CANONICALIZE flag is not set, then the reg_name is
|
|
|
|
* lower cased. Unless it's an unknown scheme type, which case it's
|
2013-03-22 14:29:11 +00:00
|
|
|
* no lower cased regardless.
|
2010-10-09 21:52:25 +00:00
|
|
|
*
|
|
|
|
* 2) Unreserved % encoded characters are decoded for known
|
|
|
|
* scheme types.
|
|
|
|
*
|
|
|
|
* 3) Forbidden characters are % encoded as long as
|
|
|
|
* Uri_CREATE_NO_ENCODE_FORBIDDEN_CHARACTERS flag is not set and
|
|
|
|
* it isn't an unknown scheme type.
|
|
|
|
*
|
|
|
|
* 4) If it's a file scheme and the host is "localhost" it's removed.
|
2010-12-20 21:29:55 +00:00
|
|
|
*
|
|
|
|
* 5) If it's a file scheme and Uri_CREATE_FILE_USE_DOS_PATH is set,
|
|
|
|
* then the UNC path characters are added before the host name.
|
2010-10-09 21:52:25 +00:00
|
|
|
*/
|
|
|
|
static BOOL canonicalize_reg_name(const parse_data *data, Uri *uri,
|
|
|
|
DWORD flags, BOOL computeOnly) {
|
|
|
|
static const WCHAR localhostW[] =
|
|
|
|
{'l','o','c','a','l','h','o','s','t',0};
|
|
|
|
const WCHAR *ptr;
|
|
|
|
const BOOL known_scheme = data->scheme_type != URL_SCHEME_UNKNOWN;
|
|
|
|
|
|
|
|
if(data->scheme_type == URL_SCHEME_FILE &&
|
|
|
|
data->host_len == lstrlenW(localhostW)) {
|
|
|
|
if(!StrCmpNIW(data->host, localhostW, data->host_len)) {
|
|
|
|
uri->host_start = -1;
|
|
|
|
uri->host_len = 0;
|
|
|
|
uri->host_type = Uri_HOST_UNKNOWN;
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-12-20 21:29:55 +00:00
|
|
|
if(data->scheme_type == URL_SCHEME_FILE && flags & Uri_CREATE_FILE_USE_DOS_PATH) {
|
|
|
|
if(!computeOnly) {
|
|
|
|
uri->canon_uri[uri->canon_len] = '\\';
|
|
|
|
uri->canon_uri[uri->canon_len+1] = '\\';
|
|
|
|
}
|
|
|
|
uri->canon_len += 2;
|
|
|
|
uri->authority_start = uri->canon_len;
|
|
|
|
}
|
|
|
|
|
|
|
|
uri->host_start = uri->canon_len;
|
|
|
|
|
2010-10-09 21:52:25 +00:00
|
|
|
for(ptr = data->host; ptr < data->host+data->host_len; ++ptr) {
|
|
|
|
if(*ptr == '%' && known_scheme) {
|
|
|
|
WCHAR val = decode_pct_val(ptr);
|
|
|
|
if(is_unreserved(val)) {
|
2013-03-22 14:29:11 +00:00
|
|
|
/* If NO_CANONICALIZE is not set, then windows lower cases the
|
2010-10-09 21:52:25 +00:00
|
|
|
* decoded value.
|
|
|
|
*/
|
|
|
|
if(!(flags & Uri_CREATE_NO_CANONICALIZE) && isupperW(val)) {
|
|
|
|
if(!computeOnly)
|
|
|
|
uri->canon_uri[uri->canon_len] = tolowerW(val);
|
|
|
|
} else {
|
|
|
|
if(!computeOnly)
|
|
|
|
uri->canon_uri[uri->canon_len] = val;
|
|
|
|
}
|
|
|
|
++uri->canon_len;
|
|
|
|
|
|
|
|
/* Skip past the % encoded character. */
|
|
|
|
ptr += 2;
|
|
|
|
continue;
|
|
|
|
} else {
|
|
|
|
/* Just copy the % over. */
|
|
|
|
if(!computeOnly)
|
|
|
|
uri->canon_uri[uri->canon_len] = *ptr;
|
|
|
|
++uri->canon_len;
|
|
|
|
}
|
|
|
|
} else if(*ptr == '\\') {
|
|
|
|
/* Only unknown scheme types could have made it here with a '\\' in the host name. */
|
|
|
|
if(!computeOnly)
|
|
|
|
uri->canon_uri[uri->canon_len] = *ptr;
|
|
|
|
++uri->canon_len;
|
2018-03-23 11:35:23 +00:00
|
|
|
} else if(!(flags & Uri_CREATE_NO_ENCODE_FORBIDDEN_CHARACTERS) && is_ascii(*ptr) &&
|
2010-10-09 21:52:25 +00:00
|
|
|
!is_unreserved(*ptr) && !is_reserved(*ptr) && known_scheme) {
|
|
|
|
if(!computeOnly) {
|
|
|
|
pct_encode_val(*ptr, uri->canon_uri+uri->canon_len);
|
|
|
|
|
|
|
|
/* The percent encoded value gets lower cased also. */
|
|
|
|
if(!(flags & Uri_CREATE_NO_CANONICALIZE)) {
|
|
|
|
uri->canon_uri[uri->canon_len+1] = tolowerW(uri->canon_uri[uri->canon_len+1]);
|
|
|
|
uri->canon_uri[uri->canon_len+2] = tolowerW(uri->canon_uri[uri->canon_len+2]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
uri->canon_len += 3;
|
|
|
|
} else {
|
|
|
|
if(!computeOnly) {
|
|
|
|
if(!(flags & Uri_CREATE_NO_CANONICALIZE) && known_scheme)
|
|
|
|
uri->canon_uri[uri->canon_len] = tolowerW(*ptr);
|
|
|
|
else
|
|
|
|
uri->canon_uri[uri->canon_len] = *ptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
++uri->canon_len;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
uri->host_len = uri->canon_len - uri->host_start;
|
|
|
|
|
|
|
|
if(!computeOnly)
|
|
|
|
TRACE("(%p %p %x %d): Canonicalize reg_name=%s len=%d\n", data, uri, flags,
|
|
|
|
computeOnly, debugstr_wn(uri->canon_uri+uri->host_start, uri->host_len),
|
|
|
|
uri->host_len);
|
|
|
|
|
|
|
|
if(!computeOnly)
|
|
|
|
find_domain_name(uri->canon_uri+uri->host_start, uri->host_len,
|
|
|
|
&(uri->domain_offset));
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Attempts to canonicalize an implicit IPv4 address. */
|
|
|
|
static BOOL canonicalize_implicit_ipv4address(const parse_data *data, Uri *uri, DWORD flags, BOOL computeOnly) {
|
|
|
|
uri->host_start = uri->canon_len;
|
Finish the Wine sync. These components are not just rc file changes
atl, comctl32, comdlg32, dwmapi, fusion, gdiplus, jscript, mpr, mshtml, msi, msimtf, msxml3, ole32, oleaut32, riched20, shdocvw, shlwapi, urlmon, usp10, version and windowscodecs
Seems to build and boot. /me hides
svn path=/trunk/; revision=48273
2010-07-26 02:26:04 +00:00
|
|
|
|
|
|
|
TRACE("%u\n", data->implicit_ipv4);
|
2013-03-22 14:29:11 +00:00
|
|
|
/* For unknown scheme types Windows doesn't convert
|
|
|
|
* the value into an IP address, but it still considers
|
Finish the Wine sync. These components are not just rc file changes
atl, comctl32, comdlg32, dwmapi, fusion, gdiplus, jscript, mpr, mshtml, msi, msimtf, msxml3, ole32, oleaut32, riched20, shdocvw, shlwapi, urlmon, usp10, version and windowscodecs
Seems to build and boot. /me hides
svn path=/trunk/; revision=48273
2010-07-26 02:26:04 +00:00
|
|
|
* it an IPv4 address.
|
|
|
|
*/
|
|
|
|
if(data->scheme_type == URL_SCHEME_UNKNOWN) {
|
|
|
|
if(!computeOnly)
|
|
|
|
memcpy(uri->canon_uri+uri->canon_len, data->host, data->host_len*sizeof(WCHAR));
|
|
|
|
uri->canon_len += data->host_len;
|
|
|
|
} else {
|
|
|
|
if(!computeOnly)
|
|
|
|
uri->canon_len += ui2ipv4(uri->canon_uri+uri->canon_len, data->implicit_ipv4);
|
|
|
|
else
|
|
|
|
uri->canon_len += ui2ipv4(NULL, data->implicit_ipv4);
|
|
|
|
}
|
|
|
|
|
|
|
|
uri->host_len = uri->canon_len - uri->host_start;
|
|
|
|
uri->host_type = Uri_HOST_IPV4;
|
|
|
|
|
|
|
|
if(!computeOnly)
|
|
|
|
TRACE("%p %p %x %d): Canonicalized implicit IP address=%s len=%d\n",
|
|
|
|
data, uri, flags, computeOnly,
|
|
|
|
debugstr_wn(uri->canon_uri+uri->host_start, uri->host_len),
|
|
|
|
uri->host_len);
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Attempts to canonicalize an IPv4 address.
|
|
|
|
*
|
|
|
|
* If the parse_data represents a URI that has an implicit IPv4 address
|
|
|
|
* (ex. http://256/, this function will convert 256 into 0.0.1.0). If
|
|
|
|
* the implicit IP address exceeds the value of UINT_MAX (maximum value
|
2013-03-22 14:29:11 +00:00
|
|
|
* for an IPv4 address) it's canonicalized as if it were a reg-name.
|
Finish the Wine sync. These components are not just rc file changes
atl, comctl32, comdlg32, dwmapi, fusion, gdiplus, jscript, mpr, mshtml, msi, msimtf, msxml3, ole32, oleaut32, riched20, shdocvw, shlwapi, urlmon, usp10, version and windowscodecs
Seems to build and boot. /me hides
svn path=/trunk/; revision=48273
2010-07-26 02:26:04 +00:00
|
|
|
*
|
|
|
|
* If the parse_data contains a partial or full IPv4 address it normalizes it.
|
|
|
|
* A partial IPv4 address is something like "192.0" and would be normalized to
|
|
|
|
* "192.0.0.0". With a full (or partial) IPv4 address like "192.002.01.003" would
|
|
|
|
* be normalized to "192.2.1.3".
|
|
|
|
*
|
|
|
|
* NOTES:
|
2013-03-22 14:29:11 +00:00
|
|
|
* Windows ONLY normalizes IPv4 address for known scheme types (one that isn't
|
Finish the Wine sync. These components are not just rc file changes
atl, comctl32, comdlg32, dwmapi, fusion, gdiplus, jscript, mpr, mshtml, msi, msimtf, msxml3, ole32, oleaut32, riched20, shdocvw, shlwapi, urlmon, usp10, version and windowscodecs
Seems to build and boot. /me hides
svn path=/trunk/; revision=48273
2010-07-26 02:26:04 +00:00
|
|
|
* URL_SCHEME_UNKNOWN). For unknown scheme types, it simply copies the data from
|
|
|
|
* the original URI into the canonicalized URI, but, it still recognizes URI's
|
|
|
|
* host type as HOST_IPV4.
|
|
|
|
*/
|
|
|
|
static BOOL canonicalize_ipv4address(const parse_data *data, Uri *uri, DWORD flags, BOOL computeOnly) {
|
|
|
|
if(data->has_implicit_ip)
|
|
|
|
return canonicalize_implicit_ipv4address(data, uri, flags, computeOnly);
|
|
|
|
else {
|
|
|
|
uri->host_start = uri->canon_len;
|
|
|
|
|
|
|
|
/* Windows only normalizes for known scheme types. */
|
|
|
|
if(data->scheme_type != URL_SCHEME_UNKNOWN) {
|
|
|
|
/* parse_data contains a partial or full IPv4 address, so normalize it. */
|
|
|
|
DWORD i, octetDigitCount = 0, octetCount = 0;
|
|
|
|
BOOL octetHasDigit = FALSE;
|
|
|
|
|
|
|
|
for(i = 0; i < data->host_len; ++i) {
|
|
|
|
if(data->host[i] == '0' && !octetHasDigit) {
|
|
|
|
/* Can ignore leading zeros if:
|
|
|
|
* 1) It isn't the last digit of the octet.
|
|
|
|
* 2) i+1 != data->host_len
|
|
|
|
* 3) i+1 != '.'
|
|
|
|
*/
|
|
|
|
if(octetDigitCount == 2 ||
|
|
|
|
i+1 == data->host_len ||
|
|
|
|
data->host[i+1] == '.') {
|
|
|
|
if(!computeOnly)
|
|
|
|
uri->canon_uri[uri->canon_len] = data->host[i];
|
|
|
|
++uri->canon_len;
|
|
|
|
TRACE("Adding zero\n");
|
|
|
|
}
|
|
|
|
} else if(data->host[i] == '.') {
|
|
|
|
if(!computeOnly)
|
|
|
|
uri->canon_uri[uri->canon_len] = data->host[i];
|
|
|
|
++uri->canon_len;
|
|
|
|
|
|
|
|
octetDigitCount = 0;
|
|
|
|
octetHasDigit = FALSE;
|
|
|
|
++octetCount;
|
|
|
|
} else {
|
|
|
|
if(!computeOnly)
|
|
|
|
uri->canon_uri[uri->canon_len] = data->host[i];
|
|
|
|
++uri->canon_len;
|
|
|
|
|
2010-10-09 21:52:25 +00:00
|
|
|
++octetDigitCount;
|
|
|
|
octetHasDigit = TRUE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Make sure the canonicalized IP address has 4 dec-octets.
|
|
|
|
* If doesn't add "0" ones until there is 4;
|
|
|
|
*/
|
|
|
|
for( ; octetCount < 3; ++octetCount) {
|
|
|
|
if(!computeOnly) {
|
|
|
|
uri->canon_uri[uri->canon_len] = '.';
|
|
|
|
uri->canon_uri[uri->canon_len+1] = '0';
|
|
|
|
}
|
|
|
|
|
|
|
|
uri->canon_len += 2;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
/* Windows doesn't normalize addresses in unknown schemes. */
|
|
|
|
if(!computeOnly)
|
|
|
|
memcpy(uri->canon_uri+uri->canon_len, data->host, data->host_len*sizeof(WCHAR));
|
|
|
|
uri->canon_len += data->host_len;
|
|
|
|
}
|
|
|
|
|
|
|
|
uri->host_len = uri->canon_len - uri->host_start;
|
|
|
|
if(!computeOnly)
|
|
|
|
TRACE("(%p %p %x %d): Canonicalized IPv4 address, ip=%s len=%d\n",
|
|
|
|
data, uri, flags, computeOnly,
|
|
|
|
debugstr_wn(uri->canon_uri+uri->host_start, uri->host_len),
|
|
|
|
uri->host_len);
|
|
|
|
}
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Attempts to canonicalize the IPv6 address of the URI.
|
|
|
|
*
|
|
|
|
* Multiple things happen during the canonicalization of an IPv6 address:
|
2013-03-22 14:29:11 +00:00
|
|
|
* 1) Any leading zero's in a h16 component are removed.
|
2010-10-09 21:52:25 +00:00
|
|
|
* Ex: [0001:0022::] -> [1:22::]
|
|
|
|
*
|
|
|
|
* 2) The longest sequence of zero h16 components are compressed
|
2013-03-22 14:29:11 +00:00
|
|
|
* into a "::" (elision). If there's a tie, the first is chosen.
|
2010-10-09 21:52:25 +00:00
|
|
|
*
|
|
|
|
* Ex: [0:0:0:0:1:6:7:8] -> [::1:6:7:8]
|
|
|
|
* [0:0:0:0:1:2::] -> [::1:2:0:0]
|
|
|
|
* [0:0:1:2:0:0:7:8] -> [::1:2:0:0:7:8]
|
|
|
|
*
|
|
|
|
* 3) If an IPv4 address is attached to the IPv6 address, it's
|
|
|
|
* also normalized.
|
|
|
|
* Ex: [::001.002.022.000] -> [::1.2.22.0]
|
|
|
|
*
|
2013-03-22 14:29:11 +00:00
|
|
|
* 4) If an elision is present, but, only represents one h16 component
|
2010-10-09 21:52:25 +00:00
|
|
|
* it's expanded.
|
|
|
|
*
|
|
|
|
* Ex: [1::2:3:4:5:6:7] -> [1:0:2:3:4:5:6:7]
|
|
|
|
*
|
|
|
|
* 5) If the IPv6 address contains an IPv4 address and there exists
|
|
|
|
* at least 1 non-zero h16 component the IPv4 address is converted
|
|
|
|
* into two h16 components, otherwise it's normalized and kept as is.
|
|
|
|
*
|
|
|
|
* Ex: [::192.200.003.4] -> [::192.200.3.4]
|
|
|
|
* [ffff::192.200.003.4] -> [ffff::c0c8:3041]
|
|
|
|
*
|
|
|
|
* NOTE:
|
|
|
|
* For unknown scheme types Windows simply copies the address over without any
|
|
|
|
* changes.
|
|
|
|
*
|
|
|
|
* IPv4 address can be included in an elision if all its components are 0's.
|
|
|
|
*/
|
|
|
|
static BOOL canonicalize_ipv6address(const parse_data *data, Uri *uri,
|
|
|
|
DWORD flags, BOOL computeOnly) {
|
|
|
|
uri->host_start = uri->canon_len;
|
|
|
|
|
|
|
|
if(data->scheme_type == URL_SCHEME_UNKNOWN) {
|
|
|
|
if(!computeOnly)
|
|
|
|
memcpy(uri->canon_uri+uri->canon_len, data->host, data->host_len*sizeof(WCHAR));
|
|
|
|
uri->canon_len += data->host_len;
|
|
|
|
} else {
|
|
|
|
USHORT values[8];
|
|
|
|
INT elision_start;
|
|
|
|
DWORD i, elision_len;
|
|
|
|
|
|
|
|
if(!ipv6_to_number(&(data->ipv6_address), values)) {
|
|
|
|
TRACE("(%p %p %x %d): Failed to compute numerical value for IPv6 address.\n",
|
|
|
|
data, uri, flags, computeOnly);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(!computeOnly)
|
|
|
|
uri->canon_uri[uri->canon_len] = '[';
|
|
|
|
++uri->canon_len;
|
|
|
|
|
|
|
|
/* Find where the elision should occur (if any). */
|
|
|
|
compute_elision_location(&(data->ipv6_address), values, &elision_start, &elision_len);
|
|
|
|
|
|
|
|
TRACE("%p %p %x %d): Elision starts at %d, len=%u\n", data, uri, flags,
|
|
|
|
computeOnly, elision_start, elision_len);
|
|
|
|
|
|
|
|
for(i = 0; i < 8; ++i) {
|
|
|
|
BOOL in_elision = (elision_start > -1 && i >= elision_start &&
|
|
|
|
i < elision_start+elision_len);
|
|
|
|
BOOL do_ipv4 = (i == 6 && data->ipv6_address.ipv4 && !in_elision &&
|
|
|
|
data->ipv6_address.h16_count == 0);
|
|
|
|
|
|
|
|
if(i == elision_start) {
|
|
|
|
if(!computeOnly) {
|
|
|
|
uri->canon_uri[uri->canon_len] = ':';
|
|
|
|
uri->canon_uri[uri->canon_len+1] = ':';
|
Finish the Wine sync. These components are not just rc file changes
atl, comctl32, comdlg32, dwmapi, fusion, gdiplus, jscript, mpr, mshtml, msi, msimtf, msxml3, ole32, oleaut32, riched20, shdocvw, shlwapi, urlmon, usp10, version and windowscodecs
Seems to build and boot. /me hides
svn path=/trunk/; revision=48273
2010-07-26 02:26:04 +00:00
|
|
|
}
|
2010-10-09 21:52:25 +00:00
|
|
|
uri->canon_len += 2;
|
Finish the Wine sync. These components are not just rc file changes
atl, comctl32, comdlg32, dwmapi, fusion, gdiplus, jscript, mpr, mshtml, msi, msimtf, msxml3, ole32, oleaut32, riched20, shdocvw, shlwapi, urlmon, usp10, version and windowscodecs
Seems to build and boot. /me hides
svn path=/trunk/; revision=48273
2010-07-26 02:26:04 +00:00
|
|
|
}
|
|
|
|
|
2010-10-09 21:52:25 +00:00
|
|
|
/* We can ignore the current component if we're in the elision. */
|
|
|
|
if(in_elision)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
/* We only add a ':' if we're not at i == 0, or when we're at
|
|
|
|
* the very end of elision range since the ':' colon was handled
|
|
|
|
* earlier. Otherwise we would end up with ":::" after elision.
|
Finish the Wine sync. These components are not just rc file changes
atl, comctl32, comdlg32, dwmapi, fusion, gdiplus, jscript, mpr, mshtml, msi, msimtf, msxml3, ole32, oleaut32, riched20, shdocvw, shlwapi, urlmon, usp10, version and windowscodecs
Seems to build and boot. /me hides
svn path=/trunk/; revision=48273
2010-07-26 02:26:04 +00:00
|
|
|
*/
|
2010-10-09 21:52:25 +00:00
|
|
|
if(i != 0 && !(elision_start > -1 && i == elision_start+elision_len)) {
|
|
|
|
if(!computeOnly)
|
|
|
|
uri->canon_uri[uri->canon_len] = ':';
|
|
|
|
++uri->canon_len;
|
|
|
|
}
|
Finish the Wine sync. These components are not just rc file changes
atl, comctl32, comdlg32, dwmapi, fusion, gdiplus, jscript, mpr, mshtml, msi, msimtf, msxml3, ole32, oleaut32, riched20, shdocvw, shlwapi, urlmon, usp10, version and windowscodecs
Seems to build and boot. /me hides
svn path=/trunk/; revision=48273
2010-07-26 02:26:04 +00:00
|
|
|
|
2010-10-09 21:52:25 +00:00
|
|
|
if(do_ipv4) {
|
|
|
|
UINT val;
|
|
|
|
DWORD len;
|
|
|
|
|
|
|
|
/* Combine the two parts of the IPv4 address values. */
|
|
|
|
val = values[i];
|
|
|
|
val <<= 16;
|
|
|
|
val += values[i+1];
|
|
|
|
|
|
|
|
if(!computeOnly)
|
|
|
|
len = ui2ipv4(uri->canon_uri+uri->canon_len, val);
|
|
|
|
else
|
|
|
|
len = ui2ipv4(NULL, val);
|
|
|
|
|
|
|
|
uri->canon_len += len;
|
|
|
|
++i;
|
|
|
|
} else {
|
|
|
|
/* Write a regular h16 component to the URI. */
|
|
|
|
|
|
|
|
/* Short circuit for the trivial case. */
|
|
|
|
if(values[i] == 0) {
|
|
|
|
if(!computeOnly)
|
|
|
|
uri->canon_uri[uri->canon_len] = '0';
|
|
|
|
++uri->canon_len;
|
|
|
|
} else {
|
|
|
|
static const WCHAR formatW[] = {'%','x',0};
|
|
|
|
|
|
|
|
if(!computeOnly)
|
|
|
|
uri->canon_len += sprintfW(uri->canon_uri+uri->canon_len,
|
|
|
|
formatW, values[i]);
|
|
|
|
else {
|
|
|
|
WCHAR tmp[5];
|
|
|
|
uri->canon_len += sprintfW(tmp, formatW, values[i]);
|
|
|
|
}
|
|
|
|
}
|
Finish the Wine sync. These components are not just rc file changes
atl, comctl32, comdlg32, dwmapi, fusion, gdiplus, jscript, mpr, mshtml, msi, msimtf, msxml3, ole32, oleaut32, riched20, shdocvw, shlwapi, urlmon, usp10, version and windowscodecs
Seems to build and boot. /me hides
svn path=/trunk/; revision=48273
2010-07-26 02:26:04 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-10-09 21:52:25 +00:00
|
|
|
/* Add the closing ']'. */
|
Finish the Wine sync. These components are not just rc file changes
atl, comctl32, comdlg32, dwmapi, fusion, gdiplus, jscript, mpr, mshtml, msi, msimtf, msxml3, ole32, oleaut32, riched20, shdocvw, shlwapi, urlmon, usp10, version and windowscodecs
Seems to build and boot. /me hides
svn path=/trunk/; revision=48273
2010-07-26 02:26:04 +00:00
|
|
|
if(!computeOnly)
|
2010-10-09 21:52:25 +00:00
|
|
|
uri->canon_uri[uri->canon_len] = ']';
|
|
|
|
++uri->canon_len;
|
Finish the Wine sync. These components are not just rc file changes
atl, comctl32, comdlg32, dwmapi, fusion, gdiplus, jscript, mpr, mshtml, msi, msimtf, msxml3, ole32, oleaut32, riched20, shdocvw, shlwapi, urlmon, usp10, version and windowscodecs
Seems to build and boot. /me hides
svn path=/trunk/; revision=48273
2010-07-26 02:26:04 +00:00
|
|
|
}
|
|
|
|
|
2010-10-09 21:52:25 +00:00
|
|
|
uri->host_len = uri->canon_len - uri->host_start;
|
|
|
|
|
|
|
|
if(!computeOnly)
|
|
|
|
TRACE("(%p %p %x %d): Canonicalized IPv6 address %s, len=%d\n", data, uri, flags,
|
|
|
|
computeOnly, debugstr_wn(uri->canon_uri+uri->host_start, uri->host_len),
|
|
|
|
uri->host_len);
|
|
|
|
|
Finish the Wine sync. These components are not just rc file changes
atl, comctl32, comdlg32, dwmapi, fusion, gdiplus, jscript, mpr, mshtml, msi, msimtf, msxml3, ole32, oleaut32, riched20, shdocvw, shlwapi, urlmon, usp10, version and windowscodecs
Seems to build and boot. /me hides
svn path=/trunk/; revision=48273
2010-07-26 02:26:04 +00:00
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
2010-10-09 21:52:25 +00:00
|
|
|
/* Attempts to canonicalize the host of the URI (if any). */
|
Finish the Wine sync. These components are not just rc file changes
atl, comctl32, comdlg32, dwmapi, fusion, gdiplus, jscript, mpr, mshtml, msi, msimtf, msxml3, ole32, oleaut32, riched20, shdocvw, shlwapi, urlmon, usp10, version and windowscodecs
Seems to build and boot. /me hides
svn path=/trunk/; revision=48273
2010-07-26 02:26:04 +00:00
|
|
|
static BOOL canonicalize_host(const parse_data *data, Uri *uri, DWORD flags, BOOL computeOnly) {
|
|
|
|
uri->host_start = -1;
|
|
|
|
uri->host_len = 0;
|
2010-10-09 21:52:25 +00:00
|
|
|
uri->domain_offset = -1;
|
Finish the Wine sync. These components are not just rc file changes
atl, comctl32, comdlg32, dwmapi, fusion, gdiplus, jscript, mpr, mshtml, msi, msimtf, msxml3, ole32, oleaut32, riched20, shdocvw, shlwapi, urlmon, usp10, version and windowscodecs
Seems to build and boot. /me hides
svn path=/trunk/; revision=48273
2010-07-26 02:26:04 +00:00
|
|
|
|
|
|
|
if(data->host) {
|
|
|
|
switch(data->host_type) {
|
2010-10-09 21:52:25 +00:00
|
|
|
case Uri_HOST_DNS:
|
|
|
|
uri->host_type = Uri_HOST_DNS;
|
|
|
|
if(!canonicalize_reg_name(data, uri, flags, computeOnly))
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
break;
|
Finish the Wine sync. These components are not just rc file changes
atl, comctl32, comdlg32, dwmapi, fusion, gdiplus, jscript, mpr, mshtml, msi, msimtf, msxml3, ole32, oleaut32, riched20, shdocvw, shlwapi, urlmon, usp10, version and windowscodecs
Seems to build and boot. /me hides
svn path=/trunk/; revision=48273
2010-07-26 02:26:04 +00:00
|
|
|
case Uri_HOST_IPV4:
|
|
|
|
uri->host_type = Uri_HOST_IPV4;
|
|
|
|
if(!canonicalize_ipv4address(data, uri, flags, computeOnly))
|
|
|
|
return FALSE;
|
|
|
|
|
2010-10-09 21:52:25 +00:00
|
|
|
break;
|
|
|
|
case Uri_HOST_IPV6:
|
|
|
|
if(!canonicalize_ipv6address(data, uri, flags, computeOnly))
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
uri->host_type = Uri_HOST_IPV6;
|
|
|
|
break;
|
|
|
|
case Uri_HOST_UNKNOWN:
|
|
|
|
if(data->host_len > 0 || data->scheme_type != URL_SCHEME_FILE) {
|
|
|
|
uri->host_start = uri->canon_len;
|
|
|
|
|
|
|
|
/* Nothing happens to unknown host types. */
|
|
|
|
if(!computeOnly)
|
|
|
|
memcpy(uri->canon_uri+uri->canon_len, data->host, data->host_len*sizeof(WCHAR));
|
|
|
|
uri->canon_len += data->host_len;
|
|
|
|
uri->host_len = data->host_len;
|
|
|
|
}
|
|
|
|
|
|
|
|
uri->host_type = Uri_HOST_UNKNOWN;
|
Finish the Wine sync. These components are not just rc file changes
atl, comctl32, comdlg32, dwmapi, fusion, gdiplus, jscript, mpr, mshtml, msi, msimtf, msxml3, ole32, oleaut32, riched20, shdocvw, shlwapi, urlmon, usp10, version and windowscodecs
Seems to build and boot. /me hides
svn path=/trunk/; revision=48273
2010-07-26 02:26:04 +00:00
|
|
|
break;
|
|
|
|
default:
|
2010-10-09 21:52:25 +00:00
|
|
|
FIXME("(%p %p %x %d): Canonicalization for host type %d not supported.\n", data,
|
|
|
|
uri, flags, computeOnly, data->host_type);
|
|
|
|
return FALSE;
|
Finish the Wine sync. These components are not just rc file changes
atl, comctl32, comdlg32, dwmapi, fusion, gdiplus, jscript, mpr, mshtml, msi, msimtf, msxml3, ole32, oleaut32, riched20, shdocvw, shlwapi, urlmon, usp10, version and windowscodecs
Seems to build and boot. /me hides
svn path=/trunk/; revision=48273
2010-07-26 02:26:04 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
2010-10-09 21:52:25 +00:00
|
|
|
static BOOL canonicalize_port(const parse_data *data, Uri *uri, DWORD flags, BOOL computeOnly) {
|
|
|
|
BOOL has_default_port = FALSE;
|
|
|
|
USHORT default_port = 0;
|
|
|
|
DWORD i;
|
|
|
|
|
2010-12-20 21:29:55 +00:00
|
|
|
uri->port_offset = -1;
|
2010-10-09 21:52:25 +00:00
|
|
|
|
|
|
|
/* Check if the scheme has a default port. */
|
2019-02-04 12:04:30 +00:00
|
|
|
for(i = 0; i < ARRAY_SIZE(default_ports); ++i) {
|
2010-10-09 21:52:25 +00:00
|
|
|
if(default_ports[i].scheme == data->scheme_type) {
|
|
|
|
has_default_port = TRUE;
|
|
|
|
default_port = default_ports[i].port;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-12-20 21:29:55 +00:00
|
|
|
uri->has_port = data->has_port || has_default_port;
|
2010-10-09 21:52:25 +00:00
|
|
|
|
|
|
|
/* Possible cases:
|
|
|
|
* 1) Has a port which is the default port.
|
|
|
|
* 2) Has a port (not the default).
|
|
|
|
* 3) Doesn't have a port, but, scheme has a default port.
|
|
|
|
* 4) No port.
|
|
|
|
*/
|
2010-12-20 21:29:55 +00:00
|
|
|
if(has_default_port && data->has_port && data->port_value == default_port) {
|
2010-10-09 21:52:25 +00:00
|
|
|
/* If it's the default port and this flag isn't set, don't do anything. */
|
|
|
|
if(flags & Uri_CREATE_NO_CANONICALIZE) {
|
2010-12-20 21:29:55 +00:00
|
|
|
uri->port_offset = uri->canon_len-uri->authority_start;
|
|
|
|
if(!computeOnly)
|
2010-10-09 21:52:25 +00:00
|
|
|
uri->canon_uri[uri->canon_len] = ':';
|
2010-12-20 21:29:55 +00:00
|
|
|
++uri->canon_len;
|
|
|
|
|
|
|
|
if(data->port) {
|
|
|
|
/* Copy the original port over. */
|
|
|
|
if(!computeOnly)
|
|
|
|
memcpy(uri->canon_uri+uri->canon_len, data->port, data->port_len*sizeof(WCHAR));
|
|
|
|
uri->canon_len += data->port_len;
|
|
|
|
} else {
|
|
|
|
if(!computeOnly)
|
|
|
|
uri->canon_len += ui2str(uri->canon_uri+uri->canon_len, data->port_value);
|
|
|
|
else
|
|
|
|
uri->canon_len += ui2str(NULL, data->port_value);
|
2010-10-09 21:52:25 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
uri->port = default_port;
|
2010-12-20 21:29:55 +00:00
|
|
|
} else if(data->has_port) {
|
|
|
|
uri->port_offset = uri->canon_len-uri->authority_start;
|
2010-10-09 21:52:25 +00:00
|
|
|
if(!computeOnly)
|
|
|
|
uri->canon_uri[uri->canon_len] = ':';
|
|
|
|
++uri->canon_len;
|
|
|
|
|
2010-12-20 21:29:55 +00:00
|
|
|
if(flags & Uri_CREATE_NO_CANONICALIZE && data->port) {
|
2010-10-09 21:52:25 +00:00
|
|
|
/* Copy the original over without changes. */
|
|
|
|
if(!computeOnly)
|
|
|
|
memcpy(uri->canon_uri+uri->canon_len, data->port, data->port_len*sizeof(WCHAR));
|
|
|
|
uri->canon_len += data->port_len;
|
|
|
|
} else {
|
|
|
|
if(!computeOnly)
|
2010-12-20 21:29:55 +00:00
|
|
|
uri->canon_len += ui2str(uri->canon_uri+uri->canon_len, data->port_value);
|
|
|
|
else
|
|
|
|
uri->canon_len += ui2str(NULL, data->port_value);
|
2010-10-09 21:52:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
uri->port = data->port_value;
|
|
|
|
} else if(has_default_port)
|
|
|
|
uri->port = default_port;
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
Finish the Wine sync. These components are not just rc file changes
atl, comctl32, comdlg32, dwmapi, fusion, gdiplus, jscript, mpr, mshtml, msi, msimtf, msxml3, ole32, oleaut32, riched20, shdocvw, shlwapi, urlmon, usp10, version and windowscodecs
Seems to build and boot. /me hides
svn path=/trunk/; revision=48273
2010-07-26 02:26:04 +00:00
|
|
|
/* Canonicalizes the authority of the URI represented by the parse_data. */
|
|
|
|
static BOOL canonicalize_authority(const parse_data *data, Uri *uri, DWORD flags, BOOL computeOnly) {
|
2010-10-09 21:52:25 +00:00
|
|
|
uri->authority_start = uri->canon_len;
|
|
|
|
uri->authority_len = 0;
|
|
|
|
|
Finish the Wine sync. These components are not just rc file changes
atl, comctl32, comdlg32, dwmapi, fusion, gdiplus, jscript, mpr, mshtml, msi, msimtf, msxml3, ole32, oleaut32, riched20, shdocvw, shlwapi, urlmon, usp10, version and windowscodecs
Seems to build and boot. /me hides
svn path=/trunk/; revision=48273
2010-07-26 02:26:04 +00:00
|
|
|
if(!canonicalize_userinfo(data, uri, flags, computeOnly))
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
if(!canonicalize_host(data, uri, flags, computeOnly))
|
|
|
|
return FALSE;
|
|
|
|
|
2010-10-09 21:52:25 +00:00
|
|
|
if(!canonicalize_port(data, uri, flags, computeOnly))
|
|
|
|
return FALSE;
|
|
|
|
|
2010-12-20 21:29:55 +00:00
|
|
|
if(uri->host_start != -1 || (data->is_relative && (data->password || data->username)))
|
2010-10-09 21:52:25 +00:00
|
|
|
uri->authority_len = uri->canon_len - uri->authority_start;
|
|
|
|
else
|
|
|
|
uri->authority_start = -1;
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Attempts to canonicalize the path of a hierarchical URI.
|
|
|
|
*
|
|
|
|
* Things that happen:
|
|
|
|
* 1). Forbidden characters are percent encoded, unless the NO_ENCODE_FORBIDDEN
|
|
|
|
* flag is set or it's a file URI. Forbidden characters are always encoded
|
2013-03-22 14:29:11 +00:00
|
|
|
* for file schemes regardless and forbidden characters are never encoded
|
2010-10-09 21:52:25 +00:00
|
|
|
* for unknown scheme types.
|
|
|
|
*
|
|
|
|
* 2). For known scheme types '\\' are changed to '/'.
|
|
|
|
*
|
|
|
|
* 3). Percent encoded, unreserved characters are decoded to their actual values.
|
|
|
|
* Unless the scheme type is unknown. For file schemes any percent encoded
|
|
|
|
* character in the unreserved or reserved set is decoded.
|
|
|
|
*
|
|
|
|
* 4). For File schemes if the path is starts with a drive letter and doesn't
|
|
|
|
* start with a '/' then one is appended.
|
|
|
|
* Ex: file://c:/test.mp3 -> file:///c:/test.mp3
|
|
|
|
*
|
|
|
|
* 5). Dot segments are removed from the path for all scheme types
|
|
|
|
* unless NO_CANONICALIZE flag is set. Dot segments aren't removed
|
|
|
|
* for wildcard scheme types.
|
|
|
|
*
|
|
|
|
* NOTES:
|
|
|
|
* file://c:/test%20test -> file:///c:/test%2520test
|
|
|
|
* file://c:/test%3Etest -> file:///c:/test%253Etest
|
2010-12-20 21:29:55 +00:00
|
|
|
* if Uri_CREATE_FILE_USE_DOS_PATH is not set:
|
2010-10-09 21:52:25 +00:00
|
|
|
* file:///c:/test%20test -> file:///c:/test%20test
|
|
|
|
* file:///c:/test%test -> file:///c:/test%25test
|
|
|
|
*/
|
2013-03-22 14:29:11 +00:00
|
|
|
static DWORD canonicalize_path_hierarchical(const WCHAR *path, DWORD path_len, URL_SCHEME scheme_type, BOOL has_host, DWORD flags,
|
2014-09-25 15:39:47 +00:00
|
|
|
BOOL is_implicit_scheme, WCHAR *ret_path) {
|
2013-03-22 14:29:11 +00:00
|
|
|
const BOOL known_scheme = scheme_type != URL_SCHEME_UNKNOWN;
|
|
|
|
const BOOL is_file = scheme_type == URL_SCHEME_FILE;
|
|
|
|
const BOOL is_res = scheme_type == URL_SCHEME_RES;
|
2010-10-09 21:52:25 +00:00
|
|
|
const WCHAR *ptr;
|
|
|
|
BOOL escape_pct = FALSE;
|
2013-03-22 14:29:11 +00:00
|
|
|
DWORD len = 0;
|
2010-10-09 21:52:25 +00:00
|
|
|
|
2013-03-22 14:29:11 +00:00
|
|
|
if(!path)
|
|
|
|
return 0;
|
2010-10-09 21:52:25 +00:00
|
|
|
|
2013-03-22 14:29:11 +00:00
|
|
|
ptr = path;
|
2010-10-09 21:52:25 +00:00
|
|
|
|
2013-03-22 14:29:11 +00:00
|
|
|
if(is_file && !has_host) {
|
2010-10-09 21:52:25 +00:00
|
|
|
/* Check if a '/' needs to be appended for the file scheme. */
|
2013-03-22 14:29:11 +00:00
|
|
|
if(path_len > 1 && is_drive_path(ptr) && !(flags & Uri_CREATE_FILE_USE_DOS_PATH)) {
|
|
|
|
if(ret_path)
|
|
|
|
ret_path[len] = '/';
|
|
|
|
len++;
|
2010-10-09 21:52:25 +00:00
|
|
|
escape_pct = TRUE;
|
|
|
|
} else if(*ptr == '/') {
|
|
|
|
if(!(flags & Uri_CREATE_FILE_USE_DOS_PATH)) {
|
|
|
|
/* Copy the extra '/' over. */
|
2013-03-22 14:29:11 +00:00
|
|
|
if(ret_path)
|
|
|
|
ret_path[len] = '/';
|
|
|
|
len++;
|
2010-10-09 21:52:25 +00:00
|
|
|
}
|
|
|
|
++ptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(is_drive_path(ptr)) {
|
2013-03-22 14:29:11 +00:00
|
|
|
if(ret_path) {
|
|
|
|
ret_path[len] = *ptr;
|
|
|
|
/* If there's a '|' after the drive letter, convert it to a ':'. */
|
|
|
|
ret_path[len+1] = ':';
|
2010-10-09 21:52:25 +00:00
|
|
|
}
|
|
|
|
ptr += 2;
|
2013-03-22 14:29:11 +00:00
|
|
|
len += 2;
|
2010-10-09 21:52:25 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-03-22 14:29:11 +00:00
|
|
|
if(!is_file && *path && *path != '/') {
|
2010-12-20 21:29:55 +00:00
|
|
|
/* Prepend a '/' to the path if it doesn't have one. */
|
2013-03-22 14:29:11 +00:00
|
|
|
if(ret_path)
|
|
|
|
ret_path[len] = '/';
|
|
|
|
len++;
|
2010-12-20 21:29:55 +00:00
|
|
|
}
|
|
|
|
|
2013-03-22 14:29:11 +00:00
|
|
|
for(; ptr < path+path_len; ++ptr) {
|
2010-12-20 21:29:55 +00:00
|
|
|
BOOL do_default_action = TRUE;
|
|
|
|
|
|
|
|
if(*ptr == '%' && !is_res) {
|
2010-10-09 21:52:25 +00:00
|
|
|
const WCHAR *tmp = ptr;
|
|
|
|
WCHAR val;
|
|
|
|
|
2013-03-22 14:29:11 +00:00
|
|
|
/* Check if the % represents a valid encoded char, or if it needs encoding. */
|
2010-12-20 21:29:55 +00:00
|
|
|
BOOL force_encode = !check_pct_encoded(&tmp) && is_file && !(flags&Uri_CREATE_FILE_USE_DOS_PATH);
|
2010-10-09 21:52:25 +00:00
|
|
|
val = decode_pct_val(ptr);
|
|
|
|
|
|
|
|
if(force_encode || escape_pct) {
|
|
|
|
/* Escape the percent sign in the file URI. */
|
2013-03-22 14:29:11 +00:00
|
|
|
if(ret_path)
|
|
|
|
pct_encode_val(*ptr, ret_path+len);
|
|
|
|
len += 3;
|
2010-12-20 21:29:55 +00:00
|
|
|
do_default_action = FALSE;
|
2010-10-09 21:52:25 +00:00
|
|
|
} else if((is_unreserved(val) && known_scheme) ||
|
2014-09-25 15:39:47 +00:00
|
|
|
(is_file && !is_implicit_scheme && (is_unreserved(val) || is_reserved(val) ||
|
2010-12-20 21:29:55 +00:00
|
|
|
(val && flags&Uri_CREATE_FILE_USE_DOS_PATH && !is_forbidden_dos_path_char(val))))) {
|
2013-03-22 14:29:11 +00:00
|
|
|
if(ret_path)
|
|
|
|
ret_path[len] = val;
|
|
|
|
len++;
|
2010-10-09 21:52:25 +00:00
|
|
|
|
|
|
|
ptr += 2;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
} else if(*ptr == '/' && is_file && (flags & Uri_CREATE_FILE_USE_DOS_PATH)) {
|
|
|
|
/* Convert the '/' back to a '\\'. */
|
2013-03-22 14:29:11 +00:00
|
|
|
if(ret_path)
|
|
|
|
ret_path[len] = '\\';
|
|
|
|
len++;
|
2010-12-20 21:29:55 +00:00
|
|
|
do_default_action = FALSE;
|
2010-10-09 21:52:25 +00:00
|
|
|
} else if(*ptr == '\\' && known_scheme) {
|
2010-12-20 21:29:55 +00:00
|
|
|
if(!(is_file && (flags & Uri_CREATE_FILE_USE_DOS_PATH))) {
|
|
|
|
/* Convert '\\' into a '/'. */
|
2013-03-22 14:29:11 +00:00
|
|
|
if(ret_path)
|
|
|
|
ret_path[len] = '/';
|
|
|
|
len++;
|
2010-12-20 21:29:55 +00:00
|
|
|
do_default_action = FALSE;
|
2010-10-09 21:52:25 +00:00
|
|
|
}
|
2018-03-23 11:35:23 +00:00
|
|
|
} else if(known_scheme && !is_res && is_ascii(*ptr) && !is_unreserved(*ptr) && !is_reserved(*ptr) &&
|
2010-10-09 21:52:25 +00:00
|
|
|
(!(flags & Uri_CREATE_NO_ENCODE_FORBIDDEN_CHARACTERS) || is_file)) {
|
2014-09-25 15:39:47 +00:00
|
|
|
if(!is_file || !(flags & Uri_CREATE_FILE_USE_DOS_PATH)) {
|
2010-10-09 21:52:25 +00:00
|
|
|
/* Escape the forbidden character. */
|
2013-03-22 14:29:11 +00:00
|
|
|
if(ret_path)
|
|
|
|
pct_encode_val(*ptr, ret_path+len);
|
|
|
|
len += 3;
|
2010-12-20 21:29:55 +00:00
|
|
|
do_default_action = FALSE;
|
2010-10-09 21:52:25 +00:00
|
|
|
}
|
2010-12-20 21:29:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if(do_default_action) {
|
2013-03-22 14:29:11 +00:00
|
|
|
if(ret_path)
|
|
|
|
ret_path[len] = *ptr;
|
|
|
|
len++;
|
2010-10-09 21:52:25 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Removing the dot segments only happens when it's not in
|
|
|
|
* computeOnly mode and it's not a wildcard scheme. File schemes
|
|
|
|
* with USE_DOS_PATH set don't get dot segments removed.
|
|
|
|
*/
|
|
|
|
if(!(is_file && (flags & Uri_CREATE_FILE_USE_DOS_PATH)) &&
|
2013-03-22 14:29:11 +00:00
|
|
|
scheme_type != URL_SCHEME_WILDCARD) {
|
|
|
|
if(!(flags & Uri_CREATE_NO_CANONICALIZE) && ret_path) {
|
2010-10-09 21:52:25 +00:00
|
|
|
/* Remove the dot segments (if any) and reset everything to the new
|
|
|
|
* correct length.
|
|
|
|
*/
|
2013-03-22 14:29:11 +00:00
|
|
|
len = remove_dot_segments(ret_path, len);
|
2010-10-09 21:52:25 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-03-22 14:29:11 +00:00
|
|
|
if(ret_path)
|
|
|
|
TRACE("Canonicalized path %s len=%d\n", debugstr_wn(ret_path, len), len);
|
|
|
|
return len;
|
2010-10-09 21:52:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Attempts to canonicalize the path for an opaque URI.
|
|
|
|
*
|
|
|
|
* For known scheme types:
|
|
|
|
* 1) forbidden characters are percent encoded if
|
|
|
|
* NO_ENCODE_FORBIDDEN_CHARACTERS isn't set.
|
|
|
|
*
|
|
|
|
* 2) Percent encoded, unreserved characters are decoded
|
|
|
|
* to their actual values, for known scheme types.
|
|
|
|
*
|
|
|
|
* 3) '\\' are changed to '/' for known scheme types
|
|
|
|
* except for mailto schemes.
|
|
|
|
*
|
|
|
|
* 4) For file schemes, if USE_DOS_PATH is set all '/'
|
|
|
|
* are converted to backslashes.
|
|
|
|
*
|
|
|
|
* 5) For file schemes, if USE_DOS_PATH isn't set all '\'
|
|
|
|
* are converted to forward slashes.
|
|
|
|
*/
|
|
|
|
static BOOL canonicalize_path_opaque(const parse_data *data, Uri *uri, DWORD flags, BOOL computeOnly) {
|
|
|
|
const WCHAR *ptr;
|
|
|
|
const BOOL known_scheme = data->scheme_type != URL_SCHEME_UNKNOWN;
|
|
|
|
const BOOL is_file = data->scheme_type == URL_SCHEME_FILE;
|
2013-03-22 14:29:11 +00:00
|
|
|
const BOOL is_mk = data->scheme_type == URL_SCHEME_MK;
|
2010-10-09 21:52:25 +00:00
|
|
|
|
|
|
|
if(!data->path) {
|
|
|
|
uri->path_start = -1;
|
|
|
|
uri->path_len = 0;
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
uri->path_start = uri->canon_len;
|
|
|
|
|
2013-03-22 14:29:11 +00:00
|
|
|
if(is_mk){
|
|
|
|
/* hijack this flag for SCHEME_MK to tell the function when to start
|
|
|
|
* converting slashes */
|
|
|
|
flags |= Uri_CREATE_FILE_USE_DOS_PATH;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* For javascript: URIs, simply copy path part without any canonicalization */
|
|
|
|
if(data->scheme_type == URL_SCHEME_JAVASCRIPT) {
|
|
|
|
if(!computeOnly)
|
|
|
|
memcpy(uri->canon_uri+uri->canon_len, data->path, data->path_len*sizeof(WCHAR));
|
|
|
|
uri->path_len = data->path_len;
|
|
|
|
uri->canon_len += data->path_len;
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
2010-10-09 21:52:25 +00:00
|
|
|
/* Windows doesn't allow a "//" to appear after the scheme
|
|
|
|
* of a URI, if it's an opaque URI.
|
|
|
|
*/
|
|
|
|
if(data->scheme && *(data->path) == '/' && *(data->path+1) == '/') {
|
|
|
|
/* So it inserts a "/." before the "//" if it exists. */
|
|
|
|
if(!computeOnly) {
|
|
|
|
uri->canon_uri[uri->canon_len] = '/';
|
|
|
|
uri->canon_uri[uri->canon_len+1] = '.';
|
|
|
|
}
|
|
|
|
|
|
|
|
uri->canon_len += 2;
|
|
|
|
}
|
|
|
|
|
|
|
|
for(ptr = data->path; ptr < data->path+data->path_len; ++ptr) {
|
2010-12-20 21:29:55 +00:00
|
|
|
BOOL do_default_action = TRUE;
|
|
|
|
|
2010-10-09 21:52:25 +00:00
|
|
|
if(*ptr == '%' && known_scheme) {
|
|
|
|
WCHAR val = decode_pct_val(ptr);
|
|
|
|
|
|
|
|
if(is_unreserved(val)) {
|
|
|
|
if(!computeOnly)
|
|
|
|
uri->canon_uri[uri->canon_len] = val;
|
|
|
|
++uri->canon_len;
|
|
|
|
|
|
|
|
ptr += 2;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
} else if(*ptr == '/' && is_file && (flags & Uri_CREATE_FILE_USE_DOS_PATH)) {
|
|
|
|
if(!computeOnly)
|
|
|
|
uri->canon_uri[uri->canon_len] = '\\';
|
|
|
|
++uri->canon_len;
|
2010-12-20 21:29:55 +00:00
|
|
|
do_default_action = FALSE;
|
|
|
|
} else if(*ptr == '\\') {
|
2013-03-22 14:29:11 +00:00
|
|
|
if((data->is_relative || is_mk || is_file) && !(flags & Uri_CREATE_FILE_USE_DOS_PATH)) {
|
2010-10-09 21:52:25 +00:00
|
|
|
/* Convert to a '/'. */
|
|
|
|
if(!computeOnly)
|
|
|
|
uri->canon_uri[uri->canon_len] = '/';
|
|
|
|
++uri->canon_len;
|
2010-12-20 21:29:55 +00:00
|
|
|
do_default_action = FALSE;
|
2010-10-09 21:52:25 +00:00
|
|
|
}
|
2013-03-22 14:29:11 +00:00
|
|
|
} else if(is_mk && *ptr == ':' && ptr + 1 < data->path + data->path_len && *(ptr + 1) == ':') {
|
|
|
|
flags &= ~Uri_CREATE_FILE_USE_DOS_PATH;
|
2018-03-23 11:35:23 +00:00
|
|
|
} else if(known_scheme && is_ascii(*ptr) && !is_unreserved(*ptr) && !is_reserved(*ptr) &&
|
2010-10-09 21:52:25 +00:00
|
|
|
!(flags & Uri_CREATE_NO_ENCODE_FORBIDDEN_CHARACTERS)) {
|
2010-12-20 21:29:55 +00:00
|
|
|
if(!(is_file && (flags & Uri_CREATE_FILE_USE_DOS_PATH))) {
|
2010-10-09 21:52:25 +00:00
|
|
|
if(!computeOnly)
|
|
|
|
pct_encode_val(*ptr, uri->canon_uri+uri->canon_len);
|
|
|
|
uri->canon_len += 3;
|
2010-12-20 21:29:55 +00:00
|
|
|
do_default_action = FALSE;
|
2010-10-09 21:52:25 +00:00
|
|
|
}
|
2010-12-20 21:29:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if(do_default_action) {
|
2010-10-09 21:52:25 +00:00
|
|
|
if(!computeOnly)
|
|
|
|
uri->canon_uri[uri->canon_len] = *ptr;
|
|
|
|
++uri->canon_len;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-03-22 14:29:11 +00:00
|
|
|
if(is_mk && !computeOnly && !(flags & Uri_CREATE_NO_CANONICALIZE)) {
|
2011-06-05 21:29:41 +00:00
|
|
|
DWORD new_len = remove_dot_segments(uri->canon_uri + uri->path_start,
|
|
|
|
uri->canon_len - uri->path_start);
|
|
|
|
uri->canon_len = uri->path_start + new_len;
|
|
|
|
}
|
|
|
|
|
2010-10-09 21:52:25 +00:00
|
|
|
uri->path_len = uri->canon_len - uri->path_start;
|
Finish the Wine sync. These components are not just rc file changes
atl, comctl32, comdlg32, dwmapi, fusion, gdiplus, jscript, mpr, mshtml, msi, msimtf, msxml3, ole32, oleaut32, riched20, shdocvw, shlwapi, urlmon, usp10, version and windowscodecs
Seems to build and boot. /me hides
svn path=/trunk/; revision=48273
2010-07-26 02:26:04 +00:00
|
|
|
|
2011-06-05 21:29:41 +00:00
|
|
|
if(!computeOnly)
|
|
|
|
TRACE("(%p %p %x %d): Canonicalized opaque URI path %s len=%d\n", data, uri, flags, computeOnly,
|
|
|
|
debugstr_wn(uri->canon_uri+uri->path_start, uri->path_len), uri->path_len);
|
Finish the Wine sync. These components are not just rc file changes
atl, comctl32, comdlg32, dwmapi, fusion, gdiplus, jscript, mpr, mshtml, msi, msimtf, msxml3, ole32, oleaut32, riched20, shdocvw, shlwapi, urlmon, usp10, version and windowscodecs
Seems to build and boot. /me hides
svn path=/trunk/; revision=48273
2010-07-26 02:26:04 +00:00
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Determines how the URI represented by the parse_data should be canonicalized.
|
|
|
|
*
|
|
|
|
* Essentially, if the parse_data represents an hierarchical URI then it calls
|
|
|
|
* canonicalize_authority and the canonicalization functions for the path. If the
|
|
|
|
* URI is opaque it canonicalizes the path of the URI.
|
|
|
|
*/
|
|
|
|
static BOOL canonicalize_hierpart(const parse_data *data, Uri *uri, DWORD flags, BOOL computeOnly) {
|
2010-12-20 21:29:55 +00:00
|
|
|
if(!data->is_opaque || (data->is_relative && (data->password || data->username))) {
|
|
|
|
/* "//" is only added for non-wildcard scheme types.
|
|
|
|
*
|
|
|
|
* A "//" is only added to a relative URI if it has a
|
|
|
|
* host or port component (this only happens if a IUriBuilder
|
|
|
|
* is generating an IUri).
|
|
|
|
*/
|
|
|
|
if((data->is_relative && (data->host || data->has_port)) ||
|
|
|
|
(!data->is_relative && data->scheme_type != URL_SCHEME_WILDCARD)) {
|
2013-03-22 14:29:11 +00:00
|
|
|
if(data->scheme_type == URL_SCHEME_WILDCARD)
|
|
|
|
FIXME("Here\n");
|
|
|
|
|
Finish the Wine sync. These components are not just rc file changes
atl, comctl32, comdlg32, dwmapi, fusion, gdiplus, jscript, mpr, mshtml, msi, msimtf, msxml3, ole32, oleaut32, riched20, shdocvw, shlwapi, urlmon, usp10, version and windowscodecs
Seems to build and boot. /me hides
svn path=/trunk/; revision=48273
2010-07-26 02:26:04 +00:00
|
|
|
if(!computeOnly) {
|
|
|
|
INT pos = uri->canon_len;
|
|
|
|
|
2010-10-09 21:52:25 +00:00
|
|
|
uri->canon_uri[pos] = '/';
|
|
|
|
uri->canon_uri[pos+1] = '/';
|
|
|
|
}
|
|
|
|
uri->canon_len += 2;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(!canonicalize_authority(data, uri, flags, computeOnly))
|
|
|
|
return FALSE;
|
|
|
|
|
2010-12-20 21:29:55 +00:00
|
|
|
if(data->is_relative && (data->password || data->username)) {
|
|
|
|
if(!canonicalize_path_opaque(data, uri, flags, computeOnly))
|
|
|
|
return FALSE;
|
|
|
|
} else {
|
2013-03-22 14:29:11 +00:00
|
|
|
if(!computeOnly)
|
|
|
|
uri->path_start = uri->canon_len;
|
|
|
|
uri->path_len = canonicalize_path_hierarchical(data->path, data->path_len, data->scheme_type, data->host_len != 0,
|
2014-09-25 15:39:47 +00:00
|
|
|
flags, data->has_implicit_scheme, computeOnly ? NULL : uri->canon_uri+uri->canon_len);
|
2013-03-22 14:29:11 +00:00
|
|
|
uri->canon_len += uri->path_len;
|
|
|
|
if(!computeOnly && !uri->path_len)
|
|
|
|
uri->path_start = -1;
|
2010-12-20 21:29:55 +00:00
|
|
|
}
|
2010-10-09 21:52:25 +00:00
|
|
|
} else {
|
|
|
|
/* Opaque URI's don't have an authority. */
|
|
|
|
uri->userinfo_start = uri->userinfo_split = -1;
|
|
|
|
uri->userinfo_len = 0;
|
|
|
|
uri->host_start = -1;
|
|
|
|
uri->host_len = 0;
|
|
|
|
uri->host_type = Uri_HOST_UNKNOWN;
|
|
|
|
uri->has_port = FALSE;
|
|
|
|
uri->authority_start = -1;
|
|
|
|
uri->authority_len = 0;
|
|
|
|
uri->domain_offset = -1;
|
2010-12-20 21:29:55 +00:00
|
|
|
uri->port_offset = -1;
|
2010-10-09 21:52:25 +00:00
|
|
|
|
|
|
|
if(is_hierarchical_scheme(data->scheme_type)) {
|
|
|
|
DWORD i;
|
|
|
|
|
|
|
|
/* Absolute URIs aren't displayed for known scheme types
|
|
|
|
* which should be hierarchical URIs.
|
|
|
|
*/
|
2010-12-20 21:29:55 +00:00
|
|
|
uri->display_modifiers |= URI_DISPLAY_NO_ABSOLUTE_URI;
|
2010-10-09 21:52:25 +00:00
|
|
|
|
|
|
|
/* Windows also sets the port for these (if they have one). */
|
2019-02-04 12:04:30 +00:00
|
|
|
for(i = 0; i < ARRAY_SIZE(default_ports); ++i) {
|
2010-10-09 21:52:25 +00:00
|
|
|
if(data->scheme_type == default_ports[i].scheme) {
|
|
|
|
uri->has_port = TRUE;
|
|
|
|
uri->port = default_ports[i].port;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if(!canonicalize_path_opaque(data, uri, flags, computeOnly))
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(uri->path_start > -1 && !computeOnly)
|
|
|
|
/* Finding file extensions happens for both types of URIs. */
|
|
|
|
uri->extension_offset = find_file_extension(uri->canon_uri+uri->path_start, uri->path_len);
|
|
|
|
else
|
|
|
|
uri->extension_offset = -1;
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Attempts to canonicalize the query string of the URI.
|
|
|
|
*
|
|
|
|
* Things that happen:
|
|
|
|
* 1) For known scheme types forbidden characters
|
|
|
|
* are percent encoded, unless the NO_DECODE_EXTRA_INFO flag is set
|
|
|
|
* or NO_ENCODE_FORBIDDEN_CHARACTERS is set.
|
|
|
|
*
|
|
|
|
* 2) For known scheme types, percent encoded, unreserved characters
|
|
|
|
* are decoded as long as the NO_DECODE_EXTRA_INFO flag isn't set.
|
|
|
|
*/
|
|
|
|
static BOOL canonicalize_query(const parse_data *data, Uri *uri, DWORD flags, BOOL computeOnly) {
|
|
|
|
const WCHAR *ptr, *end;
|
|
|
|
const BOOL known_scheme = data->scheme_type != URL_SCHEME_UNKNOWN;
|
|
|
|
|
|
|
|
if(!data->query) {
|
|
|
|
uri->query_start = -1;
|
|
|
|
uri->query_len = 0;
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
uri->query_start = uri->canon_len;
|
|
|
|
|
|
|
|
end = data->query+data->query_len;
|
|
|
|
for(ptr = data->query; ptr < end; ++ptr) {
|
|
|
|
if(*ptr == '%') {
|
|
|
|
if(known_scheme && !(flags & Uri_CREATE_NO_DECODE_EXTRA_INFO)) {
|
|
|
|
WCHAR val = decode_pct_val(ptr);
|
|
|
|
if(is_unreserved(val)) {
|
|
|
|
if(!computeOnly)
|
|
|
|
uri->canon_uri[uri->canon_len] = val;
|
|
|
|
++uri->canon_len;
|
|
|
|
|
|
|
|
ptr += 2;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
2018-03-23 11:35:23 +00:00
|
|
|
} else if(known_scheme && is_ascii(*ptr) && !is_unreserved(*ptr) && !is_reserved(*ptr)) {
|
2010-10-09 21:52:25 +00:00
|
|
|
if(!(flags & Uri_CREATE_NO_ENCODE_FORBIDDEN_CHARACTERS) &&
|
|
|
|
!(flags & Uri_CREATE_NO_DECODE_EXTRA_INFO)) {
|
|
|
|
if(!computeOnly)
|
|
|
|
pct_encode_val(*ptr, uri->canon_uri+uri->canon_len);
|
|
|
|
uri->canon_len += 3;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if(!computeOnly)
|
|
|
|
uri->canon_uri[uri->canon_len] = *ptr;
|
|
|
|
++uri->canon_len;
|
|
|
|
}
|
|
|
|
|
|
|
|
uri->query_len = uri->canon_len - uri->query_start;
|
|
|
|
|
|
|
|
if(!computeOnly)
|
|
|
|
TRACE("(%p %p %x %d): Canonicalized query string %s len=%d\n", data, uri, flags,
|
|
|
|
computeOnly, debugstr_wn(uri->canon_uri+uri->query_start, uri->query_len),
|
|
|
|
uri->query_len);
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static BOOL canonicalize_fragment(const parse_data *data, Uri *uri, DWORD flags, BOOL computeOnly) {
|
|
|
|
const WCHAR *ptr, *end;
|
|
|
|
const BOOL known_scheme = data->scheme_type != URL_SCHEME_UNKNOWN;
|
Finish the Wine sync. These components are not just rc file changes
atl, comctl32, comdlg32, dwmapi, fusion, gdiplus, jscript, mpr, mshtml, msi, msimtf, msxml3, ole32, oleaut32, riched20, shdocvw, shlwapi, urlmon, usp10, version and windowscodecs
Seems to build and boot. /me hides
svn path=/trunk/; revision=48273
2010-07-26 02:26:04 +00:00
|
|
|
|
2010-10-09 21:52:25 +00:00
|
|
|
if(!data->fragment) {
|
|
|
|
uri->fragment_start = -1;
|
|
|
|
uri->fragment_len = 0;
|
|
|
|
return TRUE;
|
|
|
|
}
|
Finish the Wine sync. These components are not just rc file changes
atl, comctl32, comdlg32, dwmapi, fusion, gdiplus, jscript, mpr, mshtml, msi, msimtf, msxml3, ole32, oleaut32, riched20, shdocvw, shlwapi, urlmon, usp10, version and windowscodecs
Seems to build and boot. /me hides
svn path=/trunk/; revision=48273
2010-07-26 02:26:04 +00:00
|
|
|
|
2010-10-09 21:52:25 +00:00
|
|
|
uri->fragment_start = uri->canon_len;
|
Finish the Wine sync. These components are not just rc file changes
atl, comctl32, comdlg32, dwmapi, fusion, gdiplus, jscript, mpr, mshtml, msi, msimtf, msxml3, ole32, oleaut32, riched20, shdocvw, shlwapi, urlmon, usp10, version and windowscodecs
Seems to build and boot. /me hides
svn path=/trunk/; revision=48273
2010-07-26 02:26:04 +00:00
|
|
|
|
2010-10-09 21:52:25 +00:00
|
|
|
end = data->fragment + data->fragment_len;
|
|
|
|
for(ptr = data->fragment; ptr < end; ++ptr) {
|
|
|
|
if(*ptr == '%') {
|
|
|
|
if(known_scheme && !(flags & Uri_CREATE_NO_DECODE_EXTRA_INFO)) {
|
|
|
|
WCHAR val = decode_pct_val(ptr);
|
|
|
|
if(is_unreserved(val)) {
|
|
|
|
if(!computeOnly)
|
|
|
|
uri->canon_uri[uri->canon_len] = val;
|
|
|
|
++uri->canon_len;
|
|
|
|
|
|
|
|
ptr += 2;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
2018-03-23 11:35:23 +00:00
|
|
|
} else if(known_scheme && is_ascii(*ptr) && !is_unreserved(*ptr) && !is_reserved(*ptr)) {
|
2010-10-09 21:52:25 +00:00
|
|
|
if(!(flags & Uri_CREATE_NO_ENCODE_FORBIDDEN_CHARACTERS) &&
|
|
|
|
!(flags & Uri_CREATE_NO_DECODE_EXTRA_INFO)) {
|
|
|
|
if(!computeOnly)
|
|
|
|
pct_encode_val(*ptr, uri->canon_uri+uri->canon_len);
|
|
|
|
uri->canon_len += 3;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if(!computeOnly)
|
|
|
|
uri->canon_uri[uri->canon_len] = *ptr;
|
|
|
|
++uri->canon_len;
|
Finish the Wine sync. These components are not just rc file changes
atl, comctl32, comdlg32, dwmapi, fusion, gdiplus, jscript, mpr, mshtml, msi, msimtf, msxml3, ole32, oleaut32, riched20, shdocvw, shlwapi, urlmon, usp10, version and windowscodecs
Seems to build and boot. /me hides
svn path=/trunk/; revision=48273
2010-07-26 02:26:04 +00:00
|
|
|
}
|
|
|
|
|
2010-10-09 21:52:25 +00:00
|
|
|
uri->fragment_len = uri->canon_len - uri->fragment_start;
|
|
|
|
|
|
|
|
if(!computeOnly)
|
|
|
|
TRACE("(%p %p %x %d): Canonicalized fragment %s len=%d\n", data, uri, flags,
|
|
|
|
computeOnly, debugstr_wn(uri->canon_uri+uri->fragment_start, uri->fragment_len),
|
|
|
|
uri->fragment_len);
|
Finish the Wine sync. These components are not just rc file changes
atl, comctl32, comdlg32, dwmapi, fusion, gdiplus, jscript, mpr, mshtml, msi, msimtf, msxml3, ole32, oleaut32, riched20, shdocvw, shlwapi, urlmon, usp10, version and windowscodecs
Seems to build and boot. /me hides
svn path=/trunk/; revision=48273
2010-07-26 02:26:04 +00:00
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Canonicalizes the scheme information specified in the parse_data using the specified flags. */
|
|
|
|
static BOOL canonicalize_scheme(const parse_data *data, Uri *uri, DWORD flags, BOOL computeOnly) {
|
|
|
|
uri->scheme_start = -1;
|
|
|
|
uri->scheme_len = 0;
|
|
|
|
|
|
|
|
if(!data->scheme) {
|
|
|
|
/* The only type of URI that doesn't have to have a scheme is a relative
|
|
|
|
* URI.
|
|
|
|
*/
|
|
|
|
if(!data->is_relative) {
|
|
|
|
FIXME("(%p %p %x): Unable to determine the scheme type of %s.\n", data,
|
|
|
|
uri, flags, debugstr_w(data->uri));
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if(!computeOnly) {
|
|
|
|
DWORD i;
|
|
|
|
INT pos = uri->canon_len;
|
|
|
|
|
|
|
|
for(i = 0; i < data->scheme_len; ++i) {
|
|
|
|
/* Scheme name must be lower case after canonicalization. */
|
|
|
|
uri->canon_uri[i + pos] = tolowerW(data->scheme[i]);
|
|
|
|
}
|
|
|
|
|
|
|
|
uri->canon_uri[i + pos] = ':';
|
|
|
|
uri->scheme_start = pos;
|
|
|
|
|
|
|
|
TRACE("(%p %p %x): Canonicalized scheme=%s, len=%d.\n", data, uri, flags,
|
2013-03-22 14:29:11 +00:00
|
|
|
debugstr_wn(uri->canon_uri+uri->scheme_start, data->scheme_len), data->scheme_len);
|
Finish the Wine sync. These components are not just rc file changes
atl, comctl32, comdlg32, dwmapi, fusion, gdiplus, jscript, mpr, mshtml, msi, msimtf, msxml3, ole32, oleaut32, riched20, shdocvw, shlwapi, urlmon, usp10, version and windowscodecs
Seems to build and boot. /me hides
svn path=/trunk/; revision=48273
2010-07-26 02:26:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* This happens in both computation modes. */
|
|
|
|
uri->canon_len += data->scheme_len + 1;
|
|
|
|
uri->scheme_len = data->scheme_len;
|
|
|
|
}
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
2013-03-22 14:29:11 +00:00
|
|
|
/* Computes what the length of the URI specified by the parse_data will be
|
Finish the Wine sync. These components are not just rc file changes
atl, comctl32, comdlg32, dwmapi, fusion, gdiplus, jscript, mpr, mshtml, msi, msimtf, msxml3, ole32, oleaut32, riched20, shdocvw, shlwapi, urlmon, usp10, version and windowscodecs
Seems to build and boot. /me hides
svn path=/trunk/; revision=48273
2010-07-26 02:26:04 +00:00
|
|
|
* after canonicalization occurs using the specified flags.
|
|
|
|
*
|
|
|
|
* This function will return a non-zero value indicating the length of the canonicalized
|
|
|
|
* URI, or -1 on error.
|
|
|
|
*/
|
|
|
|
static int compute_canonicalized_length(const parse_data *data, DWORD flags) {
|
|
|
|
Uri uri;
|
|
|
|
|
2010-10-09 21:52:25 +00:00
|
|
|
memset(&uri, 0, sizeof(Uri));
|
|
|
|
|
|
|
|
TRACE("(%p %x): Beginning to compute canonicalized length for URI %s\n", data, flags,
|
|
|
|
debugstr_w(data->uri));
|
|
|
|
|
|
|
|
if(!canonicalize_scheme(data, &uri, flags, TRUE)) {
|
|
|
|
ERR("(%p %x): Failed to compute URI scheme length.\n", data, flags);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(!canonicalize_hierpart(data, &uri, flags, TRUE)) {
|
|
|
|
ERR("(%p %x): Failed to compute URI hierpart length.\n", data, flags);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(!canonicalize_query(data, &uri, flags, TRUE)) {
|
|
|
|
ERR("(%p %x): Failed to compute query string length.\n", data, flags);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(!canonicalize_fragment(data, &uri, flags, TRUE)) {
|
|
|
|
ERR("(%p %x): Failed to compute fragment length.\n", data, flags);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
TRACE("(%p %x): Finished computing canonicalized URI length. length=%d\n", data, flags, uri.canon_len);
|
|
|
|
|
|
|
|
return uri.canon_len;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Canonicalizes the URI data specified in the parse_data, using the given flags. If the
|
2013-03-22 14:29:11 +00:00
|
|
|
* canonicalization succeeds it will store all the canonicalization information
|
2010-10-09 21:52:25 +00:00
|
|
|
* in the pointer to the Uri.
|
|
|
|
*
|
|
|
|
* To canonicalize a URI this function first computes what the length of the URI
|
2013-03-22 14:29:11 +00:00
|
|
|
* specified by the parse_data will be. Once this is done it will then perform the actual
|
2010-10-09 21:52:25 +00:00
|
|
|
* canonicalization of the URI.
|
|
|
|
*/
|
|
|
|
static HRESULT canonicalize_uri(const parse_data *data, Uri *uri, DWORD flags) {
|
|
|
|
INT len;
|
|
|
|
|
|
|
|
uri->canon_uri = NULL;
|
2011-06-05 21:29:41 +00:00
|
|
|
uri->canon_size = uri->canon_len = 0;
|
2010-10-09 21:52:25 +00:00
|
|
|
|
|
|
|
TRACE("(%p %p %x): beginning to canonicalize URI %s.\n", data, uri, flags, debugstr_w(data->uri));
|
|
|
|
|
|
|
|
/* First try to compute the length of the URI. */
|
|
|
|
len = compute_canonicalized_length(data, flags);
|
|
|
|
if(len == -1) {
|
|
|
|
ERR("(%p %p %x): Could not compute the canonicalized length of %s.\n", data, uri, flags,
|
|
|
|
debugstr_w(data->uri));
|
|
|
|
return E_INVALIDARG;
|
|
|
|
}
|
|
|
|
|
|
|
|
uri->canon_uri = heap_alloc((len+1)*sizeof(WCHAR));
|
|
|
|
if(!uri->canon_uri)
|
|
|
|
return E_OUTOFMEMORY;
|
|
|
|
|
|
|
|
uri->canon_size = len;
|
|
|
|
if(!canonicalize_scheme(data, uri, flags, FALSE)) {
|
|
|
|
ERR("(%p %p %x): Unable to canonicalize the scheme of the URI.\n", data, uri, flags);
|
|
|
|
return E_INVALIDARG;
|
|
|
|
}
|
|
|
|
uri->scheme_type = data->scheme_type;
|
|
|
|
|
|
|
|
if(!canonicalize_hierpart(data, uri, flags, FALSE)) {
|
|
|
|
ERR("(%p %p %x): Unable to canonicalize the heirpart of the URI\n", data, uri, flags);
|
|
|
|
return E_INVALIDARG;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(!canonicalize_query(data, uri, flags, FALSE)) {
|
|
|
|
ERR("(%p %p %x): Unable to canonicalize query string of the URI.\n",
|
|
|
|
data, uri, flags);
|
|
|
|
return E_INVALIDARG;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(!canonicalize_fragment(data, uri, flags, FALSE)) {
|
|
|
|
ERR("(%p %p %x): Unable to canonicalize fragment of the URI.\n",
|
|
|
|
data, uri, flags);
|
|
|
|
return E_INVALIDARG;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* There's a possibility we didn't use all the space we allocated
|
|
|
|
* earlier.
|
|
|
|
*/
|
|
|
|
if(uri->canon_len < uri->canon_size) {
|
|
|
|
/* This happens if the URI is hierarchical and dot
|
2013-03-22 14:29:11 +00:00
|
|
|
* segments were removed from its path.
|
2010-10-09 21:52:25 +00:00
|
|
|
*/
|
|
|
|
WCHAR *tmp = heap_realloc(uri->canon_uri, (uri->canon_len+1)*sizeof(WCHAR));
|
|
|
|
if(!tmp)
|
|
|
|
return E_OUTOFMEMORY;
|
|
|
|
|
|
|
|
uri->canon_uri = tmp;
|
|
|
|
uri->canon_size = uri->canon_len;
|
|
|
|
}
|
|
|
|
|
|
|
|
uri->canon_uri[uri->canon_len] = '\0';
|
|
|
|
TRACE("(%p %p %x): finished canonicalizing the URI. uri=%s\n", data, uri, flags, debugstr_w(uri->canon_uri));
|
|
|
|
|
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
static HRESULT get_builder_component(LPWSTR *component, DWORD *component_len,
|
|
|
|
LPCWSTR source, DWORD source_len,
|
|
|
|
LPCWSTR *output, DWORD *output_len)
|
|
|
|
{
|
|
|
|
if(!output_len) {
|
|
|
|
if(output)
|
|
|
|
*output = NULL;
|
|
|
|
return E_POINTER;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(!output) {
|
|
|
|
*output_len = 0;
|
|
|
|
return E_POINTER;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(!(*component) && source) {
|
|
|
|
/* Allocate 'component', and copy the contents from 'source'
|
|
|
|
* into the new allocation.
|
|
|
|
*/
|
|
|
|
*component = heap_alloc((source_len+1)*sizeof(WCHAR));
|
|
|
|
if(!(*component))
|
|
|
|
return E_OUTOFMEMORY;
|
|
|
|
|
|
|
|
memcpy(*component, source, source_len*sizeof(WCHAR));
|
|
|
|
(*component)[source_len] = '\0';
|
|
|
|
*component_len = source_len;
|
|
|
|
}
|
|
|
|
|
|
|
|
*output = *component;
|
|
|
|
*output_len = *component_len;
|
|
|
|
return *output ? S_OK : S_FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Allocates 'component' and copies the string from 'new_value' into 'component'.
|
|
|
|
* If 'prefix' is set and 'new_value' isn't NULL, then it checks if 'new_value'
|
|
|
|
* starts with 'prefix'. If it doesn't then 'prefix' is prepended to 'component'.
|
|
|
|
*
|
|
|
|
* If everything is successful, then will set 'success_flag' in 'flags'.
|
|
|
|
*/
|
|
|
|
static HRESULT set_builder_component(LPWSTR *component, DWORD *component_len, LPCWSTR new_value,
|
|
|
|
WCHAR prefix, DWORD *flags, DWORD success_flag)
|
|
|
|
{
|
|
|
|
heap_free(*component);
|
|
|
|
|
|
|
|
if(!new_value) {
|
|
|
|
*component = NULL;
|
|
|
|
*component_len = 0;
|
|
|
|
} else {
|
|
|
|
BOOL add_prefix = FALSE;
|
|
|
|
DWORD len = lstrlenW(new_value);
|
|
|
|
DWORD pos = 0;
|
|
|
|
|
|
|
|
if(prefix && *new_value != prefix) {
|
|
|
|
add_prefix = TRUE;
|
|
|
|
*component = heap_alloc((len+2)*sizeof(WCHAR));
|
|
|
|
} else
|
|
|
|
*component = heap_alloc((len+1)*sizeof(WCHAR));
|
|
|
|
|
|
|
|
if(!(*component))
|
|
|
|
return E_OUTOFMEMORY;
|
|
|
|
|
|
|
|
if(add_prefix)
|
|
|
|
(*component)[pos++] = prefix;
|
|
|
|
|
|
|
|
memcpy(*component+pos, new_value, (len+1)*sizeof(WCHAR));
|
|
|
|
*component_len = len+pos;
|
|
|
|
}
|
|
|
|
|
|
|
|
*flags |= success_flag;
|
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void reset_builder(UriBuilder *builder) {
|
|
|
|
if(builder->uri)
|
2010-12-20 21:29:55 +00:00
|
|
|
IUri_Release(&builder->uri->IUri_iface);
|
2010-10-09 21:52:25 +00:00
|
|
|
builder->uri = NULL;
|
|
|
|
|
|
|
|
heap_free(builder->fragment);
|
|
|
|
builder->fragment = NULL;
|
|
|
|
builder->fragment_len = 0;
|
|
|
|
|
|
|
|
heap_free(builder->host);
|
|
|
|
builder->host = NULL;
|
|
|
|
builder->host_len = 0;
|
|
|
|
|
|
|
|
heap_free(builder->password);
|
|
|
|
builder->password = NULL;
|
|
|
|
builder->password_len = 0;
|
|
|
|
|
|
|
|
heap_free(builder->path);
|
|
|
|
builder->path = NULL;
|
|
|
|
builder->path_len = 0;
|
|
|
|
|
|
|
|
heap_free(builder->query);
|
|
|
|
builder->query = NULL;
|
|
|
|
builder->query_len = 0;
|
|
|
|
|
|
|
|
heap_free(builder->scheme);
|
|
|
|
builder->scheme = NULL;
|
|
|
|
builder->scheme_len = 0;
|
|
|
|
|
|
|
|
heap_free(builder->username);
|
|
|
|
builder->username = NULL;
|
|
|
|
builder->username_len = 0;
|
|
|
|
|
|
|
|
builder->has_port = FALSE;
|
|
|
|
builder->port = 0;
|
|
|
|
builder->modified_props = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static HRESULT validate_scheme_name(const UriBuilder *builder, parse_data *data, DWORD flags) {
|
|
|
|
const WCHAR *component;
|
|
|
|
const WCHAR *ptr;
|
|
|
|
const WCHAR **pptr;
|
|
|
|
DWORD expected_len;
|
|
|
|
|
|
|
|
if(builder->scheme) {
|
|
|
|
ptr = builder->scheme;
|
|
|
|
expected_len = builder->scheme_len;
|
|
|
|
} else if(builder->uri && builder->uri->scheme_start > -1) {
|
|
|
|
ptr = builder->uri->canon_uri+builder->uri->scheme_start;
|
|
|
|
expected_len = builder->uri->scheme_len;
|
|
|
|
} else {
|
|
|
|
static const WCHAR nullW[] = {0};
|
|
|
|
ptr = nullW;
|
|
|
|
expected_len = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
component = ptr;
|
|
|
|
pptr = &ptr;
|
|
|
|
if(parse_scheme(pptr, data, flags, ALLOW_NULL_TERM_SCHEME) &&
|
|
|
|
data->scheme_len == expected_len) {
|
|
|
|
if(data->scheme)
|
|
|
|
TRACE("(%p %p %x): Found valid scheme component %s len=%d.\n", builder, data, flags,
|
|
|
|
debugstr_wn(data->scheme, data->scheme_len), data->scheme_len);
|
|
|
|
} else {
|
|
|
|
TRACE("(%p %p %x): Invalid scheme component found %s.\n", builder, data, flags,
|
|
|
|
debugstr_wn(component, expected_len));
|
|
|
|
return INET_E_INVALID_URL;
|
|
|
|
}
|
|
|
|
|
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
static HRESULT validate_username(const UriBuilder *builder, parse_data *data, DWORD flags) {
|
|
|
|
const WCHAR *ptr;
|
|
|
|
const WCHAR **pptr;
|
|
|
|
DWORD expected_len;
|
|
|
|
|
|
|
|
if(builder->username) {
|
|
|
|
ptr = builder->username;
|
|
|
|
expected_len = builder->username_len;
|
|
|
|
} else if(!(builder->modified_props & Uri_HAS_USER_NAME) && builder->uri &&
|
|
|
|
builder->uri->userinfo_start > -1 && builder->uri->userinfo_split != 0) {
|
|
|
|
/* Just use the username from the base Uri. */
|
|
|
|
data->username = builder->uri->canon_uri+builder->uri->userinfo_start;
|
|
|
|
data->username_len = (builder->uri->userinfo_split > -1) ?
|
|
|
|
builder->uri->userinfo_split : builder->uri->userinfo_len;
|
|
|
|
ptr = NULL;
|
|
|
|
} else {
|
|
|
|
ptr = NULL;
|
|
|
|
expected_len = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(ptr) {
|
|
|
|
const WCHAR *component = ptr;
|
|
|
|
pptr = &ptr;
|
|
|
|
if(parse_username(pptr, data, flags, ALLOW_NULL_TERM_USER_NAME) &&
|
|
|
|
data->username_len == expected_len)
|
|
|
|
TRACE("(%p %p %x): Found valid username component %s len=%d.\n", builder, data, flags,
|
|
|
|
debugstr_wn(data->username, data->username_len), data->username_len);
|
|
|
|
else {
|
|
|
|
TRACE("(%p %p %x): Invalid username component found %s.\n", builder, data, flags,
|
|
|
|
debugstr_wn(component, expected_len));
|
|
|
|
return INET_E_INVALID_URL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
static HRESULT validate_password(const UriBuilder *builder, parse_data *data, DWORD flags) {
|
|
|
|
const WCHAR *ptr;
|
|
|
|
const WCHAR **pptr;
|
|
|
|
DWORD expected_len;
|
|
|
|
|
|
|
|
if(builder->password) {
|
|
|
|
ptr = builder->password;
|
|
|
|
expected_len = builder->password_len;
|
|
|
|
} else if(!(builder->modified_props & Uri_HAS_PASSWORD) && builder->uri &&
|
|
|
|
builder->uri->userinfo_split > -1) {
|
|
|
|
data->password = builder->uri->canon_uri+builder->uri->userinfo_start+builder->uri->userinfo_split+1;
|
|
|
|
data->password_len = builder->uri->userinfo_len-builder->uri->userinfo_split-1;
|
|
|
|
ptr = NULL;
|
|
|
|
} else {
|
|
|
|
ptr = NULL;
|
|
|
|
expected_len = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(ptr) {
|
|
|
|
const WCHAR *component = ptr;
|
|
|
|
pptr = &ptr;
|
|
|
|
if(parse_password(pptr, data, flags, ALLOW_NULL_TERM_PASSWORD) &&
|
|
|
|
data->password_len == expected_len)
|
|
|
|
TRACE("(%p %p %x): Found valid password component %s len=%d.\n", builder, data, flags,
|
|
|
|
debugstr_wn(data->password, data->password_len), data->password_len);
|
|
|
|
else {
|
|
|
|
TRACE("(%p %p %x): Invalid password component found %s.\n", builder, data, flags,
|
|
|
|
debugstr_wn(component, expected_len));
|
|
|
|
return INET_E_INVALID_URL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
static HRESULT validate_userinfo(const UriBuilder *builder, parse_data *data, DWORD flags) {
|
|
|
|
HRESULT hr;
|
|
|
|
|
|
|
|
hr = validate_username(builder, data, flags);
|
|
|
|
if(FAILED(hr))
|
|
|
|
return hr;
|
|
|
|
|
|
|
|
hr = validate_password(builder, data, flags);
|
|
|
|
if(FAILED(hr))
|
|
|
|
return hr;
|
|
|
|
|
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
static HRESULT validate_host(const UriBuilder *builder, parse_data *data, DWORD flags) {
|
|
|
|
const WCHAR *ptr;
|
|
|
|
const WCHAR **pptr;
|
|
|
|
DWORD expected_len;
|
|
|
|
|
|
|
|
if(builder->host) {
|
|
|
|
ptr = builder->host;
|
|
|
|
expected_len = builder->host_len;
|
|
|
|
} else if(!(builder->modified_props & Uri_HAS_HOST) && builder->uri && builder->uri->host_start > -1) {
|
|
|
|
ptr = builder->uri->canon_uri + builder->uri->host_start;
|
|
|
|
expected_len = builder->uri->host_len;
|
|
|
|
} else
|
|
|
|
ptr = NULL;
|
|
|
|
|
|
|
|
if(ptr) {
|
|
|
|
const WCHAR *component = ptr;
|
|
|
|
DWORD extras = ALLOW_BRACKETLESS_IP_LITERAL|IGNORE_PORT_DELIMITER|SKIP_IP_FUTURE_CHECK;
|
|
|
|
pptr = &ptr;
|
|
|
|
|
|
|
|
if(parse_host(pptr, data, flags, extras) && data->host_len == expected_len)
|
|
|
|
TRACE("(%p %p %x): Found valid host name %s len=%d type=%d.\n", builder, data, flags,
|
|
|
|
debugstr_wn(data->host, data->host_len), data->host_len, data->host_type);
|
|
|
|
else {
|
|
|
|
TRACE("(%p %p %x): Invalid host name found %s.\n", builder, data, flags,
|
|
|
|
debugstr_wn(component, expected_len));
|
|
|
|
return INET_E_INVALID_URL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void setup_port(const UriBuilder *builder, parse_data *data, DWORD flags) {
|
|
|
|
if(builder->modified_props & Uri_HAS_PORT) {
|
|
|
|
if(builder->has_port) {
|
|
|
|
data->has_port = TRUE;
|
|
|
|
data->port_value = builder->port;
|
|
|
|
}
|
|
|
|
} else if(builder->uri && builder->uri->has_port) {
|
|
|
|
data->has_port = TRUE;
|
|
|
|
data->port_value = builder->uri->port;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(data->has_port)
|
|
|
|
TRACE("(%p %p %x): Using %u as port for IUri.\n", builder, data, flags, data->port_value);
|
|
|
|
}
|
|
|
|
|
|
|
|
static HRESULT validate_path(const UriBuilder *builder, parse_data *data, DWORD flags) {
|
|
|
|
const WCHAR *ptr = NULL;
|
2010-12-20 21:29:55 +00:00
|
|
|
const WCHAR *component;
|
2010-10-09 21:52:25 +00:00
|
|
|
const WCHAR **pptr;
|
|
|
|
DWORD expected_len;
|
2010-12-20 21:29:55 +00:00
|
|
|
BOOL check_len = TRUE;
|
|
|
|
BOOL valid = FALSE;
|
2010-10-09 21:52:25 +00:00
|
|
|
|
|
|
|
if(builder->path) {
|
|
|
|
ptr = builder->path;
|
|
|
|
expected_len = builder->path_len;
|
|
|
|
} else if(!(builder->modified_props & Uri_HAS_PATH) &&
|
|
|
|
builder->uri && builder->uri->path_start > -1) {
|
|
|
|
ptr = builder->uri->canon_uri+builder->uri->path_start;
|
|
|
|
expected_len = builder->uri->path_len;
|
2010-12-20 21:29:55 +00:00
|
|
|
} else {
|
|
|
|
static const WCHAR nullW[] = {0};
|
|
|
|
ptr = nullW;
|
|
|
|
check_len = FALSE;
|
2013-03-22 14:29:11 +00:00
|
|
|
expected_len = -1;
|
2010-10-09 21:52:25 +00:00
|
|
|
}
|
|
|
|
|
2010-12-20 21:29:55 +00:00
|
|
|
component = ptr;
|
|
|
|
pptr = &ptr;
|
2010-10-09 21:52:25 +00:00
|
|
|
|
2010-12-20 21:29:55 +00:00
|
|
|
/* How the path is validated depends on what type of
|
|
|
|
* URI it is.
|
|
|
|
*/
|
|
|
|
valid = data->is_opaque ?
|
|
|
|
parse_path_opaque(pptr, data, flags) : parse_path_hierarchical(pptr, data, flags);
|
2010-10-09 21:52:25 +00:00
|
|
|
|
2010-12-20 21:29:55 +00:00
|
|
|
if(!valid || (check_len && expected_len != data->path_len)) {
|
|
|
|
TRACE("(%p %p %x): Invalid path component %s.\n", builder, data, flags,
|
2013-03-22 14:29:11 +00:00
|
|
|
debugstr_wn(component, expected_len) );
|
2010-12-20 21:29:55 +00:00
|
|
|
return INET_E_INVALID_URL;
|
2010-10-09 21:52:25 +00:00
|
|
|
}
|
|
|
|
|
2010-12-20 21:29:55 +00:00
|
|
|
TRACE("(%p %p %x): Valid path component %s len=%d.\n", builder, data, flags,
|
|
|
|
debugstr_wn(data->path, data->path_len), data->path_len);
|
|
|
|
|
2010-10-09 21:52:25 +00:00
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
static HRESULT validate_query(const UriBuilder *builder, parse_data *data, DWORD flags) {
|
|
|
|
const WCHAR *ptr = NULL;
|
|
|
|
const WCHAR **pptr;
|
|
|
|
DWORD expected_len;
|
|
|
|
|
|
|
|
if(builder->query) {
|
|
|
|
ptr = builder->query;
|
|
|
|
expected_len = builder->query_len;
|
|
|
|
} else if(!(builder->modified_props & Uri_HAS_QUERY) && builder->uri &&
|
|
|
|
builder->uri->query_start > -1) {
|
|
|
|
ptr = builder->uri->canon_uri+builder->uri->query_start;
|
|
|
|
expected_len = builder->uri->query_len;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(ptr) {
|
|
|
|
const WCHAR *component = ptr;
|
|
|
|
pptr = &ptr;
|
|
|
|
|
|
|
|
if(parse_query(pptr, data, flags) && expected_len == data->query_len)
|
|
|
|
TRACE("(%p %p %x): Valid query component %s len=%d.\n", builder, data, flags,
|
|
|
|
debugstr_wn(data->query, data->query_len), data->query_len);
|
|
|
|
else {
|
|
|
|
TRACE("(%p %p %x): Invalid query component %s.\n", builder, data, flags,
|
|
|
|
debugstr_wn(component, expected_len));
|
|
|
|
return INET_E_INVALID_URL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
static HRESULT validate_fragment(const UriBuilder *builder, parse_data *data, DWORD flags) {
|
|
|
|
const WCHAR *ptr = NULL;
|
|
|
|
const WCHAR **pptr;
|
|
|
|
DWORD expected_len;
|
|
|
|
|
|
|
|
if(builder->fragment) {
|
|
|
|
ptr = builder->fragment;
|
|
|
|
expected_len = builder->fragment_len;
|
|
|
|
} else if(!(builder->modified_props & Uri_HAS_FRAGMENT) && builder->uri &&
|
|
|
|
builder->uri->fragment_start > -1) {
|
|
|
|
ptr = builder->uri->canon_uri+builder->uri->fragment_start;
|
|
|
|
expected_len = builder->uri->fragment_len;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(ptr) {
|
|
|
|
const WCHAR *component = ptr;
|
|
|
|
pptr = &ptr;
|
|
|
|
|
2010-12-20 21:29:55 +00:00
|
|
|
if(parse_fragment(pptr, data, flags) && expected_len == data->fragment_len)
|
2010-10-09 21:52:25 +00:00
|
|
|
TRACE("(%p %p %x): Valid fragment component %s len=%d.\n", builder, data, flags,
|
|
|
|
debugstr_wn(data->fragment, data->fragment_len), data->fragment_len);
|
|
|
|
else {
|
|
|
|
TRACE("(%p %p %x): Invalid fragment component %s.\n", builder, data, flags,
|
|
|
|
debugstr_wn(component, expected_len));
|
|
|
|
return INET_E_INVALID_URL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
static HRESULT validate_components(const UriBuilder *builder, parse_data *data, DWORD flags) {
|
|
|
|
HRESULT hr;
|
|
|
|
|
|
|
|
memset(data, 0, sizeof(parse_data));
|
|
|
|
|
|
|
|
TRACE("(%p %p %x): Beginning to validate builder components.\n", builder, data, flags);
|
|
|
|
|
|
|
|
hr = validate_scheme_name(builder, data, flags);
|
|
|
|
if(FAILED(hr))
|
|
|
|
return hr;
|
|
|
|
|
|
|
|
/* Extra validation for file schemes. */
|
|
|
|
if(data->scheme_type == URL_SCHEME_FILE) {
|
|
|
|
if((builder->password || (builder->uri && builder->uri->userinfo_split > -1)) ||
|
|
|
|
(builder->username || (builder->uri && builder->uri->userinfo_start > -1))) {
|
|
|
|
TRACE("(%p %p %x): File schemes can't contain a username or password.\n",
|
|
|
|
builder, data, flags);
|
|
|
|
return INET_E_INVALID_URL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
hr = validate_userinfo(builder, data, flags);
|
|
|
|
if(FAILED(hr))
|
|
|
|
return hr;
|
|
|
|
|
|
|
|
hr = validate_host(builder, data, flags);
|
|
|
|
if(FAILED(hr))
|
|
|
|
return hr;
|
Finish the Wine sync. These components are not just rc file changes
atl, comctl32, comdlg32, dwmapi, fusion, gdiplus, jscript, mpr, mshtml, msi, msimtf, msxml3, ole32, oleaut32, riched20, shdocvw, shlwapi, urlmon, usp10, version and windowscodecs
Seems to build and boot. /me hides
svn path=/trunk/; revision=48273
2010-07-26 02:26:04 +00:00
|
|
|
|
2010-10-09 21:52:25 +00:00
|
|
|
setup_port(builder, data, flags);
|
Finish the Wine sync. These components are not just rc file changes
atl, comctl32, comdlg32, dwmapi, fusion, gdiplus, jscript, mpr, mshtml, msi, msimtf, msxml3, ole32, oleaut32, riched20, shdocvw, shlwapi, urlmon, usp10, version and windowscodecs
Seems to build and boot. /me hides
svn path=/trunk/; revision=48273
2010-07-26 02:26:04 +00:00
|
|
|
|
2010-12-20 21:29:55 +00:00
|
|
|
/* The URI is opaque if it doesn't have an authority component. */
|
|
|
|
if(!data->is_relative)
|
2013-03-22 14:29:11 +00:00
|
|
|
data->is_opaque = !data->username && !data->password && !data->host && !data->has_port
|
|
|
|
&& data->scheme_type != URL_SCHEME_FILE;
|
2010-12-20 21:29:55 +00:00
|
|
|
else
|
|
|
|
data->is_opaque = !data->host && !data->has_port;
|
|
|
|
|
2010-10-09 21:52:25 +00:00
|
|
|
hr = validate_path(builder, data, flags);
|
|
|
|
if(FAILED(hr))
|
|
|
|
return hr;
|
Finish the Wine sync. These components are not just rc file changes
atl, comctl32, comdlg32, dwmapi, fusion, gdiplus, jscript, mpr, mshtml, msi, msimtf, msxml3, ole32, oleaut32, riched20, shdocvw, shlwapi, urlmon, usp10, version and windowscodecs
Seems to build and boot. /me hides
svn path=/trunk/; revision=48273
2010-07-26 02:26:04 +00:00
|
|
|
|
2010-10-09 21:52:25 +00:00
|
|
|
hr = validate_query(builder, data, flags);
|
|
|
|
if(FAILED(hr))
|
|
|
|
return hr;
|
Finish the Wine sync. These components are not just rc file changes
atl, comctl32, comdlg32, dwmapi, fusion, gdiplus, jscript, mpr, mshtml, msi, msimtf, msxml3, ole32, oleaut32, riched20, shdocvw, shlwapi, urlmon, usp10, version and windowscodecs
Seems to build and boot. /me hides
svn path=/trunk/; revision=48273
2010-07-26 02:26:04 +00:00
|
|
|
|
2010-10-09 21:52:25 +00:00
|
|
|
hr = validate_fragment(builder, data, flags);
|
|
|
|
if(FAILED(hr))
|
|
|
|
return hr;
|
Finish the Wine sync. These components are not just rc file changes
atl, comctl32, comdlg32, dwmapi, fusion, gdiplus, jscript, mpr, mshtml, msi, msimtf, msxml3, ole32, oleaut32, riched20, shdocvw, shlwapi, urlmon, usp10, version and windowscodecs
Seems to build and boot. /me hides
svn path=/trunk/; revision=48273
2010-07-26 02:26:04 +00:00
|
|
|
|
2010-10-09 21:52:25 +00:00
|
|
|
TRACE("(%p %p %x): Finished validating builder components.\n", builder, data, flags);
|
Finish the Wine sync. These components are not just rc file changes
atl, comctl32, comdlg32, dwmapi, fusion, gdiplus, jscript, mpr, mshtml, msi, msimtf, msxml3, ole32, oleaut32, riched20, shdocvw, shlwapi, urlmon, usp10, version and windowscodecs
Seems to build and boot. /me hides
svn path=/trunk/; revision=48273
2010-07-26 02:26:04 +00:00
|
|
|
|
2010-10-09 21:52:25 +00:00
|
|
|
return S_OK;
|
|
|
|
}
|
Finish the Wine sync. These components are not just rc file changes
atl, comctl32, comdlg32, dwmapi, fusion, gdiplus, jscript, mpr, mshtml, msi, msimtf, msxml3, ole32, oleaut32, riched20, shdocvw, shlwapi, urlmon, usp10, version and windowscodecs
Seems to build and boot. /me hides
svn path=/trunk/; revision=48273
2010-07-26 02:26:04 +00:00
|
|
|
|
2013-03-22 14:29:11 +00:00
|
|
|
static HRESULT compare_file_paths(const Uri *a, const Uri *b, BOOL *ret)
|
|
|
|
{
|
|
|
|
WCHAR *canon_path_a, *canon_path_b;
|
|
|
|
DWORD len_a, len_b;
|
|
|
|
|
|
|
|
if(!a->path_len) {
|
|
|
|
*ret = !b->path_len;
|
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(!b->path_len) {
|
|
|
|
*ret = FALSE;
|
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Fast path */
|
|
|
|
if(a->path_len == b->path_len && !memicmpW(a->canon_uri+a->path_start, b->canon_uri+b->path_start, a->path_len)) {
|
|
|
|
*ret = TRUE;
|
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
|
2014-09-25 15:39:47 +00:00
|
|
|
len_a = canonicalize_path_hierarchical(a->canon_uri+a->path_start, a->path_len, a->scheme_type, FALSE, 0, FALSE, NULL);
|
|
|
|
len_b = canonicalize_path_hierarchical(b->canon_uri+b->path_start, b->path_len, b->scheme_type, FALSE, 0, FALSE, NULL);
|
2013-03-22 14:29:11 +00:00
|
|
|
|
|
|
|
canon_path_a = heap_alloc(len_a*sizeof(WCHAR));
|
|
|
|
if(!canon_path_a)
|
|
|
|
return E_OUTOFMEMORY;
|
|
|
|
canon_path_b = heap_alloc(len_b*sizeof(WCHAR));
|
|
|
|
if(!canon_path_b) {
|
|
|
|
heap_free(canon_path_a);
|
|
|
|
return E_OUTOFMEMORY;
|
|
|
|
}
|
|
|
|
|
2014-09-25 15:39:47 +00:00
|
|
|
len_a = canonicalize_path_hierarchical(a->canon_uri+a->path_start, a->path_len, a->scheme_type, FALSE, 0, FALSE, canon_path_a);
|
|
|
|
len_b = canonicalize_path_hierarchical(b->canon_uri+b->path_start, b->path_len, b->scheme_type, FALSE, 0, FALSE, canon_path_b);
|
2013-03-22 14:29:11 +00:00
|
|
|
|
|
|
|
*ret = len_a == len_b && !memicmpW(canon_path_a, canon_path_b, len_a);
|
|
|
|
|
|
|
|
heap_free(canon_path_a);
|
|
|
|
heap_free(canon_path_b);
|
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Checks if the two Uri's are logically equivalent. It's a simple
|
|
|
|
* comparison, since they are both of type Uri, and it can access
|
|
|
|
* the properties of each Uri directly without the need to go
|
|
|
|
* through the "IUri_Get*" interface calls.
|
|
|
|
*/
|
|
|
|
static HRESULT compare_uris(const Uri *a, const Uri *b, BOOL *ret) {
|
|
|
|
const BOOL known_scheme = a->scheme_type != URL_SCHEME_UNKNOWN;
|
|
|
|
const BOOL are_hierarchical = a->authority_start > -1 && b->authority_start > -1;
|
|
|
|
HRESULT hres;
|
|
|
|
|
|
|
|
*ret = FALSE;
|
|
|
|
|
|
|
|
if(a->scheme_type != b->scheme_type)
|
|
|
|
return S_OK;
|
|
|
|
|
|
|
|
/* Only compare the scheme names (if any) if their unknown scheme types. */
|
|
|
|
if(!known_scheme) {
|
|
|
|
if((a->scheme_start > -1 && b->scheme_start > -1) &&
|
|
|
|
(a->scheme_len == b->scheme_len)) {
|
|
|
|
/* Make sure the schemes are the same. */
|
|
|
|
if(StrCmpNW(a->canon_uri+a->scheme_start, b->canon_uri+b->scheme_start, a->scheme_len))
|
|
|
|
return S_OK;
|
|
|
|
} else if(a->scheme_len != b->scheme_len)
|
|
|
|
/* One of the Uri's has a scheme name, while the other doesn't. */
|
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* If they have a userinfo component, perform case sensitive compare. */
|
|
|
|
if((a->userinfo_start > -1 && b->userinfo_start > -1) &&
|
|
|
|
(a->userinfo_len == b->userinfo_len)) {
|
|
|
|
if(StrCmpNW(a->canon_uri+a->userinfo_start, b->canon_uri+b->userinfo_start, a->userinfo_len))
|
|
|
|
return S_OK;
|
|
|
|
} else if(a->userinfo_len != b->userinfo_len)
|
|
|
|
/* One of the Uri's had a userinfo, while the other one doesn't. */
|
|
|
|
return S_OK;
|
|
|
|
|
|
|
|
/* Check if they have a host name. */
|
|
|
|
if((a->host_start > -1 && b->host_start > -1) &&
|
|
|
|
(a->host_len == b->host_len)) {
|
|
|
|
/* Perform a case insensitive compare if they are a known scheme type. */
|
|
|
|
if(known_scheme) {
|
|
|
|
if(StrCmpNIW(a->canon_uri+a->host_start, b->canon_uri+b->host_start, a->host_len))
|
|
|
|
return S_OK;
|
|
|
|
} else if(StrCmpNW(a->canon_uri+a->host_start, b->canon_uri+b->host_start, a->host_len))
|
|
|
|
return S_OK;
|
|
|
|
} else if(a->host_len != b->host_len)
|
|
|
|
/* One of the Uri's had a host, while the other one didn't. */
|
|
|
|
return S_OK;
|
|
|
|
|
|
|
|
if(a->has_port && b->has_port) {
|
|
|
|
if(a->port != b->port)
|
|
|
|
return S_OK;
|
|
|
|
} else if(a->has_port || b->has_port)
|
|
|
|
/* One had a port, while the other one didn't. */
|
|
|
|
return S_OK;
|
|
|
|
|
|
|
|
/* Windows is weird with how it handles paths. For example
|
|
|
|
* One URI could be "http://google.com" (after canonicalization)
|
|
|
|
* and one could be "http://google.com/" and the IsEqual function
|
|
|
|
* would still evaluate to TRUE, but, only if they are both hierarchical
|
|
|
|
* URIs.
|
|
|
|
*/
|
|
|
|
if(a->scheme_type == URL_SCHEME_FILE) {
|
|
|
|
BOOL cmp;
|
|
|
|
|
|
|
|
hres = compare_file_paths(a, b, &cmp);
|
|
|
|
if(FAILED(hres) || !cmp)
|
|
|
|
return hres;
|
|
|
|
} else if((a->path_start > -1 && b->path_start > -1) &&
|
|
|
|
(a->path_len == b->path_len)) {
|
|
|
|
if(StrCmpNW(a->canon_uri+a->path_start, b->canon_uri+b->path_start, a->path_len))
|
|
|
|
return S_OK;
|
|
|
|
} else if(are_hierarchical && a->path_len == -1 && b->path_len == 0) {
|
|
|
|
if(*(a->canon_uri+a->path_start) != '/')
|
|
|
|
return S_OK;
|
|
|
|
} else if(are_hierarchical && b->path_len == 1 && a->path_len == 0) {
|
|
|
|
if(*(b->canon_uri+b->path_start) != '/')
|
|
|
|
return S_OK;
|
|
|
|
} else if(a->path_len != b->path_len)
|
|
|
|
return S_OK;
|
|
|
|
|
|
|
|
/* Compare the query strings of the two URIs. */
|
|
|
|
if((a->query_start > -1 && b->query_start > -1) &&
|
|
|
|
(a->query_len == b->query_len)) {
|
|
|
|
if(StrCmpNW(a->canon_uri+a->query_start, b->canon_uri+b->query_start, a->query_len))
|
|
|
|
return S_OK;
|
|
|
|
} else if(a->query_len != b->query_len)
|
|
|
|
return S_OK;
|
|
|
|
|
|
|
|
if((a->fragment_start > -1 && b->fragment_start > -1) &&
|
|
|
|
(a->fragment_len == b->fragment_len)) {
|
|
|
|
if(StrCmpNW(a->canon_uri+a->fragment_start, b->canon_uri+b->fragment_start, a->fragment_len))
|
|
|
|
return S_OK;
|
|
|
|
} else if(a->fragment_len != b->fragment_len)
|
|
|
|
return S_OK;
|
|
|
|
|
|
|
|
/* If we get here, the two URIs are equivalent. */
|
|
|
|
*ret = TRUE;
|
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
|
2010-12-20 21:29:55 +00:00
|
|
|
static void convert_to_dos_path(const WCHAR *path, DWORD path_len,
|
|
|
|
WCHAR *output, DWORD *output_len)
|
2010-10-09 21:52:25 +00:00
|
|
|
{
|
2010-12-20 21:29:55 +00:00
|
|
|
const WCHAR *ptr = path;
|
Finish the Wine sync. These components are not just rc file changes
atl, comctl32, comdlg32, dwmapi, fusion, gdiplus, jscript, mpr, mshtml, msi, msimtf, msxml3, ole32, oleaut32, riched20, shdocvw, shlwapi, urlmon, usp10, version and windowscodecs
Seems to build and boot. /me hides
svn path=/trunk/; revision=48273
2010-07-26 02:26:04 +00:00
|
|
|
|
2010-12-20 21:29:55 +00:00
|
|
|
if(path_len > 3 && *ptr == '/' && is_drive_path(path+1))
|
|
|
|
/* Skip over the leading / before the drive path. */
|
|
|
|
++ptr;
|
2010-10-09 21:52:25 +00:00
|
|
|
|
2010-12-20 21:29:55 +00:00
|
|
|
for(; ptr < path+path_len; ++ptr) {
|
|
|
|
if(*ptr == '/') {
|
|
|
|
if(output)
|
|
|
|
*output++ = '\\';
|
|
|
|
(*output_len)++;
|
|
|
|
} else {
|
|
|
|
if(output)
|
|
|
|
*output++ = *ptr;
|
|
|
|
(*output_len)++;
|
|
|
|
}
|
Finish the Wine sync. These components are not just rc file changes
atl, comctl32, comdlg32, dwmapi, fusion, gdiplus, jscript, mpr, mshtml, msi, msimtf, msxml3, ole32, oleaut32, riched20, shdocvw, shlwapi, urlmon, usp10, version and windowscodecs
Seems to build and boot. /me hides
svn path=/trunk/; revision=48273
2010-07-26 02:26:04 +00:00
|
|
|
}
|
2010-12-20 21:29:55 +00:00
|
|
|
}
|
Finish the Wine sync. These components are not just rc file changes
atl, comctl32, comdlg32, dwmapi, fusion, gdiplus, jscript, mpr, mshtml, msi, msimtf, msxml3, ole32, oleaut32, riched20, shdocvw, shlwapi, urlmon, usp10, version and windowscodecs
Seems to build and boot. /me hides
svn path=/trunk/; revision=48273
2010-07-26 02:26:04 +00:00
|
|
|
|
2010-12-20 21:29:55 +00:00
|
|
|
/* Generates a raw uri string using the parse_data. */
|
|
|
|
static DWORD generate_raw_uri(const parse_data *data, BSTR uri, DWORD flags) {
|
|
|
|
DWORD length = 0;
|
|
|
|
|
|
|
|
if(data->scheme) {
|
|
|
|
if(uri) {
|
|
|
|
memcpy(uri, data->scheme, data->scheme_len*sizeof(WCHAR));
|
|
|
|
uri[data->scheme_len] = ':';
|
|
|
|
}
|
|
|
|
length += data->scheme_len+1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(!data->is_opaque) {
|
|
|
|
/* For the "//" which appears before the authority component. */
|
|
|
|
if(uri) {
|
|
|
|
uri[length] = '/';
|
|
|
|
uri[length+1] = '/';
|
2010-10-09 21:52:25 +00:00
|
|
|
}
|
2010-12-20 21:29:55 +00:00
|
|
|
length += 2;
|
Finish the Wine sync. These components are not just rc file changes
atl, comctl32, comdlg32, dwmapi, fusion, gdiplus, jscript, mpr, mshtml, msi, msimtf, msxml3, ole32, oleaut32, riched20, shdocvw, shlwapi, urlmon, usp10, version and windowscodecs
Seems to build and boot. /me hides
svn path=/trunk/; revision=48273
2010-07-26 02:26:04 +00:00
|
|
|
|
2010-12-20 21:29:55 +00:00
|
|
|
/* Check if we need to add the "\\" before the host name
|
|
|
|
* of a UNC server name in a DOS path.
|
|
|
|
*/
|
|
|
|
if(flags & RAW_URI_CONVERT_TO_DOS_PATH &&
|
|
|
|
data->scheme_type == URL_SCHEME_FILE && data->host) {
|
|
|
|
if(uri) {
|
|
|
|
uri[length] = '\\';
|
|
|
|
uri[length+1] = '\\';
|
|
|
|
}
|
|
|
|
length += 2;
|
|
|
|
}
|
Finish the Wine sync. These components are not just rc file changes
atl, comctl32, comdlg32, dwmapi, fusion, gdiplus, jscript, mpr, mshtml, msi, msimtf, msxml3, ole32, oleaut32, riched20, shdocvw, shlwapi, urlmon, usp10, version and windowscodecs
Seems to build and boot. /me hides
svn path=/trunk/; revision=48273
2010-07-26 02:26:04 +00:00
|
|
|
}
|
|
|
|
|
2010-12-20 21:29:55 +00:00
|
|
|
if(data->username) {
|
|
|
|
if(uri)
|
|
|
|
memcpy(uri+length, data->username, data->username_len*sizeof(WCHAR));
|
|
|
|
length += data->username_len;
|
Finish the Wine sync. These components are not just rc file changes
atl, comctl32, comdlg32, dwmapi, fusion, gdiplus, jscript, mpr, mshtml, msi, msimtf, msxml3, ole32, oleaut32, riched20, shdocvw, shlwapi, urlmon, usp10, version and windowscodecs
Seems to build and boot. /me hides
svn path=/trunk/; revision=48273
2010-07-26 02:26:04 +00:00
|
|
|
}
|
|
|
|
|
2010-12-20 21:29:55 +00:00
|
|
|
if(data->password) {
|
|
|
|
if(uri) {
|
|
|
|
uri[length] = ':';
|
|
|
|
memcpy(uri+length+1, data->password, data->password_len*sizeof(WCHAR));
|
|
|
|
}
|
|
|
|
length += data->password_len+1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(data->password || data->username) {
|
|
|
|
if(uri)
|
|
|
|
uri[length] = '@';
|
|
|
|
++length;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(data->host) {
|
|
|
|
/* IPv6 addresses get the brackets added around them if they don't already
|
|
|
|
* have them.
|
|
|
|
*/
|
|
|
|
const BOOL add_brackets = data->host_type == Uri_HOST_IPV6 && *(data->host) != '[';
|
|
|
|
if(add_brackets) {
|
|
|
|
if(uri)
|
|
|
|
uri[length] = '[';
|
|
|
|
++length;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(uri)
|
|
|
|
memcpy(uri+length, data->host, data->host_len*sizeof(WCHAR));
|
|
|
|
length += data->host_len;
|
|
|
|
|
|
|
|
if(add_brackets) {
|
|
|
|
if(uri)
|
|
|
|
uri[length] = ']';
|
|
|
|
length++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if(data->has_port) {
|
|
|
|
/* The port isn't included in the raw uri if it's the default
|
|
|
|
* port for the scheme type.
|
|
|
|
*/
|
|
|
|
DWORD i;
|
|
|
|
BOOL is_default = FALSE;
|
|
|
|
|
2019-02-04 12:04:30 +00:00
|
|
|
for(i = 0; i < ARRAY_SIZE(default_ports); ++i) {
|
2010-12-20 21:29:55 +00:00
|
|
|
if(data->scheme_type == default_ports[i].scheme &&
|
|
|
|
data->port_value == default_ports[i].port)
|
|
|
|
is_default = TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(!is_default || flags & RAW_URI_FORCE_PORT_DISP) {
|
|
|
|
if(uri)
|
|
|
|
uri[length] = ':';
|
|
|
|
++length;
|
|
|
|
|
|
|
|
if(uri)
|
|
|
|
length += ui2str(uri+length, data->port_value);
|
|
|
|
else
|
|
|
|
length += ui2str(NULL, data->port_value);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Check if a '/' should be added before the path for hierarchical URIs. */
|
|
|
|
if(!data->is_opaque && data->path && *(data->path) != '/') {
|
|
|
|
if(uri)
|
|
|
|
uri[length] = '/';
|
|
|
|
++length;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(data->path) {
|
|
|
|
if(!data->is_opaque && data->scheme_type == URL_SCHEME_FILE &&
|
|
|
|
flags & RAW_URI_CONVERT_TO_DOS_PATH) {
|
|
|
|
DWORD len = 0;
|
|
|
|
|
|
|
|
if(uri)
|
|
|
|
convert_to_dos_path(data->path, data->path_len, uri+length, &len);
|
|
|
|
else
|
|
|
|
convert_to_dos_path(data->path, data->path_len, NULL, &len);
|
|
|
|
|
|
|
|
length += len;
|
|
|
|
} else {
|
|
|
|
if(uri)
|
|
|
|
memcpy(uri+length, data->path, data->path_len*sizeof(WCHAR));
|
|
|
|
length += data->path_len;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if(data->query) {
|
|
|
|
if(uri)
|
|
|
|
memcpy(uri+length, data->query, data->query_len*sizeof(WCHAR));
|
|
|
|
length += data->query_len;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(data->fragment) {
|
|
|
|
if(uri)
|
|
|
|
memcpy(uri+length, data->fragment, data->fragment_len*sizeof(WCHAR));
|
|
|
|
length += data->fragment_len;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(uri)
|
|
|
|
TRACE("(%p %p): Generated raw uri=%s len=%d\n", data, uri, debugstr_wn(uri, length), length);
|
|
|
|
else
|
|
|
|
TRACE("(%p %p): Computed raw uri len=%d\n", data, uri, length);
|
|
|
|
|
|
|
|
return length;
|
|
|
|
}
|
|
|
|
|
|
|
|
static HRESULT generate_uri(const UriBuilder *builder, const parse_data *data, Uri *uri, DWORD flags) {
|
|
|
|
HRESULT hr;
|
|
|
|
DWORD length = generate_raw_uri(data, NULL, 0);
|
|
|
|
uri->raw_uri = SysAllocStringLen(NULL, length);
|
|
|
|
if(!uri->raw_uri)
|
|
|
|
return E_OUTOFMEMORY;
|
|
|
|
|
|
|
|
generate_raw_uri(data, uri->raw_uri, 0);
|
|
|
|
|
|
|
|
hr = canonicalize_uri(data, uri, flags);
|
2010-10-09 21:52:25 +00:00
|
|
|
if(FAILED(hr)) {
|
2010-12-20 21:29:55 +00:00
|
|
|
if(hr == E_INVALIDARG)
|
|
|
|
return INET_E_INVALID_URL;
|
2010-10-09 21:52:25 +00:00
|
|
|
return hr;
|
|
|
|
}
|
Finish the Wine sync. These components are not just rc file changes
atl, comctl32, comdlg32, dwmapi, fusion, gdiplus, jscript, mpr, mshtml, msi, msimtf, msxml3, ole32, oleaut32, riched20, shdocvw, shlwapi, urlmon, usp10, version and windowscodecs
Seems to build and boot. /me hides
svn path=/trunk/; revision=48273
2010-07-26 02:26:04 +00:00
|
|
|
|
2010-12-20 21:29:55 +00:00
|
|
|
uri->create_flags = flags;
|
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline Uri* impl_from_IUri(IUri *iface)
|
|
|
|
{
|
|
|
|
return CONTAINING_RECORD(iface, Uri, IUri_iface);
|
Finish the Wine sync. These components are not just rc file changes
atl, comctl32, comdlg32, dwmapi, fusion, gdiplus, jscript, mpr, mshtml, msi, msimtf, msxml3, ole32, oleaut32, riched20, shdocvw, shlwapi, urlmon, usp10, version and windowscodecs
Seems to build and boot. /me hides
svn path=/trunk/; revision=48273
2010-07-26 02:26:04 +00:00
|
|
|
}
|
|
|
|
|
2013-03-22 14:29:11 +00:00
|
|
|
static inline void destroy_uri_obj(Uri *This)
|
2010-12-20 21:29:55 +00:00
|
|
|
{
|
|
|
|
SysFreeString(This->raw_uri);
|
|
|
|
heap_free(This->canon_uri);
|
|
|
|
heap_free(This);
|
|
|
|
}
|
2010-03-04 15:24:17 +00:00
|
|
|
|
|
|
|
static HRESULT WINAPI Uri_QueryInterface(IUri *iface, REFIID riid, void **ppv)
|
|
|
|
{
|
2010-12-20 21:29:55 +00:00
|
|
|
Uri *This = impl_from_IUri(iface);
|
2010-03-04 15:24:17 +00:00
|
|
|
|
|
|
|
if(IsEqualGUID(&IID_IUnknown, riid)) {
|
|
|
|
TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv);
|
2010-12-20 21:29:55 +00:00
|
|
|
*ppv = &This->IUri_iface;
|
2010-03-04 15:24:17 +00:00
|
|
|
}else if(IsEqualGUID(&IID_IUri, riid)) {
|
|
|
|
TRACE("(%p)->(IID_IUri %p)\n", This, ppv);
|
2010-12-20 21:29:55 +00:00
|
|
|
*ppv = &This->IUri_iface;
|
|
|
|
}else if(IsEqualGUID(&IID_IUriBuilderFactory, riid)) {
|
2013-03-22 14:29:11 +00:00
|
|
|
TRACE("(%p)->(IID_IUriBuilderFactory %p)\n", This, ppv);
|
2010-12-20 21:29:55 +00:00
|
|
|
*ppv = &This->IUriBuilderFactory_iface;
|
2013-03-22 14:29:11 +00:00
|
|
|
}else if(IsEqualGUID(&IID_IPersistStream, riid)) {
|
|
|
|
TRACE("(%p)->(IID_IPersistStream %p)\n", This, ppv);
|
|
|
|
*ppv = &This->IPersistStream_iface;
|
|
|
|
}else if(IsEqualGUID(&IID_IMarshal, riid)) {
|
|
|
|
TRACE("(%p)->(IID_IMarshal %p)\n", This, ppv);
|
|
|
|
*ppv = &This->IMarshal_iface;
|
2010-10-09 21:52:25 +00:00
|
|
|
}else if(IsEqualGUID(&IID_IUriObj, riid)) {
|
|
|
|
TRACE("(%p)->(IID_IUriObj %p)\n", This, ppv);
|
|
|
|
*ppv = This;
|
|
|
|
return S_OK;
|
2010-03-04 15:24:17 +00:00
|
|
|
}else {
|
|
|
|
TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppv);
|
|
|
|
*ppv = NULL;
|
|
|
|
return E_NOINTERFACE;
|
|
|
|
}
|
|
|
|
|
|
|
|
IUnknown_AddRef((IUnknown*)*ppv);
|
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
static ULONG WINAPI Uri_AddRef(IUri *iface)
|
|
|
|
{
|
2010-12-20 21:29:55 +00:00
|
|
|
Uri *This = impl_from_IUri(iface);
|
2010-03-04 15:24:17 +00:00
|
|
|
LONG ref = InterlockedIncrement(&This->ref);
|
|
|
|
|
|
|
|
TRACE("(%p) ref=%d\n", This, ref);
|
|
|
|
|
|
|
|
return ref;
|
|
|
|
}
|
|
|
|
|
|
|
|
static ULONG WINAPI Uri_Release(IUri *iface)
|
|
|
|
{
|
2010-12-20 21:29:55 +00:00
|
|
|
Uri *This = impl_from_IUri(iface);
|
2010-03-04 15:24:17 +00:00
|
|
|
LONG ref = InterlockedDecrement(&This->ref);
|
|
|
|
|
|
|
|
TRACE("(%p) ref=%d\n", This, ref);
|
|
|
|
|
2010-12-20 21:29:55 +00:00
|
|
|
if(!ref)
|
2013-03-22 14:29:11 +00:00
|
|
|
destroy_uri_obj(This);
|
2010-03-04 15:24:17 +00:00
|
|
|
|
|
|
|
return ref;
|
|
|
|
}
|
|
|
|
|
|
|
|
static HRESULT WINAPI Uri_GetPropertyBSTR(IUri *iface, Uri_PROPERTY uriProp, BSTR *pbstrProperty, DWORD dwFlags)
|
|
|
|
{
|
2010-12-20 21:29:55 +00:00
|
|
|
Uri *This = impl_from_IUri(iface);
|
Finish the Wine sync. These components are not just rc file changes
atl, comctl32, comdlg32, dwmapi, fusion, gdiplus, jscript, mpr, mshtml, msi, msimtf, msxml3, ole32, oleaut32, riched20, shdocvw, shlwapi, urlmon, usp10, version and windowscodecs
Seems to build and boot. /me hides
svn path=/trunk/; revision=48273
2010-07-26 02:26:04 +00:00
|
|
|
HRESULT hres;
|
2013-03-22 14:29:11 +00:00
|
|
|
TRACE("(%p %s)->(%d %p %x)\n", This, debugstr_w(This->canon_uri), uriProp, pbstrProperty, dwFlags);
|
Sync devenum, atl, comctl32, comdlg32, cryptdlg, cryptui, hhctrl, itss, jscript, mapi32, msacm32, mshtml, msi, msimtf, oleacc, pstorec, shdoclc, shdocvw, shlwapi, snmpapi, urlmon, usp10, uxtheme, windowscodecs, wldap32, wtsapi32, wuapi, xinput1_3
svn path=/trunk/; revision=47961
2010-07-06 23:29:26 +00:00
|
|
|
|
2013-03-22 14:29:11 +00:00
|
|
|
if(!This->create_flags)
|
|
|
|
return E_UNEXPECTED;
|
Sync devenum, atl, comctl32, comdlg32, cryptdlg, cryptui, hhctrl, itss, jscript, mapi32, msacm32, mshtml, msi, msimtf, oleacc, pstorec, shdoclc, shdocvw, shlwapi, snmpapi, urlmon, usp10, uxtheme, windowscodecs, wldap32, wtsapi32, wuapi, xinput1_3
svn path=/trunk/; revision=47961
2010-07-06 23:29:26 +00:00
|
|
|
if(!pbstrProperty)
|
|
|
|
return E_POINTER;
|
|
|
|
|
|
|
|
if(uriProp > Uri_PROPERTY_STRING_LAST) {
|
|
|
|
/* It only returns S_FALSE for the ZONE property... */
|
2014-04-23 17:35:17 +00:00
|
|
|
if(uriProp == Uri_PROPERTY_ZONE) {
|
|
|
|
*pbstrProperty = SysAllocStringLen(NULL, 0);
|
|
|
|
if(!(*pbstrProperty))
|
|
|
|
return E_OUTOFMEMORY;
|
Sync devenum, atl, comctl32, comdlg32, cryptdlg, cryptui, hhctrl, itss, jscript, mapi32, msacm32, mshtml, msi, msimtf, oleacc, pstorec, shdoclc, shdocvw, shlwapi, snmpapi, urlmon, usp10, uxtheme, windowscodecs, wldap32, wtsapi32, wuapi, xinput1_3
svn path=/trunk/; revision=47961
2010-07-06 23:29:26 +00:00
|
|
|
return S_FALSE;
|
2014-04-23 17:35:17 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
*pbstrProperty = NULL;
|
|
|
|
return E_INVALIDARG;
|
Sync devenum, atl, comctl32, comdlg32, cryptdlg, cryptui, hhctrl, itss, jscript, mapi32, msacm32, mshtml, msi, msimtf, oleacc, pstorec, shdoclc, shdocvw, shlwapi, snmpapi, urlmon, usp10, uxtheme, windowscodecs, wldap32, wtsapi32, wuapi, xinput1_3
svn path=/trunk/; revision=47961
2010-07-06 23:29:26 +00:00
|
|
|
}
|
|
|
|
|
Finish the Wine sync. These components are not just rc file changes
atl, comctl32, comdlg32, dwmapi, fusion, gdiplus, jscript, mpr, mshtml, msi, msimtf, msxml3, ole32, oleaut32, riched20, shdocvw, shlwapi, urlmon, usp10, version and windowscodecs
Seems to build and boot. /me hides
svn path=/trunk/; revision=48273
2010-07-26 02:26:04 +00:00
|
|
|
/* Don't have support for flags yet. */
|
|
|
|
if(dwFlags) {
|
|
|
|
FIXME("(%p)->(%d %p %x)\n", This, uriProp, pbstrProperty, dwFlags);
|
|
|
|
return E_NOTIMPL;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch(uriProp) {
|
2010-10-09 21:52:25 +00:00
|
|
|
case Uri_PROPERTY_ABSOLUTE_URI:
|
2010-12-20 21:29:55 +00:00
|
|
|
if(This->display_modifiers & URI_DISPLAY_NO_ABSOLUTE_URI) {
|
2010-10-09 21:52:25 +00:00
|
|
|
*pbstrProperty = SysAllocStringLen(NULL, 0);
|
|
|
|
hres = S_FALSE;
|
|
|
|
} else {
|
|
|
|
if(This->scheme_type != URL_SCHEME_UNKNOWN && This->userinfo_start > -1) {
|
|
|
|
if(This->userinfo_len == 0) {
|
|
|
|
/* Don't include the '@' after the userinfo component. */
|
|
|
|
*pbstrProperty = SysAllocStringLen(NULL, This->canon_len-1);
|
|
|
|
hres = S_OK;
|
|
|
|
if(*pbstrProperty) {
|
|
|
|
/* Copy everything before it. */
|
|
|
|
memcpy(*pbstrProperty, This->canon_uri, This->userinfo_start*sizeof(WCHAR));
|
|
|
|
|
|
|
|
/* And everything after it. */
|
|
|
|
memcpy(*pbstrProperty+This->userinfo_start, This->canon_uri+This->userinfo_start+1,
|
|
|
|
(This->canon_len-This->userinfo_start-1)*sizeof(WCHAR));
|
|
|
|
}
|
|
|
|
} else if(This->userinfo_split == 0 && This->userinfo_len == 1) {
|
|
|
|
/* Don't include the ":@" */
|
|
|
|
*pbstrProperty = SysAllocStringLen(NULL, This->canon_len-2);
|
|
|
|
hres = S_OK;
|
|
|
|
if(*pbstrProperty) {
|
|
|
|
memcpy(*pbstrProperty, This->canon_uri, This->userinfo_start*sizeof(WCHAR));
|
|
|
|
memcpy(*pbstrProperty+This->userinfo_start, This->canon_uri+This->userinfo_start+2,
|
|
|
|
(This->canon_len-This->userinfo_start-2)*sizeof(WCHAR));
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
*pbstrProperty = SysAllocString(This->canon_uri);
|
|
|
|
hres = S_OK;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
*pbstrProperty = SysAllocString(This->canon_uri);
|
|
|
|
hres = S_OK;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if(!(*pbstrProperty))
|
|
|
|
hres = E_OUTOFMEMORY;
|
|
|
|
|
|
|
|
break;
|
|
|
|
case Uri_PROPERTY_AUTHORITY:
|
|
|
|
if(This->authority_start > -1) {
|
2010-12-20 21:29:55 +00:00
|
|
|
if(This->port_offset > -1 && is_default_port(This->scheme_type, This->port) &&
|
|
|
|
This->display_modifiers & URI_DISPLAY_NO_DEFAULT_PORT_AUTH)
|
|
|
|
/* Don't include the port in the authority component. */
|
|
|
|
*pbstrProperty = SysAllocStringLen(This->canon_uri+This->authority_start, This->port_offset);
|
|
|
|
else
|
|
|
|
*pbstrProperty = SysAllocStringLen(This->canon_uri+This->authority_start, This->authority_len);
|
2010-10-09 21:52:25 +00:00
|
|
|
hres = S_OK;
|
|
|
|
} else {
|
|
|
|
*pbstrProperty = SysAllocStringLen(NULL, 0);
|
|
|
|
hres = S_FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(!(*pbstrProperty))
|
|
|
|
hres = E_OUTOFMEMORY;
|
|
|
|
|
|
|
|
break;
|
|
|
|
case Uri_PROPERTY_DISPLAY_URI:
|
|
|
|
/* The Display URI contains everything except for the userinfo for known
|
|
|
|
* scheme types.
|
|
|
|
*/
|
|
|
|
if(This->scheme_type != URL_SCHEME_UNKNOWN && This->userinfo_start > -1) {
|
|
|
|
*pbstrProperty = SysAllocStringLen(NULL, This->canon_len-This->userinfo_len);
|
|
|
|
|
|
|
|
if(*pbstrProperty) {
|
|
|
|
/* Copy everything before the userinfo over. */
|
|
|
|
memcpy(*pbstrProperty, This->canon_uri, This->userinfo_start*sizeof(WCHAR));
|
|
|
|
/* Copy everything after the userinfo over. */
|
|
|
|
memcpy(*pbstrProperty+This->userinfo_start,
|
|
|
|
This->canon_uri+This->userinfo_start+This->userinfo_len+1,
|
|
|
|
(This->canon_len-(This->userinfo_start+This->userinfo_len+1))*sizeof(WCHAR));
|
|
|
|
}
|
|
|
|
} else
|
|
|
|
*pbstrProperty = SysAllocString(This->canon_uri);
|
|
|
|
|
|
|
|
if(!(*pbstrProperty))
|
|
|
|
hres = E_OUTOFMEMORY;
|
|
|
|
else
|
|
|
|
hres = S_OK;
|
|
|
|
|
|
|
|
break;
|
|
|
|
case Uri_PROPERTY_DOMAIN:
|
|
|
|
if(This->domain_offset > -1) {
|
|
|
|
*pbstrProperty = SysAllocStringLen(This->canon_uri+This->host_start+This->domain_offset,
|
|
|
|
This->host_len-This->domain_offset);
|
|
|
|
hres = S_OK;
|
|
|
|
} else {
|
|
|
|
*pbstrProperty = SysAllocStringLen(NULL, 0);
|
|
|
|
hres = S_FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(!(*pbstrProperty))
|
|
|
|
hres = E_OUTOFMEMORY;
|
|
|
|
|
|
|
|
break;
|
|
|
|
case Uri_PROPERTY_EXTENSION:
|
|
|
|
if(This->extension_offset > -1) {
|
|
|
|
*pbstrProperty = SysAllocStringLen(This->canon_uri+This->path_start+This->extension_offset,
|
|
|
|
This->path_len-This->extension_offset);
|
|
|
|
hres = S_OK;
|
|
|
|
} else {
|
|
|
|
*pbstrProperty = SysAllocStringLen(NULL, 0);
|
|
|
|
hres = S_FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(!(*pbstrProperty))
|
|
|
|
hres = E_OUTOFMEMORY;
|
|
|
|
|
|
|
|
break;
|
|
|
|
case Uri_PROPERTY_FRAGMENT:
|
|
|
|
if(This->fragment_start > -1) {
|
|
|
|
*pbstrProperty = SysAllocStringLen(This->canon_uri+This->fragment_start, This->fragment_len);
|
|
|
|
hres = S_OK;
|
|
|
|
} else {
|
|
|
|
*pbstrProperty = SysAllocStringLen(NULL, 0);
|
|
|
|
hres = S_FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(!(*pbstrProperty))
|
|
|
|
hres = E_OUTOFMEMORY;
|
|
|
|
|
|
|
|
break;
|
Finish the Wine sync. These components are not just rc file changes
atl, comctl32, comdlg32, dwmapi, fusion, gdiplus, jscript, mpr, mshtml, msi, msimtf, msxml3, ole32, oleaut32, riched20, shdocvw, shlwapi, urlmon, usp10, version and windowscodecs
Seems to build and boot. /me hides
svn path=/trunk/; revision=48273
2010-07-26 02:26:04 +00:00
|
|
|
case Uri_PROPERTY_HOST:
|
|
|
|
if(This->host_start > -1) {
|
2010-10-09 21:52:25 +00:00
|
|
|
/* The '[' and ']' aren't included for IPv6 addresses. */
|
|
|
|
if(This->host_type == Uri_HOST_IPV6)
|
|
|
|
*pbstrProperty = SysAllocStringLen(This->canon_uri+This->host_start+1, This->host_len-2);
|
|
|
|
else
|
|
|
|
*pbstrProperty = SysAllocStringLen(This->canon_uri+This->host_start, This->host_len);
|
|
|
|
|
Finish the Wine sync. These components are not just rc file changes
atl, comctl32, comdlg32, dwmapi, fusion, gdiplus, jscript, mpr, mshtml, msi, msimtf, msxml3, ole32, oleaut32, riched20, shdocvw, shlwapi, urlmon, usp10, version and windowscodecs
Seems to build and boot. /me hides
svn path=/trunk/; revision=48273
2010-07-26 02:26:04 +00:00
|
|
|
hres = S_OK;
|
|
|
|
} else {
|
2010-10-09 21:52:25 +00:00
|
|
|
*pbstrProperty = SysAllocStringLen(NULL, 0);
|
|
|
|
hres = S_FALSE;
|
Finish the Wine sync. These components are not just rc file changes
atl, comctl32, comdlg32, dwmapi, fusion, gdiplus, jscript, mpr, mshtml, msi, msimtf, msxml3, ole32, oleaut32, riched20, shdocvw, shlwapi, urlmon, usp10, version and windowscodecs
Seems to build and boot. /me hides
svn path=/trunk/; revision=48273
2010-07-26 02:26:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if(!(*pbstrProperty))
|
|
|
|
hres = E_OUTOFMEMORY;
|
|
|
|
|
|
|
|
break;
|
|
|
|
case Uri_PROPERTY_PASSWORD:
|
|
|
|
if(This->userinfo_split > -1) {
|
|
|
|
*pbstrProperty = SysAllocStringLen(
|
|
|
|
This->canon_uri+This->userinfo_start+This->userinfo_split+1,
|
|
|
|
This->userinfo_len-This->userinfo_split-1);
|
|
|
|
hres = S_OK;
|
|
|
|
} else {
|
|
|
|
*pbstrProperty = SysAllocStringLen(NULL, 0);
|
|
|
|
hres = S_FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(!(*pbstrProperty))
|
|
|
|
return E_OUTOFMEMORY;
|
|
|
|
|
2010-10-09 21:52:25 +00:00
|
|
|
break;
|
|
|
|
case Uri_PROPERTY_PATH:
|
|
|
|
if(This->path_start > -1) {
|
|
|
|
*pbstrProperty = SysAllocStringLen(This->canon_uri+This->path_start, This->path_len);
|
|
|
|
hres = S_OK;
|
|
|
|
} else {
|
|
|
|
*pbstrProperty = SysAllocStringLen(NULL, 0);
|
|
|
|
hres = S_FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(!(*pbstrProperty))
|
|
|
|
hres = E_OUTOFMEMORY;
|
|
|
|
|
|
|
|
break;
|
|
|
|
case Uri_PROPERTY_PATH_AND_QUERY:
|
|
|
|
if(This->path_start > -1) {
|
|
|
|
*pbstrProperty = SysAllocStringLen(This->canon_uri+This->path_start, This->path_len+This->query_len);
|
|
|
|
hres = S_OK;
|
|
|
|
} else if(This->query_start > -1) {
|
|
|
|
*pbstrProperty = SysAllocStringLen(This->canon_uri+This->query_start, This->query_len);
|
|
|
|
hres = S_OK;
|
|
|
|
} else {
|
|
|
|
*pbstrProperty = SysAllocStringLen(NULL, 0);
|
|
|
|
hres = S_FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(!(*pbstrProperty))
|
|
|
|
hres = E_OUTOFMEMORY;
|
|
|
|
|
|
|
|
break;
|
|
|
|
case Uri_PROPERTY_QUERY:
|
|
|
|
if(This->query_start > -1) {
|
|
|
|
*pbstrProperty = SysAllocStringLen(This->canon_uri+This->query_start, This->query_len);
|
|
|
|
hres = S_OK;
|
|
|
|
} else {
|
|
|
|
*pbstrProperty = SysAllocStringLen(NULL, 0);
|
|
|
|
hres = S_FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(!(*pbstrProperty))
|
|
|
|
hres = E_OUTOFMEMORY;
|
|
|
|
|
Finish the Wine sync. These components are not just rc file changes
atl, comctl32, comdlg32, dwmapi, fusion, gdiplus, jscript, mpr, mshtml, msi, msimtf, msxml3, ole32, oleaut32, riched20, shdocvw, shlwapi, urlmon, usp10, version and windowscodecs
Seems to build and boot. /me hides
svn path=/trunk/; revision=48273
2010-07-26 02:26:04 +00:00
|
|
|
break;
|
|
|
|
case Uri_PROPERTY_RAW_URI:
|
|
|
|
*pbstrProperty = SysAllocString(This->raw_uri);
|
|
|
|
if(!(*pbstrProperty))
|
|
|
|
hres = E_OUTOFMEMORY;
|
|
|
|
else
|
|
|
|
hres = S_OK;
|
|
|
|
break;
|
|
|
|
case Uri_PROPERTY_SCHEME_NAME:
|
|
|
|
if(This->scheme_start > -1) {
|
|
|
|
*pbstrProperty = SysAllocStringLen(This->canon_uri + This->scheme_start, This->scheme_len);
|
|
|
|
hres = S_OK;
|
|
|
|
} else {
|
|
|
|
*pbstrProperty = SysAllocStringLen(NULL, 0);
|
|
|
|
hres = S_FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(!(*pbstrProperty))
|
|
|
|
hres = E_OUTOFMEMORY;
|
|
|
|
|
|
|
|
break;
|
|
|
|
case Uri_PROPERTY_USER_INFO:
|
|
|
|
if(This->userinfo_start > -1) {
|
|
|
|
*pbstrProperty = SysAllocStringLen(This->canon_uri+This->userinfo_start, This->userinfo_len);
|
|
|
|
hres = S_OK;
|
|
|
|
} else {
|
|
|
|
*pbstrProperty = SysAllocStringLen(NULL, 0);
|
|
|
|
hres = S_FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(!(*pbstrProperty))
|
|
|
|
hres = E_OUTOFMEMORY;
|
|
|
|
|
|
|
|
break;
|
|
|
|
case Uri_PROPERTY_USER_NAME:
|
2010-10-09 21:52:25 +00:00
|
|
|
if(This->userinfo_start > -1 && This->userinfo_split != 0) {
|
Finish the Wine sync. These components are not just rc file changes
atl, comctl32, comdlg32, dwmapi, fusion, gdiplus, jscript, mpr, mshtml, msi, msimtf, msxml3, ole32, oleaut32, riched20, shdocvw, shlwapi, urlmon, usp10, version and windowscodecs
Seems to build and boot. /me hides
svn path=/trunk/; revision=48273
2010-07-26 02:26:04 +00:00
|
|
|
/* If userinfo_split is set, that means a password exists
|
|
|
|
* so the username is only from userinfo_start to userinfo_split.
|
|
|
|
*/
|
|
|
|
if(This->userinfo_split > -1) {
|
|
|
|
*pbstrProperty = SysAllocStringLen(This->canon_uri + This->userinfo_start, This->userinfo_split);
|
|
|
|
hres = S_OK;
|
|
|
|
} else {
|
|
|
|
*pbstrProperty = SysAllocStringLen(This->canon_uri + This->userinfo_start, This->userinfo_len);
|
|
|
|
hres = S_OK;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
*pbstrProperty = SysAllocStringLen(NULL, 0);
|
|
|
|
hres = S_FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(!(*pbstrProperty))
|
|
|
|
return E_OUTOFMEMORY;
|
|
|
|
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
FIXME("(%p)->(%d %p %x)\n", This, uriProp, pbstrProperty, dwFlags);
|
|
|
|
hres = E_NOTIMPL;
|
|
|
|
}
|
|
|
|
|
|
|
|
return hres;
|
2010-03-04 15:24:17 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static HRESULT WINAPI Uri_GetPropertyLength(IUri *iface, Uri_PROPERTY uriProp, DWORD *pcchProperty, DWORD dwFlags)
|
|
|
|
{
|
2010-12-20 21:29:55 +00:00
|
|
|
Uri *This = impl_from_IUri(iface);
|
Finish the Wine sync. These components are not just rc file changes
atl, comctl32, comdlg32, dwmapi, fusion, gdiplus, jscript, mpr, mshtml, msi, msimtf, msxml3, ole32, oleaut32, riched20, shdocvw, shlwapi, urlmon, usp10, version and windowscodecs
Seems to build and boot. /me hides
svn path=/trunk/; revision=48273
2010-07-26 02:26:04 +00:00
|
|
|
HRESULT hres;
|
2013-03-22 14:29:11 +00:00
|
|
|
TRACE("(%p %s)->(%d %p %x)\n", This, debugstr_w(This->canon_uri), uriProp, pcchProperty, dwFlags);
|
Sync devenum, atl, comctl32, comdlg32, cryptdlg, cryptui, hhctrl, itss, jscript, mapi32, msacm32, mshtml, msi, msimtf, oleacc, pstorec, shdoclc, shdocvw, shlwapi, snmpapi, urlmon, usp10, uxtheme, windowscodecs, wldap32, wtsapi32, wuapi, xinput1_3
svn path=/trunk/; revision=47961
2010-07-06 23:29:26 +00:00
|
|
|
|
2013-03-22 14:29:11 +00:00
|
|
|
if(!This->create_flags)
|
|
|
|
return E_UNEXPECTED;
|
Sync devenum, atl, comctl32, comdlg32, cryptdlg, cryptui, hhctrl, itss, jscript, mapi32, msacm32, mshtml, msi, msimtf, oleacc, pstorec, shdoclc, shdocvw, shlwapi, snmpapi, urlmon, usp10, uxtheme, windowscodecs, wldap32, wtsapi32, wuapi, xinput1_3
svn path=/trunk/; revision=47961
2010-07-06 23:29:26 +00:00
|
|
|
if(!pcchProperty)
|
|
|
|
return E_INVALIDARG;
|
|
|
|
|
|
|
|
/* Can only return a length for a property if it's a string. */
|
|
|
|
if(uriProp > Uri_PROPERTY_STRING_LAST)
|
|
|
|
return E_INVALIDARG;
|
|
|
|
|
Finish the Wine sync. These components are not just rc file changes
atl, comctl32, comdlg32, dwmapi, fusion, gdiplus, jscript, mpr, mshtml, msi, msimtf, msxml3, ole32, oleaut32, riched20, shdocvw, shlwapi, urlmon, usp10, version and windowscodecs
Seems to build and boot. /me hides
svn path=/trunk/; revision=48273
2010-07-26 02:26:04 +00:00
|
|
|
/* Don't have support for flags yet. */
|
|
|
|
if(dwFlags) {
|
|
|
|
FIXME("(%p)->(%d %p %x)\n", This, uriProp, pcchProperty, dwFlags);
|
|
|
|
return E_NOTIMPL;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch(uriProp) {
|
2010-10-09 21:52:25 +00:00
|
|
|
case Uri_PROPERTY_ABSOLUTE_URI:
|
2010-12-20 21:29:55 +00:00
|
|
|
if(This->display_modifiers & URI_DISPLAY_NO_ABSOLUTE_URI) {
|
2010-10-09 21:52:25 +00:00
|
|
|
*pcchProperty = 0;
|
|
|
|
hres = S_FALSE;
|
|
|
|
} else {
|
|
|
|
if(This->scheme_type != URL_SCHEME_UNKNOWN) {
|
|
|
|
if(This->userinfo_start > -1 && This->userinfo_len == 0)
|
|
|
|
/* Don't include the '@' in the length. */
|
|
|
|
*pcchProperty = This->canon_len-1;
|
|
|
|
else if(This->userinfo_start > -1 && This->userinfo_len == 1 &&
|
|
|
|
This->userinfo_split == 0)
|
|
|
|
/* Don't include the ":@" in the length. */
|
|
|
|
*pcchProperty = This->canon_len-2;
|
|
|
|
else
|
|
|
|
*pcchProperty = This->canon_len;
|
|
|
|
} else
|
|
|
|
*pcchProperty = This->canon_len;
|
|
|
|
|
|
|
|
hres = S_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
|
|
case Uri_PROPERTY_AUTHORITY:
|
2010-12-20 21:29:55 +00:00
|
|
|
if(This->port_offset > -1 &&
|
|
|
|
This->display_modifiers & URI_DISPLAY_NO_DEFAULT_PORT_AUTH &&
|
|
|
|
is_default_port(This->scheme_type, This->port))
|
|
|
|
/* Only count up until the port in the authority. */
|
|
|
|
*pcchProperty = This->port_offset;
|
|
|
|
else
|
|
|
|
*pcchProperty = This->authority_len;
|
2010-10-09 21:52:25 +00:00
|
|
|
hres = (This->authority_start > -1) ? S_OK : S_FALSE;
|
|
|
|
break;
|
|
|
|
case Uri_PROPERTY_DISPLAY_URI:
|
|
|
|
if(This->scheme_type != URL_SCHEME_UNKNOWN && This->userinfo_start > -1)
|
|
|
|
*pcchProperty = This->canon_len-This->userinfo_len-1;
|
|
|
|
else
|
|
|
|
*pcchProperty = This->canon_len;
|
|
|
|
|
|
|
|
hres = S_OK;
|
|
|
|
break;
|
|
|
|
case Uri_PROPERTY_DOMAIN:
|
|
|
|
if(This->domain_offset > -1)
|
|
|
|
*pcchProperty = This->host_len - This->domain_offset;
|
|
|
|
else
|
|
|
|
*pcchProperty = 0;
|
|
|
|
|
|
|
|
hres = (This->domain_offset > -1) ? S_OK : S_FALSE;
|
|
|
|
break;
|
|
|
|
case Uri_PROPERTY_EXTENSION:
|
|
|
|
if(This->extension_offset > -1) {
|
|
|
|
*pcchProperty = This->path_len - This->extension_offset;
|
|
|
|
hres = S_OK;
|
|
|
|
} else {
|
|
|
|
*pcchProperty = 0;
|
|
|
|
hres = S_FALSE;
|
Finish the Wine sync. These components are not just rc file changes
atl, comctl32, comdlg32, dwmapi, fusion, gdiplus, jscript, mpr, mshtml, msi, msimtf, msxml3, ole32, oleaut32, riched20, shdocvw, shlwapi, urlmon, usp10, version and windowscodecs
Seems to build and boot. /me hides
svn path=/trunk/; revision=48273
2010-07-26 02:26:04 +00:00
|
|
|
}
|
|
|
|
|
2010-10-09 21:52:25 +00:00
|
|
|
break;
|
|
|
|
case Uri_PROPERTY_FRAGMENT:
|
|
|
|
*pcchProperty = This->fragment_len;
|
|
|
|
hres = (This->fragment_start > -1) ? S_OK : S_FALSE;
|
|
|
|
break;
|
|
|
|
case Uri_PROPERTY_HOST:
|
Finish the Wine sync. These components are not just rc file changes
atl, comctl32, comdlg32, dwmapi, fusion, gdiplus, jscript, mpr, mshtml, msi, msimtf, msxml3, ole32, oleaut32, riched20, shdocvw, shlwapi, urlmon, usp10, version and windowscodecs
Seems to build and boot. /me hides
svn path=/trunk/; revision=48273
2010-07-26 02:26:04 +00:00
|
|
|
*pcchProperty = This->host_len;
|
2010-10-09 21:52:25 +00:00
|
|
|
|
|
|
|
/* '[' and ']' aren't included in the length. */
|
|
|
|
if(This->host_type == Uri_HOST_IPV6)
|
|
|
|
*pcchProperty -= 2;
|
|
|
|
|
Finish the Wine sync. These components are not just rc file changes
atl, comctl32, comdlg32, dwmapi, fusion, gdiplus, jscript, mpr, mshtml, msi, msimtf, msxml3, ole32, oleaut32, riched20, shdocvw, shlwapi, urlmon, usp10, version and windowscodecs
Seems to build and boot. /me hides
svn path=/trunk/; revision=48273
2010-07-26 02:26:04 +00:00
|
|
|
hres = (This->host_start > -1) ? S_OK : S_FALSE;
|
|
|
|
break;
|
|
|
|
case Uri_PROPERTY_PASSWORD:
|
|
|
|
*pcchProperty = (This->userinfo_split > -1) ? This->userinfo_len-This->userinfo_split-1 : 0;
|
|
|
|
hres = (This->userinfo_split > -1) ? S_OK : S_FALSE;
|
|
|
|
break;
|
2010-10-09 21:52:25 +00:00
|
|
|
case Uri_PROPERTY_PATH:
|
|
|
|
*pcchProperty = This->path_len;
|
|
|
|
hres = (This->path_start > -1) ? S_OK : S_FALSE;
|
|
|
|
break;
|
|
|
|
case Uri_PROPERTY_PATH_AND_QUERY:
|
|
|
|
*pcchProperty = This->path_len+This->query_len;
|
|
|
|
hres = (This->path_start > -1 || This->query_start > -1) ? S_OK : S_FALSE;
|
|
|
|
break;
|
|
|
|
case Uri_PROPERTY_QUERY:
|
|
|
|
*pcchProperty = This->query_len;
|
|
|
|
hres = (This->query_start > -1) ? S_OK : S_FALSE;
|
|
|
|
break;
|
Finish the Wine sync. These components are not just rc file changes
atl, comctl32, comdlg32, dwmapi, fusion, gdiplus, jscript, mpr, mshtml, msi, msimtf, msxml3, ole32, oleaut32, riched20, shdocvw, shlwapi, urlmon, usp10, version and windowscodecs
Seems to build and boot. /me hides
svn path=/trunk/; revision=48273
2010-07-26 02:26:04 +00:00
|
|
|
case Uri_PROPERTY_RAW_URI:
|
|
|
|
*pcchProperty = SysStringLen(This->raw_uri);
|
|
|
|
hres = S_OK;
|
|
|
|
break;
|
|
|
|
case Uri_PROPERTY_SCHEME_NAME:
|
|
|
|
*pcchProperty = This->scheme_len;
|
|
|
|
hres = (This->scheme_start > -1) ? S_OK : S_FALSE;
|
|
|
|
break;
|
|
|
|
case Uri_PROPERTY_USER_INFO:
|
|
|
|
*pcchProperty = This->userinfo_len;
|
|
|
|
hres = (This->userinfo_start > -1) ? S_OK : S_FALSE;
|
|
|
|
break;
|
|
|
|
case Uri_PROPERTY_USER_NAME:
|
|
|
|
*pcchProperty = (This->userinfo_split > -1) ? This->userinfo_split : This->userinfo_len;
|
2010-10-09 21:52:25 +00:00
|
|
|
if(This->userinfo_split == 0)
|
|
|
|
hres = S_FALSE;
|
|
|
|
else
|
|
|
|
hres = (This->userinfo_start > -1) ? S_OK : S_FALSE;
|
Finish the Wine sync. These components are not just rc file changes
atl, comctl32, comdlg32, dwmapi, fusion, gdiplus, jscript, mpr, mshtml, msi, msimtf, msxml3, ole32, oleaut32, riched20, shdocvw, shlwapi, urlmon, usp10, version and windowscodecs
Seems to build and boot. /me hides
svn path=/trunk/; revision=48273
2010-07-26 02:26:04 +00:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
FIXME("(%p)->(%d %p %x)\n", This, uriProp, pcchProperty, dwFlags);
|
|
|
|
hres = E_NOTIMPL;
|
|
|
|
}
|
|
|
|
|
|
|
|
return hres;
|
2010-03-04 15:24:17 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static HRESULT WINAPI Uri_GetPropertyDWORD(IUri *iface, Uri_PROPERTY uriProp, DWORD *pcchProperty, DWORD dwFlags)
|
|
|
|
{
|
2010-12-20 21:29:55 +00:00
|
|
|
Uri *This = impl_from_IUri(iface);
|
Finish the Wine sync. These components are not just rc file changes
atl, comctl32, comdlg32, dwmapi, fusion, gdiplus, jscript, mpr, mshtml, msi, msimtf, msxml3, ole32, oleaut32, riched20, shdocvw, shlwapi, urlmon, usp10, version and windowscodecs
Seems to build and boot. /me hides
svn path=/trunk/; revision=48273
2010-07-26 02:26:04 +00:00
|
|
|
HRESULT hres;
|
|
|
|
|
2013-03-22 14:29:11 +00:00
|
|
|
TRACE("(%p %s)->(%d %p %x)\n", This, debugstr_w(This->canon_uri), uriProp, pcchProperty, dwFlags);
|
2010-05-30 10:20:31 +00:00
|
|
|
|
2013-03-22 14:29:11 +00:00
|
|
|
if(!This->create_flags)
|
|
|
|
return E_UNEXPECTED;
|
2010-05-30 10:20:31 +00:00
|
|
|
if(!pcchProperty)
|
|
|
|
return E_INVALIDARG;
|
|
|
|
|
|
|
|
/* Microsoft's implementation for the ZONE property of a URI seems to be lacking...
|
|
|
|
* From what I can tell, instead of checking which URLZONE the URI belongs to it
|
|
|
|
* simply assigns URLZONE_INVALID and returns E_NOTIMPL. This also applies to the GetZone
|
|
|
|
* function.
|
|
|
|
*/
|
|
|
|
if(uriProp == Uri_PROPERTY_ZONE) {
|
|
|
|
*pcchProperty = URLZONE_INVALID;
|
|
|
|
return E_NOTIMPL;
|
|
|
|
}
|
|
|
|
|
Sync devenum, atl, comctl32, comdlg32, cryptdlg, cryptui, hhctrl, itss, jscript, mapi32, msacm32, mshtml, msi, msimtf, oleacc, pstorec, shdoclc, shdocvw, shlwapi, snmpapi, urlmon, usp10, uxtheme, windowscodecs, wldap32, wtsapi32, wuapi, xinput1_3
svn path=/trunk/; revision=47961
2010-07-06 23:29:26 +00:00
|
|
|
if(uriProp < Uri_PROPERTY_DWORD_START) {
|
|
|
|
*pcchProperty = 0;
|
|
|
|
return E_INVALIDARG;
|
|
|
|
}
|
|
|
|
|
Finish the Wine sync. These components are not just rc file changes
atl, comctl32, comdlg32, dwmapi, fusion, gdiplus, jscript, mpr, mshtml, msi, msimtf, msxml3, ole32, oleaut32, riched20, shdocvw, shlwapi, urlmon, usp10, version and windowscodecs
Seems to build and boot. /me hides
svn path=/trunk/; revision=48273
2010-07-26 02:26:04 +00:00
|
|
|
switch(uriProp) {
|
2010-10-09 21:52:25 +00:00
|
|
|
case Uri_PROPERTY_HOST_TYPE:
|
|
|
|
*pcchProperty = This->host_type;
|
|
|
|
hres = S_OK;
|
|
|
|
break;
|
|
|
|
case Uri_PROPERTY_PORT:
|
|
|
|
if(!This->has_port) {
|
|
|
|
*pcchProperty = 0;
|
|
|
|
hres = S_FALSE;
|
|
|
|
} else {
|
|
|
|
*pcchProperty = This->port;
|
|
|
|
hres = S_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
|
|
case Uri_PROPERTY_SCHEME:
|
|
|
|
*pcchProperty = This->scheme_type;
|
|
|
|
hres = S_OK;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
FIXME("(%p)->(%d %p %x)\n", This, uriProp, pcchProperty, dwFlags);
|
|
|
|
hres = E_NOTIMPL;
|
|
|
|
}
|
|
|
|
|
|
|
|
return hres;
|
|
|
|
}
|
|
|
|
|
|
|
|
static HRESULT WINAPI Uri_HasProperty(IUri *iface, Uri_PROPERTY uriProp, BOOL *pfHasProperty)
|
|
|
|
{
|
2010-12-20 21:29:55 +00:00
|
|
|
Uri *This = impl_from_IUri(iface);
|
2013-03-22 14:29:11 +00:00
|
|
|
|
|
|
|
TRACE("(%p %s)->(%d %p)\n", This, debugstr_w(This->canon_uri), uriProp, pfHasProperty);
|
2010-10-09 21:52:25 +00:00
|
|
|
|
|
|
|
if(!pfHasProperty)
|
|
|
|
return E_INVALIDARG;
|
|
|
|
|
|
|
|
switch(uriProp) {
|
|
|
|
case Uri_PROPERTY_ABSOLUTE_URI:
|
2010-12-20 21:29:55 +00:00
|
|
|
*pfHasProperty = !(This->display_modifiers & URI_DISPLAY_NO_ABSOLUTE_URI);
|
2010-10-09 21:52:25 +00:00
|
|
|
break;
|
|
|
|
case Uri_PROPERTY_AUTHORITY:
|
|
|
|
*pfHasProperty = This->authority_start > -1;
|
|
|
|
break;
|
|
|
|
case Uri_PROPERTY_DISPLAY_URI:
|
|
|
|
*pfHasProperty = TRUE;
|
|
|
|
break;
|
|
|
|
case Uri_PROPERTY_DOMAIN:
|
|
|
|
*pfHasProperty = This->domain_offset > -1;
|
|
|
|
break;
|
|
|
|
case Uri_PROPERTY_EXTENSION:
|
|
|
|
*pfHasProperty = This->extension_offset > -1;
|
|
|
|
break;
|
|
|
|
case Uri_PROPERTY_FRAGMENT:
|
|
|
|
*pfHasProperty = This->fragment_start > -1;
|
|
|
|
break;
|
|
|
|
case Uri_PROPERTY_HOST:
|
|
|
|
*pfHasProperty = This->host_start > -1;
|
|
|
|
break;
|
|
|
|
case Uri_PROPERTY_PASSWORD:
|
|
|
|
*pfHasProperty = This->userinfo_split > -1;
|
|
|
|
break;
|
|
|
|
case Uri_PROPERTY_PATH:
|
|
|
|
*pfHasProperty = This->path_start > -1;
|
|
|
|
break;
|
|
|
|
case Uri_PROPERTY_PATH_AND_QUERY:
|
|
|
|
*pfHasProperty = (This->path_start > -1 || This->query_start > -1);
|
|
|
|
break;
|
|
|
|
case Uri_PROPERTY_QUERY:
|
|
|
|
*pfHasProperty = This->query_start > -1;
|
|
|
|
break;
|
|
|
|
case Uri_PROPERTY_RAW_URI:
|
|
|
|
*pfHasProperty = TRUE;
|
|
|
|
break;
|
|
|
|
case Uri_PROPERTY_SCHEME_NAME:
|
|
|
|
*pfHasProperty = This->scheme_start > -1;
|
|
|
|
break;
|
|
|
|
case Uri_PROPERTY_USER_INFO:
|
|
|
|
*pfHasProperty = This->userinfo_start > -1;
|
|
|
|
break;
|
|
|
|
case Uri_PROPERTY_USER_NAME:
|
|
|
|
if(This->userinfo_split == 0)
|
|
|
|
*pfHasProperty = FALSE;
|
|
|
|
else
|
|
|
|
*pfHasProperty = This->userinfo_start > -1;
|
|
|
|
break;
|
|
|
|
case Uri_PROPERTY_HOST_TYPE:
|
|
|
|
*pfHasProperty = TRUE;
|
|
|
|
break;
|
|
|
|
case Uri_PROPERTY_PORT:
|
|
|
|
*pfHasProperty = This->has_port;
|
|
|
|
break;
|
Finish the Wine sync. These components are not just rc file changes
atl, comctl32, comdlg32, dwmapi, fusion, gdiplus, jscript, mpr, mshtml, msi, msimtf, msxml3, ole32, oleaut32, riched20, shdocvw, shlwapi, urlmon, usp10, version and windowscodecs
Seems to build and boot. /me hides
svn path=/trunk/; revision=48273
2010-07-26 02:26:04 +00:00
|
|
|
case Uri_PROPERTY_SCHEME:
|
2010-10-09 21:52:25 +00:00
|
|
|
*pfHasProperty = TRUE;
|
|
|
|
break;
|
|
|
|
case Uri_PROPERTY_ZONE:
|
|
|
|
*pfHasProperty = FALSE;
|
Finish the Wine sync. These components are not just rc file changes
atl, comctl32, comdlg32, dwmapi, fusion, gdiplus, jscript, mpr, mshtml, msi, msimtf, msxml3, ole32, oleaut32, riched20, shdocvw, shlwapi, urlmon, usp10, version and windowscodecs
Seems to build and boot. /me hides
svn path=/trunk/; revision=48273
2010-07-26 02:26:04 +00:00
|
|
|
break;
|
|
|
|
default:
|
2010-10-09 21:52:25 +00:00
|
|
|
FIXME("(%p)->(%d %p): Unsupported property type.\n", This, uriProp, pfHasProperty);
|
|
|
|
return E_NOTIMPL;
|
Finish the Wine sync. These components are not just rc file changes
atl, comctl32, comdlg32, dwmapi, fusion, gdiplus, jscript, mpr, mshtml, msi, msimtf, msxml3, ole32, oleaut32, riched20, shdocvw, shlwapi, urlmon, usp10, version and windowscodecs
Seems to build and boot. /me hides
svn path=/trunk/; revision=48273
2010-07-26 02:26:04 +00:00
|
|
|
}
|
|
|
|
|
2010-10-09 21:52:25 +00:00
|
|
|
return S_OK;
|
2010-03-04 15:24:17 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static HRESULT WINAPI Uri_GetAbsoluteUri(IUri *iface, BSTR *pstrAbsoluteUri)
|
|
|
|
{
|
2010-10-09 21:52:25 +00:00
|
|
|
TRACE("(%p)->(%p)\n", iface, pstrAbsoluteUri);
|
2010-12-20 21:29:55 +00:00
|
|
|
return IUri_GetPropertyBSTR(iface, Uri_PROPERTY_ABSOLUTE_URI, pstrAbsoluteUri, 0);
|
2010-03-04 15:24:17 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static HRESULT WINAPI Uri_GetAuthority(IUri *iface, BSTR *pstrAuthority)
|
|
|
|
{
|
2010-10-09 21:52:25 +00:00
|
|
|
TRACE("(%p)->(%p)\n", iface, pstrAuthority);
|
2010-12-20 21:29:55 +00:00
|
|
|
return IUri_GetPropertyBSTR(iface, Uri_PROPERTY_AUTHORITY, pstrAuthority, 0);
|
2010-03-04 15:24:17 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static HRESULT WINAPI Uri_GetDisplayUri(IUri *iface, BSTR *pstrDisplayUri)
|
|
|
|
{
|
2010-10-09 21:52:25 +00:00
|
|
|
TRACE("(%p)->(%p)\n", iface, pstrDisplayUri);
|
2010-12-20 21:29:55 +00:00
|
|
|
return IUri_GetPropertyBSTR(iface, Uri_PROPERTY_DISPLAY_URI, pstrDisplayUri, 0);
|
2010-03-04 15:24:17 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static HRESULT WINAPI Uri_GetDomain(IUri *iface, BSTR *pstrDomain)
|
|
|
|
{
|
2010-10-09 21:52:25 +00:00
|
|
|
TRACE("(%p)->(%p)\n", iface, pstrDomain);
|
2010-12-20 21:29:55 +00:00
|
|
|
return IUri_GetPropertyBSTR(iface, Uri_PROPERTY_DOMAIN, pstrDomain, 0);
|
2010-03-04 15:24:17 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static HRESULT WINAPI Uri_GetExtension(IUri *iface, BSTR *pstrExtension)
|
|
|
|
{
|
2010-10-09 21:52:25 +00:00
|
|
|
TRACE("(%p)->(%p)\n", iface, pstrExtension);
|
2010-12-20 21:29:55 +00:00
|
|
|
return IUri_GetPropertyBSTR(iface, Uri_PROPERTY_EXTENSION, pstrExtension, 0);
|
2010-03-04 15:24:17 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static HRESULT WINAPI Uri_GetFragment(IUri *iface, BSTR *pstrFragment)
|
|
|
|
{
|
2010-10-09 21:52:25 +00:00
|
|
|
TRACE("(%p)->(%p)\n", iface, pstrFragment);
|
2010-12-20 21:29:55 +00:00
|
|
|
return IUri_GetPropertyBSTR(iface, Uri_PROPERTY_FRAGMENT, pstrFragment, 0);
|
2010-03-04 15:24:17 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static HRESULT WINAPI Uri_GetHost(IUri *iface, BSTR *pstrHost)
|
|
|
|
{
|
Finish the Wine sync. These components are not just rc file changes
atl, comctl32, comdlg32, dwmapi, fusion, gdiplus, jscript, mpr, mshtml, msi, msimtf, msxml3, ole32, oleaut32, riched20, shdocvw, shlwapi, urlmon, usp10, version and windowscodecs
Seems to build and boot. /me hides
svn path=/trunk/; revision=48273
2010-07-26 02:26:04 +00:00
|
|
|
TRACE("(%p)->(%p)\n", iface, pstrHost);
|
2010-12-20 21:29:55 +00:00
|
|
|
return IUri_GetPropertyBSTR(iface, Uri_PROPERTY_HOST, pstrHost, 0);
|
2010-03-04 15:24:17 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static HRESULT WINAPI Uri_GetPassword(IUri *iface, BSTR *pstrPassword)
|
|
|
|
{
|
Finish the Wine sync. These components are not just rc file changes
atl, comctl32, comdlg32, dwmapi, fusion, gdiplus, jscript, mpr, mshtml, msi, msimtf, msxml3, ole32, oleaut32, riched20, shdocvw, shlwapi, urlmon, usp10, version and windowscodecs
Seems to build and boot. /me hides
svn path=/trunk/; revision=48273
2010-07-26 02:26:04 +00:00
|
|
|
TRACE("(%p)->(%p)\n", iface, pstrPassword);
|
2010-12-20 21:29:55 +00:00
|
|
|
return IUri_GetPropertyBSTR(iface, Uri_PROPERTY_PASSWORD, pstrPassword, 0);
|
2010-03-04 15:24:17 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static HRESULT WINAPI Uri_GetPath(IUri *iface, BSTR *pstrPath)
|
|
|
|
{
|
2010-10-09 21:52:25 +00:00
|
|
|
TRACE("(%p)->(%p)\n", iface, pstrPath);
|
2010-12-20 21:29:55 +00:00
|
|
|
return IUri_GetPropertyBSTR(iface, Uri_PROPERTY_PATH, pstrPath, 0);
|
2010-03-04 15:24:17 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static HRESULT WINAPI Uri_GetPathAndQuery(IUri *iface, BSTR *pstrPathAndQuery)
|
|
|
|
{
|
2010-10-09 21:52:25 +00:00
|
|
|
TRACE("(%p)->(%p)\n", iface, pstrPathAndQuery);
|
2010-12-20 21:29:55 +00:00
|
|
|
return IUri_GetPropertyBSTR(iface, Uri_PROPERTY_PATH_AND_QUERY, pstrPathAndQuery, 0);
|
2010-03-04 15:24:17 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static HRESULT WINAPI Uri_GetQuery(IUri *iface, BSTR *pstrQuery)
|
|
|
|
{
|
2010-10-09 21:52:25 +00:00
|
|
|
TRACE("(%p)->(%p)\n", iface, pstrQuery);
|
2010-12-20 21:29:55 +00:00
|
|
|
return IUri_GetPropertyBSTR(iface, Uri_PROPERTY_QUERY, pstrQuery, 0);
|
2010-03-04 15:24:17 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static HRESULT WINAPI Uri_GetRawUri(IUri *iface, BSTR *pstrRawUri)
|
|
|
|
{
|
2010-10-09 21:52:25 +00:00
|
|
|
TRACE("(%p)->(%p)\n", iface, pstrRawUri);
|
2010-12-20 21:29:55 +00:00
|
|
|
return IUri_GetPropertyBSTR(iface, Uri_PROPERTY_RAW_URI, pstrRawUri, 0);
|
2010-03-04 15:24:17 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static HRESULT WINAPI Uri_GetSchemeName(IUri *iface, BSTR *pstrSchemeName)
|
|
|
|
{
|
2010-10-09 21:52:25 +00:00
|
|
|
TRACE("(%p)->(%p)\n", iface, pstrSchemeName);
|
2010-12-20 21:29:55 +00:00
|
|
|
return IUri_GetPropertyBSTR(iface, Uri_PROPERTY_SCHEME_NAME, pstrSchemeName, 0);
|
2010-03-04 15:24:17 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static HRESULT WINAPI Uri_GetUserInfo(IUri *iface, BSTR *pstrUserInfo)
|
|
|
|
{
|
Finish the Wine sync. These components are not just rc file changes
atl, comctl32, comdlg32, dwmapi, fusion, gdiplus, jscript, mpr, mshtml, msi, msimtf, msxml3, ole32, oleaut32, riched20, shdocvw, shlwapi, urlmon, usp10, version and windowscodecs
Seems to build and boot. /me hides
svn path=/trunk/; revision=48273
2010-07-26 02:26:04 +00:00
|
|
|
TRACE("(%p)->(%p)\n", iface, pstrUserInfo);
|
2010-12-20 21:29:55 +00:00
|
|
|
return IUri_GetPropertyBSTR(iface, Uri_PROPERTY_USER_INFO, pstrUserInfo, 0);
|
2010-03-04 15:24:17 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static HRESULT WINAPI Uri_GetUserName(IUri *iface, BSTR *pstrUserName)
|
|
|
|
{
|
Finish the Wine sync. These components are not just rc file changes
atl, comctl32, comdlg32, dwmapi, fusion, gdiplus, jscript, mpr, mshtml, msi, msimtf, msxml3, ole32, oleaut32, riched20, shdocvw, shlwapi, urlmon, usp10, version and windowscodecs
Seems to build and boot. /me hides
svn path=/trunk/; revision=48273
2010-07-26 02:26:04 +00:00
|
|
|
TRACE("(%p)->(%p)\n", iface, pstrUserName);
|
2010-12-20 21:29:55 +00:00
|
|
|
return IUri_GetPropertyBSTR(iface, Uri_PROPERTY_USER_NAME, pstrUserName, 0);
|
2010-03-04 15:24:17 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static HRESULT WINAPI Uri_GetHostType(IUri *iface, DWORD *pdwHostType)
|
|
|
|
{
|
2010-10-09 21:52:25 +00:00
|
|
|
TRACE("(%p)->(%p)\n", iface, pdwHostType);
|
2010-12-20 21:29:55 +00:00
|
|
|
return IUri_GetPropertyDWORD(iface, Uri_PROPERTY_HOST_TYPE, pdwHostType, 0);
|
2010-03-04 15:24:17 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static HRESULT WINAPI Uri_GetPort(IUri *iface, DWORD *pdwPort)
|
|
|
|
{
|
2010-10-09 21:52:25 +00:00
|
|
|
TRACE("(%p)->(%p)\n", iface, pdwPort);
|
2010-12-20 21:29:55 +00:00
|
|
|
return IUri_GetPropertyDWORD(iface, Uri_PROPERTY_PORT, pdwPort, 0);
|
2010-03-04 15:24:17 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static HRESULT WINAPI Uri_GetScheme(IUri *iface, DWORD *pdwScheme)
|
|
|
|
{
|
2010-12-20 21:29:55 +00:00
|
|
|
TRACE("(%p)->(%p)\n", iface, pdwScheme);
|
|
|
|
return IUri_GetPropertyDWORD(iface, Uri_PROPERTY_SCHEME, pdwScheme, 0);
|
2010-03-04 15:24:17 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static HRESULT WINAPI Uri_GetZone(IUri *iface, DWORD *pdwZone)
|
|
|
|
{
|
2010-10-09 21:52:25 +00:00
|
|
|
TRACE("(%p)->(%p)\n", iface, pdwZone);
|
2010-12-20 21:29:55 +00:00
|
|
|
return IUri_GetPropertyDWORD(iface, Uri_PROPERTY_ZONE,pdwZone, 0);
|
2010-03-04 15:24:17 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static HRESULT WINAPI Uri_GetProperties(IUri *iface, DWORD *pdwProperties)
|
|
|
|
{
|
2010-12-20 21:29:55 +00:00
|
|
|
Uri *This = impl_from_IUri(iface);
|
2013-03-22 14:29:11 +00:00
|
|
|
TRACE("(%p %s)->(%p)\n", This, debugstr_w(This->canon_uri), pdwProperties);
|
Sync devenum, atl, comctl32, comdlg32, cryptdlg, cryptui, hhctrl, itss, jscript, mapi32, msacm32, mshtml, msi, msimtf, oleacc, pstorec, shdoclc, shdocvw, shlwapi, snmpapi, urlmon, usp10, uxtheme, windowscodecs, wldap32, wtsapi32, wuapi, xinput1_3
svn path=/trunk/; revision=47961
2010-07-06 23:29:26 +00:00
|
|
|
|
2013-03-22 14:29:11 +00:00
|
|
|
if(!This->create_flags)
|
|
|
|
return E_UNEXPECTED;
|
Sync devenum, atl, comctl32, comdlg32, cryptdlg, cryptui, hhctrl, itss, jscript, mapi32, msacm32, mshtml, msi, msimtf, oleacc, pstorec, shdoclc, shdocvw, shlwapi, snmpapi, urlmon, usp10, uxtheme, windowscodecs, wldap32, wtsapi32, wuapi, xinput1_3
svn path=/trunk/; revision=47961
2010-07-06 23:29:26 +00:00
|
|
|
if(!pdwProperties)
|
|
|
|
return E_INVALIDARG;
|
|
|
|
|
2010-10-09 21:52:25 +00:00
|
|
|
/* All URIs have these. */
|
|
|
|
*pdwProperties = Uri_HAS_DISPLAY_URI|Uri_HAS_RAW_URI|Uri_HAS_SCHEME|Uri_HAS_HOST_TYPE;
|
|
|
|
|
2010-12-20 21:29:55 +00:00
|
|
|
if(!(This->display_modifiers & URI_DISPLAY_NO_ABSOLUTE_URI))
|
2010-10-09 21:52:25 +00:00
|
|
|
*pdwProperties |= Uri_HAS_ABSOLUTE_URI;
|
|
|
|
|
|
|
|
if(This->scheme_start > -1)
|
|
|
|
*pdwProperties |= Uri_HAS_SCHEME_NAME;
|
|
|
|
|
|
|
|
if(This->authority_start > -1) {
|
|
|
|
*pdwProperties |= Uri_HAS_AUTHORITY;
|
|
|
|
if(This->userinfo_start > -1) {
|
|
|
|
*pdwProperties |= Uri_HAS_USER_INFO;
|
|
|
|
if(This->userinfo_split != 0)
|
|
|
|
*pdwProperties |= Uri_HAS_USER_NAME;
|
|
|
|
}
|
|
|
|
if(This->userinfo_split > -1)
|
|
|
|
*pdwProperties |= Uri_HAS_PASSWORD;
|
|
|
|
if(This->host_start > -1)
|
|
|
|
*pdwProperties |= Uri_HAS_HOST;
|
|
|
|
if(This->domain_offset > -1)
|
|
|
|
*pdwProperties |= Uri_HAS_DOMAIN;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(This->has_port)
|
|
|
|
*pdwProperties |= Uri_HAS_PORT;
|
|
|
|
if(This->path_start > -1)
|
|
|
|
*pdwProperties |= Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY;
|
|
|
|
if(This->query_start > -1)
|
|
|
|
*pdwProperties |= Uri_HAS_QUERY|Uri_HAS_PATH_AND_QUERY;
|
|
|
|
|
|
|
|
if(This->extension_offset > -1)
|
|
|
|
*pdwProperties |= Uri_HAS_EXTENSION;
|
|
|
|
|
|
|
|
if(This->fragment_start > -1)
|
|
|
|
*pdwProperties |= Uri_HAS_FRAGMENT;
|
|
|
|
|
|
|
|
return S_OK;
|
2010-03-04 15:24:17 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static HRESULT WINAPI Uri_IsEqual(IUri *iface, IUri *pUri, BOOL *pfEqual)
|
|
|
|
{
|
2010-12-20 21:29:55 +00:00
|
|
|
Uri *This = impl_from_IUri(iface);
|
2010-10-09 21:52:25 +00:00
|
|
|
Uri *other;
|
|
|
|
|
2013-03-22 14:29:11 +00:00
|
|
|
TRACE("(%p %s)->(%p %p)\n", This, debugstr_w(This->canon_uri), pUri, pfEqual);
|
Sync devenum, atl, comctl32, comdlg32, cryptdlg, cryptui, hhctrl, itss, jscript, mapi32, msacm32, mshtml, msi, msimtf, oleacc, pstorec, shdoclc, shdocvw, shlwapi, snmpapi, urlmon, usp10, uxtheme, windowscodecs, wldap32, wtsapi32, wuapi, xinput1_3
svn path=/trunk/; revision=47961
2010-07-06 23:29:26 +00:00
|
|
|
|
2013-03-22 14:29:11 +00:00
|
|
|
if(!This->create_flags)
|
|
|
|
return E_UNEXPECTED;
|
Sync devenum, atl, comctl32, comdlg32, cryptdlg, cryptui, hhctrl, itss, jscript, mapi32, msacm32, mshtml, msi, msimtf, oleacc, pstorec, shdoclc, shdocvw, shlwapi, snmpapi, urlmon, usp10, uxtheme, windowscodecs, wldap32, wtsapi32, wuapi, xinput1_3
svn path=/trunk/; revision=47961
2010-07-06 23:29:26 +00:00
|
|
|
if(!pfEqual)
|
|
|
|
return E_POINTER;
|
|
|
|
|
|
|
|
if(!pUri) {
|
|
|
|
*pfEqual = FALSE;
|
|
|
|
|
|
|
|
/* For some reason Windows returns S_OK here... */
|
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
|
2010-10-09 21:52:25 +00:00
|
|
|
/* Try to convert it to a Uri (allows for a more simple comparison). */
|
2013-03-22 14:29:11 +00:00
|
|
|
if(!(other = get_uri_obj(pUri))) {
|
2010-10-09 21:52:25 +00:00
|
|
|
FIXME("(%p)->(%p %p) No support for unknown IUri's yet.\n", iface, pUri, pfEqual);
|
|
|
|
return E_NOTIMPL;
|
|
|
|
}
|
|
|
|
|
2013-03-22 14:29:11 +00:00
|
|
|
TRACE("comparing to %s\n", debugstr_w(other->canon_uri));
|
|
|
|
return compare_uris(This, other, pfEqual);
|
2010-03-04 15:24:17 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static const IUriVtbl UriVtbl = {
|
|
|
|
Uri_QueryInterface,
|
|
|
|
Uri_AddRef,
|
|
|
|
Uri_Release,
|
|
|
|
Uri_GetPropertyBSTR,
|
|
|
|
Uri_GetPropertyLength,
|
|
|
|
Uri_GetPropertyDWORD,
|
|
|
|
Uri_HasProperty,
|
|
|
|
Uri_GetAbsoluteUri,
|
|
|
|
Uri_GetAuthority,
|
|
|
|
Uri_GetDisplayUri,
|
|
|
|
Uri_GetDomain,
|
|
|
|
Uri_GetExtension,
|
|
|
|
Uri_GetFragment,
|
|
|
|
Uri_GetHost,
|
|
|
|
Uri_GetPassword,
|
|
|
|
Uri_GetPath,
|
|
|
|
Uri_GetPathAndQuery,
|
|
|
|
Uri_GetQuery,
|
|
|
|
Uri_GetRawUri,
|
|
|
|
Uri_GetSchemeName,
|
|
|
|
Uri_GetUserInfo,
|
|
|
|
Uri_GetUserName,
|
|
|
|
Uri_GetHostType,
|
|
|
|
Uri_GetPort,
|
|
|
|
Uri_GetScheme,
|
|
|
|
Uri_GetZone,
|
|
|
|
Uri_GetProperties,
|
|
|
|
Uri_IsEqual
|
|
|
|
};
|
|
|
|
|
2010-12-20 21:29:55 +00:00
|
|
|
static inline Uri* impl_from_IUriBuilderFactory(IUriBuilderFactory *iface)
|
|
|
|
{
|
|
|
|
return CONTAINING_RECORD(iface, Uri, IUriBuilderFactory_iface);
|
|
|
|
}
|
|
|
|
|
|
|
|
static HRESULT WINAPI UriBuilderFactory_QueryInterface(IUriBuilderFactory *iface, REFIID riid, void **ppv)
|
|
|
|
{
|
|
|
|
Uri *This = impl_from_IUriBuilderFactory(iface);
|
2013-03-22 14:29:11 +00:00
|
|
|
return IUri_QueryInterface(&This->IUri_iface, riid, ppv);
|
2010-12-20 21:29:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static ULONG WINAPI UriBuilderFactory_AddRef(IUriBuilderFactory *iface)
|
|
|
|
{
|
|
|
|
Uri *This = impl_from_IUriBuilderFactory(iface);
|
2013-03-22 14:29:11 +00:00
|
|
|
return IUri_AddRef(&This->IUri_iface);
|
2010-12-20 21:29:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static ULONG WINAPI UriBuilderFactory_Release(IUriBuilderFactory *iface)
|
|
|
|
{
|
|
|
|
Uri *This = impl_from_IUriBuilderFactory(iface);
|
2013-03-22 14:29:11 +00:00
|
|
|
return IUri_Release(&This->IUri_iface);
|
2010-12-20 21:29:55 +00:00
|
|
|
}
|
|
|
|
|
2011-06-05 21:29:41 +00:00
|
|
|
static HRESULT WINAPI UriBuilderFactory_CreateIUriBuilder(IUriBuilderFactory *iface,
|
|
|
|
DWORD dwFlags,
|
|
|
|
DWORD_PTR dwReserved,
|
|
|
|
IUriBuilder **ppIUriBuilder)
|
2010-12-20 21:29:55 +00:00
|
|
|
{
|
|
|
|
Uri *This = impl_from_IUriBuilderFactory(iface);
|
|
|
|
TRACE("(%p)->(%08x %08x %p)\n", This, dwFlags, (DWORD)dwReserved, ppIUriBuilder);
|
|
|
|
|
|
|
|
if(!ppIUriBuilder)
|
|
|
|
return E_POINTER;
|
|
|
|
|
|
|
|
if(dwFlags || dwReserved) {
|
|
|
|
*ppIUriBuilder = NULL;
|
|
|
|
return E_INVALIDARG;
|
|
|
|
}
|
|
|
|
|
|
|
|
return CreateIUriBuilder(NULL, 0, 0, ppIUriBuilder);
|
|
|
|
}
|
|
|
|
|
2011-06-05 21:29:41 +00:00
|
|
|
static HRESULT WINAPI UriBuilderFactory_CreateInitializedIUriBuilder(IUriBuilderFactory *iface,
|
|
|
|
DWORD dwFlags,
|
|
|
|
DWORD_PTR dwReserved,
|
|
|
|
IUriBuilder **ppIUriBuilder)
|
2010-12-20 21:29:55 +00:00
|
|
|
{
|
|
|
|
Uri *This = impl_from_IUriBuilderFactory(iface);
|
|
|
|
TRACE("(%p)->(%08x %08x %p)\n", This, dwFlags, (DWORD)dwReserved, ppIUriBuilder);
|
|
|
|
|
|
|
|
if(!ppIUriBuilder)
|
|
|
|
return E_POINTER;
|
|
|
|
|
|
|
|
if(dwFlags || dwReserved) {
|
|
|
|
*ppIUriBuilder = NULL;
|
|
|
|
return E_INVALIDARG;
|
|
|
|
}
|
|
|
|
|
|
|
|
return CreateIUriBuilder(&This->IUri_iface, 0, 0, ppIUriBuilder);
|
|
|
|
}
|
|
|
|
|
|
|
|
static const IUriBuilderFactoryVtbl UriBuilderFactoryVtbl = {
|
|
|
|
UriBuilderFactory_QueryInterface,
|
|
|
|
UriBuilderFactory_AddRef,
|
|
|
|
UriBuilderFactory_Release,
|
2011-06-05 21:29:41 +00:00
|
|
|
UriBuilderFactory_CreateIUriBuilder,
|
|
|
|
UriBuilderFactory_CreateInitializedIUriBuilder
|
2010-12-20 21:29:55 +00:00
|
|
|
};
|
|
|
|
|
2013-03-22 14:29:11 +00:00
|
|
|
static inline Uri* impl_from_IPersistStream(IPersistStream *iface)
|
|
|
|
{
|
|
|
|
return CONTAINING_RECORD(iface, Uri, IPersistStream_iface);
|
|
|
|
}
|
|
|
|
|
|
|
|
static HRESULT WINAPI PersistStream_QueryInterface(IPersistStream *iface, REFIID riid, void **ppvObject)
|
|
|
|
{
|
|
|
|
Uri *This = impl_from_IPersistStream(iface);
|
|
|
|
return IUri_QueryInterface(&This->IUri_iface, riid, ppvObject);
|
|
|
|
}
|
|
|
|
|
|
|
|
static ULONG WINAPI PersistStream_AddRef(IPersistStream *iface)
|
|
|
|
{
|
|
|
|
Uri *This = impl_from_IPersistStream(iface);
|
|
|
|
return IUri_AddRef(&This->IUri_iface);
|
|
|
|
}
|
|
|
|
|
|
|
|
static ULONG WINAPI PersistStream_Release(IPersistStream *iface)
|
|
|
|
{
|
|
|
|
Uri *This = impl_from_IPersistStream(iface);
|
|
|
|
return IUri_Release(&This->IUri_iface);
|
|
|
|
}
|
|
|
|
|
|
|
|
static HRESULT WINAPI PersistStream_GetClassID(IPersistStream *iface, CLSID *pClassID)
|
|
|
|
{
|
|
|
|
Uri *This = impl_from_IPersistStream(iface);
|
|
|
|
TRACE("(%p)->(%p)\n", This, pClassID);
|
|
|
|
|
|
|
|
if(!pClassID)
|
|
|
|
return E_INVALIDARG;
|
|
|
|
|
|
|
|
*pClassID = CLSID_CUri;
|
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
static HRESULT WINAPI PersistStream_IsDirty(IPersistStream *iface)
|
|
|
|
{
|
|
|
|
Uri *This = impl_from_IPersistStream(iface);
|
|
|
|
TRACE("(%p)\n", This);
|
|
|
|
return S_FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
struct persist_uri {
|
|
|
|
DWORD size;
|
|
|
|
DWORD unk1[2];
|
|
|
|
DWORD create_flags;
|
|
|
|
DWORD unk2[3];
|
|
|
|
DWORD fields_no;
|
|
|
|
BYTE data[1];
|
|
|
|
};
|
|
|
|
|
|
|
|
static HRESULT WINAPI PersistStream_Load(IPersistStream *iface, IStream *pStm)
|
|
|
|
{
|
|
|
|
Uri *This = impl_from_IPersistStream(iface);
|
|
|
|
struct persist_uri *data;
|
|
|
|
parse_data parse;
|
|
|
|
DWORD size;
|
|
|
|
HRESULT hr;
|
|
|
|
|
|
|
|
TRACE("(%p)->(%p)\n", This, pStm);
|
|
|
|
|
|
|
|
if(This->create_flags)
|
|
|
|
return E_UNEXPECTED;
|
|
|
|
if(!pStm)
|
|
|
|
return E_INVALIDARG;
|
|
|
|
|
|
|
|
hr = IStream_Read(pStm, &size, sizeof(DWORD), NULL);
|
|
|
|
if(FAILED(hr))
|
|
|
|
return hr;
|
|
|
|
data = heap_alloc(size);
|
|
|
|
if(!data)
|
|
|
|
return E_OUTOFMEMORY;
|
|
|
|
hr = IStream_Read(pStm, data->unk1, size-sizeof(DWORD)-2, NULL);
|
|
|
|
if(FAILED(hr)) {
|
|
|
|
heap_free(data);
|
|
|
|
return hr;
|
2010-12-20 21:29:55 +00:00
|
|
|
}
|
|
|
|
|
2013-03-22 14:29:11 +00:00
|
|
|
if(size < sizeof(struct persist_uri)) {
|
|
|
|
heap_free(data);
|
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(*(DWORD*)data->data != Uri_PROPERTY_RAW_URI) {
|
|
|
|
heap_free(data);
|
|
|
|
ERR("Can't find raw_uri\n");
|
|
|
|
return E_UNEXPECTED;
|
|
|
|
}
|
|
|
|
|
|
|
|
This->raw_uri = SysAllocString((WCHAR*)(data->data+sizeof(DWORD)*2));
|
|
|
|
if(!This->raw_uri) {
|
|
|
|
heap_free(data);
|
|
|
|
return E_OUTOFMEMORY;
|
|
|
|
}
|
|
|
|
This->create_flags = data->create_flags;
|
|
|
|
heap_free(data);
|
|
|
|
TRACE("%x %s\n", This->create_flags, debugstr_w(This->raw_uri));
|
|
|
|
|
|
|
|
memset(&parse, 0, sizeof(parse_data));
|
|
|
|
parse.uri = This->raw_uri;
|
|
|
|
if(!parse_uri(&parse, This->create_flags)) {
|
|
|
|
SysFreeString(This->raw_uri);
|
|
|
|
This->create_flags = 0;
|
|
|
|
return E_UNEXPECTED;
|
|
|
|
}
|
|
|
|
|
|
|
|
hr = canonicalize_uri(&parse, This, This->create_flags);
|
|
|
|
if(FAILED(hr)) {
|
|
|
|
SysFreeString(This->raw_uri);
|
|
|
|
This->create_flags = 0;
|
|
|
|
return hr;
|
|
|
|
}
|
|
|
|
|
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline BYTE* persist_stream_add_strprop(Uri *This, BYTE *p, DWORD type, DWORD len, WCHAR *data)
|
|
|
|
{
|
|
|
|
len *= sizeof(WCHAR);
|
|
|
|
*(DWORD*)p = type;
|
|
|
|
p += sizeof(DWORD);
|
|
|
|
*(DWORD*)p = len+sizeof(WCHAR);
|
|
|
|
p += sizeof(DWORD);
|
|
|
|
memcpy(p, data, len);
|
|
|
|
p += len;
|
|
|
|
*(WCHAR*)p = 0;
|
|
|
|
return p+sizeof(WCHAR);
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline void persist_stream_save(Uri *This, IStream *pStm, BOOL marshal, struct persist_uri *data)
|
|
|
|
{
|
|
|
|
BYTE *p = NULL;
|
|
|
|
|
|
|
|
data->create_flags = This->create_flags;
|
|
|
|
|
|
|
|
if(This->create_flags) {
|
|
|
|
data->fields_no = 1;
|
|
|
|
p = persist_stream_add_strprop(This, data->data, Uri_PROPERTY_RAW_URI,
|
|
|
|
SysStringLen(This->raw_uri), This->raw_uri);
|
|
|
|
}
|
|
|
|
if(This->scheme_type!=URL_SCHEME_HTTP && This->scheme_type!=URL_SCHEME_HTTPS
|
|
|
|
&& This->scheme_type!=URL_SCHEME_FTP)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if(This->fragment_len) {
|
|
|
|
data->fields_no++;
|
|
|
|
p = persist_stream_add_strprop(This, p, Uri_PROPERTY_FRAGMENT,
|
|
|
|
This->fragment_len, This->canon_uri+This->fragment_start);
|
|
|
|
}
|
|
|
|
|
|
|
|
if(This->host_len) {
|
|
|
|
data->fields_no++;
|
|
|
|
if(This->host_type == Uri_HOST_IPV6)
|
|
|
|
p = persist_stream_add_strprop(This, p, Uri_PROPERTY_HOST,
|
|
|
|
This->host_len-2, This->canon_uri+This->host_start+1);
|
|
|
|
else
|
|
|
|
p = persist_stream_add_strprop(This, p, Uri_PROPERTY_HOST,
|
|
|
|
This->host_len, This->canon_uri+This->host_start);
|
|
|
|
}
|
|
|
|
|
|
|
|
if(This->userinfo_split > -1) {
|
|
|
|
data->fields_no++;
|
|
|
|
p = persist_stream_add_strprop(This, p, Uri_PROPERTY_PASSWORD,
|
|
|
|
This->userinfo_len-This->userinfo_split-1,
|
|
|
|
This->canon_uri+This->userinfo_start+This->userinfo_split+1);
|
|
|
|
}
|
|
|
|
|
|
|
|
if(This->path_len) {
|
|
|
|
data->fields_no++;
|
|
|
|
p = persist_stream_add_strprop(This, p, Uri_PROPERTY_PATH,
|
|
|
|
This->path_len, This->canon_uri+This->path_start);
|
|
|
|
} else if(marshal) {
|
|
|
|
WCHAR no_path = '/';
|
|
|
|
data->fields_no++;
|
|
|
|
p = persist_stream_add_strprop(This, p, Uri_PROPERTY_PATH, 1, &no_path);
|
|
|
|
}
|
|
|
|
|
|
|
|
if(This->has_port) {
|
|
|
|
data->fields_no++;
|
|
|
|
*(DWORD*)p = Uri_PROPERTY_PORT;
|
|
|
|
p += sizeof(DWORD);
|
|
|
|
*(DWORD*)p = sizeof(DWORD);
|
|
|
|
p += sizeof(DWORD);
|
|
|
|
*(DWORD*)p = This->port;
|
|
|
|
p += sizeof(DWORD);
|
|
|
|
}
|
|
|
|
|
|
|
|
if(This->query_len) {
|
|
|
|
data->fields_no++;
|
|
|
|
p = persist_stream_add_strprop(This, p, Uri_PROPERTY_QUERY,
|
|
|
|
This->query_len, This->canon_uri+This->query_start);
|
|
|
|
}
|
|
|
|
|
|
|
|
if(This->scheme_len) {
|
|
|
|
data->fields_no++;
|
|
|
|
p = persist_stream_add_strprop(This, p, Uri_PROPERTY_SCHEME_NAME,
|
|
|
|
This->scheme_len, This->canon_uri+This->scheme_start);
|
|
|
|
}
|
|
|
|
|
|
|
|
if(This->userinfo_start>-1 && This->userinfo_split!=0) {
|
|
|
|
data->fields_no++;
|
|
|
|
if(This->userinfo_split > -1)
|
|
|
|
p = persist_stream_add_strprop(This, p, Uri_PROPERTY_USER_NAME,
|
|
|
|
This->userinfo_split, This->canon_uri+This->userinfo_start);
|
|
|
|
else
|
|
|
|
p = persist_stream_add_strprop(This, p, Uri_PROPERTY_USER_NAME,
|
|
|
|
This->userinfo_len, This->canon_uri+This->userinfo_start);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static HRESULT WINAPI PersistStream_Save(IPersistStream *iface, IStream *pStm, BOOL fClearDirty)
|
|
|
|
{
|
|
|
|
Uri *This = impl_from_IPersistStream(iface);
|
|
|
|
struct persist_uri *data;
|
|
|
|
ULARGE_INTEGER size;
|
|
|
|
HRESULT hres;
|
|
|
|
|
|
|
|
TRACE("(%p)->(%p %x)\n", This, pStm, fClearDirty);
|
|
|
|
|
|
|
|
if(!pStm)
|
|
|
|
return E_INVALIDARG;
|
|
|
|
|
|
|
|
hres = IPersistStream_GetSizeMax(&This->IPersistStream_iface, &size);
|
|
|
|
if(FAILED(hres))
|
|
|
|
return hres;
|
|
|
|
|
|
|
|
data = heap_alloc_zero(size.u.LowPart);
|
|
|
|
if(!data)
|
|
|
|
return E_OUTOFMEMORY;
|
|
|
|
data->size = size.u.LowPart;
|
|
|
|
persist_stream_save(This, pStm, FALSE, data);
|
|
|
|
|
|
|
|
hres = IStream_Write(pStm, data, data->size-2, NULL);
|
|
|
|
heap_free(data);
|
|
|
|
return hres;
|
|
|
|
}
|
|
|
|
|
|
|
|
static HRESULT WINAPI PersistStream_GetSizeMax(IPersistStream *iface, ULARGE_INTEGER *pcbSize)
|
|
|
|
{
|
|
|
|
Uri *This = impl_from_IPersistStream(iface);
|
|
|
|
TRACE("(%p)->(%p)\n", This, pcbSize);
|
|
|
|
|
|
|
|
if(!pcbSize)
|
|
|
|
return E_INVALIDARG;
|
|
|
|
|
|
|
|
pcbSize->u.LowPart = 2+sizeof(struct persist_uri);
|
|
|
|
pcbSize->u.HighPart = 0;
|
|
|
|
if(This->create_flags)
|
|
|
|
pcbSize->u.LowPart += (SysStringLen(This->raw_uri)+1)*sizeof(WCHAR) + 2*sizeof(DWORD);
|
|
|
|
else /* there's no place for fields no */
|
|
|
|
pcbSize->u.LowPart -= sizeof(DWORD);
|
|
|
|
if(This->scheme_type!=URL_SCHEME_HTTP && This->scheme_type!=URL_SCHEME_HTTPS
|
|
|
|
&& This->scheme_type!=URL_SCHEME_FTP)
|
|
|
|
return S_OK;
|
|
|
|
|
|
|
|
if(This->fragment_len)
|
|
|
|
pcbSize->u.LowPart += (This->fragment_len+1)*sizeof(WCHAR) + 2*sizeof(DWORD);
|
|
|
|
if(This->host_len) {
|
|
|
|
if(This->host_type == Uri_HOST_IPV6)
|
|
|
|
pcbSize->u.LowPart += (This->host_len-1)*sizeof(WCHAR) + 2*sizeof(DWORD);
|
|
|
|
else
|
|
|
|
pcbSize->u.LowPart += (This->host_len+1)*sizeof(WCHAR) + 2*sizeof(DWORD);
|
|
|
|
}
|
|
|
|
if(This->userinfo_split > -1)
|
|
|
|
pcbSize->u.LowPart += (This->userinfo_len-This->userinfo_split)*sizeof(WCHAR) + 2*sizeof(DWORD);
|
|
|
|
if(This->path_len)
|
|
|
|
pcbSize->u.LowPart += (This->path_len+1)*sizeof(WCHAR) + 2*sizeof(DWORD);
|
|
|
|
if(This->has_port)
|
|
|
|
pcbSize->u.LowPart += 3*sizeof(DWORD);
|
|
|
|
if(This->query_len)
|
|
|
|
pcbSize->u.LowPart += (This->query_len+1)*sizeof(WCHAR) + 2*sizeof(DWORD);
|
|
|
|
if(This->scheme_len)
|
|
|
|
pcbSize->u.LowPart += (This->scheme_len+1)*sizeof(WCHAR) + 2*sizeof(DWORD);
|
|
|
|
if(This->userinfo_start>-1 && This->userinfo_split!=0) {
|
|
|
|
if(This->userinfo_split > -1)
|
|
|
|
pcbSize->u.LowPart += (This->userinfo_split+1)*sizeof(WCHAR) + 2*sizeof(DWORD);
|
|
|
|
else
|
|
|
|
pcbSize->u.LowPart += (This->userinfo_len+1)*sizeof(WCHAR) + 2*sizeof(DWORD);
|
|
|
|
}
|
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
static const IPersistStreamVtbl PersistStreamVtbl = {
|
|
|
|
PersistStream_QueryInterface,
|
|
|
|
PersistStream_AddRef,
|
|
|
|
PersistStream_Release,
|
|
|
|
PersistStream_GetClassID,
|
|
|
|
PersistStream_IsDirty,
|
|
|
|
PersistStream_Load,
|
|
|
|
PersistStream_Save,
|
|
|
|
PersistStream_GetSizeMax
|
|
|
|
};
|
|
|
|
|
|
|
|
static inline Uri* impl_from_IMarshal(IMarshal *iface)
|
|
|
|
{
|
|
|
|
return CONTAINING_RECORD(iface, Uri, IMarshal_iface);
|
|
|
|
}
|
|
|
|
|
|
|
|
static HRESULT WINAPI Marshal_QueryInterface(IMarshal *iface, REFIID riid, void **ppvObject)
|
|
|
|
{
|
|
|
|
Uri *This = impl_from_IMarshal(iface);
|
|
|
|
return IUri_QueryInterface(&This->IUri_iface, riid, ppvObject);
|
|
|
|
}
|
|
|
|
|
|
|
|
static ULONG WINAPI Marshal_AddRef(IMarshal *iface)
|
|
|
|
{
|
|
|
|
Uri *This = impl_from_IMarshal(iface);
|
|
|
|
return IUri_AddRef(&This->IUri_iface);
|
|
|
|
}
|
|
|
|
|
|
|
|
static ULONG WINAPI Marshal_Release(IMarshal *iface)
|
|
|
|
{
|
|
|
|
Uri *This = impl_from_IMarshal(iface);
|
|
|
|
return IUri_Release(&This->IUri_iface);
|
|
|
|
}
|
|
|
|
|
|
|
|
static HRESULT WINAPI Marshal_GetUnmarshalClass(IMarshal *iface, REFIID riid, void *pv,
|
|
|
|
DWORD dwDestContext, void *pvDestContext, DWORD mshlflags, CLSID *pCid)
|
|
|
|
{
|
|
|
|
Uri *This = impl_from_IMarshal(iface);
|
|
|
|
TRACE("(%p)->(%s %p %x %p %x %p)\n", This, debugstr_guid(riid), pv,
|
|
|
|
dwDestContext, pvDestContext, mshlflags, pCid);
|
|
|
|
|
|
|
|
if(!pCid || (dwDestContext!=MSHCTX_LOCAL && dwDestContext!=MSHCTX_NOSHAREDMEM
|
|
|
|
&& dwDestContext!=MSHCTX_INPROC))
|
|
|
|
return E_INVALIDARG;
|
|
|
|
|
|
|
|
*pCid = CLSID_CUri;
|
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
struct inproc_marshal_uri {
|
|
|
|
DWORD size;
|
|
|
|
DWORD mshlflags;
|
|
|
|
DWORD unk[4]; /* process identifier? */
|
|
|
|
Uri *uri;
|
|
|
|
};
|
|
|
|
|
|
|
|
static HRESULT WINAPI Marshal_GetMarshalSizeMax(IMarshal *iface, REFIID riid, void *pv,
|
|
|
|
DWORD dwDestContext, void *pvDestContext, DWORD mshlflags, DWORD *pSize)
|
|
|
|
{
|
|
|
|
Uri *This = impl_from_IMarshal(iface);
|
|
|
|
ULARGE_INTEGER size;
|
|
|
|
HRESULT hres;
|
|
|
|
TRACE("(%p)->(%s %p %x %p %x %p)\n", This, debugstr_guid(riid), pv,
|
|
|
|
dwDestContext, pvDestContext, mshlflags, pSize);
|
|
|
|
|
|
|
|
if(!pSize || (dwDestContext!=MSHCTX_LOCAL && dwDestContext!=MSHCTX_NOSHAREDMEM
|
|
|
|
&& dwDestContext!=MSHCTX_INPROC))
|
|
|
|
return E_INVALIDARG;
|
|
|
|
|
|
|
|
if(dwDestContext == MSHCTX_INPROC) {
|
|
|
|
*pSize = sizeof(struct inproc_marshal_uri);
|
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
hres = IPersistStream_GetSizeMax(&This->IPersistStream_iface, &size);
|
|
|
|
if(FAILED(hres))
|
|
|
|
return hres;
|
|
|
|
if(!This->path_len && (This->scheme_type==URL_SCHEME_HTTP
|
|
|
|
|| This->scheme_type==URL_SCHEME_HTTPS
|
|
|
|
|| This->scheme_type==URL_SCHEME_FTP))
|
|
|
|
size.u.LowPart += 3*sizeof(DWORD);
|
|
|
|
*pSize = size.u.LowPart+2*sizeof(DWORD);
|
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
static HRESULT WINAPI Marshal_MarshalInterface(IMarshal *iface, IStream *pStm, REFIID riid,
|
|
|
|
void *pv, DWORD dwDestContext, void *pvDestContext, DWORD mshlflags)
|
|
|
|
{
|
|
|
|
Uri *This = impl_from_IMarshal(iface);
|
|
|
|
DWORD *data;
|
|
|
|
DWORD size;
|
|
|
|
HRESULT hres;
|
|
|
|
|
|
|
|
TRACE("(%p)->(%p %s %p %x %p %x)\n", This, pStm, debugstr_guid(riid), pv,
|
|
|
|
dwDestContext, pvDestContext, mshlflags);
|
|
|
|
|
|
|
|
if(!pStm || mshlflags!=MSHLFLAGS_NORMAL || (dwDestContext!=MSHCTX_LOCAL
|
|
|
|
&& dwDestContext!=MSHCTX_NOSHAREDMEM && dwDestContext!=MSHCTX_INPROC))
|
|
|
|
return E_INVALIDARG;
|
|
|
|
|
|
|
|
if(dwDestContext == MSHCTX_INPROC) {
|
|
|
|
struct inproc_marshal_uri data;
|
|
|
|
|
|
|
|
data.size = sizeof(data);
|
|
|
|
data.mshlflags = MSHCTX_INPROC;
|
|
|
|
data.unk[0] = 0;
|
|
|
|
data.unk[1] = 0;
|
|
|
|
data.unk[2] = 0;
|
|
|
|
data.unk[3] = 0;
|
|
|
|
data.uri = This;
|
|
|
|
|
|
|
|
hres = IStream_Write(pStm, &data, data.size, NULL);
|
|
|
|
if(FAILED(hres))
|
|
|
|
return hres;
|
|
|
|
|
|
|
|
IUri_AddRef(&This->IUri_iface);
|
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
hres = IMarshal_GetMarshalSizeMax(iface, riid, pv, dwDestContext,
|
|
|
|
pvDestContext, mshlflags, &size);
|
|
|
|
if(FAILED(hres))
|
|
|
|
return hres;
|
|
|
|
|
|
|
|
data = heap_alloc_zero(size);
|
|
|
|
if(!data)
|
|
|
|
return E_OUTOFMEMORY;
|
|
|
|
|
|
|
|
data[0] = size;
|
|
|
|
data[1] = dwDestContext;
|
|
|
|
data[2] = size-2*sizeof(DWORD);
|
|
|
|
persist_stream_save(This, pStm, TRUE, (struct persist_uri*)(data+2));
|
|
|
|
|
|
|
|
hres = IStream_Write(pStm, data, data[0]-2, NULL);
|
|
|
|
heap_free(data);
|
|
|
|
return hres;
|
|
|
|
}
|
|
|
|
|
|
|
|
static HRESULT WINAPI Marshal_UnmarshalInterface(IMarshal *iface,
|
|
|
|
IStream *pStm, REFIID riid, void **ppv)
|
|
|
|
{
|
|
|
|
Uri *This = impl_from_IMarshal(iface);
|
|
|
|
DWORD header[2];
|
|
|
|
HRESULT hres;
|
|
|
|
|
|
|
|
TRACE("(%p)->(%p %s %p)\n", This, pStm, debugstr_guid(riid), ppv);
|
|
|
|
|
|
|
|
if(This->create_flags)
|
|
|
|
return E_UNEXPECTED;
|
|
|
|
if(!pStm || !riid || !ppv)
|
|
|
|
return E_INVALIDARG;
|
|
|
|
|
|
|
|
hres = IStream_Read(pStm, header, sizeof(header), NULL);
|
|
|
|
if(FAILED(hres))
|
|
|
|
return hres;
|
|
|
|
|
|
|
|
if(header[1]!=MSHCTX_LOCAL && header[1]!=MSHCTX_NOSHAREDMEM
|
|
|
|
&& header[1]!=MSHCTX_INPROC)
|
|
|
|
return E_UNEXPECTED;
|
|
|
|
|
|
|
|
if(header[1] == MSHCTX_INPROC) {
|
|
|
|
struct inproc_marshal_uri data;
|
|
|
|
parse_data parse;
|
|
|
|
|
|
|
|
hres = IStream_Read(pStm, data.unk, sizeof(data)-2*sizeof(DWORD), NULL);
|
|
|
|
if(FAILED(hres))
|
|
|
|
return hres;
|
|
|
|
|
|
|
|
This->raw_uri = SysAllocString(data.uri->raw_uri);
|
|
|
|
if(!This->raw_uri) {
|
|
|
|
return E_OUTOFMEMORY;
|
|
|
|
}
|
|
|
|
|
|
|
|
memset(&parse, 0, sizeof(parse_data));
|
|
|
|
parse.uri = This->raw_uri;
|
|
|
|
|
|
|
|
if(!parse_uri(&parse, data.uri->create_flags))
|
|
|
|
return E_INVALIDARG;
|
|
|
|
|
|
|
|
hres = canonicalize_uri(&parse, This, data.uri->create_flags);
|
|
|
|
if(FAILED(hres))
|
|
|
|
return hres;
|
|
|
|
|
|
|
|
This->create_flags = data.uri->create_flags;
|
|
|
|
IUri_Release(&data.uri->IUri_iface);
|
|
|
|
|
|
|
|
return IUri_QueryInterface(&This->IUri_iface, riid, ppv);
|
|
|
|
}
|
|
|
|
|
|
|
|
hres = IPersistStream_Load(&This->IPersistStream_iface, pStm);
|
|
|
|
if(FAILED(hres))
|
|
|
|
return hres;
|
|
|
|
|
|
|
|
return IUri_QueryInterface(&This->IUri_iface, riid, ppv);
|
|
|
|
}
|
|
|
|
|
|
|
|
static HRESULT WINAPI Marshal_ReleaseMarshalData(IMarshal *iface, IStream *pStm)
|
|
|
|
{
|
|
|
|
Uri *This = impl_from_IMarshal(iface);
|
|
|
|
LARGE_INTEGER off;
|
|
|
|
DWORD header[2];
|
|
|
|
HRESULT hres;
|
|
|
|
|
|
|
|
TRACE("(%p)->(%p)\n", This, pStm);
|
|
|
|
|
|
|
|
if(!pStm)
|
|
|
|
return E_INVALIDARG;
|
|
|
|
|
|
|
|
hres = IStream_Read(pStm, header, 2*sizeof(DWORD), NULL);
|
|
|
|
if(FAILED(hres))
|
|
|
|
return hres;
|
|
|
|
|
|
|
|
if(header[1] == MSHCTX_INPROC) {
|
|
|
|
struct inproc_marshal_uri data;
|
|
|
|
|
|
|
|
hres = IStream_Read(pStm, data.unk, sizeof(data)-2*sizeof(DWORD), NULL);
|
|
|
|
if(FAILED(hres))
|
|
|
|
return hres;
|
|
|
|
|
|
|
|
IUri_Release(&data.uri->IUri_iface);
|
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
off.u.LowPart = header[0]-sizeof(header)-2;
|
|
|
|
off.u.HighPart = 0;
|
|
|
|
return IStream_Seek(pStm, off, STREAM_SEEK_CUR, NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
static HRESULT WINAPI Marshal_DisconnectObject(IMarshal *iface, DWORD dwReserved)
|
|
|
|
{
|
|
|
|
Uri *This = impl_from_IMarshal(iface);
|
|
|
|
TRACE("(%p)->(%x)\n", This, dwReserved);
|
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
static const IMarshalVtbl MarshalVtbl = {
|
|
|
|
Marshal_QueryInterface,
|
|
|
|
Marshal_AddRef,
|
|
|
|
Marshal_Release,
|
|
|
|
Marshal_GetUnmarshalClass,
|
|
|
|
Marshal_GetMarshalSizeMax,
|
|
|
|
Marshal_MarshalInterface,
|
|
|
|
Marshal_UnmarshalInterface,
|
|
|
|
Marshal_ReleaseMarshalData,
|
|
|
|
Marshal_DisconnectObject
|
|
|
|
};
|
|
|
|
|
|
|
|
HRESULT Uri_Construct(IUnknown *pUnkOuter, LPVOID *ppobj)
|
|
|
|
{
|
|
|
|
Uri *ret = heap_alloc_zero(sizeof(Uri));
|
|
|
|
|
|
|
|
TRACE("(%p %p)\n", pUnkOuter, ppobj);
|
|
|
|
|
|
|
|
*ppobj = ret;
|
|
|
|
if(!ret)
|
|
|
|
return E_OUTOFMEMORY;
|
|
|
|
|
|
|
|
ret->IUri_iface.lpVtbl = &UriVtbl;
|
|
|
|
ret->IUriBuilderFactory_iface.lpVtbl = &UriBuilderFactoryVtbl;
|
|
|
|
ret->IPersistStream_iface.lpVtbl = &PersistStreamVtbl;
|
|
|
|
ret->IMarshal_iface.lpVtbl = &MarshalVtbl;
|
|
|
|
ret->ref = 1;
|
|
|
|
|
|
|
|
*ppobj = &ret->IUri_iface;
|
|
|
|
return S_OK;
|
2010-12-20 21:29:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/***********************************************************************
|
|
|
|
* CreateUri (urlmon.@)
|
|
|
|
*
|
|
|
|
* Creates a new IUri object using the URI represented by pwzURI. This function
|
|
|
|
* parses and validates the components of pwzURI and then canonicalizes the
|
|
|
|
* parsed components.
|
|
|
|
*
|
|
|
|
* PARAMS
|
|
|
|
* pwzURI [I] The URI to parse, validate, and canonicalize.
|
|
|
|
* dwFlags [I] Flags which can affect how the parsing/canonicalization is performed.
|
|
|
|
* dwReserved [I] Reserved (not used).
|
|
|
|
* ppURI [O] The resulting IUri after parsing/canonicalization occurs.
|
|
|
|
*
|
|
|
|
* RETURNS
|
|
|
|
* Success: Returns S_OK. ppURI contains the pointer to the newly allocated IUri.
|
2013-03-22 14:29:11 +00:00
|
|
|
* Failure: E_INVALIDARG if there are invalid flag combinations in dwFlags, or an
|
|
|
|
* invalid parameter, or pwzURI doesn't represent a valid URI.
|
2010-10-09 21:52:25 +00:00
|
|
|
* E_OUTOFMEMORY if any memory allocation fails.
|
|
|
|
*
|
|
|
|
* NOTES
|
|
|
|
* Default flags:
|
|
|
|
* Uri_CREATE_CANONICALIZE, Uri_CREATE_DECODE_EXTRA_INFO, Uri_CREATE_CRACK_UNKNOWN_SCHEMES,
|
|
|
|
* Uri_CREATE_PRE_PROCESS_HTML_URI, Uri_CREATE_NO_IE_SETTINGS.
|
2010-03-04 15:24:17 +00:00
|
|
|
*/
|
|
|
|
HRESULT WINAPI CreateUri(LPCWSTR pwzURI, DWORD dwFlags, DWORD_PTR dwReserved, IUri **ppURI)
|
|
|
|
{
|
2010-10-09 21:52:25 +00:00
|
|
|
const DWORD supported_flags = Uri_CREATE_ALLOW_RELATIVE|Uri_CREATE_ALLOW_IMPLICIT_WILDCARD_SCHEME|
|
|
|
|
Uri_CREATE_ALLOW_IMPLICIT_FILE_SCHEME|Uri_CREATE_NO_CANONICALIZE|Uri_CREATE_CANONICALIZE|
|
|
|
|
Uri_CREATE_DECODE_EXTRA_INFO|Uri_CREATE_NO_DECODE_EXTRA_INFO|Uri_CREATE_CRACK_UNKNOWN_SCHEMES|
|
|
|
|
Uri_CREATE_NO_CRACK_UNKNOWN_SCHEMES|Uri_CREATE_PRE_PROCESS_HTML_URI|Uri_CREATE_NO_PRE_PROCESS_HTML_URI|
|
|
|
|
Uri_CREATE_NO_IE_SETTINGS|Uri_CREATE_NO_ENCODE_FORBIDDEN_CHARACTERS|Uri_CREATE_FILE_USE_DOS_PATH;
|
2010-03-04 15:24:17 +00:00
|
|
|
Uri *ret;
|
Finish the Wine sync. These components are not just rc file changes
atl, comctl32, comdlg32, dwmapi, fusion, gdiplus, jscript, mpr, mshtml, msi, msimtf, msxml3, ole32, oleaut32, riched20, shdocvw, shlwapi, urlmon, usp10, version and windowscodecs
Seems to build and boot. /me hides
svn path=/trunk/; revision=48273
2010-07-26 02:26:04 +00:00
|
|
|
HRESULT hr;
|
|
|
|
parse_data data;
|
2010-03-04 15:24:17 +00:00
|
|
|
|
|
|
|
TRACE("(%s %x %x %p)\n", debugstr_w(pwzURI), dwFlags, (DWORD)dwReserved, ppURI);
|
|
|
|
|
2010-05-30 10:20:31 +00:00
|
|
|
if(!ppURI)
|
|
|
|
return E_INVALIDARG;
|
|
|
|
|
2013-03-22 14:29:11 +00:00
|
|
|
if(!pwzURI) {
|
2010-10-09 21:52:25 +00:00
|
|
|
*ppURI = NULL;
|
|
|
|
return E_INVALIDARG;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Check for invalid flags. */
|
|
|
|
if(has_invalid_flag_combination(dwFlags)) {
|
2010-05-30 10:20:31 +00:00
|
|
|
*ppURI = NULL;
|
|
|
|
return E_INVALIDARG;
|
|
|
|
}
|
|
|
|
|
2010-10-09 21:52:25 +00:00
|
|
|
/* Currently unsupported. */
|
|
|
|
if(dwFlags & ~supported_flags)
|
|
|
|
FIXME("Ignoring unsupported flag(s) %x\n", dwFlags & ~supported_flags);
|
|
|
|
|
2013-03-22 14:29:11 +00:00
|
|
|
hr = Uri_Construct(NULL, (void**)&ret);
|
|
|
|
if(FAILED(hr)) {
|
2010-12-20 21:29:55 +00:00
|
|
|
*ppURI = NULL;
|
2013-03-22 14:29:11 +00:00
|
|
|
return hr;
|
2010-12-20 21:29:55 +00:00
|
|
|
}
|
2010-03-04 15:24:17 +00:00
|
|
|
|
2010-10-09 21:52:25 +00:00
|
|
|
/* Explicitly set the default flags if it doesn't cause a flag conflict. */
|
|
|
|
apply_default_flags(&dwFlags);
|
|
|
|
|
|
|
|
/* Pre process the URI, unless told otherwise. */
|
|
|
|
if(!(dwFlags & Uri_CREATE_NO_PRE_PROCESS_HTML_URI))
|
|
|
|
ret->raw_uri = pre_process_uri(pwzURI);
|
|
|
|
else
|
|
|
|
ret->raw_uri = SysAllocString(pwzURI);
|
|
|
|
|
Finish the Wine sync. These components are not just rc file changes
atl, comctl32, comdlg32, dwmapi, fusion, gdiplus, jscript, mpr, mshtml, msi, msimtf, msxml3, ole32, oleaut32, riched20, shdocvw, shlwapi, urlmon, usp10, version and windowscodecs
Seems to build and boot. /me hides
svn path=/trunk/; revision=48273
2010-07-26 02:26:04 +00:00
|
|
|
if(!ret->raw_uri) {
|
|
|
|
heap_free(ret);
|
|
|
|
return E_OUTOFMEMORY;
|
|
|
|
}
|
|
|
|
|
|
|
|
memset(&data, 0, sizeof(parse_data));
|
|
|
|
data.uri = ret->raw_uri;
|
|
|
|
|
2013-03-22 14:29:11 +00:00
|
|
|
/* Validate and parse the URI into its components. */
|
Finish the Wine sync. These components are not just rc file changes
atl, comctl32, comdlg32, dwmapi, fusion, gdiplus, jscript, mpr, mshtml, msi, msimtf, msxml3, ole32, oleaut32, riched20, shdocvw, shlwapi, urlmon, usp10, version and windowscodecs
Seems to build and boot. /me hides
svn path=/trunk/; revision=48273
2010-07-26 02:26:04 +00:00
|
|
|
if(!parse_uri(&data, dwFlags)) {
|
|
|
|
/* Encountered an unsupported or invalid URI */
|
2010-12-20 21:29:55 +00:00
|
|
|
IUri_Release(&ret->IUri_iface);
|
Finish the Wine sync. These components are not just rc file changes
atl, comctl32, comdlg32, dwmapi, fusion, gdiplus, jscript, mpr, mshtml, msi, msimtf, msxml3, ole32, oleaut32, riched20, shdocvw, shlwapi, urlmon, usp10, version and windowscodecs
Seems to build and boot. /me hides
svn path=/trunk/; revision=48273
2010-07-26 02:26:04 +00:00
|
|
|
*ppURI = NULL;
|
|
|
|
return E_INVALIDARG;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Canonicalize the URI. */
|
|
|
|
hr = canonicalize_uri(&data, ret, dwFlags);
|
|
|
|
if(FAILED(hr)) {
|
2010-12-20 21:29:55 +00:00
|
|
|
IUri_Release(&ret->IUri_iface);
|
Finish the Wine sync. These components are not just rc file changes
atl, comctl32, comdlg32, dwmapi, fusion, gdiplus, jscript, mpr, mshtml, msi, msimtf, msxml3, ole32, oleaut32, riched20, shdocvw, shlwapi, urlmon, usp10, version and windowscodecs
Seems to build and boot. /me hides
svn path=/trunk/; revision=48273
2010-07-26 02:26:04 +00:00
|
|
|
*ppURI = NULL;
|
|
|
|
return hr;
|
|
|
|
}
|
|
|
|
|
2010-10-09 21:52:25 +00:00
|
|
|
ret->create_flags = dwFlags;
|
|
|
|
|
2010-12-20 21:29:55 +00:00
|
|
|
*ppURI = &ret->IUri_iface;
|
2010-03-04 15:24:17 +00:00
|
|
|
return S_OK;
|
|
|
|
}
|
2010-03-21 17:43:25 +00:00
|
|
|
|
2010-10-09 21:52:25 +00:00
|
|
|
/***********************************************************************
|
|
|
|
* CreateUriWithFragment (urlmon.@)
|
|
|
|
*
|
|
|
|
* Creates a new IUri object. This is almost the same as CreateUri, expect that
|
|
|
|
* it allows you to explicitly specify a fragment (pwzFragment) for pwzURI.
|
|
|
|
*
|
|
|
|
* PARAMS
|
|
|
|
* pwzURI [I] The URI to parse and perform canonicalization on.
|
2013-03-22 14:29:11 +00:00
|
|
|
* pwzFragment [I] The explicit fragment string which should be added to pwzURI.
|
2010-10-09 21:52:25 +00:00
|
|
|
* dwFlags [I] The flags which will be passed to CreateUri.
|
|
|
|
* dwReserved [I] Reserved (not used).
|
|
|
|
* ppURI [O] The resulting IUri after parsing/canonicalization.
|
|
|
|
*
|
|
|
|
* RETURNS
|
|
|
|
* Success: S_OK. ppURI contains the pointer to the newly allocated IUri.
|
|
|
|
* Failure: E_INVALIDARG if pwzURI already contains a fragment and pwzFragment
|
|
|
|
* isn't NULL. Will also return E_INVALIDARG for the same reasons as
|
2013-03-22 14:29:11 +00:00
|
|
|
* CreateUri will. E_OUTOFMEMORY if any allocation fails.
|
2010-10-09 21:52:25 +00:00
|
|
|
*/
|
|
|
|
HRESULT WINAPI CreateUriWithFragment(LPCWSTR pwzURI, LPCWSTR pwzFragment, DWORD dwFlags,
|
|
|
|
DWORD_PTR dwReserved, IUri **ppURI)
|
|
|
|
{
|
|
|
|
HRESULT hres;
|
|
|
|
TRACE("(%s %s %x %x %p)\n", debugstr_w(pwzURI), debugstr_w(pwzFragment), dwFlags, (DWORD)dwReserved, ppURI);
|
|
|
|
|
|
|
|
if(!ppURI)
|
|
|
|
return E_INVALIDARG;
|
|
|
|
|
|
|
|
if(!pwzURI) {
|
|
|
|
*ppURI = NULL;
|
|
|
|
return E_INVALIDARG;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Check if a fragment should be appended to the URI string. */
|
|
|
|
if(pwzFragment) {
|
|
|
|
WCHAR *uriW;
|
|
|
|
DWORD uri_len, frag_len;
|
|
|
|
BOOL add_pound;
|
|
|
|
|
|
|
|
/* Check if the original URI already has a fragment component. */
|
|
|
|
if(StrChrW(pwzURI, '#')) {
|
|
|
|
*ppURI = NULL;
|
|
|
|
return E_INVALIDARG;
|
|
|
|
}
|
|
|
|
|
|
|
|
uri_len = lstrlenW(pwzURI);
|
|
|
|
frag_len = lstrlenW(pwzFragment);
|
|
|
|
|
|
|
|
/* If the fragment doesn't start with a '#', one will be added. */
|
|
|
|
add_pound = *pwzFragment != '#';
|
|
|
|
|
|
|
|
if(add_pound)
|
|
|
|
uriW = heap_alloc((uri_len+frag_len+2)*sizeof(WCHAR));
|
|
|
|
else
|
|
|
|
uriW = heap_alloc((uri_len+frag_len+1)*sizeof(WCHAR));
|
|
|
|
|
|
|
|
if(!uriW)
|
|
|
|
return E_OUTOFMEMORY;
|
|
|
|
|
|
|
|
memcpy(uriW, pwzURI, uri_len*sizeof(WCHAR));
|
|
|
|
if(add_pound)
|
|
|
|
uriW[uri_len++] = '#';
|
|
|
|
memcpy(uriW+uri_len, pwzFragment, (frag_len+1)*sizeof(WCHAR));
|
|
|
|
|
|
|
|
hres = CreateUri(uriW, dwFlags, 0, ppURI);
|
|
|
|
|
|
|
|
heap_free(uriW);
|
|
|
|
} else
|
|
|
|
/* A fragment string wasn't specified, so just forward the call. */
|
|
|
|
hres = CreateUri(pwzURI, dwFlags, 0, ppURI);
|
|
|
|
|
|
|
|
return hres;
|
|
|
|
}
|
|
|
|
|
2010-12-20 21:29:55 +00:00
|
|
|
static HRESULT build_uri(const UriBuilder *builder, IUri **uri, DWORD create_flags,
|
|
|
|
DWORD use_orig_flags, DWORD encoding_mask)
|
|
|
|
{
|
|
|
|
HRESULT hr;
|
|
|
|
parse_data data;
|
|
|
|
Uri *ret;
|
|
|
|
|
|
|
|
if(!uri)
|
|
|
|
return E_POINTER;
|
|
|
|
|
|
|
|
if(encoding_mask && (!builder->uri || builder->modified_props)) {
|
|
|
|
*uri = NULL;
|
|
|
|
return E_NOTIMPL;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Decide what flags should be used when creating the Uri. */
|
|
|
|
if((use_orig_flags & UriBuilder_USE_ORIGINAL_FLAGS) && builder->uri)
|
|
|
|
create_flags = builder->uri->create_flags;
|
|
|
|
else {
|
|
|
|
if(has_invalid_flag_combination(create_flags)) {
|
|
|
|
*uri = NULL;
|
|
|
|
return E_INVALIDARG;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Set the default flags if they don't cause a conflict. */
|
|
|
|
apply_default_flags(&create_flags);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Return the base IUri if no changes have been made and the create_flags match. */
|
|
|
|
if(builder->uri && !builder->modified_props && builder->uri->create_flags == create_flags) {
|
|
|
|
*uri = &builder->uri->IUri_iface;
|
|
|
|
IUri_AddRef(*uri);
|
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
hr = validate_components(builder, &data, create_flags);
|
|
|
|
if(FAILED(hr)) {
|
|
|
|
*uri = NULL;
|
|
|
|
return hr;
|
|
|
|
}
|
|
|
|
|
2013-03-22 14:29:11 +00:00
|
|
|
hr = Uri_Construct(NULL, (void**)&ret);
|
|
|
|
if(FAILED(hr)) {
|
2010-12-20 21:29:55 +00:00
|
|
|
*uri = NULL;
|
2013-03-22 14:29:11 +00:00
|
|
|
return hr;
|
2010-12-20 21:29:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
hr = generate_uri(builder, &data, ret, create_flags);
|
|
|
|
if(FAILED(hr)) {
|
|
|
|
IUri_Release(&ret->IUri_iface);
|
|
|
|
*uri = NULL;
|
|
|
|
return hr;
|
|
|
|
}
|
|
|
|
|
|
|
|
*uri = &ret->IUri_iface;
|
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline UriBuilder* impl_from_IUriBuilder(IUriBuilder *iface)
|
|
|
|
{
|
|
|
|
return CONTAINING_RECORD(iface, UriBuilder, IUriBuilder_iface);
|
|
|
|
}
|
2010-03-21 17:43:25 +00:00
|
|
|
|
|
|
|
static HRESULT WINAPI UriBuilder_QueryInterface(IUriBuilder *iface, REFIID riid, void **ppv)
|
|
|
|
{
|
2010-12-20 21:29:55 +00:00
|
|
|
UriBuilder *This = impl_from_IUriBuilder(iface);
|
2010-03-21 17:43:25 +00:00
|
|
|
|
|
|
|
if(IsEqualGUID(&IID_IUnknown, riid)) {
|
|
|
|
TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv);
|
2010-12-20 21:29:55 +00:00
|
|
|
*ppv = &This->IUriBuilder_iface;
|
2010-03-21 17:43:25 +00:00
|
|
|
}else if(IsEqualGUID(&IID_IUriBuilder, riid)) {
|
2010-12-20 21:29:55 +00:00
|
|
|
TRACE("(%p)->(IID_IUriBuilder %p)\n", This, ppv);
|
|
|
|
*ppv = &This->IUriBuilder_iface;
|
2010-03-21 17:43:25 +00:00
|
|
|
}else {
|
|
|
|
TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppv);
|
|
|
|
*ppv = NULL;
|
|
|
|
return E_NOINTERFACE;
|
|
|
|
}
|
|
|
|
|
|
|
|
IUnknown_AddRef((IUnknown*)*ppv);
|
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
static ULONG WINAPI UriBuilder_AddRef(IUriBuilder *iface)
|
|
|
|
{
|
2010-12-20 21:29:55 +00:00
|
|
|
UriBuilder *This = impl_from_IUriBuilder(iface);
|
2010-03-21 17:43:25 +00:00
|
|
|
LONG ref = InterlockedIncrement(&This->ref);
|
|
|
|
|
|
|
|
TRACE("(%p) ref=%d\n", This, ref);
|
|
|
|
|
|
|
|
return ref;
|
|
|
|
}
|
|
|
|
|
|
|
|
static ULONG WINAPI UriBuilder_Release(IUriBuilder *iface)
|
|
|
|
{
|
2010-12-20 21:29:55 +00:00
|
|
|
UriBuilder *This = impl_from_IUriBuilder(iface);
|
2010-03-21 17:43:25 +00:00
|
|
|
LONG ref = InterlockedDecrement(&This->ref);
|
|
|
|
|
|
|
|
TRACE("(%p) ref=%d\n", This, ref);
|
|
|
|
|
2010-10-09 21:52:25 +00:00
|
|
|
if(!ref) {
|
2010-12-20 21:29:55 +00:00
|
|
|
if(This->uri) IUri_Release(&This->uri->IUri_iface);
|
2010-10-09 21:52:25 +00:00
|
|
|
heap_free(This->fragment);
|
|
|
|
heap_free(This->host);
|
|
|
|
heap_free(This->password);
|
|
|
|
heap_free(This->path);
|
|
|
|
heap_free(This->query);
|
|
|
|
heap_free(This->scheme);
|
|
|
|
heap_free(This->username);
|
2010-03-21 17:43:25 +00:00
|
|
|
heap_free(This);
|
2010-10-09 21:52:25 +00:00
|
|
|
}
|
2010-03-21 17:43:25 +00:00
|
|
|
|
|
|
|
return ref;
|
|
|
|
}
|
|
|
|
|
|
|
|
static HRESULT WINAPI UriBuilder_CreateUriSimple(IUriBuilder *iface,
|
|
|
|
DWORD dwAllowEncodingPropertyMask,
|
|
|
|
DWORD_PTR dwReserved,
|
|
|
|
IUri **ppIUri)
|
|
|
|
{
|
2010-12-20 21:29:55 +00:00
|
|
|
UriBuilder *This = impl_from_IUriBuilder(iface);
|
2010-10-09 21:52:25 +00:00
|
|
|
HRESULT hr;
|
|
|
|
TRACE("(%p)->(%d %d %p)\n", This, dwAllowEncodingPropertyMask, (DWORD)dwReserved, ppIUri);
|
|
|
|
|
|
|
|
hr = build_uri(This, ppIUri, 0, UriBuilder_USE_ORIGINAL_FLAGS, dwAllowEncodingPropertyMask);
|
|
|
|
if(hr == E_NOTIMPL)
|
|
|
|
FIXME("(%p)->(%d %d %p)\n", This, dwAllowEncodingPropertyMask, (DWORD)dwReserved, ppIUri);
|
|
|
|
return hr;
|
2010-03-21 17:43:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static HRESULT WINAPI UriBuilder_CreateUri(IUriBuilder *iface,
|
|
|
|
DWORD dwCreateFlags,
|
|
|
|
DWORD dwAllowEncodingPropertyMask,
|
|
|
|
DWORD_PTR dwReserved,
|
|
|
|
IUri **ppIUri)
|
|
|
|
{
|
2010-12-20 21:29:55 +00:00
|
|
|
UriBuilder *This = impl_from_IUriBuilder(iface);
|
2010-10-09 21:52:25 +00:00
|
|
|
HRESULT hr;
|
|
|
|
TRACE("(%p)->(0x%08x %d %d %p)\n", This, dwCreateFlags, dwAllowEncodingPropertyMask, (DWORD)dwReserved, ppIUri);
|
|
|
|
|
|
|
|
if(dwCreateFlags == -1)
|
|
|
|
hr = build_uri(This, ppIUri, 0, UriBuilder_USE_ORIGINAL_FLAGS, dwAllowEncodingPropertyMask);
|
|
|
|
else
|
|
|
|
hr = build_uri(This, ppIUri, dwCreateFlags, 0, dwAllowEncodingPropertyMask);
|
|
|
|
|
|
|
|
if(hr == E_NOTIMPL)
|
|
|
|
FIXME("(%p)->(0x%08x %d %d %p)\n", This, dwCreateFlags, dwAllowEncodingPropertyMask, (DWORD)dwReserved, ppIUri);
|
|
|
|
return hr;
|
2010-03-21 17:43:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static HRESULT WINAPI UriBuilder_CreateUriWithFlags(IUriBuilder *iface,
|
|
|
|
DWORD dwCreateFlags,
|
|
|
|
DWORD dwUriBuilderFlags,
|
|
|
|
DWORD dwAllowEncodingPropertyMask,
|
|
|
|
DWORD_PTR dwReserved,
|
|
|
|
IUri **ppIUri)
|
|
|
|
{
|
2010-12-20 21:29:55 +00:00
|
|
|
UriBuilder *This = impl_from_IUriBuilder(iface);
|
2010-10-09 21:52:25 +00:00
|
|
|
HRESULT hr;
|
|
|
|
TRACE("(%p)->(0x%08x 0x%08x %d %d %p)\n", This, dwCreateFlags, dwUriBuilderFlags,
|
2010-03-21 17:43:25 +00:00
|
|
|
dwAllowEncodingPropertyMask, (DWORD)dwReserved, ppIUri);
|
2010-10-09 21:52:25 +00:00
|
|
|
|
|
|
|
hr = build_uri(This, ppIUri, dwCreateFlags, dwUriBuilderFlags, dwAllowEncodingPropertyMask);
|
|
|
|
if(hr == E_NOTIMPL)
|
|
|
|
FIXME("(%p)->(0x%08x 0x%08x %d %d %p)\n", This, dwCreateFlags, dwUriBuilderFlags,
|
|
|
|
dwAllowEncodingPropertyMask, (DWORD)dwReserved, ppIUri);
|
|
|
|
return hr;
|
2010-03-21 17:43:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static HRESULT WINAPI UriBuilder_GetIUri(IUriBuilder *iface, IUri **ppIUri)
|
|
|
|
{
|
2010-12-20 21:29:55 +00:00
|
|
|
UriBuilder *This = impl_from_IUriBuilder(iface);
|
2010-10-09 21:52:25 +00:00
|
|
|
TRACE("(%p)->(%p)\n", This, ppIUri);
|
|
|
|
|
|
|
|
if(!ppIUri)
|
|
|
|
return E_POINTER;
|
|
|
|
|
|
|
|
if(This->uri) {
|
2010-12-20 21:29:55 +00:00
|
|
|
IUri *uri = &This->uri->IUri_iface;
|
2010-10-09 21:52:25 +00:00
|
|
|
IUri_AddRef(uri);
|
|
|
|
*ppIUri = uri;
|
|
|
|
} else
|
|
|
|
*ppIUri = NULL;
|
|
|
|
|
|
|
|
return S_OK;
|
2010-03-21 17:43:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static HRESULT WINAPI UriBuilder_SetIUri(IUriBuilder *iface, IUri *pIUri)
|
|
|
|
{
|
2010-12-20 21:29:55 +00:00
|
|
|
UriBuilder *This = impl_from_IUriBuilder(iface);
|
2010-10-09 21:52:25 +00:00
|
|
|
TRACE("(%p)->(%p)\n", This, pIUri);
|
|
|
|
|
|
|
|
if(pIUri) {
|
|
|
|
Uri *uri;
|
|
|
|
|
|
|
|
if((uri = get_uri_obj(pIUri))) {
|
2014-04-23 17:35:17 +00:00
|
|
|
/* Only reset the builder if its Uri isn't the same as
|
2010-10-09 21:52:25 +00:00
|
|
|
* the Uri passed to the function.
|
|
|
|
*/
|
|
|
|
if(This->uri != uri) {
|
|
|
|
reset_builder(This);
|
|
|
|
|
|
|
|
This->uri = uri;
|
|
|
|
if(uri->has_port)
|
|
|
|
This->port = uri->port;
|
|
|
|
|
|
|
|
IUri_AddRef(pIUri);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
FIXME("(%p)->(%p) Unknown IUri types not supported yet.\n", This, pIUri);
|
|
|
|
return E_NOTIMPL;
|
|
|
|
}
|
|
|
|
} else if(This->uri)
|
2014-04-23 17:35:17 +00:00
|
|
|
/* Only reset the builder if its Uri isn't NULL. */
|
2010-10-09 21:52:25 +00:00
|
|
|
reset_builder(This);
|
|
|
|
|
|
|
|
return S_OK;
|
2010-03-21 17:43:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static HRESULT WINAPI UriBuilder_GetFragment(IUriBuilder *iface, DWORD *pcchFragment, LPCWSTR *ppwzFragment)
|
|
|
|
{
|
2010-12-20 21:29:55 +00:00
|
|
|
UriBuilder *This = impl_from_IUriBuilder(iface);
|
2010-10-09 21:52:25 +00:00
|
|
|
TRACE("(%p)->(%p %p)\n", This, pcchFragment, ppwzFragment);
|
|
|
|
|
|
|
|
if(!This->uri || This->uri->fragment_start == -1 || This->modified_props & Uri_HAS_FRAGMENT)
|
|
|
|
return get_builder_component(&This->fragment, &This->fragment_len, NULL, 0, ppwzFragment, pcchFragment);
|
|
|
|
else
|
|
|
|
return get_builder_component(&This->fragment, &This->fragment_len, This->uri->canon_uri+This->uri->fragment_start,
|
|
|
|
This->uri->fragment_len, ppwzFragment, pcchFragment);
|
2010-03-21 17:43:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static HRESULT WINAPI UriBuilder_GetHost(IUriBuilder *iface, DWORD *pcchHost, LPCWSTR *ppwzHost)
|
|
|
|
{
|
2010-12-20 21:29:55 +00:00
|
|
|
UriBuilder *This = impl_from_IUriBuilder(iface);
|
2010-10-09 21:52:25 +00:00
|
|
|
TRACE("(%p)->(%p %p)\n", This, pcchHost, ppwzHost);
|
|
|
|
|
|
|
|
if(!This->uri || This->uri->host_start == -1 || This->modified_props & Uri_HAS_HOST)
|
|
|
|
return get_builder_component(&This->host, &This->host_len, NULL, 0, ppwzHost, pcchHost);
|
|
|
|
else {
|
|
|
|
if(This->uri->host_type == Uri_HOST_IPV6)
|
|
|
|
/* Don't include the '[' and ']' around the address. */
|
|
|
|
return get_builder_component(&This->host, &This->host_len, This->uri->canon_uri+This->uri->host_start+1,
|
|
|
|
This->uri->host_len-2, ppwzHost, pcchHost);
|
|
|
|
else
|
|
|
|
return get_builder_component(&This->host, &This->host_len, This->uri->canon_uri+This->uri->host_start,
|
|
|
|
This->uri->host_len, ppwzHost, pcchHost);
|
|
|
|
}
|
2010-03-21 17:43:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static HRESULT WINAPI UriBuilder_GetPassword(IUriBuilder *iface, DWORD *pcchPassword, LPCWSTR *ppwzPassword)
|
|
|
|
{
|
2010-12-20 21:29:55 +00:00
|
|
|
UriBuilder *This = impl_from_IUriBuilder(iface);
|
2010-10-09 21:52:25 +00:00
|
|
|
TRACE("(%p)->(%p %p)\n", This, pcchPassword, ppwzPassword);
|
|
|
|
|
|
|
|
if(!This->uri || This->uri->userinfo_split == -1 || This->modified_props & Uri_HAS_PASSWORD)
|
|
|
|
return get_builder_component(&This->password, &This->password_len, NULL, 0, ppwzPassword, pcchPassword);
|
|
|
|
else {
|
|
|
|
const WCHAR *start = This->uri->canon_uri+This->uri->userinfo_start+This->uri->userinfo_split+1;
|
|
|
|
DWORD len = This->uri->userinfo_len-This->uri->userinfo_split-1;
|
|
|
|
return get_builder_component(&This->password, &This->password_len, start, len, ppwzPassword, pcchPassword);
|
|
|
|
}
|
2010-03-21 17:43:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static HRESULT WINAPI UriBuilder_GetPath(IUriBuilder *iface, DWORD *pcchPath, LPCWSTR *ppwzPath)
|
|
|
|
{
|
2010-12-20 21:29:55 +00:00
|
|
|
UriBuilder *This = impl_from_IUriBuilder(iface);
|
2010-10-09 21:52:25 +00:00
|
|
|
TRACE("(%p)->(%p %p)\n", This, pcchPath, ppwzPath);
|
|
|
|
|
|
|
|
if(!This->uri || This->uri->path_start == -1 || This->modified_props & Uri_HAS_PATH)
|
|
|
|
return get_builder_component(&This->path, &This->path_len, NULL, 0, ppwzPath, pcchPath);
|
|
|
|
else
|
|
|
|
return get_builder_component(&This->path, &This->path_len, This->uri->canon_uri+This->uri->path_start,
|
|
|
|
This->uri->path_len, ppwzPath, pcchPath);
|
2010-03-21 17:43:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static HRESULT WINAPI UriBuilder_GetPort(IUriBuilder *iface, BOOL *pfHasPort, DWORD *pdwPort)
|
|
|
|
{
|
2010-12-20 21:29:55 +00:00
|
|
|
UriBuilder *This = impl_from_IUriBuilder(iface);
|
2010-10-09 21:52:25 +00:00
|
|
|
TRACE("(%p)->(%p %p)\n", This, pfHasPort, pdwPort);
|
|
|
|
|
|
|
|
if(!pfHasPort) {
|
|
|
|
if(pdwPort)
|
|
|
|
*pdwPort = 0;
|
|
|
|
return E_POINTER;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(!pdwPort) {
|
|
|
|
*pfHasPort = FALSE;
|
|
|
|
return E_POINTER;
|
|
|
|
}
|
|
|
|
|
|
|
|
*pfHasPort = This->has_port;
|
|
|
|
*pdwPort = This->port;
|
|
|
|
return S_OK;
|
2010-03-21 17:43:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static HRESULT WINAPI UriBuilder_GetQuery(IUriBuilder *iface, DWORD *pcchQuery, LPCWSTR *ppwzQuery)
|
|
|
|
{
|
2010-12-20 21:29:55 +00:00
|
|
|
UriBuilder *This = impl_from_IUriBuilder(iface);
|
2010-10-09 21:52:25 +00:00
|
|
|
TRACE("(%p)->(%p %p)\n", This, pcchQuery, ppwzQuery);
|
|
|
|
|
|
|
|
if(!This->uri || This->uri->query_start == -1 || This->modified_props & Uri_HAS_QUERY)
|
|
|
|
return get_builder_component(&This->query, &This->query_len, NULL, 0, ppwzQuery, pcchQuery);
|
|
|
|
else
|
|
|
|
return get_builder_component(&This->query, &This->query_len, This->uri->canon_uri+This->uri->query_start,
|
|
|
|
This->uri->query_len, ppwzQuery, pcchQuery);
|
2010-03-21 17:43:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static HRESULT WINAPI UriBuilder_GetSchemeName(IUriBuilder *iface, DWORD *pcchSchemeName, LPCWSTR *ppwzSchemeName)
|
|
|
|
{
|
2010-12-20 21:29:55 +00:00
|
|
|
UriBuilder *This = impl_from_IUriBuilder(iface);
|
2010-10-09 21:52:25 +00:00
|
|
|
TRACE("(%p)->(%p %p)\n", This, pcchSchemeName, ppwzSchemeName);
|
|
|
|
|
|
|
|
if(!This->uri || This->uri->scheme_start == -1 || This->modified_props & Uri_HAS_SCHEME_NAME)
|
|
|
|
return get_builder_component(&This->scheme, &This->scheme_len, NULL, 0, ppwzSchemeName, pcchSchemeName);
|
|
|
|
else
|
|
|
|
return get_builder_component(&This->scheme, &This->scheme_len, This->uri->canon_uri+This->uri->scheme_start,
|
|
|
|
This->uri->scheme_len, ppwzSchemeName, pcchSchemeName);
|
2010-03-21 17:43:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static HRESULT WINAPI UriBuilder_GetUserName(IUriBuilder *iface, DWORD *pcchUserName, LPCWSTR *ppwzUserName)
|
|
|
|
{
|
2010-12-20 21:29:55 +00:00
|
|
|
UriBuilder *This = impl_from_IUriBuilder(iface);
|
2010-10-09 21:52:25 +00:00
|
|
|
TRACE("(%p)->(%p %p)\n", This, pcchUserName, ppwzUserName);
|
|
|
|
|
|
|
|
if(!This->uri || This->uri->userinfo_start == -1 || This->uri->userinfo_split == 0 ||
|
|
|
|
This->modified_props & Uri_HAS_USER_NAME)
|
|
|
|
return get_builder_component(&This->username, &This->username_len, NULL, 0, ppwzUserName, pcchUserName);
|
|
|
|
else {
|
|
|
|
const WCHAR *start = This->uri->canon_uri+This->uri->userinfo_start;
|
|
|
|
|
|
|
|
/* Check if there's a password in the userinfo section. */
|
|
|
|
if(This->uri->userinfo_split > -1)
|
|
|
|
/* Don't include the password. */
|
|
|
|
return get_builder_component(&This->username, &This->username_len, start,
|
|
|
|
This->uri->userinfo_split, ppwzUserName, pcchUserName);
|
|
|
|
else
|
|
|
|
return get_builder_component(&This->username, &This->username_len, start,
|
|
|
|
This->uri->userinfo_len, ppwzUserName, pcchUserName);
|
|
|
|
}
|
2010-03-21 17:43:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static HRESULT WINAPI UriBuilder_SetFragment(IUriBuilder *iface, LPCWSTR pwzNewValue)
|
|
|
|
{
|
2010-12-20 21:29:55 +00:00
|
|
|
UriBuilder *This = impl_from_IUriBuilder(iface);
|
2010-10-09 21:52:25 +00:00
|
|
|
TRACE("(%p)->(%s)\n", This, debugstr_w(pwzNewValue));
|
|
|
|
return set_builder_component(&This->fragment, &This->fragment_len, pwzNewValue, '#',
|
|
|
|
&This->modified_props, Uri_HAS_FRAGMENT);
|
2010-03-21 17:43:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static HRESULT WINAPI UriBuilder_SetHost(IUriBuilder *iface, LPCWSTR pwzNewValue)
|
|
|
|
{
|
2010-12-20 21:29:55 +00:00
|
|
|
UriBuilder *This = impl_from_IUriBuilder(iface);
|
2010-10-09 21:52:25 +00:00
|
|
|
TRACE("(%p)->(%s)\n", This, debugstr_w(pwzNewValue));
|
|
|
|
|
|
|
|
/* Host name can't be set to NULL. */
|
|
|
|
if(!pwzNewValue)
|
|
|
|
return E_INVALIDARG;
|
|
|
|
|
|
|
|
return set_builder_component(&This->host, &This->host_len, pwzNewValue, 0,
|
|
|
|
&This->modified_props, Uri_HAS_HOST);
|
2010-03-21 17:43:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static HRESULT WINAPI UriBuilder_SetPassword(IUriBuilder *iface, LPCWSTR pwzNewValue)
|
|
|
|
{
|
2010-12-20 21:29:55 +00:00
|
|
|
UriBuilder *This = impl_from_IUriBuilder(iface);
|
2010-10-09 21:52:25 +00:00
|
|
|
TRACE("(%p)->(%s)\n", This, debugstr_w(pwzNewValue));
|
|
|
|
return set_builder_component(&This->password, &This->password_len, pwzNewValue, 0,
|
|
|
|
&This->modified_props, Uri_HAS_PASSWORD);
|
2010-03-21 17:43:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static HRESULT WINAPI UriBuilder_SetPath(IUriBuilder *iface, LPCWSTR pwzNewValue)
|
|
|
|
{
|
2010-12-20 21:29:55 +00:00
|
|
|
UriBuilder *This = impl_from_IUriBuilder(iface);
|
2010-10-09 21:52:25 +00:00
|
|
|
TRACE("(%p)->(%s)\n", This, debugstr_w(pwzNewValue));
|
|
|
|
return set_builder_component(&This->path, &This->path_len, pwzNewValue, 0,
|
|
|
|
&This->modified_props, Uri_HAS_PATH);
|
2010-03-21 17:43:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static HRESULT WINAPI UriBuilder_SetPort(IUriBuilder *iface, BOOL fHasPort, DWORD dwNewValue)
|
|
|
|
{
|
2010-12-20 21:29:55 +00:00
|
|
|
UriBuilder *This = impl_from_IUriBuilder(iface);
|
2010-10-09 21:52:25 +00:00
|
|
|
TRACE("(%p)->(%d %d)\n", This, fHasPort, dwNewValue);
|
|
|
|
|
|
|
|
This->has_port = fHasPort;
|
|
|
|
This->port = dwNewValue;
|
|
|
|
This->modified_props |= Uri_HAS_PORT;
|
|
|
|
return S_OK;
|
2010-03-21 17:43:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static HRESULT WINAPI UriBuilder_SetQuery(IUriBuilder *iface, LPCWSTR pwzNewValue)
|
|
|
|
{
|
2010-12-20 21:29:55 +00:00
|
|
|
UriBuilder *This = impl_from_IUriBuilder(iface);
|
2010-10-09 21:52:25 +00:00
|
|
|
TRACE("(%p)->(%s)\n", This, debugstr_w(pwzNewValue));
|
|
|
|
return set_builder_component(&This->query, &This->query_len, pwzNewValue, '?',
|
|
|
|
&This->modified_props, Uri_HAS_QUERY);
|
2010-03-21 17:43:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static HRESULT WINAPI UriBuilder_SetSchemeName(IUriBuilder *iface, LPCWSTR pwzNewValue)
|
|
|
|
{
|
2010-12-20 21:29:55 +00:00
|
|
|
UriBuilder *This = impl_from_IUriBuilder(iface);
|
2010-10-09 21:52:25 +00:00
|
|
|
TRACE("(%p)->(%s)\n", This, debugstr_w(pwzNewValue));
|
|
|
|
|
|
|
|
/* Only set the scheme name if it's not NULL or empty. */
|
|
|
|
if(!pwzNewValue || !*pwzNewValue)
|
|
|
|
return E_INVALIDARG;
|
|
|
|
|
|
|
|
return set_builder_component(&This->scheme, &This->scheme_len, pwzNewValue, 0,
|
|
|
|
&This->modified_props, Uri_HAS_SCHEME_NAME);
|
2010-03-21 17:43:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static HRESULT WINAPI UriBuilder_SetUserName(IUriBuilder *iface, LPCWSTR pwzNewValue)
|
|
|
|
{
|
2010-12-20 21:29:55 +00:00
|
|
|
UriBuilder *This = impl_from_IUriBuilder(iface);
|
2010-10-09 21:52:25 +00:00
|
|
|
TRACE("(%p)->(%s)\n", This, debugstr_w(pwzNewValue));
|
|
|
|
return set_builder_component(&This->username, &This->username_len, pwzNewValue, 0,
|
|
|
|
&This->modified_props, Uri_HAS_USER_NAME);
|
2010-03-21 17:43:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static HRESULT WINAPI UriBuilder_RemoveProperties(IUriBuilder *iface, DWORD dwPropertyMask)
|
|
|
|
{
|
2010-10-09 21:52:25 +00:00
|
|
|
const DWORD accepted_flags = Uri_HAS_AUTHORITY|Uri_HAS_DOMAIN|Uri_HAS_EXTENSION|Uri_HAS_FRAGMENT|Uri_HAS_HOST|
|
|
|
|
Uri_HAS_PASSWORD|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_QUERY|
|
|
|
|
Uri_HAS_USER_INFO|Uri_HAS_USER_NAME;
|
|
|
|
|
2010-12-20 21:29:55 +00:00
|
|
|
UriBuilder *This = impl_from_IUriBuilder(iface);
|
2010-10-09 21:52:25 +00:00
|
|
|
TRACE("(%p)->(0x%08x)\n", This, dwPropertyMask);
|
|
|
|
|
|
|
|
if(dwPropertyMask & ~accepted_flags)
|
|
|
|
return E_INVALIDARG;
|
|
|
|
|
|
|
|
if(dwPropertyMask & Uri_HAS_FRAGMENT)
|
|
|
|
UriBuilder_SetFragment(iface, NULL);
|
|
|
|
|
|
|
|
/* Even though you can't set the host name to NULL or an
|
|
|
|
* empty string, you can still remove it... for some reason.
|
|
|
|
*/
|
|
|
|
if(dwPropertyMask & Uri_HAS_HOST)
|
|
|
|
set_builder_component(&This->host, &This->host_len, NULL, 0,
|
|
|
|
&This->modified_props, Uri_HAS_HOST);
|
|
|
|
|
|
|
|
if(dwPropertyMask & Uri_HAS_PASSWORD)
|
|
|
|
UriBuilder_SetPassword(iface, NULL);
|
|
|
|
|
|
|
|
if(dwPropertyMask & Uri_HAS_PATH)
|
|
|
|
UriBuilder_SetPath(iface, NULL);
|
|
|
|
|
|
|
|
if(dwPropertyMask & Uri_HAS_PORT)
|
|
|
|
UriBuilder_SetPort(iface, FALSE, 0);
|
|
|
|
|
|
|
|
if(dwPropertyMask & Uri_HAS_QUERY)
|
|
|
|
UriBuilder_SetQuery(iface, NULL);
|
|
|
|
|
|
|
|
if(dwPropertyMask & Uri_HAS_USER_NAME)
|
|
|
|
UriBuilder_SetUserName(iface, NULL);
|
|
|
|
|
|
|
|
return S_OK;
|
2010-03-21 17:43:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static HRESULT WINAPI UriBuilder_HasBeenModified(IUriBuilder *iface, BOOL *pfModified)
|
|
|
|
{
|
2010-12-20 21:29:55 +00:00
|
|
|
UriBuilder *This = impl_from_IUriBuilder(iface);
|
2010-10-09 21:52:25 +00:00
|
|
|
TRACE("(%p)->(%p)\n", This, pfModified);
|
|
|
|
|
|
|
|
if(!pfModified)
|
|
|
|
return E_POINTER;
|
|
|
|
|
|
|
|
*pfModified = This->modified_props > 0;
|
|
|
|
return S_OK;
|
2010-03-21 17:43:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static const IUriBuilderVtbl UriBuilderVtbl = {
|
|
|
|
UriBuilder_QueryInterface,
|
|
|
|
UriBuilder_AddRef,
|
|
|
|
UriBuilder_Release,
|
|
|
|
UriBuilder_CreateUriSimple,
|
|
|
|
UriBuilder_CreateUri,
|
|
|
|
UriBuilder_CreateUriWithFlags,
|
|
|
|
UriBuilder_GetIUri,
|
|
|
|
UriBuilder_SetIUri,
|
|
|
|
UriBuilder_GetFragment,
|
|
|
|
UriBuilder_GetHost,
|
|
|
|
UriBuilder_GetPassword,
|
|
|
|
UriBuilder_GetPath,
|
|
|
|
UriBuilder_GetPort,
|
|
|
|
UriBuilder_GetQuery,
|
|
|
|
UriBuilder_GetSchemeName,
|
|
|
|
UriBuilder_GetUserName,
|
|
|
|
UriBuilder_SetFragment,
|
|
|
|
UriBuilder_SetHost,
|
|
|
|
UriBuilder_SetPassword,
|
|
|
|
UriBuilder_SetPath,
|
|
|
|
UriBuilder_SetPort,
|
|
|
|
UriBuilder_SetQuery,
|
|
|
|
UriBuilder_SetSchemeName,
|
|
|
|
UriBuilder_SetUserName,
|
|
|
|
UriBuilder_RemoveProperties,
|
|
|
|
UriBuilder_HasBeenModified,
|
|
|
|
};
|
|
|
|
|
|
|
|
/***********************************************************************
|
|
|
|
* CreateIUriBuilder (urlmon.@)
|
|
|
|
*/
|
|
|
|
HRESULT WINAPI CreateIUriBuilder(IUri *pIUri, DWORD dwFlags, DWORD_PTR dwReserved, IUriBuilder **ppIUriBuilder)
|
|
|
|
{
|
|
|
|
UriBuilder *ret;
|
|
|
|
|
|
|
|
TRACE("(%p %x %x %p)\n", pIUri, dwFlags, (DWORD)dwReserved, ppIUriBuilder);
|
|
|
|
|
2010-10-09 21:52:25 +00:00
|
|
|
if(!ppIUriBuilder)
|
|
|
|
return E_POINTER;
|
|
|
|
|
|
|
|
ret = heap_alloc_zero(sizeof(UriBuilder));
|
2010-03-21 17:43:25 +00:00
|
|
|
if(!ret)
|
|
|
|
return E_OUTOFMEMORY;
|
|
|
|
|
2010-12-20 21:29:55 +00:00
|
|
|
ret->IUriBuilder_iface.lpVtbl = &UriBuilderVtbl;
|
2010-03-21 17:43:25 +00:00
|
|
|
ret->ref = 1;
|
|
|
|
|
2010-10-09 21:52:25 +00:00
|
|
|
if(pIUri) {
|
|
|
|
Uri *uri;
|
|
|
|
|
|
|
|
if((uri = get_uri_obj(pIUri))) {
|
2013-03-22 14:29:11 +00:00
|
|
|
if(!uri->create_flags) {
|
|
|
|
heap_free(ret);
|
|
|
|
return E_UNEXPECTED;
|
|
|
|
}
|
2010-10-09 21:52:25 +00:00
|
|
|
IUri_AddRef(pIUri);
|
|
|
|
ret->uri = uri;
|
|
|
|
|
|
|
|
if(uri->has_port)
|
|
|
|
/* Windows doesn't set 'has_port' to TRUE in this case. */
|
|
|
|
ret->port = uri->port;
|
|
|
|
|
|
|
|
} else {
|
|
|
|
heap_free(ret);
|
|
|
|
*ppIUriBuilder = NULL;
|
|
|
|
FIXME("(%p %x %x %p): Unknown IUri types not supported yet.\n", pIUri, dwFlags,
|
|
|
|
(DWORD)dwReserved, ppIUriBuilder);
|
|
|
|
return E_NOTIMPL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-12-20 21:29:55 +00:00
|
|
|
*ppIUriBuilder = &ret->IUriBuilder_iface;
|
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Merges the base path with the relative path and stores the resulting path
|
|
|
|
* and path len in 'result' and 'result_len'.
|
|
|
|
*/
|
|
|
|
static HRESULT merge_paths(parse_data *data, const WCHAR *base, DWORD base_len, const WCHAR *relative,
|
|
|
|
DWORD relative_len, WCHAR **result, DWORD *result_len, DWORD flags)
|
|
|
|
{
|
|
|
|
const WCHAR *end = NULL;
|
|
|
|
DWORD base_copy_len = 0;
|
|
|
|
WCHAR *ptr;
|
|
|
|
|
|
|
|
if(base_len) {
|
2013-03-22 14:29:11 +00:00
|
|
|
if(data->scheme_type == URL_SCHEME_MK && *relative == '/') {
|
|
|
|
/* Find '::' segment */
|
|
|
|
for(end = base; end < base+base_len-1; end++) {
|
|
|
|
if(end[0] == ':' && end[1] == ':') {
|
|
|
|
end++;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* If not found, try finding the end of @xxx: */
|
|
|
|
if(end == base+base_len-1)
|
|
|
|
end = *base == '@' ? memchr(base, ':', base_len) : NULL;
|
|
|
|
}else {
|
|
|
|
/* Find the characters that will be copied over from the base path. */
|
|
|
|
end = memrchrW(base, '/', base_len);
|
|
|
|
if(!end && data->scheme_type == URL_SCHEME_FILE)
|
|
|
|
/* Try looking for a '\\'. */
|
|
|
|
end = memrchrW(base, '\\', base_len);
|
|
|
|
}
|
2010-12-20 21:29:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if(end) {
|
|
|
|
base_copy_len = (end+1)-base;
|
|
|
|
*result = heap_alloc((base_copy_len+relative_len+1)*sizeof(WCHAR));
|
|
|
|
} else
|
|
|
|
*result = heap_alloc((relative_len+1)*sizeof(WCHAR));
|
|
|
|
|
|
|
|
if(!(*result)) {
|
|
|
|
*result_len = 0;
|
|
|
|
return E_OUTOFMEMORY;
|
|
|
|
}
|
|
|
|
|
|
|
|
ptr = *result;
|
|
|
|
if(end) {
|
|
|
|
memcpy(ptr, base, base_copy_len*sizeof(WCHAR));
|
|
|
|
ptr += base_copy_len;
|
|
|
|
}
|
|
|
|
|
|
|
|
memcpy(ptr, relative, relative_len*sizeof(WCHAR));
|
|
|
|
ptr += relative_len;
|
|
|
|
*ptr = '\0';
|
|
|
|
|
|
|
|
*result_len = (ptr-*result);
|
2013-03-22 14:29:11 +00:00
|
|
|
TRACE("ret %s\n", debugstr_wn(*result, *result_len));
|
2010-03-21 17:43:25 +00:00
|
|
|
return S_OK;
|
|
|
|
}
|
2010-12-20 21:29:55 +00:00
|
|
|
|
|
|
|
static HRESULT combine_uri(Uri *base, Uri *relative, DWORD flags, IUri **result, DWORD extras) {
|
|
|
|
Uri *ret;
|
|
|
|
HRESULT hr;
|
|
|
|
parse_data data;
|
2013-03-22 14:29:11 +00:00
|
|
|
Uri *proc_uri = base;
|
2010-12-20 21:29:55 +00:00
|
|
|
DWORD create_flags = 0, len = 0;
|
|
|
|
|
|
|
|
memset(&data, 0, sizeof(parse_data));
|
|
|
|
|
|
|
|
/* Base case is when the relative Uri has a scheme name,
|
|
|
|
* if it does, then 'result' will contain the same data
|
|
|
|
* as the relative Uri.
|
|
|
|
*/
|
|
|
|
if(relative->scheme_start > -1) {
|
|
|
|
data.uri = SysAllocString(relative->raw_uri);
|
|
|
|
if(!data.uri) {
|
|
|
|
*result = NULL;
|
|
|
|
return E_OUTOFMEMORY;
|
|
|
|
}
|
|
|
|
|
2013-09-28 15:08:52 +00:00
|
|
|
parse_uri(&data, Uri_CREATE_ALLOW_IMPLICIT_FILE_SCHEME);
|
2010-12-20 21:29:55 +00:00
|
|
|
|
2013-03-22 14:29:11 +00:00
|
|
|
hr = Uri_Construct(NULL, (void**)&ret);
|
|
|
|
if(FAILED(hr)) {
|
2010-12-20 21:29:55 +00:00
|
|
|
*result = NULL;
|
2013-03-22 14:29:11 +00:00
|
|
|
return hr;
|
2010-12-20 21:29:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if(extras & COMBINE_URI_FORCE_FLAG_USE) {
|
|
|
|
if(flags & URL_DONT_SIMPLIFY)
|
|
|
|
create_flags |= Uri_CREATE_NO_CANONICALIZE;
|
|
|
|
if(flags & URL_DONT_UNESCAPE_EXTRA_INFO)
|
|
|
|
create_flags |= Uri_CREATE_NO_DECODE_EXTRA_INFO;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret->raw_uri = data.uri;
|
|
|
|
hr = canonicalize_uri(&data, ret, create_flags);
|
|
|
|
if(FAILED(hr)) {
|
|
|
|
IUri_Release(&ret->IUri_iface);
|
|
|
|
*result = NULL;
|
|
|
|
return hr;
|
|
|
|
}
|
|
|
|
|
|
|
|
apply_default_flags(&create_flags);
|
|
|
|
ret->create_flags = create_flags;
|
|
|
|
|
|
|
|
*result = &ret->IUri_iface;
|
|
|
|
} else {
|
|
|
|
WCHAR *path = NULL;
|
|
|
|
DWORD raw_flags = 0;
|
|
|
|
|
|
|
|
if(base->scheme_start > -1) {
|
|
|
|
data.scheme = base->canon_uri+base->scheme_start;
|
|
|
|
data.scheme_len = base->scheme_len;
|
|
|
|
data.scheme_type = base->scheme_type;
|
|
|
|
} else {
|
|
|
|
data.is_relative = TRUE;
|
|
|
|
data.scheme_type = URL_SCHEME_UNKNOWN;
|
|
|
|
create_flags |= Uri_CREATE_ALLOW_RELATIVE;
|
|
|
|
}
|
|
|
|
|
2013-03-22 14:29:11 +00:00
|
|
|
if(relative->authority_start > -1)
|
|
|
|
proc_uri = relative;
|
|
|
|
|
|
|
|
if(proc_uri->authority_start > -1) {
|
|
|
|
if(proc_uri->userinfo_start > -1 && proc_uri->userinfo_split != 0) {
|
|
|
|
data.username = proc_uri->canon_uri+proc_uri->userinfo_start;
|
|
|
|
data.username_len = (proc_uri->userinfo_split > -1) ? proc_uri->userinfo_split : proc_uri->userinfo_len;
|
2010-12-20 21:29:55 +00:00
|
|
|
}
|
|
|
|
|
2013-03-22 14:29:11 +00:00
|
|
|
if(proc_uri->userinfo_split > -1) {
|
|
|
|
data.password = proc_uri->canon_uri+proc_uri->userinfo_start+proc_uri->userinfo_split+1;
|
|
|
|
data.password_len = proc_uri->userinfo_len-proc_uri->userinfo_split-1;
|
2010-12-20 21:29:55 +00:00
|
|
|
}
|
|
|
|
|
2013-03-22 14:29:11 +00:00
|
|
|
if(proc_uri->host_start > -1) {
|
|
|
|
data.host = proc_uri->canon_uri+proc_uri->host_start;
|
|
|
|
data.host_len = proc_uri->host_len;
|
|
|
|
data.host_type = proc_uri->host_type;
|
2010-12-20 21:29:55 +00:00
|
|
|
}
|
|
|
|
|
2013-03-22 14:29:11 +00:00
|
|
|
if(proc_uri->has_port) {
|
2010-12-20 21:29:55 +00:00
|
|
|
data.has_port = TRUE;
|
2013-03-22 14:29:11 +00:00
|
|
|
data.port_value = proc_uri->port;
|
2010-12-20 21:29:55 +00:00
|
|
|
}
|
|
|
|
} else if(base->scheme_type != URL_SCHEME_FILE)
|
|
|
|
data.is_opaque = TRUE;
|
|
|
|
|
2013-03-22 14:29:11 +00:00
|
|
|
if(proc_uri == relative || relative->path_start == -1 || !relative->path_len) {
|
|
|
|
if(proc_uri->path_start > -1) {
|
|
|
|
data.path = proc_uri->canon_uri+proc_uri->path_start;
|
|
|
|
data.path_len = proc_uri->path_len;
|
|
|
|
} else if(!data.is_opaque) {
|
2010-12-20 21:29:55 +00:00
|
|
|
/* Just set the path as a '/' if the base didn't have
|
2014-04-23 17:35:17 +00:00
|
|
|
* one and if it's a hierarchical URI.
|
2010-12-20 21:29:55 +00:00
|
|
|
*/
|
|
|
|
static const WCHAR slashW[] = {'/',0};
|
|
|
|
data.path = slashW;
|
|
|
|
data.path_len = 1;
|
|
|
|
}
|
|
|
|
|
2013-03-22 14:29:11 +00:00
|
|
|
if(relative->query_start > -1)
|
|
|
|
proc_uri = relative;
|
|
|
|
|
|
|
|
if(proc_uri->query_start > -1) {
|
|
|
|
data.query = proc_uri->canon_uri+proc_uri->query_start;
|
|
|
|
data.query_len = proc_uri->query_len;
|
2010-12-20 21:29:55 +00:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
const WCHAR *ptr, **pptr;
|
|
|
|
DWORD path_offset = 0, path_len = 0;
|
|
|
|
|
|
|
|
/* There's two possibilities on what will happen to the path component
|
|
|
|
* of the result IUri. First, if the relative path begins with a '/'
|
|
|
|
* then the resulting path will just be the relative path. Second, if
|
|
|
|
* relative path doesn't begin with a '/' then the base path and relative
|
|
|
|
* path are merged together.
|
|
|
|
*/
|
2013-03-22 14:29:11 +00:00
|
|
|
if(relative->path_len && *(relative->canon_uri+relative->path_start) == '/' && data.scheme_type != URL_SCHEME_MK) {
|
2010-12-20 21:29:55 +00:00
|
|
|
WCHAR *tmp = NULL;
|
|
|
|
BOOL copy_drive_path = FALSE;
|
|
|
|
|
|
|
|
/* If the relative IUri's path starts with a '/', then we
|
|
|
|
* don't use the base IUri's path. Unless the base IUri
|
|
|
|
* is a file URI, in which case it uses the drive path of
|
|
|
|
* the base IUri (if it has any) in the new path.
|
|
|
|
*/
|
|
|
|
if(base->scheme_type == URL_SCHEME_FILE) {
|
|
|
|
if(base->path_len > 3 && *(base->canon_uri+base->path_start) == '/' &&
|
|
|
|
is_drive_path(base->canon_uri+base->path_start+1)) {
|
|
|
|
path_len += 3;
|
|
|
|
copy_drive_path = TRUE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
path_len += relative->path_len;
|
|
|
|
|
|
|
|
path = heap_alloc((path_len+1)*sizeof(WCHAR));
|
|
|
|
if(!path) {
|
|
|
|
*result = NULL;
|
|
|
|
return E_OUTOFMEMORY;
|
|
|
|
}
|
|
|
|
|
|
|
|
tmp = path;
|
|
|
|
|
|
|
|
/* Copy the base paths, drive path over. */
|
|
|
|
if(copy_drive_path) {
|
|
|
|
memcpy(tmp, base->canon_uri+base->path_start, 3*sizeof(WCHAR));
|
|
|
|
tmp += 3;
|
|
|
|
}
|
|
|
|
|
|
|
|
memcpy(tmp, relative->canon_uri+relative->path_start, relative->path_len*sizeof(WCHAR));
|
|
|
|
path[path_len] = '\0';
|
|
|
|
} else {
|
|
|
|
/* Merge the base path with the relative path. */
|
|
|
|
hr = merge_paths(&data, base->canon_uri+base->path_start, base->path_len,
|
|
|
|
relative->canon_uri+relative->path_start, relative->path_len,
|
|
|
|
&path, &path_len, flags);
|
|
|
|
if(FAILED(hr)) {
|
|
|
|
*result = NULL;
|
|
|
|
return hr;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* If the resulting IUri is a file URI, the drive path isn't
|
|
|
|
* reduced out when the dot segments are removed.
|
|
|
|
*/
|
|
|
|
if(path_len >= 3 && data.scheme_type == URL_SCHEME_FILE && !data.host) {
|
|
|
|
if(*path == '/' && is_drive_path(path+1))
|
|
|
|
path_offset = 2;
|
|
|
|
else if(is_drive_path(path))
|
|
|
|
path_offset = 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Check if the dot segments need to be removed from the path. */
|
|
|
|
if(!(flags & URL_DONT_SIMPLIFY) && !data.is_opaque) {
|
|
|
|
DWORD offset = (path_offset > 0) ? path_offset+1 : 0;
|
|
|
|
DWORD new_len = remove_dot_segments(path+offset,path_len-offset);
|
|
|
|
|
|
|
|
if(new_len != path_len) {
|
2011-06-05 21:29:41 +00:00
|
|
|
WCHAR *tmp = heap_realloc(path, (offset+new_len+1)*sizeof(WCHAR));
|
2010-12-20 21:29:55 +00:00
|
|
|
if(!tmp) {
|
|
|
|
heap_free(path);
|
|
|
|
*result = NULL;
|
|
|
|
return E_OUTOFMEMORY;
|
|
|
|
}
|
|
|
|
|
|
|
|
tmp[new_len+offset] = '\0';
|
|
|
|
path = tmp;
|
|
|
|
path_len = new_len+offset;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-06-05 21:29:41 +00:00
|
|
|
if(relative->query_start > -1) {
|
|
|
|
data.query = relative->canon_uri+relative->query_start;
|
|
|
|
data.query_len = relative->query_len;
|
|
|
|
}
|
|
|
|
|
2010-12-20 21:29:55 +00:00
|
|
|
/* Make sure the path component is valid. */
|
|
|
|
ptr = path;
|
|
|
|
pptr = &ptr;
|
|
|
|
if((data.is_opaque && !parse_path_opaque(pptr, &data, 0)) ||
|
|
|
|
(!data.is_opaque && !parse_path_hierarchical(pptr, &data, 0))) {
|
|
|
|
heap_free(path);
|
|
|
|
*result = NULL;
|
|
|
|
return E_INVALIDARG;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if(relative->fragment_start > -1) {
|
|
|
|
data.fragment = relative->canon_uri+relative->fragment_start;
|
|
|
|
data.fragment_len = relative->fragment_len;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(flags & URL_DONT_SIMPLIFY)
|
|
|
|
raw_flags |= RAW_URI_FORCE_PORT_DISP;
|
|
|
|
if(flags & URL_FILE_USE_PATHURL)
|
|
|
|
raw_flags |= RAW_URI_CONVERT_TO_DOS_PATH;
|
|
|
|
|
|
|
|
len = generate_raw_uri(&data, data.uri, raw_flags);
|
|
|
|
data.uri = SysAllocStringLen(NULL, len);
|
|
|
|
if(!data.uri) {
|
|
|
|
heap_free(path);
|
|
|
|
*result = NULL;
|
|
|
|
return E_OUTOFMEMORY;
|
|
|
|
}
|
|
|
|
|
|
|
|
generate_raw_uri(&data, data.uri, raw_flags);
|
|
|
|
|
2013-03-22 14:29:11 +00:00
|
|
|
hr = Uri_Construct(NULL, (void**)&ret);
|
|
|
|
if(FAILED(hr)) {
|
2010-12-20 21:29:55 +00:00
|
|
|
SysFreeString(data.uri);
|
|
|
|
heap_free(path);
|
|
|
|
*result = NULL;
|
2013-03-22 14:29:11 +00:00
|
|
|
return hr;
|
2010-12-20 21:29:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if(flags & URL_DONT_SIMPLIFY)
|
|
|
|
create_flags |= Uri_CREATE_NO_CANONICALIZE;
|
|
|
|
if(flags & URL_FILE_USE_PATHURL)
|
|
|
|
create_flags |= Uri_CREATE_FILE_USE_DOS_PATH;
|
|
|
|
|
|
|
|
ret->raw_uri = data.uri;
|
|
|
|
hr = canonicalize_uri(&data, ret, create_flags);
|
|
|
|
if(FAILED(hr)) {
|
|
|
|
IUri_Release(&ret->IUri_iface);
|
|
|
|
*result = NULL;
|
|
|
|
return hr;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(flags & URL_DONT_SIMPLIFY)
|
|
|
|
ret->display_modifiers |= URI_DISPLAY_NO_DEFAULT_PORT_AUTH;
|
|
|
|
|
|
|
|
apply_default_flags(&create_flags);
|
|
|
|
ret->create_flags = create_flags;
|
|
|
|
*result = &ret->IUri_iface;
|
|
|
|
|
|
|
|
heap_free(path);
|
|
|
|
}
|
|
|
|
|
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
/***********************************************************************
|
|
|
|
* CoInternetCombineIUri (urlmon.@)
|
|
|
|
*/
|
|
|
|
HRESULT WINAPI CoInternetCombineIUri(IUri *pBaseUri, IUri *pRelativeUri, DWORD dwCombineFlags,
|
|
|
|
IUri **ppCombinedUri, DWORD_PTR dwReserved)
|
|
|
|
{
|
|
|
|
HRESULT hr;
|
|
|
|
IInternetProtocolInfo *info;
|
|
|
|
Uri *relative, *base;
|
|
|
|
TRACE("(%p %p %x %p %x)\n", pBaseUri, pRelativeUri, dwCombineFlags, ppCombinedUri, (DWORD)dwReserved);
|
|
|
|
|
|
|
|
if(!ppCombinedUri)
|
|
|
|
return E_INVALIDARG;
|
|
|
|
|
|
|
|
if(!pBaseUri || !pRelativeUri) {
|
|
|
|
*ppCombinedUri = NULL;
|
|
|
|
return E_INVALIDARG;
|
|
|
|
}
|
|
|
|
|
|
|
|
relative = get_uri_obj(pRelativeUri);
|
|
|
|
base = get_uri_obj(pBaseUri);
|
|
|
|
if(!relative || !base) {
|
|
|
|
*ppCombinedUri = NULL;
|
|
|
|
FIXME("(%p %p %x %p %x) Unknown IUri types not supported yet.\n",
|
|
|
|
pBaseUri, pRelativeUri, dwCombineFlags, ppCombinedUri, (DWORD)dwReserved);
|
|
|
|
return E_NOTIMPL;
|
|
|
|
}
|
|
|
|
|
|
|
|
info = get_protocol_info(base->canon_uri);
|
|
|
|
if(info) {
|
|
|
|
WCHAR result[INTERNET_MAX_URL_LENGTH+1];
|
|
|
|
DWORD result_len = 0;
|
|
|
|
|
|
|
|
hr = IInternetProtocolInfo_CombineUrl(info, base->canon_uri, relative->canon_uri, dwCombineFlags,
|
|
|
|
result, INTERNET_MAX_URL_LENGTH+1, &result_len, 0);
|
|
|
|
IInternetProtocolInfo_Release(info);
|
|
|
|
if(SUCCEEDED(hr)) {
|
|
|
|
hr = CreateUri(result, Uri_CREATE_ALLOW_RELATIVE, 0, ppCombinedUri);
|
|
|
|
if(SUCCEEDED(hr))
|
|
|
|
return hr;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return combine_uri(base, relative, dwCombineFlags, ppCombinedUri, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
/***********************************************************************
|
|
|
|
* CoInternetCombineUrlEx (urlmon.@)
|
|
|
|
*/
|
|
|
|
HRESULT WINAPI CoInternetCombineUrlEx(IUri *pBaseUri, LPCWSTR pwzRelativeUrl, DWORD dwCombineFlags,
|
|
|
|
IUri **ppCombinedUri, DWORD_PTR dwReserved)
|
|
|
|
{
|
|
|
|
IUri *relative;
|
|
|
|
Uri *base;
|
|
|
|
HRESULT hr;
|
|
|
|
IInternetProtocolInfo *info;
|
|
|
|
|
2017-03-19 16:57:50 +00:00
|
|
|
TRACE("(%p %s %x %p %x)\n", pBaseUri, debugstr_w(pwzRelativeUrl), dwCombineFlags,
|
2010-12-20 21:29:55 +00:00
|
|
|
ppCombinedUri, (DWORD)dwReserved);
|
|
|
|
|
|
|
|
if(!ppCombinedUri)
|
|
|
|
return E_POINTER;
|
|
|
|
|
|
|
|
if(!pwzRelativeUrl) {
|
|
|
|
*ppCombinedUri = NULL;
|
|
|
|
return E_UNEXPECTED;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(!pBaseUri) {
|
|
|
|
*ppCombinedUri = NULL;
|
|
|
|
return E_INVALIDARG;
|
|
|
|
}
|
|
|
|
|
|
|
|
base = get_uri_obj(pBaseUri);
|
|
|
|
if(!base) {
|
|
|
|
*ppCombinedUri = NULL;
|
|
|
|
FIXME("(%p %s %x %p %x) Unknown IUri's not supported yet.\n", pBaseUri, debugstr_w(pwzRelativeUrl),
|
|
|
|
dwCombineFlags, ppCombinedUri, (DWORD)dwReserved);
|
|
|
|
return E_NOTIMPL;
|
|
|
|
}
|
|
|
|
|
|
|
|
info = get_protocol_info(base->canon_uri);
|
|
|
|
if(info) {
|
|
|
|
WCHAR result[INTERNET_MAX_URL_LENGTH+1];
|
|
|
|
DWORD result_len = 0;
|
|
|
|
|
|
|
|
hr = IInternetProtocolInfo_CombineUrl(info, base->canon_uri, pwzRelativeUrl, dwCombineFlags,
|
|
|
|
result, INTERNET_MAX_URL_LENGTH+1, &result_len, 0);
|
|
|
|
IInternetProtocolInfo_Release(info);
|
|
|
|
if(SUCCEEDED(hr)) {
|
|
|
|
hr = CreateUri(result, Uri_CREATE_ALLOW_RELATIVE, 0, ppCombinedUri);
|
|
|
|
if(SUCCEEDED(hr))
|
|
|
|
return hr;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-09-28 15:08:52 +00:00
|
|
|
hr = CreateUri(pwzRelativeUrl, Uri_CREATE_ALLOW_RELATIVE|Uri_CREATE_ALLOW_IMPLICIT_FILE_SCHEME, 0, &relative);
|
2010-12-20 21:29:55 +00:00
|
|
|
if(FAILED(hr)) {
|
|
|
|
*ppCombinedUri = NULL;
|
|
|
|
return hr;
|
|
|
|
}
|
|
|
|
|
|
|
|
hr = combine_uri(base, get_uri_obj(relative), dwCombineFlags, ppCombinedUri, COMBINE_URI_FORCE_FLAG_USE);
|
|
|
|
|
|
|
|
IUri_Release(relative);
|
|
|
|
return hr;
|
|
|
|
}
|
|
|
|
|
|
|
|
static HRESULT parse_canonicalize(const Uri *uri, DWORD flags, LPWSTR output,
|
|
|
|
DWORD output_len, DWORD *result_len)
|
|
|
|
{
|
|
|
|
const WCHAR *ptr = NULL;
|
|
|
|
WCHAR *path = NULL;
|
|
|
|
const WCHAR **pptr;
|
|
|
|
DWORD len = 0;
|
|
|
|
BOOL reduce_path;
|
|
|
|
|
|
|
|
/* URL_UNESCAPE only has effect if none of the URL_ESCAPE flags are set. */
|
|
|
|
const BOOL allow_unescape = !(flags & URL_ESCAPE_UNSAFE) &&
|
|
|
|
!(flags & URL_ESCAPE_SPACES_ONLY) &&
|
|
|
|
!(flags & URL_ESCAPE_PERCENT);
|
|
|
|
|
|
|
|
|
|
|
|
/* Check if the dot segments need to be removed from the
|
|
|
|
* path component.
|
|
|
|
*/
|
|
|
|
if(uri->scheme_start > -1 && uri->path_start > -1) {
|
|
|
|
ptr = uri->canon_uri+uri->scheme_start+uri->scheme_len+1;
|
|
|
|
pptr = &ptr;
|
|
|
|
}
|
2015-07-22 00:37:05 +00:00
|
|
|
reduce_path = !(flags & URL_DONT_SIMPLIFY) &&
|
2010-12-20 21:29:55 +00:00
|
|
|
ptr && check_hierarchical(pptr);
|
|
|
|
|
|
|
|
for(ptr = uri->canon_uri; ptr < uri->canon_uri+uri->canon_len; ++ptr) {
|
|
|
|
BOOL do_default_action = TRUE;
|
|
|
|
|
|
|
|
/* Keep track of the path if we need to remove dot segments from
|
|
|
|
* it later.
|
|
|
|
*/
|
|
|
|
if(reduce_path && !path && ptr == uri->canon_uri+uri->path_start)
|
2017-03-19 16:57:50 +00:00
|
|
|
path = output+len;
|
2010-12-20 21:29:55 +00:00
|
|
|
|
|
|
|
/* Check if it's time to reduce the path. */
|
|
|
|
if(reduce_path && ptr == uri->canon_uri+uri->path_start+uri->path_len) {
|
2017-03-19 16:57:50 +00:00
|
|
|
DWORD current_path_len = (output+len) - path;
|
2010-12-20 21:29:55 +00:00
|
|
|
DWORD new_path_len = remove_dot_segments(path, current_path_len);
|
|
|
|
|
|
|
|
/* Update the current length. */
|
|
|
|
len -= (current_path_len-new_path_len);
|
|
|
|
reduce_path = FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(*ptr == '%') {
|
|
|
|
const WCHAR decoded = decode_pct_val(ptr);
|
|
|
|
if(decoded) {
|
|
|
|
if(allow_unescape && (flags & URL_UNESCAPE)) {
|
2017-03-19 16:57:50 +00:00
|
|
|
if(len < output_len)
|
|
|
|
output[len] = decoded;
|
|
|
|
len++;
|
2010-12-20 21:29:55 +00:00
|
|
|
ptr += 2;
|
|
|
|
do_default_action = FALSE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* See if %'s needed to encoded. */
|
|
|
|
if(do_default_action && (flags & URL_ESCAPE_PERCENT)) {
|
2017-03-19 16:57:50 +00:00
|
|
|
if(len + 3 < output_len)
|
|
|
|
pct_encode_val(*ptr, output+len);
|
2010-12-20 21:29:55 +00:00
|
|
|
len += 3;
|
|
|
|
do_default_action = FALSE;
|
|
|
|
}
|
|
|
|
} else if(*ptr == ' ') {
|
|
|
|
if((flags & URL_ESCAPE_SPACES_ONLY) &&
|
|
|
|
!(flags & URL_ESCAPE_UNSAFE)) {
|
2017-03-19 16:57:50 +00:00
|
|
|
if(len + 3 < output_len)
|
|
|
|
pct_encode_val(*ptr, output+len);
|
2010-12-20 21:29:55 +00:00
|
|
|
len += 3;
|
|
|
|
do_default_action = FALSE;
|
|
|
|
}
|
2018-03-23 11:35:23 +00:00
|
|
|
} else if(is_ascii(*ptr) && !is_reserved(*ptr) && !is_unreserved(*ptr)) {
|
2010-12-20 21:29:55 +00:00
|
|
|
if(flags & URL_ESCAPE_UNSAFE) {
|
2017-03-19 16:57:50 +00:00
|
|
|
if(len + 3 < output_len)
|
|
|
|
pct_encode_val(*ptr, output+len);
|
2010-12-20 21:29:55 +00:00
|
|
|
len += 3;
|
|
|
|
do_default_action = FALSE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-03-19 16:57:50 +00:00
|
|
|
if(do_default_action) {
|
|
|
|
if(len < output_len)
|
|
|
|
output[len] = *ptr;
|
|
|
|
len++;
|
|
|
|
}
|
2010-12-20 21:29:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Sometimes the path is the very last component of the IUri, so
|
|
|
|
* see if the dot segments need to be reduced now.
|
|
|
|
*/
|
|
|
|
if(reduce_path && path) {
|
2017-03-19 16:57:50 +00:00
|
|
|
DWORD current_path_len = (output+len) - path;
|
2010-12-20 21:29:55 +00:00
|
|
|
DWORD new_path_len = remove_dot_segments(path, current_path_len);
|
|
|
|
|
|
|
|
/* Update the current length. */
|
|
|
|
len -= (current_path_len-new_path_len);
|
|
|
|
}
|
|
|
|
|
2017-03-19 16:57:50 +00:00
|
|
|
if(len < output_len)
|
|
|
|
output[len] = 0;
|
|
|
|
else
|
|
|
|
output[output_len-1] = 0;
|
2010-12-20 21:29:55 +00:00
|
|
|
|
2013-03-22 14:29:11 +00:00
|
|
|
/* The null terminator isn't included in the length. */
|
2017-03-19 16:57:50 +00:00
|
|
|
*result_len = len;
|
|
|
|
if(len >= output_len)
|
2010-12-20 21:29:55 +00:00
|
|
|
return STRSAFE_E_INSUFFICIENT_BUFFER;
|
|
|
|
|
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
static HRESULT parse_friendly(IUri *uri, LPWSTR output, DWORD output_len,
|
|
|
|
DWORD *result_len)
|
|
|
|
{
|
|
|
|
HRESULT hr;
|
|
|
|
DWORD display_len;
|
|
|
|
BSTR display;
|
|
|
|
|
|
|
|
hr = IUri_GetPropertyLength(uri, Uri_PROPERTY_DISPLAY_URI, &display_len, 0);
|
|
|
|
if(FAILED(hr)) {
|
|
|
|
*result_len = 0;
|
|
|
|
return hr;
|
|
|
|
}
|
|
|
|
|
|
|
|
*result_len = display_len;
|
|
|
|
if(display_len+1 > output_len)
|
|
|
|
return STRSAFE_E_INSUFFICIENT_BUFFER;
|
|
|
|
|
|
|
|
hr = IUri_GetDisplayUri(uri, &display);
|
|
|
|
if(FAILED(hr)) {
|
|
|
|
*result_len = 0;
|
|
|
|
return hr;
|
|
|
|
}
|
|
|
|
|
|
|
|
memcpy(output, display, (display_len+1)*sizeof(WCHAR));
|
|
|
|
SysFreeString(display);
|
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
static HRESULT parse_rootdocument(const Uri *uri, LPWSTR output, DWORD output_len,
|
|
|
|
DWORD *result_len)
|
|
|
|
{
|
|
|
|
static const WCHAR colon_slashesW[] = {':','/','/'};
|
|
|
|
|
|
|
|
WCHAR *ptr;
|
|
|
|
DWORD len = 0;
|
|
|
|
|
|
|
|
/* Windows only returns the root document if the URI has an authority
|
|
|
|
* and it's not an unknown scheme type or a file scheme type.
|
|
|
|
*/
|
|
|
|
if(uri->authority_start == -1 ||
|
|
|
|
uri->scheme_type == URL_SCHEME_UNKNOWN ||
|
|
|
|
uri->scheme_type == URL_SCHEME_FILE) {
|
|
|
|
*result_len = 0;
|
|
|
|
if(!output_len)
|
|
|
|
return STRSAFE_E_INSUFFICIENT_BUFFER;
|
|
|
|
|
|
|
|
output[0] = 0;
|
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
len = uri->scheme_len+uri->authority_len;
|
|
|
|
/* For the "://" and '/' which will be added. */
|
|
|
|
len += 4;
|
|
|
|
|
|
|
|
if(len+1 > output_len) {
|
|
|
|
*result_len = len;
|
|
|
|
return STRSAFE_E_INSUFFICIENT_BUFFER;
|
|
|
|
}
|
|
|
|
|
|
|
|
ptr = output;
|
|
|
|
memcpy(ptr, uri->canon_uri+uri->scheme_start, uri->scheme_len*sizeof(WCHAR));
|
|
|
|
|
|
|
|
/* Add the "://". */
|
|
|
|
ptr += uri->scheme_len;
|
|
|
|
memcpy(ptr, colon_slashesW, sizeof(colon_slashesW));
|
|
|
|
|
|
|
|
/* Add the authority. */
|
2019-02-04 12:04:30 +00:00
|
|
|
ptr += ARRAY_SIZE(colon_slashesW);
|
2010-12-20 21:29:55 +00:00
|
|
|
memcpy(ptr, uri->canon_uri+uri->authority_start, uri->authority_len*sizeof(WCHAR));
|
|
|
|
|
|
|
|
/* Add the '/' after the authority. */
|
|
|
|
ptr += uri->authority_len;
|
|
|
|
*ptr = '/';
|
|
|
|
ptr[1] = 0;
|
|
|
|
|
|
|
|
*result_len = len;
|
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
static HRESULT parse_document(const Uri *uri, LPWSTR output, DWORD output_len,
|
|
|
|
DWORD *result_len)
|
|
|
|
{
|
|
|
|
DWORD len = 0;
|
|
|
|
|
|
|
|
/* It has to be a known scheme type, but, it can't be a file
|
|
|
|
* scheme. It also has to hierarchical.
|
|
|
|
*/
|
|
|
|
if(uri->scheme_type == URL_SCHEME_UNKNOWN ||
|
|
|
|
uri->scheme_type == URL_SCHEME_FILE ||
|
|
|
|
uri->authority_start == -1) {
|
|
|
|
*result_len = 0;
|
|
|
|
if(output_len < 1)
|
|
|
|
return STRSAFE_E_INSUFFICIENT_BUFFER;
|
|
|
|
|
|
|
|
output[0] = 0;
|
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(uri->fragment_start > -1)
|
|
|
|
len = uri->fragment_start;
|
|
|
|
else
|
|
|
|
len = uri->canon_len;
|
|
|
|
|
|
|
|
*result_len = len;
|
|
|
|
if(len+1 > output_len)
|
|
|
|
return STRSAFE_E_INSUFFICIENT_BUFFER;
|
|
|
|
|
|
|
|
memcpy(output, uri->canon_uri, len*sizeof(WCHAR));
|
|
|
|
output[len] = 0;
|
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
static HRESULT parse_path_from_url(const Uri *uri, LPWSTR output, DWORD output_len,
|
|
|
|
DWORD *result_len)
|
|
|
|
{
|
|
|
|
const WCHAR *path_ptr;
|
|
|
|
WCHAR buffer[INTERNET_MAX_URL_LENGTH+1];
|
|
|
|
WCHAR *ptr;
|
|
|
|
|
|
|
|
if(uri->scheme_type != URL_SCHEME_FILE) {
|
|
|
|
*result_len = 0;
|
|
|
|
if(output_len > 0)
|
|
|
|
output[0] = 0;
|
|
|
|
return E_INVALIDARG;
|
|
|
|
}
|
|
|
|
|
|
|
|
ptr = buffer;
|
|
|
|
if(uri->host_start > -1) {
|
|
|
|
static const WCHAR slash_slashW[] = {'\\','\\'};
|
|
|
|
|
|
|
|
memcpy(ptr, slash_slashW, sizeof(slash_slashW));
|
2019-02-04 12:04:30 +00:00
|
|
|
ptr += ARRAY_SIZE(slash_slashW);
|
2010-12-20 21:29:55 +00:00
|
|
|
memcpy(ptr, uri->canon_uri+uri->host_start, uri->host_len*sizeof(WCHAR));
|
|
|
|
ptr += uri->host_len;
|
|
|
|
}
|
|
|
|
|
|
|
|
path_ptr = uri->canon_uri+uri->path_start;
|
|
|
|
if(uri->path_len > 3 && *path_ptr == '/' && is_drive_path(path_ptr+1))
|
|
|
|
/* Skip past the '/' in front of the drive path. */
|
|
|
|
++path_ptr;
|
|
|
|
|
|
|
|
for(; path_ptr < uri->canon_uri+uri->path_start+uri->path_len; ++path_ptr, ++ptr) {
|
|
|
|
BOOL do_default_action = TRUE;
|
|
|
|
|
|
|
|
if(*path_ptr == '%') {
|
|
|
|
const WCHAR decoded = decode_pct_val(path_ptr);
|
|
|
|
if(decoded) {
|
|
|
|
*ptr = decoded;
|
|
|
|
path_ptr += 2;
|
|
|
|
do_default_action = FALSE;
|
|
|
|
}
|
|
|
|
} else if(*path_ptr == '/') {
|
|
|
|
*ptr = '\\';
|
|
|
|
do_default_action = FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(do_default_action)
|
|
|
|
*ptr = *path_ptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
*ptr = 0;
|
|
|
|
|
|
|
|
*result_len = ptr-buffer;
|
|
|
|
if(*result_len+1 > output_len)
|
|
|
|
return STRSAFE_E_INSUFFICIENT_BUFFER;
|
|
|
|
|
|
|
|
memcpy(output, buffer, (*result_len+1)*sizeof(WCHAR));
|
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
static HRESULT parse_url_from_path(IUri *uri, LPWSTR output, DWORD output_len,
|
|
|
|
DWORD *result_len)
|
|
|
|
{
|
|
|
|
HRESULT hr;
|
|
|
|
BSTR received;
|
|
|
|
DWORD len = 0;
|
|
|
|
|
|
|
|
hr = IUri_GetPropertyLength(uri, Uri_PROPERTY_ABSOLUTE_URI, &len, 0);
|
|
|
|
if(FAILED(hr)) {
|
|
|
|
*result_len = 0;
|
|
|
|
return hr;
|
|
|
|
}
|
|
|
|
|
|
|
|
*result_len = len;
|
|
|
|
if(len+1 > output_len)
|
|
|
|
return STRSAFE_E_INSUFFICIENT_BUFFER;
|
|
|
|
|
|
|
|
hr = IUri_GetAbsoluteUri(uri, &received);
|
|
|
|
if(FAILED(hr)) {
|
|
|
|
*result_len = 0;
|
|
|
|
return hr;
|
|
|
|
}
|
|
|
|
|
|
|
|
memcpy(output, received, (len+1)*sizeof(WCHAR));
|
|
|
|
SysFreeString(received);
|
|
|
|
|
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
static HRESULT parse_schema(IUri *uri, LPWSTR output, DWORD output_len,
|
|
|
|
DWORD *result_len)
|
|
|
|
{
|
|
|
|
HRESULT hr;
|
|
|
|
DWORD len;
|
|
|
|
BSTR received;
|
|
|
|
|
|
|
|
hr = IUri_GetPropertyLength(uri, Uri_PROPERTY_SCHEME_NAME, &len, 0);
|
|
|
|
if(FAILED(hr)) {
|
|
|
|
*result_len = 0;
|
|
|
|
return hr;
|
|
|
|
}
|
|
|
|
|
|
|
|
*result_len = len;
|
|
|
|
if(len+1 > output_len)
|
|
|
|
return STRSAFE_E_INSUFFICIENT_BUFFER;
|
|
|
|
|
|
|
|
hr = IUri_GetSchemeName(uri, &received);
|
|
|
|
if(FAILED(hr)) {
|
|
|
|
*result_len = 0;
|
|
|
|
return hr;
|
|
|
|
}
|
|
|
|
|
|
|
|
memcpy(output, received, (len+1)*sizeof(WCHAR));
|
|
|
|
SysFreeString(received);
|
|
|
|
|
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
static HRESULT parse_site(IUri *uri, LPWSTR output, DWORD output_len, DWORD *result_len)
|
|
|
|
{
|
|
|
|
HRESULT hr;
|
|
|
|
DWORD len;
|
|
|
|
BSTR received;
|
|
|
|
|
|
|
|
hr = IUri_GetPropertyLength(uri, Uri_PROPERTY_HOST, &len, 0);
|
|
|
|
if(FAILED(hr)) {
|
|
|
|
*result_len = 0;
|
|
|
|
return hr;
|
|
|
|
}
|
|
|
|
|
|
|
|
*result_len = len;
|
|
|
|
if(len+1 > output_len)
|
|
|
|
return STRSAFE_E_INSUFFICIENT_BUFFER;
|
|
|
|
|
|
|
|
hr = IUri_GetHost(uri, &received);
|
|
|
|
if(FAILED(hr)) {
|
|
|
|
*result_len = 0;
|
|
|
|
return hr;
|
|
|
|
}
|
|
|
|
|
|
|
|
memcpy(output, received, (len+1)*sizeof(WCHAR));
|
|
|
|
SysFreeString(received);
|
|
|
|
|
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
static HRESULT parse_domain(IUri *uri, LPWSTR output, DWORD output_len, DWORD *result_len)
|
|
|
|
{
|
|
|
|
HRESULT hr;
|
|
|
|
DWORD len;
|
|
|
|
BSTR received;
|
|
|
|
|
|
|
|
hr = IUri_GetPropertyLength(uri, Uri_PROPERTY_DOMAIN, &len, 0);
|
|
|
|
if(FAILED(hr)) {
|
|
|
|
*result_len = 0;
|
|
|
|
return hr;
|
|
|
|
}
|
|
|
|
|
|
|
|
*result_len = len;
|
|
|
|
if(len+1 > output_len)
|
|
|
|
return STRSAFE_E_INSUFFICIENT_BUFFER;
|
|
|
|
|
|
|
|
hr = IUri_GetDomain(uri, &received);
|
|
|
|
if(FAILED(hr)) {
|
|
|
|
*result_len = 0;
|
|
|
|
return hr;
|
|
|
|
}
|
|
|
|
|
|
|
|
memcpy(output, received, (len+1)*sizeof(WCHAR));
|
|
|
|
SysFreeString(received);
|
|
|
|
|
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
static HRESULT parse_anchor(IUri *uri, LPWSTR output, DWORD output_len, DWORD *result_len)
|
|
|
|
{
|
|
|
|
HRESULT hr;
|
|
|
|
DWORD len;
|
|
|
|
BSTR received;
|
|
|
|
|
|
|
|
hr = IUri_GetPropertyLength(uri, Uri_PROPERTY_FRAGMENT, &len, 0);
|
|
|
|
if(FAILED(hr)) {
|
|
|
|
*result_len = 0;
|
|
|
|
return hr;
|
|
|
|
}
|
|
|
|
|
|
|
|
*result_len = len;
|
|
|
|
if(len+1 > output_len)
|
|
|
|
return STRSAFE_E_INSUFFICIENT_BUFFER;
|
|
|
|
|
|
|
|
hr = IUri_GetFragment(uri, &received);
|
|
|
|
if(FAILED(hr)) {
|
|
|
|
*result_len = 0;
|
|
|
|
return hr;
|
|
|
|
}
|
|
|
|
|
|
|
|
memcpy(output, received, (len+1)*sizeof(WCHAR));
|
|
|
|
SysFreeString(received);
|
|
|
|
|
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
/***********************************************************************
|
|
|
|
* CoInternetParseIUri (urlmon.@)
|
|
|
|
*/
|
|
|
|
HRESULT WINAPI CoInternetParseIUri(IUri *pIUri, PARSEACTION ParseAction, DWORD dwFlags,
|
|
|
|
LPWSTR pwzResult, DWORD cchResult, DWORD *pcchResult,
|
|
|
|
DWORD_PTR dwReserved)
|
|
|
|
{
|
|
|
|
HRESULT hr;
|
|
|
|
Uri *uri;
|
|
|
|
IInternetProtocolInfo *info;
|
|
|
|
|
|
|
|
TRACE("(%p %d %x %p %d %p %x)\n", pIUri, ParseAction, dwFlags, pwzResult,
|
|
|
|
cchResult, pcchResult, (DWORD)dwReserved);
|
|
|
|
|
|
|
|
if(!pcchResult)
|
|
|
|
return E_POINTER;
|
|
|
|
|
|
|
|
if(!pwzResult || !pIUri) {
|
|
|
|
*pcchResult = 0;
|
|
|
|
return E_INVALIDARG;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(!(uri = get_uri_obj(pIUri))) {
|
|
|
|
*pcchResult = 0;
|
|
|
|
FIXME("(%p %d %x %p %d %p %x) Unknown IUri's not supported for this action.\n",
|
|
|
|
pIUri, ParseAction, dwFlags, pwzResult, cchResult, pcchResult, (DWORD)dwReserved);
|
|
|
|
return E_NOTIMPL;
|
|
|
|
}
|
|
|
|
|
|
|
|
info = get_protocol_info(uri->canon_uri);
|
|
|
|
if(info) {
|
|
|
|
hr = IInternetProtocolInfo_ParseUrl(info, uri->canon_uri, ParseAction, dwFlags,
|
|
|
|
pwzResult, cchResult, pcchResult, 0);
|
|
|
|
IInternetProtocolInfo_Release(info);
|
|
|
|
if(SUCCEEDED(hr)) return hr;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch(ParseAction) {
|
|
|
|
case PARSE_CANONICALIZE:
|
|
|
|
hr = parse_canonicalize(uri, dwFlags, pwzResult, cchResult, pcchResult);
|
|
|
|
break;
|
|
|
|
case PARSE_FRIENDLY:
|
|
|
|
hr = parse_friendly(pIUri, pwzResult, cchResult, pcchResult);
|
|
|
|
break;
|
|
|
|
case PARSE_ROOTDOCUMENT:
|
|
|
|
hr = parse_rootdocument(uri, pwzResult, cchResult, pcchResult);
|
|
|
|
break;
|
|
|
|
case PARSE_DOCUMENT:
|
|
|
|
hr = parse_document(uri, pwzResult, cchResult, pcchResult);
|
|
|
|
break;
|
|
|
|
case PARSE_PATH_FROM_URL:
|
|
|
|
hr = parse_path_from_url(uri, pwzResult, cchResult, pcchResult);
|
|
|
|
break;
|
|
|
|
case PARSE_URL_FROM_PATH:
|
|
|
|
hr = parse_url_from_path(pIUri, pwzResult, cchResult, pcchResult);
|
|
|
|
break;
|
|
|
|
case PARSE_SCHEMA:
|
|
|
|
hr = parse_schema(pIUri, pwzResult, cchResult, pcchResult);
|
|
|
|
break;
|
|
|
|
case PARSE_SITE:
|
|
|
|
hr = parse_site(pIUri, pwzResult, cchResult, pcchResult);
|
|
|
|
break;
|
|
|
|
case PARSE_DOMAIN:
|
|
|
|
hr = parse_domain(pIUri, pwzResult, cchResult, pcchResult);
|
|
|
|
break;
|
|
|
|
case PARSE_LOCATION:
|
|
|
|
case PARSE_ANCHOR:
|
|
|
|
hr = parse_anchor(pIUri, pwzResult, cchResult, pcchResult);
|
|
|
|
break;
|
|
|
|
case PARSE_SECURITY_URL:
|
|
|
|
case PARSE_MIME:
|
|
|
|
case PARSE_SERVER:
|
|
|
|
case PARSE_SECURITY_DOMAIN:
|
|
|
|
*pcchResult = 0;
|
|
|
|
hr = E_FAIL;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
*pcchResult = 0;
|
|
|
|
hr = E_NOTIMPL;
|
|
|
|
FIXME("(%p %d %x %p %d %p %x) Partial stub.\n", pIUri, ParseAction, dwFlags,
|
|
|
|
pwzResult, cchResult, pcchResult, (DWORD)dwReserved);
|
|
|
|
}
|
|
|
|
|
|
|
|
return hr;
|
|
|
|
}
|