1/*
2 * Copyright (C) 2008 Apple Computer, Inc.  All rights reserved.
3 * Copyright (C) 2006 Michael Emmel mike.emmel@gmail.com
4 * Copyright (C) 2007 Alp Toker <alp.toker@collabora.co.uk>
5 * Copyright (C) 2007 Holger Hans Peter Freyther
6 * Copyright (C) 2008 Collabora Ltd.
7 * All rights reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 *    notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 *    notice, this list of conditions and the following disclaimer in the
16 *    documentation and/or other materials provided with the distribution.
17 *
18 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
19 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
21 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
22 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
23 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
24 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
25 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
26 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */
30
31#include "config.h"
32#include "FormDataStreamCurl.h"
33
34#include "FormData.h"
35#include "ResourceRequest.h"
36#include <wtf/text/CString.h>
37
38namespace WebCore {
39
40FormDataStream::~FormDataStream()
41{
42    if (m_file)
43        fclose(m_file);
44}
45
46size_t FormDataStream::read(void* ptr, size_t blockSize, size_t numberOfBlocks)
47{
48    // Check for overflow.
49    if (!numberOfBlocks || blockSize > std::numeric_limits<size_t>::max() / numberOfBlocks)
50        return 0;
51
52    Vector<FormDataElement> elements;
53    if (m_resourceHandle->firstRequest().httpBody())
54        elements = m_resourceHandle->firstRequest().httpBody()->elements();
55
56    if (m_formDataElementIndex >= elements.size())
57        return 0;
58
59    FormDataElement element = elements[m_formDataElementIndex];
60
61    size_t toSend = blockSize * numberOfBlocks;
62    size_t sent;
63
64    if (element.m_type == FormDataElement::encodedFile) {
65        if (!m_file)
66            m_file = fopen(element.m_filename.utf8().data(), "rb");
67
68        if (!m_file) {
69            // FIXME: show a user error?
70#ifndef NDEBUG
71            printf("Failed while trying to open %s for upload\n", element.m_filename.utf8().data());
72#endif
73            return 0;
74        }
75
76        sent = fread(ptr, blockSize, numberOfBlocks, m_file);
77        if (!blockSize && ferror(m_file)) {
78            // FIXME: show a user error?
79#ifndef NDEBUG
80            printf("Failed while trying to read %s for upload\n", element.m_filename.utf8().data());
81#endif
82            return 0;
83        }
84        if (feof(m_file)) {
85            fclose(m_file);
86            m_file = 0;
87            m_formDataElementIndex++;
88        }
89    } else {
90        size_t elementSize = element.m_data.size() - m_formDataElementDataOffset;
91        sent = elementSize > toSend ? toSend : elementSize;
92        memcpy(ptr, element.m_data.data() + m_formDataElementDataOffset, sent);
93        if (elementSize > sent)
94            m_formDataElementDataOffset += sent;
95        else {
96            m_formDataElementDataOffset = 0;
97            m_formDataElementIndex++;
98        }
99    }
100
101    return sent;
102}
103
104bool FormDataStream::hasMoreElements() const
105{
106    Vector<FormDataElement> elements;
107    if (m_resourceHandle->firstRequest().httpBody())
108        elements = m_resourceHandle->firstRequest().httpBody()->elements();
109
110    return m_formDataElementIndex < elements.size();
111}
112
113} // namespace WebCore
114