Home | History | Annotate | Download | only in cf
      1 /*
      2  * Copyright (C) 2005, 2006, 2007 Apple Inc.  All rights reserved.
      3  *
      4  * Redistribution and use in source and binary forms, with or without
      5  * modification, are permitted provided that the following conditions
      6  * are met:
      7  *
      8  * 1.  Redistributions of source code must retain the above copyright
      9  *     notice, this list of conditions and the following disclaimer.
     10  * 2.  Redistributions in binary form must reproduce the above copyright
     11  *     notice, this list of conditions and the following disclaimer in the
     12  *     documentation and/or other materials provided with the distribution.
     13  * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
     14  *     its contributors may be used to endorse or promote products derived
     15  *     from this software without specific prior written permission.
     16  *
     17  * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
     18  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
     19  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
     20  * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
     21  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
     22  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
     23  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
     24  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     26  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     27  */
     28 
     29 /* originally written by Becky Willrich, additional code by Darin Adler */
     30 
     31 #include "config.h"
     32 #include "FormDataStreamCFNet.h"
     33 
     34 #if USE(CFNETWORK)
     35 
     36 #include "FileSystem.h"
     37 #include "FormData.h"
     38 #include <CFNetwork/CFURLRequestPriv.h>
     39 #include <CoreFoundation/CFStreamAbstract.h>
     40 #include <WebKitSystemInterface/WebKitSystemInterface.h>
     41 #include <sys/types.h>
     42 #include <wtf/Assertions.h>
     43 #include <wtf/HashMap.h>
     44 #include <wtf/RetainPtr.h>
     45 #include <wtf/text/CString.h>
     46 
     47 #define USE_V1_CFSTREAM_CALLBACKS
     48 #ifdef USE_V1_CFSTREAM_CALLBACKS
     49 typedef CFReadStreamCallBacksV1 WCReadStreamCallBacks;
     50 #else
     51 typedef CFReadStreamCallBacks WCReadStreamCallBacks;
     52 #endif
     53 
     54 namespace WebCore {
     55 
     56 void setHTTPBody(CFMutableURLRequestRef request, PassRefPtr<FormData> formData)
     57 {
     58     if (!formData) {
     59         wkCFURLRequestSetHTTPRequestBodyParts(request, 0);
     60         return;
     61     }
     62 
     63     size_t count = formData->elements().size();
     64 
     65     if (count == 0)
     66         return;
     67 
     68     // Handle the common special case of one piece of form data, with no files.
     69     if (count == 1) {
     70         const FormDataElement& element = formData->elements()[0];
     71         if (element.m_type == FormDataElement::data) {
     72             CFDataRef data = CFDataCreate(0, reinterpret_cast<const UInt8 *>(element.m_data.data()), element.m_data.size());
     73             CFURLRequestSetHTTPRequestBody(request, data);
     74             CFRelease(data);
     75             return;
     76         }
     77     }
     78 
     79     RetainPtr<CFMutableArrayRef> array(AdoptCF, CFArrayCreateMutable(0, 0, &kCFTypeArrayCallBacks));
     80 
     81     for (size_t i = 0; i < count; ++i) {
     82         const FormDataElement& element = formData->elements()[i];
     83         if (element.m_type == FormDataElement::data) {
     84             RetainPtr<CFDataRef> data(AdoptCF, CFDataCreate(0, reinterpret_cast<const UInt8*>(element.m_data.data()), element.m_data.size()));
     85             CFArrayAppendValue(array.get(), data.get());
     86         } else {
     87             RetainPtr<CFStringRef> filename(AdoptCF, element.m_filename.createCFString());
     88             CFArrayAppendValue(array.get(), filename.get());
     89         }
     90     }
     91 
     92     wkCFURLRequestSetHTTPRequestBodyParts(request, array.get());
     93 }
     94 
     95 PassRefPtr<FormData> httpBodyFromRequest(CFURLRequestRef request)
     96 {
     97     if (RetainPtr<CFDataRef> bodyData = CFURLRequestCopyHTTPRequestBody(request))
     98         return FormData::create(CFDataGetBytePtr(bodyData.get()), CFDataGetLength(bodyData.get()));
     99 
    100     if (RetainPtr<CFArrayRef> bodyParts = wkCFURLRequestCopyHTTPRequestBodyParts(request)) {
    101         RefPtr<FormData> formData = FormData::create();
    102 
    103         CFIndex count = CFArrayGetCount(bodyParts.get());
    104         for (CFIndex i = 0; i < count; i++) {
    105             CFTypeRef bodyPart = CFArrayGetValueAtIndex(bodyParts.get(), i);
    106             CFTypeID typeID = CFGetTypeID(bodyPart);
    107             if (typeID == CFStringGetTypeID()) {
    108                 String filename = (CFStringRef)bodyPart;
    109                 formData->appendFile(filename);
    110             } else if (typeID == CFDataGetTypeID()) {
    111                 CFDataRef data = (CFDataRef)bodyPart;
    112                 formData->appendData(CFDataGetBytePtr(data), CFDataGetLength(data));
    113             } else
    114                 ASSERT_NOT_REACHED();
    115         }
    116         return formData.release();
    117     }
    118 
    119     // FIXME: what to do about arbitrary body streams?
    120     return 0;
    121 }
    122 
    123 } // namespace WebCore
    124 
    125 #endif // USE(CFNETWORK)
    126