LCOV - code coverage report
Current view: directory - netwerk/protocol/about - nsAboutCacheEntry.cpp (source / functions) Found Hit Coverage
Test: app.info Lines: 208 0 0.0 %
Date: 2012-06-02 Functions: 14 0 0.0 %

       1                 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       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) 2001
      20                 :  * the Initial Developer. All Rights Reserved.
      21                 :  *
      22                 :  * Contributor(s):
      23                 :  *   Darin Fisher <darin@netscape.com> (original author)
      24                 :  *   Alexey Chernyak <alexeyc@bigfoot.com> (XHTML 1.1 conversion)
      25                 :  *   Steffen Wilberg <steffen.wilberg@web.de> (new layout)
      26                 :  *
      27                 :  * Alternatively, the contents of this file may be used under the terms of
      28                 :  * either the GNU General Public License Version 2 or later (the "GPL"), or
      29                 :  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
      30                 :  * in which case the provisions of the GPL or the LGPL are applicable instead
      31                 :  * of those above. If you wish to allow use of your version of this file only
      32                 :  * under the terms of either the GPL or the LGPL, and not to allow others to
      33                 :  * use your version of this file under the terms of the MPL, indicate your
      34                 :  * decision by deleting the provisions above and replace them with the notice
      35                 :  * and other provisions required by the GPL or the LGPL. If you do not delete
      36                 :  * the provisions above, a recipient may use your version of this file under
      37                 :  * the terms of any one of the MPL, the GPL or the LGPL.
      38                 :  *
      39                 :  * ***** END LICENSE BLOCK ***** */
      40                 : 
      41                 : #include <limits.h>
      42                 : 
      43                 : #include "nsAboutCacheEntry.h"
      44                 : #include "nsICacheService.h"
      45                 : #include "nsICacheEntryDescriptor.h"
      46                 : #include "nsIStorageStream.h"
      47                 : #include "nsNetUtil.h"
      48                 : #include "nsAutoPtr.h"
      49                 : #include "prprf.h"
      50                 : #include "prtime.h"
      51                 : #include "nsEscape.h"
      52                 : 
      53                 : #define HEXDUMP_MAX_ROWS 16
      54                 : 
      55                 : static void
      56               0 : HexDump(PRUint32 *state, const char *buf, PRInt32 n, nsCString &result)
      57                 : {
      58                 :   char temp[16];
      59                 : 
      60                 :   const unsigned char *p;
      61               0 :   while (n) {
      62               0 :     PR_snprintf(temp, sizeof(temp), "%08x:  ", *state);
      63               0 :     result.Append(temp);
      64               0 :     *state += HEXDUMP_MAX_ROWS;
      65                 : 
      66               0 :     p = (const unsigned char *) buf;
      67                 : 
      68               0 :     PRInt32 i, row_max = NS_MIN(HEXDUMP_MAX_ROWS, n);
      69                 : 
      70                 :     // print hex codes:
      71               0 :     for (i = 0; i < row_max; ++i) {
      72               0 :       PR_snprintf(temp, sizeof(temp), "%02x  ", *p++);
      73               0 :       result.Append(temp);
      74                 :     }
      75               0 :     for (i = row_max; i < HEXDUMP_MAX_ROWS; ++i) {
      76               0 :       result.AppendLiteral("    ");
      77                 :     }
      78                 : 
      79                 :     // print ASCII glyphs if possible:
      80               0 :     p = (const unsigned char *) buf;
      81               0 :     for (i = 0; i < row_max; ++i, ++p) {
      82               0 :       switch (*p) {
      83                 :       case '<':
      84               0 :         result.AppendLiteral("&lt;");
      85               0 :         break;
      86                 :       case '>':
      87               0 :         result.AppendLiteral("&gt;");
      88               0 :         break;
      89                 :       case '&':
      90               0 :         result.AppendLiteral("&amp;");
      91               0 :         break;
      92                 :       default:
      93               0 :         if (*p < 0x7F && *p > 0x1F) {
      94               0 :           result.Append(*p);
      95                 :         } else {
      96               0 :           result.Append('.');
      97                 :         }
      98                 :       }
      99                 :     }
     100                 : 
     101               0 :     result.Append('\n');
     102                 : 
     103               0 :     buf += row_max;
     104               0 :     n -= row_max;
     105                 :   }
     106               0 : }
     107                 : 
     108                 : //-----------------------------------------------------------------------------
     109                 : // nsAboutCacheEntry::nsISupports
     110                 : 
     111               0 : NS_IMPL_ISUPPORTS2(nsAboutCacheEntry,
     112                 :                    nsIAboutModule,
     113                 :                    nsICacheMetaDataVisitor)
     114                 : 
     115                 : //-----------------------------------------------------------------------------
     116                 : // nsAboutCacheEntry::nsIAboutModule
     117                 : 
     118                 : NS_IMETHODIMP
     119               0 : nsAboutCacheEntry::NewChannel(nsIURI *uri, nsIChannel **result)
     120                 : {
     121               0 :     NS_ENSURE_ARG_POINTER(uri);
     122                 :     nsresult rv;
     123                 : 
     124               0 :     nsCOMPtr<nsIInputStream> stream;
     125               0 :     rv = GetContentStream(uri, getter_AddRefs(stream));
     126               0 :     if (NS_FAILED(rv)) return rv;
     127                 : 
     128                 :     return NS_NewInputStreamChannel(result, uri, stream,
     129               0 :                                     NS_LITERAL_CSTRING("text/html"),
     130               0 :                                     NS_LITERAL_CSTRING("utf-8"));
     131                 : }
     132                 : 
     133                 : NS_IMETHODIMP
     134               0 : nsAboutCacheEntry::GetURIFlags(nsIURI *aURI, PRUint32 *result)
     135                 : {
     136               0 :     *result = nsIAboutModule::HIDE_FROM_ABOUTABOUT;
     137               0 :     return NS_OK;
     138                 : }
     139                 : 
     140                 : //-----------------------------------------------------------------------------
     141                 : // nsAboutCacheEntry
     142                 : 
     143                 : nsresult
     144               0 : nsAboutCacheEntry::GetContentStream(nsIURI *uri, nsIInputStream **result)
     145                 : {
     146               0 :     nsCOMPtr<nsIStorageStream> storageStream;
     147               0 :     nsCOMPtr<nsIOutputStream> outputStream;
     148                 :     PRUint32 n;
     149               0 :     nsCString buffer;
     150                 :     nsresult rv;
     151                 : 
     152               0 :     nsCOMPtr<nsICacheEntryDescriptor> descriptor;
     153               0 :     OpenCacheEntry(uri, getter_AddRefs(descriptor));
     154                 : 
     155                 :     // Init: (block size, maximum length)
     156               0 :     rv = NS_NewStorageStream(256, PRUint32(-1), getter_AddRefs(storageStream));
     157               0 :     if (NS_FAILED(rv)) return rv;
     158                 : 
     159               0 :     rv = storageStream->GetOutputStream(0, getter_AddRefs(outputStream));
     160               0 :     if (NS_FAILED(rv)) return rv;
     161                 : 
     162                 :     buffer.AssignLiteral(
     163                 :       "<!DOCTYPE html>\n"
     164                 :       "<html>\n"
     165                 :       "<head>\n"
     166                 :       "  <title>Cache entry information</title>\n"
     167                 :       "  <link rel=\"stylesheet\" "
     168                 :       "href=\"chrome://global/skin/about.css\" type=\"text/css\"/>\n"
     169                 :       "  <link rel=\"stylesheet\" "
     170                 :       "href=\"chrome://global/skin/aboutCacheEntry.css\" type=\"text/css\"/>\n"
     171                 :       "</head>\n"
     172                 :       "<body>\n"
     173               0 :       "<h1>Cache entry information</h1>\n");
     174               0 :     outputStream->Write(buffer.get(), buffer.Length(), &n);
     175                 : 
     176               0 :     if (descriptor)
     177               0 :         rv = WriteCacheEntryDescription(outputStream, descriptor);
     178                 :     else
     179               0 :         rv = WriteCacheEntryUnavailable(outputStream);
     180               0 :     if (NS_FAILED(rv)) return rv;
     181                 : 
     182               0 :     buffer.AssignLiteral("</body>\n</html>\n");
     183               0 :     outputStream->Write(buffer.get(), buffer.Length(), &n);
     184                 : 
     185               0 :     nsCOMPtr<nsIInputStream> inStr;
     186                 :     PRUint32 size;
     187                 : 
     188               0 :     rv = storageStream->GetLength(&size);
     189               0 :     if (NS_FAILED(rv)) return rv;
     190                 : 
     191               0 :     return storageStream->NewInputStream(0, result);
     192                 : }
     193                 : 
     194                 : nsresult
     195               0 : nsAboutCacheEntry::OpenCacheEntry(nsIURI *uri, nsICacheEntryDescriptor **result)
     196                 : {
     197                 :     nsresult rv;
     198               0 :     nsCAutoString clientID, key;
     199               0 :     bool streamBased = true;
     200                 : 
     201               0 :     rv = ParseURI(uri, clientID, streamBased, key);
     202               0 :     if (NS_FAILED(rv)) return rv;
     203                 : 
     204                 :     nsCOMPtr<nsICacheService> serv =
     205               0 :         do_GetService(NS_CACHESERVICE_CONTRACTID, &rv);
     206               0 :     if (NS_FAILED(rv)) return rv;
     207                 : 
     208               0 :     nsCOMPtr<nsICacheSession> session;
     209               0 :     rv = serv->CreateSession(clientID.get(),
     210                 :                              nsICache::STORE_ANYWHERE,
     211                 :                              streamBased,
     212               0 :                              getter_AddRefs(session));
     213               0 :     if (NS_FAILED(rv)) return rv;
     214                 : 
     215               0 :     rv = session->SetDoomEntriesIfExpired(false);
     216               0 :     if (NS_FAILED(rv)) return rv;
     217                 : 
     218               0 :     rv = session->OpenCacheEntry(key, nsICache::ACCESS_READ, false, result);
     219               0 :     return rv;
     220                 : }
     221                 : 
     222                 : 
     223                 : //-----------------------------------------------------------------------------
     224                 : // helper methods
     225                 : //-----------------------------------------------------------------------------
     226                 : 
     227               0 : static PRTime SecondsToPRTime(PRUint32 t_sec)
     228                 : {
     229                 :     PRTime t_usec, usec_per_sec;
     230               0 :     LL_I2L(t_usec, t_sec);
     231               0 :     LL_I2L(usec_per_sec, PR_USEC_PER_SEC);
     232               0 :     LL_MUL(t_usec, t_usec, usec_per_sec);
     233               0 :     return t_usec;
     234                 : }
     235               0 : static void PrintTimeString(char *buf, PRUint32 bufsize, PRUint32 t_sec)
     236                 : {
     237                 :     PRExplodedTime et;
     238               0 :     PRTime t_usec = SecondsToPRTime(t_sec);
     239               0 :     PR_ExplodeTime(t_usec, PR_LocalTimeParameters, &et);
     240               0 :     PR_FormatTime(buf, bufsize, "%Y-%m-%d %H:%M:%S", &et);
     241               0 : }
     242                 : 
     243                 : #define APPEND_ROW(label, value) \
     244                 :     PR_BEGIN_MACRO \
     245                 :     buffer.AppendLiteral("  <tr>\n" \
     246                 :                          "    <th>"); \
     247                 :     buffer.AppendLiteral(label); \
     248                 :     buffer.AppendLiteral(":</th>\n" \
     249                 :                          "    <td>"); \
     250                 :     buffer.Append(value); \
     251                 :     buffer.AppendLiteral("</td>\n" \
     252                 :                          "  </tr>\n"); \
     253                 :     PR_END_MACRO
     254                 : 
     255                 : nsresult
     256               0 : nsAboutCacheEntry::WriteCacheEntryDescription(nsIOutputStream *outputStream,
     257                 :                                               nsICacheEntryDescriptor *descriptor)
     258                 : {
     259                 :     nsresult rv;
     260               0 :     nsCString buffer;
     261                 :     PRUint32 n;
     262                 : 
     263               0 :     nsCAutoString str;
     264                 : 
     265               0 :     rv = descriptor->GetKey(str);
     266               0 :     if (NS_FAILED(rv)) return rv;
     267                 : 
     268               0 :     buffer.SetCapacity(4096);
     269                 :     buffer.AssignLiteral("<table>\n"
     270                 :                          "  <tr>\n"
     271                 :                          "    <th>key:</th>\n"
     272               0 :                          "    <td id=\"td-key\">");
     273                 : 
     274                 :     // Test if the key is actually a URI
     275               0 :     nsCOMPtr<nsIURI> uri;
     276               0 :     bool isJS = false;
     277               0 :     bool isData = false;
     278                 : 
     279               0 :     rv = NS_NewURI(getter_AddRefs(uri), str);
     280                 :     // javascript: and data: URLs should not be linkified
     281                 :     // since clicking them can cause scripts to run - bug 162584
     282               0 :     if (NS_SUCCEEDED(rv)) {
     283               0 :         uri->SchemeIs("javascript", &isJS);
     284               0 :         uri->SchemeIs("data", &isData);
     285                 :     }
     286               0 :     char* escapedStr = nsEscapeHTML(str.get());
     287               0 :     if (NS_SUCCEEDED(rv) && !(isJS || isData)) {
     288               0 :         buffer.AppendLiteral("<a href=\"");
     289               0 :         buffer.Append(escapedStr);
     290               0 :         buffer.AppendLiteral("\">");
     291               0 :         buffer.Append(escapedStr);
     292               0 :         buffer.AppendLiteral("</a>");
     293               0 :         uri = 0;
     294                 :     }
     295                 :     else
     296               0 :         buffer.Append(escapedStr);
     297               0 :     nsMemory::Free(escapedStr);
     298                 :     buffer.AppendLiteral("</td>\n"
     299               0 :                          "  </tr>\n");
     300                 : 
     301                 :     // temp vars for reporting
     302                 :     char timeBuf[255];
     303               0 :     PRUint32 u = 0;
     304               0 :     PRInt32  i = 0;
     305               0 :     nsCAutoString s;
     306                 : 
     307                 :     // Fetch Count
     308               0 :     s.Truncate();
     309               0 :     descriptor->GetFetchCount(&i);
     310               0 :     s.AppendInt(i);
     311               0 :     APPEND_ROW("fetch count", s);
     312                 : 
     313                 :     // Last Fetched
     314               0 :     descriptor->GetLastFetched(&u);
     315               0 :     if (u) {
     316               0 :         PrintTimeString(timeBuf, sizeof(timeBuf), u);
     317               0 :         APPEND_ROW("last fetched", timeBuf);
     318                 :     } else {
     319               0 :         APPEND_ROW("last fetched", "No last fetch time");
     320                 :     }
     321                 : 
     322                 :     // Last Modified
     323               0 :     descriptor->GetLastModified(&u);
     324               0 :     if (u) {
     325               0 :         PrintTimeString(timeBuf, sizeof(timeBuf), u);
     326               0 :         APPEND_ROW("last modified", timeBuf);
     327                 :     } else {
     328               0 :         APPEND_ROW("last modified", "No last modified time");
     329                 :     }
     330                 : 
     331                 :     // Expiration Time
     332               0 :     descriptor->GetExpirationTime(&u);
     333               0 :     if (u < 0xFFFFFFFF) {
     334               0 :         PrintTimeString(timeBuf, sizeof(timeBuf), u);
     335               0 :         APPEND_ROW("expires", timeBuf);
     336                 :     } else {
     337               0 :         APPEND_ROW("expires", "No expiration time");
     338                 :     }
     339                 : 
     340                 :     // Data Size
     341               0 :     s.Truncate();
     342                 :     PRUint32 dataSize;
     343               0 :     descriptor->GetStorageDataSize(&dataSize);
     344               0 :     s.AppendInt((PRInt32)dataSize);     // XXX nsICacheEntryInfo interfaces should be fixed.
     345               0 :     APPEND_ROW("Data size", s);
     346                 : 
     347                 :     // Storage Policy
     348                 : 
     349                 :     // XXX Stream Based?
     350                 : 
     351                 :     // XXX Cache Device
     352                 :     // File on disk
     353               0 :     nsCOMPtr<nsIFile> cacheFile;
     354               0 :     rv = descriptor->GetFile(getter_AddRefs(cacheFile));
     355               0 :     if (NS_SUCCEEDED(rv)) {
     356               0 :         nsAutoString filePath;
     357               0 :         cacheFile->GetPath(filePath);
     358               0 :         APPEND_ROW("file on disk", NS_ConvertUTF16toUTF8(filePath));
     359                 :     }
     360                 :     else
     361               0 :         APPEND_ROW("file on disk", "none");
     362                 : 
     363                 :     // Security Info
     364               0 :     nsCOMPtr<nsISupports> securityInfo;
     365               0 :     descriptor->GetSecurityInfo(getter_AddRefs(securityInfo));
     366               0 :     if (securityInfo) {
     367               0 :         APPEND_ROW("Security", "This is a secure document.");
     368                 :     } else {
     369               0 :         APPEND_ROW("Security",
     370                 :                    "This document does not have any security info associated with it.");
     371                 :     }
     372                 : 
     373                 :     buffer.AppendLiteral("</table>\n"
     374                 :                          "<hr/>\n"
     375               0 :                          "<table>\n");
     376                 :     // Meta Data
     377                 :     // let's just look for some well known (HTTP) meta data tags, for now.
     378                 : 
     379                 :     // Client ID
     380               0 :     nsXPIDLCString str2;
     381               0 :     descriptor->GetClientID(getter_Copies(str2));
     382               0 :     if (!str2.IsEmpty())  APPEND_ROW("Client", str2);
     383                 : 
     384                 : 
     385               0 :     mBuffer = &buffer;  // make it available for VisitMetaDataElement().
     386                 :     // nsCacheEntryDescriptor::VisitMetaData calls
     387                 :     // nsCacheEntry.h VisitMetaDataElements, which returns
     388                 :     // nsCacheMetaData::VisitElements, which calls
     389                 :     // nsAboutCacheEntry::VisitMetaDataElement (below) in a loop.
     390               0 :     descriptor->VisitMetaData(this);
     391               0 :     mBuffer = nsnull;
     392                 : 
     393               0 :     buffer.AppendLiteral("</table>\n");
     394               0 :     outputStream->Write(buffer.get(), buffer.Length(), &n);
     395                 : 
     396               0 :     buffer.Truncate();
     397                 : 
     398                 :     // Provide a hexdump of the data
     399               0 :     if (dataSize) { // don't draw an <hr> if the Data Size is 0.
     400               0 :         nsCOMPtr<nsIInputStream> stream;
     401               0 :         descriptor->OpenInputStream(0, getter_AddRefs(stream));
     402               0 :         if (stream) {
     403                 :             buffer.AssignLiteral("<hr/>\n"
     404               0 :                                  "<pre>");
     405               0 :             PRUint32 hexDumpState = 0;
     406                 :             char chunk[4096];
     407               0 :             while(NS_SUCCEEDED(stream->Read(chunk, sizeof(chunk), &n)) && 
     408                 :                   n > 0) {
     409               0 :                 HexDump(&hexDumpState, chunk, n, buffer);
     410               0 :                 outputStream->Write(buffer.get(), buffer.Length(), &n);
     411               0 :                 buffer.Truncate();
     412                 :             }
     413               0 :             buffer.AssignLiteral("</pre>\n");
     414               0 :             outputStream->Write(buffer.get(), buffer.Length(), &n);
     415                 :       }
     416                 :     }
     417               0 :     return NS_OK;
     418                 : }
     419                 : 
     420                 : nsresult
     421               0 : nsAboutCacheEntry::WriteCacheEntryUnavailable(nsIOutputStream *outputStream)
     422                 : {
     423                 :     PRUint32 n;
     424               0 :     NS_NAMED_LITERAL_CSTRING(buffer,
     425                 :         "The cache entry you selected is not available.");
     426               0 :     outputStream->Write(buffer.get(), buffer.Length(), &n);
     427               0 :     return NS_OK;
     428                 : }
     429                 : 
     430                 : nsresult
     431               0 : nsAboutCacheEntry::ParseURI(nsIURI *uri, nsCString &clientID,
     432                 :                             bool &streamBased, nsCString &key)
     433                 : {
     434                 :     //
     435                 :     // about:cache-entry?client=[string]&sb=[boolean]&key=[string]
     436                 :     //
     437                 :     nsresult rv;
     438                 : 
     439               0 :     nsCAutoString path;
     440               0 :     rv = uri->GetPath(path);
     441               0 :     if (NS_FAILED(rv)) return rv;
     442                 : 
     443               0 :     nsACString::const_iterator i1, i2, i3, end;
     444               0 :     path.BeginReading(i1);
     445               0 :     path.EndReading(end);
     446                 : 
     447               0 :     i2 = end;
     448               0 :     if (!FindInReadable(NS_LITERAL_CSTRING("?client="), i1, i2))
     449               0 :         return NS_ERROR_FAILURE;
     450                 :     // i2 points to the start of clientID
     451                 : 
     452               0 :     i1 = i2;
     453               0 :     i3 = end;
     454               0 :     if (!FindInReadable(NS_LITERAL_CSTRING("&sb="), i1, i3))
     455               0 :         return NS_ERROR_FAILURE;
     456                 :     // i1 points to the end of clientID
     457                 :     // i3 points to the start of isStreamBased
     458                 : 
     459               0 :     clientID.Assign(Substring(i2, i1));
     460                 : 
     461               0 :     i1 = i3;
     462               0 :     i2 = end;
     463               0 :     if (!FindInReadable(NS_LITERAL_CSTRING("&key="), i1, i2))
     464               0 :         return NS_ERROR_FAILURE;
     465                 :     // i1 points to the end of isStreamBased
     466                 :     // i2 points to the start of key
     467                 : 
     468               0 :     streamBased = FindCharInReadable('1', i3, i1);
     469               0 :     key.Assign(Substring(i2, end));
     470                 : 
     471               0 :     return NS_OK;
     472                 : }
     473                 : 
     474                 : 
     475                 : //-----------------------------------------------------------------------------
     476                 : // nsICacheMetaDataVisitor implementation
     477                 : //-----------------------------------------------------------------------------
     478                 : 
     479                 : NS_IMETHODIMP
     480               0 : nsAboutCacheEntry::VisitMetaDataElement(const char * key,
     481                 :                                         const char * value,
     482                 :                                         bool *     keepGoing)
     483                 : {
     484                 :     mBuffer->AppendLiteral("  <tr>\n"
     485               0 :                            "    <th>");
     486               0 :     mBuffer->Append(key);
     487                 :     mBuffer->AppendLiteral(":</th>\n"
     488               0 :                            "    <td>");
     489               0 :     char* escapedValue = nsEscapeHTML(value);
     490               0 :     mBuffer->Append(escapedValue);
     491               0 :     nsMemory::Free(escapedValue);
     492                 :     mBuffer->AppendLiteral("</td>\n"
     493               0 :                            "  </tr>\n");
     494                 : 
     495               0 :     *keepGoing = true;
     496               0 :     return NS_OK;
     497                 : }

Generated by: LCOV version 1.7