зеркало из https://github.com/mozilla/pjs.git
327 строки
9.7 KiB
C++
327 строки
9.7 KiB
C++
/* -*- 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 mozilla.org code.
|
|
*
|
|
* The Initial Developer of the Original Code is
|
|
* Netscape Communications Corporation.
|
|
* Portions created by the Initial Developer are Copyright (C) 1998
|
|
* the Initial Developer. All Rights Reserved.
|
|
*
|
|
* Contributor(s):
|
|
*
|
|
* Alternatively, the contents of this file may be used under the terms of
|
|
* either of 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 ***** */
|
|
|
|
/* Here is the list, from beppe and glazman:
|
|
href >> A, AREA, BASE, LINK
|
|
src >> FRAME, IFRAME, IMG, INPUT, SCRIPT
|
|
<META http-equiv="refresh" content="3,http://www.acme.com/intro.html">
|
|
longdesc >> FRAME, IFRAME, IMG
|
|
usemap >> IMG, INPUT, OBJECT
|
|
action >> FORM
|
|
background >> BODY
|
|
codebase >> OBJECT, APPLET
|
|
classid >> OBJECT
|
|
data >> OBJECT
|
|
cite >> BLOCKQUOTE, DEL, INS, Q
|
|
profile >> HEAD
|
|
ARCHIVE attribute on APPLET ; warning, it contains a list of URIs.
|
|
|
|
Easier way of organizing the list:
|
|
a: href
|
|
area: href
|
|
base: href
|
|
body: background
|
|
blockquote: cite (not normally rewritable)
|
|
link: href
|
|
frame: src, longdesc
|
|
iframe: src, longdesc
|
|
input: src, usemap
|
|
form: action
|
|
img: src, longdesc, usemap
|
|
script: src
|
|
applet: codebase, archive <list>
|
|
object: codebase, data, classid, usemap
|
|
head: profile
|
|
del: cite
|
|
ins: cite
|
|
q: cite
|
|
*/
|
|
|
|
/* Here is how to open a channel for testing
|
|
(from embed/qa/testembed/Tests.cpp):
|
|
|
|
nsCOMPtr<nsIChannel> theChannel;
|
|
nsCString uri;
|
|
nsCOMPtr<nsIURI> theURI;
|
|
rv = NS_NewURI(getter_AddRefs(theURI), theSpec);
|
|
if (!theURI)
|
|
error;
|
|
rv = NS_OpenURI(getter_AddRefs(theChannel), theURI, nsnull, theLoadGroup);
|
|
if (!theChannel)
|
|
error;
|
|
nsCOMPtr<nsILoadGroup> theLoadGroup(do_CreateInstance(NS_LOADGROUP_CONTRACTID));
|
|
if (!theLoadGroup)
|
|
error;
|
|
nsCOMPtr<nsIStreamListener> listener(static_cast<nsIStreamListener*>(qaBrowserImpl));
|
|
//nsCOMPtr<nsIWeakReference> thisListener(do_GetWeakReference(listener));
|
|
//qaWebBrowser->AddWebBrowserListener(thisListener, NS_GET_IID(nsIStreamListener));
|
|
|
|
// this calls nsIStreamListener::OnDataAvailable()
|
|
rv = theChannel->AsyncOpen(listener, nsnull);
|
|
|
|
nsCOMPtr<nsIRequest> theRequest = do_QueryInterface(theChannel);
|
|
// Now we can do things on nsIRequest (like what?)
|
|
*/
|
|
|
|
#include "nsHTMLURIRefObject.h"
|
|
|
|
#include "nsAString.h"
|
|
#include "nsString.h"
|
|
#include "nsIDOMAttr.h"
|
|
#include "nsIDOMElement.h"
|
|
|
|
// String classes change too often and I can't keep up.
|
|
// Set this macro to this week's approved case-insensitive compare routine.
|
|
#define MATCHES(tagName, str) tagName.EqualsIgnoreCase(str)
|
|
|
|
nsHTMLURIRefObject::nsHTMLURIRefObject()
|
|
{
|
|
mCurAttrIndex = mAttributeCnt = 0;
|
|
}
|
|
|
|
nsHTMLURIRefObject::~nsHTMLURIRefObject()
|
|
{
|
|
}
|
|
|
|
//Interfaces for addref and release and queryinterface
|
|
NS_IMPL_ISUPPORTS1(nsHTMLURIRefObject, nsIURIRefObject)
|
|
|
|
NS_IMETHODIMP
|
|
nsHTMLURIRefObject::Reset()
|
|
{
|
|
mCurAttrIndex = 0;
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsHTMLURIRefObject::GetNextURI(nsAString & aURI)
|
|
{
|
|
NS_ENSURE_TRUE(mNode, NS_ERROR_NOT_INITIALIZED);
|
|
|
|
nsAutoString tagName;
|
|
nsresult rv = mNode->GetNodeName(tagName);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
// Loop over attribute list:
|
|
if (!mAttributes)
|
|
{
|
|
nsCOMPtr<nsIDOMElement> element (do_QueryInterface(mNode));
|
|
NS_ENSURE_TRUE(element, NS_ERROR_INVALID_ARG);
|
|
|
|
mCurAttrIndex = 0;
|
|
mNode->GetAttributes(getter_AddRefs(mAttributes));
|
|
NS_ENSURE_TRUE(mAttributes, NS_ERROR_NOT_INITIALIZED);
|
|
|
|
rv = mAttributes->GetLength(&mAttributeCnt);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
NS_ENSURE_TRUE(mAttributeCnt, NS_ERROR_FAILURE);
|
|
mCurAttrIndex = 0;
|
|
}
|
|
#ifdef DEBUG_akkana
|
|
printf("Looking at tag '%s'\n",
|
|
NS_LossyConvertUTF16toASCII(tagName).get());
|
|
#endif
|
|
while (mCurAttrIndex < mAttributeCnt)
|
|
{
|
|
nsCOMPtr<nsIDOMNode> attrNode;
|
|
rv = mAttributes->Item(mCurAttrIndex++, getter_AddRefs(attrNode));
|
|
// XXX Does Item() addref, or not?
|
|
// The comparable code in nsEditor assumes it doesn't.
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
NS_ENSURE_ARG_POINTER(attrNode);
|
|
nsCOMPtr<nsIDOMAttr> curAttrNode (do_QueryInterface(attrNode));
|
|
NS_ENSURE_ARG_POINTER(curAttrNode);
|
|
nsString curAttr;
|
|
rv = curAttrNode->GetName(curAttr);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
// href >> A, AREA, BASE, LINK
|
|
#ifdef DEBUG_akkana
|
|
printf("Trying to match attribute '%s'\n",
|
|
NS_LossyConvertUTF16toASCII(curAttr).get());
|
|
#endif
|
|
if (MATCHES(curAttr, "href"))
|
|
{
|
|
if (!MATCHES(tagName, "a") && !MATCHES(tagName, "area")
|
|
&& !MATCHES(tagName, "base") && !MATCHES(tagName, "link"))
|
|
continue;
|
|
rv = curAttrNode->GetValue(aURI);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
nsString uri (aURI);
|
|
// href pointing to a named anchor doesn't count
|
|
if (aURI.First() != PRUnichar('#'))
|
|
return NS_OK;
|
|
aURI.Truncate();
|
|
return NS_ERROR_INVALID_ARG;
|
|
}
|
|
// src >> FRAME, IFRAME, IMG, INPUT, SCRIPT
|
|
else if (MATCHES(curAttr, "src"))
|
|
{
|
|
if (!MATCHES(tagName, "img")
|
|
&& !MATCHES(tagName, "frame") && !MATCHES(tagName, "iframe")
|
|
&& !MATCHES(tagName, "input") && !MATCHES(tagName, "script"))
|
|
continue;
|
|
return curAttrNode->GetValue(aURI);
|
|
}
|
|
//<META http-equiv="refresh" content="3,http://www.acme.com/intro.html">
|
|
else if (MATCHES(curAttr, "content"))
|
|
{
|
|
if (!MATCHES(tagName, "meta"))
|
|
continue;
|
|
}
|
|
// longdesc >> FRAME, IFRAME, IMG
|
|
else if (MATCHES(curAttr, "longdesc"))
|
|
{
|
|
if (!MATCHES(tagName, "img")
|
|
&& !MATCHES(tagName, "frame") && !MATCHES(tagName, "iframe"))
|
|
continue;
|
|
}
|
|
// usemap >> IMG, INPUT, OBJECT
|
|
else if (MATCHES(curAttr, "usemap"))
|
|
{
|
|
if (!MATCHES(tagName, "img")
|
|
&& !MATCHES(tagName, "input") && !MATCHES(tagName, "object"))
|
|
continue;
|
|
}
|
|
// action >> FORM
|
|
else if (MATCHES(curAttr, "action"))
|
|
{
|
|
if (!MATCHES(tagName, "form"))
|
|
continue;
|
|
}
|
|
// background >> BODY
|
|
else if (MATCHES(curAttr, "background"))
|
|
{
|
|
if (!MATCHES(tagName, "body"))
|
|
continue;
|
|
}
|
|
// codebase >> OBJECT, APPLET
|
|
else if (MATCHES(curAttr, "codebase"))
|
|
{
|
|
if (!MATCHES(tagName, "meta"))
|
|
continue;
|
|
}
|
|
// classid >> OBJECT
|
|
else if (MATCHES(curAttr, "classid"))
|
|
{
|
|
if (!MATCHES(tagName, "object"))
|
|
continue;
|
|
}
|
|
// data >> OBJECT
|
|
else if (MATCHES(curAttr, "data"))
|
|
{
|
|
if (!MATCHES(tagName, "object"))
|
|
continue;
|
|
}
|
|
// cite >> BLOCKQUOTE, DEL, INS, Q
|
|
else if (MATCHES(curAttr, "cite"))
|
|
{
|
|
if (!MATCHES(tagName, "blockquote") && !MATCHES(tagName, "q")
|
|
&& !MATCHES(tagName, "del") && !MATCHES(tagName, "ins"))
|
|
continue;
|
|
}
|
|
// profile >> HEAD
|
|
else if (MATCHES(curAttr, "profile"))
|
|
{
|
|
if (!MATCHES(tagName, "head"))
|
|
continue;
|
|
}
|
|
// archive attribute on APPLET; warning, it contains a list of URIs.
|
|
else if (MATCHES(curAttr, "archive"))
|
|
{
|
|
if (!MATCHES(tagName, "applet"))
|
|
continue;
|
|
}
|
|
}
|
|
// Return a code to indicate that there are no more,
|
|
// to distinguish that case from real errors.
|
|
return NS_ERROR_NOT_AVAILABLE;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsHTMLURIRefObject::RewriteAllURIs(const nsAString & aOldPat,
|
|
const nsAString & aNewPat,
|
|
PRBool aMakeRel)
|
|
{
|
|
#ifdef DEBUG_akkana
|
|
printf("Can't rewrite URIs yet\n");
|
|
#endif
|
|
return NS_ERROR_NOT_IMPLEMENTED;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsHTMLURIRefObject::GetNode(nsIDOMNode** aNode)
|
|
{
|
|
NS_ENSURE_TRUE(mNode, NS_ERROR_NOT_INITIALIZED);
|
|
NS_ENSURE_TRUE(aNode, NS_ERROR_NULL_POINTER);
|
|
*aNode = mNode.get();
|
|
NS_ADDREF(*aNode);
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsHTMLURIRefObject::SetNode(nsIDOMNode *aNode)
|
|
{
|
|
mNode = aNode;
|
|
nsAutoString dummyURI;
|
|
if (NS_SUCCEEDED(GetNextURI(dummyURI)))
|
|
{
|
|
mCurAttrIndex = 0; // Reset so we'll get the first node next time
|
|
return NS_OK;
|
|
}
|
|
|
|
// If there weren't any URIs in the attributes,
|
|
// then don't accept this node.
|
|
mNode = 0;
|
|
return NS_ERROR_INVALID_ARG;
|
|
}
|
|
|
|
nsresult NS_NewHTMLURIRefObject(nsIURIRefObject** aResult, nsIDOMNode* aNode)
|
|
{
|
|
nsHTMLURIRefObject* refObject = new nsHTMLURIRefObject();
|
|
NS_ENSURE_TRUE(refObject, NS_ERROR_OUT_OF_MEMORY);
|
|
nsresult rv = refObject->SetNode(aNode);
|
|
if (NS_FAILED(rv)) {
|
|
*aResult = 0;
|
|
delete refObject;
|
|
return rv;
|
|
}
|
|
return refObject->QueryInterface(NS_GET_IID(nsIURIRefObject),
|
|
(void**)aResult);
|
|
}
|
|
|