Line data Source code
1 : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 : /* This Source Code Form is subject to the terms of the Mozilla Public
3 : * License, v. 2.0. If a copy of the MPL was not distributed with this
4 : * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5 :
6 : /* Here is the list, from beppe and glazman:
7 : href >> A, AREA, BASE, LINK
8 : src >> FRAME, IFRAME, IMG, INPUT, SCRIPT
9 : <META http-equiv="refresh" content="3,http://www.acme.com/intro.html">
10 : longdesc >> FRAME, IFRAME, IMG
11 : usemap >> IMG, INPUT, OBJECT
12 : action >> FORM
13 : background >> BODY
14 : codebase >> OBJECT, APPLET
15 : classid >> OBJECT
16 : data >> OBJECT
17 : cite >> BLOCKQUOTE, DEL, INS, Q
18 : profile >> HEAD
19 : ARCHIVE attribute on APPLET ; warning, it contains a list of URIs.
20 :
21 : Easier way of organizing the list:
22 : a: href
23 : area: href
24 : base: href
25 : body: background
26 : blockquote: cite (not normally rewritable)
27 : link: href
28 : frame: src, longdesc
29 : iframe: src, longdesc
30 : input: src, usemap
31 : form: action
32 : img: src, longdesc, usemap
33 : script: src
34 : applet: codebase, archive <list>
35 : object: codebase, data, classid, usemap
36 : head: profile
37 : del: cite
38 : ins: cite
39 : q: cite
40 : */
41 :
42 : #include "HTMLURIRefObject.h"
43 :
44 : #include "mozilla/mozalloc.h"
45 : #include "nsAString.h"
46 : #include "nsDebug.h"
47 : #include "nsError.h"
48 : #include "nsID.h"
49 : #include "nsIDOMAttr.h"
50 : #include "nsIDOMElement.h"
51 : #include "nsIDOMMozNamedAttrMap.h"
52 : #include "nsIDOMNode.h"
53 : #include "nsISupportsUtils.h"
54 : #include "nsString.h"
55 :
56 : namespace mozilla {
57 :
58 : // String classes change too often and I can't keep up.
59 : // Set this macro to this week's approved case-insensitive compare routine.
60 : #define MATCHES(tagName, str) tagName.EqualsIgnoreCase(str)
61 :
62 0 : HTMLURIRefObject::HTMLURIRefObject()
63 : : mCurAttrIndex(0)
64 0 : , mAttributeCnt(0)
65 : {
66 0 : }
67 :
68 0 : HTMLURIRefObject::~HTMLURIRefObject()
69 : {
70 0 : }
71 :
72 : //Interfaces for addref and release and queryinterface
73 0 : NS_IMPL_ISUPPORTS(HTMLURIRefObject, nsIURIRefObject)
74 :
75 : NS_IMETHODIMP
76 0 : HTMLURIRefObject::Reset()
77 : {
78 0 : mCurAttrIndex = 0;
79 0 : return NS_OK;
80 : }
81 :
82 : NS_IMETHODIMP
83 0 : HTMLURIRefObject::GetNextURI(nsAString& aURI)
84 : {
85 0 : NS_ENSURE_TRUE(mNode, NS_ERROR_NOT_INITIALIZED);
86 :
87 : // XXX Why don't you use nsIAtom for comparing the tag name a lot?
88 0 : nsAutoString tagName;
89 0 : nsresult rv = mNode->GetNodeName(tagName);
90 0 : NS_ENSURE_SUCCESS(rv, rv);
91 :
92 : // Loop over attribute list:
93 0 : if (!mAttributes) {
94 0 : nsCOMPtr<nsIDOMElement> element (do_QueryInterface(mNode));
95 0 : NS_ENSURE_TRUE(element, NS_ERROR_INVALID_ARG);
96 :
97 0 : mCurAttrIndex = 0;
98 0 : element->GetAttributes(getter_AddRefs(mAttributes));
99 0 : NS_ENSURE_TRUE(mAttributes, NS_ERROR_NOT_INITIALIZED);
100 :
101 0 : rv = mAttributes->GetLength(&mAttributeCnt);
102 0 : NS_ENSURE_SUCCESS(rv, rv);
103 0 : NS_ENSURE_TRUE(mAttributeCnt, NS_ERROR_FAILURE);
104 0 : mCurAttrIndex = 0;
105 : }
106 :
107 0 : while (mCurAttrIndex < mAttributeCnt) {
108 0 : nsCOMPtr<nsIDOMAttr> attrNode;
109 0 : rv = mAttributes->Item(mCurAttrIndex++, getter_AddRefs(attrNode));
110 0 : NS_ENSURE_SUCCESS(rv, rv);
111 0 : NS_ENSURE_ARG_POINTER(attrNode);
112 0 : nsString curAttr;
113 0 : rv = attrNode->GetName(curAttr);
114 0 : NS_ENSURE_SUCCESS(rv, rv);
115 :
116 : // href >> A, AREA, BASE, LINK
117 0 : if (MATCHES(curAttr, "href")) {
118 0 : if (!MATCHES(tagName, "a") && !MATCHES(tagName, "area") &&
119 0 : !MATCHES(tagName, "base") && !MATCHES(tagName, "link")) {
120 0 : continue;
121 : }
122 0 : rv = attrNode->GetValue(aURI);
123 0 : NS_ENSURE_SUCCESS(rv, rv);
124 0 : nsString uri (aURI);
125 : // href pointing to a named anchor doesn't count
126 0 : if (aURI.First() != char16_t('#')) {
127 0 : return NS_OK;
128 : }
129 0 : aURI.Truncate();
130 0 : return NS_ERROR_INVALID_ARG;
131 : }
132 : // src >> FRAME, IFRAME, IMG, INPUT, SCRIPT
133 0 : else if (MATCHES(curAttr, "src")) {
134 0 : if (!MATCHES(tagName, "img") &&
135 0 : !MATCHES(tagName, "frame") && !MATCHES(tagName, "iframe") &&
136 0 : !MATCHES(tagName, "input") && !MATCHES(tagName, "script")) {
137 0 : continue;
138 : }
139 0 : return attrNode->GetValue(aURI);
140 : }
141 : //<META http-equiv="refresh" content="3,http://www.acme.com/intro.html">
142 0 : else if (MATCHES(curAttr, "content")) {
143 0 : if (!MATCHES(tagName, "meta")) {
144 0 : continue;
145 : }
146 : }
147 : // longdesc >> FRAME, IFRAME, IMG
148 0 : else if (MATCHES(curAttr, "longdesc")) {
149 0 : if (!MATCHES(tagName, "img") &&
150 0 : !MATCHES(tagName, "frame") && !MATCHES(tagName, "iframe")) {
151 0 : continue;
152 : }
153 : }
154 : // usemap >> IMG, INPUT, OBJECT
155 0 : else if (MATCHES(curAttr, "usemap")) {
156 0 : if (!MATCHES(tagName, "img") &&
157 0 : !MATCHES(tagName, "input") && !MATCHES(tagName, "object")) {
158 0 : continue;
159 : }
160 : }
161 : // action >> FORM
162 0 : else if (MATCHES(curAttr, "action")) {
163 0 : if (!MATCHES(tagName, "form")) {
164 0 : continue;
165 : }
166 : }
167 : // background >> BODY
168 0 : else if (MATCHES(curAttr, "background")) {
169 0 : if (!MATCHES(tagName, "body")) {
170 0 : continue;
171 : }
172 : }
173 : // codebase >> OBJECT, APPLET
174 0 : else if (MATCHES(curAttr, "codebase")) {
175 0 : if (!MATCHES(tagName, "meta")) {
176 0 : continue;
177 : }
178 : }
179 : // classid >> OBJECT
180 0 : else if (MATCHES(curAttr, "classid")) {
181 0 : if (!MATCHES(tagName, "object")) {
182 0 : continue;
183 : }
184 : }
185 : // data >> OBJECT
186 0 : else if (MATCHES(curAttr, "data")) {
187 0 : if (!MATCHES(tagName, "object")) {
188 0 : continue;
189 : }
190 : }
191 : // cite >> BLOCKQUOTE, DEL, INS, Q
192 0 : else if (MATCHES(curAttr, "cite")) {
193 0 : if (!MATCHES(tagName, "blockquote") && !MATCHES(tagName, "q") &&
194 0 : !MATCHES(tagName, "del") && !MATCHES(tagName, "ins")) {
195 0 : continue;
196 : }
197 : }
198 : // profile >> HEAD
199 0 : else if (MATCHES(curAttr, "profile")) {
200 0 : if (!MATCHES(tagName, "head")) {
201 0 : continue;
202 : }
203 : }
204 : // archive attribute on APPLET; warning, it contains a list of URIs.
205 0 : else if (MATCHES(curAttr, "archive")) {
206 0 : if (!MATCHES(tagName, "applet")) {
207 0 : continue;
208 : }
209 : }
210 : }
211 : // Return a code to indicate that there are no more,
212 : // to distinguish that case from real errors.
213 0 : return NS_ERROR_NOT_AVAILABLE;
214 : }
215 :
216 : NS_IMETHODIMP
217 0 : HTMLURIRefObject::RewriteAllURIs(const nsAString& aOldPat,
218 : const nsAString& aNewPat,
219 : bool aMakeRel)
220 : {
221 0 : return NS_ERROR_NOT_IMPLEMENTED;
222 : }
223 :
224 : NS_IMETHODIMP
225 0 : HTMLURIRefObject::GetNode(nsIDOMNode** aNode)
226 : {
227 0 : NS_ENSURE_TRUE(mNode, NS_ERROR_NOT_INITIALIZED);
228 0 : NS_ENSURE_TRUE(aNode, NS_ERROR_NULL_POINTER);
229 0 : *aNode = mNode.get();
230 0 : NS_ADDREF(*aNode);
231 0 : return NS_OK;
232 : }
233 :
234 : NS_IMETHODIMP
235 0 : HTMLURIRefObject::SetNode(nsIDOMNode* aNode)
236 : {
237 0 : mNode = aNode;
238 0 : nsAutoString dummyURI;
239 0 : if (NS_SUCCEEDED(GetNextURI(dummyURI))) {
240 0 : mCurAttrIndex = 0; // Reset so we'll get the first node next time
241 0 : return NS_OK;
242 : }
243 :
244 : // If there weren't any URIs in the attributes,
245 : // then don't accept this node.
246 0 : mNode = nullptr;
247 0 : return NS_ERROR_INVALID_ARG;
248 : }
249 :
250 : } // namespace mozilla
251 :
252 0 : nsresult NS_NewHTMLURIRefObject(nsIURIRefObject** aResult, nsIDOMNode* aNode)
253 : {
254 0 : RefPtr<mozilla::HTMLURIRefObject> refObject = new mozilla::HTMLURIRefObject();
255 0 : nsresult rv = refObject->SetNode(aNode);
256 0 : if (NS_FAILED(rv)) {
257 0 : *aResult = 0;
258 0 : return rv;
259 : }
260 0 : refObject.forget(aResult);
261 0 : return NS_OK;
262 : }
|