/* -*- 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 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 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 theChannel; nsCString uri; nsCOMPtr theURI; rv = NS_NewURI(getter_AddRefs(theURI), theSpec); if (!theURI) error; rv = NS_OpenURI(getter_AddRefs(theChannel), theURI, nsnull, theLoadGroup); if (!theChannel) error; nsCOMPtr theLoadGroup(do_CreateInstance(NS_LOADGROUP_CONTRACTID)); if (!theLoadGroup) error; nsCOMPtr listener(NS_STATIC_CAST(nsIStreamListener*, qaBrowserImpl)); //nsCOMPtr thisListener(do_GetWeakReference(listener)); //qaWebBrowser->AddWebBrowserListener(thisListener, NS_GET_IID(nsIStreamListener)); // this calls nsIStreamListener::OnDataAvailable() rv = theChannel->AsyncOpen(listener, nsnull); nsCOMPtr 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) { if (!mNode) return NS_ERROR_NOT_INITIALIZED; nsAutoString tagName; nsresult rv = mNode->GetNodeName(tagName); if (NS_FAILED(rv)) return rv; // Loop over attribute list: if (!mAttributes) { nsCOMPtr element (do_QueryInterface(mNode)); if (!element) return NS_ERROR_INVALID_ARG; mCurAttrIndex = 0; mNode->GetAttributes(getter_AddRefs(mAttributes)); if (!mAttributes) return NS_ERROR_NOT_INITIALIZED; rv = mAttributes->GetLength(&mAttributeCnt); NS_ENSURE_SUCCESS(rv, rv); if (!mAttributeCnt) return NS_ERROR_FAILURE; mCurAttrIndex = 0; } #ifdef DEBUG_akkana printf("Looking at tag '%s'\n", NS_LossyConvertUCS2toASCII(tagName).get()); #endif while (mCurAttrIndex < mAttributeCnt) { nsCOMPtr 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 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_LossyConvertUCS2toASCII(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); } // 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) { if (!mNode) return NS_ERROR_NOT_INITIALIZED; if (!aNode) return 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(); if (!refObject) return 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); }