18e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project/*
28e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * Copyright (C) 2005, 2006, 2007 Apple Inc.  All rights reserved.
38e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *
48e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * Redistribution and use in source and binary forms, with or without
58e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * modification, are permitted provided that the following conditions
68e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * are met:
78e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *
88e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * 1.  Redistributions of source code must retain the above copyright
98e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *     notice, this list of conditions and the following disclaimer.
108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * 2.  Redistributions in binary form must reproduce the above copyright
118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *     notice, this list of conditions and the following disclaimer in the
128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *     documentation and/or other materials provided with the distribution.
138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *     its contributors may be used to endorse or promote products derived
158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *     from this software without specific prior written permission.
168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *
178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project */
288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project/* originally written by Becky Willrich, additional code by Darin Adler */
308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "config.h"
328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "FormDataStreamCFNet.h"
338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
34cad810f21b803229eb11403f9209855525a25d57Steve Block#if USE(CFNETWORK)
35cad810f21b803229eb11403f9209855525a25d57Steve Block
368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "FileSystem.h"
378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "FormData.h"
388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include <CFNetwork/CFURLRequestPriv.h>
398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include <CoreFoundation/CFStreamAbstract.h>
408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include <WebKitSystemInterface/WebKitSystemInterface.h>
418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include <sys/types.h>
428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include <wtf/Assertions.h>
438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include <wtf/HashMap.h>
448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include <wtf/RetainPtr.h>
45dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block#include <wtf/text/CString.h>
468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#define USE_V1_CFSTREAM_CALLBACKS
488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#ifdef USE_V1_CFSTREAM_CALLBACKS
498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projecttypedef CFReadStreamCallBacksV1 WCReadStreamCallBacks;
508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#else
518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projecttypedef CFReadStreamCallBacks WCReadStreamCallBacks;
528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#endif
538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectnamespace WebCore {
558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid setHTTPBody(CFMutableURLRequestRef request, PassRefPtr<FormData> formData)
578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!formData) {
598f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        wkCFURLRequestSetHTTPRequestBodyParts(request, 0);
608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return;
618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    size_t count = formData->elements().size();
648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (count == 0)
668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return;
678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Handle the common special case of one piece of form data, with no files.
698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (count == 1) {
708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        const FormDataElement& element = formData->elements()[0];
718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (element.m_type == FormDataElement::data) {
728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            CFDataRef data = CFDataCreate(0, reinterpret_cast<const UInt8 *>(element.m_data.data()), element.m_data.size());
738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            CFURLRequestSetHTTPRequestBody(request, data);
748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            CFRelease(data);
758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            return;
768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        }
778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
798f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    RetainPtr<CFMutableArrayRef> array(AdoptCF, CFArrayCreateMutable(0, 0, &kCFTypeArrayCallBacks));
808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    for (size_t i = 0; i < count; ++i) {
828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        const FormDataElement& element = formData->elements()[i];
838f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        if (element.m_type == FormDataElement::data) {
848f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian            RetainPtr<CFDataRef> data(AdoptCF, CFDataCreate(0, reinterpret_cast<const UInt8*>(element.m_data.data()), element.m_data.size()));
858f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian            CFArrayAppendValue(array.get(), data.get());
868f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        } else {
878f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian            RetainPtr<CFStringRef> filename(AdoptCF, element.m_filename.createCFString());
888f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian            CFArrayAppendValue(array.get(), filename.get());
898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        }
908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
928f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    wkCFURLRequestSetHTTPRequestBodyParts(request, array.get());
938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectPassRefPtr<FormData> httpBodyFromRequest(CFURLRequestRef request)
968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (RetainPtr<CFDataRef> bodyData = CFURLRequestCopyHTTPRequestBody(request))
988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return FormData::create(CFDataGetBytePtr(bodyData.get()), CFDataGetLength(bodyData.get()));
998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1008f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    if (RetainPtr<CFArrayRef> bodyParts = wkCFURLRequestCopyHTTPRequestBodyParts(request)) {
1018f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        RefPtr<FormData> formData = FormData::create();
1028f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
1038f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        CFIndex count = CFArrayGetCount(bodyParts.get());
1048f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        for (CFIndex i = 0; i < count; i++) {
1058f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian            CFTypeRef bodyPart = CFArrayGetValueAtIndex(bodyParts.get(), i);
1068f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian            CFTypeID typeID = CFGetTypeID(bodyPart);
1078f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian            if (typeID == CFStringGetTypeID()) {
1088f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian                String filename = (CFStringRef)bodyPart;
1098f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian                formData->appendFile(filename);
1108f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian            } else if (typeID == CFDataGetTypeID()) {
1118f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian                CFDataRef data = (CFDataRef)bodyPart;
1128f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian                formData->appendData(CFDataGetBytePtr(data), CFDataGetLength(data));
1138f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian            } else
1148f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian                ASSERT_NOT_REACHED();
1158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        }
1168f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        return formData.release();
1178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
1188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // FIXME: what to do about arbitrary body streams?
1208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return 0;
1218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
1228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
123cad810f21b803229eb11403f9209855525a25d57Steve Block} // namespace WebCore
124cad810f21b803229eb11403f9209855525a25d57Steve Block
125cad810f21b803229eb11403f9209855525a25d57Steve Block#endif // USE(CFNETWORK)
126