LCOV - code coverage report
Current view: top level - netwerk/streamconv/converters - nsFTPDirListingConv.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 0 144 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 14 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       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             : #include "nsFTPDirListingConv.h"
       7             : #include "nsMemory.h"
       8             : #include "plstr.h"
       9             : #include "mozilla/Logging.h"
      10             : #include "nsCOMPtr.h"
      11             : #include "nsEscape.h"
      12             : #include "nsStringStream.h"
      13             : #include "nsIStreamListener.h"
      14             : #include "nsCRT.h"
      15             : #include "nsIChannel.h"
      16             : #include "nsIURI.h"
      17             : 
      18             : #include "ParseFTPList.h"
      19             : #include <algorithm>
      20             : 
      21             : #include "mozilla/SizePrintfMacros.h"
      22             : #include "mozilla/UniquePtrExtensions.h"
      23             : #include "mozilla/Unused.h"
      24             : 
      25             : //
      26             : // Log module for FTP dir listing stream converter logging...
      27             : //
      28             : // To enable logging (see prlog.h for full details):
      29             : //
      30             : //    set MOZ_LOG=nsFTPDirListConv:5
      31             : //    set MOZ_LOG_FILE=network.log
      32             : //
      33             : // This enables LogLevel::Debug level information and places all output in
      34             : // the file network.log.
      35             : //
      36             : static mozilla::LazyLogModule gFTPDirListConvLog("nsFTPDirListingConv");
      37             : using namespace mozilla;
      38             : 
      39             : // nsISupports implementation
      40           0 : NS_IMPL_ISUPPORTS(nsFTPDirListingConv,
      41             :                   nsIStreamConverter,
      42             :                   nsIStreamListener,
      43             :                   nsIRequestObserver)
      44             : 
      45             : 
      46             : // nsIStreamConverter implementation
      47             : NS_IMETHODIMP
      48           0 : nsFTPDirListingConv::Convert(nsIInputStream *aFromStream,
      49             :                              const char *aFromType,
      50             :                              const char *aToType,
      51             :                              nsISupports *aCtxt, nsIInputStream **_retval) {
      52           0 :     return NS_ERROR_NOT_IMPLEMENTED;
      53             : }
      54             : 
      55             : 
      56             : // Stream converter service calls this to initialize the actual stream converter (us).
      57             : NS_IMETHODIMP
      58           0 : nsFTPDirListingConv::AsyncConvertData(const char *aFromType, const char *aToType,
      59             :                                       nsIStreamListener *aListener, nsISupports *aCtxt) {
      60           0 :     NS_ASSERTION(aListener && aFromType && aToType, "null pointer passed into FTP dir listing converter");
      61             : 
      62             :     // hook up our final listener. this guy gets the various On*() calls we want to throw
      63             :     // at him.
      64           0 :     mFinalListener = aListener;
      65           0 :     NS_ADDREF(mFinalListener);
      66             : 
      67           0 :     MOZ_LOG(gFTPDirListConvLog, LogLevel::Debug,
      68             :         ("nsFTPDirListingConv::AsyncConvertData() converting FROM raw, TO application/http-index-format\n"));
      69             : 
      70           0 :     return NS_OK;
      71             : }
      72             : 
      73             : 
      74             : // nsIStreamListener implementation
      75             : NS_IMETHODIMP
      76           0 : nsFTPDirListingConv::OnDataAvailable(nsIRequest* request, nsISupports *ctxt,
      77             :                                   nsIInputStream *inStr, uint64_t sourceOffset, uint32_t count) {
      78           0 :     NS_ASSERTION(request, "FTP dir listing stream converter needs a request");
      79             : 
      80             :     nsresult rv;
      81             : 
      82           0 :     nsCOMPtr<nsIChannel> channel = do_QueryInterface(request, &rv);
      83           0 :     NS_ENSURE_SUCCESS(rv, rv);
      84             : 
      85             :     uint32_t read, streamLen;
      86             : 
      87             :     uint64_t streamLen64;
      88           0 :     rv = inStr->Available(&streamLen64);
      89           0 :     NS_ENSURE_SUCCESS(rv, rv);
      90           0 :     streamLen = (uint32_t)std::min(streamLen64, uint64_t(UINT32_MAX - 1));
      91             : 
      92           0 :     auto buffer = MakeUniqueFallible<char[]>(streamLen + 1);
      93           0 :     NS_ENSURE_TRUE(buffer, NS_ERROR_OUT_OF_MEMORY);
      94             : 
      95           0 :     rv = inStr->Read(buffer.get(), streamLen, &read);
      96           0 :     NS_ENSURE_SUCCESS(rv, rv);
      97             : 
      98             :     // the dir listings are ascii text, null terminate this sucker.
      99           0 :     buffer[streamLen] = '\0';
     100             : 
     101           0 :     MOZ_LOG(gFTPDirListConvLog, LogLevel::Debug, ("nsFTPDirListingConv::OnData(request = %p, ctxt = %p, inStr = %p, sourceOffset = %" PRIu64 ", count = %u)\n", request, ctxt, inStr, sourceOffset, count));
     102             : 
     103           0 :     if (!mBuffer.IsEmpty()) {
     104             :         // we have data left over from a previous OnDataAvailable() call.
     105             :         // combine the buffers so we don't lose any data.
     106           0 :         mBuffer.Append(buffer.get());
     107             : 
     108           0 :         buffer = MakeUniqueFallible<char[]>(mBuffer.Length()+1);
     109           0 :         NS_ENSURE_TRUE(buffer, NS_ERROR_OUT_OF_MEMORY);
     110             : 
     111           0 :         strncpy(buffer.get(), mBuffer.get(), mBuffer.Length()+1);
     112           0 :         mBuffer.Truncate();
     113             :     }
     114             : 
     115           0 :     MOZ_LOG(gFTPDirListConvLog, LogLevel::Debug, ("::OnData() received the following %d bytes...\n\n%s\n\n", streamLen, buffer.get()) );
     116             : 
     117           0 :     nsAutoCString indexFormat;
     118           0 :     if (!mSentHeading) {
     119             :         // build up the 300: line
     120           0 :         nsCOMPtr<nsIURI> uri;
     121           0 :         rv = channel->GetURI(getter_AddRefs(uri));
     122           0 :         NS_ENSURE_SUCCESS(rv, rv);
     123             : 
     124           0 :         rv = GetHeaders(indexFormat, uri);
     125           0 :         NS_ENSURE_SUCCESS(rv, rv);
     126             : 
     127           0 :         mSentHeading = true;
     128             :     }
     129             : 
     130           0 :     char *line = buffer.get();
     131           0 :     line = DigestBufferLines(line, indexFormat);
     132             : 
     133           0 :     MOZ_LOG(gFTPDirListConvLog, LogLevel::Debug, ("::OnData() sending the following %d bytes...\n\n%s\n\n",
     134             :         indexFormat.Length(), indexFormat.get()) );
     135             : 
     136             :     // if there's any data left over, buffer it.
     137           0 :     if (line && *line) {
     138           0 :         mBuffer.Append(line);
     139           0 :         MOZ_LOG(gFTPDirListConvLog, LogLevel::Debug, ("::OnData() buffering the following %" PRIuSIZE " bytes...\n\n%s\n\n",
     140             :             strlen(line), line) );
     141             :     }
     142             : 
     143             :     // send the converted data out.
     144           0 :     nsCOMPtr<nsIInputStream> inputData;
     145             : 
     146           0 :     rv = NS_NewCStringInputStream(getter_AddRefs(inputData), indexFormat);
     147           0 :     NS_ENSURE_SUCCESS(rv, rv);
     148             : 
     149           0 :     rv = mFinalListener->OnDataAvailable(request, ctxt, inputData, 0, indexFormat.Length());
     150             : 
     151           0 :     return rv;
     152             : }
     153             : 
     154             : 
     155             : // nsIRequestObserver implementation
     156             : NS_IMETHODIMP
     157           0 : nsFTPDirListingConv::OnStartRequest(nsIRequest* request, nsISupports *ctxt) {
     158             :     // we don't care about start. move along... but start masqeurading
     159             :     // as the http-index channel now.
     160           0 :     return mFinalListener->OnStartRequest(request, ctxt);
     161             : }
     162             : 
     163             : NS_IMETHODIMP
     164           0 : nsFTPDirListingConv::OnStopRequest(nsIRequest* request, nsISupports *ctxt,
     165             :                                    nsresult aStatus) {
     166             :     // we don't care about stop. move along...
     167             : 
     168           0 :     return mFinalListener->OnStopRequest(request, ctxt, aStatus);
     169             : }
     170             : 
     171             : 
     172             : // nsFTPDirListingConv methods
     173           0 : nsFTPDirListingConv::nsFTPDirListingConv() {
     174           0 :     mFinalListener      = nullptr;
     175           0 :     mSentHeading        = false;
     176           0 : }
     177             : 
     178           0 : nsFTPDirListingConv::~nsFTPDirListingConv() {
     179           0 :     NS_IF_RELEASE(mFinalListener);
     180           0 : }
     181             : 
     182             : nsresult
     183           0 : nsFTPDirListingConv::GetHeaders(nsACString& headers,
     184             :                                 nsIURI* uri)
     185             : {
     186           0 :     nsresult rv = NS_OK;
     187             :     // build up 300 line
     188           0 :     headers.AppendLiteral("300: ");
     189             : 
     190             :     // Bug 111117 - don't print the password
     191           0 :     nsAutoCString pw;
     192           0 :     nsAutoCString spec;
     193           0 :     uri->GetPassword(pw);
     194           0 :     if (!pw.IsEmpty()) {
     195           0 :          rv = uri->SetPassword(EmptyCString());
     196           0 :          if (NS_FAILED(rv)) return rv;
     197           0 :          rv = uri->GetAsciiSpec(spec);
     198           0 :          if (NS_FAILED(rv)) return rv;
     199           0 :          headers.Append(spec);
     200           0 :          rv = uri->SetPassword(pw);
     201           0 :          if (NS_FAILED(rv)) return rv;
     202             :     } else {
     203           0 :         rv = uri->GetAsciiSpec(spec);
     204           0 :         if (NS_FAILED(rv)) return rv;
     205             : 
     206           0 :         headers.Append(spec);
     207             :     }
     208           0 :     headers.Append(char(nsCRT::LF));
     209             :     // END 300:
     210             : 
     211             :     // build up the column heading; 200:
     212           0 :     headers.AppendLiteral("200: filename content-length last-modified file-type\n");
     213             :     // END 200:
     214           0 :     return rv;
     215             : }
     216             : 
     217             : char *
     218           0 : nsFTPDirListingConv::DigestBufferLines(char *aBuffer, nsCString &aString) {
     219           0 :     char *line = aBuffer;
     220             :     char *eol;
     221           0 :     bool cr = false;
     222             : 
     223           0 :     list_state state;
     224             : 
     225             :     // while we have new lines, parse 'em into application/http-index-format.
     226           0 :     while ( line && (eol = PL_strchr(line, nsCRT::LF)) ) {
     227             :         // yank any carriage returns too.
     228           0 :         if (eol > line && *(eol-1) == nsCRT::CR) {
     229           0 :             eol--;
     230           0 :             *eol = '\0';
     231           0 :             cr = true;
     232             :         } else {
     233           0 :             *eol = '\0';
     234           0 :             cr = false;
     235             :         }
     236             : 
     237             :         list_result result;
     238             : 
     239           0 :         int type = ParseFTPList(line, &state, &result );
     240             : 
     241             :         // if it is other than a directory, file, or link -OR- if it is a
     242             :         // directory named . or .., skip over this line.
     243           0 :         if ((type != 'd' && type != 'f' && type != 'l') ||
     244           0 :             (result.fe_type == 'd' && result.fe_fname[0] == '.' &&
     245           0 :             (result.fe_fnlen == 1 || (result.fe_fnlen == 2 &&  result.fe_fname[1] == '.'))) )
     246             :         {
     247           0 :             if (cr)
     248           0 :                 line = eol+2;
     249             :             else
     250           0 :                 line = eol+1;
     251             : 
     252           0 :             continue;
     253             :         }
     254             : 
     255             :         // blast the index entry into the indexFormat buffer as a 201: line.
     256           0 :         aString.AppendLiteral("201: ");
     257             :         // FILENAME
     258             : 
     259             :         // parsers for styles 'U' and 'W' handle sequence " -> " themself
     260           0 :         if (state.lstyle != 'U' && state.lstyle != 'W') {
     261           0 :             const char* offset = strstr(result.fe_fname, " -> ");
     262           0 :             if (offset) {
     263           0 :                 result.fe_fnlen = offset - result.fe_fname;
     264             :             }
     265             :         }
     266             : 
     267           0 :         nsAutoCString buf;
     268           0 :         aString.Append('\"');
     269           0 :         aString.Append(NS_EscapeURL(Substring(result.fe_fname,
     270           0 :                                               result.fe_fname+result.fe_fnlen),
     271           0 :                                     esc_Minimal|esc_OnlyASCII|esc_Forced,buf));
     272           0 :         aString.AppendLiteral("\" ");
     273             : 
     274             :         // CONTENT LENGTH
     275             : 
     276           0 :         if (type != 'd')
     277             :         {
     278           0 :             for (int i = 0; i < int(sizeof(result.fe_size)); ++i)
     279             :             {
     280           0 :                 if (result.fe_size[i] != '\0')
     281           0 :                     aString.Append((const char*)&result.fe_size[i], 1);
     282             :             }
     283             : 
     284           0 :             aString.Append(' ');
     285             :         }
     286             :         else
     287           0 :             aString.AppendLiteral("0 ");
     288             : 
     289             : 
     290             :         // MODIFIED DATE
     291           0 :         char buffer[256] = "";
     292             : 
     293             :         // ParseFTPList can return time structure with invalid values.
     294             :         // PR_NormalizeTime will set all values into valid limits.
     295           0 :         result.fe_time.tm_params.tp_gmt_offset = 0;
     296           0 :         result.fe_time.tm_params.tp_dst_offset = 0;
     297           0 :         PR_NormalizeTime(&result.fe_time, PR_GMTParameters);
     298             : 
     299             :         // Note: The below is the RFC822/1123 format, as required by
     300             :         // the application/http-index-format specs
     301             :         // viewers of such a format can then reformat this into the
     302             :         // current locale (or anything else they choose)
     303             :         PR_FormatTimeUSEnglish(buffer, sizeof(buffer),
     304           0 :                                "%a, %d %b %Y %H:%M:%S", &result.fe_time );
     305             : 
     306           0 :         nsAutoCString escaped;
     307           0 :         Unused << NS_WARN_IF(!NS_Escape(nsDependentCString(buffer), escaped, url_Path));
     308           0 :         aString.Append(escaped);
     309           0 :         aString.Append(' ');
     310             : 
     311             :         // ENTRY TYPE
     312           0 :         if (type == 'd')
     313           0 :             aString.AppendLiteral("DIRECTORY");
     314           0 :         else if (type == 'l')
     315           0 :             aString.AppendLiteral("SYMBOLIC-LINK");
     316             :         else
     317           0 :             aString.AppendLiteral("FILE");
     318             : 
     319           0 :         aString.Append(' ');
     320             : 
     321           0 :         aString.Append(char(nsCRT::LF)); // complete this line
     322             :         // END 201:
     323             : 
     324           0 :         if (cr)
     325           0 :             line = eol+2;
     326             :         else
     327           0 :             line = eol+1;
     328             :     } // end while(eol)
     329             : 
     330           0 :     return line;
     331             : }
     332             : 
     333             : nsresult
     334           0 : NS_NewFTPDirListingConv(nsFTPDirListingConv** aFTPDirListingConv)
     335             : {
     336           0 :     NS_PRECONDITION(aFTPDirListingConv != nullptr, "null ptr");
     337           0 :     if (! aFTPDirListingConv)
     338           0 :         return NS_ERROR_NULL_POINTER;
     339             : 
     340           0 :     *aFTPDirListingConv = new nsFTPDirListingConv();
     341           0 :     if (! *aFTPDirListingConv)
     342           0 :         return NS_ERROR_OUT_OF_MEMORY;
     343             : 
     344           0 :     NS_ADDREF(*aFTPDirListingConv);
     345           0 :     return NS_OK;
     346             : }

Generated by: LCOV version 1.13