Back to index

lightning-sunbird  0.9+nobinonly
nsWebDAVService.cpp
Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
00002 // vim:expandtab:ts=4 sw=4:
00003 /* ***** BEGIN LICENSE BLOCK *****
00004  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00005  *
00006  * The contents of this file are subject to the Mozilla Public License Version
00007  * 1.1 (the "License"); you may not use this file except in compliance with
00008  * the License. You may obtain a copy of the License at
00009  * http://www.mozilla.org/MPL/
00010  *
00011  * Software distributed under the License is distributed on an "AS IS" basis,
00012  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00013  * for the specific language governing rights and limitations under the
00014  * License.
00015  *
00016  * The Original Code is Mozilla.
00017  *
00018  * The Initial Developer of the Original Code is
00019  * Oracle Corporation.
00020  * Portions created by the Initial Developer are Copyright (C) 2004
00021  * the Initial Developer. All Rights Reserved.
00022  *
00023  * Contributor(s):
00024  *   Mike Shaver <shaver@off.net> (original author)
00025  *   Gary van der Merwe <garyvdm@gmail.com>
00026  *
00027  * Alternatively, the contents of this file may be used under the terms of
00028  * either the GNU General Public License Version 2 or later (the "GPL"), or
00029  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00030  * in which case the provisions of the GPL or the LGPL are applicable instead
00031  * of those above. If you wish to allow use of your version of this file only
00032  * under the terms of either the GPL or the LGPL, and not to allow others to
00033  * use your version of this file under the terms of the MPL, indicate your
00034  * decision by deleting the provisions above and replace them with the notice
00035  * and other provisions required by the GPL or the LGPL. If you do not delete
00036  * the provisions above, a recipient may use your version of this file under
00037  * the terms of any one of the MPL, the GPL or the LGPL.
00038  *
00039  * ***** END LICENSE BLOCK ***** */
00040 
00041 #include "nsWebDAVInternal.h"
00042 
00043 #include "nsIWebDAVService.h"
00044 #include "nsWebDAVServiceCID.h"
00045 
00046 #include "nsServiceManagerUtils.h"
00047 
00048 #include "nsIHttpChannel.h"
00049 #include "nsIIOService.h"
00050 #include "nsNetUtil.h"
00051 #include "nsIStorageStream.h"
00052 #include "nsIUploadChannel.h"
00053 #include "nsIURL.h"
00054 
00055 #include "nsContentCID.h"
00056 
00057 #include "nsIDOMXMLDocument.h"
00058 #include "nsIDOMElement.h"
00059 #include "nsIDOMNodeList.h"
00060 #include "nsIDOM3Node.h"
00061 #include "nsIPrivateDOMImplementation.h" // I don't even pretend any more
00062 #include "nsIDOMDOMImplementation.h"
00063 
00064 #include "nsIDocument.h"
00065 #include "nsIDocumentEncoder.h"
00066 #include "nsContentCID.h"
00067 
00068 #include "nsIDOMParser.h"
00069 
00070 #include "nsIGenericFactory.h"
00071 
00072 class nsWebDAVService : public nsIWebDAVService
00073 {
00074 public:
00075     NS_DECL_ISUPPORTS
00076     NS_DECL_NSIWEBDAVSERVICE
00077     
00078     nsWebDAVService();
00079     virtual ~nsWebDAVService();
00080 protected:
00081     nsresult EnsureIOService();
00082     nsresult ChannelFromResource(nsIWebDAVResource *resource,
00083                                  nsIInterfaceRequestor *notificationCallbacks,
00084                                  nsIHttpChannel** channel,
00085                                  nsIURI ** resourceURI = 0);
00086 
00087     nsresult CreatePropfindDocument(nsIURI *resourceURI,
00088                                     nsIDOMDocument **requestDoc,
00089                                     nsIDOMElement **propfindElt);
00090 
00091     nsresult PropfindInternal(nsIWebDAVResource *resource, PRUint32 propCount,
00092                               const char **properties, PRBool withDepth,
00093                               nsIWebDAVOperationListener *listener,
00094                               nsIInterfaceRequestor *notificationCallbacks,
00095                               nsISupports *closure, PRBool namesOnly);
00096 
00097     nsresult SendDocumentToChannel(nsIDocument *doc, nsIHttpChannel *channel,
00098                                    const char *const method,
00099                                    nsIStreamListener *listener,
00100                                    PRBool withDepth);
00101     nsCOMPtr<nsIIOService> mIOService; // XXX weak?
00102     nsAutoString mDAVNSString; // "DAV:"
00103 };
00104 
00105 NS_IMPL_ISUPPORTS1_CI(nsWebDAVService, nsIWebDAVService)
00106 
00107 #define ENSURE_IO_SERVICE()                     \
00108 {                                               \
00109     nsresult rv_ = EnsureIOService();           \
00110     NS_ENSURE_SUCCESS(rv_, rv_);                \
00111 }
00112 
00113 nsresult
00114 nsWebDAVService::EnsureIOService()
00115 {
00116     if (!mIOService) {
00117         nsresult rv;
00118         mIOService = do_GetIOService(&rv);
00119         if (!mIOService)
00120             return rv;
00121     }
00122 
00123     return NS_OK;
00124 }
00125 
00126 nsresult
00127 nsWebDAVService::SendDocumentToChannel(nsIDocument *doc,
00128                                        nsIHttpChannel *channel, 
00129                                        const char *const method,
00130                                        nsIStreamListener *listener,
00131                                        PRBool withDepth)
00132 {
00133     nsCOMPtr<nsIStorageStream> storageStream;
00134     // Why do I have to pick values for these?  I just want to store some data
00135     // for stream access!  (And how would script set these?)
00136     nsresult rv = NS_NewStorageStream(4096, PR_UINT32_MAX,
00137                                       getter_AddRefs(storageStream));
00138     NS_ENSURE_SUCCESS(rv, rv);
00139 
00140     nsCOMPtr<nsIOutputStream> storageOutputStream;
00141     rv = storageStream->GetOutputStream(0,
00142                                         getter_AddRefs(storageOutputStream));
00143     NS_ENSURE_SUCCESS(rv, rv);
00144 
00145     nsCOMPtr<nsIDocumentEncoder> encoder =
00146         do_CreateInstance(NS_DOC_ENCODER_CONTRACTID_BASE "text/xml", &rv);
00147     NS_ENSURE_SUCCESS(rv, rv);
00148     
00149     rv = encoder->Init(doc, NS_LITERAL_STRING("text/xml"),
00150                        nsIDocumentEncoder::OutputEncodeBasicEntities);
00151     NS_ENSURE_SUCCESS(rv, rv);
00152 
00153     encoder->SetCharset(NS_LITERAL_CSTRING("UTF-8"));
00154     rv =  encoder->EncodeToStream(storageOutputStream);
00155     NS_ENSURE_SUCCESS(rv, rv);
00156 
00157     storageOutputStream->Close();
00158 
00159     // You gotta really want it.
00160 #ifdef PR_LOGGING
00161     if (PR_LOG_TEST(gDAVLog, 5)) {
00162         nsCOMPtr<nsIInputStream> logInputStream;
00163         rv = storageStream->NewInputStream(0, getter_AddRefs(logInputStream));
00164         NS_ENSURE_SUCCESS(rv, rv);
00165 
00166         PRUint32 len, read;
00167         logInputStream->Available(&len);
00168 
00169         char *buf = new char[len+1];
00170         memset(buf, 0, len+1);
00171         logInputStream->Read(buf, len, &read);
00172         NS_ASSERTION(len == read, "short read on closed storage stream?");
00173         LOG(("XML:\n\n%*s\n\n", len, buf));
00174         
00175         delete [] buf;
00176     }
00177 #endif
00178 
00179     nsCOMPtr<nsIInputStream> inputStream;
00180     rv = storageStream->NewInputStream(0, getter_AddRefs(inputStream));
00181     NS_ENSURE_SUCCESS(rv, rv);
00182 
00183     nsCOMPtr<nsIUploadChannel> uploadChannel = do_QueryInterface(channel, &rv);
00184     NS_ENSURE_SUCCESS(rv, rv);
00185     rv = uploadChannel->SetUploadStream(inputStream,
00186                                         NS_LITERAL_CSTRING("text/xml"), -1);
00187     NS_ENSURE_SUCCESS(rv, rv);
00188     
00189     channel->SetRequestMethod(nsDependentCString(method));
00190     channel->SetRequestHeader(NS_LITERAL_CSTRING("Content-Type"),
00191                               NS_LITERAL_CSTRING("text/xml; charset=utf-8"),
00192                               PR_FALSE);
00193     channel->SetRequestHeader(NS_LITERAL_CSTRING("Accept"),
00194                               NS_LITERAL_CSTRING("text/xml"),
00195                               PR_FALSE);
00196     channel->SetRequestHeader(NS_LITERAL_CSTRING("Accept-Charset"),
00197                               NS_LITERAL_CSTRING("utf-8,*;q=0.1"),
00198                               PR_FALSE);
00199     
00200 
00201     if (withDepth) {
00202         channel->SetRequestHeader(NS_LITERAL_CSTRING("Depth"),
00203                                   NS_LITERAL_CSTRING("1"), PR_FALSE);
00204     } else {
00205         channel->SetRequestHeader(NS_LITERAL_CSTRING("Depth"),
00206                                   NS_LITERAL_CSTRING("0"), PR_FALSE);
00207     }
00208 
00209 #ifdef PR_LOGGING
00210     if (LOG_ENABLED()) {
00211         nsCOMPtr<nsIURI> uri;
00212         channel->GetURI(getter_AddRefs(uri));
00213         nsCAutoString spec;
00214         uri->GetSpec(spec);
00215         LOG(("%s starting for %s", method, spec.get()));
00216     }
00217 #endif
00218 
00219     return channel->AsyncOpen(listener, channel);
00220 }
00221 
00222 nsresult
00223 nsWebDAVService::CreatePropfindDocument(nsIURI *resourceURI,
00224                                         nsIDOMDocument **requestDoc,
00225                                         nsIDOMElement **propfindElt)
00226 {
00227     nsresult rv;
00228     static NS_DEFINE_CID(kDOMDOMDOMDOMImplementationCID,
00229                          NS_DOM_IMPLEMENTATION_CID);
00230     nsCOMPtr<nsIDOMDOMImplementation>
00231         implementation(do_CreateInstance(kDOMDOMDOMDOMImplementationCID, &rv));
00232     NS_ENSURE_SUCCESS(rv, rv);
00233 
00234     nsCOMPtr<nsIPrivateDOMImplementation> 
00235         privImpl(do_QueryInterface(implementation));
00236     privImpl->Init(resourceURI);
00237 
00238     nsCOMPtr<nsIDOMDocument> doc;
00239     rv = implementation->CreateDocument(mDAVNSString, EmptyString(), nsnull,
00240                                         getter_AddRefs(doc));
00241     NS_ENSURE_SUCCESS(rv, rv);
00242 
00243     nsCOMPtr<nsIDocument> baseDoc = do_QueryInterface(doc);
00244     baseDoc->SetXMLDeclaration(NS_LITERAL_STRING("1.0").get(),
00245                                EmptyString().get(), -1);
00246     baseDoc->SetDocumentURI(resourceURI);
00247 
00248     nsCOMPtr<nsIDOMElement> elt;
00249     rv = NS_WD_AppendElementWithNS(doc, doc, mDAVNSString,
00250                                    NS_LITERAL_STRING("propfind"),
00251                                    getter_AddRefs(elt));
00252     elt->SetPrefix(NS_LITERAL_STRING("D"));
00253     NS_ENSURE_SUCCESS(rv, rv);
00254 
00255     *requestDoc = doc.get();
00256     NS_ADDREF(*requestDoc);
00257     *propfindElt = elt.get();
00258     NS_ADDREF(*propfindElt);
00259 
00260     return NS_OK;
00261 }
00262 
00263 nsresult
00264 nsWebDAVService::ChannelFromResource(nsIWebDAVResource *aResource,
00265                                      nsIInterfaceRequestor *notificationCallbacks,
00266                                      nsIHttpChannel **aChannel,
00267                                      nsIURI **aResourceURI)
00268 {
00269     ENSURE_IO_SERVICE();
00270 
00271     nsCOMPtr<nsIURL> resourceURL;
00272 
00273     nsresult rv = aResource->GetResourceURL(getter_AddRefs(resourceURL));
00274     NS_ENSURE_SUCCESS(rv, rv);
00275 
00276     nsCOMPtr<nsIChannel> baseChannel;
00277     rv = mIOService->NewChannelFromURI(resourceURL, getter_AddRefs(baseChannel));
00278     NS_ENSURE_SUCCESS(rv, rv);
00279 
00280     rv = baseChannel->SetNotificationCallbacks(notificationCallbacks);
00281     NS_ENSURE_SUCCESS(rv, rv);
00282 
00283     nsLoadFlags loadFlags;
00284     rv = baseChannel->GetLoadFlags(&loadFlags);
00285     if (NS_SUCCEEDED(rv)) {
00286         rv = baseChannel->SetLoadFlags(loadFlags | 
00287                                        nsIRequest::VALIDATE_ALWAYS);
00288         NS_ASSERTION(NS_SUCCEEDED(rv),
00289                      "nsWebDavService::ChannelFromResource(): "
00290                      "Couldn't set loadflags on channel");
00291     }
00292 
00293     rv = CallQueryInterface(baseChannel, aChannel);
00294 
00295     if (NS_SUCCEEDED(rv) && aResourceURI) {
00296         *aResourceURI = resourceURL.get();
00297         NS_ADDREF(*aResourceURI);
00298     }
00299 
00300     return rv;
00301 }
00302 
00303 nsWebDAVService::nsWebDAVService() :
00304     mDAVNSString(NS_LITERAL_STRING("DAV:"))
00305 
00306 {
00307 #ifdef PR_LOGGING
00308     gDAVLog = PR_NewLogModule("webdav");
00309 #endif
00310 }
00311 
00312 nsWebDAVService::~nsWebDAVService()
00313 {
00314   /* destructor code */
00315 }
00316 
00317 NS_IMETHODIMP
00318 nsWebDAVService::LockResources(PRUint32 count, nsIWebDAVResource **resources,
00319                                nsIWebDAVOperationListener *listener,
00320                                nsIInterfaceRequestor *notificationCallbacks,
00321                                nsISupports *closure)
00322 {
00323     return NS_ERROR_NOT_IMPLEMENTED;
00324 }
00325 
00326 NS_IMETHODIMP
00327 nsWebDAVService::UnlockResources(PRUint32 count, nsIWebDAVResource **resources,
00328                                  nsIWebDAVOperationListener *listener,
00329                                  nsIInterfaceRequestor *notificationCallbacks,
00330                                  nsISupports *closure)
00331 {
00332     return NS_ERROR_NOT_IMPLEMENTED;
00333 }
00334 
00335 NS_IMETHODIMP
00336 nsWebDAVService::GetResourcePropertyNames(nsIWebDAVResource *resource,
00337                                           PRBool withDepth,
00338                                           nsIWebDAVOperationListener *listener,
00339                                           nsIInterfaceRequestor *notificationCallbacks,
00340                                           nsISupports *closure)
00341 {
00342     return PropfindInternal(resource, 0, nsnull, withDepth,
00343                             listener, notificationCallbacks, closure, PR_TRUE);
00344 }
00345 
00346 NS_IMETHODIMP
00347 nsWebDAVService::GetResourceProperties(nsIWebDAVResource *resource,
00348                                        PRUint32 propCount,
00349                                        const char **properties,
00350                                        PRBool withDepth,
00351                                        nsIWebDAVOperationListener *listener,
00352                                        nsIInterfaceRequestor *notificationCallbacks,
00353                                        nsISupports *closure)
00354 {
00355     return PropfindInternal(resource, propCount, properties, withDepth,
00356                             listener, notificationCallbacks, closure, PR_FALSE);
00357 }
00358 
00359 nsresult
00360 nsWebDAVService::PropfindInternal(nsIWebDAVResource *resource,
00361                                   PRUint32 propCount,
00362                                   const char **properties,
00363                                   PRBool withDepth,
00364                                   nsIWebDAVOperationListener *listener,
00365                                   nsIInterfaceRequestor *notificationCallbacks,
00366                                   nsISupports *closure,
00367                                   PRBool namesOnly)
00368 {
00369     nsresult rv;
00370 
00371     NS_ENSURE_ARG(resource);
00372     NS_ENSURE_ARG(listener);
00373 
00374     nsCOMPtr<nsIURI> resourceURI;
00375     nsCOMPtr<nsIHttpChannel> channel;
00376     rv = ChannelFromResource(resource, notificationCallbacks, getter_AddRefs(channel),
00377                              getter_AddRefs(resourceURI));
00378     if (NS_FAILED(rv))
00379         return rv;
00380 
00381     nsCOMPtr<nsIDOMDocument> requestDoc;
00382     nsCOMPtr<nsIDOMElement> propfindElt;
00383     rv = CreatePropfindDocument(resourceURI, getter_AddRefs(requestDoc),
00384                                 getter_AddRefs(propfindElt));
00385     NS_ENSURE_SUCCESS(rv, rv);
00386 
00387     if (namesOnly) {
00388         nsCOMPtr<nsIDOMElement> allpropElt;
00389         rv = NS_WD_AppendElementWithNS(requestDoc, propfindElt,
00390                                        mDAVNSString, NS_LITERAL_STRING("propname"),
00391                                        getter_AddRefs(allpropElt));
00392         NS_ENSURE_SUCCESS(rv, rv);
00393     } else if (propCount == 0) {
00394         nsCOMPtr<nsIDOMElement> allpropElt;
00395         rv = NS_WD_AppendElementWithNS(requestDoc, propfindElt,
00396                                        mDAVNSString, NS_LITERAL_STRING("allprop"),
00397                                        getter_AddRefs(allpropElt));
00398         NS_ENSURE_SUCCESS(rv, rv);
00399     } else {
00400         nsCOMPtr<nsIDOMElement> propElt;
00401         rv = NS_WD_AppendElementWithNS(requestDoc, propfindElt,
00402                                        mDAVNSString, NS_LITERAL_STRING("prop"),
00403                                        getter_AddRefs(propElt));
00404         NS_ENSURE_SUCCESS(rv, rv);
00405 
00406         for (PRUint32 i = 0; i < propCount; i++) {
00407             nsDependentCString fullpropName(properties[i]);
00408 
00409             // This string math is _ridiculous_.  It better compile to a total of
00410             // 5 instructions, or I'm ripping it all out and doing my own looping.
00411 
00412             nsACString::const_iterator start, saveStart, end, saveEnd;
00413             fullpropName.BeginReading(start);
00414             fullpropName.BeginReading(saveStart);
00415             fullpropName.EndReading(end);
00416             fullpropName.EndReading(saveEnd);
00417             RFindInReadable(NS_LITERAL_CSTRING(" "), start, end);
00418 
00419             if (start == end) {
00420                 nsCAutoString msg(NS_LITERAL_CSTRING("Illegal property name ")
00421                                   + fullpropName + NS_LITERAL_CSTRING("\n"));
00422                 NS_WARNING(msg.get());
00423                 return NS_ERROR_INVALID_ARG;
00424             }
00425 
00426 #ifdef PR_LOGGING
00427             if (LOG_ENABLED()) {
00428                 nsACString::const_iterator s = start;
00429                 
00430                 nsCAutoString propNamespace(nsDependentCSubstring(saveStart, s));
00431                 nsCAutoString propName(nsDependentCSubstring(++s, saveEnd));
00432                 
00433                 LOG(("prop ns: '%s', name: '%s'", propNamespace.get(), propName.get()));
00434             }
00435 #endif
00436 
00437             NS_ConvertASCIItoUTF16 propNamespace(nsDependentCSubstring(saveStart, start)),
00438                 propName(nsDependentCSubstring(++start, saveEnd));
00439 
00440             nsCOMPtr<nsIDOMElement> junk;
00441             rv = NS_WD_AppendElementWithNS(requestDoc, propElt, propNamespace,
00442                                            propName, getter_AddRefs(junk));
00443             NS_ENSURE_SUCCESS(rv, rv);
00444         }
00445     }
00446 
00447     nsCOMPtr<nsIStreamListener> streamListener = 
00448         NS_WD_NewPropfindStreamListener(resource, listener, closure,
00449                                         namesOnly);
00450 
00451     if (!streamListener)
00452         return NS_ERROR_OUT_OF_MEMORY;
00453     
00454     nsCOMPtr<nsIDocument> requestBaseDoc = do_QueryInterface(requestDoc);
00455     return SendDocumentToChannel(requestBaseDoc, channel, "PROPFIND",
00456                                  streamListener, withDepth);
00457 }
00458 
00459 NS_IMETHODIMP
00460 nsWebDAVService::GetResourceOptions(nsIWebDAVResource *resource,
00461                                     nsIWebDAVOperationListener *listener,
00462                                     nsIInterfaceRequestor *notificationCallbacks,
00463                                     nsISupports *closure)
00464 {
00465     return NS_ERROR_NOT_IMPLEMENTED;
00466 }
00467 
00468 NS_IMETHODIMP
00469 nsWebDAVService::Get(nsIWebDAVResource *resource, nsIStreamListener *listener,
00470                      nsIInterfaceRequestor *notificationCallbacks)
00471 {
00472     nsresult rv;
00473     nsCOMPtr<nsIHttpChannel> channel;
00474     rv = ChannelFromResource(resource, notificationCallbacks, getter_AddRefs(channel));
00475     if (NS_FAILED(rv))
00476         return rv;
00477 
00478     return channel->AsyncOpen(listener, channel);
00479 }
00480 
00481 NS_IMETHODIMP
00482 nsWebDAVService::GetToOutputStream(nsIWebDAVResource *resource,
00483                                    nsIOutputStream *stream,
00484                                    nsIWebDAVOperationListener *listener,
00485                                    nsIInterfaceRequestor *notificationCallbacks,
00486                                    nsISupports *closure)
00487 {
00488     nsCOMPtr<nsIRequestObserver> getObserver;
00489     nsresult rv;
00490 
00491     rv = NS_WD_NewGetOperationRequestObserver(resource, listener, closure, 
00492                                               stream,
00493                                               getter_AddRefs(getObserver));
00494     NS_ENSURE_SUCCESS(rv, rv);
00495 
00496     nsCOMPtr<nsIStreamListener> streamListener;
00497     rv = NS_NewSimpleStreamListener(getter_AddRefs(streamListener),
00498                                     stream, getObserver);
00499     NS_ENSURE_SUCCESS(rv, rv);
00500 
00501     return Get(resource, streamListener, notificationCallbacks);
00502 }
00503 
00504 NS_IMETHODIMP
00505 nsWebDAVService::GetToString(nsIWebDAVResource *resource,
00506                              nsIWebDAVOperationListener *listener,
00507                              nsIInterfaceRequestor *notificationCallbacks,
00508                              nsISupports *closure)
00509 {
00510     nsCOMPtr<nsIStreamListener> getListener;
00511     nsresult rv;
00512 
00513     rv = NS_WD_NewGetToStringOperationRequestObserver(resource, listener,
00514                                                       closure,
00515                                                       getter_AddRefs(getListener));
00516     NS_ENSURE_SUCCESS(rv, rv);
00517 
00518     nsCOMPtr<nsIHttpChannel> channel;
00519     rv = ChannelFromResource(resource, notificationCallbacks, getter_AddRefs(channel));
00520     NS_ENSURE_SUCCESS(rv, rv);
00521 
00522     return channel->AsyncOpen(getListener, channel);
00523 }
00524 
00525 NS_IMETHODIMP
00526 nsWebDAVService::Put(nsIWebDAVResource *resource,
00527                      const nsACString& contentType, nsIInputStream *data,
00528                      nsIWebDAVOperationListener *listener,
00529                      nsIInterfaceRequestor *notificationCallbacks,
00530                      nsISupports *closure)
00531 {
00532     nsCOMPtr<nsIHttpChannel> channel;
00533 
00534     nsresult rv = ChannelFromResource(resource, notificationCallbacks, getter_AddRefs(channel));
00535     NS_ENSURE_SUCCESS(rv, rv);
00536     
00537     nsCOMPtr<nsIUploadChannel> uploadChannel = do_QueryInterface(channel, &rv);
00538     NS_ENSURE_SUCCESS(rv, rv);
00539 
00540     rv = uploadChannel->SetUploadStream(data, contentType, -1);
00541     NS_ENSURE_SUCCESS(rv, rv);
00542 
00543     nsCOMPtr<nsIStreamListener> streamListener;
00544     rv = NS_WD_NewOperationStreamListener(resource, listener, closure,
00545                                           nsIWebDAVOperationListener::PUT,
00546                                           getter_AddRefs(streamListener));
00547     NS_ENSURE_SUCCESS(rv, rv);
00548 
00549     channel->SetRequestMethod(NS_LITERAL_CSTRING("PUT"));
00550 
00551 #ifdef PR_LOGGING
00552     if (LOG_ENABLED()) {
00553         nsCOMPtr<nsIURI> uri;
00554         channel->GetURI(getter_AddRefs(uri));
00555         nsCAutoString spec;
00556         uri->GetSpec(spec);
00557         LOG(("PUT starting for %s", spec.get()));
00558     }
00559 #endif
00560 
00561     return channel->AsyncOpen(streamListener, channel);
00562 }
00563 
00564 NS_IMETHODIMP
00565 nsWebDAVService::PutFromString(nsIWebDAVResource *resource,
00566                                const nsACString& contentType,
00567                                const nsACString& data,
00568                                nsIWebDAVOperationListener *listener,
00569                                nsIInterfaceRequestor *notificationCallbacks,
00570                                nsISupports *closure)
00571 {
00572     nsresult rv;
00573     nsCOMPtr<nsIStringInputStream> dataStream = 
00574         do_CreateInstance("@mozilla.org/io/string-input-stream;1", &rv);
00575     NS_ENSURE_SUCCESS(rv, rv);
00576 
00577     dataStream->SetData(PromiseFlatCString(data).get(),
00578                         data.Length());
00579     return Put(resource, contentType, dataStream, listener, 
00580                notificationCallbacks, closure);
00581 }
00582 
00583 NS_IMETHODIMP
00584 nsWebDAVService::Remove(nsIWebDAVResource *resource,
00585                         nsIWebDAVOperationListener *listener,
00586                         nsIInterfaceRequestor *notificationCallbacks,
00587                         nsISupports *closure)
00588 {
00589     nsCOMPtr<nsIHttpChannel> channel;
00590     nsresult rv = ChannelFromResource(resource, notificationCallbacks, getter_AddRefs(channel));
00591     NS_ENSURE_SUCCESS(rv, rv);
00592 
00593     nsCOMPtr<nsIStreamListener> streamListener;
00594     rv = NS_WD_NewOperationStreamListener(resource, listener, closure,
00595                                           nsIWebDAVOperationListener::REMOVE,
00596                                           getter_AddRefs(streamListener));
00597     NS_ENSURE_SUCCESS(rv, rv);
00598 
00599     channel->SetRequestMethod(NS_LITERAL_CSTRING("DELETE"));
00600 
00601 #ifdef PR_LOGGING
00602     if (LOG_ENABLED()) {
00603         nsCOMPtr<nsIURI> uri;
00604         channel->GetURI(getter_AddRefs(uri));
00605         nsCAutoString spec;
00606         uri->GetSpec(spec);
00607         LOG(("DELETE starting for %s", spec.get()));
00608     }
00609 #endif
00610 
00611     return channel->AsyncOpen(streamListener, channel);
00612 }
00613 
00614 NS_IMETHODIMP
00615 nsWebDAVService::MakeCollection(nsIWebDAVResource *resource,
00616                                 nsIWebDAVOperationListener *listener,
00617                                 nsIInterfaceRequestor *notificationCallbacks,
00618                                 nsISupports *closure)
00619 {
00620     nsCOMPtr<nsIHttpChannel> channel;
00621     nsresult rv = ChannelFromResource(resource, notificationCallbacks, getter_AddRefs(channel));
00622     NS_ENSURE_SUCCESS(rv, rv);
00623 
00624     nsCOMPtr<nsIStreamListener> streamListener;
00625     rv = NS_WD_NewOperationStreamListener(resource, listener, closure,
00626                                           nsIWebDAVOperationListener::MAKE_COLLECTION,
00627                                           getter_AddRefs(streamListener));
00628     NS_ENSURE_SUCCESS(rv, rv);
00629 
00630     channel->SetRequestMethod(NS_LITERAL_CSTRING("MKCOL"));
00631 
00632 #ifdef PR_LOGGING
00633     if (LOG_ENABLED()) {
00634         nsCOMPtr<nsIURI> uri;
00635         channel->GetURI(getter_AddRefs(uri));
00636         nsCAutoString spec;
00637         uri->GetSpec(spec);
00638         LOG(("MKCOL starting for %s", spec.get()));
00639     }
00640 #endif
00641 
00642     return channel->AsyncOpen(streamListener, channel);
00643 }
00644 
00645 NS_IMETHODIMP
00646 nsWebDAVService::MoveTo(nsIWebDAVResource *resource,
00647                         const nsACString &destination,
00648                         PRBool overwrite,
00649                         nsIWebDAVOperationListener *listener,
00650                         nsIInterfaceRequestor *notificationCallbacks,
00651                         nsISupports *closure)
00652 {
00653     nsCOMPtr<nsIHttpChannel> channel;
00654     nsresult rv = ChannelFromResource(resource, notificationCallbacks, getter_AddRefs(channel));
00655     NS_ENSURE_SUCCESS(rv, rv);
00656 
00657     nsCOMPtr<nsIStreamListener> streamListener;
00658     rv = NS_WD_NewOperationStreamListener(resource, listener, closure,
00659                                           nsIWebDAVOperationListener::COPY,
00660                                           getter_AddRefs(streamListener));
00661     NS_ENSURE_SUCCESS(rv, rv);
00662 
00663     channel->SetRequestMethod(NS_LITERAL_CSTRING("MOVE"));
00664 
00665     if (!overwrite) {
00666         channel->SetRequestHeader(NS_LITERAL_CSTRING("Overwrite"),
00667                                   NS_LITERAL_CSTRING("F"),
00668                                   PR_FALSE);
00669     } else {
00670         channel->SetRequestHeader(NS_LITERAL_CSTRING("Overwrite"),
00671                                   NS_LITERAL_CSTRING("F"),
00672                                   PR_FALSE);
00673     }
00674 
00675     channel->SetRequestHeader(NS_LITERAL_CSTRING("Destination"),
00676                               destination, PR_FALSE);
00677 
00678 #ifdef PR_LOGGING
00679     if (LOG_ENABLED()) {
00680         nsCOMPtr<nsIURI> uri;
00681         channel->GetURI(getter_AddRefs(uri));
00682         nsCAutoString spec;
00683         uri->GetSpec(spec);
00684         LOG(("MOVE starting for %s -> %s", spec.get(),
00685              nsCAutoString(destination).get()));
00686     }
00687 #endif
00688 
00689     return channel->AsyncOpen(streamListener, channel);
00690 }
00691 
00692 NS_IMETHODIMP
00693 nsWebDAVService::CopyTo(nsIWebDAVResource *resource,
00694                         const nsACString &destination,
00695                         PRBool recursive, PRBool overwrite,
00696                         nsIWebDAVOperationListener *listener,
00697                         nsIInterfaceRequestor *notificationCallbacks,
00698                         nsISupports *closure)
00699 
00700 {
00701     nsCOMPtr<nsIHttpChannel> channel;
00702     nsresult rv = ChannelFromResource(resource, notificationCallbacks, getter_AddRefs(channel));
00703     NS_ENSURE_SUCCESS(rv, rv);
00704 
00705     nsCOMPtr<nsIStreamListener> streamListener;
00706     rv = NS_WD_NewOperationStreamListener(resource, listener, closure,
00707                                           nsIWebDAVOperationListener::COPY,
00708                                           getter_AddRefs(streamListener));
00709     NS_ENSURE_SUCCESS(rv, rv);
00710 
00711     channel->SetRequestMethod(NS_LITERAL_CSTRING("COPY"));
00712     if (!overwrite) {
00713         channel->SetRequestHeader(NS_LITERAL_CSTRING("Overwrite"),
00714                                   NS_LITERAL_CSTRING("F"),
00715                                   PR_FALSE);
00716     } else {
00717         channel->SetRequestHeader(NS_LITERAL_CSTRING("Overwrite"),
00718                                   NS_LITERAL_CSTRING("F"),
00719                                   PR_FALSE);
00720     }
00721 
00722     if (recursive) {
00723         channel->SetRequestHeader(NS_LITERAL_CSTRING("Depth"),
00724                                   NS_LITERAL_CSTRING("infinity"), PR_FALSE);
00725     } else {
00726         channel->SetRequestHeader(NS_LITERAL_CSTRING("Depth"),
00727                                   NS_LITERAL_CSTRING("0"), PR_FALSE);
00728     }
00729 
00730     channel->SetRequestHeader(NS_LITERAL_CSTRING("Destination"),
00731                               destination, PR_FALSE);
00732 
00733 #ifdef PR_LOGGING
00734     if (LOG_ENABLED()) {
00735         nsCOMPtr<nsIURI> uri;
00736         channel->GetURI(getter_AddRefs(uri));
00737         nsCAutoString spec;
00738         uri->GetSpec(spec);
00739         LOG(("COPY starting for %s -> %s", spec.get(),
00740              nsCAutoString(destination).get()));
00741     }
00742 #endif
00743 
00744     return channel->AsyncOpen(streamListener, channel);
00745 }
00746 
00747 
00748 NS_IMETHODIMP
00749 nsWebDAVService::Report(nsIWebDAVResource *resource, nsIDOMDocument *query, 
00750                         PRBool withDepth, 
00751                         nsIWebDAVOperationListener *listener, 
00752                         nsIInterfaceRequestor *notificationCallbacks,
00753                         nsISupports *closure)
00754 {
00755     nsresult rv;
00756 
00757     NS_ENSURE_ARG(resource);
00758     NS_ENSURE_ARG(query);
00759     NS_ENSURE_ARG(listener);
00760 
00761     nsCOMPtr<nsIDocument> queryDoc = do_QueryInterface(query, &rv);
00762     NS_ENSURE_SUCCESS(rv, rv);
00763     
00764     nsCOMPtr<nsIURI> resourceURI;
00765     nsCOMPtr<nsIHttpChannel> channel;
00766     rv = ChannelFromResource(resource, notificationCallbacks, getter_AddRefs(channel),
00767                              getter_AddRefs(resourceURI));
00768     if (NS_FAILED(rv))
00769         return rv;
00770 
00771     nsCOMPtr<nsIStreamListener> streamListener = 
00772         NS_WD_NewReportStreamListener(resource, listener, closure);
00773     if (!streamListener)
00774         return NS_ERROR_OUT_OF_MEMORY;
00775 
00776     return SendDocumentToChannel(queryDoc, channel, "REPORT", streamListener,
00777                                  withDepth);
00778 }
00779 
00780 NS_GENERIC_FACTORY_CONSTRUCTOR(nsWebDAVService)
00781 
00782 NS_DECL_CLASSINFO(nsWebDAVService)
00783 
00784 static const nsModuleComponentInfo components[] =
00785 {
00786     { "WebDAV Service", NS_WEBDAVSERVICE_CID, NS_WEBDAVSERVICE_CONTRACTID,
00787       nsWebDAVServiceConstructor,
00788       NULL, NULL, NULL,
00789       NS_CI_INTERFACE_GETTER_NAME(nsWebDAVService),
00790       NULL,
00791       &NS_CLASSINFO_NAME(nsWebDAVService)
00792     }
00793 };
00794 
00795 NS_IMPL_NSGETMODULE(nsWebDAVService, components)