зеркало из https://github.com/mozilla/gecko-dev.git
Override same origin check for public services listed in the master service list. b=203371, r=darin@netscape.com sr=jst@netscape.com
This commit is contained in:
Родитель
7146549efc
Коммит
da49627bbe
|
@ -53,10 +53,12 @@ REQUIRES = xpcom \
|
|||
necko \
|
||||
intl \
|
||||
xmlextras \
|
||||
pref \
|
||||
$(NULL)
|
||||
|
||||
CPPSRCS = \
|
||||
nsWebScriptsAccess.cpp \
|
||||
nsWSAUtils.cpp \
|
||||
$(NULL)
|
||||
|
||||
LOCAL_INCLUDES = \
|
||||
|
|
|
@ -0,0 +1,330 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* 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 the web scripts access security code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2003
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s): Harish Dhurvasula <harishd@netscape.com>
|
||||
*
|
||||
* 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 "nsWSAUtils.h"
|
||||
#include "nsReadableUtils.h"
|
||||
#include "nsIStringBundle.h"
|
||||
#include "nsIConsoleService.h"
|
||||
#include "nsIServiceManager.h"
|
||||
#include "nsIDNSService.h"
|
||||
#include "nsIRequest.h"
|
||||
#include "nsEventQueueUtils.h"
|
||||
#include "nsAutoPtr.h"
|
||||
|
||||
static const char kSecurityProperties[] =
|
||||
"chrome://communicator/locale/webservices/security.properties";
|
||||
static NS_DEFINE_CID(kDNSServiceCID, NS_DNSSERVICE_CID);
|
||||
static NS_DEFINE_CID(kEventQueueServiceCID, NS_EVENTQUEUESERVICE_CID);
|
||||
|
||||
class nsDNSListener : public nsIDNSListener
|
||||
{
|
||||
public:
|
||||
nsDNSListener();
|
||||
virtual ~nsDNSListener();
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIDNSLISTENER
|
||||
|
||||
nsCString mOfficialHostName;
|
||||
PRBool mLookupFinished;
|
||||
};
|
||||
|
||||
#ifdef DEBUG
|
||||
|
||||
struct TestStruct {
|
||||
const char* lhs; // string that contains the wild char(s).
|
||||
const char* rhs; // string that is compared against lhs.
|
||||
PRBool equal; // set to true if lhs and rhs are expected
|
||||
// to be equal else set false;
|
||||
};
|
||||
|
||||
static
|
||||
const TestStruct kStrings[] = {
|
||||
{ "f*o*bar", "foobar", PR_TRUE },
|
||||
{ "foo*bar", "foofbar", PR_TRUE },
|
||||
{ "*foo*bar", "ffoofoobbarbarbar", PR_TRUE },
|
||||
{ "*foo*bar*barbar", "ffoofoobbarbarbar", PR_TRUE },
|
||||
{ "http://*.*.*/*", "http://www.mozilla.org/", PR_TRUE},
|
||||
{ "http://*/*", "http://www.mozilla.org/", PR_TRUE},
|
||||
{ "http://*.mozilla.org/*/*", "http://www.mozilla.org/Projects/", PR_TRUE},
|
||||
{ "http://www.m*zi*la.org/*", "http://www.mozilla.org/", PR_TRUE },
|
||||
{ "http://www.mozilla.org/*.html", "http://www.mozilla.org/owners.html", PR_TRUE },
|
||||
{ "http://www.mozilla.org/*.htm*", "http://www.mozilla.org/owners.html", PR_TRUE },
|
||||
{ "http://www.mozilla.org/*rs.htm*", "http://www.mozilla.org/ownres.html", PR_FALSE },
|
||||
{ "http://www.mozilla.org/a*c.html", "http://www.mozilla.org/abcd.html", PR_FALSE },
|
||||
{ "https://www.mozilla.org/*", "http://www.mozilla.org/abcd.html", PR_FALSE },
|
||||
};
|
||||
|
||||
void
|
||||
nsWSAUtils::VerifyIsEqual()
|
||||
{
|
||||
static PRUint32 size = NS_ARRAY_LENGTH(kStrings);
|
||||
PRUint32 i;
|
||||
for (i = 0; i < size; ++i) {
|
||||
if (IsEqual(NS_ConvertUTF8toUCS2(kStrings[i].lhs),
|
||||
NS_ConvertUTF8toUCS2(kStrings[i].rhs))
|
||||
!= kStrings[i].equal) {
|
||||
const char* equal =
|
||||
kStrings[i].equal ? "equivalent" :
|
||||
"not equivalent";
|
||||
printf("\nTest Failed: %s is %s to %s.\n",
|
||||
kStrings[i].lhs, equal, kStrings[i].rhs);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/**
|
||||
* This method compares two strings where the lhs string value may contain
|
||||
* asterisk. Therefore, an lhs with a value of "he*o" should be equal to a rhs
|
||||
* value of "hello" or "hero" etc.. These strings are compared as follows:
|
||||
* 1) Characters before the first asterisk are compared from left to right.
|
||||
* Thus if the lhs string did not contain an asterisk then we just do
|
||||
* a simple string comparison.
|
||||
* 2) Match a pattern, found between asterisk. That is, if lhs and rhs were
|
||||
* "h*ll*" and "hello" respectively, then compare the pattern "ll".
|
||||
* 3) Characters after the last asterisk are compared from right to left.
|
||||
* Thus, "*lo" == "hello" and != "blow"
|
||||
*/
|
||||
PRBool
|
||||
nsWSAUtils::IsEqual(const nsAString& aLhs, const nsAString& aRhs)
|
||||
{
|
||||
nsAString::const_iterator lhs_begin, lhs_end;
|
||||
nsAString::const_iterator rhs_begin, rhs_end;
|
||||
|
||||
aLhs.BeginReading(lhs_begin);
|
||||
aLhs.EndReading(lhs_end);
|
||||
aRhs.BeginReading(rhs_begin);
|
||||
aRhs.EndReading(rhs_end);
|
||||
|
||||
PRBool pattern_before_asterisk = PR_TRUE;
|
||||
nsAString::const_iterator curr_posn = lhs_begin;
|
||||
while (curr_posn != lhs_end) {
|
||||
if (*lhs_begin == '*') {
|
||||
pattern_before_asterisk = PR_FALSE;
|
||||
++lhs_begin; // Do this to not include '*' when pattern matching.
|
||||
}
|
||||
else if (pattern_before_asterisk) {
|
||||
// Match character by character to see if lhs and rhs are identical
|
||||
if (*curr_posn != *rhs_begin) {
|
||||
return PR_FALSE;
|
||||
}
|
||||
++lhs_begin;
|
||||
++curr_posn;
|
||||
++rhs_begin;
|
||||
if (rhs_begin == rhs_end &&
|
||||
curr_posn == lhs_end) {
|
||||
return PR_TRUE; // lhs and rhs matched perfectly
|
||||
}
|
||||
}
|
||||
else if (++curr_posn == lhs_end) {
|
||||
if (curr_posn != lhs_begin) {
|
||||
// Here we're matching the last few characters to make sure
|
||||
// that lhs is actually equal to rhs. Ex. "a*c" != "abcd"
|
||||
// and "*xabcd" != "abcd".
|
||||
PRBool done = PR_FALSE;
|
||||
for (;;) {
|
||||
if (--curr_posn == lhs_begin)
|
||||
done = PR_TRUE;
|
||||
if (rhs_end == rhs_begin)
|
||||
return PR_FALSE;
|
||||
if (*(--rhs_end) != *curr_posn)
|
||||
return PR_FALSE;
|
||||
if (done)
|
||||
return PR_TRUE;
|
||||
}
|
||||
}
|
||||
// No discrepency between lhs and rhs
|
||||
return PR_TRUE;
|
||||
}
|
||||
else if (*curr_posn == '*') {
|
||||
// Matching pattern between asterisks. That is, in "h*ll*" we
|
||||
// check to see if "ll" exists in the rhs string.
|
||||
const nsAString& pattern = Substring(lhs_begin, curr_posn);
|
||||
|
||||
nsAString::const_iterator tmp_end = rhs_end;
|
||||
if (!FindInReadable(pattern, rhs_begin, rhs_end)) {
|
||||
return PR_FALSE;
|
||||
}
|
||||
rhs_begin = rhs_end;
|
||||
rhs_end = tmp_end;
|
||||
lhs_begin = curr_posn;
|
||||
}
|
||||
}
|
||||
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsWSAUtils::ReportError(const PRUnichar* aMessageID,
|
||||
const PRUnichar** aInputs,
|
||||
const PRInt32 aLength)
|
||||
{
|
||||
nsCOMPtr<nsIStringBundleService> bundleService
|
||||
= do_GetService(NS_STRINGBUNDLE_CONTRACTID);
|
||||
NS_ENSURE_TRUE(bundleService, NS_OK); // intentionally returning NS_OK;
|
||||
|
||||
nsCOMPtr<nsIStringBundle> bundle;
|
||||
bundleService->CreateBundle(kSecurityProperties, getter_AddRefs(bundle));
|
||||
NS_ENSURE_TRUE(bundle, NS_OK);
|
||||
|
||||
nsXPIDLString message;
|
||||
bundle->FormatStringFromName(aMessageID, aInputs, aLength,
|
||||
getter_Copies(message));
|
||||
|
||||
nsCOMPtr<nsIConsoleService> consoleService =
|
||||
do_GetService(NS_CONSOLESERVICE_CONTRACTID);
|
||||
NS_ENSURE_TRUE(consoleService, NS_OK); // intentionally returning NS_OK;
|
||||
|
||||
return consoleService->LogStringMessage(message.get());
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsWSAUtils::GetOfficialHostName(nsIURI* aServiceURI,
|
||||
nsACString& aResult)
|
||||
{
|
||||
NS_ASSERTION(aServiceURI, "Cannot get FQDN for a null URI!");
|
||||
|
||||
if (!aServiceURI)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsIDNSService> dns(do_GetService(kDNSServiceCID, &rv));
|
||||
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
nsXPIDLCString host;
|
||||
aServiceURI->GetHost(host);
|
||||
|
||||
nsRefPtr<nsDNSListener> listener = new nsDNSListener();
|
||||
NS_ENSURE_TRUE(listener, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
nsCOMPtr<nsIRequest> dummy;
|
||||
rv = dns->Lookup(host, listener, nsnull, getter_AddRefs(dummy));
|
||||
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
nsCOMPtr<nsIEventQueueService> eventQService =
|
||||
do_GetService(kEventQueueServiceCID, &rv);
|
||||
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
nsCOMPtr<nsIEventQueue> eventQ;
|
||||
rv = eventQService->PushThreadEventQueue(getter_AddRefs(eventQ));
|
||||
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
while (!listener->mLookupFinished)
|
||||
eventQ->ProcessPendingEvents();
|
||||
|
||||
eventQService->PopThreadEventQueue(eventQ);
|
||||
|
||||
aResult.Assign(listener->mOfficialHostName);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
static void* PR_CALLBACK
|
||||
EventHandler(PLEvent *aEvent)
|
||||
{
|
||||
nsDNSListener* listener = (nsDNSListener*)PL_GetEventOwner(aEvent);
|
||||
if (listener)
|
||||
listener->mLookupFinished = PR_TRUE;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void PR_CALLBACK
|
||||
DestroyHandler(PLEvent *aEvent)
|
||||
{
|
||||
delete aEvent;
|
||||
}
|
||||
|
||||
NS_IMPL_THREADSAFE_ISUPPORTS1(nsDNSListener,
|
||||
nsIDNSListener);
|
||||
|
||||
nsDNSListener::nsDNSListener()
|
||||
: mLookupFinished(PR_FALSE)
|
||||
{
|
||||
}
|
||||
|
||||
nsDNSListener::~nsDNSListener()
|
||||
{
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDNSListener::OnStartLookup(nsISupports* aContext, const char* aHost)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDNSListener::OnFound(nsISupports* aContext,
|
||||
const char* aHost,
|
||||
nsHostEnt* aHostEnt)
|
||||
{
|
||||
if (aHostEnt)
|
||||
mOfficialHostName.Assign(aHostEnt->hostEnt.h_name);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDNSListener::OnStopLookup(nsISupports* aContext,
|
||||
const char* aHost,
|
||||
nsresult aStatus)
|
||||
{
|
||||
// Post an event to the UI thread's event queue to cause
|
||||
// ProcessPendingEvents to run.
|
||||
nsCOMPtr<nsIEventQueue> uiEventQ;
|
||||
nsresult rv = NS_GetMainEventQ(getter_AddRefs(uiEventQ));
|
||||
if (uiEventQ) {
|
||||
PLEvent* event = new PLEvent();
|
||||
NS_ENSURE_TRUE(event, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
PL_InitEvent(event, this, EventHandler, DestroyHandler);
|
||||
rv = uiEventQ->PostEvent(event);
|
||||
if (NS_FAILED(rv))
|
||||
PL_DestroyEvent(event);
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
|
@ -0,0 +1,65 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* 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 the web scripts access security code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2003
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s): Harish Dhurvasula <harishd@netscape.com>
|
||||
*
|
||||
* 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 ***** */
|
||||
|
||||
#ifndef nsWSAUtils_h__
|
||||
#define nsWSAUtils_h__
|
||||
|
||||
#include "nsIDNSListener.h"
|
||||
#include "nsIEventQueueService.h"
|
||||
#include "nsIURI.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsString.h"
|
||||
|
||||
class nsWSAUtils
|
||||
{
|
||||
public:
|
||||
static PRBool IsEqual(const nsAString& aLhs, const nsAString& aRhs);
|
||||
static nsresult ReportError(const PRUnichar* aMessageID,
|
||||
const PRUnichar** aInputs,
|
||||
const PRInt32 aLength);
|
||||
static nsresult GetOfficialHostName(nsIURI* aURI, nsACString& aResult);
|
||||
#ifdef DEBUG
|
||||
static void VerifyIsEqual();
|
||||
#endif
|
||||
|
||||
private:
|
||||
// Use the |static| methods |only|
|
||||
nsWSAUtils() {}
|
||||
~nsWSAUtils() {}
|
||||
};
|
||||
|
||||
#endif
|
|
@ -43,23 +43,31 @@
|
|||
#include "nsIDOMNodeList.h"
|
||||
#include "nsIDOMAttr.h"
|
||||
#include "nsIDOMNamedNodeMap.h"
|
||||
#include "nsComponentManagerUtils.h"
|
||||
#include "nsIServiceManagerUtils.h"
|
||||
#include "nsICodebasePrincipal.h"
|
||||
#include "nsIURL.h"
|
||||
#include "nsReadableUtils.h"
|
||||
#include "nsIHttpChannel.h"
|
||||
#include "nsNetUtil.h"
|
||||
#include "nsIStringBundle.h"
|
||||
#include "nsIConsoleService.h"
|
||||
#include "nsIXPConnect.h"
|
||||
#include "jsapi.h"
|
||||
|
||||
#define WSA_GRANT_ACCESS_TO_ALL (1 << 0)
|
||||
#define WSA_FILE_NOT_FOUND (1 << 1)
|
||||
#define WSA_FILE_DELEGATED (1 << 2)
|
||||
#include "nsISOAPCall.h"
|
||||
#include "nsISOAPEncoding.h"
|
||||
#include "nsISOAPResponse.h"
|
||||
#include "nsISOAPFault.h"
|
||||
#include "nsISOAPParameter.h"
|
||||
#include "nsISOAPBlock.h"
|
||||
#include "nsIVariant.h"
|
||||
#include "nsIPrefService.h"
|
||||
#include "nsIPrefBranchInternal.h"
|
||||
#include "nsIPref.h"
|
||||
#include "nsIJSContextStack.h"
|
||||
|
||||
#define SECURITY_PROPERTIES "chrome://communicator/locale/webservices/security.properties"
|
||||
#define WSA_GRANT_ACCESS_TO_ALL (1 << 0)
|
||||
#define WSA_FILE_NOT_FOUND (1 << 1)
|
||||
#define WSA_FILE_DELEGATED (1 << 2)
|
||||
#define SERVICE_LISTED_PUBLIC (1 << 3)
|
||||
#define HAS_MASTER_SERVICE_DECISION (1 << 4)
|
||||
|
||||
NS_NAMED_LITERAL_STRING(kNamespace2002, "http://www.mozilla.org/2002/soap/security");
|
||||
|
||||
|
@ -75,132 +83,8 @@ NS_NAMED_LITERAL_STRING(kFromAttr, "from");
|
|||
// Default attribute value
|
||||
NS_NAMED_LITERAL_STRING(kAny, "any");
|
||||
|
||||
/**
|
||||
* This method compares two strings where the lhs string value may contain
|
||||
* asterisk. Therefore, an lhs with a value of "he*o" should be equal to a rhs
|
||||
* value of "hello" or "hero" etc.. These strings are compared as follows:
|
||||
* 1) Characters before the first asterisk are compared from left to right.
|
||||
* Thus if the lhs string did not contain an asterisk then we just do
|
||||
* a simple string comparison.
|
||||
* 2) Match a pattern, found between asterisk. That is, if lhs and rhs were
|
||||
* "h*ll*" and "hello" respectively, then compare the pattern "ll".
|
||||
* 3) Characters after the last asterisk are compared from right to left.
|
||||
* Thus, "*lo" == "hello" and != "blow"
|
||||
*/
|
||||
static PRBool
|
||||
IsEqual(const nsAString& aLhs, const nsAString& aRhs)
|
||||
{
|
||||
nsAString::const_iterator lhs_begin, lhs_end;
|
||||
nsAString::const_iterator rhs_begin, rhs_end;
|
||||
|
||||
aLhs.BeginReading(lhs_begin);
|
||||
aLhs.EndReading(lhs_end);
|
||||
aRhs.BeginReading(rhs_begin);
|
||||
aRhs.EndReading(rhs_end);
|
||||
|
||||
PRBool pattern_before_asterisk = PR_TRUE;
|
||||
nsAString::const_iterator curr_posn = lhs_begin;
|
||||
while (curr_posn != lhs_end) {
|
||||
if (*lhs_begin == '*') {
|
||||
pattern_before_asterisk = PR_FALSE;
|
||||
++lhs_begin; // Do this to not include '*' when pattern matching.
|
||||
}
|
||||
else if (pattern_before_asterisk) {
|
||||
// Match character by character to see if lhs and rhs are identical
|
||||
if (*curr_posn != *rhs_begin) {
|
||||
return PR_FALSE;
|
||||
}
|
||||
++lhs_begin;
|
||||
++curr_posn;
|
||||
++rhs_begin;
|
||||
if (rhs_begin == rhs_end &&
|
||||
curr_posn == lhs_end) {
|
||||
return PR_TRUE; // lhs and rhs matched perfectly
|
||||
}
|
||||
}
|
||||
else if (++curr_posn == lhs_end) {
|
||||
if (curr_posn != lhs_begin) {
|
||||
// Here we're matching the last few characters to make sure
|
||||
// that lhs is actually equal to rhs. Ex. "a*c" != "abcd"
|
||||
// and "*xabcd" != "abcd".
|
||||
PRBool done = PR_FALSE;
|
||||
for (;;) {
|
||||
if (--curr_posn == lhs_begin)
|
||||
done = PR_TRUE;
|
||||
if (rhs_end == rhs_begin)
|
||||
return PR_FALSE;
|
||||
if (*(--rhs_end) != *curr_posn)
|
||||
return PR_FALSE;
|
||||
if (done)
|
||||
return PR_TRUE;
|
||||
}
|
||||
}
|
||||
// No discrepency between lhs and rhs
|
||||
return PR_TRUE;
|
||||
}
|
||||
else if (*curr_posn == '*') {
|
||||
// Matching pattern between asterisks. That is, in "h*ll*" we
|
||||
// check to see if "ll" exists in the rhs string.
|
||||
const nsAString& pattern = Substring(lhs_begin, curr_posn);
|
||||
|
||||
nsAString::const_iterator tmp_end = rhs_end;
|
||||
if (!FindInReadable(pattern, rhs_begin, rhs_end)) {
|
||||
return PR_FALSE;
|
||||
}
|
||||
rhs_begin = rhs_end;
|
||||
rhs_end = tmp_end;
|
||||
lhs_begin = curr_posn;
|
||||
}
|
||||
}
|
||||
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
|
||||
struct TestStruct {
|
||||
const char* lhs; // string that contains the wild char(s).
|
||||
const char* rhs; // string that is compared against lhs.
|
||||
PRBool equal; // set to true if lhs and rhs are expected
|
||||
// to be equal else set false;
|
||||
};
|
||||
|
||||
static
|
||||
const TestStruct kStrings[] = {
|
||||
{ "f*o*bar", "foobar", PR_TRUE },
|
||||
{ "foo*bar", "foofbar", PR_TRUE },
|
||||
{ "*foo*bar", "ffoofoobbarbarbar", PR_TRUE },
|
||||
{ "*foo*bar*barbar", "ffoofoobbarbarbar", PR_TRUE },
|
||||
{ "http://*.*.*/*", "http://www.mozilla.org/", PR_TRUE},
|
||||
{ "http://*/*", "http://www.mozilla.org/", PR_TRUE},
|
||||
{ "http://*.mozilla.org/*/*", "http://www.mozilla.org/Projects/", PR_TRUE},
|
||||
{ "http://www.m*zi*la.org/*", "http://www.mozilla.org/", PR_TRUE },
|
||||
{ "http://www.mozilla.org/*.html", "http://www.mozilla.org/owners.html", PR_TRUE },
|
||||
{ "http://www.mozilla.org/*.htm*", "http://www.mozilla.org/owners.html", PR_TRUE },
|
||||
{ "http://www.mozilla.org/*rs.htm*", "http://www.mozilla.org/ownres.html", PR_FALSE },
|
||||
{ "http://www.mozilla.org/a*c.html", "http://www.mozilla.org/abcd.html", PR_FALSE },
|
||||
{ "https://www.mozilla.org/*", "http://www.mozilla.org/abcd.html", PR_FALSE },
|
||||
};
|
||||
|
||||
static
|
||||
void VerifyIsEqual()
|
||||
{
|
||||
static PRUint32 size = sizeof(kStrings)/sizeof(kStrings[0]);
|
||||
PRUint32 i;
|
||||
for (i = 0; i < size; ++i) {
|
||||
if (IsEqual(NS_ConvertUTF8toUCS2(kStrings[i].lhs),
|
||||
NS_ConvertUTF8toUCS2(kStrings[i].rhs))
|
||||
!= kStrings[i].equal) {
|
||||
const char* equal =
|
||||
kStrings[i].equal ? "equivalent" :
|
||||
"not equivalent";
|
||||
printf("\nTest Failed: %s is %s to %s.\n",
|
||||
kStrings[i].lhs, equal, kStrings[i].rhs);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
// Method name. Note: This method should be implemented by master services.
|
||||
NS_NAMED_LITERAL_STRING(kIsServicePublic, "isServicePublic");
|
||||
|
||||
static PRBool PR_CALLBACK
|
||||
FreeEntries(nsHashKey *aKey, void *aData, void* aClosure)
|
||||
|
@ -212,10 +96,10 @@ FreeEntries(nsHashKey *aKey, void *aData, void* aClosure)
|
|||
|
||||
NS_IMPL_ISUPPORTS1(nsWebScriptsAccess,
|
||||
nsIWebScriptsAccessService)
|
||||
|
||||
|
||||
nsWebScriptsAccess::nsWebScriptsAccess()
|
||||
{
|
||||
NS_INIT_ISUPPORTS();
|
||||
}
|
||||
|
||||
nsWebScriptsAccess::~nsWebScriptsAccess()
|
||||
|
@ -243,31 +127,6 @@ nsWebScriptsAccess::CanAccess(nsIURI* aTransportURI,
|
|||
if (NS_FAILED(rv) || *aAccessGranted)
|
||||
return rv;
|
||||
|
||||
rv = mSecurityManager->CheckSameOrigin(0, aTransportURI);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
// script security manager has granted access
|
||||
*aAccessGranted = PR_TRUE;
|
||||
return rv;
|
||||
}
|
||||
else {
|
||||
// Script security manager has denied access and has set an
|
||||
// exception. Clear the exception and fall back on the new
|
||||
// security model's decision.
|
||||
nsCOMPtr<nsIXPConnect> xpc(do_GetService(nsIXPConnect::GetCID()));
|
||||
if (xpc) {
|
||||
nsCOMPtr<nsIXPCNativeCallContext> cc;
|
||||
xpc->GetCurrentNativeCallContext(getter_AddRefs(cc));
|
||||
if (cc) {
|
||||
JSContext* cx;
|
||||
rv = cc->GetJSContext(&cx);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
JS_ClearPendingException(cx);
|
||||
cc->SetExceptionWasThrown(PR_FALSE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mServiceURI = aTransportURI;
|
||||
|
||||
nsXPIDLCString path;
|
||||
|
@ -275,8 +134,36 @@ nsWebScriptsAccess::CanAccess(nsIURI* aTransportURI,
|
|||
path += '/';
|
||||
|
||||
AccessInfoEntry* entry = 0;
|
||||
rv = GetAccessInfoEntry(path, PR_FALSE, &entry);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
rv = GetAccessInfoEntry(path, &entry);
|
||||
if (!entry) {
|
||||
rv = mSecurityManager->CheckSameOrigin(0, aTransportURI);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
// script security manager has granted access
|
||||
*aAccessGranted = PR_TRUE;
|
||||
return rv;
|
||||
}
|
||||
else {
|
||||
// Script security manager has denied access and has set an
|
||||
// exception. Clear the exception and fall back on the new
|
||||
// security model's decision.
|
||||
nsCOMPtr<nsIXPConnect> xpc(do_GetService(nsIXPConnect::GetCID()));
|
||||
if (xpc) {
|
||||
nsCOMPtr<nsIXPCNativeCallContext> cc;
|
||||
xpc->GetCurrentNativeCallContext(getter_AddRefs(cc));
|
||||
if (cc) {
|
||||
JSContext* cx;
|
||||
rv = cc->GetJSContext(&cx);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
JS_ClearPendingException(cx);
|
||||
cc->SetExceptionWasThrown(PR_FALSE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
rv = CreateEntry(path, PR_FALSE, &entry);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
return CheckAccess(entry, aRequestType, aAccessGranted);
|
||||
}
|
||||
|
@ -301,86 +188,24 @@ nsWebScriptsAccess::InvalidateCache(const char* aTransportURI)
|
|||
|
||||
nsresult
|
||||
nsWebScriptsAccess::GetAccessInfoEntry(const char* aKey,
|
||||
const PRBool aIsDelegated,
|
||||
AccessInfoEntry** aEntry)
|
||||
{
|
||||
nsCStringKey key(aKey);
|
||||
|
||||
*aEntry = NS_REINTERPRET_CAST(AccessInfoEntry*, mAccessInfoTable.Get(&key));
|
||||
|
||||
if (!*aEntry) {
|
||||
// There's no entry for this server. Load the declaration file (
|
||||
// web-scripts-access.xml ) and extract access information from
|
||||
// it. Record the extracted info. for this session
|
||||
nsCOMPtr<nsIDOMDocument> document;
|
||||
nsresult rv =
|
||||
GetDocument(PromiseFlatCString(nsDependentCString(aKey) +
|
||||
NS_LITERAL_CSTRING("web-scripts-access.xml")).get(),
|
||||
getter_AddRefs(document));
|
||||
if (*aEntry && ((*aEntry)->mFlags & WSA_FILE_DELEGATED)) {
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsIURL> url(do_QueryInterface(mServiceURI, &rv));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
if (document) {
|
||||
// Extract access information from the document.
|
||||
rv = GetInfoFromDocument(document, aIsDelegated, aEntry);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCAutoString path;
|
||||
url->GetPrePath(path);
|
||||
nsCAutoString directory;
|
||||
url->GetDirectory(directory);
|
||||
path += directory;
|
||||
|
||||
// If the document is invalid then an entry will not be created.
|
||||
if (!*aEntry)
|
||||
return NS_OK;
|
||||
}
|
||||
else {
|
||||
rv = CreateAccessInfoEntry(WSA_FILE_NOT_FOUND, aEntry);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
mAccessInfoTable.Put(&key, *aEntry);
|
||||
return GetAccessInfoEntry(path.get(), aEntry);
|
||||
}
|
||||
NS_ASSERTION(*aEntry, "unexpected: access info entry is null!");
|
||||
if (*aEntry && ((*aEntry)->mFlags & WSA_FILE_DELEGATED))
|
||||
return GetDelegatedInfo(aEntry);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsWebScriptsAccess::GetInfoFromDocument(nsIDOMDocument* aDocument,
|
||||
const PRBool aIsDelegated,
|
||||
AccessInfoEntry** aEntry)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aDocument);
|
||||
PRBool valid;
|
||||
nsresult rv = ValidateDocument(aDocument, &valid);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (!valid) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (!aIsDelegated) {
|
||||
nsCOMPtr<nsIDOMNodeList> delegateList;
|
||||
rv = aDocument->GetElementsByTagNameNS(kNamespace2002, kDelegateTag,
|
||||
getter_AddRefs(delegateList));
|
||||
NS_ENSURE_TRUE(delegateList, rv);
|
||||
nsCOMPtr<nsIDOMNode> node;
|
||||
delegateList->Item(0, getter_AddRefs(node));
|
||||
if (node) {
|
||||
rv = CreateAccessInfoEntry(WSA_FILE_DELEGATED, aEntry);
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIDOMNodeList> allowList;
|
||||
rv = aDocument->GetElementsByTagNameNS(kNamespace2002, kAllowTag,
|
||||
getter_AddRefs(allowList));
|
||||
NS_ENSURE_TRUE(allowList, rv);
|
||||
|
||||
PRUint32 count;
|
||||
allowList->GetLength(&count);
|
||||
if (count) {
|
||||
rv = CreateAccessInfoEntry(allowList, aEntry);
|
||||
}
|
||||
else {
|
||||
// Since there are no ALLOW elements present grant access to all.
|
||||
rv = CreateAccessInfoEntry(WSA_GRANT_ACCESS_TO_ALL, aEntry);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -444,25 +269,93 @@ nsWebScriptsAccess::GetCodebaseURI(nsIURI** aCodebase)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsWebScriptsAccess::GetDelegatedInfo(AccessInfoEntry** aEntry)
|
||||
nsresult
|
||||
nsWebScriptsAccess::CreateEntry(const char* aKey,
|
||||
const PRBool aIsDelegated,
|
||||
AccessInfoEntry** aEntry)
|
||||
{
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsIURL> url(do_QueryInterface(mServiceURI, &rv));
|
||||
NS_ENSURE_ARG_POINTER(aEntry);
|
||||
*aEntry = nsnull;
|
||||
// create an entry by loading the declaration file (
|
||||
// web-scripts-access.xml ) and extracting access information from
|
||||
// it. Record the extracted info. for this session
|
||||
nsCOMPtr<nsIDOMDocument> document;
|
||||
nsresult rv =
|
||||
GetDocument(PromiseFlatCString(nsDependentCString(aKey) +
|
||||
NS_LITERAL_CSTRING("web-scripts-access.xml")).get(),
|
||||
getter_AddRefs(document));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsXPIDLCString path;
|
||||
url->GetPrePath(path);
|
||||
nsXPIDLCString directory;
|
||||
url->GetDirectory(directory);
|
||||
path += directory;
|
||||
if (document) {
|
||||
// Create an entry by extracting access information from the document.
|
||||
rv = CreateEntry(document, aIsDelegated, aEntry);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return GetAccessInfoEntry(path, PR_TRUE, aEntry);
|
||||
// If the document is invalid then an entry will not be created.
|
||||
if (!*aEntry)
|
||||
return NS_OK;
|
||||
}
|
||||
else {
|
||||
rv = CreateEntry(WSA_FILE_NOT_FOUND, aEntry);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
nsCStringKey key(aKey);
|
||||
mAccessInfoTable.Put(&key, *aEntry);
|
||||
|
||||
NS_ASSERTION(*aEntry, "unexpected: access info entry is null!");
|
||||
if (*aEntry && ((*aEntry)->mFlags & WSA_FILE_DELEGATED))
|
||||
rv = CreateDelegatedEntry(aEntry);
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsWebScriptsAccess::CreateEntry(nsIDOMDocument* aDocument,
|
||||
const PRBool aIsDelegated,
|
||||
AccessInfoEntry** aEntry)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aDocument);
|
||||
NS_ENSURE_ARG_POINTER(aEntry);
|
||||
*aEntry = nsnull;
|
||||
|
||||
PRBool valid;
|
||||
nsresult rv = ValidateDocument(aDocument, &valid);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (!valid) {
|
||||
return NS_OK; // XXX should I return an error instead ?
|
||||
}
|
||||
|
||||
if (!aIsDelegated) {
|
||||
nsCOMPtr<nsIDOMNodeList> delegateList;
|
||||
rv = aDocument->GetElementsByTagNameNS(kNamespace2002, kDelegateTag,
|
||||
getter_AddRefs(delegateList));
|
||||
NS_ENSURE_TRUE(delegateList, rv);
|
||||
nsCOMPtr<nsIDOMNode> node;
|
||||
delegateList->Item(0, getter_AddRefs(node));
|
||||
if (node)
|
||||
return CreateEntry(WSA_FILE_DELEGATED, aEntry);
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIDOMNodeList> allowList;
|
||||
rv = aDocument->GetElementsByTagNameNS(kNamespace2002, kAllowTag,
|
||||
getter_AddRefs(allowList));
|
||||
NS_ENSURE_TRUE(allowList, rv);
|
||||
|
||||
PRUint32 count;
|
||||
allowList->GetLength(&count);
|
||||
if (count) {
|
||||
rv = CreateEntry(allowList, aEntry);
|
||||
}
|
||||
else {
|
||||
// Since there are no ALLOW elements present grant access to all.
|
||||
rv = CreateEntry(WSA_GRANT_ACCESS_TO_ALL, aEntry);
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsWebScriptsAccess::CreateAccessInfoEntry(const PRInt32 aFlags,
|
||||
AccessInfoEntry** aEntry)
|
||||
nsWebScriptsAccess::CreateEntry(const PRInt32 aFlags,
|
||||
AccessInfoEntry** aEntry)
|
||||
{
|
||||
*aEntry = new AccessInfoEntry(aFlags);
|
||||
NS_ENSURE_TRUE(*aEntry, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
@ -471,11 +364,13 @@ nsWebScriptsAccess::CreateAccessInfoEntry(const PRInt32 aFlags,
|
|||
}
|
||||
|
||||
nsresult
|
||||
nsWebScriptsAccess::CreateAccessInfoEntry(nsIDOMNodeList* aAllowList,
|
||||
AccessInfoEntry** aEntry)
|
||||
nsWebScriptsAccess::CreateEntry(nsIDOMNodeList* aAllowList,
|
||||
AccessInfoEntry** aEntry)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aAllowList);
|
||||
|
||||
NS_ENSURE_ARG_POINTER(aEntry);
|
||||
*aEntry = nsnull;
|
||||
|
||||
nsAutoPtr<AccessInfoEntry> entry(new AccessInfoEntry());
|
||||
NS_ENSURE_TRUE(entry, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
|
@ -529,6 +424,25 @@ nsWebScriptsAccess::CreateAccessInfoEntry(nsIDOMNodeList* aAllowList,
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsWebScriptsAccess::CreateDelegatedEntry(AccessInfoEntry** aEntry)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aEntry);
|
||||
*aEntry = nsnull;
|
||||
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsIURL> url(do_QueryInterface(mServiceURI, &rv));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCAutoString path;
|
||||
url->GetPrePath(path);
|
||||
nsCAutoString directory;
|
||||
url->GetDirectory(directory);
|
||||
path += directory;
|
||||
|
||||
return CreateEntry(path.get(), PR_TRUE, aEntry);
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsWebScriptsAccess::CheckAccess(AccessInfoEntry* aEntry,
|
||||
const nsAString& aRequestType,
|
||||
|
@ -538,24 +452,44 @@ nsWebScriptsAccess::CheckAccess(AccessInfoEntry* aEntry,
|
|||
static PRBool verified = PR_FALSE;
|
||||
if (!verified) {
|
||||
verified = PR_TRUE;
|
||||
VerifyIsEqual();
|
||||
nsWSAUtils::VerifyIsEqual();
|
||||
}
|
||||
#endif
|
||||
|
||||
*aAccessGranted = PR_FALSE;
|
||||
NS_ENSURE_ARG_POINTER(aEntry);
|
||||
|
||||
nsresult rv = NS_OK;
|
||||
if (aEntry->mFlags & WSA_FILE_NOT_FOUND) {
|
||||
return NS_OK;
|
||||
}
|
||||
if (aEntry->mFlags & HAS_MASTER_SERVICE_DECISION) {
|
||||
if (aEntry->mFlags & SERVICE_LISTED_PUBLIC)
|
||||
*aAccessGranted = PR_TRUE;
|
||||
return rv;
|
||||
}
|
||||
nsCAutoString fqdn;
|
||||
rv = nsWSAUtils::GetOfficialHostName(mServiceURI, fqdn);
|
||||
if (NS_FAILED(rv) || fqdn.IsEmpty())
|
||||
return rv;
|
||||
|
||||
PRBool isPublic = PR_FALSE;
|
||||
rv = IsPublicService(fqdn.get(), &isPublic);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
if (isPublic) {
|
||||
aEntry->mFlags |= SERVICE_LISTED_PUBLIC;
|
||||
*aAccessGranted = PR_TRUE;
|
||||
}
|
||||
aEntry->mFlags |= HAS_MASTER_SERVICE_DECISION;
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
if (aEntry->mFlags & WSA_GRANT_ACCESS_TO_ALL) {
|
||||
*aAccessGranted = PR_TRUE;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIURI> codebase_uri;
|
||||
nsresult rv = GetCodebaseURI(getter_AddRefs(codebase_uri));
|
||||
rv = GetCodebaseURI(getter_AddRefs(codebase_uri));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsXPIDLCString tmp;
|
||||
|
@ -577,14 +511,15 @@ nsWebScriptsAccess::CheckAccess(AccessInfoEntry* aEntry,
|
|||
break;
|
||||
}
|
||||
else {
|
||||
if (IsEqual(nsDependentString(access_info->mFrom), codebase)) {
|
||||
if (nsWSAUtils::IsEqual(nsDependentString(access_info->mFrom),
|
||||
codebase)) {
|
||||
*aAccessGranted = PR_TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -618,13 +553,15 @@ nsWebScriptsAccess::ValidateDocument(nsIDOMDocument* aDocument,
|
|||
|
||||
if (!ns.Equals(kNamespace2002)) {
|
||||
const PRUnichar *inputs[1] = { ns.get() };
|
||||
return ReportError(NS_LITERAL_STRING("UnsupportedNamespace").get(),
|
||||
inputs, 1);
|
||||
return nsWSAUtils::ReportError(
|
||||
NS_LITERAL_STRING("UnsupportedNamespace").get(),
|
||||
inputs, 1);
|
||||
}
|
||||
if (!name.Equals(kWebScriptAccessTag)) {
|
||||
const PRUnichar *inputs[1] = { name.get() };
|
||||
return ReportError(NS_LITERAL_STRING("UnknownRootElement").get(),
|
||||
inputs, 1);
|
||||
return nsWSAUtils::ReportError(
|
||||
NS_LITERAL_STRING("UnknownRootElement").get(),
|
||||
inputs, 1);
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIDOMNode> rootNode(do_QueryInterface(rootElement));
|
||||
|
@ -664,15 +601,17 @@ nsWebScriptsAccess::ValidateDocument(nsIDOMDocument* aDocument,
|
|||
// There can me no more than one delegate element.
|
||||
if (hadDelegate) {
|
||||
const PRUnichar *inputs[1] = { name.get() };
|
||||
return ReportError(NS_LITERAL_STRING("TooManyElements").get(),
|
||||
inputs, 1);
|
||||
return nsWSAUtils::ReportError(
|
||||
NS_LITERAL_STRING("TooManyElements").get(),
|
||||
inputs, 1);
|
||||
}
|
||||
// Make sure that the delegate element is EMPTY.
|
||||
child->HasChildNodes(&hasChildNodes);
|
||||
if (hasChildNodes) {
|
||||
const PRUnichar *inputs[1] = { name.get() };
|
||||
return ReportError(NS_LITERAL_STRING("ElementNotEmpty").get(),
|
||||
inputs, 1);
|
||||
return nsWSAUtils::ReportError(
|
||||
NS_LITERAL_STRING("ElementNotEmpty").get(),
|
||||
inputs, 1);
|
||||
}
|
||||
hadDelegate = PR_TRUE;
|
||||
}
|
||||
|
@ -681,8 +620,9 @@ nsWebScriptsAccess::ValidateDocument(nsIDOMDocument* aDocument,
|
|||
child->HasChildNodes(&hasChildNodes);
|
||||
if (hasChildNodes) {
|
||||
const PRUnichar *inputs[1] = { name.get() };
|
||||
return ReportError(NS_LITERAL_STRING("ElementNotEmpty").get(),
|
||||
inputs, 1);
|
||||
return nsWSAUtils::ReportError(
|
||||
NS_LITERAL_STRING("ElementNotEmpty").get(),
|
||||
inputs, 1);
|
||||
}
|
||||
rv = child->GetAttributes(getter_AddRefs(attrs));
|
||||
if (NS_FAILED(rv))
|
||||
|
@ -698,16 +638,18 @@ nsWebScriptsAccess::ValidateDocument(nsIDOMDocument* aDocument,
|
|||
return rv;
|
||||
if (!name.Equals(kTypeAttr) && !name.Equals(kFromAttr)) {
|
||||
const PRUnichar *inputs[1] = { name.get() };
|
||||
return ReportError(NS_LITERAL_STRING("UnknownAttribute").get(),
|
||||
inputs, 1);
|
||||
return nsWSAUtils::ReportError(
|
||||
NS_LITERAL_STRING("UnknownAttribute").get(),
|
||||
inputs, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
const PRUnichar *inputs[1] = { name.get() };
|
||||
return ReportError(NS_LITERAL_STRING("UnknownElement").get(),
|
||||
inputs, 1);
|
||||
return nsWSAUtils::ReportError(
|
||||
NS_LITERAL_STRING("UnknownElement").get(),
|
||||
inputs, 1);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -716,27 +658,197 @@ nsWebScriptsAccess::ValidateDocument(nsIDOMDocument* aDocument,
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsWebScriptsAccess::ReportError(const PRUnichar* aMessageID,
|
||||
const PRUnichar** aInputs,
|
||||
const PRInt32 aLength)
|
||||
static PRBool
|
||||
IsCharInSet(const char* aSet,
|
||||
const PRUnichar aChar)
|
||||
{
|
||||
nsCOMPtr<nsIStringBundleService> bundleService
|
||||
= do_GetService(NS_STRINGBUNDLE_CONTRACTID);
|
||||
NS_ENSURE_TRUE(bundleService, NS_OK); // intentionally returning NS_OK;
|
||||
|
||||
nsCOMPtr<nsIStringBundle> bundle;
|
||||
bundleService->CreateBundle(SECURITY_PROPERTIES, getter_AddRefs(bundle));
|
||||
NS_ENSURE_TRUE(bundle, NS_OK);
|
||||
|
||||
nsXPIDLString message;
|
||||
bundle->FormatStringFromName(aMessageID, aInputs, aLength,
|
||||
getter_Copies(message));
|
||||
|
||||
nsCOMPtr<nsIConsoleService> consoleService =
|
||||
do_GetService(NS_CONSOLESERVICE_CONTRACTID);
|
||||
NS_ENSURE_TRUE(consoleService, NS_OK); // intentionally returning NS_OK;
|
||||
|
||||
return consoleService->LogStringMessage(message.get());
|
||||
PRUnichar ch;
|
||||
while ((ch = *aSet)) {
|
||||
if (aChar == PRUnichar(ch)) {
|
||||
return PR_TRUE;
|
||||
}
|
||||
++aSet;
|
||||
}
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsWebScriptsAccess::IsPublicService(const char* aHost, PRBool* aReturn)
|
||||
{
|
||||
*aReturn = PR_FALSE;
|
||||
nsresult rv = NS_OK;
|
||||
// Cache the master services included in the prefs.
|
||||
if (mMasterServices.Count() == 0) {
|
||||
nsCOMPtr<nsIPrefBranch> prefBranch =
|
||||
do_GetService(NS_PREFSERVICE_CONTRACTID);
|
||||
|
||||
if (!prefBranch)
|
||||
return rv;
|
||||
|
||||
nsXPIDLCString value;
|
||||
rv = prefBranch->GetCharPref("xml.webservice.security.masterservices",
|
||||
getter_Copies(value));
|
||||
|
||||
if (NS_FAILED(rv) || value.IsEmpty())
|
||||
return rv;
|
||||
|
||||
nsACString::const_iterator begin, end, curr;
|
||||
nsACString::const_iterator uri_begin, uri_end;
|
||||
value.BeginReading(begin);
|
||||
value.EndReading(end);
|
||||
|
||||
// Parse the comma separated pref. value
|
||||
static const char* kWhitespace = " \n\r\t\b";
|
||||
while (begin != end) {
|
||||
curr = begin;
|
||||
// strip leading whitespaces
|
||||
while (IsCharInSet(kWhitespace, *curr) && ++curr != end);
|
||||
uri_begin = curr;
|
||||
// consume until the delimiter ( comma ).
|
||||
while (curr != end && *curr != ',')
|
||||
++curr;
|
||||
uri_end = curr;
|
||||
// strip trailing whitespaces
|
||||
while (uri_end != uri_begin) {
|
||||
if (!IsCharInSet(kWhitespace, *(--uri_end))) {
|
||||
++uri_end; // include the last non whitespace char.
|
||||
break;
|
||||
}
|
||||
}
|
||||
const nsAFlatString& transportURI =
|
||||
NS_ConvertUTF8toUCS2(Substring(uri_begin, uri_end));
|
||||
if (!transportURI.IsEmpty())
|
||||
mMasterServices.AppendString(transportURI);
|
||||
begin = (*curr == ',' && curr != end) ? ++curr : curr;
|
||||
}
|
||||
}
|
||||
|
||||
// Allocate param block.
|
||||
nsISOAPParameter** bodyBlocks =
|
||||
NS_STATIC_CAST(nsISOAPParameter**,
|
||||
nsMemory::Alloc(1 * sizeof(nsISOAPParameter*)));
|
||||
if (!bodyBlocks)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
rv =
|
||||
CallCreateInstance(NS_SOAPPARAMETER_CONTRACTID, &bodyBlocks[0]);
|
||||
|
||||
if (NS_FAILED(rv)) {
|
||||
NS_FREE_XPCOM_ISUPPORTS_POINTER_ARRAY(0, bodyBlocks);
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsISOAPBlock> block = do_QueryInterface(bodyBlocks[0], &rv);
|
||||
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
block->SetName(NS_LITERAL_STRING("fqdn"));
|
||||
|
||||
nsCOMPtr <nsIWritableVariant> variant =
|
||||
do_CreateInstance(NS_VARIANT_CONTRACTID, &rv);
|
||||
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
variant->SetAsString(aHost);
|
||||
|
||||
block->SetValue(variant);
|
||||
|
||||
// Create the call instance
|
||||
nsCOMPtr<nsISOAPCall> call =
|
||||
do_CreateInstance(NS_SOAPCALL_CONTRACTID, &rv);
|
||||
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
nsCOMPtr<nsISOAPEncoding> encoding =
|
||||
do_CreateInstance(NS_SOAPENCODING_CONTRACTID, &rv);
|
||||
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
call->SetEncoding(encoding);
|
||||
|
||||
// Since the SOAP request to the central server will be made
|
||||
// from the native code we can safely override cross-domain
|
||||
// checks by pushing in a null jscontext on the context stack.
|
||||
nsCOMPtr<nsIJSContextStack> stack =
|
||||
do_GetService("@mozilla.org/js/xpc/ContextStack;1");
|
||||
if (stack)
|
||||
stack->Push(nsnull);
|
||||
|
||||
nsCOMPtr<nsISOAPResponse> response;
|
||||
PRInt32 i, count = mMasterServices.Count();
|
||||
for (i = 0; i < count && !response; i++) {
|
||||
rv =
|
||||
call->SetTransportURI(*mMasterServices.StringAt(i));
|
||||
|
||||
if (NS_FAILED(rv))
|
||||
break;
|
||||
|
||||
rv = call->Encode(nsISOAPMessage::VERSION_1_1,
|
||||
kIsServicePublic,
|
||||
kNamespace2002, // The target URI
|
||||
0, 0, 1, bodyBlocks);
|
||||
if (NS_FAILED(rv))
|
||||
break;
|
||||
|
||||
call->Invoke(getter_AddRefs(response)); // XXX - How to handle time out and 404?
|
||||
}
|
||||
|
||||
if (stack) {
|
||||
JSContext* cx;
|
||||
stack->Pop(&cx);
|
||||
NS_ASSERTION(!cx, "context should be null");
|
||||
}
|
||||
|
||||
if (!response)
|
||||
return rv;
|
||||
|
||||
nsCOMPtr<nsISOAPFault> fault;
|
||||
response->GetFault(getter_AddRefs(fault));
|
||||
|
||||
if (fault) {
|
||||
nsAutoString faultNamespaceURI, faultCode, faultString;
|
||||
fault->GetFaultNamespaceURI(faultNamespaceURI);
|
||||
fault->GetFaultCode(faultCode);
|
||||
fault->GetFaultString(faultString);
|
||||
const PRUnichar *inputs[5] =
|
||||
{
|
||||
kNamespace2002.get(),
|
||||
kIsServicePublic.get(),
|
||||
faultNamespaceURI.get(),
|
||||
faultCode.get(),
|
||||
faultString.get()
|
||||
};
|
||||
return nsWSAUtils::ReportError(
|
||||
NS_LITERAL_STRING("SOAPFault").get(),
|
||||
inputs, 5);
|
||||
}
|
||||
else {
|
||||
PRUint32 bodyCount;
|
||||
rv = response->GetParameters(PR_FALSE, &bodyCount, &bodyBlocks);
|
||||
NS_ASSERTION(bodyBlocks, "insufficient information");
|
||||
|
||||
if (!bodyBlocks || NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
NS_ASSERTION(bodyCount == 1, "body seems to contain unnecessary information.");
|
||||
block = do_QueryInterface(bodyBlocks[0], &rv);
|
||||
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
nsCOMPtr<nsIVariant> value;
|
||||
rv = block->GetValue(getter_AddRefs(value));
|
||||
|
||||
if (NS_FAILED(rv) || !value)
|
||||
return rv;
|
||||
|
||||
rv = value->GetAsBool(aReturn);
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
|
|
@ -38,13 +38,12 @@
|
|||
#ifndef nsWebScriptsAccess_h__
|
||||
#define nsWebScriptsAccess_h__
|
||||
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsIURI.h"
|
||||
#include "nsIWebScriptsAccessService.h"
|
||||
#include "nsIScriptSecurityManager.h"
|
||||
#include "nsHashtable.h"
|
||||
#include "nsIXMLHttpRequest.h"
|
||||
#include "nsVoidArray.h"
|
||||
#include "nsWSAUtils.h"
|
||||
|
||||
class nsIDOMDocument;
|
||||
class nsIDOMNode;
|
||||
|
@ -98,20 +97,22 @@ public:
|
|||
NS_DECL_NSIWEBSCRIPTSACCESSSERVICE
|
||||
|
||||
protected:
|
||||
nsresult CheckAccess(AccessInfoEntry* aAccessInfoEntry, const nsAString& aRequestType, PRBool* aAccessGranted);
|
||||
nsresult GetAccessInfoEntry(const char* aKey, const PRBool aIsDelegated, AccessInfoEntry** aEntry);
|
||||
nsresult GetInfoFromDocument(nsIDOMDocument* aDocument, const PRBool aIsDelegated, AccessInfoEntry** aAccessInfoEntry);
|
||||
nsresult GetAccessInfoEntry(const char* aKey, AccessInfoEntry** aEntry);
|
||||
nsresult GetDocument(const char* aDeclFilePath, nsIDOMDocument** aDocument);
|
||||
nsresult GetCodebaseURI(nsIURI** aCodebase);
|
||||
nsresult GetDelegatedInfo(AccessInfoEntry** aAccessInfoEntry);
|
||||
nsresult CreateAccessInfoEntry(nsIDOMNodeList* aAllowList, AccessInfoEntry** aAccessInfoEntry);
|
||||
nsresult CreateAccessInfoEntry(const PRInt32 aFlags, AccessInfoEntry** aAccessInfoEntry);
|
||||
nsresult ReportError(const PRUnichar* aMessageID, const PRUnichar** aInputs, const PRInt32 aLength);
|
||||
nsresult CreateEntry(const char* aKey, const PRBool aIsDelegated, AccessInfoEntry** aEntry);
|
||||
nsresult CreateEntry(nsIDOMDocument* aDocument, const PRBool aIsDelegated, AccessInfoEntry** aAccessInfoEntry);
|
||||
nsresult CreateEntry(nsIDOMNodeList* aAllowList, AccessInfoEntry** aAccessInfoEntry);
|
||||
nsresult CreateEntry(const PRInt32 aFlags, AccessInfoEntry** aAccessInfoEntry);
|
||||
nsresult CreateDelegatedEntry(AccessInfoEntry** aAccessInfoEntry);
|
||||
nsresult CheckAccess(AccessInfoEntry* aAccessInfoEntry, const nsAString& aRequestType, PRBool* aAccessGranted);
|
||||
nsresult ValidateDocument(nsIDOMDocument* aDocument, PRBool* aIsValid);
|
||||
nsresult IsPublicService(const char* aHost, PRBool* aReturn);
|
||||
|
||||
nsCOMPtr<nsIURI> mServiceURI;
|
||||
nsCOMPtr<nsIXMLHttpRequest> mRequest;
|
||||
nsCOMPtr<nsIScriptSecurityManager> mSecurityManager;
|
||||
nsStringArray mMasterServices;
|
||||
nsHashtable mAccessInfoTable;
|
||||
};
|
||||
|
||||
|
|
|
@ -41,4 +41,5 @@ UnknownAttribute = The attribute "%S" is not recognized.
|
|||
TooManyElements = There can be no more than one "%S" element.
|
||||
ElementHasSibling = "%S" element cannot have "%S" sibiling.
|
||||
ElementNotEmpty = The "%S" element should be empty.
|
||||
SOAPFault = SOAP { %S } %S call resulted in fault: { %S } %S : %S.
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче