1 : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 : /* ***** BEGIN LICENSE BLOCK *****
3 : * Version: MPL 1.1/GPL 2.0/LGPL 2.1
4 : *
5 : * The contents of this file are subject to the Mozilla Public License Version
6 : * 1.1 (the "License"); you may not use this file except in compliance with
7 : * the License. You may obtain a copy of the License at
8 : * http://www.mozilla.org/MPL/
9 : *
10 : * Software distributed under the License is distributed on an "AS IS" basis,
11 : * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 : * for the specific language governing rights and limitations under the
13 : * License.
14 : *
15 : * The Original Code is mozilla.org code.
16 : *
17 : * The Initial Developer of the Original Code is
18 : * Netscape Communications Corporation.
19 : * Portions created by the Initial Developer are Copyright (C) 1998
20 : * the Initial Developer. All Rights Reserved.
21 : *
22 : * Contributor(s):
23 : *
24 : * Alternatively, the contents of this file may be used under the terms of
25 : * either of the GNU General Public License Version 2 or later (the "GPL"),
26 : * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
27 : * in which case the provisions of the GPL or the LGPL are applicable instead
28 : * of those above. If you wish to allow use of your version of this file only
29 : * under the terms of either the GPL or the LGPL, and not to allow others to
30 : * use your version of this file under the terms of the MPL, indicate your
31 : * decision by deleting the provisions above and replace them with the notice
32 : * and other provisions required by the GPL or the LGPL. If you do not delete
33 : * the provisions above, a recipient may use your version of this file under
34 : * the terms of any one of the MPL, the GPL or the LGPL.
35 : *
36 : * ***** END LICENSE BLOCK ***** */
37 :
38 : /* Here is the list, from beppe and glazman:
39 : href >> A, AREA, BASE, LINK
40 : src >> FRAME, IFRAME, IMG, INPUT, SCRIPT
41 : <META http-equiv="refresh" content="3,http://www.acme.com/intro.html">
42 : longdesc >> FRAME, IFRAME, IMG
43 : usemap >> IMG, INPUT, OBJECT
44 : action >> FORM
45 : background >> BODY
46 : codebase >> OBJECT, APPLET
47 : classid >> OBJECT
48 : data >> OBJECT
49 : cite >> BLOCKQUOTE, DEL, INS, Q
50 : profile >> HEAD
51 : ARCHIVE attribute on APPLET ; warning, it contains a list of URIs.
52 :
53 : Easier way of organizing the list:
54 : a: href
55 : area: href
56 : base: href
57 : body: background
58 : blockquote: cite (not normally rewritable)
59 : link: href
60 : frame: src, longdesc
61 : iframe: src, longdesc
62 : input: src, usemap
63 : form: action
64 : img: src, longdesc, usemap
65 : script: src
66 : applet: codebase, archive <list>
67 : object: codebase, data, classid, usemap
68 : head: profile
69 : del: cite
70 : ins: cite
71 : q: cite
72 : */
73 :
74 : /* Here is how to open a channel for testing
75 : (from embed/qa/testembed/Tests.cpp):
76 :
77 : nsCOMPtr<nsIChannel> theChannel;
78 : nsCString uri;
79 : nsCOMPtr<nsIURI> theURI;
80 : rv = NS_NewURI(getter_AddRefs(theURI), theSpec);
81 : if (!theURI)
82 : error;
83 : rv = NS_OpenURI(getter_AddRefs(theChannel), theURI, nsnull, theLoadGroup);
84 : if (!theChannel)
85 : error;
86 : nsCOMPtr<nsILoadGroup> theLoadGroup(do_CreateInstance(NS_LOADGROUP_CONTRACTID));
87 : if (!theLoadGroup)
88 : error;
89 : nsCOMPtr<nsIStreamListener> listener(static_cast<nsIStreamListener*>(qaBrowserImpl));
90 : //nsCOMPtr<nsIWeakReference> thisListener(do_GetWeakReference(listener));
91 : //qaWebBrowser->AddWebBrowserListener(thisListener, NS_GET_IID(nsIStreamListener));
92 :
93 : // this calls nsIStreamListener::OnDataAvailable()
94 : rv = theChannel->AsyncOpen(listener, nsnull);
95 :
96 : nsCOMPtr<nsIRequest> theRequest = do_QueryInterface(theChannel);
97 : // Now we can do things on nsIRequest (like what?)
98 : */
99 :
100 : #include "nsHTMLURIRefObject.h"
101 :
102 : #include "nsAString.h"
103 : #include "nsString.h"
104 : #include "nsIDOMAttr.h"
105 : #include "nsIDOMElement.h"
106 :
107 : // String classes change too often and I can't keep up.
108 : // Set this macro to this week's approved case-insensitive compare routine.
109 : #define MATCHES(tagName, str) tagName.EqualsIgnoreCase(str)
110 :
111 0 : nsHTMLURIRefObject::nsHTMLURIRefObject()
112 : {
113 0 : mCurAttrIndex = mAttributeCnt = 0;
114 0 : }
115 :
116 0 : nsHTMLURIRefObject::~nsHTMLURIRefObject()
117 : {
118 0 : }
119 :
120 : //Interfaces for addref and release and queryinterface
121 0 : NS_IMPL_ISUPPORTS1(nsHTMLURIRefObject, nsIURIRefObject)
122 :
123 : NS_IMETHODIMP
124 0 : nsHTMLURIRefObject::Reset()
125 : {
126 0 : mCurAttrIndex = 0;
127 0 : return NS_OK;
128 : }
129 :
130 : NS_IMETHODIMP
131 0 : nsHTMLURIRefObject::GetNextURI(nsAString & aURI)
132 : {
133 0 : NS_ENSURE_TRUE(mNode, NS_ERROR_NOT_INITIALIZED);
134 :
135 0 : nsAutoString tagName;
136 0 : nsresult rv = mNode->GetNodeName(tagName);
137 0 : NS_ENSURE_SUCCESS(rv, rv);
138 :
139 : // Loop over attribute list:
140 0 : if (!mAttributes)
141 : {
142 0 : nsCOMPtr<nsIDOMElement> element (do_QueryInterface(mNode));
143 0 : NS_ENSURE_TRUE(element, NS_ERROR_INVALID_ARG);
144 :
145 0 : mCurAttrIndex = 0;
146 0 : mNode->GetAttributes(getter_AddRefs(mAttributes));
147 0 : NS_ENSURE_TRUE(mAttributes, NS_ERROR_NOT_INITIALIZED);
148 :
149 0 : rv = mAttributes->GetLength(&mAttributeCnt);
150 0 : NS_ENSURE_SUCCESS(rv, rv);
151 0 : NS_ENSURE_TRUE(mAttributeCnt, NS_ERROR_FAILURE);
152 0 : mCurAttrIndex = 0;
153 : }
154 : #ifdef DEBUG_akkana
155 : printf("Looking at tag '%s'\n",
156 : NS_LossyConvertUTF16toASCII(tagName).get());
157 : #endif
158 0 : while (mCurAttrIndex < mAttributeCnt)
159 : {
160 0 : nsCOMPtr<nsIDOMNode> attrNode;
161 0 : rv = mAttributes->Item(mCurAttrIndex++, getter_AddRefs(attrNode));
162 : // XXX Does Item() addref, or not?
163 : // The comparable code in nsEditor assumes it doesn't.
164 0 : NS_ENSURE_SUCCESS(rv, rv);
165 0 : NS_ENSURE_ARG_POINTER(attrNode);
166 0 : nsCOMPtr<nsIDOMAttr> curAttrNode (do_QueryInterface(attrNode));
167 0 : NS_ENSURE_ARG_POINTER(curAttrNode);
168 0 : nsString curAttr;
169 0 : rv = curAttrNode->GetName(curAttr);
170 0 : NS_ENSURE_SUCCESS(rv, rv);
171 :
172 : // href >> A, AREA, BASE, LINK
173 : #ifdef DEBUG_akkana
174 : printf("Trying to match attribute '%s'\n",
175 : NS_LossyConvertUTF16toASCII(curAttr).get());
176 : #endif
177 0 : if (MATCHES(curAttr, "href"))
178 : {
179 0 : if (!MATCHES(tagName, "a") && !MATCHES(tagName, "area")
180 0 : && !MATCHES(tagName, "base") && !MATCHES(tagName, "link"))
181 0 : continue;
182 0 : rv = curAttrNode->GetValue(aURI);
183 0 : NS_ENSURE_SUCCESS(rv, rv);
184 0 : nsString uri (aURI);
185 : // href pointing to a named anchor doesn't count
186 0 : if (aURI.First() != PRUnichar('#'))
187 0 : return NS_OK;
188 0 : aURI.Truncate();
189 0 : return NS_ERROR_INVALID_ARG;
190 : }
191 : // src >> FRAME, IFRAME, IMG, INPUT, SCRIPT
192 0 : else if (MATCHES(curAttr, "src"))
193 : {
194 0 : if (!MATCHES(tagName, "img")
195 0 : && !MATCHES(tagName, "frame") && !MATCHES(tagName, "iframe")
196 0 : && !MATCHES(tagName, "input") && !MATCHES(tagName, "script"))
197 0 : continue;
198 0 : return curAttrNode->GetValue(aURI);
199 : }
200 : //<META http-equiv="refresh" content="3,http://www.acme.com/intro.html">
201 0 : else if (MATCHES(curAttr, "content"))
202 : {
203 0 : if (!MATCHES(tagName, "meta"))
204 0 : continue;
205 : }
206 : // longdesc >> FRAME, IFRAME, IMG
207 0 : else if (MATCHES(curAttr, "longdesc"))
208 : {
209 0 : if (!MATCHES(tagName, "img")
210 0 : && !MATCHES(tagName, "frame") && !MATCHES(tagName, "iframe"))
211 0 : continue;
212 : }
213 : // usemap >> IMG, INPUT, OBJECT
214 0 : else if (MATCHES(curAttr, "usemap"))
215 : {
216 0 : if (!MATCHES(tagName, "img")
217 0 : && !MATCHES(tagName, "input") && !MATCHES(tagName, "object"))
218 0 : continue;
219 : }
220 : // action >> FORM
221 0 : else if (MATCHES(curAttr, "action"))
222 : {
223 0 : if (!MATCHES(tagName, "form"))
224 0 : continue;
225 : }
226 : // background >> BODY
227 0 : else if (MATCHES(curAttr, "background"))
228 : {
229 0 : if (!MATCHES(tagName, "body"))
230 0 : continue;
231 : }
232 : // codebase >> OBJECT, APPLET
233 0 : else if (MATCHES(curAttr, "codebase"))
234 : {
235 0 : if (!MATCHES(tagName, "meta"))
236 0 : continue;
237 : }
238 : // classid >> OBJECT
239 0 : else if (MATCHES(curAttr, "classid"))
240 : {
241 0 : if (!MATCHES(tagName, "object"))
242 0 : continue;
243 : }
244 : // data >> OBJECT
245 0 : else if (MATCHES(curAttr, "data"))
246 : {
247 0 : if (!MATCHES(tagName, "object"))
248 0 : continue;
249 : }
250 : // cite >> BLOCKQUOTE, DEL, INS, Q
251 0 : else if (MATCHES(curAttr, "cite"))
252 : {
253 0 : if (!MATCHES(tagName, "blockquote") && !MATCHES(tagName, "q")
254 0 : && !MATCHES(tagName, "del") && !MATCHES(tagName, "ins"))
255 0 : continue;
256 : }
257 : // profile >> HEAD
258 0 : else if (MATCHES(curAttr, "profile"))
259 : {
260 0 : if (!MATCHES(tagName, "head"))
261 0 : continue;
262 : }
263 : // archive attribute on APPLET; warning, it contains a list of URIs.
264 0 : else if (MATCHES(curAttr, "archive"))
265 : {
266 0 : if (!MATCHES(tagName, "applet"))
267 0 : continue;
268 : }
269 : }
270 : // Return a code to indicate that there are no more,
271 : // to distinguish that case from real errors.
272 0 : return NS_ERROR_NOT_AVAILABLE;
273 : }
274 :
275 : NS_IMETHODIMP
276 0 : nsHTMLURIRefObject::RewriteAllURIs(const nsAString & aOldPat,
277 : const nsAString & aNewPat,
278 : bool aMakeRel)
279 : {
280 : #ifdef DEBUG_akkana
281 : printf("Can't rewrite URIs yet\n");
282 : #endif
283 0 : return NS_ERROR_NOT_IMPLEMENTED;
284 : }
285 :
286 : NS_IMETHODIMP
287 0 : nsHTMLURIRefObject::GetNode(nsIDOMNode** aNode)
288 : {
289 0 : NS_ENSURE_TRUE(mNode, NS_ERROR_NOT_INITIALIZED);
290 0 : NS_ENSURE_TRUE(aNode, NS_ERROR_NULL_POINTER);
291 0 : *aNode = mNode.get();
292 0 : NS_ADDREF(*aNode);
293 0 : return NS_OK;
294 : }
295 :
296 : NS_IMETHODIMP
297 0 : nsHTMLURIRefObject::SetNode(nsIDOMNode *aNode)
298 : {
299 0 : mNode = aNode;
300 0 : nsAutoString dummyURI;
301 0 : if (NS_SUCCEEDED(GetNextURI(dummyURI)))
302 : {
303 0 : mCurAttrIndex = 0; // Reset so we'll get the first node next time
304 0 : return NS_OK;
305 : }
306 :
307 : // If there weren't any URIs in the attributes,
308 : // then don't accept this node.
309 0 : mNode = 0;
310 0 : return NS_ERROR_INVALID_ARG;
311 : }
312 :
313 0 : nsresult NS_NewHTMLURIRefObject(nsIURIRefObject** aResult, nsIDOMNode* aNode)
314 : {
315 0 : nsHTMLURIRefObject* refObject = new nsHTMLURIRefObject();
316 0 : NS_ENSURE_TRUE(refObject, NS_ERROR_OUT_OF_MEMORY);
317 0 : nsresult rv = refObject->SetNode(aNode);
318 0 : if (NS_FAILED(rv)) {
319 0 : *aResult = 0;
320 0 : delete refObject;
321 0 : return rv;
322 : }
323 : return refObject->QueryInterface(NS_GET_IID(nsIURIRefObject),
324 0 : (void**)aResult);
325 : }
326 :
|