1 /* 2 * Copyright 2016 Google Inc. 3 * 4 * Use of this source code is governed by a BSD-style license that can be 5 * found in the LICENSE file. 6 */ 7 8 #include "UrlHandler.h" 9 10 #include "microhttpd.h" 11 #include "../Request.h" 12 #include "../Response.h" 13 14 using namespace Response; 15 16 static const size_t kBufferSize = 1024; 17 18 static int process_upload_data(void* cls, enum MHD_ValueKind kind, 19 const char* key, const char* filename, 20 const char* content_type, const char* transfer_encoding, 21 const char* data, uint64_t off, size_t size) { 22 struct UploadContext* uc = reinterpret_cast<UploadContext*>(cls); 23 24 if (0 != size) { 25 uc->fStream.write(data, size); 26 } 27 return MHD_YES; 28 } 29 30 bool PostHandler::canHandle(const char* method, const char* url) { 31 return 0 == strcmp(method, MHD_HTTP_METHOD_POST) && 32 0 == strcmp(url, "/new"); 33 } 34 35 int PostHandler::handle(Request* request, MHD_Connection* connection, 36 const char* url, const char* method, 37 const char* upload_data, size_t* upload_data_size) { 38 UploadContext* uc = request->fUploadContext; 39 40 // New connection 41 if (!uc) { 42 // TODO make this a method on request 43 uc = new UploadContext; 44 uc->connection = connection; 45 uc->fPostProcessor = MHD_create_post_processor(connection, kBufferSize, 46 &process_upload_data, uc); 47 SkASSERT(uc->fPostProcessor); 48 49 request->fUploadContext = uc; 50 return MHD_YES; 51 } 52 53 // in process upload 54 if (0 != *upload_data_size) { 55 SkASSERT(uc->fPostProcessor); 56 MHD_post_process(uc->fPostProcessor, upload_data, *upload_data_size); 57 *upload_data_size = 0; 58 return MHD_YES; 59 } 60 61 // end of upload 62 MHD_destroy_post_processor(uc->fPostProcessor); 63 uc->fPostProcessor = nullptr; 64 65 std::unique_ptr<SkStreamAsset> stream(request->fUploadContext->fStream.detachAsStream()); 66 if (!request->initPictureFromStream(stream.get())) { 67 fprintf(stderr, "Could not create picture from stream.\n"); 68 return MHD_NO; 69 } 70 71 // clear upload context 72 delete request->fUploadContext; 73 request->fUploadContext = nullptr; 74 75 return SendTemplate(connection, true, "/"); 76 } 77