Back to index

lightning-sunbird  0.9+nobinonly
nsIconURI.cpp
Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
00002  *
00003  * ***** BEGIN LICENSE BLOCK *****
00004  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00005  *
00006  * The contents of this file are subject to the Mozilla Public License Version
00007  * 1.1 (the "License"); you may not use this file except in compliance with
00008  * the License. You may obtain a copy of the License at
00009  * http://www.mozilla.org/MPL/
00010  *
00011  * Software distributed under the License is distributed on an "AS IS" basis,
00012  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00013  * for the specific language governing rights and limitations under the
00014  * License.
00015  *
00016  * The Original Code is mozilla.org Code.
00017  *
00018  * The Initial Developer of the Original Code is
00019  * Netscape Communications Corporation.
00020  * Portions created by the Initial Developer are Copyright (C) 1998
00021  * the Initial Developer. All Rights Reserved.
00022  *
00023  * Contributor(s):
00024  *   Scott MacGregor <mscott@netscape.com>
00025  *
00026  * Alternatively, the contents of this file may be used under the terms of
00027  * either the GNU General Public License Version 2 or later (the "GPL"), or
00028  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00029  * in which case the provisions of the GPL or the LGPL are applicable instead
00030  * of those above. If you wish to allow use of your version of this file only
00031  * under the terms of either the GPL or the LGPL, and not to allow others to
00032  * use your version of this file under the terms of the MPL, indicate your
00033  * decision by deleting the provisions above and replace them with the notice
00034  * and other provisions required by the GPL or the LGPL. If you do not delete
00035  * the provisions above, a recipient may use your version of this file under
00036  * the terms of any one of the MPL, the GPL or the LGPL.
00037  *
00038  * ***** END LICENSE BLOCK ***** */
00039 
00040 #include "nsIconURI.h"
00041 #include "nsNetUtil.h"
00042 #include "nsIIOService.h"
00043 #include "nsIURL.h"
00044 #include "nsCRT.h"
00045 #include "nsReadableUtils.h"
00046 #include "nsPrintfCString.h"
00047 #include "nsIAtom.h"
00048 #include "nsStaticAtom.h"
00049 
00050 static NS_DEFINE_CID(kIOServiceCID,     NS_IOSERVICE_CID);
00051 #define DEFAULT_IMAGE_SIZE          16
00052 
00053 // helper function for parsing out attributes like size, and contentType
00054 // from the icon url.
00055 static void extractAttributeValue(const char * searchString, const char * attributeName, char ** result);
00056  
00057 static nsIAtom *sStockSizeButton = nsnull;
00058 static nsIAtom *sStockSizeToolbar = nsnull;
00059 static nsIAtom *sStockSizeToolbarsmall = nsnull;
00060 static nsIAtom *sStockSizeMenu = nsnull;
00061 static nsIAtom *sStockSizeDialog = nsnull;
00062 static nsIAtom *sStockStateNormal = nsnull;
00063 static nsIAtom *sStockStateDisabled = nsnull;
00064 
00065 /* static */ const nsStaticAtom nsMozIconURI::sSizeAtoms[] =
00066 {
00067   { "button", &sStockSizeButton },
00068   { "toolbar", &sStockSizeToolbar },
00069   { "toolbarsmall", &sStockSizeToolbarsmall },
00070   { "menu", &sStockSizeMenu },
00071   { "dialog", &sStockSizeDialog }
00072 };
00073 
00074 /* static */ const nsStaticAtom nsMozIconURI::sStateAtoms[] =
00075 {
00076   { "normal", &sStockStateNormal },
00077   { "disabled", &sStockStateDisabled }
00078 };
00079 
00081  
00082 nsMozIconURI::nsMozIconURI()
00083   : mSize(DEFAULT_IMAGE_SIZE)
00084 {
00085 }
00086  
00087 nsMozIconURI::~nsMozIconURI()
00088 {
00089 }
00090 
00091 
00092 /* static */ void
00093 nsMozIconURI::InitAtoms()
00094 {
00095   NS_RegisterStaticAtoms(sSizeAtoms, NS_ARRAY_LENGTH(sSizeAtoms));
00096   NS_RegisterStaticAtoms(sStateAtoms, NS_ARRAY_LENGTH(sStateAtoms));
00097 }
00098 
00099 NS_IMPL_THREADSAFE_ISUPPORTS2(nsMozIconURI, nsIMozIconURI, nsIURI)
00100 
00101 #define NS_MOZICON_SCHEME           "moz-icon:"
00102 #define NS_MOZ_ICON_DELIMITER        '?'
00103 
00104 
00105 nsresult
00106 nsMozIconURI::FormatSpec(nsACString &spec)
00107 {
00108   nsresult rv = NS_OK;
00109   spec = NS_MOZICON_SCHEME;
00110 
00111   if (mFileIcon)
00112   {
00113     nsCAutoString fileIconSpec;
00114     rv = mFileIcon->GetSpec(fileIconSpec);
00115     NS_ENSURE_SUCCESS(rv, rv);
00116     spec += fileIconSpec;
00117   }
00118   else if (!mStockIcon.IsEmpty())
00119   {
00120     spec += "//stock/";
00121     spec += mStockIcon;
00122   }
00123   else
00124   {
00125     spec += "//";
00126     spec += mDummyFilePath;
00127   }
00128 
00129   if (mIconSize)
00130   {
00131     spec += NS_MOZ_ICON_DELIMITER;
00132     spec += "size=";
00133     const char *size_string;
00134     mIconSize->GetUTF8String(&size_string);
00135     spec.Append(size_string);
00136   }
00137   else
00138   {
00139     spec += NS_MOZ_ICON_DELIMITER;
00140     spec += "size=";
00141     spec.Append(nsPrintfCString("%d", mSize));
00142   }
00143 
00144   if (mIconState) {
00145     spec += "&state=";
00146     const char *state_string;
00147     mIconState->GetUTF8String(&state_string);
00148     spec.Append(state_string);
00149   }
00150 
00151   if (!mContentType.IsEmpty())
00152   {
00153     spec += "&contentType=";
00154     spec += mContentType.get();
00155   }
00156   
00157   return NS_OK;
00158 }
00159 
00161 // nsURI methods:
00162 
00163 NS_IMETHODIMP
00164 nsMozIconURI::GetSpec(nsACString &aSpec)
00165 {
00166   return FormatSpec(aSpec);
00167 }
00168 
00169 // takes a string like ?size=32&contentType=text/html and returns a new string 
00170 // containing just the attribute value. i.e you could pass in this string with
00171 // an attribute name of size, this will return 32
00172 // Assumption: attribute pairs in the string are separated by '&'.
00173 void extractAttributeValue(const char * searchString, const char * attributeName, char ** result)
00174 {
00175   //NS_ENSURE_ARG_POINTER(extractAttributeValue);
00176 
00177        char * attributeValue = nsnull;
00178        if (searchString && attributeName)
00179        {
00180               // search the string for attributeName
00181               PRUint32 attributeNameSize = PL_strlen(attributeName);
00182               char * startOfAttribute = PL_strcasestr(searchString, attributeName);
00183               if (startOfAttribute &&
00184                  ( *(startOfAttribute-1) == '?' || *(startOfAttribute-1) == '&') )
00185               {
00186                      startOfAttribute += attributeNameSize; // skip over the attributeName
00187                      if (startOfAttribute) // is there something after the attribute name
00188                      {
00189                             char * endofAttribute = startOfAttribute ? PL_strchr(startOfAttribute, '&') : nsnull;
00190                             if (startOfAttribute && endofAttribute) // is there text after attribute value
00191                                    attributeValue = PL_strndup(startOfAttribute, endofAttribute - startOfAttribute);
00192                             else // there is nothing left so eat up rest of line.
00193                                    attributeValue = PL_strdup(startOfAttribute);
00194                      } // if we have a attribute value
00195               } // if we have a attribute name
00196        } // if we got non-null search string and attribute name values
00197 
00198   *result = attributeValue; // passing ownership of attributeValue into result...no need to 
00199 }
00200 
00201 NS_IMETHODIMP
00202 nsMozIconURI::SetSpec(const nsACString &aSpec)
00203 {
00204   nsresult rv;
00205   nsCOMPtr<nsIIOService> ioService (do_GetService(kIOServiceCID, &rv));
00206   NS_ENSURE_SUCCESS(rv, rv);
00207 
00208   nsCAutoString scheme;
00209   rv = ioService->ExtractScheme(aSpec, scheme);
00210   NS_ENSURE_SUCCESS(rv, rv);
00211 
00212   if (strcmp("moz-icon", scheme.get()) != 0) 
00213     return NS_ERROR_MALFORMED_URI;
00214 
00215   nsXPIDLCString sizeString;
00216   nsXPIDLCString stateString;
00217   nsCAutoString mozIconPath(aSpec);
00218   PRInt32 endPos = mozIconPath.FindChar(':') + 1; // guaranteed to exist!
00219   PRInt32 pos = mozIconPath.FindChar(NS_MOZ_ICON_DELIMITER);
00220 
00221   if (pos == -1) // no size or content type specified
00222   {
00223     mozIconPath.Right(mDummyFilePath, mozIconPath.Length() - endPos);
00224   }
00225   else
00226   {
00227     mozIconPath.Mid(mDummyFilePath, endPos, pos - endPos);
00228     // fill in any size and content type values...
00229     nsXPIDLCString contentTypeString;
00230     extractAttributeValue(mozIconPath.get() + pos, "size=", getter_Copies(sizeString));
00231     extractAttributeValue(mozIconPath.get() + pos, "state=", getter_Copies(stateString));
00232     extractAttributeValue(mozIconPath.get() + pos, "contentType=", getter_Copies(contentTypeString));
00233     mContentType = contentTypeString;
00234   }
00235 
00236   if (!sizeString.IsEmpty())
00237   {
00238     nsCOMPtr<nsIAtom> atom = do_GetAtom(sizeString);
00239     for (PRUint32 i = 0; i < NS_ARRAY_LENGTH(sSizeAtoms); i++)
00240     {
00241       if (atom == *(sSizeAtoms[i].mAtom))
00242       {
00243         mIconSize = atom;
00244         break;
00245       }
00246     }
00247   }
00248 
00249   if (!stateString.IsEmpty())
00250   {
00251     nsCOMPtr<nsIAtom> atom = do_GetAtom(stateString);
00252     for (PRUint32 i = 0; i < NS_ARRAY_LENGTH(sStateAtoms); i++)
00253     {
00254       if (atom == *(sStateAtoms[i].mAtom))
00255       {
00256         mIconState = atom;
00257         break;
00258       }
00259     }
00260   }
00261 
00262   // Okay now we have a bit of a hack here...filePath can have three forms:
00263   // (1) file://<some valid platform specific file url>
00264   // (2) //<some dummy file with an extension>
00265   // (3) stock/<icon-identifier>
00266   // We need to determine which case we are and behave accordingly...
00267   if (mDummyFilePath.Length() > 2)
00268   {
00269     if (!strncmp("//stock/", mDummyFilePath.get(), 8))
00270     {
00271       // we have a stock icon
00272       mStockIcon = Substring(mDummyFilePath, 8);
00273     }
00274     else
00275     {
00276       if (!strncmp("//", mDummyFilePath.get(), 2))// must not have a url here..
00277       {
00278         // in this case the string looks like //somefile.html or // somefile.extension. So throw away the "//" part
00279         // and remember the rest in mDummyFilePath
00280         mDummyFilePath.Cut(0, 2); // cut the first 2 bytes....
00281       }
00282       if (!strncmp("file://", mDummyFilePath.get(), 7))
00283       { 
00284         // we have a file url, let the IOService normalize it
00285         nsCOMPtr<nsIURI> tmpURI;
00286         rv = ioService->NewURI(mDummyFilePath, nsnull, nsnull, getter_AddRefs(tmpURI));
00287         if (NS_SUCCEEDED(rv) && tmpURI)
00288         {
00289           mFileIcon = tmpURI;
00290         }
00291       }
00292       if (!sizeString.IsEmpty())
00293       {
00294         PRInt32 sizeValue = atoi(sizeString);
00295         // if the size value we got back is > 0 then use it
00296         if (sizeValue)
00297           mSize = sizeValue;
00298       }
00299     }
00300   }
00301   else
00302     rv = NS_ERROR_MALFORMED_URI; // they didn't include a file path...
00303   return rv;
00304 }
00305 
00306 NS_IMETHODIMP
00307 nsMozIconURI::GetPrePath(nsACString &prePath)
00308 {
00309   prePath = NS_MOZICON_SCHEME;
00310   return NS_OK;
00311 }
00312 
00313 NS_IMETHODIMP
00314 nsMozIconURI::GetScheme(nsACString &aScheme)
00315 {
00316   aScheme = "moz-icon";
00317   return NS_OK;
00318 }
00319 
00320 NS_IMETHODIMP
00321 nsMozIconURI::SetScheme(const nsACString &aScheme)
00322 {
00323   // doesn't make sense to set the scheme of a moz-icon URL
00324   return NS_ERROR_FAILURE;
00325 }
00326 
00327 NS_IMETHODIMP
00328 nsMozIconURI::GetUsername(nsACString &aUsername)
00329 {
00330   return NS_ERROR_FAILURE;
00331 }
00332 
00333 NS_IMETHODIMP
00334 nsMozIconURI::SetUsername(const nsACString &aUsername)
00335 {
00336   return NS_ERROR_FAILURE;
00337 }
00338 
00339 NS_IMETHODIMP
00340 nsMozIconURI::GetPassword(nsACString &aPassword)
00341 {
00342   return NS_ERROR_FAILURE;
00343 }
00344 
00345 NS_IMETHODIMP
00346 nsMozIconURI::SetPassword(const nsACString &aPassword)
00347 {
00348   return NS_ERROR_FAILURE;
00349 }
00350 
00351 NS_IMETHODIMP
00352 nsMozIconURI::GetUserPass(nsACString &aUserPass)
00353 {
00354   return NS_ERROR_FAILURE;
00355 }
00356 
00357 NS_IMETHODIMP
00358 nsMozIconURI::SetUserPass(const nsACString &aUserPass)
00359 {
00360   return NS_ERROR_FAILURE;
00361 }
00362 
00363 NS_IMETHODIMP
00364 nsMozIconURI::GetHostPort(nsACString &aHostPort)
00365 {
00366   return NS_ERROR_FAILURE;
00367 }
00368 
00369 NS_IMETHODIMP
00370 nsMozIconURI::SetHostPort(const nsACString &aHostPort)
00371 {
00372   return NS_ERROR_FAILURE;
00373 }
00374 
00375 NS_IMETHODIMP
00376 nsMozIconURI::GetHost(nsACString &aHost)
00377 {
00378   return NS_ERROR_FAILURE;
00379 }
00380 
00381 NS_IMETHODIMP
00382 nsMozIconURI::SetHost(const nsACString &aHost)
00383 {
00384   return NS_ERROR_FAILURE;
00385 }
00386 
00387 NS_IMETHODIMP
00388 nsMozIconURI::GetPort(PRInt32 *aPort)
00389 {
00390   return NS_ERROR_FAILURE;
00391 }
00392  
00393 NS_IMETHODIMP
00394 nsMozIconURI::SetPort(PRInt32 aPort)
00395 {
00396   return NS_ERROR_FAILURE;
00397 }
00398 
00399 NS_IMETHODIMP
00400 nsMozIconURI::GetPath(nsACString &aPath)
00401 {
00402   aPath.Truncate();
00403   return NS_OK;
00404 }
00405 
00406 NS_IMETHODIMP
00407 nsMozIconURI::SetPath(const nsACString &aPath)
00408 {
00409   return NS_ERROR_FAILURE;
00410 }
00411 
00412 NS_IMETHODIMP
00413 nsMozIconURI::Equals(nsIURI *other, PRBool *result)
00414 {
00415   NS_ENSURE_ARG_POINTER(other);
00416   NS_PRECONDITION(result, "null pointer");
00417 
00418   nsCAutoString spec1;
00419   nsCAutoString spec2;
00420 
00421   other->GetSpec(spec2);
00422   GetSpec(spec1);
00423   if (!nsCRT::strcasecmp(spec1.get(), spec2.get()))
00424     *result = PR_TRUE;
00425   else
00426     *result = PR_FALSE;
00427   return NS_OK;
00428 }
00429 
00430 NS_IMETHODIMP
00431 nsMozIconURI::SchemeIs(const char *i_Scheme, PRBool *o_Equals)
00432 {
00433   NS_ENSURE_ARG_POINTER(o_Equals);
00434   if (!i_Scheme) return NS_ERROR_INVALID_ARG;
00435   
00436   *o_Equals = PL_strcasecmp("moz-icon", i_Scheme) ? PR_FALSE : PR_TRUE;
00437   return NS_OK;
00438 }
00439 
00440 NS_IMETHODIMP
00441 nsMozIconURI::Clone(nsIURI **result)
00442 {
00443   return NS_ERROR_NOT_IMPLEMENTED;
00444 }
00445 
00446 NS_IMETHODIMP
00447 nsMozIconURI::Resolve(const nsACString &relativePath, nsACString &result)
00448 {
00449   return NS_ERROR_NOT_IMPLEMENTED;
00450 }
00451 
00452 NS_IMETHODIMP
00453 nsMozIconURI::GetAsciiSpec(nsACString &aSpecA)
00454 {
00455   return GetSpec(aSpecA);
00456 }
00457 
00458 NS_IMETHODIMP
00459 nsMozIconURI::GetAsciiHost(nsACString &aHostA)
00460 {
00461   return GetHost(aHostA);
00462 }
00463 
00464 NS_IMETHODIMP
00465 nsMozIconURI::GetOriginCharset(nsACString &result)
00466 {
00467   result.Truncate();
00468   return NS_OK;
00469 }
00470 
00472 // nsIIconUri methods:
00473 
00474 NS_IMETHODIMP
00475 nsMozIconURI::GetIconFile(nsIURI* * aFileUrl)
00476 {
00477   *aFileUrl = mFileIcon;
00478   NS_IF_ADDREF(*aFileUrl);
00479   return NS_OK;
00480 }
00481 
00482 NS_IMETHODIMP
00483 nsMozIconURI::SetIconFile(nsIURI* aFileUrl)
00484 {
00485   // this isn't called anywhere, needs to go through SetSpec parsing
00486   return NS_ERROR_NOT_IMPLEMENTED;
00487 }
00488 
00489 NS_IMETHODIMP
00490 nsMozIconURI::GetImageSize(PRUint32 * aImageSize)  // measured by # of pixels in a row. defaults to 16.
00491 {
00492   *aImageSize = mSize;
00493   return NS_OK;
00494 }
00495 
00496 NS_IMETHODIMP
00497 nsMozIconURI::SetImageSize(PRUint32 aImageSize)  // measured by # of pixels in a row. defaults to 16.
00498 {
00499   mSize = aImageSize;
00500   return NS_OK;
00501 }
00502 
00503 NS_IMETHODIMP
00504 nsMozIconURI::GetContentType(nsACString &aContentType)  
00505 {
00506   aContentType = mContentType;
00507   return NS_OK;
00508 }
00509 
00510 NS_IMETHODIMP
00511 nsMozIconURI::SetContentType(const nsACString &aContentType) 
00512 {
00513   mContentType = aContentType;
00514   return NS_OK;
00515 }
00516 
00517 NS_IMETHODIMP
00518 nsMozIconURI::GetFileExtension(nsACString &aFileExtension)  
00519 {
00520   nsCAutoString fileExtension;
00521   nsresult rv = NS_OK;
00522 
00523   // First, try to get the extension from mFileIcon if we have one
00524   if (mFileIcon)
00525   {
00526     nsCAutoString fileExt;
00527     nsCOMPtr<nsIURL> url (do_QueryInterface(mFileIcon, &rv));
00528     if (NS_SUCCEEDED(rv) && url)
00529     {
00530       rv = url->GetFileExtension(fileExt);
00531       if (NS_SUCCEEDED(rv))
00532       {
00533         // unfortunately, this code doesn't give us the required '.' in front of the extension
00534         // so we have to do it ourselves..
00535         aFileExtension = NS_LITERAL_CSTRING(".") + fileExt;
00536         return NS_OK;
00537       }
00538     }
00539     
00540     mFileIcon->GetSpec(fileExt);
00541     fileExtension = fileExt;
00542   }
00543   else
00544   {
00545     fileExtension = mDummyFilePath;
00546   }
00547 
00548   // truncate the extension out of the file path...
00549   const char * chFileName = fileExtension.get(); // get the underlying buffer
00550   const char * fileExt = strrchr(chFileName, '.');
00551   if (!fileExt) return NS_ERROR_FAILURE; // no file extension to work from.
00552 
00553   aFileExtension = nsDependentCString(fileExt);
00554 
00555   return NS_OK;
00556 }
00557 
00558 NS_IMETHODIMP
00559 nsMozIconURI::GetStockIcon(nsACString &aStockIcon)
00560 {
00561   aStockIcon.Assign(mStockIcon);
00562 
00563   return NS_OK;
00564 }
00565 
00566 NS_IMETHODIMP
00567 nsMozIconURI::GetIconSize(nsACString &aSize)
00568 {
00569   if (mIconSize)
00570     return mIconSize->ToUTF8String(aSize);
00571   aSize.Truncate();
00572   return NS_OK;
00573 }
00574 
00575 NS_IMETHODIMP
00576 nsMozIconURI::GetIconState(nsACString &aState)
00577 {
00578   if (mIconState)
00579     return mIconState->ToUTF8String(aState);
00580   aState.Truncate();
00581   return NS_OK;
00582 }