4 / _ \\ /| '_ \ / _` | __|
5 | __// \| |_) | (_| | |_
6 \___/_/\_\ .__/ \__,_|\__|
9 Copyright (c) 1997-2000 Thai Open Source Software Center Ltd
10 Copyright (c) 2000-2017 Expat development team
11 Licensed under the MIT license:
13 Permission is hereby granted, free of charge, to any person obtaining
14 a copy of this software and associated documentation files (the
15 "Software"), to deal in the Software without restriction, including
16 without limitation the rights to use, copy, modify, merge, publish,
17 distribute, sublicense, and/or sell copies of the Software, and to permit
18 persons to whom the Software is furnished to do so, subject to the
21 The above copyright notice and this permission notice shall be included
22 in all copies or substantial portions of the Software.
24 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
25 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
26 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
27 NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
28 DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
29 OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
30 USE OR OTHER DEALINGS IN THE SOFTWARE.
46 processURL(XML_Parser parser, IMoniker *baseMoniker, const XML_Char *url);
48 typedef void (*StopHandler)(void *, HRESULT);
50 class Callback : public IBindStatusCallback {
53 STDMETHODIMP QueryInterface(REFIID,void **);
54 STDMETHODIMP_(ULONG) AddRef();
55 STDMETHODIMP_(ULONG) Release();
56 // IBindStatusCallback methods
57 STDMETHODIMP OnStartBinding(DWORD, IBinding *);
58 STDMETHODIMP GetPriority(LONG *);
59 STDMETHODIMP OnLowResource(DWORD);
60 STDMETHODIMP OnProgress(ULONG, ULONG, ULONG, LPCWSTR);
61 STDMETHODIMP OnStopBinding(HRESULT, LPCWSTR);
62 STDMETHODIMP GetBindInfo(DWORD *, BINDINFO *);
63 STDMETHODIMP OnDataAvailable(DWORD, DWORD, FORMATETC *, STGMEDIUM *);
64 STDMETHODIMP OnObjectAvailable(REFIID, IUnknown *);
65 Callback(XML_Parser, IMoniker *, StopHandler, void *);
67 int externalEntityRef(const XML_Char *context,
68 const XML_Char *systemId, const XML_Char *publicId);
71 IMoniker *baseMoniker_;
75 StopHandler stopHandler_;
96 Callback::QueryInterface(REFIID riid, void** ppv)
98 if (IsEqualGUID(riid, IID_IUnknown))
99 *ppv = (IUnknown *)this;
100 else if (IsEqualGUID(riid, IID_IBindStatusCallback))
101 *ppv = (IBindStatusCallback *)this;
103 return E_NOINTERFACE;
104 ((LPUNKNOWN)*ppv)->AddRef();
109 Callback::OnStartBinding(DWORD, IBinding* pBinding)
111 pBinding_ = pBinding;
117 Callback::GetPriority(LONG *)
123 Callback::OnLowResource(DWORD)
129 Callback::OnProgress(ULONG, ULONG, ULONG, LPCWSTR)
135 Callback::OnStopBinding(HRESULT hr, LPCWSTR szError)
138 pBinding_->Release();
142 baseMoniker_->Release();
145 stopHandler_(stopArg_, hr);
150 Callback::GetBindInfo(DWORD* pgrfBINDF, BINDINFO* pbindinfo)
152 *pgrfBINDF = BINDF_ASYNCHRONOUS;
157 reportError(XML_Parser parser)
159 int code = XML_GetErrorCode(parser);
160 const XML_Char *message = XML_ErrorString(code);
162 _ftprintf(stderr, _T("%s:%d:%ld: %s\n"),
164 XML_GetErrorLineNumber(parser),
165 XML_GetErrorColumnNumber(parser),
168 _ftprintf(stderr, _T("%s: (unknown message %d)\n"),
169 XML_GetBase(parser), code);
173 Callback::OnDataAvailable(DWORD grfBSCF,
178 if (grfBSCF & BSCF_FIRSTDATANOTIFICATION) {
179 IWinInetHttpInfo *hp;
180 HRESULT hr = pBinding_->QueryInterface(IID_IWinInetHttpInfo,
183 char contentType[1024];
184 DWORD bufSize = sizeof(contentType);
187 hr = hp->QueryInfo(HTTP_QUERY_CONTENT_TYPE, contentType,
190 char charset[CHARSET_MAX];
191 getXMLCharset(contentType, charset);
194 XML_Char wcharset[CHARSET_MAX];
195 XML_Char *p1 = wcharset;
196 const char *p2 = charset;
197 while ((*p1++ = (unsigned char)*p2++) != 0)
199 XML_SetEncoding(parser_, wcharset);
201 XML_SetEncoding(parser_, charset);
210 if (pstgmed->tymed == TYMED_ISTREAM) {
211 while (totalRead_ < dwSize) {
212 #define READ_MAX (64*1024)
213 DWORD nToRead = dwSize - totalRead_;
214 if (nToRead > READ_MAX)
216 void *buf = XML_GetBuffer(parser_, nToRead);
218 _ftprintf(stderr, _T("out of memory\n"));
222 HRESULT hr = pstgmed->pstm->Read(buf, nToRead, &nRead);
225 if (!XML_ParseBuffer(parser_,
227 (grfBSCF & BSCF_LASTDATANOTIFICATION) != 0
228 && totalRead_ == dwSize)) {
229 reportError(parser_);
239 Callback::OnObjectAvailable(REFIID, IUnknown *)
245 Callback::externalEntityRef(const XML_Char *context,
246 const XML_Char *systemId,
247 const XML_Char *publicId)
249 XML_Parser entParser = XML_ExternalEntityParserCreate(parser_, context, 0);
250 XML_SetBase(entParser, systemId);
251 int ret = processURL(entParser, baseMoniker_, systemId);
252 XML_ParserFree(entParser);
256 Callback::Callback(XML_Parser parser, IMoniker *baseMoniker,
257 StopHandler stopHandler, void *stopArg)
259 baseMoniker_(baseMoniker),
263 stopHandler_(stopHandler),
267 baseMoniker_->AddRef();
270 Callback::~Callback()
273 pBinding_->Release();
275 baseMoniker_->Release();
279 externalEntityRef(void *arg,
280 const XML_Char *context,
281 const XML_Char *base,
282 const XML_Char *systemId,
283 const XML_Char *publicId)
285 return ((Callback *)arg)->externalEntityRef(context, systemId, publicId);
290 openStream(XML_Parser parser,
291 IMoniker *baseMoniker,
293 StopHandler stopHandler, void *stopArg)
295 if (!XML_SetBase(parser, uri))
296 return E_OUTOFMEMORY;
300 hr = CreateURLMoniker(0, uri, &m);
302 LPWSTR uriw = new wchar_t[strlen(uri) + 1];
303 for (int i = 0;; i++) {
308 hr = CreateURLMoniker(baseMoniker, uriw, &m);
313 IBindStatusCallback *cb = new Callback(parser, m, stopHandler, stopArg);
314 XML_SetExternalEntityRefHandler(parser, externalEntityRef);
315 XML_SetExternalEntityRefHandlerArg(parser, cb);
318 if (FAILED(hr = CreateAsyncBindCtx(0, cb, 0, &b))) {
325 hr = m->BindToStorage(b, 0, IID_IStream, (void **)&pStream);
330 if (hr == MK_S_ASYNCHRONOUS)
344 winPerror(const XML_Char *url, HRESULT hr)
347 if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER
348 | FORMAT_MESSAGE_FROM_HMODULE,
349 GetModuleHandleA("urlmon.dll"),
351 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
355 || FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER
356 | FORMAT_MESSAGE_FROM_SYSTEM,
359 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
363 /* The system error messages seem to end with a newline. */
364 _ftprintf(stderr, _T("%s: %s"), url, buf);
369 _ftprintf(stderr, _T("%s: error %x\n"), url, hr);
373 threadQuit(void *p, HRESULT hr)
375 QuitInfo *qi = (QuitInfo *)p;
384 return SUCCEEDED(CoInitialize(0));
395 processURL(XML_Parser parser, IMoniker *baseMoniker,
402 XML_SetBase(parser, url);
403 HRESULT hr = openStream(parser, baseMoniker, url, threadQuit, &qi);
408 else if (FAILED(qi.hr)) {
409 winPerror(url, qi.hr);
413 while (!qi.stop && GetMessage (&msg, NULL, 0, 0)) {
414 TranslateMessage (&msg);
415 DispatchMessage (&msg);
422 XML_ProcessURL(XML_Parser parser,
426 return processURL(parser, 0, url);