kore

An easy to use, scalable and secure web application framework for writing web APIs in C.
Commits | Files | Refs | README | LICENSE | git clone https://git.kore.io/kore.git

upload.c (3253B)



      1 /*
      2  * Copyright (c) 2016-2018 Joris Vink <joris@coders.se>
      3  *
      4  * Permission to use, copy, modify, and distribute this software for any
      5  * purpose with or without fee is hereby granted, provided that the above
      6  * copyright notice and this permission notice appear in all copies.
      7  *
      8  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
      9  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
     10  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
     11  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
     12  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
     13  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
     14  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
     15  */
     16 
     17 /*
     18  * This example demonstrates how to properly deal with file uploads
     19  * coming from a multipart form.
     20  *
     21  * The basics are quite trivial:
     22  *	1) call http_populate_multipart_form()
     23  *	2) find the file using http_file_lookup().
     24  *	3) read the file data using http_file_read().
     25  *
     26  * In this example the contents is written to a newly created file
     27  * on the server that matches the naming given by the uploader.
     28  *
     29  * Note that the above is probably not what you want to do in real life.
     30  */
     31 
     32 #include <kore/kore.h>
     33 #include <kore/http.h>
     34 
     35 #include <fcntl.h>
     36 #include <unistd.h>
     37 
     38 int		page(struct http_request *);
     39 
     40 int
     41 page(struct http_request *req)
     42 {
     43 	int			fd;
     44 	struct http_file	*file;
     45 	u_int8_t		buf[BUFSIZ];
     46 	ssize_t			ret, written;
     47 
     48 	/* Only deal with POSTs. */
     49 	if (req->method != HTTP_METHOD_POST) {
     50 		http_response(req, 405, NULL, 0);
     51 		return (KORE_RESULT_OK);
     52 	}
     53 
     54 	/* Parse the multipart data that was present. */
     55 	http_populate_multipart_form(req);
     56 
     57 	/* Find our file. */
     58 	if ((file = http_file_lookup(req, "file")) == NULL) {
     59 		http_response(req, 400, NULL, 0);
     60 		return (KORE_RESULT_OK);
     61 	}
     62 
     63 	/* Open dump file where we will write file contents. */
     64 	fd = open(file->filename, O_CREAT | O_TRUNC | O_WRONLY, 0700);
     65 	if (fd == -1) {
     66 		http_response(req, 500, NULL, 0);
     67 		return (KORE_RESULT_OK);
     68 	}
     69 
     70 	/* While we have data from http_file_read(), write it. */
     71 	/* Alternatively you could look at file->offset and file->length. */
     72 	ret = KORE_RESULT_ERROR;
     73 	for (;;) {
     74 		ret = http_file_read(file, buf, sizeof(buf));
     75 		if (ret == -1) {
     76 			kore_log(LOG_ERR, "failed to read from file");
     77 			http_response(req, 500, NULL, 0);
     78 			goto cleanup;
     79 		}
     80 
     81 		if (ret == 0)
     82 			break;
     83 
     84 		written = write(fd, buf, ret);
     85 		if (written == -1) {
     86 			kore_log(LOG_ERR,"write(%s): %s",
     87 			    file->filename, errno_s);
     88 			http_response(req, 500, NULL, 0);
     89 			goto cleanup;
     90 		}
     91 
     92 		if (written != ret) {
     93 			kore_log(LOG_ERR, "partial write on %s",
     94 			    file->filename);
     95 			http_response(req, 500, NULL, 0);
     96 			goto cleanup;
     97 		}
     98 	}
     99 
    100 	ret = KORE_RESULT_OK;
    101 	http_response(req, 200, NULL, 0);
    102 	kore_log(LOG_INFO, "file '%s' successfully received",
    103 	    file->filename);
    104 
    105 cleanup:
    106 	if (close(fd) == -1)
    107 		kore_log(LOG_WARNING, "close(%s): %s", file->filename, errno_s);
    108 
    109 	if (ret == KORE_RESULT_ERROR) {
    110 		if (unlink(file->filename) == -1) {
    111 			kore_log(LOG_WARNING, "unlink(%s): %s",
    112 			    file->filename, errno_s);
    113 		}
    114 		ret = KORE_RESULT_OK;
    115 	}
    116 
    117 	return (KORE_RESULT_OK);
    118 }