Rewrite pretty much all variable and parameter handling. Makes global and local variables be handled differently. Global variables are no longer part of the variables stack, and are lazily evaluated. Fixes bugs 117658, 92929 and some unfiled bugs and fixes remaining parts of bugs 83651 and 96802. Patch by sicking, r=Pike sr=bz. Fix for bug 156464: fix rounding problems in module, allow patterns without any '0's in the integer part and fix problems with grouping for standalone. Patch by sicking, r=Pike sr=bz. Fix for bug 157340 (Probable bugs in extensions/transformiix/source/base/txMozillaString.h). Patch by peterv, r=Pike, sr=bz. Fix for bug 146967 (Clean up Transformiix strings). Patch by peterv, r=sicking, sr=jst. Fix for bug 156464 (Remove static strings from Transformiix). Patch by peterv, r=Pike, sr=jst. git-svn-id: svn://10.0.0.236/trunk@126495 18797224-902f-48f8-a5cc-f745e15eee43
400 lines
11 KiB
C++
400 lines
11 KiB
C++
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 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 TransforMiiX XSLT processor.
|
|
*
|
|
* The Initial Developer of the Original Code is The MITRE Corporation.
|
|
* Portions created by MITRE are Copyright (C) 1999 The MITRE Corporation.
|
|
*
|
|
* Portions created by Keith Visco as a Non MITRE employee,
|
|
* (C) 1999 Keith Visco. All Rights Reserved.
|
|
*
|
|
* Contributor(s):
|
|
* Keith Visco, kvisco@ziplink.net
|
|
* -- original author.
|
|
* Larry Fitzpatrick, OpenText, lef@opentext.com
|
|
* -- 19990806
|
|
* -- moved initialization of constant shorts and chars from
|
|
* URIUtils.cpp to here
|
|
*
|
|
* Peter Van der Beken
|
|
*
|
|
*/
|
|
|
|
#include "txURIUtils.h"
|
|
|
|
#ifndef TX_EXE
|
|
#include "nsNetUtil.h"
|
|
#include "nsIScriptSecurityManager.h"
|
|
#include "nsIDocument.h"
|
|
#include "nsIDOMDocument.h"
|
|
#include "nsIContent.h"
|
|
#include "nsIPrincipal.h"
|
|
#include "nsINodeInfo.h"
|
|
#endif
|
|
|
|
/**
|
|
* URIUtils
|
|
* A set of utilities for handling URIs
|
|
**/
|
|
|
|
#ifdef TX_EXE
|
|
//- Constants -/
|
|
|
|
const String URIUtils::HTTP_PROTOCOL("http");
|
|
const String URIUtils::FILE_PROTOCOL("file");
|
|
const char URIUtils::HREF_PATH_SEP = '/';
|
|
const char URIUtils::DEVICE_SEP = '|';
|
|
const char URIUtils::PORT_SEP = ':';
|
|
const char URIUtils::PROTOCOL_SEP = ':';
|
|
const short URIUtils::PROTOCOL_MODE = 1;
|
|
const short URIUtils::HOST_MODE = 2;
|
|
const short URIUtils::PORT_MODE = 3;
|
|
const short URIUtils::PATH_MODE = 4;
|
|
|
|
|
|
/**
|
|
* Returns an InputStream for the file represented by the href
|
|
* argument
|
|
* @param href the href of the file to get the input stream for.
|
|
* @return an InputStream to the desired resource
|
|
* @exception java.io.FileNotFoundException when the file could not be
|
|
* found
|
|
**/
|
|
istream* URIUtils::getInputStream
|
|
(const String& href, String& errMsg)
|
|
{
|
|
|
|
istream* inStream = 0;
|
|
|
|
ParsedURI* uri = parseURI(href);
|
|
if ( !uri->isMalformed ) {
|
|
inStream = openStream(uri);
|
|
}
|
|
else {
|
|
// Try local files
|
|
inStream = new ifstream(NS_LossyConvertUCS2toASCII(href).get(),
|
|
ios::in);
|
|
}
|
|
delete uri;
|
|
|
|
return inStream;
|
|
|
|
} //-- getInputStream
|
|
|
|
/**
|
|
* Returns the document base of the href argument
|
|
* @return the document base of the given href
|
|
**/
|
|
void URIUtils::getDocumentBase(const String& href, String& dest) {
|
|
//-- use temp str so the subString method doesn't destroy dest
|
|
String docBase("");
|
|
|
|
if (!href.isEmpty()) {
|
|
|
|
int idx = -1;
|
|
//-- check for URL
|
|
ParsedURI* uri = parseURI(href);
|
|
if ( !uri->isMalformed ) {
|
|
idx = href.lastIndexOf(HREF_PATH_SEP);
|
|
}
|
|
else {
|
|
//-- The following contains a fix from Shane Hathaway
|
|
//-- to handle the case when both "\" and "/" appear in filename
|
|
int idx2 = href.lastIndexOf(HREF_PATH_SEP);
|
|
//idx = href.lastIndexOf(File.separator);
|
|
idx = -1; //-- hack change later
|
|
if (idx2 > idx) idx = idx2;
|
|
}
|
|
if (idx >= 0) href.subString(0,idx, docBase);
|
|
delete uri;
|
|
}
|
|
dest.append(docBase);
|
|
} //-- getDocumentBase
|
|
#endif
|
|
|
|
/**
|
|
* Resolves the given href argument, using the given documentBase
|
|
* if necessary.
|
|
* The new resolved href will be appended to the given dest String
|
|
**/
|
|
void URIUtils::resolveHref(const String& href, const String& base,
|
|
String& dest) {
|
|
if (base.isEmpty()) {
|
|
dest.append(href);
|
|
return;
|
|
}
|
|
if (href.isEmpty()) {
|
|
dest.append(base);
|
|
return;
|
|
}
|
|
|
|
#ifndef TX_EXE
|
|
nsCOMPtr<nsIURI> pURL;
|
|
String resultHref;
|
|
nsresult result = NS_NewURI(getter_AddRefs(pURL), base);
|
|
if (NS_SUCCEEDED(result)) {
|
|
NS_MakeAbsoluteURI(resultHref, href, pURL);
|
|
dest.append(resultHref);
|
|
}
|
|
#else
|
|
String documentBase;
|
|
getDocumentBase(base, documentBase);
|
|
|
|
//-- check for URL
|
|
ParsedURI* uri = parseURI(href);
|
|
if ( !uri->isMalformed ) {
|
|
dest.append(href);
|
|
delete uri;
|
|
return;
|
|
}
|
|
|
|
|
|
//-- join document base + href
|
|
String xHref;
|
|
if (!documentBase.isEmpty()) {
|
|
xHref.append(documentBase);
|
|
if (documentBase.charAt(documentBase.length()-1) != HREF_PATH_SEP)
|
|
xHref.append(HREF_PATH_SEP);
|
|
}
|
|
xHref.append(href);
|
|
|
|
//-- check new href
|
|
ParsedURI* newUri = parseURI(xHref);
|
|
if ( !newUri->isMalformed ) {
|
|
dest.append(xHref);
|
|
}
|
|
else {
|
|
// Try local files
|
|
ifstream inFile(NS_LossyConvertUCS2toASCII(xHref).get(),
|
|
ios::in);
|
|
if ( inFile ) dest.append(xHref);
|
|
else dest.append(href);
|
|
inFile.close();
|
|
}
|
|
delete uri;
|
|
delete newUri;
|
|
//cout << "\n---\nhref='" << href << "', base='" << base << "'\ndocumentBase='" << documentBase << "', dest='" << dest << "'\n---\n";
|
|
#endif
|
|
} //-- resolveHref
|
|
|
|
void URIUtils::getFragmentIdentifier(const String& href, String& frag) {
|
|
PRInt32 pos;
|
|
pos = href.lastIndexOf('#');
|
|
if(pos != kNotFound)
|
|
href.subString(pos+1, frag);
|
|
else
|
|
frag.clear();
|
|
} //-- getFragmentIdentifier
|
|
|
|
void URIUtils::getDocumentURI(const String& href, String& docUri) {
|
|
PRInt32 pos;
|
|
pos = href.lastIndexOf('#');
|
|
if(pos != kNotFound)
|
|
href.subString(0,pos,docUri);
|
|
else
|
|
docUri = href;
|
|
} //-- getDocumentURI
|
|
|
|
#ifdef TX_EXE
|
|
istream* URIUtils::openStream(ParsedURI* uri) {
|
|
if ( !uri ) return 0;
|
|
// check protocol
|
|
|
|
istream* inStream = 0;
|
|
if ( FILE_PROTOCOL.isEqual(uri->protocol) ) {
|
|
ifstream* inFile =
|
|
new ifstream(NS_LossyConvertUCS2toASCII(uri->path).get(),
|
|
ios::in);
|
|
inStream = inFile;
|
|
}
|
|
|
|
return inStream;
|
|
} //-- openStream
|
|
|
|
URIUtils::ParsedURI* URIUtils::parseURI(const String& uri) {
|
|
|
|
ParsedURI* uriTokens = new ParsedURI;
|
|
if (!uriTokens)
|
|
return NULL;
|
|
uriTokens->isMalformed = MB_FALSE;
|
|
|
|
short mode = PROTOCOL_MODE;
|
|
|
|
// look for protocol
|
|
int totalCount = uri.length();
|
|
int charCount = 0;
|
|
UNICODE_CHAR prevCh = '\0';
|
|
int fslash = 0;
|
|
String buffer(uri.length());
|
|
while ( charCount < totalCount ) {
|
|
UNICODE_CHAR ch = uri.charAt(charCount++);
|
|
switch(ch) {
|
|
case '.' :
|
|
if ( mode == PROTOCOL_MODE ) {
|
|
uriTokens->isMalformed = MB_TRUE;
|
|
mode = HOST_MODE;
|
|
}
|
|
buffer.append(ch);
|
|
break;
|
|
case ':' :
|
|
{
|
|
switch ( mode ) {
|
|
case PROTOCOL_MODE :
|
|
uriTokens->protocol = buffer;
|
|
buffer.clear();
|
|
mode = HOST_MODE;
|
|
break;
|
|
case HOST_MODE :
|
|
uriTokens->host = buffer;
|
|
buffer.clear();
|
|
mode = PORT_MODE;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
break;
|
|
}
|
|
case '/' :
|
|
switch ( mode ) {
|
|
case HOST_MODE :
|
|
if (!buffer.isEmpty()) {
|
|
mode = PATH_MODE;
|
|
buffer.append(ch);
|
|
}
|
|
else if ( fslash == 2 ) mode = PATH_MODE;
|
|
else ++fslash;
|
|
break;
|
|
case PORT_MODE :
|
|
mode = PATH_MODE;
|
|
uriTokens->port.append(buffer);
|
|
buffer.clear();
|
|
break;
|
|
default:
|
|
buffer.append(ch);
|
|
break;
|
|
}
|
|
break;
|
|
default:
|
|
buffer.append(ch);
|
|
}
|
|
prevCh = ch;
|
|
}
|
|
|
|
if ( mode == PROTOCOL_MODE ) {
|
|
uriTokens->isMalformed = MB_TRUE;
|
|
}
|
|
//-- finish remaining mode
|
|
if (!buffer.isEmpty()) {
|
|
switch ( mode ) {
|
|
case PROTOCOL_MODE :
|
|
uriTokens->protocol.append(buffer);
|
|
break;
|
|
case HOST_MODE :
|
|
uriTokens->host.append(buffer);
|
|
break;
|
|
case PORT_MODE :
|
|
uriTokens->port.append(buffer);
|
|
break;
|
|
case PATH_MODE :
|
|
uriTokens->path.append(buffer);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
return uriTokens;
|
|
} //-- parseURI
|
|
|
|
#else /* TX_EXE */
|
|
|
|
|
|
nsIScriptSecurityManager *gTxSecurityManager = 0;
|
|
|
|
// static
|
|
PRBool URIUtils::CanCallerAccess(nsIDOMNode *aNode)
|
|
{
|
|
if (!gTxSecurityManager) {
|
|
// No security manager available, let any calls go through...
|
|
|
|
return PR_TRUE;
|
|
}
|
|
|
|
nsCOMPtr<nsIPrincipal> subjectPrincipal;
|
|
gTxSecurityManager->GetSubjectPrincipal(getter_AddRefs(subjectPrincipal));
|
|
|
|
if (!subjectPrincipal) {
|
|
// we're running as system, grant access to the node.
|
|
|
|
return PR_TRUE;
|
|
}
|
|
|
|
// Make sure that this is a real node. We do this by first QI'ing to
|
|
// nsIContent (which is important performance wise) and if that QI
|
|
// fails we QI to nsIDocument. If both those QI's fail we won't let
|
|
// the caller access this unknown node.
|
|
nsCOMPtr<nsIPrincipal> principal;
|
|
nsCOMPtr<nsIContent> content(do_QueryInterface(aNode));
|
|
|
|
if (!content) {
|
|
nsCOMPtr<nsIDocument> doc = do_QueryInterface(aNode);
|
|
|
|
if (!doc) {
|
|
// aNode is neither a nsIContent nor an nsIDocument, something
|
|
// weird is going on...
|
|
|
|
NS_ERROR("aNode is neither an nsIContent nor an nsIDocument!");
|
|
|
|
return PR_FALSE;
|
|
}
|
|
doc->GetPrincipal(getter_AddRefs(principal));
|
|
}
|
|
else {
|
|
nsCOMPtr<nsIDOMDocument> domDoc;
|
|
aNode->GetOwnerDocument(getter_AddRefs(domDoc));
|
|
if (!domDoc) {
|
|
nsCOMPtr<nsINodeInfo> ni;
|
|
content->GetNodeInfo(*getter_AddRefs(ni));
|
|
if (!ni) {
|
|
// aNode is not part of a document, let any caller access it.
|
|
|
|
return PR_TRUE;
|
|
}
|
|
|
|
ni->GetDocumentPrincipal(getter_AddRefs(principal));
|
|
}
|
|
else {
|
|
nsCOMPtr<nsIDocument> doc = do_QueryInterface(domDoc);
|
|
NS_ASSERTION(doc, "QI to nsIDocument failed");
|
|
doc->GetPrincipal(getter_AddRefs(principal));
|
|
}
|
|
}
|
|
|
|
if (!principal) {
|
|
// We can't get hold of the principal for this node. This should happen
|
|
// very rarely, like for textnodes out of the tree and <option>s created
|
|
// using 'new Option'.
|
|
// If we didn't allow access to nodes like this you wouldn't be able to
|
|
// insert these nodes into a document.
|
|
|
|
return PR_TRUE;
|
|
}
|
|
|
|
nsresult rv = gTxSecurityManager->CheckSameOriginPrincipal(subjectPrincipal,
|
|
principal);
|
|
|
|
return NS_SUCCEEDED(rv);
|
|
}
|
|
|
|
|
|
#endif /* TX_EXE */
|