Home | History | Annotate | Download | only in network
      1 /*
      2  * Copyright (C) 2004, 2006, 2008 Apple Inc. All rights reserved.
      3  * Copyright (C) 2009 Google Inc. All rights reserved.
      4  *
      5  * This library is free software; you can redistribute it and/or
      6  * modify it under the terms of the GNU Library General Public
      7  * License as published by the Free Software Foundation; either
      8  * version 2 of the License, or (at your option) any later version.
      9  *
     10  * This library is distributed in the hope that it will be useful,
     11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
     12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
     13  * Library General Public License for more details.
     14  *
     15  * You should have received a copy of the GNU Library General Public License
     16  * along with this library; see the file COPYING.LIB. If not, write to
     17  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
     18  * Boston, MA 02110-1301, USA.
     19  */
     20 
     21 #include "config.h"
     22 #include "FormData.h"
     23 
     24 #include "CString.h"
     25 #include "ChromeClient.h"
     26 #include "FileSystem.h"
     27 #include "TextEncoding.h"
     28 
     29 namespace WebCore {
     30 
     31 inline FormData::FormData()
     32     : m_identifier(0)
     33     , m_hasGeneratedFiles(false)
     34     , m_alwaysStream(false)
     35 {
     36 }
     37 
     38 inline FormData::FormData(const FormData& data)
     39     : RefCounted<FormData>()
     40     , m_elements(data.m_elements)
     41     , m_identifier(data.m_identifier)
     42     , m_hasGeneratedFiles(false)
     43     , m_alwaysStream(false)
     44 {
     45     // We shouldn't be copying FormData that hasn't already removed its generated files
     46     // but just in case, make sure the new FormData is ready to generate its own files.
     47     if (data.m_hasGeneratedFiles) {
     48         size_t n = m_elements.size();
     49         for (size_t i = 0; i < n; ++i) {
     50             FormDataElement& e = m_elements[i];
     51             if (e.m_type == FormDataElement::encodedFile)
     52                 e.m_generatedFilename = String();
     53         }
     54     }
     55 }
     56 
     57 FormData::~FormData()
     58 {
     59     // This cleanup should've happened when the form submission finished.
     60     // Just in case, let's assert, and do the cleanup anyway in release builds.
     61     ASSERT(!m_hasGeneratedFiles);
     62     removeGeneratedFilesIfNeeded();
     63 }
     64 
     65 PassRefPtr<FormData> FormData::create()
     66 {
     67     return adoptRef(new FormData);
     68 }
     69 
     70 PassRefPtr<FormData> FormData::create(const void* data, size_t size)
     71 {
     72     RefPtr<FormData> result = create();
     73     result->appendData(data, size);
     74     return result.release();
     75 }
     76 
     77 PassRefPtr<FormData> FormData::create(const CString& string)
     78 {
     79     RefPtr<FormData> result = create();
     80     result->appendData(string.data(), string.length());
     81     return result.release();
     82 }
     83 
     84 PassRefPtr<FormData> FormData::create(const Vector<char>& vector)
     85 {
     86     RefPtr<FormData> result = create();
     87     result->appendData(vector.data(), vector.size());
     88     return result.release();
     89 }
     90 
     91 PassRefPtr<FormData> FormData::copy() const
     92 {
     93     return adoptRef(new FormData(*this));
     94 }
     95 
     96 PassRefPtr<FormData> FormData::deepCopy() const
     97 {
     98     RefPtr<FormData> formData(create());
     99 
    100     formData->m_alwaysStream = m_alwaysStream;
    101 
    102     size_t n = m_elements.size();
    103     formData->m_elements.reserveInitialCapacity(n);
    104     for (size_t i = 0; i < n; ++i) {
    105         const FormDataElement& e = m_elements[i];
    106         switch (e.m_type) {
    107         case FormDataElement::data:
    108             formData->m_elements.append(FormDataElement(e.m_data));
    109             break;
    110         case FormDataElement::encodedFile:
    111             formData->m_elements.append(FormDataElement(e.m_filename, e.m_shouldGenerateFile));
    112             break;
    113         }
    114     }
    115     return formData.release();
    116 }
    117 
    118 void FormData::appendData(const void* data, size_t size)
    119 {
    120     if (m_elements.isEmpty() || m_elements.last().m_type != FormDataElement::data)
    121         m_elements.append(FormDataElement());
    122     FormDataElement& e = m_elements.last();
    123     size_t oldSize = e.m_data.size();
    124     e.m_data.grow(oldSize + size);
    125     memcpy(e.m_data.data() + oldSize, data, size);
    126 }
    127 
    128 void FormData::appendFile(const String& filename, bool shouldGenerateFile)
    129 {
    130     m_elements.append(FormDataElement(filename, shouldGenerateFile));
    131 }
    132 
    133 void FormData::flatten(Vector<char>& data) const
    134 {
    135     // Concatenate all the byte arrays, but omit any files.
    136     data.clear();
    137     size_t n = m_elements.size();
    138     for (size_t i = 0; i < n; ++i) {
    139         const FormDataElement& e = m_elements[i];
    140         if (e.m_type == FormDataElement::data) {
    141             size_t oldSize = data.size();
    142             size_t delta = e.m_data.size();
    143             data.grow(oldSize + delta);
    144             memcpy(data.data() + oldSize, e.m_data.data(), delta);
    145         }
    146     }
    147 }
    148 
    149 String FormData::flattenToString() const
    150 {
    151     Vector<char> bytes;
    152     flatten(bytes);
    153     return Latin1Encoding().decode(bytes.data(), bytes.size());
    154 }
    155 
    156 void FormData::generateFiles(ChromeClient* client)
    157 {
    158     ASSERT(!m_hasGeneratedFiles);
    159 
    160     if (m_hasGeneratedFiles)
    161         return;
    162 
    163     size_t n = m_elements.size();
    164     for (size_t i = 0; i < n; ++i) {
    165         FormDataElement& e = m_elements[i];
    166         if (e.m_type == FormDataElement::encodedFile && e.m_shouldGenerateFile) {
    167             e.m_generatedFilename = client->generateReplacementFile(e.m_filename);
    168             m_hasGeneratedFiles = true;
    169         }
    170     }
    171 }
    172 
    173 void FormData::removeGeneratedFilesIfNeeded()
    174 {
    175     if (!m_hasGeneratedFiles)
    176         return;
    177 
    178     size_t n = m_elements.size();
    179     for (size_t i = 0; i < n; ++i) {
    180         FormDataElement& e = m_elements[i];
    181         if (e.m_type == FormDataElement::encodedFile && !e.m_generatedFilename.isEmpty()) {
    182             ASSERT(e.m_shouldGenerateFile);
    183             String directory = directoryName(e.m_generatedFilename);
    184             deleteFile(e.m_generatedFilename);
    185             deleteEmptyDirectory(directory);
    186             e.m_generatedFilename = String();
    187         }
    188     }
    189     m_hasGeneratedFiles = false;
    190 }
    191 
    192 } // namespace WebCore
    193