Changeset 87788 in webkit


Ignore:
Timestamp:
Jun 1, 2011 2:17:53 AM (13 years ago)
Author:
jcivelli@chromium.org
Message:

2011-06-01 Jay Civelli <jcivelli@chromium.org>

Reviewed by Adam Barth.

Added a method to generate RFC 2822 compliant date strings.
https://bugs.webkit.org/show_bug.cgi?id=7169

  • wtf/DateMath.cpp: (WTF::twoDigitStringFromNumber): (WTF::makeRFC2822DateString):
  • wtf/DateMath.h:

2011-06-01 Jay Civelli <jcivelli@chromium.org>

Reviewed by Adam Barth.

Adding MHTML generation support to MHTMLArchive.
https://bugs.webkit.org/show_bug.cgi?id=7169

  • loader/archive/mhtml/MHTMLArchive.cpp: (WebCore::generateRandomBoundary): (WebCore::replaceNonPrintableCharacters): (WebCore::MHTMLArchive::generateMHTMLData):
  • loader/archive/mhtml/MHTMLArchive.h:
  • page/PageSerializer.cpp: (WebCore::PageSerializer::serializeFrame): (WebCore::PageSerializer::serializeCSSStyleSheet):
  • platform/SharedBuffer.cpp: (WebCore::SharedBuffer::append):
  • platform/SharedBuffer.h:

2011-06-01 Jay Civelli <jcivelli@chromium.org>

Reviewed by Adam Barth.

Adding MHTML generation support to MHTMLArchive.
https://bugs.webkit.org/show_bug.cgi?id=7169

  • public/WebPageSerializer.h:
  • src/WebPageSerializer.cpp: (WebKit::WebPageSerializer::serializeToMHTML):
Location:
trunk/Source
Files:
12 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/ChangeLog

    r87771 r87788  
     12011-06-01  Jay Civelli  <jcivelli@chromium.org>
     2
     3        Reviewed by Adam Barth.
     4
     5        Added a method to generate RFC 2822 compliant date strings.
     6        https://bugs.webkit.org/show_bug.cgi?id=7169
     7
     8        * wtf/DateMath.cpp:
     9        (WTF::twoDigitStringFromNumber):
     10        (WTF::makeRFC2822DateString):
     11        * wtf/DateMath.h:
     12
    1132011-05-31  Yong Li  <yoli@rim.com>
    214
  • trunk/Source/JavaScriptCore/wtf/DateMath.cpp

    r81040 r87788  
    9191#include <stdint.h>
    9292#include <time.h>
    93 
     93#include <wtf/text/StringBuilder.h>
    9494
    9595#if HAVE(ERRNO_H)
     
    179179{
    180180    return floor(ms / msPerDay);
     181}
     182
     183static String twoDigitStringFromNumber(int number)
     184{
     185    ASSERT(number >= 0 && number < 100);
     186    if (number > 9)
     187        return String::number(number);
     188    return makeString("0", String::number(number));
    181189}
    182190
     
    10281036        return NaN;
    10291037    return trunc(t);
     1038}
     1039
     1040// See http://tools.ietf.org/html/rfc2822#section-3.3 for more information.
     1041String makeRFC2822DateString(unsigned dayOfWeek, unsigned day, unsigned month, unsigned year, unsigned hours, unsigned minutes, unsigned seconds, int utcOffset)
     1042{
     1043    StringBuilder stringBuilder;
     1044    stringBuilder.append(weekdayName[dayOfWeek]);
     1045    stringBuilder.append(", ");
     1046    stringBuilder.append(String::number(day));
     1047    stringBuilder.append(" ");
     1048    stringBuilder.append(monthName[month]);
     1049    stringBuilder.append(" ");
     1050    stringBuilder.append(String::number(year));
     1051    stringBuilder.append(" ");
     1052
     1053    stringBuilder.append(twoDigitStringFromNumber(hours));
     1054    stringBuilder.append(':');
     1055    stringBuilder.append(twoDigitStringFromNumber(minutes));
     1056    stringBuilder.append(':');
     1057    stringBuilder.append(twoDigitStringFromNumber(seconds));
     1058    stringBuilder.append(' ');
     1059
     1060    stringBuilder.append(utcOffset > 0 ? "+" : "-");
     1061    int absoluteUTCOffset = abs(utcOffset);
     1062    stringBuilder.append(twoDigitStringFromNumber(absoluteUTCOffset / 60));
     1063    stringBuilder.append(twoDigitStringFromNumber(absoluteUTCOffset % 60));
     1064
     1065    return stringBuilder.toString();
    10301066}
    10311067} // namespace WTF
  • trunk/Source/JavaScriptCore/wtf/DateMath.h

    r77785 r87788  
    5252#include <wtf/OwnArrayPtr.h>
    5353#include <wtf/PassOwnArrayPtr.h>
     54#include <wtf/text/WTFString.h>
    5455#include <wtf/UnusedParam.h>
    5556
     
    6263double parseDateFromNullTerminatedCharacters(const char* dateString);
    6364double timeClip(double);
     65// dayOfWeek: [0, 6] 0 being Monday, day: [1, 31], month: [0, 11], year: ex: 2011, hours: [0, 23], minutes: [0, 59], seconds: [0, 59], utcOffset: [-720,720].
     66String makeRFC2822DateString(unsigned dayOfWeek, unsigned day, unsigned month, unsigned year, unsigned hours, unsigned minutes, unsigned seconds, int utcOffset);
    6467
    6568inline double jsCurrentTime()
     
    107110using WTF::secondsPerMinute;
    108111using WTF::parseDateFromNullTerminatedCharacters;
     112using WTF::makeRFC2822DateString;
    109113using WTF::calculateUTCOffset;
    110114using WTF::calculateDSTOffset;
  • trunk/Source/WebCore/ChangeLog

    r87780 r87788  
     12011-06-01  Jay Civelli  <jcivelli@chromium.org>
     2
     3        Reviewed by Adam Barth.
     4
     5        Adding MHTML generation support to MHTMLArchive.
     6        https://bugs.webkit.org/show_bug.cgi?id=7169
     7
     8        * loader/archive/mhtml/MHTMLArchive.cpp:
     9        (WebCore::generateRandomBoundary):
     10        (WebCore::replaceNonPrintableCharacters):
     11        (WebCore::MHTMLArchive::generateMHTMLData):
     12        * loader/archive/mhtml/MHTMLArchive.h:
     13        * page/PageSerializer.cpp:
     14        (WebCore::PageSerializer::serializeFrame):
     15        (WebCore::PageSerializer::serializeCSSStyleSheet):
     16        * platform/SharedBuffer.cpp:
     17        (WebCore::SharedBuffer::append):
     18        * platform/SharedBuffer.h:
     19
    1202011-06-01  Dimitri Glazkov  <dglazkov@chromium.org>
    221
  • trunk/Source/WebCore/loader/archive/mhtml/MHTMLArchive.cpp

    r87266 r87788  
    3434#include "MHTMLArchive.h"
    3535
     36#include "Base64.h"
     37#include "CryptographicallyRandomNumber.h"
     38#include "DateMath.h"
     39#include "Document.h"
     40#include "Frame.h"
    3641#include "MHTMLParser.h"
    37 #include "MIMEHeader.h"
     42#include "MIMETypeRegistry.h"
     43#include "Page.h"
     44#include "PageSerializer.h"
     45#include "QuotedPrintable.h"
     46#include "SharedBuffer.h"
     47#include <sys/time.h>
     48#include <wtf/StdLibExtras.h>
     49#include <wtf/text/StringBuilder.h>
    3850
    3951namespace WebCore {
     52
     53const char* const quotedPrintable = "quoted-printable";
     54const char* const base64 = "base64";
     55
     56static String generateRandomBoundary()
     57{
     58    // Trying to generate random boundaries similar to IE/UnMHT (ex: ----=_NextPart_000_001B_01CC157B.96F808A0).
     59    const size_t randomValuesLength = 10;
     60    char randomValues[randomValuesLength];
     61    cryptographicallyRandomValues(&randomValues, randomValuesLength);
     62    StringBuilder stringBuilder;
     63    stringBuilder.append("----=_NextPart_000_");
     64    for (size_t i = 0; i < randomValuesLength; ++i) {
     65        if (i == 2)
     66            stringBuilder.append('_');
     67        else if (i == 6)
     68            stringBuilder.append('.');
     69        stringBuilder.append(lowerNibbleToASCIIHexDigit(randomValues[i]));
     70        stringBuilder.append(upperNibbleToASCIIHexDigit(randomValues[i]));
     71    }
     72    return stringBuilder.toString();
     73}
     74
     75static String replaceNonPrintableCharacters(const String& text)
     76{
     77    StringBuilder stringBuilder;
     78    for (size_t i = 0; i < text.length(); ++i) {
     79      if (isASCIIPrintable(text[i]))
     80        stringBuilder.append(text[i]);
     81      else
     82        stringBuilder.append('?');
     83    }
     84    return stringBuilder.toString();
     85}
    4086
    4187MHTMLArchive::MHTMLArchive()
     
    72118}
    73119
     120PassRefPtr<SharedBuffer> MHTMLArchive::generateMHTMLData(Page* page)
     121{
     122    Vector<PageSerializer::Resource> resources;
     123    PageSerializer pageSerializer(&resources);
     124    pageSerializer.serialize(page);
     125
     126    String boundary = generateRandomBoundary();
     127    String endOfResourceBoundary = makeString("--", boundary, "\r\n");
     128
     129    String dateString;
     130    timeval timeValue = { 0 };
     131    if (!gettimeofday(&timeValue, 0)) {
     132        tm timeAndDate = { 0 };
     133        if (localtime_r(&(timeValue.tv_sec), &timeAndDate))
     134            dateString = makeRFC2822DateString(timeAndDate.tm_wday, timeAndDate.tm_mday, timeAndDate.tm_mon, 1900 + timeAndDate.tm_year, timeAndDate.tm_hour, timeAndDate.tm_min, timeAndDate.tm_sec, calculateUTCOffset() / (1000 * 60));
     135        else
     136            ASSERT_NOT_REACHED();
     137    } else
     138        ASSERT_NOT_REACHED();
     139
     140    StringBuilder stringBuilder;
     141    stringBuilder.append("From: <Saved by WebKit>\r\n");
     142    stringBuilder.append("Subject: ");
     143    // We replace non ASCII characters with '?' characters to match IE's behavior.
     144    stringBuilder.append(replaceNonPrintableCharacters(page->mainFrame()->document()->title()));
     145    if (!dateString.isEmpty()) {
     146        stringBuilder.append("\r\nDate: ");
     147        stringBuilder.append(dateString);
     148    }
     149    stringBuilder.append("\r\nMIME-Version: 1.0\r\n");
     150    stringBuilder.append("Content-Type: multipart/related;\r\n");
     151    stringBuilder.append("\ttype=\"");
     152    stringBuilder.append(page->mainFrame()->document()->suggestedMIMEType());
     153    stringBuilder.append("\";\r\n");
     154    stringBuilder.append("\tboundary=\"");
     155    stringBuilder.append(boundary);
     156    stringBuilder.append("\"\r\n\r\n");
     157
     158    // We use utf8() below instead of ascii() as ascii() replaces CRLFs with ?? (we still only have put ASCII characters in it).
     159    ASSERT(stringBuilder.toString().containsOnlyASCII());
     160    CString asciiString = stringBuilder.toString().utf8();
     161    RefPtr<SharedBuffer> mhtmlData = SharedBuffer::create();
     162    mhtmlData->append(asciiString.data(), asciiString.length());
     163
     164    for (size_t i = 0; i < resources.size(); ++i) {
     165        const PageSerializer::Resource& resource = resources[i];
     166
     167        stringBuilder.clear();
     168        stringBuilder.append(endOfResourceBoundary);
     169        stringBuilder.append("Content-Type: ");
     170        stringBuilder.append(resource.mimeType);
     171
     172        const char* contentEncoding = MIMETypeRegistry::isSupportedJavaScriptMIMEType(resource.mimeType) || MIMETypeRegistry::isSupportedNonImageMIMEType(resource.mimeType) ? quotedPrintable : base64;
     173        stringBuilder.append("\r\nContent-Transfer-Encoding: ");
     174        stringBuilder.append(contentEncoding);
     175        stringBuilder.append("\r\nContent-Location: ");
     176        stringBuilder.append(resource.url);
     177        stringBuilder.append("\r\n\r\n");
     178
     179        asciiString = stringBuilder.toString().utf8();
     180        mhtmlData->append(asciiString.data(), asciiString.length());
     181
     182        // FIXME: ideally we would encode the content as a stream without having to fetch it all.
     183        const char* data = resource.data->data();
     184        size_t dataLength = resource.data->size();
     185        Vector<char> encodedData;
     186        if (!strcmp(contentEncoding, quotedPrintable)) {
     187            quotedPrintableEncode(data, dataLength, encodedData);
     188            mhtmlData->append(encodedData.data(), encodedData.size());
     189            mhtmlData->append("\r\n", 2);
     190        } else {
     191            ASSERT(!strcmp(contentEncoding, base64));
     192            // We are not specifying insertLFs = true below as it would cut the lines with LFs and MHTML requires CRLFs.
     193            base64Encode(data, dataLength, encodedData);
     194            const size_t maximumLineLength = 76;
     195            size_t index = 0;
     196            size_t encodedDataLength = encodedData.size();
     197            do {
     198                size_t lineLength = std::min(encodedDataLength - index, maximumLineLength);
     199                mhtmlData->append(encodedData.data() + index, lineLength);
     200                mhtmlData->append("\r\n", 2);
     201                index += maximumLineLength;
     202            } while (index < encodedDataLength);
     203        }
     204    }
     205
     206    asciiString = makeString("--", boundary, "--\r\n").utf8();
     207    mhtmlData->append(asciiString.data(), asciiString.length());
     208
     209    return mhtmlData.release();
     210}
     211
    74212}
    75213#endif
  • trunk/Source/WebCore/loader/archive/mhtml/MHTMLArchive.h

    r87189 r87788  
    3939
    4040class MHTMLParser;
     41class Page;
     42class SharedBuffer;
    4143
    4244class MHTMLArchive : public Archive {
     
    4648    static PassRefPtr<MHTMLArchive> create();
    4749    static PassRefPtr<MHTMLArchive> create(const KURL&, SharedBuffer*);
     50
     51    static PassRefPtr<SharedBuffer> generateMHTMLData(Page*);
    4852
    4953private:
  • trunk/Source/WebCore/page/PageSerializer.cpp

    r86949 r87788  
    207207    Vector<Node*> nodes;
    208208    SerializerMarkupAccumulator accumulator(this, document, &nodes);
    209     TextEncoding textEncoding(TextEncoding(document->charset()));
    210     ASSERT(textEncoding.isValid());
     209    TextEncoding textEncoding(document->charset());
     210    CString data;
     211    if (!textEncoding.isValid()) {
     212        // FIXME: iframes used as images trigger this. We should deal with them correctly.
     213        return;
     214    }
    211215    String text = accumulator.serializeNodes(document->documentElement(), 0, IncludeNode);
    212216    CString frameHTML = textEncoding.encode(text.characters(), text.length(), EntitiesForUnencodables);
     
    275279    if (url.isValid() && !m_resourceURLs.contains(url)) {
    276280        // FIXME: We should check whether a charset has been specified and if none was found add one.
    277         TextEncoding textEncoding = TextEncoding(styleSheet->charset());
     281        TextEncoding textEncoding(styleSheet->charset());
    278282        ASSERT(textEncoding.isValid());
    279283        String textString = cssText.toString();
  • trunk/Source/WebCore/platform/SharedBuffer.cpp

    r81710 r87788  
    118118}
    119119
     120void SharedBuffer::append(SharedBuffer* data)
     121{
     122    const char* segment;
     123    size_t position = 0;
     124    while (size_t length = data->getSomeData(segment, position)) {
     125        append(segment, length);
     126        position += length;
     127    }
     128}
     129
    120130void SharedBuffer::append(const char* data, unsigned length)
    121131{
  • trunk/Source/WebCore/platform/SharedBuffer.h

    r87312 r87788  
    8585    bool isEmpty() const { return !size(); }
    8686
     87    void append(SharedBuffer*);
    8788    void append(const char*, unsigned);
    8889    void clear();
  • trunk/Source/WebKit/chromium/ChangeLog

    r87786 r87788  
     12011-06-01  Jay Civelli  <jcivelli@chromium.org>
     2
     3        Reviewed by Adam Barth.
     4
     5        Adding MHTML generation support to MHTMLArchive.
     6        https://bugs.webkit.org/show_bug.cgi?id=7169
     7
     8        * public/WebPageSerializer.h:
     9        * src/WebPageSerializer.cpp:
     10        (WebKit::WebPageSerializer::serializeToMHTML):
     11
    1122011-06-01  Mikhail Naganov  <mnaganov@chromium.org>
    213
  • trunk/Source/WebKit/chromium/public/WebPageSerializer.h

    r85244 r87788  
    5959    WEBKIT_API static void serialize(WebView*, WebVector<Resource>*);
    6060
     61    // Serializes the WebView contents to a MHTML representation.
     62    WEBKIT_API static WebCString serializeToMHTML(WebView*);
     63
    6164    // IMPORTANT:
    6265    // The API below is an older implementation of a pageserialization that
  • trunk/Source/WebKit/chromium/src/WebPageSerializer.cpp

    r85244 r87788  
    4040#include "HTMLNames.h"
    4141#include "KURL.h"
     42#include "MHTMLArchive.h"
    4243#include "PageSerializer.h"
    4344#include "Vector.h"
     
    201202}
    202203
     204WebCString WebPageSerializer::serializeToMHTML(WebView* view)
     205{
     206    RefPtr<SharedBuffer> mhtml = MHTMLArchive::generateMHTMLData(static_cast<WebViewImpl*>(view)->page());
     207    // FIXME: we are copying all the data here. Idealy we would have a WebSharedData().
     208    return WebCString(mhtml->data(), mhtml->size());
     209}
     210
    203211bool WebPageSerializer::serialize(WebFrame* frame,
    204212                                  bool recursive,
Note: See TracChangeset for help on using the changeset viewer.