/************************************************************************** * WsEncodeUrl [webservices.@] */ HRESULT WINAPI WsEncodeUrl( const WS_URL *base, ULONG flags, WS_HEAP *heap, WS_STRING *ret, WS_ERROR *error ) { static const WCHAR fmtW[] = {':','%','u',0}; ULONG len = 0, len_scheme, len_enc, ret_size; const WS_HTTP_URL *url = (const WS_HTTP_URL *)base; const WCHAR *scheme; WCHAR *str, *p, *q; ULONG port = 0; HRESULT hr; TRACE( "%p %08x %p %p %p\n", base, flags, heap, ret, error ); if (error) FIXME( "ignoring error parameter\n" ); if (!url || !heap || !ret) return E_INVALIDARG; if (flags) { FIXME( "unimplemented flags %08x\n", flags ); return E_NOTIMPL; } if (!(scheme = scheme_str( url->url.scheme, &len_scheme ))) return WS_E_INVALID_FORMAT; len = len_scheme + 3; /* '://' */ len += 6; /* ':65535' */ if ((hr = url_encode_size( url->host.chars, url->host.length, "", &len_enc )) != S_OK) return hr; len += len_enc; if ((hr = url_encode_size( url->path.chars, url->path.length, "/", &len_enc )) != S_OK) return hr; len += len_enc; if ((hr = url_encode_size( url->query.chars, url->query.length, "/?", &len_enc )) != S_OK) return hr; len += len_enc + 1; /* '?' */ if ((hr = url_encode_size( url->fragment.chars, url->fragment.length, "/?", &len_enc )) != S_OK) return hr; len += len_enc + 1; /* '#' */ ret_size = len * sizeof(WCHAR); if (!(str = ws_alloc( heap, ret_size ))) return WS_E_QUOTA_EXCEEDED; memcpy( str, scheme, len_scheme * sizeof(WCHAR) ); p = str + len_scheme; p[0] = ':'; p[1] = p[2] = '/'; p += 3; if ((hr = url_encode( url->host.chars, url->host.length, p, "", &len_enc )) != S_OK) goto error; p += len_enc; if (url->portAsString.length) { q = url->portAsString.chars; len = url->portAsString.length; while (len && isdigitW( *q )) { if ((port = port * 10 + *q - '0') > 65535) { hr = WS_E_INVALID_FORMAT; goto error; } q++; len--; } if (url->port && port != url->port) { hr = E_INVALIDARG; goto error; } } else port = url->port; if (port == default_port( url->url.scheme )) port = 0; if (port) { WCHAR buf[7]; len = sprintfW( buf, fmtW, port ); memcpy( p, buf, len * sizeof(WCHAR) ); p += len; } if ((hr = url_encode( url->path.chars, url->path.length, p, "/", &len_enc )) != S_OK) goto error; p += len_enc; if (url->query.length) { *p++ = '?'; if ((hr = url_encode( url->query.chars, url->query.length, p, "/?", &len_enc )) != S_OK) goto error; p += len_enc; } if (url->fragment.length) { *p++ = '#'; if ((hr = url_encode( url->fragment.chars, url->fragment.length, p, "/?", &len_enc )) != S_OK) goto error; p += len_enc; } ret->length = p - str; ret->chars = str; return S_OK; error: ws_free( heap, str, ret_size ); return hr; }
unsigned default_port() const { return default_port(scheme()); }
/************************************************************************** * WsDecodeUrl [webservices.@] */ HRESULT WINAPI WsDecodeUrl( const WS_STRING *str, ULONG flags, WS_HEAP *heap, WS_URL **ret, WS_ERROR *error ) { HRESULT hr = WS_E_QUOTA_EXCEEDED; WCHAR *p, *q, *decoded = NULL; WS_HTTP_URL *url = NULL; ULONG len, len_decoded, port = 0; TRACE( "%s %08x %p %p %p\n", str ? debugstr_wn(str->chars, str->length) : "null", flags, heap, ret, error ); if (error) FIXME( "ignoring error parameter\n" ); if (!str || !heap) return E_INVALIDARG; if (!str->length) return WS_E_INVALID_FORMAT; if (flags) { FIXME( "unimplemented flags %08x\n", flags ); return E_NOTIMPL; } if (!(decoded = url_decode( str->chars, str->length, heap, &len_decoded )) || !(url = ws_alloc( heap, sizeof(*url) ))) goto error; hr = WS_E_INVALID_FORMAT; p = q = decoded; len = len_decoded; while (len && *q != ':') { q++; len--; }; if (*q != ':') goto error; if ((url->url.scheme = scheme_type( p, q - p )) == ~0u) goto error; if (!--len || *++q != '/') goto error; if (!--len || *++q != '/') goto error; p = ++q; len--; while (len && *q != '/' && *q != ':' && *q != '?' && *q != '#') { q++; len--; }; if (q == p) goto error; url->host.length = q - p; url->host.chars = p; if (len && *q == ':') { p = ++q; len--; while (len && isdigitW( *q )) { if ((port = port * 10 + *q - '0') > 65535) goto error; q++; len--; }; url->port = port; url->portAsString.length = q - p; url->portAsString.chars = p; } if (!port) { url->port = default_port( url->url.scheme ); url->portAsString.length = 0; url->portAsString.chars = NULL; } if (len && *q == '/') { p = q; while (len && *q != '?') { q++; len--; }; url->path.length = q - p; url->path.chars = p; } else url->path.length = 0; if (len && *q == '?') { p = ++q; len--; while (len && *q != '#') { q++; len--; }; url->query.length = q - p; url->query.chars = p; } else url->query.length = 0; if (len && *q == '#') { p = ++q; len--; while (len && *q != '#') { q++; len--; }; url->fragment.length = q - p; url->fragment.chars = p; } else url->fragment.length = 0; *ret = (WS_URL *)url; return S_OK; error: if (decoded != str->chars) ws_free( heap, decoded, len_decoded ); ws_free( heap, url, sizeof(*url) ); return hr; }
//============================================================================= short Uri::get_port() const { return (m_port > 0) ? m_port : default_port(m_scheme); }