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

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; 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 "nsTXTToHTMLConv.h"
       7             : #include "nsEscape.h"
       8             : #include "nsStringStream.h"
       9             : #include "nsAutoPtr.h"
      10             : #include "nsIChannel.h"
      11             : #include <algorithm>
      12             : 
      13             : #include "mozilla/UniquePtrExtensions.h"
      14             : 
      15             : #define TOKEN_DELIMITERS u"\t\r\n "
      16             : 
      17             : using namespace mozilla;
      18             : 
      19             : // nsISupports methods
      20           0 : NS_IMPL_ISUPPORTS(nsTXTToHTMLConv,
      21             :                   nsIStreamConverter,
      22             :                   nsITXTToHTMLConv,
      23             :                   nsIRequestObserver,
      24             :                   nsIStreamListener)
      25             : 
      26             : 
      27             : // nsIStreamConverter methods
      28             : NS_IMETHODIMP
      29           0 : nsTXTToHTMLConv::Convert(nsIInputStream *aFromStream,
      30             :                          const char *aFromType, const char *aToType,
      31             :                          nsISupports *aCtxt, nsIInputStream * *_retval)
      32             : {
      33           0 :     return NS_ERROR_NOT_IMPLEMENTED;
      34             : }
      35             : 
      36             : NS_IMETHODIMP
      37           0 : nsTXTToHTMLConv::AsyncConvertData(const char *aFromType,
      38             :                                   const char *aToType,
      39             :                                   nsIStreamListener *aListener,
      40             :                                   nsISupports *aCtxt)
      41             : {
      42           0 :     NS_ASSERTION(aListener, "null pointer");
      43           0 :     mListener = aListener;
      44           0 :     return NS_OK;
      45             : }
      46             : 
      47             : 
      48             : // nsIRequestObserver methods
      49             : NS_IMETHODIMP
      50           0 : nsTXTToHTMLConv::OnStartRequest(nsIRequest* request, nsISupports *aContext)
      51             : {
      52           0 :     mBuffer.AssignLiteral("<html>\n<head><title>");
      53           0 :     mBuffer.Append(mPageTitle);
      54           0 :     mBuffer.AppendLiteral("</title></head>\n<body>\n");
      55           0 :     if (mPreFormatHTML) {     // Use <pre> tags
      56           0 :         mBuffer.AppendLiteral("<pre>\n");
      57             :     }
      58             : 
      59             :     // Push mBuffer to the listener now, so the initial HTML will not
      60             :     // be parsed in OnDataAvailable().
      61             : 
      62           0 :     nsCOMPtr<nsIChannel> channel = do_QueryInterface(request);
      63           0 :     if (channel)
      64           0 :         channel->SetContentType(NS_LITERAL_CSTRING("text/html"));
      65             :     // else, assume there is a channel somewhere that knows what it is doing!
      66             : 
      67           0 :     nsresult rv = mListener->OnStartRequest(request, aContext);
      68           0 :     if (NS_FAILED(rv)) return rv;
      69             : 
      70             :     // The request may have been canceled, and if that happens, we want to
      71             :     // suppress calls to OnDataAvailable.
      72           0 :     request->GetStatus(&rv);
      73           0 :     if (NS_FAILED(rv)) return rv;
      74             : 
      75           0 :     nsCOMPtr<nsIInputStream> inputData;
      76           0 :     NS_LossyConvertUTF16toASCII asciiData(mBuffer);
      77           0 :     rv = NS_NewCStringInputStream(getter_AddRefs(inputData), asciiData);
      78           0 :     if (NS_FAILED(rv)) return rv;
      79             : 
      80           0 :     rv = mListener->OnDataAvailable(request, aContext,
      81           0 :                                     inputData, 0, mBuffer.Length());
      82           0 :     if (NS_FAILED(rv)) return rv;
      83           0 :     mBuffer.Truncate();
      84           0 :     return rv;
      85             : }
      86             : 
      87             : NS_IMETHODIMP
      88           0 : nsTXTToHTMLConv::OnStopRequest(nsIRequest* request, nsISupports *aContext,
      89             :                                nsresult aStatus)
      90             : {
      91           0 :     nsresult rv = NS_OK;
      92           0 :     if (mToken) {
      93             :         // we still have an outstanding token
      94           0 :         NS_ASSERTION(mToken->prepend,
      95             :                      "Non prepending tokens should be handled in "
      96             :                      "OnDataAvailable. There should only be a single "
      97             :                      "prepending token left to be processed.");
      98           0 :         (void)CatHTML(0, mBuffer.Length());
      99             :     }
     100           0 :     if (mPreFormatHTML) {
     101           0 :         mBuffer.AppendLiteral("</pre>\n");
     102             :     }
     103           0 :     mBuffer.AppendLiteral("\n</body></html>");
     104             : 
     105           0 :     nsCOMPtr<nsIInputStream> inputData;
     106           0 :     NS_LossyConvertUTF16toASCII asciiData(mBuffer);
     107           0 :     rv = NS_NewCStringInputStream(getter_AddRefs(inputData), asciiData);
     108           0 :     if (NS_FAILED(rv)) return rv;
     109             : 
     110           0 :     rv = mListener->OnDataAvailable(request, aContext,
     111           0 :                                     inputData, 0, mBuffer.Length());
     112           0 :     if (NS_FAILED(rv)) return rv;
     113             : 
     114           0 :     return mListener->OnStopRequest(request, aContext, aStatus);
     115             : }
     116             : 
     117             : // nsITXTToHTMLConv methods
     118             : NS_IMETHODIMP
     119           0 : nsTXTToHTMLConv::SetTitle(const char16_t *aTitle)
     120             : {
     121           0 :     mPageTitle.Assign(aTitle);
     122           0 :     return NS_OK;
     123             : }
     124             : 
     125             : NS_IMETHODIMP
     126           0 : nsTXTToHTMLConv::PreFormatHTML(bool value)
     127             : {
     128           0 :     mPreFormatHTML = value;
     129           0 :     return NS_OK;
     130             : }
     131             : 
     132             : // nsIStreamListener method
     133             : NS_IMETHODIMP
     134           0 : nsTXTToHTMLConv::OnDataAvailable(nsIRequest* request, nsISupports *aContext,
     135             :                                  nsIInputStream *aInStream,
     136             :                                  uint64_t aOffset, uint32_t aCount)
     137             : {
     138           0 :     nsresult rv = NS_OK;
     139           0 :     nsString pushBuffer;
     140           0 :     uint32_t amtRead = 0;
     141           0 :     auto buffer = MakeUniqueFallible<char[]>(aCount+1);
     142           0 :     if (!buffer) return NS_ERROR_OUT_OF_MEMORY;
     143             : 
     144           0 :     do {
     145           0 :         uint32_t read = 0;
     146             :         // XXX readSegments, to avoid the first copy?
     147           0 :         rv = aInStream->Read(buffer.get(), aCount-amtRead, &read);
     148           0 :         if (NS_FAILED(rv)) return rv;
     149             : 
     150           0 :         buffer[read] = '\0';
     151             :         // XXX charsets?? non-latin1 characters?? utf-16??
     152           0 :         AppendASCIItoUTF16(buffer.get(), mBuffer);
     153           0 :         amtRead += read;
     154             : 
     155           0 :         int32_t front = -1, back = -1, tokenLoc = -1, cursor = 0;
     156             : 
     157           0 :         while ( (tokenLoc = FindToken(cursor, &mToken)) > -1) {
     158           0 :             if (mToken->prepend) {
     159           0 :                 front = mBuffer.RFindCharInSet(TOKEN_DELIMITERS, tokenLoc);
     160           0 :                 front++;
     161           0 :                 back = mBuffer.FindCharInSet(TOKEN_DELIMITERS, tokenLoc);
     162             :             } else {
     163           0 :                 front = tokenLoc;
     164           0 :                 back = front + mToken->token.Length();
     165             :             }
     166           0 :             if (back == -1) {
     167             :                 // didn't find an ending, buffer up.
     168           0 :                 mBuffer.Left(pushBuffer, front);
     169           0 :                 cursor = front;
     170           0 :                 break;
     171             :             }
     172             :             // found the end of the token.
     173           0 :             cursor = CatHTML(front, back);
     174             :         }
     175             : 
     176           0 :         int32_t end = mBuffer.RFind(TOKEN_DELIMITERS, mBuffer.Length());
     177           0 :         mBuffer.Left(pushBuffer, std::max(cursor, end));
     178           0 :         mBuffer.Cut(0, std::max(cursor, end));
     179           0 :         cursor = 0;
     180             : 
     181           0 :         if (!pushBuffer.IsEmpty()) {
     182           0 :             nsCOMPtr<nsIInputStream> inputData;
     183           0 :             NS_LossyConvertUTF16toASCII asciiData(pushBuffer);
     184           0 :             rv = NS_NewCStringInputStream(getter_AddRefs(inputData), asciiData);
     185           0 :             if (NS_FAILED(rv))
     186           0 :                 return rv;
     187             : 
     188           0 :             rv = mListener->OnDataAvailable(request, aContext,
     189           0 :                                             inputData, 0, pushBuffer.Length());
     190           0 :             if (NS_FAILED(rv))
     191           0 :                 return rv;
     192             :         }
     193           0 :     } while (amtRead < aCount);
     194             : 
     195           0 :     return rv;
     196             : }
     197             : 
     198             : // nsTXTToHTMLConv methods
     199           0 : nsTXTToHTMLConv::nsTXTToHTMLConv()
     200             : {
     201           0 :     mToken = nullptr;
     202           0 :     mPreFormatHTML = false;
     203           0 : }
     204             : 
     205           0 : nsTXTToHTMLConv::~nsTXTToHTMLConv()
     206             : {
     207           0 :     mTokens.Clear();
     208           0 : }
     209             : 
     210             : nsresult
     211           0 : nsTXTToHTMLConv::Init()
     212             : {
     213           0 :     nsresult rv = NS_OK;
     214             : 
     215             :     // build up the list of tokens to handle
     216           0 :     convToken *token = new convToken;
     217           0 :     if (!token) return NS_ERROR_OUT_OF_MEMORY;
     218           0 :     token->prepend = false;
     219           0 :     token->token.Assign(char16_t('<'));
     220           0 :     token->modText.AssignLiteral("&lt;");
     221           0 :     mTokens.AppendElement(token);
     222             : 
     223           0 :     token = new convToken;
     224           0 :     if (!token) return NS_ERROR_OUT_OF_MEMORY;
     225           0 :     token->prepend = false;
     226           0 :     token->token.Assign(char16_t('>'));
     227           0 :     token->modText.AssignLiteral("&gt;");
     228           0 :     mTokens.AppendElement(token);
     229             : 
     230           0 :     token = new convToken;
     231           0 :     if (!token) return NS_ERROR_OUT_OF_MEMORY;
     232           0 :     token->prepend = false;
     233           0 :     token->token.Assign(char16_t('&'));
     234           0 :     token->modText.AssignLiteral("&amp;");
     235           0 :     mTokens.AppendElement(token);
     236             : 
     237           0 :     token = new convToken;
     238           0 :     if (!token) return NS_ERROR_OUT_OF_MEMORY;
     239           0 :     token->prepend = true;
     240           0 :     token->token.AssignLiteral("http://"); // XXX need to iterate through all protos
     241           0 :     mTokens.AppendElement(token);
     242             : 
     243           0 :     token = new convToken;
     244           0 :     if (!token) return NS_ERROR_OUT_OF_MEMORY;
     245           0 :     token->prepend = true;
     246           0 :     token->token.Assign(char16_t('@'));
     247           0 :     token->modText.AssignLiteral("mailto:");
     248           0 :     mTokens.AppendElement(token);
     249             : 
     250           0 :     return rv;
     251             : }
     252             : 
     253             : int32_t
     254           0 : nsTXTToHTMLConv::FindToken(int32_t cursor, convToken* *_retval)
     255             : {
     256           0 :     int32_t loc = -1, firstToken = mBuffer.Length();
     257           0 :     int8_t token = -1;
     258           0 :     for (uint8_t i=0; i < mTokens.Length(); i++) {
     259           0 :         loc = mBuffer.Find(mTokens[i]->token, cursor);
     260           0 :         if (loc != -1)
     261           0 :             if (loc < firstToken) {
     262           0 :                 firstToken = loc;
     263           0 :                 token = i;
     264             :             }
     265             :     }
     266           0 :     if (token == -1)
     267           0 :         return -1;
     268             : 
     269           0 :     *_retval = mTokens[token];
     270           0 :     return firstToken;
     271             : }
     272             : 
     273             : int32_t
     274           0 : nsTXTToHTMLConv::CatHTML(int32_t front, int32_t back)
     275             : {
     276           0 :     int32_t cursor = 0;
     277           0 :     int32_t modLen = mToken->modText.Length();
     278           0 :     if (!mToken->prepend) {
     279             :         // replace the entire token (from delimiter to delimiter)
     280           0 :         mBuffer.Cut(front, back - front);
     281           0 :         mBuffer.Insert(mToken->modText, front);
     282           0 :         cursor = front+modLen;
     283             :     } else {
     284           0 :         nsString linkText;
     285             :         // href is implied
     286           0 :         mBuffer.Mid(linkText, front, back-front);
     287             : 
     288           0 :         mBuffer.Insert(NS_LITERAL_STRING("<a href=\""), front);
     289           0 :         cursor += front+9;
     290           0 :         if (modLen) {
     291           0 :             mBuffer.Insert(mToken->modText, cursor);
     292           0 :             cursor += modLen;
     293             :         }
     294             : 
     295           0 :         NS_ConvertUTF16toUTF8 linkTextUTF8(linkText);
     296           0 :         nsCString escaped;
     297           0 :         if (NS_EscapeURL(linkTextUTF8.Data(), linkTextUTF8.Length(), esc_Minimal, escaped)) {
     298           0 :             mBuffer.Cut(cursor, back - front);
     299           0 :             CopyUTF8toUTF16(escaped, linkText);
     300           0 :             mBuffer.Insert(linkText, cursor);
     301           0 :             back = front + linkText.Length();
     302             :         }
     303             : 
     304           0 :         cursor += back-front;
     305           0 :         mBuffer.Insert(NS_LITERAL_STRING("\">"), cursor);
     306           0 :         cursor += 2;
     307           0 :         mBuffer.Insert(linkText, cursor);
     308           0 :         cursor += linkText.Length();
     309           0 :         mBuffer.Insert(NS_LITERAL_STRING("</a>"), cursor);
     310           0 :         cursor += 4;
     311             :     }
     312           0 :     mToken = nullptr; // indicates completeness
     313           0 :     return cursor;
     314             : }

Generated by: LCOV version 1.13