2 * Copyright 2005 Jacek Caban
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
25 #define NONAMELESSUNION
26 #define NONAMELESSSTRUCT
35 #include "wine/debug.h"
36 #include "wine/unicode.h"
38 #include "mshtml_private.h"
40 WINE_DEFAULT_DEBUG_CHANNEL(mshtml
);
42 #define USER_AGENT "User-Agent:"
43 #define CONTENT_TYPE "Content-Type:"
45 static int fix_headers(char *buf
, DWORD post_len
)
49 if(!strncasecmp(USER_AGENT
, buf
, sizeof(USER_AGENT
)-1)) {
52 ptr
= strstr(buf
, "\r\n" USER_AGENT
);
60 FIXME("Ignoring User-Agent header\n");
62 ptr2
= strstr(ptr
, "\r\n");
64 memmove(ptr
, ptr2
, strlen(ptr2
)+1);
68 if(!strncasecmp(CONTENT_TYPE
, buf
, sizeof(CONTENT_TYPE
)-1)) {
71 ptr
= strstr(buf
, "\r\n" CONTENT_TYPE
);
79 TRACE("Ignoring Content-Type header\n");
81 ptr2
= strstr(ptr
, "\r\n");
83 memmove(ptr
, ptr2
, strlen(ptr2
)+1);
90 static nsIInputStream
*get_post_data_stream(IBindCtx
*bctx
)
92 nsIInputStream
*ret
= NULL
;
94 IBindStatusCallback
*callback
;
95 IServiceProvider
*service_provider
;
98 DWORD post_len
= 0, headers_len
= 0;
99 LPWSTR headers
= NULL
;
100 WCHAR emptystr
[] = {0};
104 static WCHAR _BSCB_Holder_
[] =
105 {'_','B','S','C','B','_','H','o','l','d','e','r','_',0};
108 /* FIXME: This should be done in URLMoniker */
112 hres
= IBindCtx_GetObjectParam(bctx
, _BSCB_Holder_
, &unk
);
116 hres
= IUnknown_QueryInterface(unk
, &IID_IBindStatusCallback
, (void**)&callback
);
118 IUnknown_Release(unk
);
122 hres
= IUnknown_QueryInterface(unk
, &IID_IServiceProvider
, (void**)&service_provider
);
123 IUnknown_Release(unk
);
124 if(SUCCEEDED(hres
)) {
125 IHttpNegotiate
*http_negotiate
;
127 hres
= IServiceProvider_QueryService(service_provider
, &IID_IHttpNegotiate
, &IID_IHttpNegotiate
,
128 (void**)&http_negotiate
);
129 if(SUCCEEDED(hres
)) {
130 hres
= IHttpNegotiate_BeginningTransaction(http_negotiate
, emptystr
,
131 emptystr
, 0, &headers
);
132 IHttpNegotiate_Release(http_negotiate
);
134 if(SUCCEEDED(hres
) && headers
)
135 headers_len
= WideCharToMultiByte(CP_ACP
, 0, headers
, -1, NULL
, 0, NULL
, NULL
);
138 IServiceProvider_Release(service_provider
);
141 memset(&bindinfo
, 0, sizeof(bindinfo
));
142 bindinfo
.cbSize
= sizeof(bindinfo
);
144 hres
= IBindStatusCallback_GetBindInfo(callback
, &bindf
, &bindinfo
);
146 if(SUCCEEDED(hres
) && bindinfo
.dwBindVerb
== BINDVERB_POST
)
147 post_len
= bindinfo
.cbstgmedData
;
149 if(headers_len
|| post_len
) {
152 static const char content_length
[] = "Content-Length: %u\r\n\r\n";
154 data
= heap_alloc(headers_len
+post_len
+sizeof(content_length
)+8);
157 WideCharToMultiByte(CP_ACP
, 0, headers
, -1, data
, -1, NULL
, NULL
);
158 len
= fix_headers(data
, post_len
);
162 if(len
>= 4 && !strcmp(data
+len
-4, "\r\n\r\n"))
165 sprintf(data
+len
, content_length
, post_len
);
168 memcpy(data
+len
, bindinfo
.stgmedData
.u
.hGlobal
, post_len
);
171 TRACE("data = %s\n", debugstr_an(data
, len
+post_len
));
173 ret
= create_nsstream(data
, len
+post_len
);
176 CoTaskMemFree(headers
);
177 ReleaseBindInfo(&bindinfo
);
178 IBindStatusCallback_Release(callback
);
183 void set_current_mon(HTMLDocument
*This
, IMoniker
*mon
)
188 IMoniker_Release(This
->mon
);
193 CoTaskMemFree(This
->url
);
200 IMoniker_AddRef(mon
);
203 hres
= IMoniker_GetDisplayName(mon
, NULL
, NULL
, &This
->url
);
205 WARN("GetDisplayName failed: %08x\n", hres
);
208 static HRESULT
set_moniker(HTMLDocument
*This
, IMoniker
*mon
, IBindCtx
*pibc
, BOOL
*bind_complete
)
210 BSCallback
*bscallback
;
217 IUnknown
*unk
= NULL
;
221 * "__PrecreatedObject"
222 * "BIND_CONTEXT_PARAM"
223 * "__HTMLLOADOPTIONS"
227 * "_ITransData_Object_"
231 IBindCtx_GetObjectParam(pibc
, (LPOLESTR
)SZ_HTML_CLIENTSITE_OBJECTPARAM
, &unk
);
233 IOleClientSite
*client
= NULL
;
235 hres
= IUnknown_QueryInterface(unk
, &IID_IOleClientSite
, (void**)&client
);
236 if(SUCCEEDED(hres
)) {
237 TRACE("Got client site %p\n", client
);
238 IOleObject_SetClientSite(OLEOBJ(This
), client
);
239 IOleClientSite_Release(client
);
242 IUnknown_Release(unk
);
246 This
->readystate
= READYSTATE_LOADING
;
247 call_property_onchanged(&This
->cp_propnotif
, DISPID_READYSTATE
);
248 update_doc(This
, UPDATE_TITLE
);
250 HTMLDocument_LockContainer(This
, TRUE
);
252 hres
= IMoniker_GetDisplayName(mon
, pibc
, NULL
, &url
);
254 WARN("GetDiaplayName failed: %08x\n", hres
);
258 TRACE("got url: %s\n", debugstr_w(url
));
260 set_current_mon(This
, mon
);
263 VARIANT silent
, offline
;
264 IOleCommandTarget
*cmdtrg
= NULL
;
266 hres
= get_client_disp_property(This
->client
, DISPID_AMBIENT_SILENT
, &silent
);
267 if(SUCCEEDED(hres
)) {
268 if(V_VT(&silent
) != VT_BOOL
)
269 WARN("V_VT(silent) = %d\n", V_VT(&silent
));
270 else if(V_BOOL(&silent
))
271 FIXME("silent == true\n");
274 hres
= get_client_disp_property(This
->client
,
275 DISPID_AMBIENT_OFFLINEIFNOTCONNECTED
, &offline
);
276 if(SUCCEEDED(hres
)) {
277 if(V_VT(&silent
) != VT_BOOL
)
278 WARN("V_VT(offline) = %d\n", V_VT(&silent
));
279 else if(V_BOOL(&silent
))
280 FIXME("offline == true\n");
283 hres
= IOleClientSite_QueryInterface(This
->client
, &IID_IOleCommandTarget
,
285 if(SUCCEEDED(hres
)) {
290 IOleCommandTarget_Exec(cmdtrg
, &CGID_ShellDocView
, 37, 0, &var
, NULL
);
292 IOleCommandTarget_Release(cmdtrg
);
296 bscallback
= create_bscallback(mon
);
299 task
= heap_alloc(sizeof(task_t
));
302 task
->task_id
= TASK_SETPROGRESS
;
308 task
= heap_alloc(sizeof(task_t
));
311 task
->task_id
= TASK_SETDOWNLOADSTATE
;
316 if(This
->nscontainer
) {
317 nsIInputStream
*post_data_stream
= get_post_data_stream(pibc
);
319 This
->nscontainer
->bscallback
= bscallback
;
320 nsres
= nsIWebNavigation_LoadURI(This
->nscontainer
->navigation
, url
,
321 LOAD_FLAGS_NONE
, NULL
, post_data_stream
, NULL
);
322 This
->nscontainer
->bscallback
= NULL
;
325 nsIInputStream_Release(post_data_stream
);
327 if(NS_SUCCEEDED(nsres
)) {
328 /* FIXME: don't return here (URL Moniker needs to be good enough) */
330 IBindStatusCallback_Release(STATUSCLB(bscallback
));
334 *bind_complete
= TRUE
;
336 }else if(nsres
!= WINE_NS_LOAD_FROM_MONIKER
) {
337 WARN("LoadURI failed: %08x\n", nsres
);
341 set_document_bscallback(This
, bscallback
);
342 IBindStatusCallback_Release(STATUSCLB(bscallback
));
346 *bind_complete
= FALSE
;
350 static HRESULT
get_doc_string(HTMLDocument
*This
, char **str
, DWORD
*len
)
352 nsIDOMDocument
*nsdoc
;
358 if(!This
->nscontainer
) {
359 WARN("no nscontainer, returning NULL\n");
363 nsres
= nsIWebNavigation_GetDocument(This
->nscontainer
->navigation
, &nsdoc
);
364 if(NS_FAILED(nsres
)) {
365 ERR("GetDocument failed: %08x\n", nsres
);
369 nsres
= nsIDOMDocument_QueryInterface(nsdoc
, &IID_nsIDOMNode
, (void**)&nsnode
);
370 nsIDOMDocument_Release(nsdoc
);
371 if(NS_FAILED(nsres
)) {
372 ERR("Could not get nsIDOMNode failed: %08x\n", nsres
);
376 nsAString_Init(&nsstr
, NULL
);
377 nsnode_to_nsstring(nsnode
, &nsstr
);
378 nsIDOMNode_Release(nsnode
);
380 nsAString_GetData(&nsstr
, &strw
);
381 TRACE("%s\n", debugstr_w(strw
));
383 *len
= WideCharToMultiByte(CP_ACP
, 0, strw
, -1, NULL
, 0, NULL
, NULL
);
384 *str
= heap_alloc(*len
);
385 WideCharToMultiByte(CP_ACP
, 0, strw
, -1, *str
, *len
, NULL
, NULL
);
387 nsAString_Finish(&nsstr
);
393 /**********************************************************
394 * IPersistMoniker implementation
397 #define PERSISTMON_THIS(iface) DEFINE_THIS(HTMLDocument, PersistMoniker, iface)
399 static HRESULT WINAPI
PersistMoniker_QueryInterface(IPersistMoniker
*iface
, REFIID riid
,
402 HTMLDocument
*This
= PERSISTMON_THIS(iface
);
403 return IHTMLDocument2_QueryInterface(HTMLDOC(This
), riid
, ppvObject
);
406 static ULONG WINAPI
PersistMoniker_AddRef(IPersistMoniker
*iface
)
408 HTMLDocument
*This
= PERSISTMON_THIS(iface
);
409 return IHTMLDocument2_AddRef(HTMLDOC(This
));
412 static ULONG WINAPI
PersistMoniker_Release(IPersistMoniker
*iface
)
414 HTMLDocument
*This
= PERSISTMON_THIS(iface
);
415 return IHTMLDocument2_Release(HTMLDOC(This
));
418 static HRESULT WINAPI
PersistMoniker_GetClassID(IPersistMoniker
*iface
, CLSID
*pClassID
)
420 HTMLDocument
*This
= PERSISTMON_THIS(iface
);
421 return IPersist_GetClassID(PERSIST(This
), pClassID
);
424 static HRESULT WINAPI
PersistMoniker_IsDirty(IPersistMoniker
*iface
)
426 HTMLDocument
*This
= PERSISTMON_THIS(iface
);
428 TRACE("(%p)\n", This
);
430 return IPersistStreamInit_IsDirty(PERSTRINIT(This
));
433 static HRESULT WINAPI
PersistMoniker_Load(IPersistMoniker
*iface
, BOOL fFullyAvailable
,
434 IMoniker
*pimkName
, LPBC pibc
, DWORD grfMode
)
436 HTMLDocument
*This
= PERSISTMON_THIS(iface
);
437 BOOL bind_complete
= FALSE
;
440 TRACE("(%p)->(%x %p %p %08x)\n", This
, fFullyAvailable
, pimkName
, pibc
, grfMode
);
442 hres
= set_moniker(This
, pimkName
, pibc
, &bind_complete
);
447 return start_binding(This
, This
->bscallback
, pibc
);
452 static HRESULT WINAPI
PersistMoniker_Save(IPersistMoniker
*iface
, IMoniker
*pimkName
,
453 LPBC pbc
, BOOL fRemember
)
455 HTMLDocument
*This
= PERSISTMON_THIS(iface
);
456 FIXME("(%p)->(%p %p %x)\n", This
, pimkName
, pbc
, fRemember
);
460 static HRESULT WINAPI
PersistMoniker_SaveCompleted(IPersistMoniker
*iface
, IMoniker
*pimkName
, LPBC pibc
)
462 HTMLDocument
*This
= PERSISTMON_THIS(iface
);
463 FIXME("(%p)->(%p %p)\n", This
, pimkName
, pibc
);
467 static HRESULT WINAPI
PersistMoniker_GetCurMoniker(IPersistMoniker
*iface
, IMoniker
**ppimkName
)
469 HTMLDocument
*This
= PERSISTMON_THIS(iface
);
471 TRACE("(%p)->(%p)\n", This
, ppimkName
);
476 IMoniker_AddRef(This
->mon
);
477 *ppimkName
= This
->mon
;
481 static const IPersistMonikerVtbl PersistMonikerVtbl
= {
482 PersistMoniker_QueryInterface
,
483 PersistMoniker_AddRef
,
484 PersistMoniker_Release
,
485 PersistMoniker_GetClassID
,
486 PersistMoniker_IsDirty
,
489 PersistMoniker_SaveCompleted
,
490 PersistMoniker_GetCurMoniker
493 /**********************************************************
494 * IMonikerProp implementation
497 #define MONPROP_THIS(iface) DEFINE_THIS(HTMLDocument, MonikerProp, iface)
499 static HRESULT WINAPI
MonikerProp_QueryInterface(IMonikerProp
*iface
, REFIID riid
, void **ppvObject
)
501 HTMLDocument
*This
= MONPROP_THIS(iface
);
502 return IHTMLDocument2_QueryInterface(HTMLDOC(This
), riid
, ppvObject
);
505 static ULONG WINAPI
MonikerProp_AddRef(IMonikerProp
*iface
)
507 HTMLDocument
*This
= MONPROP_THIS(iface
);
508 return IHTMLDocument2_AddRef(HTMLDOC(This
));
511 static ULONG WINAPI
MonikerProp_Release(IMonikerProp
*iface
)
513 HTMLDocument
*This
= MONPROP_THIS(iface
);
514 return IHTMLDocument_Release(HTMLDOC(This
));
517 static HRESULT WINAPI
MonikerProp_PutProperty(IMonikerProp
*iface
, MONIKERPROPERTY mkp
, LPCWSTR val
)
519 HTMLDocument
*This
= MONPROP_THIS(iface
);
521 TRACE("(%p)->(%d %s)\n", This
, mkp
, debugstr_w(val
));
525 heap_free(This
->mime
);
526 This
->mime
= heap_strdupW(val
);
533 FIXME("mkp %d\n", mkp
);
540 static const IMonikerPropVtbl MonikerPropVtbl
= {
541 MonikerProp_QueryInterface
,
544 MonikerProp_PutProperty
547 /**********************************************************
548 * IPersistFile implementation
551 #define PERSISTFILE_THIS(iface) DEFINE_THIS(HTMLDocument, PersistFile, iface)
553 static HRESULT WINAPI
PersistFile_QueryInterface(IPersistFile
*iface
, REFIID riid
, void **ppvObject
)
555 HTMLDocument
*This
= PERSISTFILE_THIS(iface
);
556 return IHTMLDocument2_QueryInterface(HTMLDOC(This
), riid
, ppvObject
);
559 static ULONG WINAPI
PersistFile_AddRef(IPersistFile
*iface
)
561 HTMLDocument
*This
= PERSISTFILE_THIS(iface
);
562 return IHTMLDocument2_AddRef(HTMLDOC(This
));
565 static ULONG WINAPI
PersistFile_Release(IPersistFile
*iface
)
567 HTMLDocument
*This
= PERSISTFILE_THIS(iface
);
568 return IHTMLDocument2_Release(HTMLDOC(This
));
571 static HRESULT WINAPI
PersistFile_GetClassID(IPersistFile
*iface
, CLSID
*pClassID
)
573 HTMLDocument
*This
= PERSISTFILE_THIS(iface
);
575 TRACE("(%p)->(%p)\n", This
, pClassID
);
580 memcpy(pClassID
, &CLSID_HTMLDocument
, sizeof(CLSID
));
584 static HRESULT WINAPI
PersistFile_IsDirty(IPersistFile
*iface
)
586 HTMLDocument
*This
= PERSISTFILE_THIS(iface
);
588 TRACE("(%p)\n", This
);
590 return IPersistStreamInit_IsDirty(PERSTRINIT(This
));
593 static HRESULT WINAPI
PersistFile_Load(IPersistFile
*iface
, LPCOLESTR pszFileName
, DWORD dwMode
)
595 HTMLDocument
*This
= PERSISTFILE_THIS(iface
);
596 FIXME("(%p)->(%s %08x)\n", This
, debugstr_w(pszFileName
), dwMode
);
600 static HRESULT WINAPI
PersistFile_Save(IPersistFile
*iface
, LPCOLESTR pszFileName
, BOOL fRemember
)
602 HTMLDocument
*This
= PERSISTFILE_THIS(iface
);
604 DWORD len
, written
=0;
608 TRACE("(%p)->(%s %x)\n", This
, debugstr_w(pszFileName
), fRemember
);
610 file
= CreateFileW(pszFileName
, GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
,
611 FILE_ATTRIBUTE_NORMAL
, NULL
);
612 if(file
== INVALID_HANDLE_VALUE
) {
613 WARN("Could not create file: %u\n", GetLastError());
617 hres
= get_doc_string(This
, &str
, &len
);
621 WriteFile(file
, str
, len
, &written
, NULL
);
626 static HRESULT WINAPI
PersistFile_SaveCompleted(IPersistFile
*iface
, LPCOLESTR pszFileName
)
628 HTMLDocument
*This
= PERSISTFILE_THIS(iface
);
629 FIXME("(%p)->(%s)\n", This
, debugstr_w(pszFileName
));
633 static HRESULT WINAPI
PersistFile_GetCurFile(IPersistFile
*iface
, LPOLESTR
*pszFileName
)
635 HTMLDocument
*This
= PERSISTFILE_THIS(iface
);
636 FIXME("(%p)->(%p)\n", This
, pszFileName
);
640 static const IPersistFileVtbl PersistFileVtbl
= {
641 PersistFile_QueryInterface
,
644 PersistFile_GetClassID
,
648 PersistFile_SaveCompleted
,
649 PersistFile_GetCurFile
652 #define PERSTRINIT_THIS(iface) DEFINE_THIS(HTMLDocument, PersistStreamInit, iface)
654 static HRESULT WINAPI
PersistStreamInit_QueryInterface(IPersistStreamInit
*iface
,
655 REFIID riid
, void **ppv
)
657 HTMLDocument
*This
= PERSTRINIT_THIS(iface
);
658 return IHTMLDocument2_QueryInterface(HTMLDOC(This
), riid
, ppv
);
661 static ULONG WINAPI
PersistStreamInit_AddRef(IPersistStreamInit
*iface
)
663 HTMLDocument
*This
= PERSTRINIT_THIS(iface
);
664 return IHTMLDocument2_AddRef(HTMLDOC(This
));
667 static ULONG WINAPI
PersistStreamInit_Release(IPersistStreamInit
*iface
)
669 HTMLDocument
*This
= PERSTRINIT_THIS(iface
);
670 return IHTMLDocument2_Release(HTMLDOC(This
));
673 static HRESULT WINAPI
PersistStreamInit_GetClassID(IPersistStreamInit
*iface
, CLSID
*pClassID
)
675 HTMLDocument
*This
= PERSTRINIT_THIS(iface
);
676 return IPersist_GetClassID(PERSIST(This
), pClassID
);
679 static HRESULT WINAPI
PersistStreamInit_IsDirty(IPersistStreamInit
*iface
)
681 HTMLDocument
*This
= PERSTRINIT_THIS(iface
);
683 TRACE("(%p)\n", This
);
685 if(This
->usermode
== EDITMODE
)
686 return editor_is_dirty(This
);
691 static HRESULT WINAPI
PersistStreamInit_Load(IPersistStreamInit
*iface
, LPSTREAM pStm
)
693 HTMLDocument
*This
= PERSTRINIT_THIS(iface
);
697 static const WCHAR about_blankW
[] = {'a','b','o','u','t',':','b','l','a','n','k',0};
699 TRACE("(%p)->(%p)\n", This
, pStm
);
701 hres
= CreateURLMoniker(NULL
, about_blankW
, &mon
);
703 WARN("CreateURLMoniker failed: %08x\n", hres
);
707 hres
= set_moniker(This
, mon
, NULL
, NULL
);
708 IMoniker_Release(mon
);
712 return load_stream(This
->bscallback
, pStm
);
715 static HRESULT WINAPI
PersistStreamInit_Save(IPersistStreamInit
*iface
, LPSTREAM pStm
,
718 HTMLDocument
*This
= PERSTRINIT_THIS(iface
);
720 DWORD len
, written
=0;
723 TRACE("(%p)->(%p %x)\n", This
, pStm
, fClearDirty
);
725 hres
= get_doc_string(This
, &str
, &len
);
729 hres
= IStream_Write(pStm
, str
, len
, &written
);
731 FIXME("Write failed: %08x\n", hres
);
736 set_dirty(This
, VARIANT_FALSE
);
741 static HRESULT WINAPI
PersistStreamInit_GetSizeMax(IPersistStreamInit
*iface
,
742 ULARGE_INTEGER
*pcbSize
)
744 HTMLDocument
*This
= PERSTRINIT_THIS(iface
);
745 FIXME("(%p)->(%p)\n", This
, pcbSize
);
749 static HRESULT WINAPI
PersistStreamInit_InitNew(IPersistStreamInit
*iface
)
751 HTMLDocument
*This
= PERSTRINIT_THIS(iface
);
752 FIXME("(%p)\n", This
);
756 #undef PERSTRINIT_THIS
758 static const IPersistStreamInitVtbl PersistStreamInitVtbl
= {
759 PersistStreamInit_QueryInterface
,
760 PersistStreamInit_AddRef
,
761 PersistStreamInit_Release
,
762 PersistStreamInit_GetClassID
,
763 PersistStreamInit_IsDirty
,
764 PersistStreamInit_Load
,
765 PersistStreamInit_Save
,
766 PersistStreamInit_GetSizeMax
,
767 PersistStreamInit_InitNew
770 void HTMLDocument_Persist_Init(HTMLDocument
*This
)
772 This
->lpPersistMonikerVtbl
= &PersistMonikerVtbl
;
773 This
->lpPersistFileVtbl
= &PersistFileVtbl
;
774 This
->lpMonikerPropVtbl
= &MonikerPropVtbl
;
775 This
->lpPersistStreamInitVtbl
= &PersistStreamInitVtbl
;
777 This
->bscallback
= NULL
;