michael@0: /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #include "nsHTMLFormatConverter.h" michael@0: michael@0: #include "nsCRT.h" michael@0: #include "nsISupportsArray.h" michael@0: #include "nsIComponentManager.h" michael@0: #include "nsCOMPtr.h" michael@0: #include "nsXPCOM.h" michael@0: #include "nsISupportsPrimitives.h" michael@0: michael@0: #include "nsITransferable.h" // for mime defs, this is BAD michael@0: michael@0: // HTML convertor stuff michael@0: #include "nsPrimitiveHelpers.h" michael@0: #include "nsIDocumentEncoder.h" michael@0: #include "nsContentUtils.h" michael@0: michael@0: nsHTMLFormatConverter::nsHTMLFormatConverter() michael@0: { michael@0: } michael@0: michael@0: nsHTMLFormatConverter::~nsHTMLFormatConverter() michael@0: { michael@0: } michael@0: michael@0: NS_IMPL_ISUPPORTS(nsHTMLFormatConverter, nsIFormatConverter) michael@0: michael@0: // michael@0: // GetInputDataFlavors michael@0: // michael@0: // Creates a new list and returns the list of all the flavors this converter michael@0: // knows how to import. In this case, it's just HTML. michael@0: // michael@0: // Flavors (strings) are wrapped in a primitive object so that JavaScript can michael@0: // access them easily via XPConnect. michael@0: // michael@0: NS_IMETHODIMP michael@0: nsHTMLFormatConverter::GetInputDataFlavors(nsISupportsArray **_retval) michael@0: { michael@0: if ( !_retval ) michael@0: return NS_ERROR_INVALID_ARG; michael@0: michael@0: nsresult rv = NS_NewISupportsArray ( _retval ); // addrefs for us michael@0: if ( NS_SUCCEEDED(rv) ) michael@0: rv = AddFlavorToList ( *_retval, kHTMLMime ); michael@0: michael@0: return rv; michael@0: michael@0: } // GetInputDataFlavors michael@0: michael@0: michael@0: // michael@0: // GetOutputDataFlavors michael@0: // michael@0: // Creates a new list and returns the list of all the flavors this converter michael@0: // knows how to export (convert). In this case, it's all sorts of things that HTML can be michael@0: // converted to. michael@0: // michael@0: // Flavors (strings) are wrapped in a primitive object so that JavaScript can michael@0: // access them easily via XPConnect. michael@0: // michael@0: NS_IMETHODIMP michael@0: nsHTMLFormatConverter::GetOutputDataFlavors(nsISupportsArray **_retval) michael@0: { michael@0: if ( !_retval ) michael@0: return NS_ERROR_INVALID_ARG; michael@0: michael@0: nsresult rv = NS_NewISupportsArray ( _retval ); // addrefs for us michael@0: if ( NS_SUCCEEDED(rv) ) { michael@0: rv = AddFlavorToList ( *_retval, kHTMLMime ); michael@0: if ( NS_FAILED(rv) ) michael@0: return rv; michael@0: #if NOT_NOW michael@0: // pinkerton michael@0: // no one uses this flavor right now, so it's just slowing things down. If anyone cares I michael@0: // can put it back in. michael@0: rv = AddFlavorToList ( *_retval, kAOLMailMime ); michael@0: if ( NS_FAILED(rv) ) michael@0: return rv; michael@0: #endif michael@0: rv = AddFlavorToList ( *_retval, kUnicodeMime ); michael@0: if ( NS_FAILED(rv) ) michael@0: return rv; michael@0: } michael@0: return rv; michael@0: michael@0: } // GetOutputDataFlavors michael@0: michael@0: michael@0: // michael@0: // AddFlavorToList michael@0: // michael@0: // Convenience routine for adding a flavor wrapped in an nsISupportsCString object michael@0: // to a list michael@0: // michael@0: nsresult michael@0: nsHTMLFormatConverter :: AddFlavorToList ( nsISupportsArray* inList, const char* inFlavor ) michael@0: { michael@0: nsresult rv; michael@0: michael@0: nsCOMPtr dataFlavor = michael@0: do_CreateInstance(NS_SUPPORTS_CSTRING_CONTRACTID, &rv); michael@0: if ( dataFlavor ) { michael@0: dataFlavor->SetData ( nsDependentCString(inFlavor) ); michael@0: // add to list as an nsISupports so the correct interface gets the addref michael@0: // in AppendElement() michael@0: nsCOMPtr genericFlavor ( do_QueryInterface(dataFlavor) ); michael@0: inList->AppendElement ( genericFlavor); michael@0: } michael@0: return rv; michael@0: michael@0: } // AddFlavorToList michael@0: michael@0: michael@0: // michael@0: // CanConvert michael@0: // michael@0: // Determines if we support the given conversion. Currently, this method only michael@0: // converts from HTML to others. michael@0: // michael@0: NS_IMETHODIMP michael@0: nsHTMLFormatConverter::CanConvert(const char *aFromDataFlavor, const char *aToDataFlavor, bool *_retval) michael@0: { michael@0: if ( !_retval ) michael@0: return NS_ERROR_INVALID_ARG; michael@0: michael@0: *_retval = false; michael@0: if ( !nsCRT::strcmp(aFromDataFlavor, kHTMLMime) ) { michael@0: if ( !nsCRT::strcmp(aToDataFlavor, kHTMLMime) ) michael@0: *_retval = true; michael@0: else if ( !nsCRT::strcmp(aToDataFlavor, kUnicodeMime) ) michael@0: *_retval = true; michael@0: #if NOT_NOW michael@0: // pinkerton michael@0: // no one uses this flavor right now, so it's just slowing things down. If anyone cares I michael@0: // can put it back in. michael@0: else if ( toFlavor.Equals(kAOLMailMime) ) michael@0: *_retval = true; michael@0: #endif michael@0: } michael@0: return NS_OK; michael@0: michael@0: } // CanConvert michael@0: michael@0: michael@0: michael@0: // michael@0: // Convert michael@0: // michael@0: // Convert data from one flavor to another. The data is wrapped in primitive objects so that it is michael@0: // accessible from JS. Currently, this only accepts HTML input, so anything else is invalid. michael@0: // michael@0: //XXX This method copies the data WAAAAY too many time for my liking. Grrrrrr. Mostly it's because michael@0: //XXX we _must_ put things into nsStrings so that the parser will accept it. Lame lame lame lame. We michael@0: //XXX also can't just get raw unicode out of the nsString, so we have to allocate heap to get michael@0: //XXX unicode out of the string. Lame lame lame. michael@0: // michael@0: NS_IMETHODIMP michael@0: nsHTMLFormatConverter::Convert(const char *aFromDataFlavor, nsISupports *aFromData, uint32_t aDataLen, michael@0: const char *aToDataFlavor, nsISupports **aToData, uint32_t *aDataToLen) michael@0: { michael@0: if ( !aToData || !aDataToLen ) michael@0: return NS_ERROR_INVALID_ARG; michael@0: michael@0: nsresult rv = NS_OK; michael@0: *aToData = nullptr; michael@0: *aDataToLen = 0; michael@0: michael@0: if ( !nsCRT::strcmp(aFromDataFlavor, kHTMLMime) ) { michael@0: nsAutoCString toFlavor ( aToDataFlavor ); michael@0: michael@0: // HTML on clipboard is going to always be double byte so it will be in a primitive michael@0: // class of nsISupportsString. Also, since the data is in two byte chunks the michael@0: // length represents the length in 1-byte chars, so we need to divide by two. michael@0: nsCOMPtr dataWrapper0 ( do_QueryInterface(aFromData) ); michael@0: if (!dataWrapper0) { michael@0: return NS_ERROR_INVALID_ARG; michael@0: } michael@0: michael@0: nsAutoString dataStr; michael@0: dataWrapper0->GetData ( dataStr ); //еее COPY #1 michael@0: // note: conversion to text/plain is done inside the clipboard. we do not need to worry michael@0: // about it here. michael@0: if ( toFlavor.Equals(kHTMLMime) || toFlavor.Equals(kUnicodeMime) ) { michael@0: nsresult res; michael@0: if (toFlavor.Equals(kHTMLMime)) { michael@0: int32_t dataLen = dataStr.Length() * 2; michael@0: nsPrimitiveHelpers::CreatePrimitiveForData ( toFlavor.get(), dataStr.get(), dataLen, aToData ); michael@0: if ( *aToData ) michael@0: *aDataToLen = dataLen; michael@0: } else { michael@0: nsAutoString outStr; michael@0: res = ConvertFromHTMLToUnicode(dataStr, outStr); michael@0: if (NS_SUCCEEDED(res)) { michael@0: int32_t dataLen = outStr.Length() * 2; michael@0: nsPrimitiveHelpers::CreatePrimitiveForData ( toFlavor.get(), outStr.get(), dataLen, aToData ); michael@0: if ( *aToData ) michael@0: *aDataToLen = dataLen; michael@0: } michael@0: } michael@0: } // else if HTML or Unicode michael@0: else if ( toFlavor.Equals(kAOLMailMime) ) { michael@0: nsAutoString outStr; michael@0: if ( NS_SUCCEEDED(ConvertFromHTMLToAOLMail(dataStr, outStr)) ) { michael@0: int32_t dataLen = outStr.Length() * 2; michael@0: nsPrimitiveHelpers::CreatePrimitiveForData ( toFlavor.get(), outStr.get(), dataLen, aToData ); michael@0: if ( *aToData ) michael@0: *aDataToLen = dataLen; michael@0: } michael@0: } // else if AOL mail michael@0: else { michael@0: rv = NS_ERROR_FAILURE; michael@0: } michael@0: } // if we got html mime michael@0: else michael@0: rv = NS_ERROR_FAILURE; michael@0: michael@0: return rv; michael@0: michael@0: } // Convert michael@0: michael@0: michael@0: // michael@0: // ConvertFromHTMLToUnicode michael@0: // michael@0: // Takes HTML and converts it to plain text but in unicode. michael@0: // michael@0: NS_IMETHODIMP michael@0: nsHTMLFormatConverter::ConvertFromHTMLToUnicode(const nsAutoString & aFromStr, nsAutoString & aToStr) michael@0: { michael@0: return nsContentUtils::ConvertToPlainText(aFromStr, michael@0: aToStr, michael@0: nsIDocumentEncoder::OutputSelectionOnly | michael@0: nsIDocumentEncoder::OutputAbsoluteLinks | michael@0: nsIDocumentEncoder::OutputNoScriptContent | michael@0: nsIDocumentEncoder::OutputNoFramesContent, michael@0: 0); michael@0: } // ConvertFromHTMLToUnicode michael@0: michael@0: michael@0: NS_IMETHODIMP michael@0: nsHTMLFormatConverter::ConvertFromHTMLToAOLMail(const nsAutoString & aFromStr, michael@0: nsAutoString & aToStr) michael@0: { michael@0: aToStr.AssignLiteral(""); michael@0: aToStr.Append(aFromStr); michael@0: aToStr.AppendLiteral(""); michael@0: michael@0: return NS_OK; michael@0: } michael@0: