Codebase list ulfius / 11520ac
Import Upstream version 2.2 Thorsten Alteholz 6 years ago
14 changed file(s) with 313 addition(s) and 63 deletion(s). Raw diff Collapse all Expand all
00 *.o
1 example_programs/*/*.o
2 example_programs/*/valgrind*.txt
3 src/*.o
4 src/*.so
5 src/*.so.*
1 *.so
2 *.so.*
3 *.a
64 example_programs/auth_example/auth_client
75 example_programs/auth_example/auth_server
86 example_programs/injection_example/injection_example
1715 example_programs/multiple_callbacks_example/multiple_callbacks_example
1816 example_programs/sheep_counter/sheep_counter
1917 example_programs/websocket_example/websocket_example
18 example_programs/*/valgrind*.txt
2019 test/valgrind*.txt
2120 test/*.o
2221 test/core
732732
733733 If you want to limit the size of a post parameter, if you want to limit the file size for example, set the value `struct _u_instance.max_post_param_size`. Files or post data exceeding this size will be truncated to the size `struct _u_instance.max_post_param_size`. If this parameter is 0, then no limit is set. Default value is 0.
734734
735 If you want to handle file upload yourself, you can intercept the file upload process with your own callback function. Before running the webservice with `ulfius_start_framework`, you must call the function `ulfius_set_upload_file_callback_function` with a pointer to your file upload callback function. By using this method, the specified callback function will be executed as much as needed with a chunk of the file upload each time.
736
737 This function `ulfius_set_upload_file_callback_function` has the following prototype:
738
739 ```C
740 /**
741 * ulfius_set_upload_file_callback_function
742 *
743 * Set the callback function to handle file upload
744 * Used to facilitate large files upload management
745 * The callback function file_upload_callback will be called
746 * multiple times, with the uploaded file in striped in parts
747 *
748 * Warning: If this function is used, all the uploaded files
749 * for the instance will be managed via this function, and they
750 * will no longer be available in the struct _u_request in the
751 * ulfius callback function afterwards.
752 *
753 * Thanks to Thad Phetteplace for the help on this feature
754 *
755 * u_instance: pointer to a struct _u_instance that describe its port and bind address
756 * file_upload_callback: Pointer to a callback function that will handle all file uploads
757 * cls: a pointer that will be passed to file_upload_callback each tim it's called
758 */
759 int ulfius_set_upload_file_callback_function(struct _u_instance * u_instance,
760 int (* file_upload_callback) (const struct _u_request * request,
761 const char * key,
762 const char * filename,
763 const char * content_type,
764 const char * transfer_encoding,
765 const char * data,
766 uint64_t off,
767 size_t size,
768 void * cls),
769 void * cls);
770 ```
771
772 This callback function will be called before all the other callback functions, and be aware that not all parameters, especially url parameters, will be present during the file upload callback function executions.
773
735774 See `examples/sheep_counter` for a file upload example.
736775
737776 ### Streaming data
10131052 * return -1 if no match found
10141053 * search is case sensitive
10151054 */
1016 size_t u_map_get_length(const struct _u_map * u_map, const const char * key);
1055 size_t u_map_get_length(const struct _u_map * u_map, const char * key);
10171056
10181057 /**
10191058 * get the value length corresponding to the specified key in the u_map
10201059 * return -1 if no match found
10211060 * search is case insensitive
10221061 */
1023 size_t u_map_get_case_length(const struct _u_map * u_map, const const char * key);
1062 size_t u_map_get_case_length(const struct _u_map * u_map, const char * key);
10241063
10251064 /**
10261065 * get the value corresponding to the specified key in the u_map
10271066 * return NULL if no match found
10281067 * search is case sensitive
10291068 */
1030 const char * u_map_get(const struct _u_map * u_map, const const char * key);
1069 const char * u_map_get(const struct _u_map * u_map, const char * key);
10311070
10321071 /**
10331072 * get the value corresponding to the specified key in the u_map
00 # Install Ulfius
11
2 ## Prerequisites
2 ## Debian-ish packages
33
4 ### External dependencies
4 [![Packaging status](https://repology.org/badge/vertical-allrepos/ulfius.svg)](https://repology.org/metapackage/ulfius)
5
6 Ulfius is now available in Debian Buster (testing) and some Debian based distributions. To install it on your device, use the following command as root:
7
8 ```shell
9 # apt install libulfius-dev # Or apt install libulfius.1 if you don't need the development files
10 ```
11
12 ## Manual install
13
14 ### Prerequisites
15
16 #### External dependencies
517
618 To install all the external dependencies, for Debian based distributions (Debian, Ubuntu, Raspbian, etc.), run as root:
719
921 # apt-get install libmicrohttpd-dev libjansson-dev libcurl4-gnutls-dev libgnutls28-dev libgcrypt20-dev
1022 ```
1123
12 ### Note
24 #### Note
1325
1426 Here libcurl4-gnutls-dev for the example, but any `libcurl*-dev` library should be sufficent, depending on your needs and configuration. Note that gnutls is mandatory for websocket management and https support.
1527
1931
2032 If you want to use the websocket server functions, you need to install libmicrohttpd 0.9.53 minimum version.
2133
22 ## Installation
34 ### Installation
35
36 #### Install Ulfius as a shared library
2337
2438 Download Ulfius source code from Github, get the submodules, compile and install each submodule, then compile and install ulfius:
2539
3650 $ sudo make install
3751 ```
3852
53 #### Update Ulfius
54
3955 If you update Ulfius from a previous version, you must install the corresponding version of the submodules as well:
4056
4157 ```shell
5066 $ make
5167 $ sudo make install
5268 ```
69
70 #### Disable dependencies
5371
5472 To disable libcurl functions, append the option `CURLFLAG=-DU_DISABLE_CURL` to the make command when you build Ulfius:
5573
8199 $ make CURLFLAG=-DU_DISABLE_CURL JANSSONFLAG=-DU_DISABLE_JANSSON
82100 ```
83101
102 #### Installation directory
103
84104 By default, the shared libraries and the header files will be installed in the `/usr/local` location. To change this setting, you can modify the `PREFIX` value in the `src/Makefile`, `lib/orcania/src/Makefile` and `lib/yder/src/Makefile` files.
105
106 ```shell
107 $ make PREFIX=/tmp install # to install ulfius in /tmp/lib for example
108 ```
109
110 You can install Ulfius without root permission if your user has write access to `$(PREFIX)`.
111 A `ldconfig` command is executed at the end of the install, it will probably fail if you don't have root permission, but this is harmless.
112 If you choose to install Ulfius in another directory, you must set your environment variable `LD_LIBRARY_PATH` properly.
113
114 #### Install from a `.zip` archive
85115
86116 If you download Ulfius as a `.zip` or `.tar.gz` file via github release tab, you must initiaize the submodules prior to the compilaton with the following command:
87117
89119 $ cd ulfius/
90120 $ git submodule update --init
91121 ```
122
123 #### Install as a static archive
124
125 To install Ulfius library as a static archive, `libulfius.a`, use the make commands `make static*`:
126
127 The archives `liborcania.a` and `libyder.a` must previously be installed in the $(PREFIX) directory.
128
129 ```shell
130 $ cd ulfius/src
131 $ make static && sudo make static-install # or make PREFIX=/tmp static-install if you want to install in `/tmp/lib`
132 ```
133
134 The example program `example_program/simple_example` has a static make command to test and validate building a program with the archive.
135
00 # Ulfius
11
2 Web Framework for REST Applications in C.
2 HTTP Framework for REST Applications in C.
33
44 Based on [GNU Libmicrohttpd](https://www.gnu.org/software/libmicrohttpd/) for the backend web server, [Jansson](http://www.digip.org/jansson/) for the json manipulation library, and [Libcurl](http://curl.haxx.se/libcurl/) for the http/smtp client API.
55
8989 - [Hutch](https://github.com/babelouest/hutch), a safe locker for passwords and other secrets, using encryption on the client side only
9090 - [Taulas Raspberry Pi Serial interface](https://github.com/babelouest/taulas/tree/master/taulas_raspberrypi_serial), an interface for Arduino devices that implent [Taulas](https://github.com/babelouest/taulas/) protocol, a house automation protocol
9191
92 ## What's new in Ulfius 2.1 ?
92 ## What's new in Ulfius 2.2?
93
94 Allow to use your own callback function when uploading files with `ulfius_set_upload_file_callback_function`, so a large file can be uploaded, even with the option `struct _u_instance.max_post_param_size` set.
95
96 ## What's new in Ulfius 2.1?
9397
9498 I know it wasn't long since Ulfius 2.0 was released. But after some review and tests, I realized some adjustments had to be made to avoid bugs and to clean the framework a little bit more.
9599
102106
103107 The minor version number has been incremented, from 2.0 to 2.1 because some of the changes may require changes in your own code.
104108
105 ## What's new in Ulfius 2.0 ?
109 ## What's new in Ulfius 2.0?
106110
107111 Ulfius 2.0 brings several changes that make the library incompatible with Ulfius 1.0.x branch. The goal of making Ulfius 2.0 is to make a spring cleaning of some functions, remove what is apparently useless, and should bring bugs and memory loss. The main new features are multiple callback functions and websockets implementation.
108112
3939 // Callback function used to upload file
4040 int callback_upload_file (const struct _u_request * request, struct _u_response * response, void * user_data);
4141
42 // File upload callback function
43 int file_upload_callback (const struct _u_request * request,
44 const char * key,
45 const char * filename,
46 const char * content_type,
47 const char * transfer_encoding,
48 const char * data,
49 uint64_t off,
50 size_t size,
51 void * user_data);
4252 /**
4353 * decode a u_map into a string
4454 */
5060 keys = u_map_enum_keys(map);
5161 for (i=0; keys[i] != NULL; i++) {
5262 value = u_map_get(map, keys[i]);
53 len = snprintf(NULL, 0, "key is %s, length is %ld, value is %.*s", keys[i], u_map_get_length(map, keys[i]), (int)u_map_get_length(map, keys[i]), value);
63 len = snprintf(NULL, 0, "key is %s, length is %zu, value is %.*s", keys[i], u_map_get_length(map, keys[i]), (int)u_map_get_length(map, keys[i]), value);
5464 line = o_malloc((len+1)*sizeof(char));
55 snprintf(line, (len+1), "key is %s, length is %ld, value is %.*s", keys[i], u_map_get_length(map, keys[i]), (int)u_map_get_length(map, keys[i]), value);
65 snprintf(line, (len+1), "key is %s, length is %zu, value is %.*s", keys[i], u_map_get_length(map, keys[i]), (int)u_map_get_length(map, keys[i]), value);
5666 if (to_return != NULL) {
5767 len = strlen(to_return) + strlen(line) + 1;
5868 to_return = o_realloc(to_return, (len+1)*sizeof(char));
96106 // Initialize the instance
97107 struct _u_instance instance;
98108
109 y_init_logs("sheep_counter", Y_LOG_MODE_CONSOLE, Y_LOG_LEVEL_DEBUG, NULL, "Starting sheep_counter");
110
99111 if (ulfius_init_instance(&instance, PORT, NULL, NULL) != U_OK) {
100112 y_log_message(Y_LOG_LEVEL_ERROR, "Error ulfius_init_instance, abort");
101113 return(1);
103115
104116 // Max post param size is 16 Kb, which means an uploaded file is no more than 16 Kb
105117 instance.max_post_param_size = 16*1024;
118
119 if (ulfius_set_upload_file_callback_function(&instance, &file_upload_callback, "my cls") != U_OK) {
120 y_log_message(Y_LOG_LEVEL_ERROR, "Error ulfius_set_upload_file_callback_function");
121 }
106122
107123 // MIME types that will define the static files
108124 struct _u_map mime_types;
140156 printf("End framework\n");
141157 ulfius_stop_framework(&instance);
142158 ulfius_clean_instance(&instance);
159
160 y_close_logs();
143161
144162 return 0;
145163 }
270288 o_free(string_body);
271289 return U_CALLBACK_CONTINUE;
272290 }
291
292 /**
293 * File upload callback function
294 */
295 int file_upload_callback (const struct _u_request * request,
296 const char * key,
297 const char * filename,
298 const char * content_type,
299 const char * transfer_encoding,
300 const char * data,
301 uint64_t off,
302 size_t size,
303 void * cls) {
304 y_log_message(Y_LOG_LEVEL_DEBUG, "Got from file '%s' of the key '%s', offset %llu, size %zu, cls is '%s'", filename, key, off, size, cls);
305 return U_OK;
306 }
11 <html>
22 <body>
33
4 <form action="/upload" method="post" enctype="multipart/form-data">
4 <form action="upload" method="post" enctype="multipart/form-data">
5 <input type="text" name="textParam" value="textValue">
56 Select files to upload:<br>
6 <input type="file" name="fileToUpload1" id="fileToUpload"><br>
7 <input type="file" name="fileToUpload1" id="fileToUpload" value=""><br>
78 <input type="submit" value="Upload File" name="submit">
89 </form>
910
1011 </body>
1112 </html>
12
1111 # but WITHOUT ANY WARRANTY; without even the implied warranty of
1212 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
1313 #
14
14 PREFIX=/usr/local
1515 LIBYDER_LOCATION=../../lib/yder/src
1616 CC=gcc
1717 CFLAGS=-c -Wall -I$(LIBYDER_LOCATION) -D_REENTRANT $(ADDITIONALFLAGS)
3838
3939 test: simple_example
4040 LD_LIBRARY_PATH=$(ULFIUS_LOCATION):${LD_LIBRARY_PATH} ./simple_example
41
42 static: simple_example.o
43 $(CC) -o simple_example simple_example.o $(PREFIX)/lib/liborcania.a $(PREFIX)/lib/libyder.a $(PREFIX)/lib/libulfius.a -ljansson -lmicrohttpd -lpthread -lgnutls
55
66 ```bash
77 $ make test
8 ```
9
10 ## Compile with Ulfius built as a static archive
11
12 Ulfius must be built as a static archive and installed in the $(PREFIX) directory.
13
14 ```bash
15 $ make static
816 ```
917
1018 ### https connection
2525 CFLAGS=-c -pedantic -std=gnu99 -fPIC -Wall -D_REENTRANT -I$(PREFIX)/include -I$(LIBORCANIA_LOCATION) -I$(LIBYDER_LOCATION) $(ADDITIONALFLAGS) $(JANSSONFLAG) $(CURLFLAG) $(WEBSOCKETFLAG)
2626 LIBS=-L$(PREFIX)/lib -L$(LIBORCANIA_LOCATION) -L$(LIBYDER_LOCATION) -lc -lmicrohttpd -lyder -lorcania -lpthread
2727 OUTPUT=libulfius.so
28 VERSION=2.1
28 VERSION=2.2
2929
30 ifneq (($(JANSSONFLAG)),"")
30 ifndef JANSSONFLAG
3131 LJANSSON=-ljansson
3232 endif
3333
34 ifneq (($(CURLFLAG)),"")
34 ifndef CURLFLAG
3535 LCURL=-lcurl
3636 endif
3737
38 ifneq (($(WEBSOCKETFLAG)),"")
38 ifndef WEBSOCKETFLAG
3939 LWEBSOCKET=-lgnutls
4040 endif
4141
4444 libulfius.so: ulfius.o u_map.o u_request.o u_response.o u_send_request.o u_websocket.o
4545 $(CC) -shared -Wl,-soname,$(OUTPUT) -o $(OUTPUT).$(VERSION) ulfius.o u_map.o u_request.o u_response.o u_send_request.o u_websocket.o $(LIBS) $(LJANSSON) $(LCURL) $(LWEBSOCKET)
4646 ln -sf $(OUTPUT).$(VERSION) $(OUTPUT)
47
48 libulfius.a: ulfius.o u_map.o u_request.o u_response.o u_send_request.o u_websocket.o
49 ar rcs libulfius.a ulfius.o u_map.o u_request.o u_response.o u_send_request.o u_websocket.o
4750
4851 ulfius.o: ulfius.h u_private.h ulfius.c
4952 $(CC) $(CFLAGS) ulfius.c
6467 $(CC) $(CFLAGS) u_send_request.c
6568
6669 clean:
67 rm -f *.o *.so $(OUTPUT) $(OUTPUT).*
70 rm -f *.o *.so *.a $(OUTPUT) $(OUTPUT).*
6871
6972 install: all
7073 cp $(OUTPUT).$(VERSION) $(PREFIX)/lib
7174 cp ulfius.h $(PREFIX)/include
72 ldconfig
75 -ldconfig
76
77 static-install: static
78 cp libulfius.a $(PREFIX)/lib
79 cp ulfius.h $(PREFIX)/include
7380
7481 uninstall:
75 rm -f $(PREFIX)/lib/$(OUTPUT)
82 rm -f $(PREFIX)/lib/$(OUTPUT) libulfius.a
7683 rm -f $(PREFIX)/lib/$(OUTPUT).*
7784 rm -f $(PREFIX)/include/ulfius.h
7885
8390 release: ADDITIONALFLAGS=-O3
8491
8592 release: libulfius.so
93
94 static: ADDITIONALFLAGS=-O3
95
96 static: libulfius.a
97
98 static-debug: ADDITIONALFLAGS=-DDEBUG -g -O0
99
100 static-debug: libulfius.a
511511 * return -1 if no match found
512512 * search is case sensitive
513513 */
514 ssize_t u_map_get_length(const struct _u_map * u_map, const const char * key) {
514 ssize_t u_map_get_length(const struct _u_map * u_map, const char * key) {
515515 int i;
516516 if (u_map != NULL && key != NULL) {
517517 for (i=0; u_map->keys[i] != NULL; i++) {
530530 * return -1 if no match found
531531 * search is case insensitive
532532 */
533 ssize_t u_map_get_case_length(const struct _u_map * u_map, const const char * key) {
533 ssize_t u_map_get_case_length(const struct _u_map * u_map, const char * key) {
534534 int i;
535535 if (u_map != NULL && key != NULL) {
536536 for (i=0; u_map->keys[i] != NULL; i++) {
413413
414414 request->binary_body = (void*) json_dumps(body, JSON_COMPACT);
415415 if (request->binary_body == NULL) {
416 y_log_message(Y_LOG_LEVEL_ERROR, "Ulfius - Error allocating memory for dest->binary_body");
416 y_log_message(Y_LOG_LEVEL_ERROR, "Ulfius - Error allocating memory for request->binary_body");
417417 return U_ERROR_MEMORY;
418418 }
419419 request->binary_body_length = strlen((char*)request->binary_body);
571571 response->binary_body = o_malloc(binary_body_length);
572572
573573 if (response->binary_body == NULL) {
574 y_log_message(Y_LOG_LEVEL_ERROR, "Ulfius - Error allocating memory for dest->binary_body");
574 y_log_message(Y_LOG_LEVEL_ERROR, "Ulfius - Error allocating memory for response->binary_body");
575575 return U_ERROR_MEMORY;
576576 } else {
577577 response->status = status;
598598
599599 response->binary_body = o_malloc(length);
600600 if (response->binary_body == NULL) {
601 y_log_message(Y_LOG_LEVEL_ERROR, "Ulfius - Error allocating memory for dest->binary_body");
601 y_log_message(Y_LOG_LEVEL_ERROR, "Ulfius - Error allocating memory for response->binary_body");
602602 return U_ERROR_MEMORY;
603603 }
604604 memcpy(response->binary_body, binary_body, length);
675675
676676 response->binary_body = (void*) json_dumps(binary_body, JSON_COMPACT);
677677 if (response->binary_body == NULL) {
678 y_log_message(Y_LOG_LEVEL_ERROR, "Ulfius - Error allocating memory for dest->binary_body");
678 y_log_message(Y_LOG_LEVEL_ERROR, "Ulfius - Error allocating memory for response->binary_body");
679679 return U_ERROR_MEMORY;
680680 }
681681 response->binary_body_length = strlen((char*)response->binary_body);
126126 struct connection_info_struct * con_info = o_malloc (sizeof (struct connection_info_struct));
127127 if (con_info != NULL) {
128128 con_info->callback_first_iteration = 1;
129 con_info->u_instance = NULL;
129130 con_info->request = o_malloc(sizeof(struct _u_request));
130131 if (con_info->request == NULL) {
131132 y_log_message(Y_LOG_LEVEL_ERROR, "Ulfius - Error allocating memory for con_info->request");
219220
220221 struct connection_info_struct * con_info = coninfo_cls;
221222 size_t cur_size = size;
222 char * data_dup = o_strndup(data, size); // Force value to end with a NULL character
223
224 if (con_info->max_post_param_size > 0) {
225 if (off > con_info->max_post_param_size) {
223 char * data_dup, * filename_param;
224
225 if (filename != NULL && con_info->u_instance != NULL && con_info->u_instance->file_upload_callback != NULL) {
226 if (con_info->u_instance->file_upload_callback(con_info->request, key, filename, content_type, transfer_encoding, data, off, size, con_info->u_instance->file_upload_cls) == U_OK) {
226227 return MHD_YES;
227 } else if (off + size > con_info->max_post_param_size) {
228 cur_size = con_info->max_post_param_size - off;
229 }
230 }
231
232 if (cur_size > 0 && data_dup != NULL && u_map_put_binary((struct _u_map *)con_info->request->map_post_body, key, data_dup, off, cur_size + 1) == U_OK) {
233 o_free(data_dup);
234 return MHD_YES;
235 } else {
236 o_free(data_dup);
237 return MHD_NO;
228 } else {
229 return MHD_NO;
230 }
231 } else {
232 data_dup = o_strndup(data, size); // Force value to end with a NULL character
233 if (con_info->max_post_param_size > 0) {
234 if (off > con_info->max_post_param_size) {
235 return MHD_YES;
236 } else if (off + size > con_info->max_post_param_size) {
237 cur_size = con_info->max_post_param_size - off;
238 }
239 }
240
241 if (filename != NULL) {
242 filename_param = msprintf("%s_filename", key);
243 if (u_map_put((struct _u_map *)con_info->request->map_post_body, filename_param, filename) != U_OK) {
244 y_log_message(Y_LOG_LEVEL_ERROR, "ulfius - Error u_map_put filename value");
245 }
246 o_free(filename_param);
247 }
248
249 if (cur_size > 0 && data_dup != NULL && u_map_put_binary((struct _u_map *)con_info->request->map_post_body, key, data_dup, off, cur_size + 1) == U_OK) {
250 o_free(data_dup);
251 return MHD_YES;
252 } else {
253 o_free(data_dup);
254 return MHD_NO;
255 }
238256 }
239257 }
240258
269287 if (con_info == NULL) {
270288 y_log_message(Y_LOG_LEVEL_ERROR, "Ulfius - Error con_info is NULL");
271289 return MHD_NO;
290 }
291
292 if (con_info->u_instance == NULL) {
293 con_info->u_instance = (struct _u_instance *)cls;
294
272295 }
273296
274297 if (con_info->callback_first_iteration) {
304327 }
305328 return MHD_YES;
306329 } else if (*upload_data_size != 0) {
307
308330 size_t body_len = con_info->request->binary_body_length + *upload_data_size, upload_data_size_current = *upload_data_size;
309331
310332 if (((struct _u_instance *)cls)->max_post_body_size > 0 && con_info->request->binary_body_length + *upload_data_size > ((struct _u_instance *)cls)->max_post_body_size) {
320342 } else {
321343 memcpy((char*)con_info->request->binary_body + con_info->request->binary_body_length, upload_data, upload_data_size_current);
322344 con_info->request->binary_body_length += upload_data_size_current;
345 // Handles request binary_body
346 const char * content_type = u_map_get_case(con_info->request->map_header, ULFIUS_HTTP_HEADER_CONTENT);
347 if (0 == o_strncmp(MHD_HTTP_POST_ENCODING_FORM_URLENCODED, content_type, strlen(MHD_HTTP_POST_ENCODING_FORM_URLENCODED)) ||
348 0 == o_strncmp(MHD_HTTP_POST_ENCODING_MULTIPART_FORMDATA, content_type, strlen(MHD_HTTP_POST_ENCODING_MULTIPART_FORMDATA))) {
349 MHD_post_process (con_info->post_processor, upload_data, *upload_data_size);
350 }
323351 *upload_data_size = 0;
324352 return MHD_YES;
325353 }
327355 return MHD_YES;
328356 }
329357 } else {
330 // Handles request binary_body
331 const char * content_type = u_map_get_case(con_info->request->map_header, ULFIUS_HTTP_HEADER_CONTENT);
332 if (0 == o_strncmp(MHD_HTTP_POST_ENCODING_FORM_URLENCODED, content_type, strlen(MHD_HTTP_POST_ENCODING_FORM_URLENCODED)) ||
333 0 == o_strncmp(MHD_HTTP_POST_ENCODING_MULTIPART_FORMDATA, content_type, strlen(MHD_HTTP_POST_ENCODING_MULTIPART_FORMDATA))) {
334 MHD_post_process (con_info->post_processor, con_info->request->binary_body, con_info->request->binary_body_length);
335 }
336
337358 // Check if the endpoint has one or more matches
338359 current_endpoint_list = ulfius_endpoint_match(method, url, endpoint_list);
339360
570591 mhd_ret = MHD_queue_basic_auth_fail_response (connection, auth_realm, mhd_response);
571592 } else if (inner_error == U_CALLBACK_UNAUTHORIZED) {
572593 mhd_ret = MHD_queue_response (connection, MHD_HTTP_UNAUTHORIZED, mhd_response);
573 #ifndef U_DISABLE_WEBSOCKET
594 #ifndef U_DISABLE_WEBSOCKET
574595 } else if (upgrade_protocol) {
575596 mhd_ret = MHD_queue_response (connection,
576597 MHD_HTTP_SWITCHING_PROTOCOLS,
577598 mhd_response);
578 #endif
599 #endif
579600 } else {
580601 mhd_ret = MHD_queue_response (connection, response->status, mhd_response);
581602 }
10781099 }
10791100
10801101 /**
1102 * ulfius_set_upload_file_callback_function
1103 *
1104 * Set the callback function to handle file upload
1105 * Used to facilitate large files upload management
1106 * The callback function file_upload_callback will be called
1107 * multiple times, with the uploaded file in striped in parts
1108 *
1109 * Warning: If this function is used, all the uploaded files
1110 * for the instance will be managed via this function, and they
1111 * will no longer be available in the struct _u_request in the
1112 * ulfius callback function afterwards.
1113 *
1114 * Thanks to Thad Phetteplace for the help on this feature
1115 *
1116 * u_instance: pointer to a struct _u_instance that describe its port and bind address
1117 * file_upload_callback: Pointer to a callback function that will handle all file uploads
1118 * cls: a pointer that will be passed to file_upload_callback each tim it's called
1119 */
1120 int ulfius_set_upload_file_callback_function(struct _u_instance * u_instance,
1121 int (* file_upload_callback) (const struct _u_request * request,
1122 const char * key,
1123 const char * filename,
1124 const char * content_type,
1125 const char * transfer_encoding,
1126 const char * data,
1127 uint64_t off,
1128 size_t size,
1129 void * cls),
1130 void * cls) {
1131 if (u_instance != NULL && file_upload_callback != NULL) {
1132 u_instance->file_upload_callback = file_upload_callback;
1133 u_instance->file_upload_cls = cls;
1134 return U_OK;
1135 } else {
1136 return U_ERROR_PARAMS;
1137 }
1138 }
1139
1140 /**
10811141 * ulfius_clean_instance
10821142 *
10831143 * Clean memory allocated by a struct _u_instance *
11331193 u_instance->default_endpoint = NULL;
11341194 u_instance->max_post_param_size = 0;
11351195 u_instance->max_post_body_size = 0;
1196 u_instance->file_upload_callback = NULL;
1197 u_instance->file_upload_cls = NULL;
11361198 #ifndef U_DISABLE_WEBSOCKET
11371199 u_instance->websocket_handler = o_malloc(sizeof(struct _websocket_handler));
11381200 if (u_instance->websocket_handler == NULL) {
11511213 }
11521214 ((struct _websocket_handler *)u_instance->websocket_handler)->pthread_init = 1;
11531215 #else
1154 u_instance->websocket_handler = NULL;
1216 u_instance->websocket_handler = NULL;
11551217 #endif
11561218 return U_OK;
11571219 } else {
5555 #define U_ERROR_LIBCURL 5 // Error in libcurl execution
5656 #define U_ERROR_NOT_FOUND 6 // Something was not found
5757
58 #define ULFIUS_VERSION 2.1
58 #define ULFIUS_VERSION 2.2
5959
6060 #define U_CALLBACK_CONTINUE 0
6161 #define U_CALLBACK_COMPLETE 1
117117 char * http_protocol;
118118 char * http_verb;
119119 char * http_url;
120 char * proxy;
120 char * proxy;
121121 int check_server_certificate;
122122 long timeout;
123123 struct sockaddr * client_address;
232232 size_t max_post_param_size;
233233 size_t max_post_body_size;
234234 void * websocket_handler;
235 int (* file_upload_callback) (const struct _u_request * request,
236 const char * key,
237 const char * filename,
238 const char * content_type,
239 const char * transfer_encoding,
240 const char * data,
241 uint64_t off,
242 size_t size,
243 void * cls);
244 void * file_upload_cls;
235245 };
236246
237247 /**
238248 * Structures used to facilitate data manipulations (internal)
239249 */
240250 struct connection_info_struct {
251 struct _u_instance * u_instance;
241252 struct MHD_PostProcessor * post_processor;
242253 int has_post_processor;
243254 int callback_first_iteration;
244 struct _u_request * request;
255 struct _u_request * request;
245256 size_t max_post_param_size;
246257 struct _u_map map_url_initial;
247258 };
298309 * return U_OK on success
299310 */
300311 int ulfius_stop_framework(struct _u_instance * u_instance);
312
313 /**
314 * ulfius_set_upload_file_callback_function
315 *
316 * Set the callback function to handle file upload
317 * Used to facilitate large files upload management
318 * The callback function file_upload_callback will be called
319 * multiple times, with the uploaded file in striped in parts
320 *
321 * Warning: If this function is used, all the uploaded files
322 * for the instance will be managed via this function, and they
323 * will no longer be available in the struct _u_request in the
324 * ulfius callback function afterwards.
325 *
326 * Thanks to Thad Phetteplace for the help on this feature
327 *
328 * u_instance: pointer to a struct _u_instance that describe its port and bind address
329 * file_upload_callback: Pointer to a callback function that will handle all file uploads
330 * cls: a pointer that will be passed to file_upload_callback each tim it's called
331 */
332 int ulfius_set_upload_file_callback_function(struct _u_instance * u_instance,
333 int (* file_upload_callback) (const struct _u_request * request,
334 const char * key,
335 const char * filename,
336 const char * content_type,
337 const char * transfer_encoding,
338 const char * data,
339 uint64_t off,
340 size_t size,
341 void * cls),
342 void * cls);
301343
302344 /***********************************
303345 * Endpoints functions declarations