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 
process_upload_data(void * cls,enum MHD_ValueKind kind,const char * key,const char * filename,const char * content_type,const char * transfer_encoding,const char * data,uint64_t off,size_t size)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 
canHandle(const char * method,const char * url)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 
handle(Request * request,MHD_Connection * connection,const char * url,const char * method,const char * upload_data,size_t * upload_data_size)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     // parse picture from stream
66     request->fPicture.reset(
67         SkPicture::CreateFromStream(request->fUploadContext->fStream.detachAsStream()));
68     if (!request->fPicture.get()) {
69         fprintf(stderr, "Could not create picture from stream.\n");
70         return MHD_NO;
71     }
72 
73     // pour picture into debug canvas
74     request->fDebugCanvas.reset(new SkDebugCanvas(Request::kImageWidth,
75                                                   Request::kImageHeight));
76     request->fDebugCanvas->drawPicture(request->fPicture);
77 
78     // clear upload context
79     delete request->fUploadContext;
80     request->fUploadContext = nullptr;
81 
82     return SendTemplate(connection, true, "/");
83 }
84 
85