Wed, 31 Dec 2014 06:09:35 +0100
Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2 *
3 * This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #include "mozilla/ArrayUtils.h"
9 #include "nsIconURI.h"
10 #include "nsNetUtil.h"
11 #include "nsIIOService.h"
12 #include "nsIURL.h"
13 #include "prprf.h"
14 #include "plstr.h"
15 #include <stdlib.h>
17 using namespace mozilla;
19 #define DEFAULT_IMAGE_SIZE 16
21 #if defined(MAX_PATH)
22 #define SANE_FILE_NAME_LEN MAX_PATH
23 #elif defined(PATH_MAX)
24 #define SANE_FILE_NAME_LEN PATH_MAX
25 #else
26 #define SANE_FILE_NAME_LEN 1024
27 #endif
29 // helper function for parsing out attributes like size, and contentType
30 // from the icon url.
31 static void extractAttributeValue(const char * searchString, const char * attributeName, nsCString& aResult);
33 static const char *kSizeStrings[] =
34 {
35 "button",
36 "toolbar",
37 "toolbarsmall",
38 "menu",
39 "dnd",
40 "dialog"
41 };
43 static const char *kStateStrings[] =
44 {
45 "normal",
46 "disabled"
47 };
49 ////////////////////////////////////////////////////////////////////////////////
51 nsMozIconURI::nsMozIconURI()
52 : mSize(DEFAULT_IMAGE_SIZE),
53 mIconSize(-1),
54 mIconState(-1)
55 {
56 }
58 nsMozIconURI::~nsMozIconURI()
59 {
60 }
62 NS_IMPL_ISUPPORTS(nsMozIconURI, nsIMozIconURI, nsIURI)
64 #define MOZICON_SCHEME "moz-icon:"
65 #define MOZICON_SCHEME_LEN (sizeof(MOZICON_SCHEME) - 1)
67 ////////////////////////////////////////////////////////////////////////////////
68 // nsIURI methods:
70 NS_IMETHODIMP
71 nsMozIconURI::GetSpec(nsACString &aSpec)
72 {
73 aSpec = MOZICON_SCHEME;
75 if (mIconURL)
76 {
77 nsAutoCString fileIconSpec;
78 nsresult rv = mIconURL->GetSpec(fileIconSpec);
79 NS_ENSURE_SUCCESS(rv, rv);
80 aSpec += fileIconSpec;
81 }
82 else if (!mStockIcon.IsEmpty())
83 {
84 aSpec += "//stock/";
85 aSpec += mStockIcon;
86 }
87 else
88 {
89 aSpec += "//";
90 aSpec += mFileName;
91 }
93 aSpec += "?size=";
94 if (mIconSize >= 0)
95 {
96 aSpec += kSizeStrings[mIconSize];
97 }
98 else
99 {
100 char buf[20];
101 PR_snprintf(buf, sizeof(buf), "%d", mSize);
102 aSpec.Append(buf);
103 }
105 if (mIconState >= 0) {
106 aSpec += "&state=";
107 aSpec += kStateStrings[mIconState];
108 }
110 if (!mContentType.IsEmpty())
111 {
112 aSpec += "&contentType=";
113 aSpec += mContentType.get();
114 }
116 return NS_OK;
117 }
119 NS_IMETHODIMP
120 nsMozIconURI::GetSpecIgnoringRef(nsACString &result)
121 {
122 return GetSpec(result);
123 }
125 NS_IMETHODIMP
126 nsMozIconURI::GetHasRef(bool *result)
127 {
128 *result = false;
129 return NS_OK;
130 }
132 // takes a string like ?size=32&contentType=text/html and returns a new string
133 // containing just the attribute value. i.e you could pass in this string with
134 // an attribute name of 'size=', this will return 32
135 // Assumption: attribute pairs in the string are separated by '&'.
136 void extractAttributeValue(const char * searchString, const char * attributeName, nsCString& result)
137 {
138 //NS_ENSURE_ARG_POINTER(extractAttributeValue);
140 result.Truncate();
142 if (searchString && attributeName)
143 {
144 // search the string for attributeName
145 uint32_t attributeNameSize = strlen(attributeName);
146 const char * startOfAttribute = PL_strcasestr(searchString, attributeName);
147 if (startOfAttribute &&
148 ( *(startOfAttribute-1) == '?' || *(startOfAttribute-1) == '&') )
149 {
150 startOfAttribute += attributeNameSize; // skip over the attributeName
151 if (*startOfAttribute) // is there something after the attribute name
152 {
153 const char * endofAttribute = strchr(startOfAttribute, '&');
154 if (endofAttribute)
155 result.Assign(Substring(startOfAttribute, endofAttribute));
156 else
157 result.Assign(startOfAttribute);
158 } // if we have a attribute value
159 } // if we have a attribute name
160 } // if we got non-null search string and attribute name values
161 }
163 NS_IMETHODIMP
164 nsMozIconURI::SetSpec(const nsACString &aSpec)
165 {
166 // Reset everything to default values.
167 mIconURL = nullptr;
168 mSize = DEFAULT_IMAGE_SIZE;
169 mContentType.Truncate();
170 mFileName.Truncate();
171 mStockIcon.Truncate();
172 mIconSize = -1;
173 mIconState = -1;
175 nsAutoCString iconSpec(aSpec);
176 if (!Substring(iconSpec, 0, MOZICON_SCHEME_LEN).EqualsLiteral(MOZICON_SCHEME))
177 return NS_ERROR_MALFORMED_URI;
179 int32_t questionMarkPos = iconSpec.Find("?");
180 if (questionMarkPos != -1 && static_cast<int32_t>(iconSpec.Length()) > (questionMarkPos + 1))
181 {
182 extractAttributeValue(iconSpec.get(), "contentType=", mContentType);
184 nsAutoCString sizeString;
185 extractAttributeValue(iconSpec.get(), "size=", sizeString);
186 if (!sizeString.IsEmpty())
187 {
188 const char *sizeStr = sizeString.get();
189 for (uint32_t i = 0; i < ArrayLength(kSizeStrings); i++)
190 {
191 if (PL_strcasecmp(sizeStr, kSizeStrings[i]) == 0)
192 {
193 mIconSize = i;
194 break;
195 }
196 }
198 int32_t sizeValue = atoi(sizeString.get());
199 if (sizeValue)
200 mSize = sizeValue;
201 }
203 nsAutoCString stateString;
204 extractAttributeValue(iconSpec.get(), "state=", stateString);
205 if (!stateString.IsEmpty())
206 {
207 const char *stateStr = stateString.get();
208 for (uint32_t i = 0; i < ArrayLength(kStateStrings); i++)
209 {
210 if (PL_strcasecmp(stateStr, kStateStrings[i]) == 0)
211 {
212 mIconState = i;
213 break;
214 }
215 }
216 }
217 }
219 int32_t pathLength = iconSpec.Length() - MOZICON_SCHEME_LEN;
220 if (questionMarkPos != -1)
221 pathLength = questionMarkPos - MOZICON_SCHEME_LEN;
222 if (pathLength < 3)
223 return NS_ERROR_MALFORMED_URI;
225 nsAutoCString iconPath(Substring(iconSpec, MOZICON_SCHEME_LEN, pathLength));
227 // Icon URI path can have three forms:
228 // (1) //stock/<icon-identifier>
229 // (2) //<some dummy file with an extension>
230 // (3) a valid URL
232 if (!strncmp("//stock/", iconPath.get(), 8))
233 {
234 mStockIcon.Assign(Substring(iconPath, 8));
235 // An icon identifier must always be specified.
236 if (mStockIcon.IsEmpty())
237 return NS_ERROR_MALFORMED_URI;
238 return NS_OK;
239 }
241 if (StringBeginsWith(iconPath, NS_LITERAL_CSTRING("//")))
242 {
243 // Sanity check this supposed dummy file name.
244 if (iconPath.Length() > SANE_FILE_NAME_LEN)
245 return NS_ERROR_MALFORMED_URI;
246 iconPath.Cut(0, 2);
247 mFileName.Assign(iconPath);
248 }
250 nsresult rv;
251 nsCOMPtr<nsIIOService> ioService(do_GetService(NS_IOSERVICE_CONTRACTID, &rv));
252 NS_ENSURE_SUCCESS(rv, rv);
254 nsCOMPtr<nsIURI> uri;
255 ioService->NewURI(iconPath, nullptr, nullptr, getter_AddRefs(uri));
256 mIconURL = do_QueryInterface(uri);
257 if (mIconURL)
258 mFileName.Truncate();
259 else if (mFileName.IsEmpty())
260 return NS_ERROR_MALFORMED_URI;
262 return NS_OK;
263 }
265 NS_IMETHODIMP
266 nsMozIconURI::GetPrePath(nsACString &prePath)
267 {
268 prePath = MOZICON_SCHEME;
269 return NS_OK;
270 }
272 NS_IMETHODIMP
273 nsMozIconURI::GetScheme(nsACString &aScheme)
274 {
275 aScheme = "moz-icon";
276 return NS_OK;
277 }
279 NS_IMETHODIMP
280 nsMozIconURI::SetScheme(const nsACString &aScheme)
281 {
282 // doesn't make sense to set the scheme of a moz-icon URL
283 return NS_ERROR_FAILURE;
284 }
286 NS_IMETHODIMP
287 nsMozIconURI::GetUsername(nsACString &aUsername)
288 {
289 return NS_ERROR_FAILURE;
290 }
292 NS_IMETHODIMP
293 nsMozIconURI::SetUsername(const nsACString &aUsername)
294 {
295 return NS_ERROR_FAILURE;
296 }
298 NS_IMETHODIMP
299 nsMozIconURI::GetPassword(nsACString &aPassword)
300 {
301 return NS_ERROR_FAILURE;
302 }
304 NS_IMETHODIMP
305 nsMozIconURI::SetPassword(const nsACString &aPassword)
306 {
307 return NS_ERROR_FAILURE;
308 }
310 NS_IMETHODIMP
311 nsMozIconURI::GetUserPass(nsACString &aUserPass)
312 {
313 return NS_ERROR_FAILURE;
314 }
316 NS_IMETHODIMP
317 nsMozIconURI::SetUserPass(const nsACString &aUserPass)
318 {
319 return NS_ERROR_FAILURE;
320 }
322 NS_IMETHODIMP
323 nsMozIconURI::GetHostPort(nsACString &aHostPort)
324 {
325 return NS_ERROR_FAILURE;
326 }
328 NS_IMETHODIMP
329 nsMozIconURI::SetHostPort(const nsACString &aHostPort)
330 {
331 return NS_ERROR_FAILURE;
332 }
334 NS_IMETHODIMP
335 nsMozIconURI::GetHost(nsACString &aHost)
336 {
337 return NS_ERROR_FAILURE;
338 }
340 NS_IMETHODIMP
341 nsMozIconURI::SetHost(const nsACString &aHost)
342 {
343 return NS_ERROR_FAILURE;
344 }
346 NS_IMETHODIMP
347 nsMozIconURI::GetPort(int32_t *aPort)
348 {
349 return NS_ERROR_FAILURE;
350 }
352 NS_IMETHODIMP
353 nsMozIconURI::SetPort(int32_t aPort)
354 {
355 return NS_ERROR_FAILURE;
356 }
358 NS_IMETHODIMP
359 nsMozIconURI::GetPath(nsACString &aPath)
360 {
361 aPath.Truncate();
362 return NS_OK;
363 }
365 NS_IMETHODIMP
366 nsMozIconURI::SetPath(const nsACString &aPath)
367 {
368 return NS_ERROR_FAILURE;
369 }
371 NS_IMETHODIMP
372 nsMozIconURI::GetRef(nsACString &aRef)
373 {
374 aRef.Truncate();
375 return NS_OK;
376 }
378 NS_IMETHODIMP
379 nsMozIconURI::SetRef(const nsACString &aRef)
380 {
381 return NS_ERROR_FAILURE;
382 }
384 NS_IMETHODIMP
385 nsMozIconURI::Equals(nsIURI *other, bool *result)
386 {
387 NS_ENSURE_ARG_POINTER(other);
388 NS_PRECONDITION(result, "null pointer");
390 nsAutoCString spec1;
391 nsAutoCString spec2;
393 other->GetSpec(spec2);
394 GetSpec(spec1);
395 if (!PL_strcasecmp(spec1.get(), spec2.get()))
396 *result = true;
397 else
398 *result = false;
399 return NS_OK;
400 }
402 NS_IMETHODIMP
403 nsMozIconURI::EqualsExceptRef(nsIURI *other, bool *result)
404 {
405 // GetRef/SetRef not supported by nsMozIconURI, so
406 // EqualsExceptRef() is the same as Equals().
407 return Equals(other, result);
408 }
410 NS_IMETHODIMP
411 nsMozIconURI::SchemeIs(const char *i_Scheme, bool *o_Equals)
412 {
413 NS_ENSURE_ARG_POINTER(o_Equals);
414 if (!i_Scheme) return NS_ERROR_INVALID_ARG;
416 *o_Equals = PL_strcasecmp("moz-icon", i_Scheme) ? false : true;
417 return NS_OK;
418 }
420 NS_IMETHODIMP
421 nsMozIconURI::Clone(nsIURI **result)
422 {
423 nsCOMPtr<nsIURL> newIconURL;
424 if (mIconURL)
425 {
426 nsCOMPtr<nsIURI> newURI;
427 nsresult rv = mIconURL->Clone(getter_AddRefs(newURI));
428 if (NS_FAILED(rv))
429 return rv;
430 newIconURL = do_QueryInterface(newURI, &rv);
431 if (NS_FAILED(rv))
432 return rv;
433 }
435 nsMozIconURI *uri = new nsMozIconURI();
436 newIconURL.swap(uri->mIconURL);
437 uri->mSize = mSize;
438 uri->mContentType = mContentType;
439 uri->mFileName = mFileName;
440 uri->mStockIcon = mStockIcon;
441 uri->mIconSize = mIconSize;
442 uri->mIconState = mIconState;
443 NS_ADDREF(*result = uri);
445 return NS_OK;
446 }
448 NS_IMETHODIMP
449 nsMozIconURI::CloneIgnoringRef(nsIURI **result)
450 {
451 // GetRef/SetRef not supported by nsMozIconURI, so
452 // CloneIgnoringRef() is the same as Clone().
453 return Clone(result);
454 }
456 NS_IMETHODIMP
457 nsMozIconURI::Resolve(const nsACString &relativePath, nsACString &result)
458 {
459 return NS_ERROR_NOT_IMPLEMENTED;
460 }
462 NS_IMETHODIMP
463 nsMozIconURI::GetAsciiSpec(nsACString &aSpecA)
464 {
465 return GetSpec(aSpecA);
466 }
468 NS_IMETHODIMP
469 nsMozIconURI::GetAsciiHost(nsACString &aHostA)
470 {
471 return GetHost(aHostA);
472 }
474 NS_IMETHODIMP
475 nsMozIconURI::GetOriginCharset(nsACString &result)
476 {
477 result.Truncate();
478 return NS_OK;
479 }
481 ////////////////////////////////////////////////////////////////////////////////
482 // nsIIconUri methods:
484 NS_IMETHODIMP
485 nsMozIconURI::GetIconURL(nsIURL* * aFileUrl)
486 {
487 *aFileUrl = mIconURL;
488 NS_IF_ADDREF(*aFileUrl);
489 return NS_OK;
490 }
492 NS_IMETHODIMP
493 nsMozIconURI::SetIconURL(nsIURL* aFileUrl)
494 {
495 // this isn't called anywhere, needs to go through SetSpec parsing
496 return NS_ERROR_NOT_IMPLEMENTED;
497 }
499 NS_IMETHODIMP
500 nsMozIconURI::GetImageSize(uint32_t * aImageSize) // measured by # of pixels in a row. defaults to 16.
501 {
502 *aImageSize = mSize;
503 return NS_OK;
504 }
506 NS_IMETHODIMP
507 nsMozIconURI::SetImageSize(uint32_t aImageSize) // measured by # of pixels in a row. defaults to 16.
508 {
509 mSize = aImageSize;
510 return NS_OK;
511 }
513 NS_IMETHODIMP
514 nsMozIconURI::GetContentType(nsACString &aContentType)
515 {
516 aContentType = mContentType;
517 return NS_OK;
518 }
520 NS_IMETHODIMP
521 nsMozIconURI::SetContentType(const nsACString &aContentType)
522 {
523 mContentType = aContentType;
524 return NS_OK;
525 }
527 NS_IMETHODIMP
528 nsMozIconURI::GetFileExtension(nsACString &aFileExtension)
529 {
530 // First, try to get the extension from mIconURL if we have one
531 if (mIconURL)
532 {
533 nsAutoCString fileExt;
534 if (NS_SUCCEEDED(mIconURL->GetFileExtension(fileExt)))
535 {
536 if (!fileExt.IsEmpty())
537 {
538 // unfortunately, this code doesn't give us the required '.' in front of the extension
539 // so we have to do it ourselves..
540 aFileExtension.Assign('.');
541 aFileExtension.Append(fileExt);
542 }
543 }
544 return NS_OK;
545 }
547 if (!mFileName.IsEmpty())
548 {
549 // truncate the extension out of the file path...
550 const char * chFileName = mFileName.get(); // get the underlying buffer
551 const char * fileExt = strrchr(chFileName, '.');
552 if (!fileExt)
553 return NS_OK;
554 aFileExtension = fileExt;
555 }
557 return NS_OK;
558 }
560 NS_IMETHODIMP
561 nsMozIconURI::GetStockIcon(nsACString &aStockIcon)
562 {
563 aStockIcon = mStockIcon;
564 return NS_OK;
565 }
567 NS_IMETHODIMP
568 nsMozIconURI::GetIconSize(nsACString &aSize)
569 {
570 if (mIconSize >= 0)
571 aSize = kSizeStrings[mIconSize];
572 else
573 aSize.Truncate();
574 return NS_OK;
575 }
577 NS_IMETHODIMP
578 nsMozIconURI::GetIconState(nsACString &aState)
579 {
580 if (mIconState >= 0)
581 aState = kStateStrings[mIconState];
582 else
583 aState.Truncate();
584 return NS_OK;
585 }
586 ////////////////////////////////////////////////////////////////////////////////