2 * Copyright 2016 Hans Leidekker for CodeWeavers
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
24 #include "webservices.h"
26 #include "wine/debug.h"
27 #include "wine/list.h"
28 #include "wine/unicode.h"
29 #include "webservices_private.h"
31 WINE_DEFAULT_DEBUG_CHANNEL(webservices
);
33 static const WCHAR http
[] = {'h','t','t','p'};
34 static const WCHAR https
[] = {'h','t','t','p','s'};
35 static const WCHAR nettcp
[] = {'n','e','t','.','t','c','p'};
36 static const WCHAR soapudp
[] = {'s','o','a','p','.','u','d','p'};
37 static const WCHAR netpipe
[] = {'n','e','t','.','p','i','p','e'};
39 static WS_URL_SCHEME_TYPE
scheme_type( const WCHAR
*str
, ULONG len
)
41 if (len
== sizeof(http
)/sizeof(http
[0]) && !memicmpW( str
, http
, sizeof(http
)/sizeof(http
[0]) ))
42 return WS_URL_HTTP_SCHEME_TYPE
;
44 if (len
== sizeof(https
)/sizeof(https
[0]) && !memicmpW( str
, https
, sizeof(https
)/sizeof(https
[0]) ))
45 return WS_URL_HTTPS_SCHEME_TYPE
;
47 if (len
== sizeof(nettcp
)/sizeof(nettcp
[0]) && !memicmpW( str
, nettcp
, sizeof(nettcp
)/sizeof(nettcp
[0]) ))
48 return WS_URL_NETTCP_SCHEME_TYPE
;
50 if (len
== sizeof(soapudp
)/sizeof(soapudp
[0]) && !memicmpW( str
, soapudp
, sizeof(soapudp
)/sizeof(soapudp
[0]) ))
51 return WS_URL_SOAPUDP_SCHEME_TYPE
;
53 if (len
== sizeof(netpipe
)/sizeof(netpipe
[0]) && !memicmpW( str
, netpipe
, sizeof(netpipe
)/sizeof(netpipe
[0]) ))
54 return WS_URL_NETPIPE_SCHEME_TYPE
;
59 static USHORT
default_port( WS_URL_SCHEME_TYPE scheme
)
63 case WS_URL_HTTP_SCHEME_TYPE
: return 80;
64 case WS_URL_HTTPS_SCHEME_TYPE
: return 443;
65 case WS_URL_NETTCP_SCHEME_TYPE
: return 808;
66 case WS_URL_SOAPUDP_SCHEME_TYPE
:
67 case WS_URL_NETPIPE_SCHEME_TYPE
: return 65535;
69 ERR( "unhandled scheme %u\n", scheme
);
74 static WCHAR
*url_decode( WCHAR
*str
, ULONG len
, WS_HEAP
*heap
, ULONG
*ret_len
)
76 WCHAR
*p
= str
, *q
, *ret
;
81 for (i
= 0; i
< len
; i
++, p
++)
83 if ((len
- i
) < 3) break;
84 if (p
[0] == '%' && isxdigitW( p
[1] ) && isxdigitW( p
[2] ))
90 if (!decode
) return str
;
92 if (!(q
= ret
= ws_alloc( heap
, *ret_len
* sizeof(WCHAR
) ))) return NULL
;
96 if (len
>= 3 && p
[0] == '%' && isxdigitW( p
[1] ) && isxdigitW( p
[2] ))
98 if (p
[1] >= '0' && p
[1] <= '9') val
= (p
[1] - '0') * 16;
99 else if (p
[1] >= 'a' && p
[1] <= 'f') val
= (p
[1] - 'a') * 16;
100 else val
= (p
[1] - 'A') * 16;
102 if (p
[2] >= '0' && p
[2] <= '9') val
+= p
[2] - '0';
103 else if (p
[1] >= 'a' && p
[1] <= 'f') val
+= p
[2] - 'a';
104 else val
+= p
[1] - 'A';
120 /**************************************************************************
121 * WsDecodeUrl [webservices.@]
123 HRESULT WINAPI
WsDecodeUrl( const WS_STRING
*str
, ULONG flags
, WS_HEAP
*heap
, WS_URL
**ret
,
126 HRESULT hr
= WS_E_QUOTA_EXCEEDED
;
127 WCHAR
*p
, *q
, *decoded
= NULL
;
128 WS_HTTP_URL
*url
= NULL
;
131 TRACE( "%s %08x %p %p %p\n", str
? debugstr_wn(str
->chars
, str
->length
) : "null", flags
,
133 if (error
) FIXME( "ignoring error parameter\n" );
135 if (!str
|| !heap
) return E_INVALIDARG
;
136 if (!str
->length
) return WS_E_INVALID_FORMAT
;
139 FIXME( "unimplemented flags %08x\n", flags
);
142 if (!(decoded
= url_decode( str
->chars
, str
->length
, heap
, &len
)) ||
143 !(url
= ws_alloc( heap
, sizeof(*url
) ))) goto error
;
145 hr
= WS_E_INVALID_FORMAT
;
148 while (len
&& *q
!= ':') { q
++; len
--; };
149 if (*q
!= ':') goto error
;
150 if ((url
->url
.scheme
= scheme_type( p
, q
- p
)) == ~0u) goto error
;
152 if (!--len
|| *++q
!= '/') goto error
;
153 if (!--len
|| *++q
!= '/') goto error
;
156 while (len
&& *q
!= '/' && *q
!= ':' && *q
!= '?' && *q
!= '#') { q
++; len
--; };
157 if (q
== p
) goto error
;
158 url
->host
.length
= q
- p
;
161 if (len
&& *q
== ':')
164 while (len
&& isdigitW( *q
))
166 if ((port
= port
* 10 + *q
- '0') > 65535) goto error
;
170 url
->portAsString
.length
= q
- p
;
171 url
->portAsString
.chars
= p
;
175 url
->port
= default_port( url
->url
.scheme
);
176 url
->portAsString
.length
= 0;
177 url
->portAsString
.chars
= NULL
;
180 if (len
&& *q
== '/')
183 while (len
&& *q
!= '?') { q
++; len
--; };
184 url
->path
.length
= q
- p
;
187 else url
->path
.length
= 0;
189 if (len
&& *q
== '?')
192 while (len
&& *q
!= '#') { q
++; len
--; };
193 url
->query
.length
= q
- p
;
194 url
->query
.chars
= p
;
196 else url
->query
.length
= 0;
198 if (len
&& *q
== '#')
201 while (len
&& *q
!= '#') { q
++; len
--; };
202 url
->fragment
.length
= q
- p
;
203 url
->fragment
.chars
= p
;
205 else url
->fragment
.length
= 0;
207 *ret
= (WS_URL
*)url
;
211 if (decoded
!= str
->chars
) ws_free( heap
, decoded
);
212 ws_free( heap
, url
);