зеркало из https://github.com/mozilla/pjs.git
WebDAV checkpoint (NPOTB, I feel so dirty).
- return properties for propname results, as well as properties proper. (Depends on 263957 to actually be useful.) - ACString > string. - remove vestigial ChildListener interface. - OperationListener is also used for get and put. - put needs a content-type. - getToOutputStream for somewhat easier use from script. - implement put, getToOutputStream - much refactoring of propfind stuff for reuse and clarity - "davshell" xpcshell test framework - honestly, did we lose a string-API bet with someone?
This commit is contained in:
Родитель
08eea60ca0
Коммит
1c3f4cfd9e
|
@ -44,9 +44,7 @@ interface nsIWebDAVMetadataListener : nsISupports
|
|||
{
|
||||
void onGetPropertyNamesResult(in unsigned long aStatusCode,
|
||||
in AUTF8String aResource,
|
||||
in PRUint32 nameCount,
|
||||
[array, size_is(nameCount)]
|
||||
in string propertyNames);
|
||||
in nsIProperties aPropertyNames);
|
||||
|
||||
void onGetPropertiesResult(in unsigned long aStatusCode,
|
||||
in AUTF8String aResource,
|
||||
|
@ -59,7 +57,7 @@ interface nsIWebDAVMetadataListener : nsISupports
|
|||
|
||||
void onMetadataComplete(in unsigned long aStatusCode,
|
||||
in nsIWebDAVResource aResource,
|
||||
in string method);
|
||||
in ACString method);
|
||||
};
|
||||
|
||||
[scriptable,uuid(e198a0fd-9e62-4299-84e3-d93c0cd68881)]
|
||||
|
@ -73,17 +71,8 @@ interface nsIWebDAVOperationListener : nsISupports
|
|||
in nsIWebDAVResource aResource);
|
||||
void onCopyResult(in unsigned long aStatusCode,
|
||||
in nsIWebDAVResource aResource);
|
||||
};
|
||||
|
||||
[scriptable,uuid(c368540a-b4c3-45d7-b20f-1474c140c0dd)]
|
||||
interface nsIWebDAVChildrenListener : nsISupports
|
||||
{
|
||||
void hasChild(in unsigned long aStatusCode,
|
||||
in AUTF8String aParent,
|
||||
in AUTF8String aChild);
|
||||
|
||||
void childListComplete(in AUTF8String aParent);
|
||||
|
||||
void childListFailed(in unsigned long aStatusCode,
|
||||
in AUTF8String aParent);
|
||||
void onPutResult(in unsigned long aStatusCode,
|
||||
in nsIWebDAVResource aResource);
|
||||
void onGetResult(in unsigned long aStatusCode,
|
||||
in nsIWebDAVResource aResource);
|
||||
};
|
||||
|
|
|
@ -39,6 +39,7 @@
|
|||
#include "nsIWebDAVResource.idl"
|
||||
|
||||
interface nsIStreamListener;
|
||||
interface nsIOutputStream;
|
||||
|
||||
[scriptable,uuid(173ef52e-2a2f-45ca-8f9f-abc7429163c2)]
|
||||
interface nsIWebDAVService : nsISupports
|
||||
|
@ -67,13 +68,15 @@ interface nsIWebDAVService : nsISupports
|
|||
void getResourceOptions(in nsIWebDAVResource resource,
|
||||
in nsIWebDAVMetadataListener listener);
|
||||
|
||||
void getChildren(in nsIWebDAVResource resource,
|
||||
in PRUint32 depth, in nsIWebDAVChildrenListener listener);
|
||||
|
||||
void get(in nsIWebDAVResource resource,
|
||||
in nsIStreamListener listener);
|
||||
|
||||
void getToOutputStream(in nsIWebDAVResource resource,
|
||||
in nsIOutputStream stream,
|
||||
in nsIWebDAVOperationListener listener);
|
||||
|
||||
void put(in nsIWebDAVResourceWithData resource,
|
||||
in ACString contentType,
|
||||
in nsIWebDAVOperationListener listener);
|
||||
|
||||
void remove(in nsIWebDAVResource resource,
|
||||
|
|
|
@ -58,9 +58,10 @@ REQUIRES = xpcom \
|
|||
xmlextras \
|
||||
$(NULL)
|
||||
|
||||
CPPSRCS = nsWebDAVService.cpp \
|
||||
nsPropfindStreamListener.cpp \
|
||||
nsWebDAVUtils.cpp \
|
||||
CPPSRCS = nsWebDAVService.cpp \
|
||||
nsPropfindStreamListener.cpp \
|
||||
nsOperationStreamListeners.cpp \
|
||||
nsWebDAVUtils.cpp \
|
||||
$(NULL)
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
|
|
@ -0,0 +1,123 @@
|
|||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
// vim:expandtab:ts=4 sw=4:
|
||||
/*
|
||||
* The contents of this file are subject to the Mozilla Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is Mozilla.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Oracle Corporation.
|
||||
* Portions created by Oracle Corporation are Copyright (C) 2004
|
||||
* by Oracle Corporation. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Mike Shaver <shaver@off.net> (original author)
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "nsIHttpChannel.h"
|
||||
#include "nsIIOService.h"
|
||||
#include "nsNetUtil.h"
|
||||
|
||||
#include "nsIWebDAVResource.h"
|
||||
#include "nsIWebDAVListener.h"
|
||||
|
||||
#include "nsWebDAVInternal.h"
|
||||
|
||||
class OperationStreamListener : public nsIStreamListener
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIREQUESTOBSERVER
|
||||
NS_DECL_NSISTREAMLISTENER
|
||||
|
||||
enum OperationMode {
|
||||
PUT, GET
|
||||
};
|
||||
|
||||
OperationStreamListener(nsIWebDAVResource *resource,
|
||||
nsIWebDAVOperationListener *listener,
|
||||
OperationMode mode) :
|
||||
mResource(resource), mListener(listener), mMode(mode) { }
|
||||
virtual ~OperationStreamListener() { }
|
||||
|
||||
protected:
|
||||
|
||||
nsCOMPtr<nsIWebDAVResource> mResource;
|
||||
nsCOMPtr<nsIWebDAVOperationListener> mListener;
|
||||
OperationMode mMode;
|
||||
|
||||
};
|
||||
|
||||
NS_IMPL_ISUPPORTS1(OperationStreamListener, nsIStreamListener);
|
||||
|
||||
NS_IMETHODIMP
|
||||
OperationStreamListener::OnStartRequest(nsIRequest *aRequest,
|
||||
nsISupports *aContext)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
OperationStreamListener::OnStopRequest(nsIRequest *aRequest,
|
||||
nsISupports *aContext,
|
||||
nsresult aStatusCode)
|
||||
{
|
||||
switch (mMode) {
|
||||
case PUT:
|
||||
mListener->OnPutResult(aStatusCode, mResource);
|
||||
break;
|
||||
case GET:
|
||||
mListener->OnGetResult(aStatusCode, mResource);
|
||||
break;
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
OperationStreamListener::OnDataAvailable(nsIRequest *aRequest,
|
||||
nsISupports *aContext,
|
||||
nsIInputStream *aInputStream,
|
||||
PRUint32 offset, PRUint32 count)
|
||||
{
|
||||
aRequest->Cancel(NS_BINDING_ABORTED);
|
||||
return NS_BINDING_ABORTED;
|
||||
}
|
||||
|
||||
nsIStreamListener *
|
||||
NS_WD_NewPutOperationStreamListener(nsIWebDAVResource *resource,
|
||||
nsIWebDAVOperationListener *listener)
|
||||
{
|
||||
nsCOMPtr<nsIStreamListener> osl =
|
||||
return new OperationStreamListener(resource, listener,
|
||||
OperationStreamListener::PUT);
|
||||
}
|
||||
|
||||
nsIRequestObserver *
|
||||
NS_WD_NewGetOperationRequestObserver(nsIWebDAVResource *resource,
|
||||
nsIWebDAVOperationListener *listener)
|
||||
{
|
||||
nsCOMPtr<nsIRequestObserver> osl =
|
||||
do_QueryInterface(new OperationStreamListener(resource, listener,
|
||||
OperationStreamListener::GET));
|
||||
return osl.get();
|
||||
}
|
|
@ -19,6 +19,7 @@
|
|||
*
|
||||
* Contributor(s):
|
||||
* Mike Shaver <shaver@off.net> (original author)
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
|
@ -62,8 +63,9 @@ public:
|
|||
NS_DECL_NSISTREAMLISTENER
|
||||
|
||||
PropfindStreamListener(nsIWebDAVResource *resource,
|
||||
nsIWebDAVMetadataListener *listener) :
|
||||
mResource(resource), mListener(listener) { }
|
||||
nsIWebDAVMetadataListener *listener,
|
||||
PRBool isPropname) :
|
||||
mResource(resource), mListener(listener), mNameOnly(isPropname) { }
|
||||
virtual ~PropfindStreamListener() { }
|
||||
protected:
|
||||
|
||||
|
@ -79,7 +81,8 @@ protected:
|
|||
mResource->GetUrlSpec(spec);
|
||||
LOG(("PROPFIND completed for %s: %d", spec.get(), aStatusCode));
|
||||
}
|
||||
mListener->OnMetadataComplete(aStatusCode, mResource, "PROPFIND");
|
||||
mListener->OnMetadataComplete(aStatusCode, mResource,
|
||||
NS_LITERAL_CSTRING("PROPFIND"));
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -91,6 +94,7 @@ protected:
|
|||
nsCOMPtr<nsIWebDAVMetadataListener> mListener;
|
||||
nsCOMPtr<nsIDOMDocument> mXMLDoc;
|
||||
nsCString mBody;
|
||||
PRBool mNameOnly;
|
||||
};
|
||||
|
||||
NS_IMPL_ISUPPORTS1(PropfindStreamListener, nsIStreamListener)
|
||||
|
@ -152,6 +156,15 @@ PropfindStreamListener::PropertiesFromPropElt(nsIDOMElement *propElt,
|
|||
rv = node->GetLocalName(propName);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
NS_ConvertUTF16toUTF8 propkey(nsStr + NS_LITERAL_STRING(" ") +
|
||||
propName);
|
||||
if (mNameOnly) {
|
||||
LOG((" propname: %s", propkey.get()));
|
||||
rv = props->Set(propkey.get(), nsnull);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
continue;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIDocumentEncoder> encoder =
|
||||
do_CreateInstance(NS_DOC_ENCODER_CONTRACTID_BASE "text/xml", &rv);
|
||||
|
||||
|
@ -175,8 +188,6 @@ PropfindStreamListener::PropertiesFromPropElt(nsIDOMElement *propElt,
|
|||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
suppString->SetData(valueStr);
|
||||
|
||||
NS_ConvertUTF16toUTF8 propkey(nsStr + NS_LITERAL_STRING(" ") +
|
||||
propName);
|
||||
LOG((" %s = %s", propkey.get(),
|
||||
NS_ConvertUTF16toUTF8(valueStr).get()));
|
||||
rv = props->Set(propkey.get(), suppString);
|
||||
|
@ -240,7 +251,14 @@ PropfindStreamListener::ProcessResponse(nsIDOMElement *responseElt)
|
|||
PRInt32 statusVal = nsCAutoString(Substring(statusUTF8, 8)).ToInteger(&res, 10);
|
||||
NS_ENSURE_SUCCESS(res, (nsresult)res);
|
||||
|
||||
mListener->OnGetPropertiesResult((PRUint32)statusVal, hrefUTF8, props);
|
||||
|
||||
if (mNameOnly) {
|
||||
mListener->OnGetPropertyNamesResult((PRUint32)statusVal, hrefUTF8,
|
||||
props);
|
||||
} else {
|
||||
mListener->OnGetPropertiesResult((PRUint32)statusVal, hrefUTF8,
|
||||
props);
|
||||
}
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -346,8 +364,9 @@ PropfindStreamListener::OnDataAvailable(nsIRequest *aRequest,
|
|||
}
|
||||
|
||||
nsIStreamListener *
|
||||
NS_NewPropfindStreamListener(nsIWebDAVResource *resource,
|
||||
nsIWebDAVMetadataListener *listener)
|
||||
NS_WD_NewPropfindStreamListener(nsIWebDAVResource *resource,
|
||||
nsIWebDAVMetadataListener *listener,
|
||||
PRBool isPropname)
|
||||
{
|
||||
return new PropfindStreamListener(resource, listener);
|
||||
return new PropfindStreamListener(resource, listener, isPropname);
|
||||
}
|
||||
|
|
|
@ -42,6 +42,7 @@
|
|||
#include "nsString.h"
|
||||
|
||||
class nsIStreamListener;
|
||||
class nsIRequestObserver;
|
||||
|
||||
#include "nsIDOMElement.h"
|
||||
#include "nsIWebDAVListener.h"
|
||||
|
@ -53,8 +54,17 @@ class nsIStreamListener;
|
|||
extern PRLogModuleInfo *gDAVLog;
|
||||
|
||||
nsIStreamListener *
|
||||
NS_NewPropfindStreamListener(nsIWebDAVResource *resource,
|
||||
nsIWebDAVMetadataListener *listener);
|
||||
NS_WD_NewPropfindStreamListener(nsIWebDAVResource *resource,
|
||||
nsIWebDAVMetadataListener *listener,
|
||||
PRBool isPropname);
|
||||
|
||||
nsIStreamListener *
|
||||
NS_WD_NewPutOperationStreamListener(nsIWebDAVResource *resource,
|
||||
nsIWebDAVOperationListener *listener);
|
||||
|
||||
nsIRequestObserver *
|
||||
NS_WD_NewGetOperationRequestObserver(nsIWebDAVResource *resource,
|
||||
nsIWebDAVOperationListener *listener);
|
||||
|
||||
nsresult
|
||||
NS_WD_GetElementByTagName(nsIDOMElement *parentElt, const nsAString &tagName,
|
||||
|
@ -64,4 +74,9 @@ nsresult
|
|||
NS_WD_ElementTextChildValue(nsIDOMElement *elt, const nsAString &tagName,
|
||||
nsAString &value);
|
||||
|
||||
nsresult
|
||||
NS_WD_AppendElementWithNS(nsIDOMDocument *doc, nsIDOMNode *parent,
|
||||
const nsAString& ns, const nsAString& tagName,
|
||||
nsIDOMElement **child);
|
||||
|
||||
#endif /* nsWebDAVInternal_h__ */
|
||||
|
|
|
@ -48,10 +48,20 @@
|
|||
#include "nsIHttpChannel.h"
|
||||
#include "nsIIOService.h"
|
||||
#include "nsNetUtil.h"
|
||||
#include "nsIStorageStream.h"
|
||||
#include "nsIUploadChannel.h"
|
||||
|
||||
#include "nsContentCID.h"
|
||||
|
||||
#include "nsIDOMXMLDocument.h"
|
||||
#include "nsIDOMElement.h"
|
||||
#include "nsIDOMNodeList.h"
|
||||
#include "nsIDOM3Node.h"
|
||||
#include "nsIPrivateDOMImplementation.h" // I don't even pretend any more
|
||||
#include "nsIDOMDOMImplementation.h"
|
||||
|
||||
#include "nsIDocument.h"
|
||||
#include "nsIDocumentEncoder.h"
|
||||
|
||||
#include "nsIDOMParser.h"
|
||||
|
||||
|
@ -68,8 +78,28 @@ public:
|
|||
protected:
|
||||
nsresult EnsureIOService();
|
||||
nsresult ChannelFromResource(nsIWebDAVResource *resource,
|
||||
nsIHttpChannel** channel);
|
||||
nsIHttpChannel** channel,
|
||||
nsIURI ** resourceURI = 0);
|
||||
|
||||
nsresult ChannelWithStreamFromResource(nsIWebDAVResource *resource,
|
||||
nsIHttpChannel **channel,
|
||||
nsIInputStream **stream);
|
||||
|
||||
nsresult CreatePropfindDocument(nsIURI *resourceURI,
|
||||
nsIDOMDocument **requestDoc,
|
||||
nsIDOMElement **propfindElt);
|
||||
|
||||
nsresult PropfindInternal(nsIWebDAVResource *resource, PRUint32 propCount,
|
||||
const char **properties, PRBool withDepth,
|
||||
nsIWebDAVMetadataListener *listener,
|
||||
PRBool namesOnly);
|
||||
|
||||
nsresult SendPropfindDocumentToChannel(nsIDocument *doc,
|
||||
nsIHttpChannel *channel,
|
||||
nsIStreamListener *listener,
|
||||
PRBool withDepth);
|
||||
nsCOMPtr<nsIIOService> mIOService; // XXX weak?
|
||||
nsAutoString mDAVNSString; // "DAV:"
|
||||
};
|
||||
|
||||
NS_IMPL_ISUPPORTS1_CI(nsWebDAVService, nsIWebDAVService)
|
||||
|
@ -93,13 +123,149 @@ nsWebDAVService::EnsureIOService()
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsWebDAVService::SendPropfindDocumentToChannel(nsIDocument *doc,
|
||||
nsIHttpChannel *channel,
|
||||
nsIStreamListener *listener,
|
||||
PRBool withDepth)
|
||||
{
|
||||
nsCOMPtr<nsIStorageStream> storageStream;
|
||||
// Why do I have to pick values for these? I just want to store some data
|
||||
// for stream access! (And how would script set these?)
|
||||
nsresult rv = NS_NewStorageStream(4 * 1024, 256 * 1024,
|
||||
getter_AddRefs(storageStream));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsIOutputStream> storageOutputStream;
|
||||
rv = storageStream->GetOutputStream(0,
|
||||
getter_AddRefs(storageOutputStream));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsIDocumentEncoder> encoder =
|
||||
do_CreateInstance(NS_DOC_ENCODER_CONTRACTID_BASE "text/xml", &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = encoder->Init(doc, NS_LITERAL_STRING("text/xml"),
|
||||
nsIDocumentEncoder::OutputEncodeBasicEntities);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
encoder->SetCharset(NS_LITERAL_CSTRING("UTF-8"));
|
||||
rv = encoder->EncodeToStream(storageOutputStream);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
storageOutputStream->Close();
|
||||
|
||||
// You gotta really want it.
|
||||
if (PR_LOG_TEST(gDAVLog, 5)) {
|
||||
nsCOMPtr<nsIInputStream> logInputStream;
|
||||
rv = storageStream->NewInputStream(0, getter_AddRefs(logInputStream));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
PRUint32 len, read;
|
||||
logInputStream->Available(&len);
|
||||
|
||||
char *buf = new char[len+1];
|
||||
memset(buf, 0, len+1);
|
||||
logInputStream->Read(buf, len, &read);
|
||||
NS_ASSERTION(len == read, "short read on closed storage stream?");
|
||||
LOG(("XML:\n\n%*s\n\n", len, buf));
|
||||
|
||||
delete [] buf;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIInputStream> inputStream;
|
||||
rv = storageStream->NewInputStream(0, getter_AddRefs(inputStream));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsIUploadChannel> uploadChannel = do_QueryInterface(channel, &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
rv = uploadChannel->SetUploadStream(inputStream,
|
||||
NS_LITERAL_CSTRING("text/xml"), -1);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
channel->SetRequestMethod(NS_LITERAL_CSTRING("PROPFIND"));
|
||||
|
||||
// XXX I wonder how many compilers this will break...
|
||||
const nsACString &depthValue = withDepth ? NS_LITERAL_CSTRING("1") :
|
||||
NS_LITERAL_CSTRING("0");
|
||||
channel->SetRequestHeader(NS_LITERAL_CSTRING("Depth"), depthValue, false);
|
||||
|
||||
if (LOG_ENABLED()) {
|
||||
nsCOMPtr<nsIURI> uri;
|
||||
channel->GetURI(getter_AddRefs(uri));
|
||||
nsCAutoString spec;
|
||||
uri->GetSpec(spec);
|
||||
LOG(("PROPFIND starting for %s", spec.get()));
|
||||
}
|
||||
|
||||
return channel->AsyncOpen(listener, channel);
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsWebDAVService::CreatePropfindDocument(nsIURI *resourceURI,
|
||||
nsIDOMDocument **requestDoc,
|
||||
nsIDOMElement **propfindElt)
|
||||
{
|
||||
nsresult rv;
|
||||
static NS_DEFINE_CID(kDOMDOMDOMDOMImplementationCID,
|
||||
NS_DOM_IMPLEMENTATION_CID);
|
||||
nsCOMPtr<nsIDOMDOMImplementation>
|
||||
implementation(do_CreateInstance(kDOMDOMDOMDOMImplementationCID, &rv));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsIPrivateDOMImplementation>
|
||||
privImpl(do_QueryInterface(implementation));
|
||||
privImpl->Init(resourceURI);
|
||||
|
||||
nsCOMPtr<nsIDOMDocument> doc;
|
||||
nsAutoString emptyString;
|
||||
rv = implementation->CreateDocument(mDAVNSString, emptyString, nsnull,
|
||||
getter_AddRefs(doc));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsIDocument> baseDoc = do_QueryInterface(doc);
|
||||
baseDoc->SetXMLDeclaration(NS_LITERAL_STRING("1.0"), emptyString,
|
||||
emptyString);
|
||||
baseDoc->SetDocumentURI(resourceURI);
|
||||
|
||||
nsCOMPtr<nsIDOMElement> elt;
|
||||
rv = NS_WD_AppendElementWithNS(doc, doc, mDAVNSString, NS_LITERAL_STRING("propfind"),
|
||||
getter_AddRefs(elt));
|
||||
elt->SetPrefix(NS_LITERAL_STRING("D"));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
*requestDoc = doc.get();
|
||||
NS_ADDREF(*requestDoc);
|
||||
*propfindElt = elt.get();
|
||||
NS_ADDREF(*propfindElt);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsWebDAVService::ChannelWithStreamFromResource(nsIWebDAVResource *resource,
|
||||
nsIHttpChannel **channel,
|
||||
nsIInputStream **stream)
|
||||
{
|
||||
nsresult rv = ChannelFromResource(resource, channel);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsIWebDAVResourceWithData> resWithData =
|
||||
do_QueryInterface(resource, &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return resWithData->GetData(stream);
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsWebDAVService::ChannelFromResource(nsIWebDAVResource *resource,
|
||||
nsIHttpChannel **channel)
|
||||
nsIHttpChannel **channel,
|
||||
nsIURI **resourceURI)
|
||||
{
|
||||
ENSURE_IO_SERVICE();
|
||||
|
||||
nsCAutoString spec;
|
||||
|
||||
nsresult rv = resource->GetUrlSpec(spec);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
if (spec.IsEmpty()) {
|
||||
|
@ -115,10 +281,17 @@ nsWebDAVService::ChannelFromResource(nsIWebDAVResource *resource,
|
|||
rv = mIOService->NewChannelFromURI(uri, getter_AddRefs(baseChannel));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (resourceURI) {
|
||||
*resourceURI = uri.get();
|
||||
NS_ADDREF(*resourceURI);
|
||||
}
|
||||
|
||||
return CallQueryInterface(baseChannel, channel);
|
||||
}
|
||||
|
||||
nsWebDAVService::nsWebDAVService()
|
||||
nsWebDAVService::nsWebDAVService() :
|
||||
mDAVNSString(NS_LITERAL_STRING("DAV:"))
|
||||
|
||||
{
|
||||
gDAVLog = PR_NewLogModule("webdav");
|
||||
}
|
||||
|
@ -147,46 +320,114 @@ nsWebDAVService::GetResourcePropertyNames(nsIWebDAVResource *resource,
|
|||
PRBool withDepth,
|
||||
nsIWebDAVMetadataListener *listener)
|
||||
{
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
return PropfindInternal(resource, 0, nsnull, withDepth,
|
||||
listener, PR_TRUE);
|
||||
}
|
||||
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsWebDAVService::GetResourceProperties(nsIWebDAVResource *resource,
|
||||
PRUint32 propCount,
|
||||
const char **properties,
|
||||
PRBool withDepth,
|
||||
nsIWebDAVMetadataListener *listener)
|
||||
{
|
||||
return PropfindInternal(resource, propCount, properties, withDepth,
|
||||
listener, PR_FALSE);
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsWebDAVService::PropfindInternal(nsIWebDAVResource *resource,
|
||||
PRUint32 propCount,
|
||||
const char **properties,
|
||||
PRBool withDepth,
|
||||
nsIWebDAVMetadataListener *listener,
|
||||
PRBool namesOnly)
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
NS_ENSURE_ARG(resource);
|
||||
NS_ENSURE_ARG(listener);
|
||||
|
||||
nsCOMPtr<nsIURI> resourceURI;
|
||||
nsCOMPtr<nsIHttpChannel> channel;
|
||||
rv = ChannelFromResource(resource, getter_AddRefs(channel));
|
||||
rv = ChannelFromResource(resource, getter_AddRefs(channel),
|
||||
getter_AddRefs(resourceURI));
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
// XXX I wonder how many compilers this will break...
|
||||
const nsACString &depthValue = withDepth ? NS_LITERAL_CSTRING("1") :
|
||||
NS_LITERAL_CSTRING("0");
|
||||
channel->SetRequestMethod(NS_LITERAL_CSTRING("PROPFIND"));
|
||||
channel->SetRequestHeader(NS_LITERAL_CSTRING("Depth"), depthValue, false);
|
||||
nsCOMPtr<nsIDOMDocument> requestDoc;
|
||||
nsCOMPtr<nsIDOMElement> propfindElt;
|
||||
rv = CreatePropfindDocument(resourceURI, getter_AddRefs(requestDoc),
|
||||
getter_AddRefs(propfindElt));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (LOG_ENABLED()) {
|
||||
nsCAutoString spec;
|
||||
resource->GetUrlSpec(spec);
|
||||
LOG(("PROPFIND starting for %s", spec.get()));
|
||||
if (namesOnly) {
|
||||
nsCOMPtr<nsIDOMElement> allpropElt;
|
||||
rv = NS_WD_AppendElementWithNS(requestDoc, propfindElt,
|
||||
mDAVNSString, NS_LITERAL_STRING("propname"),
|
||||
getter_AddRefs(allpropElt));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
} else if (propCount == 0) {
|
||||
nsCOMPtr<nsIDOMElement> allpropElt;
|
||||
rv = NS_WD_AppendElementWithNS(requestDoc, propfindElt,
|
||||
mDAVNSString, NS_LITERAL_STRING("allprop"),
|
||||
getter_AddRefs(allpropElt));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
} else {
|
||||
nsCOMPtr<nsIDOMElement> propElt;
|
||||
rv = NS_WD_AppendElementWithNS(requestDoc, propfindElt,
|
||||
mDAVNSString, NS_LITERAL_STRING("prop"),
|
||||
getter_AddRefs(propElt));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
for (PRUint32 i = 0; i < propCount; i++) {
|
||||
nsDependentCString fullpropName(properties[i]);
|
||||
|
||||
// This string math is _ridiculous_. It better compile to a total of
|
||||
// 5 instructions, or I'm ripping it all out and doing my own looping.
|
||||
|
||||
nsACString::const_iterator start, saveStart, end, saveEnd;
|
||||
fullpropName.BeginReading(start);
|
||||
fullpropName.BeginReading(saveStart);
|
||||
fullpropName.EndReading(end);
|
||||
fullpropName.EndReading(saveEnd);
|
||||
RFindInReadable(NS_LITERAL_CSTRING(" "), start, end);
|
||||
|
||||
if (start == end) {
|
||||
nsCAutoString msg(NS_LITERAL_CSTRING("Illegal property name ") +
|
||||
fullpropName);
|
||||
NS_WARNING(msg.get());
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
|
||||
if (LOG_ENABLED()) {
|
||||
nsACString::const_iterator s = start;
|
||||
|
||||
nsCAutoString propNamespace(nsDependentCSubstring(saveStart, s));
|
||||
nsCAutoString propName(nsDependentCSubstring(++s, saveEnd));
|
||||
|
||||
LOG(("prop ns: '%s', name: '%s'", propNamespace.get(), propName.get()));
|
||||
}
|
||||
|
||||
NS_ConvertASCIItoUTF16 propNamespace(nsDependentCSubstring(saveStart, start)),
|
||||
propName(nsDependentCSubstring(++start, saveEnd));
|
||||
|
||||
nsCOMPtr<nsIDOMElement> junk;
|
||||
rv = NS_WD_AppendElementWithNS(requestDoc, propElt, propNamespace,
|
||||
propName, getter_AddRefs(junk));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIStreamListener> streamListener =
|
||||
NS_NewPropfindStreamListener(resource, listener);
|
||||
NS_WD_NewPropfindStreamListener(resource, listener, namesOnly);
|
||||
|
||||
if (!streamListener)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
return channel->AsyncOpen(streamListener, channel);
|
||||
|
||||
nsCOMPtr<nsIDocument> requestBaseDoc = do_QueryInterface(requestDoc);
|
||||
return SendPropfindDocumentToChannel(requestBaseDoc, channel,
|
||||
streamListener, withDepth);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
@ -196,13 +437,6 @@ nsWebDAVService::GetResourceOptions(nsIWebDAVResource *resource,
|
|||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsWebDAVService::GetChildren(nsIWebDAVResource *resource, PRUint32 depth,
|
||||
nsIWebDAVChildrenListener *listener)
|
||||
{
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsWebDAVService::Get(nsIWebDAVResource *resource, nsIStreamListener *listener)
|
||||
{
|
||||
|
@ -215,11 +449,61 @@ nsWebDAVService::Get(nsIWebDAVResource *resource, nsIStreamListener *listener)
|
|||
return channel->AsyncOpen(listener, nsnull);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsWebDAVService::GetToOutputStream(nsIWebDAVResource *resource,
|
||||
nsIOutputStream *stream,
|
||||
nsIWebDAVOperationListener *listener)
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
nsCOMPtr<nsIRequestObserver> getObserver =
|
||||
NS_WD_NewGetOperationRequestObserver(resource, listener);
|
||||
if (!getObserver)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
nsCOMPtr<nsIStreamListener> streamListener;
|
||||
rv = NS_NewSimpleStreamListener(getter_AddRefs(streamListener),
|
||||
stream, getObserver);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return Get(resource, streamListener);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsWebDAVService::Put(nsIWebDAVResourceWithData *resource,
|
||||
const nsACString& contentType,
|
||||
nsIWebDAVOperationListener *listener)
|
||||
{
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
nsCOMPtr<nsIHttpChannel> channel;
|
||||
nsCOMPtr<nsIInputStream> stream;
|
||||
nsresult rv = ChannelWithStreamFromResource(resource,
|
||||
getter_AddRefs(channel),
|
||||
getter_AddRefs(stream));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsIUploadChannel> uploadChannel = do_QueryInterface(channel, &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = uploadChannel->SetUploadStream(stream, contentType, -1);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsIStreamListener> streamListener =
|
||||
NS_WD_NewPutOperationStreamListener(resource, listener);
|
||||
|
||||
if (!streamListener)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
channel->SetRequestMethod(NS_LITERAL_CSTRING("PUT"));
|
||||
|
||||
if (LOG_ENABLED()) {
|
||||
nsCOMPtr<nsIURI> uri;
|
||||
channel->GetURI(getter_AddRefs(uri));
|
||||
nsCAutoString spec;
|
||||
uri->GetSpec(spec);
|
||||
LOG(("PUT starting for %s", spec.get()));
|
||||
}
|
||||
|
||||
return channel->AsyncOpen(streamListener, channel);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
|
|
@ -40,6 +40,7 @@
|
|||
#include "nsIDOMNode.h"
|
||||
#include "nsIDOM3Node.h"
|
||||
#include "nsIDOMNodeList.h"
|
||||
#include "nsIDOMDocument.h"
|
||||
|
||||
#if defined(PR_LOGGING)
|
||||
PRLogModuleInfo *gDAVLog = nsnull;
|
||||
|
@ -77,3 +78,24 @@ NS_WD_ElementTextChildValue(nsIDOMElement *elt, const nsAString &tagName,
|
|||
return node3->GetTextContent(value);
|
||||
}
|
||||
|
||||
nsresult
|
||||
NS_WD_AppendElementWithNS(nsIDOMDocument *doc, nsIDOMNode *parent,
|
||||
const nsAString& ns, const nsAString& tagName,
|
||||
nsIDOMElement **child)
|
||||
{
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsIDOMElement> childElt;
|
||||
nsCOMPtr<nsIDOMNode> junk;
|
||||
|
||||
rv = doc->CreateElementNS(ns, tagName, getter_AddRefs(childElt));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = parent->AppendChild(childElt, getter_AddRefs(junk));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
*child = childElt.get();
|
||||
NS_ADDREF(*child);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,182 @@
|
|||
const C = Components;
|
||||
const CI = C.interfaces;
|
||||
|
||||
function getService(contract, iface)
|
||||
{
|
||||
return C.classes[contract].getService(CI[iface]);
|
||||
}
|
||||
|
||||
function createInstance(contract, iface)
|
||||
{
|
||||
return C.classes[contract].createInstance(CI[iface]);
|
||||
}
|
||||
|
||||
const davSvc = getService("@mozilla.org/webdav/service;1",
|
||||
"nsIWebDAVService");
|
||||
|
||||
function Resource(url)
|
||||
{
|
||||
this.urlSpec = url;
|
||||
}
|
||||
|
||||
Resource.prototype = {
|
||||
QueryInterface: function(outer, iid) {
|
||||
if (iid.equals(CI.nsIWebDAVResource) ||
|
||||
iid.equals(CI.nsISupports)) {
|
||||
return this;
|
||||
}
|
||||
|
||||
throw Components.interfaces.NS_NO_INTERFACE;
|
||||
}
|
||||
};
|
||||
|
||||
function ResourceWithFileData(url, filename)
|
||||
{
|
||||
this.urlSpec = url;
|
||||
this.mFilename = filename;
|
||||
}
|
||||
|
||||
ResourceWithFileData.prototype = {
|
||||
QueryInterface: function(outer, iid) {
|
||||
if (iid.equals(CI.nsIWebDAVResourceWithData))
|
||||
return this;
|
||||
|
||||
return Resource.prototype.QueryInterface.call(this, outer, iid);
|
||||
},
|
||||
|
||||
__proto__: Resource.prototype
|
||||
};
|
||||
|
||||
function propertiesToKeyArray(props)
|
||||
{
|
||||
return props.getKeys({ });
|
||||
}
|
||||
|
||||
function propertiesToObject(props)
|
||||
{
|
||||
var count = { };
|
||||
var keys = props.getKeys({ });
|
||||
|
||||
var propObj = { };
|
||||
for (var i = 0; i < keys.length; i++) {
|
||||
var key = keys[i];
|
||||
var val = props.get(keys[i], CI.nsISupportsString);
|
||||
val = val.data;
|
||||
propObj[key] = val;
|
||||
}
|
||||
|
||||
return propObj;
|
||||
}
|
||||
|
||||
function OperationListener()
|
||||
{
|
||||
}
|
||||
|
||||
OperationListener.prototype =
|
||||
{
|
||||
onPutResult: function (status, resource)
|
||||
{
|
||||
dump("PUT " + resource.urlSpec + " complete: " + status + "\n");
|
||||
stopEventPump();
|
||||
},
|
||||
|
||||
onGetResult: function (status, resource)
|
||||
{
|
||||
dump("GET " + resource.urlSpec + " complete: " + status + "\n");
|
||||
stopEventPump();
|
||||
}
|
||||
}
|
||||
|
||||
function PropfindListener()
|
||||
{
|
||||
}
|
||||
|
||||
PropfindListener.prototype =
|
||||
{
|
||||
onGetPropertyNamesResult: function (status, URL, props)
|
||||
{
|
||||
var keys = propertiesToKeyArray(props);
|
||||
dump(URL + " (" + status + "):\n");
|
||||
for (var i = 0; i < keys.length; i++ )
|
||||
dump(" " + keys[i] + "\n");
|
||||
},
|
||||
|
||||
onGetPropertiesResult: function (status, URL, props)
|
||||
{
|
||||
var propObj = propertiesToObject(props);
|
||||
dump(URL + " (" + status + "):\n");
|
||||
|
||||
for (var i in propObj) {
|
||||
dump(" " + i + " = " + propObj[i] + "\n");
|
||||
}
|
||||
},
|
||||
|
||||
onMetadataComplete: function (status, resource, method)
|
||||
{
|
||||
dump(method + " on " + resource.urlSpec + " completed: " + status +
|
||||
"\n");
|
||||
stopEventPump();
|
||||
}
|
||||
}
|
||||
|
||||
const evQSvc = getService("@mozilla.org/event-queue-service;1",
|
||||
"nsIEventQueueService");
|
||||
const ioSvc = getService("@mozilla.org/network/io-service;1",
|
||||
"nsIIOService");
|
||||
|
||||
const evQ = evQSvc.getSpecialEventQueue(CI.nsIEventQueueService.CURRENT_THREAD_EVENT_QUEUE);
|
||||
|
||||
function runEventPump()
|
||||
{
|
||||
pumpRunning = true;
|
||||
while (pumpRunning) {
|
||||
evQ.processPendingEvents();
|
||||
}
|
||||
}
|
||||
|
||||
function stopEventPump()
|
||||
{
|
||||
pumpRunning = false;
|
||||
}
|
||||
|
||||
function PROPFIND(url, depth, props)
|
||||
{
|
||||
var listener = new PropfindListener();
|
||||
|
||||
if (props) {
|
||||
var length = props.length;
|
||||
} else {
|
||||
var length = 0;
|
||||
props = null;
|
||||
}
|
||||
|
||||
davSvc.getResourceProperties(new Resource(url), length, props, depth,
|
||||
listener);
|
||||
runEventPump();
|
||||
}
|
||||
|
||||
function PROPFIND_names(url, depth)
|
||||
{
|
||||
var listener = new PropfindListener();
|
||||
davSvc.getResourcePropertyNames(new Resource(url), depth, listener);
|
||||
runEventPump();
|
||||
}
|
||||
|
||||
function makeFile(path)
|
||||
{
|
||||
var file = createInstance("@mozilla.org/file/local;1", "nsILocalFile");
|
||||
file.initWithPath(path);
|
||||
return file;
|
||||
}
|
||||
|
||||
function GET(url, filename)
|
||||
{
|
||||
var file = makeFile(filename);
|
||||
var outstream = createInstance("@mozilla.org/network/file-output-stream;1",
|
||||
"nsIFileOutputStream");
|
||||
outstream.init(file, 0x02 | 0x08, 0644, 0);
|
||||
|
||||
davSvc.getToOutputStream(new Resource(url), outstream,
|
||||
new OperationListener());
|
||||
runEventPump();
|
||||
}
|
Загрузка…
Ссылка в новой задаче