Changeset 29423 in webkit
- Timestamp:
- Jan 11, 2008 5:36:02 PM (16 years ago)
- Location:
- trunk/WebCore
- Files:
-
- 5 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/WebCore/ChangeLog
r29422 r29423 1 2008-01-11 Luca Bruno <lethalman88@gmail.com> 2 3 Reviewed by Alp Toker. 4 5 http://bugs.webkit.org/show_bug.cgi?id=16729 6 [cURL] Allow multiple files for upload 7 8 * platform/network/ResourceHandleInternal.h: 9 (WebCore::ResourceHandleInternal::ResourceHandleInternal): 10 * platform/network/curl/ResourceHandleCurl.cpp: 11 (WebCore::ResourceHandleInternal::~ResourceHandleInternal): 12 * platform/network/curl/ResourceHandleManager.cpp: 13 (WebCore::readCallback): added 14 (WebCore::ResourceHandleManager::setupPOST): setup for streaming the POST 15 (WebCore::ResourceHandleManager::startJob): 16 (WebCore::ResourceHandleManager::cancel): revert the previous patch for regression 17 * platform/network/curl/ResourceHandleManager.h: 18 1 19 2008-01-11 Christian Dywan <christian@imendio.com> 2 20 -
trunk/WebCore/platform/network/ResourceHandleInternal.h
r29222 r29423 97 97 , m_handle(0) 98 98 , m_url(0) 99 , m_fileName(0)100 99 , m_customHeaders(0) 101 100 , m_cancelled(false) 101 , m_file(0) 102 , m_formDataElementIndex(0) 103 , m_formDataElementDataOffset(0) 102 104 #endif 103 105 #if PLATFORM(QT) … … 150 152 CURL* m_handle; 151 153 char* m_url; 152 char* m_fileName;153 154 struct curl_slist* m_customHeaders; 154 Vector<char> m_postBytes;155 155 ResourceResponse m_response; 156 156 bool m_cancelled; 157 158 FILE* m_file; 159 size_t m_formDataElementIndex; 160 size_t m_formDataElementDataOffset; 161 Vector<char> m_postBytes; 157 162 #endif 158 163 #if PLATFORM(QT) -
trunk/WebCore/platform/network/curl/ResourceHandleCurl.cpp
r29352 r29423 39 39 { 40 40 free(m_url); 41 free(m_fileName);42 41 if (m_customHeaders) 43 42 curl_slist_free_all(m_customHeaders); 43 if (m_file) 44 fclose(m_file); 44 45 } 45 46 -
trunk/WebCore/platform/network/curl/ResourceHandleManager.cpp
r29366 r29423 32 32 33 33 #include "CString.h" 34 #include "FileSystem.h" 34 35 #include "MIMETypeRegistry.h" 35 36 #include "NotImplemented.h" … … 192 193 } 193 194 195 /* This is called to obtain HTTP POST or PUT data. 196 Iterate through FormData elements and upload files. 197 Carefully respect the given buffer size and fill the rest of the data at the next calls. 198 */ 199 size_t readCallback(void* ptr, size_t size, size_t nmemb, void* data) 200 { 201 ResourceHandle* job = static_cast<ResourceHandle*>(data); 202 ResourceHandleInternal* d = job->getInternal(); 203 if (d->m_cancelled) 204 return 0; 205 206 size_t sent = 0; 207 size_t toSend = size * nmemb; 208 if (!toSend) 209 return 0; 210 211 Vector<FormDataElement> elements = job->request().httpBody()->elements(); 212 if (d->m_formDataElementIndex >= elements.size()) 213 return 0; 214 215 FormDataElement element = elements[d->m_formDataElementIndex]; 216 217 if (element.m_type == FormDataElement::encodedFile) { 218 if (!d->m_file) 219 d->m_file = fopen(element.m_filename.utf8().data(), "rb"); 220 221 if (!d->m_file) { 222 // FIXME: show a user error? 223 #ifndef NDEBUG 224 printf("Failed while trying to open %s for upload\n", element.m_filename.utf8().data()); 225 #endif 226 job->cancel(); 227 return 0; 228 } 229 230 sent = fread(ptr, size, nmemb, d->m_file); 231 if (!size && ferror(d->m_file)) { 232 // FIXME: show a user error? 233 #ifndef NDEBUG 234 printf("Failed while trying to read %s for upload\n", element.m_filename.utf8().data()); 235 #endif 236 job->cancel(); 237 return 0; 238 } 239 if (feof(d->m_file)) { 240 fclose(d->m_file); 241 d->m_file = 0; 242 d->m_formDataElementIndex++; 243 } 244 } else { 245 size_t elementSize = element.m_data.size() - d->m_formDataElementDataOffset; 246 sent = elementSize > toSend ? toSend : elementSize; 247 memcpy(ptr, element.m_data.data() + d->m_formDataElementDataOffset, sent); 248 if (elementSize > sent) 249 d->m_formDataElementDataOffset += sent; 250 else { 251 d->m_formDataElementDataOffset = 0; 252 d->m_formDataElementIndex++; 253 } 254 } 255 256 return sent; 257 } 258 194 259 void ResourceHandleManager::downloadTimerCallback(Timer<ResourceHandleManager>* timer) 195 260 { … … 289 354 } 290 355 291 void ResourceHandleManager::setupPUT(ResourceHandle* )356 void ResourceHandleManager::setupPUT(ResourceHandle*, struct curl_slist**) 292 357 { 293 358 notImplemented(); 294 359 } 295 360 296 void ResourceHandleManager::setupPOST(ResourceHandle* job) 361 /* Calculate the length of the POST. 362 Force chunked data transfer if size of files can't be obtained. 363 */ 364 void ResourceHandleManager::setupPOST(ResourceHandle* job, struct curl_slist** headers) 297 365 { 298 366 ResourceHandleInternal* d = job->getInternal(); 299 300 job->request().httpBody()->flatten(d->m_postBytes);301 if (d->m_postBytes.size() != 0) {302 curl_easy_setopt(d->m_handle, CURLOPT_POST, TRUE);303 curl_easy_setopt(d->m_handle, CURLOPT_POSTFIELDSIZE, d->m_postBytes.size());304 curl_easy_setopt(d->m_handle, CURLOPT_POSTFIELDS, d->m_postBytes.data());305 }306 307 367 Vector<FormDataElement> elements = job->request().httpBody()->elements(); 308 size_t size = elements.size(); 309 struct curl_httppost* lastItem = 0; 310 struct curl_httppost* post = 0; 311 for (size_t i = 0; i < size; i++) { 312 if (elements[i].m_type != FormDataElement::encodedFile) 313 continue; 314 CString cstring = elements[i].m_filename.utf8(); 315 ASSERT(!d->m_fileName); 316 d->m_fileName = strdup(cstring.data()); 317 318 // Fill in the file upload field 319 curl_formadd(&post, &lastItem, CURLFORM_COPYNAME, "sendfile", CURLFORM_FILE, d->m_fileName, CURLFORM_END); 320 321 // Fill in the filename field 322 curl_formadd(&post, &lastItem, CURLFORM_COPYNAME, "filename", CURLFORM_COPYCONTENTS, d->m_fileName, CURLFORM_END); 323 324 // FIXME: We should not add a "submit" field for each file uploaded. Review this code. 325 // Fill in the submit field too, even if this is rarely needed 326 curl_formadd(&post, &lastItem, CURLFORM_COPYNAME, "submit", CURLFORM_COPYCONTENTS, "send", CURLFORM_END); 327 328 // FIXME: should we support more than one file? 329 break; 330 } 331 332 if (post) 333 curl_easy_setopt(d->m_handle, CURLOPT_HTTPPOST, post); 368 size_t numElements = elements.size(); 369 370 if (!numElements) 371 return; 372 373 // Do not stream for simple POST data 374 if (numElements == 1) { 375 job->request().httpBody()->flatten(d->m_postBytes); 376 if (d->m_postBytes.size() != 0) { 377 curl_easy_setopt(d->m_handle, CURLOPT_POST, TRUE); 378 curl_easy_setopt(d->m_handle, CURLOPT_POSTFIELDSIZE, d->m_postBytes.size()); 379 curl_easy_setopt(d->m_handle, CURLOPT_POSTFIELDS, d->m_postBytes.data()); 380 } 381 return; 382 } 383 384 // Obtain the total size of the POST 385 static const long long maxCurlOffT = (1LL << (sizeof(curl_off_t) * 8 - 1)) - 1; 386 curl_off_t size = 0; 387 bool chunkedTransfer = false; 388 for (size_t i = 0; i < numElements; i++) { 389 FormDataElement element = elements[i]; 390 if (element.m_type == FormDataElement::encodedFile) { 391 long long fileSizeResult; 392 if (fileSize(element.m_filename, fileSizeResult)) { 393 if (fileSizeResult > maxCurlOffT) { 394 // File size is too big for specifying it to cURL 395 chunkedTransfer = true; 396 break; 397 } 398 size += fileSizeResult; 399 } else { 400 chunkedTransfer = true; 401 break; 402 } 403 } else 404 size += elements[i].m_data.size(); 405 } 406 407 curl_easy_setopt(d->m_handle, CURLOPT_POST, TRUE); 408 409 // cURL guesses that we want chunked encoding as long as we specify the header 410 if (chunkedTransfer) 411 *headers = curl_slist_append(*headers, "Transfer-Encoding: chunked"); 412 else 413 curl_easy_setopt(d->m_handle, CURLOPT_POSTFIELDSIZE_LARGE, size); 414 415 curl_easy_setopt(d->m_handle, CURLOPT_READFUNCTION, readCallback); 416 curl_easy_setopt(d->m_handle, CURLOPT_READDATA, job); 334 417 } 335 418 … … 346 429 { 347 430 int size = m_resourceHandleList.size(); 348 for (int i =0; i < size; i++) {431 for (int i = 0; i < size; i++) { 349 432 if (job == m_resourceHandleList[i]) { 350 433 m_resourceHandleList.remove(i); … … 472 555 } 473 556 557 struct curl_slist* headers = 0; 474 558 if (job->request().httpHeaderFields().size() > 0) { 475 struct curl_slist* headers = 0;476 559 HTTPHeaderMap customHeaders = job->request().httpHeaderFields(); 477 560 HTTPHeaderMap::const_iterator end = customHeaders.end(); … … 485 568 headers = curl_slist_append(headers, headerLatin1.data()); 486 569 } 487 curl_easy_setopt(d->m_handle, CURLOPT_HTTPHEADER, headers);488 d->m_customHeaders = headers;489 570 } 490 571 … … 492 573 curl_easy_setopt(d->m_handle, CURLOPT_HTTPGET, TRUE); 493 574 else if ("POST" == job->request().httpMethod()) 494 setupPOST(job );575 setupPOST(job, &headers); 495 576 else if ("PUT" == job->request().httpMethod()) 496 setupPUT(job );577 setupPUT(job, &headers); 497 578 else if ("HEAD" == job->request().httpMethod()) 498 579 curl_easy_setopt(d->m_handle, CURLOPT_NOBODY, TRUE); 580 581 if (headers) { 582 curl_easy_setopt(d->m_handle, CURLOPT_HTTPHEADER, headers); 583 d->m_customHeaders = headers; 584 } 499 585 500 586 m_runningJobs++; -
trunk/WebCore/platform/network/curl/ResourceHandleManager.h
r28573 r29423 45 45 void setCookieJarFileName(const char* cookieJarFileName); 46 46 47 void setupPOST(ResourceHandle* );48 void setupPUT(ResourceHandle* );47 void setupPOST(ResourceHandle*, struct curl_slist**); 48 void setupPUT(ResourceHandle*, struct curl_slist**); 49 49 50 50 private:
Note: See TracChangeset
for help on using the changeset viewer.