Back to index

lightning-sunbird  0.9+nobinonly
nsHTMLURIRefObject.cpp
Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
00002 /* ***** BEGIN LICENSE BLOCK *****
00003  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00004  *
00005  * The contents of this file are subject to the Mozilla Public License Version
00006  * 1.1 (the "License"); you may not use this file except in compliance with
00007  * the License. You may obtain a copy of the License at
00008  * http://www.mozilla.org/MPL/
00009  *
00010  * Software distributed under the License is distributed on an "AS IS" basis,
00011  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00012  * for the specific language governing rights and limitations under the
00013  * License.
00014  *
00015  * The Original Code is mozilla.org code.
00016  *
00017  * The Initial Developer of the Original Code is
00018  * Netscape Communications Corporation.
00019  * Portions created by the Initial Developer are Copyright (C) 1998
00020  * the Initial Developer. All Rights Reserved.
00021  *
00022  * Contributor(s):
00023  *
00024  * Alternatively, the contents of this file may be used under the terms of
00025  * either of the GNU General Public License Version 2 or later (the "GPL"),
00026  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00027  * in which case the provisions of the GPL or the LGPL are applicable instead
00028  * of those above. If you wish to allow use of your version of this file only
00029  * under the terms of either the GPL or the LGPL, and not to allow others to
00030  * use your version of this file under the terms of the MPL, indicate your
00031  * decision by deleting the provisions above and replace them with the notice
00032  * and other provisions required by the GPL or the LGPL. If you do not delete
00033  * the provisions above, a recipient may use your version of this file under
00034  * the terms of any one of the MPL, the GPL or the LGPL.
00035  *
00036  * ***** END LICENSE BLOCK ***** */
00037 
00038 /* Here is the list, from beppe and glazman:
00039     href >> A, AREA, BASE, LINK
00040     src >> FRAME, IFRAME, IMG, INPUT, SCRIPT
00041     <META http-equiv="refresh" content="3,http://www.acme.com/intro.html">
00042     longdesc >> FRAME, IFRAME, IMG
00043     usemap >> IMG, INPUT, OBJECT
00044     action >> FORM
00045     background >> BODY
00046     codebase >> OBJECT, APPLET
00047     classid >> OBJECT
00048     data >> OBJECT
00049     cite >> BLOCKQUOTE, DEL, INS, Q
00050     profile >> HEAD
00051     ARCHIVE attribute on APPLET ; warning, it contains a list of URIs.
00052 
00053     Easier way of organizing the list:
00054     a:      href
00055     area:   href
00056     base:   href
00057     body:   background
00058     blockquote: cite (not normally rewritable)
00059     link:   href
00060     frame:  src, longdesc
00061     iframe: src, longdesc
00062     input:  src, usemap
00063     form:   action
00064     img:    src, longdesc, usemap
00065     script: src
00066     applet: codebase, archive <list>
00067     object: codebase, data, classid, usemap
00068     head:   profile
00069     del:    cite
00070     ins:    cite
00071     q:      cite
00072  */
00073 
00074 /* Here is how to open a channel for testing
00075    (from embed/qa/testembed/Tests.cpp):
00076 
00077   nsCOMPtr<nsIChannel> theChannel;
00078   nsCString uri;
00079   nsCOMPtr<nsIURI> theURI;
00080   rv = NS_NewURI(getter_AddRefs(theURI), theSpec);
00081   if (!theURI)
00082     error;
00083   rv = NS_OpenURI(getter_AddRefs(theChannel), theURI, nsnull, theLoadGroup);
00084   if (!theChannel)
00085     error;
00086   nsCOMPtr<nsILoadGroup> theLoadGroup(do_CreateInstance(NS_LOADGROUP_CONTRACTID));
00087   if (!theLoadGroup)
00088     error;
00089               nsCOMPtr<nsIStreamListener> listener(NS_STATIC_CAST(nsIStreamListener*, qaBrowserImpl));
00090               //nsCOMPtr<nsIWeakReference> thisListener(do_GetWeakReference(listener));
00091               //qaWebBrowser->AddWebBrowserListener(thisListener, NS_GET_IID(nsIStreamListener));
00092 
00093               // this calls nsIStreamListener::OnDataAvailable()
00094               rv = theChannel->AsyncOpen(listener, nsnull);
00095 
00096               nsCOMPtr<nsIRequest> theRequest = do_QueryInterface(theChannel);
00097     // Now we can do things on nsIRequest (like what?)
00098  */
00099 
00100 #include "nsHTMLURIRefObject.h"
00101 
00102 #include "nsAString.h"
00103 #include "nsString.h"
00104 #include "nsIDOMAttr.h"
00105 #include "nsIDOMElement.h"
00106 
00107 // String classes change too often and I can't keep up.
00108 // Set this macro to this week's approved case-insensitive compare routine.
00109 #define MATCHES(tagName, str) tagName.EqualsIgnoreCase(str)
00110 
00111 nsHTMLURIRefObject::nsHTMLURIRefObject()
00112 {
00113   mCurAttrIndex = mAttributeCnt = 0;
00114 }
00115 
00116 nsHTMLURIRefObject::~nsHTMLURIRefObject()
00117 {
00118 }
00119 
00120 //Interfaces for addref and release and queryinterface
00121 NS_IMPL_ISUPPORTS1(nsHTMLURIRefObject, nsIURIRefObject)
00122 
00123 NS_IMETHODIMP
00124 nsHTMLURIRefObject::Reset()
00125 {
00126   mCurAttrIndex = 0;
00127   return NS_OK;
00128 }
00129 
00130 NS_IMETHODIMP
00131 nsHTMLURIRefObject::GetNextURI(nsAString & aURI)
00132 {
00133   if (!mNode)
00134     return NS_ERROR_NOT_INITIALIZED;
00135 
00136   nsAutoString tagName;
00137   nsresult rv = mNode->GetNodeName(tagName);
00138   if (NS_FAILED(rv))
00139   return rv;
00140 
00141   // Loop over attribute list:
00142   if (!mAttributes)
00143   {
00144     nsCOMPtr<nsIDOMElement> element (do_QueryInterface(mNode));
00145     if (!element)
00146       return NS_ERROR_INVALID_ARG;
00147 
00148     mCurAttrIndex = 0;
00149     mNode->GetAttributes(getter_AddRefs(mAttributes));
00150     if (!mAttributes)
00151       return NS_ERROR_NOT_INITIALIZED;
00152 
00153     rv = mAttributes->GetLength(&mAttributeCnt);
00154     NS_ENSURE_SUCCESS(rv, rv);
00155     if (!mAttributeCnt) return NS_ERROR_FAILURE;
00156     mCurAttrIndex = 0;
00157   }
00158 #ifdef DEBUG_akkana
00159   printf("Looking at tag '%s'\n",
00160          NS_LossyConvertUCS2toASCII(tagName).get());
00161 #endif
00162   while (mCurAttrIndex < mAttributeCnt)
00163   {
00164     nsCOMPtr<nsIDOMNode> attrNode;
00165     rv = mAttributes->Item(mCurAttrIndex++, getter_AddRefs(attrNode));
00166       // XXX Does Item() addref, or not?
00167       // The comparable code in nsEditor assumes it doesn't.
00168     NS_ENSURE_SUCCESS(rv, rv);
00169     NS_ENSURE_ARG_POINTER(attrNode);
00170     nsCOMPtr<nsIDOMAttr> curAttrNode (do_QueryInterface(attrNode));
00171     NS_ENSURE_ARG_POINTER(curAttrNode);
00172     nsString curAttr;
00173     rv = curAttrNode->GetName(curAttr);
00174     NS_ENSURE_SUCCESS(rv, rv);
00175 
00176     // href >> A, AREA, BASE, LINK
00177 #ifdef DEBUG_akkana
00178     printf("Trying to match attribute '%s'\n",
00179            NS_LossyConvertUCS2toASCII(curAttr).get());
00180 #endif
00181     if (MATCHES(curAttr, "href"))
00182     {
00183       if (!MATCHES(tagName, "a") && !MATCHES(tagName, "area")
00184           && !MATCHES(tagName, "base") && !MATCHES(tagName, "link"))
00185         continue;
00186       rv = curAttrNode->GetValue(aURI);
00187       NS_ENSURE_SUCCESS(rv, rv);
00188       nsString uri (aURI);
00189       // href pointing to a named anchor doesn't count
00190       if (aURI.First() != PRUnichar('#'))
00191         return NS_OK;
00192       aURI.Truncate();
00193       return NS_ERROR_INVALID_ARG;
00194     }
00195     // src >> FRAME, IFRAME, IMG, INPUT, SCRIPT
00196     else if (MATCHES(curAttr, "src"))
00197     {
00198       if (!MATCHES(tagName, "img")
00199           && !MATCHES(tagName, "frame") && !MATCHES(tagName, "iframe")
00200           && !MATCHES(tagName, "input") && !MATCHES(tagName, "script"))
00201         continue;
00202       return curAttrNode->GetValue(aURI);
00203     }
00204     //<META http-equiv="refresh" content="3,http://www.acme.com/intro.html">
00205     else if (MATCHES(curAttr, "content"))
00206     {
00207       if (!MATCHES(tagName, "meta"))
00208         continue;
00209     }
00210     // longdesc >> FRAME, IFRAME, IMG
00211     else if (MATCHES(curAttr, "longdesc"))
00212     {
00213       if (!MATCHES(tagName, "img")
00214           && !MATCHES(tagName, "frame") && !MATCHES(tagName, "iframe"))
00215         continue;
00216     }
00217     // usemap >> IMG, INPUT, OBJECT
00218     else if (MATCHES(curAttr, "usemap"))
00219     {
00220       if (!MATCHES(tagName, "img")
00221           && !MATCHES(tagName, "input") && !MATCHES(tagName, "object"))
00222         continue;
00223     }
00224     // action >> FORM
00225     else if (MATCHES(curAttr, "action"))
00226     {
00227       if (!MATCHES(tagName, "form"))
00228         continue;
00229     }
00230     // background >> BODY
00231     else if (MATCHES(curAttr, "background"))
00232     {
00233       if (!MATCHES(tagName, "body"))
00234         continue;
00235     }
00236     // codebase >> OBJECT, APPLET
00237     else if (MATCHES(curAttr, "codebase"))
00238     {
00239       if (!MATCHES(tagName, "meta"))
00240         continue;
00241     }
00242     // classid >> OBJECT
00243     else if (MATCHES(curAttr, "classid"))
00244     {
00245       if (!MATCHES(tagName, "object"))
00246         continue;
00247     }
00248     // data >> OBJECT
00249     else if (MATCHES(curAttr, "data"))
00250     {
00251       if (!MATCHES(tagName, "object"))
00252         continue;
00253     }
00254     // cite >> BLOCKQUOTE, DEL, INS, Q
00255     else if (MATCHES(curAttr, "cite"))
00256     {
00257       if (!MATCHES(tagName, "blockquote") && !MATCHES(tagName, "q")
00258           && !MATCHES(tagName, "del") && !MATCHES(tagName, "ins"))
00259         continue;
00260     }
00261     // profile >> HEAD
00262     else if (MATCHES(curAttr, "profile"))
00263     {
00264       if (!MATCHES(tagName, "head"))
00265         continue;
00266     }
00267     // archive attribute on APPLET; warning, it contains a list of URIs.
00268     else if (MATCHES(curAttr, "archive"))
00269     {
00270       if (!MATCHES(tagName, "applet"))
00271         continue;
00272     }
00273   }
00274   // Return a code to indicate that there are no more,
00275   // to distinguish that case from real errors.
00276   return NS_ERROR_NOT_AVAILABLE;
00277 }
00278 
00279 NS_IMETHODIMP
00280 nsHTMLURIRefObject::RewriteAllURIs(const nsAString & aOldPat,
00281                             const nsAString & aNewPat,
00282                             PRBool aMakeRel)
00283 {
00284 #ifdef DEBUG_akkana
00285   printf("Can't rewrite URIs yet\n");
00286 #endif
00287   return NS_ERROR_NOT_IMPLEMENTED;
00288 }
00289 
00290 NS_IMETHODIMP
00291 nsHTMLURIRefObject::GetNode(nsIDOMNode** aNode)
00292 {
00293   if (!mNode)
00294     return NS_ERROR_NOT_INITIALIZED;
00295   if (!aNode)
00296     return NS_ERROR_NULL_POINTER;
00297   *aNode = mNode.get();
00298   NS_ADDREF(*aNode);
00299   return NS_OK;
00300 }
00301 
00302 NS_IMETHODIMP
00303 nsHTMLURIRefObject::SetNode(nsIDOMNode *aNode)
00304 {
00305   mNode = aNode;
00306   nsAutoString dummyURI;
00307   if (NS_SUCCEEDED(GetNextURI(dummyURI)))
00308   {
00309     mCurAttrIndex = 0;    // Reset so we'll get the first node next time
00310     return NS_OK;
00311   }
00312 
00313   // If there weren't any URIs in the attributes,
00314   // then don't accept this node.
00315   mNode = 0;
00316   return NS_ERROR_INVALID_ARG;
00317 }
00318 
00319 nsresult NS_NewHTMLURIRefObject(nsIURIRefObject** aResult, nsIDOMNode* aNode)
00320 {
00321   nsHTMLURIRefObject* refObject = new nsHTMLURIRefObject();
00322   if (!refObject) return NS_ERROR_OUT_OF_MEMORY;
00323   nsresult rv = refObject->SetNode(aNode);
00324   if (NS_FAILED(rv)) {
00325     *aResult = 0;
00326     delete refObject;
00327     return rv;
00328   }
00329   return refObject->QueryInterface(NS_GET_IID(nsIURIRefObject),
00330                                    (void**)aResult);
00331 }
00332