1104349Sphk#include "expat.h" 2104349Sphk#ifdef XML_UNICODE 3104349Sphk#define UNICODE 4104349Sphk#endif 5104349Sphk#include <windows.h> 6104349Sphk#include <urlmon.h> 7104349Sphk#include <wininet.h> 8104349Sphk#include <stdio.h> 9104349Sphk#include <tchar.h> 10104349Sphk#include "xmlurl.h" 11104349Sphk#include "xmlmime.h" 12104349Sphk 13104349Sphkstatic int 14104349SphkprocessURL(XML_Parser parser, IMoniker *baseMoniker, const XML_Char *url); 15104349Sphk 16104349Sphktypedef void (*StopHandler)(void *, HRESULT); 17104349Sphk 18104349Sphkclass Callback : public IBindStatusCallback { 19104349Sphkpublic: 20104349Sphk // IUnknown methods 21104349Sphk STDMETHODIMP QueryInterface(REFIID,void **); 22104349Sphk STDMETHODIMP_(ULONG) AddRef(); 23104349Sphk STDMETHODIMP_(ULONG) Release(); 24104349Sphk // IBindStatusCallback methods 25104349Sphk STDMETHODIMP OnStartBinding(DWORD, IBinding *); 26104349Sphk STDMETHODIMP GetPriority(LONG *); 27104349Sphk STDMETHODIMP OnLowResource(DWORD); 28104349Sphk STDMETHODIMP OnProgress(ULONG, ULONG, ULONG, LPCWSTR); 29104349Sphk STDMETHODIMP OnStopBinding(HRESULT, LPCWSTR); 30104349Sphk STDMETHODIMP GetBindInfo(DWORD *, BINDINFO *); 31104349Sphk STDMETHODIMP OnDataAvailable(DWORD, DWORD, FORMATETC *, STGMEDIUM *); 32104349Sphk STDMETHODIMP OnObjectAvailable(REFIID, IUnknown *); 33104349Sphk Callback(XML_Parser, IMoniker *, StopHandler, void *); 34104349Sphk ~Callback(); 35104349Sphk int externalEntityRef(const XML_Char *context, 36104349Sphk const XML_Char *systemId, const XML_Char *publicId); 37104349Sphkprivate: 38104349Sphk XML_Parser parser_; 39104349Sphk IMoniker *baseMoniker_; 40104349Sphk DWORD totalRead_; 41104349Sphk ULONG ref_; 42104349Sphk IBinding *pBinding_; 43104349Sphk StopHandler stopHandler_; 44104349Sphk void *stopArg_; 45104349Sphk}; 46104349Sphk 47104349SphkSTDMETHODIMP_(ULONG) 48104349SphkCallback::AddRef() 49104349Sphk{ 50104349Sphk return ref_++; 51104349Sphk} 52104349Sphk 53104349SphkSTDMETHODIMP_(ULONG) 54104349SphkCallback::Release() 55104349Sphk{ 56104349Sphk if (--ref_ == 0) { 57104349Sphk delete this; 58104349Sphk return 0; 59104349Sphk } 60104349Sphk return ref_; 61104349Sphk} 62104349Sphk 63104349SphkSTDMETHODIMP 64104349SphkCallback::QueryInterface(REFIID riid, void** ppv) 65104349Sphk{ 66104349Sphk if (IsEqualGUID(riid, IID_IUnknown)) 67104349Sphk *ppv = (IUnknown *)this; 68104349Sphk else if (IsEqualGUID(riid, IID_IBindStatusCallback)) 69104349Sphk *ppv = (IBindStatusCallback *)this; 70104349Sphk else 71104349Sphk return E_NOINTERFACE; 72104349Sphk ((LPUNKNOWN)*ppv)->AddRef(); 73104349Sphk return S_OK; 74104349Sphk} 75104349Sphk 76104349SphkSTDMETHODIMP 77104349SphkCallback::OnStartBinding(DWORD, IBinding* pBinding) 78104349Sphk{ 79104349Sphk pBinding_ = pBinding; 80104349Sphk pBinding->AddRef(); 81104349Sphk return S_OK; 82104349Sphk} 83104349Sphk 84104349SphkSTDMETHODIMP 85104349SphkCallback::GetPriority(LONG *) 86104349Sphk{ 87104349Sphk return E_NOTIMPL; 88104349Sphk} 89104349Sphk 90104349SphkSTDMETHODIMP 91104349SphkCallback::OnLowResource(DWORD) 92104349Sphk{ 93104349Sphk return E_NOTIMPL; 94104349Sphk} 95104349Sphk 96104349SphkSTDMETHODIMP 97104349SphkCallback::OnProgress(ULONG, ULONG, ULONG, LPCWSTR) 98104349Sphk{ 99104349Sphk return S_OK; 100104349Sphk} 101104349Sphk 102104349SphkSTDMETHODIMP 103104349SphkCallback::OnStopBinding(HRESULT hr, LPCWSTR szError) 104104349Sphk{ 105104349Sphk if (pBinding_) { 106104349Sphk pBinding_->Release(); 107104349Sphk pBinding_ = 0; 108104349Sphk } 109104349Sphk if (baseMoniker_) { 110104349Sphk baseMoniker_->Release(); 111104349Sphk baseMoniker_ = 0; 112104349Sphk } 113104349Sphk stopHandler_(stopArg_, hr); 114104349Sphk return S_OK; 115104349Sphk} 116104349Sphk 117104349SphkSTDMETHODIMP 118104349SphkCallback::GetBindInfo(DWORD* pgrfBINDF, BINDINFO* pbindinfo) 119104349Sphk{ 120104349Sphk *pgrfBINDF = BINDF_ASYNCHRONOUS; 121104349Sphk return S_OK; 122104349Sphk} 123104349Sphk 124104349Sphkstatic void 125104349SphkreportError(XML_Parser parser) 126104349Sphk{ 127104349Sphk int code = XML_GetErrorCode(parser); 128104349Sphk const XML_Char *message = XML_ErrorString(code); 129104349Sphk if (message) 130104349Sphk _ftprintf(stderr, _T("%s:%d:%ld: %s\n"), 131104349Sphk XML_GetBase(parser), 132104349Sphk XML_GetErrorLineNumber(parser), 133104349Sphk XML_GetErrorColumnNumber(parser), 134104349Sphk message); 135104349Sphk else 136104349Sphk _ftprintf(stderr, _T("%s: (unknown message %d)\n"), 137104349Sphk XML_GetBase(parser), code); 138104349Sphk} 139104349Sphk 140104349SphkSTDMETHODIMP 141104349SphkCallback::OnDataAvailable(DWORD grfBSCF, 142104349Sphk DWORD dwSize, 143104349Sphk FORMATETC *pfmtetc, 144104349Sphk STGMEDIUM* pstgmed) 145104349Sphk{ 146104349Sphk if (grfBSCF & BSCF_FIRSTDATANOTIFICATION) { 147104349Sphk IWinInetHttpInfo *hp; 148104349Sphk HRESULT hr = pBinding_->QueryInterface(IID_IWinInetHttpInfo, 149104349Sphk (void **)&hp); 150104349Sphk if (SUCCEEDED(hr)) { 151104349Sphk char contentType[1024]; 152104349Sphk DWORD bufSize = sizeof(contentType); 153104349Sphk DWORD flags = 0; 154104349Sphk contentType[0] = 0; 155104349Sphk hr = hp->QueryInfo(HTTP_QUERY_CONTENT_TYPE, contentType, 156104349Sphk &bufSize, 0, NULL); 157104349Sphk if (SUCCEEDED(hr)) { 158104349Sphk char charset[CHARSET_MAX]; 159104349Sphk getXMLCharset(contentType, charset); 160104349Sphk if (charset[0]) { 161104349Sphk#ifdef XML_UNICODE 162104349Sphk XML_Char wcharset[CHARSET_MAX]; 163104349Sphk XML_Char *p1 = wcharset; 164104349Sphk const char *p2 = charset; 165104349Sphk while ((*p1++ = (unsigned char)*p2++) != 0) 166104349Sphk ; 167104349Sphk XML_SetEncoding(parser_, wcharset); 168104349Sphk#else 169104349Sphk XML_SetEncoding(parser_, charset); 170104349Sphk#endif 171104349Sphk } 172104349Sphk } 173104349Sphk hp->Release(); 174104349Sphk } 175104349Sphk } 176104349Sphk if (!parser_) 177104349Sphk return E_ABORT; 178104349Sphk if (pstgmed->tymed == TYMED_ISTREAM) { 179104349Sphk while (totalRead_ < dwSize) { 180104349Sphk#define READ_MAX (64*1024) 181104349Sphk DWORD nToRead = dwSize - totalRead_; 182104349Sphk if (nToRead > READ_MAX) 183104349Sphk nToRead = READ_MAX; 184104349Sphk void *buf = XML_GetBuffer(parser_, nToRead); 185104349Sphk if (!buf) { 186104349Sphk _ftprintf(stderr, _T("out of memory\n")); 187104349Sphk return E_ABORT; 188104349Sphk } 189104349Sphk DWORD nRead; 190104349Sphk HRESULT hr = pstgmed->pstm->Read(buf, nToRead, &nRead); 191104349Sphk if (SUCCEEDED(hr)) { 192104349Sphk totalRead_ += nRead; 193104349Sphk if (!XML_ParseBuffer(parser_, 194104349Sphk nRead, 195104349Sphk (grfBSCF & BSCF_LASTDATANOTIFICATION) != 0 196104349Sphk && totalRead_ == dwSize)) { 197104349Sphk reportError(parser_); 198104349Sphk return E_ABORT; 199104349Sphk } 200104349Sphk } 201104349Sphk } 202104349Sphk } 203104349Sphk return S_OK; 204104349Sphk} 205104349Sphk 206104349SphkSTDMETHODIMP 207104349SphkCallback::OnObjectAvailable(REFIID, IUnknown *) 208104349Sphk{ 209104349Sphk return S_OK; 210104349Sphk} 211104349Sphk 212104349Sphkint 213104349SphkCallback::externalEntityRef(const XML_Char *context, 214104349Sphk const XML_Char *systemId, 215104349Sphk const XML_Char *publicId) 216104349Sphk{ 217104349Sphk XML_Parser entParser = XML_ExternalEntityParserCreate(parser_, context, 0); 218104349Sphk XML_SetBase(entParser, systemId); 219104349Sphk int ret = processURL(entParser, baseMoniker_, systemId); 220104349Sphk XML_ParserFree(entParser); 221104349Sphk return ret; 222104349Sphk} 223104349Sphk 224104349SphkCallback::Callback(XML_Parser parser, IMoniker *baseMoniker, 225104349Sphk StopHandler stopHandler, void *stopArg) 226104349Sphk: parser_(parser), 227104349Sphk baseMoniker_(baseMoniker), 228104349Sphk ref_(0), 229104349Sphk pBinding_(0), 230104349Sphk totalRead_(0), 231104349Sphk stopHandler_(stopHandler), 232104349Sphk stopArg_(stopArg) 233104349Sphk{ 234104349Sphk if (baseMoniker_) 235104349Sphk baseMoniker_->AddRef(); 236104349Sphk} 237104349Sphk 238104349SphkCallback::~Callback() 239104349Sphk{ 240104349Sphk if (pBinding_) 241104349Sphk pBinding_->Release(); 242104349Sphk if (baseMoniker_) 243104349Sphk baseMoniker_->Release(); 244104349Sphk} 245104349Sphk 246104349Sphkstatic int 247104349SphkexternalEntityRef(void *arg, 248104349Sphk const XML_Char *context, 249104349Sphk const XML_Char *base, 250104349Sphk const XML_Char *systemId, 251104349Sphk const XML_Char *publicId) 252104349Sphk{ 253104349Sphk return ((Callback *)arg)->externalEntityRef(context, systemId, publicId); 254104349Sphk} 255104349Sphk 256104349Sphk 257104349Sphkstatic HRESULT 258104349SphkopenStream(XML_Parser parser, 259104349Sphk IMoniker *baseMoniker, 260104349Sphk const XML_Char *uri, 261104349Sphk StopHandler stopHandler, void *stopArg) 262104349Sphk{ 263104349Sphk if (!XML_SetBase(parser, uri)) 264104349Sphk return E_OUTOFMEMORY; 265104349Sphk HRESULT hr; 266104349Sphk IMoniker *m; 267104349Sphk#ifdef XML_UNICODE 268104349Sphk hr = CreateURLMoniker(0, uri, &m); 269104349Sphk#else 270104349Sphk LPWSTR uriw = new wchar_t[strlen(uri) + 1]; 271104349Sphk for (int i = 0;; i++) { 272104349Sphk uriw[i] = uri[i]; 273104349Sphk if (uriw[i] == 0) 274104349Sphk break; 275104349Sphk } 276104349Sphk hr = CreateURLMoniker(baseMoniker, uriw, &m); 277104349Sphk delete [] uriw; 278104349Sphk#endif 279104349Sphk if (FAILED(hr)) 280104349Sphk return hr; 281104349Sphk IBindStatusCallback *cb = new Callback(parser, m, stopHandler, stopArg); 282104349Sphk XML_SetExternalEntityRefHandler(parser, externalEntityRef); 283104349Sphk XML_SetExternalEntityRefHandlerArg(parser, cb); 284104349Sphk cb->AddRef(); 285104349Sphk IBindCtx *b; 286104349Sphk if (FAILED(hr = CreateAsyncBindCtx(0, cb, 0, &b))) { 287104349Sphk cb->Release(); 288104349Sphk m->Release(); 289104349Sphk return hr; 290104349Sphk } 291104349Sphk cb->Release(); 292104349Sphk IStream *pStream; 293104349Sphk hr = m->BindToStorage(b, 0, IID_IStream, (void **)&pStream); 294104349Sphk if (SUCCEEDED(hr)) { 295104349Sphk if (pStream) 296104349Sphk pStream->Release(); 297104349Sphk } 298104349Sphk if (hr == MK_S_ASYNCHRONOUS) 299104349Sphk hr = S_OK; 300104349Sphk m->Release(); 301104349Sphk b->Release(); 302104349Sphk return hr; 303104349Sphk} 304104349Sphk 305104349Sphkstruct QuitInfo { 306104349Sphk const XML_Char *url; 307104349Sphk HRESULT hr; 308104349Sphk int stop; 309104349Sphk}; 310104349Sphk 311104349Sphkstatic void 312104349SphkwinPerror(const XML_Char *url, HRESULT hr) 313104349Sphk{ 314104349Sphk LPVOID buf; 315104349Sphk if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER 316104349Sphk | FORMAT_MESSAGE_FROM_HMODULE, 317104349Sphk GetModuleHandleA("urlmon.dll"), 318104349Sphk hr, 319104349Sphk MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), 320104349Sphk (LPTSTR) &buf, 321104349Sphk 0, 322104349Sphk NULL) 323104349Sphk || FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER 324104349Sphk | FORMAT_MESSAGE_FROM_SYSTEM, 325104349Sphk 0, 326104349Sphk hr, 327104349Sphk MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), 328104349Sphk (LPTSTR) &buf, 329104349Sphk 0, 330104349Sphk NULL)) { 331104349Sphk /* The system error messages seem to end with a newline. */ 332104349Sphk _ftprintf(stderr, _T("%s: %s"), url, buf); 333104349Sphk fflush(stderr); 334104349Sphk LocalFree(buf); 335104349Sphk } 336104349Sphk else 337104349Sphk _ftprintf(stderr, _T("%s: error %x\n"), url, hr); 338104349Sphk} 339104349Sphk 340104349Sphkstatic void 341104349SphkthreadQuit(void *p, HRESULT hr) 342104349Sphk{ 343104349Sphk QuitInfo *qi = (QuitInfo *)p; 344104349Sphk qi->hr = hr; 345104349Sphk qi->stop = 1; 346104349Sphk} 347104349Sphk 348104349Sphkextern "C" 349104349Sphkint 350104349SphkXML_URLInit(void) 351104349Sphk{ 352104349Sphk return SUCCEEDED(CoInitialize(0)); 353104349Sphk} 354104349Sphk 355104349Sphkextern "C" 356104349Sphkvoid 357104349SphkXML_URLUninit(void) 358104349Sphk{ 359104349Sphk CoUninitialize(); 360104349Sphk} 361104349Sphk 362104349Sphkstatic int 363104349SphkprocessURL(XML_Parser parser, IMoniker *baseMoniker, 364104349Sphk const XML_Char *url) 365104349Sphk{ 366104349Sphk QuitInfo qi; 367104349Sphk qi.stop = 0; 368104349Sphk qi.url = url; 369104349Sphk 370104349Sphk XML_SetBase(parser, url); 371104349Sphk HRESULT hr = openStream(parser, baseMoniker, url, threadQuit, &qi); 372104349Sphk if (FAILED(hr)) { 373104349Sphk winPerror(url, hr); 374104349Sphk return 0; 375104349Sphk } 376104349Sphk else if (FAILED(qi.hr)) { 377104349Sphk winPerror(url, qi.hr); 378104349Sphk return 0; 379104349Sphk } 380104349Sphk MSG msg; 381104349Sphk while (!qi.stop && GetMessage (&msg, NULL, 0, 0)) { 382104349Sphk TranslateMessage (&msg); 383104349Sphk DispatchMessage (&msg); 384104349Sphk } 385104349Sphk return 1; 386104349Sphk} 387104349Sphk 388104349Sphkextern "C" 389104349Sphkint 390104349SphkXML_ProcessURL(XML_Parser parser, 391104349Sphk const XML_Char *url, 392104349Sphk unsigned flags) 393104349Sphk{ 394104349Sphk return processURL(parser, 0, url); 395104349Sphk} 396