1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
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 "nsHTMLFormatConverter.h"
7 
8 #include "nsArray.h"
9 #include "nsCRT.h"
10 #include "nsCOMPtr.h"
11 #include "nsITransferable.h"
12 #include "nsLiteralString.h"
13 #include "nsXPCOM.h"
14 #include "nsISupportsPrimitives.h"
15 
16 // HTML convertor stuff
17 #include "nsPrimitiveHelpers.h"
18 #include "nsIDocumentEncoder.h"
19 #include "nsContentUtils.h"
20 
21 nsHTMLFormatConverter::nsHTMLFormatConverter() = default;
22 
23 nsHTMLFormatConverter::~nsHTMLFormatConverter() = default;
24 
NS_IMPL_ISUPPORTS(nsHTMLFormatConverter,nsIFormatConverter)25 NS_IMPL_ISUPPORTS(nsHTMLFormatConverter, nsIFormatConverter)
26 
27 //
28 // GetInputDataFlavors
29 //
30 // Creates a new list and returns the list of all the flavors this converter
31 // knows how to import. In this case, it's just HTML.
32 //
33 NS_IMETHODIMP
34 nsHTMLFormatConverter::GetInputDataFlavors(nsTArray<nsCString>& aFlavors) {
35   aFlavors.AppendElement(nsLiteralCString(kHTMLMime));
36   return NS_OK;
37 }
38 
39 //
40 // GetOutputDataFlavors
41 //
42 // Creates a new list and returns the list of all the flavors this converter
43 // knows how to export (convert). In this case, it's all sorts of things that
44 // HTML can be converted to.
45 //
46 NS_IMETHODIMP
GetOutputDataFlavors(nsTArray<nsCString> & aFlavors)47 nsHTMLFormatConverter::GetOutputDataFlavors(nsTArray<nsCString>& aFlavors) {
48   aFlavors.AppendElement(nsLiteralCString(kHTMLMime));
49   aFlavors.AppendElement(nsLiteralCString(kUnicodeMime));
50   return NS_OK;
51 }
52 
53 //
54 // CanConvert
55 //
56 // Determines if we support the given conversion. Currently, this method only
57 // converts from HTML to others.
58 //
59 NS_IMETHODIMP
CanConvert(const char * aFromDataFlavor,const char * aToDataFlavor,bool * _retval)60 nsHTMLFormatConverter::CanConvert(const char* aFromDataFlavor,
61                                   const char* aToDataFlavor, bool* _retval) {
62   if (!_retval) return NS_ERROR_INVALID_ARG;
63 
64   *_retval = false;
65   if (!nsCRT::strcmp(aFromDataFlavor, kHTMLMime)) {
66     if (!nsCRT::strcmp(aToDataFlavor, kHTMLMime))
67       *_retval = true;
68     else if (!nsCRT::strcmp(aToDataFlavor, kUnicodeMime))
69       *_retval = true;
70 #if NOT_NOW
71     // pinkerton
72     // no one uses this flavor right now, so it's just slowing things down. If
73     // anyone cares I can put it back in.
74     else if (toFlavor.Equals(kAOLMailMime))
75       *_retval = true;
76 #endif
77   }
78   return NS_OK;
79 
80 }  // CanConvert
81 
82 //
83 // Convert
84 //
85 // Convert data from one flavor to another. The data is wrapped in primitive
86 // objects so that it is accessible from JS. Currently, this only accepts HTML
87 // input, so anything else is invalid.
88 //
89 // XXX This method copies the data WAAAAY too many time for my liking. Grrrrrr.
90 // Mostly it's because
91 // XXX we _must_ put things into nsStrings so that the parser will accept it.
92 // Lame lame lame lame. We
93 // XXX also can't just get raw unicode out of the nsString, so we have to
94 // allocate heap to get
95 // XXX unicode out of the string. Lame lame lame.
96 //
97 NS_IMETHODIMP
Convert(const char * aFromDataFlavor,nsISupports * aFromData,const char * aToDataFlavor,nsISupports ** aToData)98 nsHTMLFormatConverter::Convert(const char* aFromDataFlavor,
99                                nsISupports* aFromData,
100                                const char* aToDataFlavor,
101                                nsISupports** aToData) {
102   if (!aToData) return NS_ERROR_INVALID_ARG;
103 
104   nsresult rv = NS_OK;
105   *aToData = nullptr;
106 
107   if (!nsCRT::strcmp(aFromDataFlavor, kHTMLMime)) {
108     nsAutoCString toFlavor(aToDataFlavor);
109 
110     // HTML on clipboard is going to always be double byte so it will be in a
111     // primitive class of nsISupportsString. Also, since the data is in two byte
112     // chunks the length represents the length in 1-byte chars, so we need to
113     // divide by two.
114     nsCOMPtr<nsISupportsString> dataWrapper0(do_QueryInterface(aFromData));
115     if (!dataWrapper0) {
116       return NS_ERROR_INVALID_ARG;
117     }
118 
119     nsAutoString dataStr;
120     dataWrapper0->GetData(dataStr);  // COPY #1
121     // note: conversion to text/plain is done inside the clipboard. we do not
122     // need to worry about it here.
123     if (toFlavor.Equals(kHTMLMime) || toFlavor.Equals(kUnicodeMime)) {
124       nsresult res;
125       if (toFlavor.Equals(kHTMLMime)) {
126         int32_t dataLen = dataStr.Length() * 2;
127         nsPrimitiveHelpers::CreatePrimitiveForData(toFlavor, dataStr.get(),
128                                                    dataLen, aToData);
129       } else {
130         nsAutoString outStr;
131         res = ConvertFromHTMLToUnicode(dataStr, outStr);
132         if (NS_SUCCEEDED(res)) {
133           int32_t dataLen = outStr.Length() * 2;
134           nsPrimitiveHelpers::CreatePrimitiveForData(toFlavor, outStr.get(),
135                                                      dataLen, aToData);
136         }
137       }
138     }  // else if HTML or Unicode
139     else if (toFlavor.Equals(kAOLMailMime)) {
140       nsAutoString outStr;
141       if (NS_SUCCEEDED(ConvertFromHTMLToAOLMail(dataStr, outStr))) {
142         int32_t dataLen = outStr.Length() * 2;
143         nsPrimitiveHelpers::CreatePrimitiveForData(toFlavor, outStr.get(),
144                                                    dataLen, aToData);
145       }
146     }  // else if AOL mail
147     else {
148       rv = NS_ERROR_FAILURE;
149     }
150   }  // if we got html mime
151   else
152     rv = NS_ERROR_FAILURE;
153 
154   return rv;
155 
156 }  // Convert
157 
158 //
159 // ConvertFromHTMLToUnicode
160 //
161 // Takes HTML and converts it to plain text but in unicode.
162 //
163 NS_IMETHODIMP
ConvertFromHTMLToUnicode(const nsAutoString & aFromStr,nsAutoString & aToStr)164 nsHTMLFormatConverter::ConvertFromHTMLToUnicode(const nsAutoString& aFromStr,
165                                                 nsAutoString& aToStr) {
166   return nsContentUtils::ConvertToPlainText(
167       aFromStr, aToStr,
168       nsIDocumentEncoder::OutputSelectionOnly |
169           nsIDocumentEncoder::OutputAbsoluteLinks |
170           nsIDocumentEncoder::OutputNoScriptContent |
171           nsIDocumentEncoder::OutputNoFramesContent,
172       0);
173 }  // ConvertFromHTMLToUnicode
174 
175 NS_IMETHODIMP
ConvertFromHTMLToAOLMail(const nsAutoString & aFromStr,nsAutoString & aToStr)176 nsHTMLFormatConverter::ConvertFromHTMLToAOLMail(const nsAutoString& aFromStr,
177                                                 nsAutoString& aToStr) {
178   aToStr.AssignLiteral("<HTML>");
179   aToStr.Append(aFromStr);
180   aToStr.AppendLiteral("</HTML>");
181 
182   return NS_OK;
183 }
184