Updated source code for download-provider from tizen 2.2.1 git branch
[platform/framework/web/download-provider.git] / agent / download-agent-http-msg-handler.c
1 /*
2  * Copyright (c) 2012 Samsung Electronics Co., Ltd All Rights Reserved
3  *
4  * Licensed under the Apache License, Version 2.0 (the License);
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an AS IS BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #include <string.h>
18 #include <stdlib.h>
19 #include <ctype.h>
20
21 #include "download-agent-http-msg-handler.h"
22 #include "download-agent-debug.h"
23 #include "download-agent-http-misc.h"
24 #include "download-agent-encoding.h"
25
26 // '.' and ';' are request from Vodafone
27 #define IS_TERMINATING_CHAR(c)          ( ((c) == ';') || ((c) == '\0') || ((c) == 0x0d) || ((c) == 0x0a) || ((c) == 0x20) )
28 #define IS_TERMINATING_CHAR_EX(c)       ( ((c) == '"') || ((c) == ';') || ((c) == '\0') || ((c) == 0x0d) || ((c) == 0x0a) || ((c) == 0x20) )
29 #define IS_URI_TERMINATING_CHAR(c)      ( ((c) == '\0') || ((c) == 0x0d) || ((c) == 0x0a) || ((c) == 0x20) )
30
31 enum parsing_type {
32         WITH_PARSING_OPTION,
33         WITHOUT_PARSING_OPTION
34 };
35
36 static da_result_t __http_header_add_field(http_header_t **head,
37         const char *field, const char *value, enum parsing_type type);
38 static void __http_header_destroy_all_field(http_header_t **head);
39 static da_bool_t __get_http_header_for_field(
40         http_msg_response_t *http_msg_response, const char *in_field,
41         http_header_t **out_header);
42 static void __exchange_header_value(http_header_t *header,
43         const char *in_raw_value);
44
45 static http_header_options_t *__create_http_header_option(const char *field,
46         const char *value);
47 static void __http_header_destroy_all_option(http_header_options_t **head);
48 static da_bool_t __get_http_header_option_for_field(
49         http_header_options_t *header_option, const char *in_field,
50         char **out_value);
51
52 static http_header_options_t *__parsing_N_create_option_str(char *org_str);
53 static http_header_options_t *__parsing_options(char *org_str);
54 static void __parsing_raw_value(http_header_t *http_header);
55
56 da_result_t http_msg_request_create(http_msg_request_t **http_msg_request)
57 {
58         http_msg_request_t *temp_http_msg_request = NULL;
59
60         DA_LOG_FUNC_LOGV(HTTPManager);
61
62         temp_http_msg_request = (http_msg_request_t *)calloc(1,
63                 sizeof(http_msg_request_t));
64         if (!temp_http_msg_request) {
65                 *http_msg_request = NULL;
66                 DA_LOG_ERR(HTTPManager, "DA_ERR_FAIL_TO_MEMALLOC");
67                 return DA_ERR_FAIL_TO_MEMALLOC;
68         }
69
70         temp_http_msg_request->http_method = NULL;
71         temp_http_msg_request->url = NULL;
72         temp_http_msg_request->head = NULL;
73         temp_http_msg_request->http_body = NULL;
74
75         *http_msg_request = temp_http_msg_request;
76         DA_LOG_DEBUG(HTTPManager, "http_msg_request: %x", (unsigned int)(*http_msg_request));
77
78         return DA_RESULT_OK;
79 }
80
81 void http_msg_request_destroy(http_msg_request_t **http_msg_request)
82 {
83         http_msg_request_t *temp_http_msg_request = *http_msg_request;
84
85         DA_LOG_FUNC_LOGV(HTTPManager);
86
87         if (temp_http_msg_request) {
88                 if (temp_http_msg_request->http_method) {
89                         free(temp_http_msg_request->http_method);
90                         temp_http_msg_request->http_method = NULL;
91                 }
92
93                 if (temp_http_msg_request->url) {
94                         free(temp_http_msg_request->url);
95                         temp_http_msg_request->url = NULL;
96                 }
97
98                 if (temp_http_msg_request->http_body) {
99                         free(temp_http_msg_request->http_body);
100                         temp_http_msg_request->http_body = NULL;
101                 }
102
103                 __http_header_destroy_all_field(&(temp_http_msg_request->head));
104
105                 free(temp_http_msg_request);
106                 *http_msg_request = NULL;
107         }
108
109 }
110
111 da_result_t http_msg_request_set_method(http_msg_request_t *http_msg_request,
112         const char *method)
113 {
114         DA_LOG_FUNC_LOGD(HTTPManager);
115
116         if (!http_msg_request || !method) {
117                 DA_LOG_ERR(HTTPManager, "DA_ERR_INVALID_ARGUMENT");
118                 return DA_ERR_INVALID_ARGUMENT;
119         }
120
121         // ToDo: check method is valid
122
123         http_msg_request->http_method = strdup(method);
124
125         DA_LOG(HTTPManager, "http method : %s", http_msg_request->http_method);
126
127         return DA_RESULT_OK;
128 }
129
130 da_result_t http_msg_request_get_method(http_msg_request_t *http_msg_request,
131         const char **method)
132 {
133         DA_LOG_FUNC_LOGV(HTTPManager);
134
135         if (!http_msg_request) {
136                 DA_LOG_ERR(HTTPManager, "DA_ERR_INVALID_ARGUMENT");
137                 return DA_ERR_INVALID_ARGUMENT;
138         }
139
140         if (http_msg_request->http_method) {
141                 *method = http_msg_request->http_method;
142                 return DA_RESULT_OK;
143         } else {
144                 *method = DA_NULL;
145                 return DA_ERR_INVALID_ARGUMENT;
146         }
147 }
148
149 da_result_t http_msg_request_set_url(http_msg_request_t *http_msg_request,
150         const char *url)
151 {
152         DA_LOG_FUNC_LOGV(HTTPManager);
153
154         if (!http_msg_request) {
155                 DA_LOG_ERR(HTTPManager, "http_msg_request is NULL; DA_ERR_INVALID_ARGUMENT");
156                 return DA_ERR_INVALID_ARGUMENT;
157         }
158
159         if (!url) {
160                 DA_LOG_ERR(HTTPManager, "url is NULL; DA_ERR_INVALID_ARGUMENT");
161                 return DA_ERR_INVALID_URL;
162         }
163
164         http_msg_request->url = strdup(url);
165
166         //DA_SECURE_LOGD("http url : %s", http_msg_request->url);
167
168         return DA_RESULT_OK;
169 }
170
171 da_result_t http_msg_request_get_url(http_msg_request_t *http_msg_request,
172         const char **url)
173 {
174         DA_LOG_FUNC_LOGV(HTTPManager);
175
176         if (!http_msg_request) {
177                 DA_LOG_ERR(HTTPManager, "http_msg_request is NULL; DA_ERR_INVALID_ARGUMENT");
178                 return DA_ERR_INVALID_ARGUMENT;
179         }
180
181         if (http_msg_request->url) {
182                 *url = http_msg_request->url;
183                 return DA_RESULT_OK;
184         } else {
185                 *url = DA_NULL;
186                 return DA_ERR_INVALID_ARGUMENT;
187         }
188 }
189
190 da_result_t http_msg_request_set_body(http_msg_request_t *http_msg_request,
191         const char *body)
192 {
193         DA_LOG_FUNC_LOGV(HTTPManager);
194
195         if (!http_msg_request) {
196                 DA_LOG_ERR(HTTPManager, "DA_ERR_INVALID_ARGUMENT");
197                 return DA_ERR_INVALID_ARGUMENT;
198         }
199
200         if (!body)
201                 return DA_RESULT_OK;
202
203         http_msg_request->http_body = strdup(body);
204
205         DA_SECURE_LOGD("http body : %s", http_msg_request->http_body);
206
207         return DA_RESULT_OK;
208 }
209
210 da_result_t http_msg_request_get_body(http_msg_request_t *http_msg_request,
211         const char **body)
212 {
213         DA_LOG_FUNC_LOGV(HTTPManager);
214
215         if (!http_msg_request) {
216                 DA_LOG_ERR(HTTPManager, "DA_ERR_INVALID_ARGUMENT");
217                 return DA_ERR_INVALID_ARGUMENT;
218         }
219
220         if (http_msg_request->http_body) {
221                 *body = http_msg_request->http_body;
222                 return DA_RESULT_OK;
223         } else {
224                 *body = DA_NULL;
225                 return DA_ERR_INVALID_ARGUMENT;
226         }
227 }
228
229 /* FIXME later : check to free filed and value after this API is called */
230 da_result_t http_msg_request_add_field(http_msg_request_t *http_msg_request,
231         const char *field, const char *value)
232 {
233         DA_LOG_FUNC_LOGV(HTTPManager);
234
235         if (!http_msg_request) {
236                 DA_LOG_ERR(HTTPManager, "DA_ERR_INVALID_ARGUMENT");
237                 return DA_ERR_INVALID_ARGUMENT;
238         }
239
240         return __http_header_add_field(&(http_msg_request->head), field, value, WITHOUT_PARSING_OPTION);
241 }
242
243 da_result_t http_msg_response_create(http_msg_response_t **http_msg_response)
244 {
245         http_msg_response_t *temp_http_msg_response = NULL;
246
247         DA_LOG_FUNC_LOGV(HTTPManager);
248
249         temp_http_msg_response = (http_msg_response_t *)calloc(1,
250                 sizeof(http_msg_response_t));
251         if (!temp_http_msg_response) {
252                 DA_LOG_ERR(HTTPManager, "DA_ERR_FAIL_TO_MEMALLOC");
253                 return DA_ERR_FAIL_TO_MEMALLOC;
254         } else {
255                 temp_http_msg_response->status_code = 0;
256                 temp_http_msg_response->head = NULL;
257
258                 *http_msg_response = temp_http_msg_response;
259
260                 return DA_RESULT_OK;
261         }
262 }
263
264 void http_msg_response_destroy(http_msg_response_t **http_msg_response)
265 {
266         http_msg_response_t *temp_http_msg_response = *http_msg_response;
267
268         DA_LOG_FUNC_LOGV(HTTPManager);
269         if (temp_http_msg_response) {
270                 __http_header_destroy_all_field(&(temp_http_msg_response->head));
271
272                 free(temp_http_msg_response);
273                 *http_msg_response = DA_NULL;
274         }
275 }
276
277 da_result_t http_msg_response_set_status_code(
278         http_msg_response_t *http_msg_response, int status_code)
279 {
280         DA_LOG_FUNC_LOGV(HTTPManager);
281
282         if (!http_msg_response) {
283                 DA_LOG_ERR(HTTPManager, "DA_ERR_INVALID_ARGUMENT");
284                 return DA_ERR_INVALID_ARGUMENT;
285         }
286
287         http_msg_response->status_code = status_code;
288
289         return DA_RESULT_OK;
290 }
291
292 da_result_t http_msg_response_get_status_code(
293         http_msg_response_t *http_msg_response, int *status_code)
294 {
295         DA_LOG_FUNC_LOGD(HTTPManager);
296
297         if (!http_msg_response) {
298                 DA_LOG_ERR(HTTPManager, "DA_ERR_INVALID_ARGUMENT");
299                 return DA_ERR_INVALID_ARGUMENT;
300         }
301
302         *status_code = http_msg_response->status_code;
303
304         return DA_RESULT_OK;
305 }
306
307 da_result_t http_msg_response_add_field(http_msg_response_t *http_msg_response,
308         const char *field, const char *value)
309 {
310         DA_LOG_FUNC_LOGV(HTTPManager);
311
312         if (!http_msg_response) {
313                 DA_LOG_ERR(HTTPManager, "DA_ERR_INVALID_ARGUMENT");
314                 return DA_ERR_INVALID_ARGUMENT;
315         }
316
317         return __http_header_add_field(&(http_msg_response->head), field, value, WITH_PARSING_OPTION);
318 }
319
320 da_result_t __http_header_add_field(http_header_t **head,
321         const char *field, const char *value, enum parsing_type type)
322 {
323         http_header_t *pre = NULL;
324         http_header_t *cur = NULL;
325
326         //DA_SECURE_LOGD("[%s][%s]", field, value);
327
328         pre = cur = *head;
329         while (cur) {
330                 pre = cur;
331                 /* Replace default value with user wanted value
332                  * Remove the value which is stored before and add a new value.
333                 */
334                 if (cur->field && cur->raw_value &&
335                                 strncasecmp(cur->field, field, strlen(field)) == 0) {
336                         DA_SECURE_LOGD("Remove value for replacement [%s][%s]", cur->field, cur->raw_value);
337                         if (cur->field) {
338                                 free(cur->field);
339                                 cur->field = NULL;
340                         }
341                         if (cur->raw_value) {
342                                 free(cur->raw_value);
343                                 cur->raw_value= NULL;
344                         }
345                 }
346                 cur = cur->next;
347         }
348
349         cur = (http_header_t *)calloc(1, sizeof(http_header_t));
350         if (cur) {
351                 cur->field = strdup(field);
352                 cur->raw_value = strdup(value);
353                 cur->options = NULL;
354                 cur->next = NULL;
355
356                 if (type == WITHOUT_PARSING_OPTION) {
357                         cur->value = strdup(value);
358                         cur->options = NULL;
359                 } else {
360                         __parsing_raw_value(cur);
361                 }
362
363                 if (pre)
364                         pre->next = cur;
365                 else
366                         *head = cur;
367         } else {
368                 DA_LOG_ERR(HTTPManager, "DA_ERR_FAIL_TO_MEMALLOC");
369                 return DA_ERR_FAIL_TO_MEMALLOC;
370         }
371
372         return DA_RESULT_OK;
373 }
374
375 void __http_header_destroy_all_field(http_header_t **head)
376 {
377         http_header_t *pre = NULL;
378         http_header_t *cur = NULL;
379
380         DA_LOG_FUNC_LOGV(HTTPManager);
381
382         cur = *head;
383
384         while (cur) {
385                 if (cur->field) {
386                         free(cur->field);
387                         cur->field = DA_NULL;
388                 }
389
390                 if (cur->value) {
391                         free(cur->value);
392                         cur->value = DA_NULL;
393                 }
394
395                 if (cur->raw_value) {
396                         free(cur->raw_value);
397                         cur->raw_value = DA_NULL;
398                 }
399
400                 __http_header_destroy_all_option(&(cur->options));
401
402                 pre = cur;
403                 cur = cur->next;
404
405                 free(pre);
406         }
407
408         *head = DA_NULL;
409 }
410
411 http_header_options_t *__create_http_header_option(const char *field,
412         const char *value)
413 {
414         http_header_options_t *option = NULL;
415
416         option = (http_header_options_t *)calloc(1,
417                 sizeof(http_header_options_t));
418         if (option) {
419                 if (field)
420                         option->field = strdup(field);
421
422                 if (value)
423                         option->value = strdup(value);
424
425                 option->next = NULL;
426         }
427
428         return option;
429 }
430
431 void __http_header_destroy_all_option(http_header_options_t **head)
432 {
433         http_header_options_t *pre = NULL;
434         http_header_options_t *cur = NULL;
435
436         DA_LOG_FUNC_LOGV(HTTPManager);
437
438         cur = *head;
439
440         while (cur) {
441                 if (cur->field) {
442                         DA_LOG_VERBOSE("field= %s", cur->field);
443                         free(cur->field);
444                         cur->field = DA_NULL;
445                 }
446
447                 if (cur->value) {
448                         free(cur->value);
449                         cur->value = DA_NULL;
450                 }
451
452                 pre = cur;
453                 cur = cur->next;
454
455                 free(pre);
456         }
457
458         *head = DA_NULL;
459 }
460
461 da_result_t http_msg_request_get_iter(http_msg_request_t *http_msg_request,
462         http_msg_iter_t *http_msg_iter)
463 {
464         DA_LOG_FUNC_LOGV(HTTPManager);
465
466         if (!http_msg_request) {
467                 DA_LOG_ERR(HTTPManager, "DA_ERR_INVALID_ARGUMENT");
468                 return DA_ERR_INVALID_ARGUMENT;
469         }
470
471         *http_msg_iter = http_msg_request->head;
472
473         return DA_RESULT_OK;
474 }
475
476 da_result_t http_msg_response_get_iter(http_msg_response_t *http_msg_response,
477         http_msg_iter_t *http_msg_iter)
478 {
479         if (!http_msg_response) {
480                 DA_LOG_ERR(HTTPManager, "DA_ERR_INVALID_ARGUMENT");
481                 return DA_ERR_INVALID_ARGUMENT;
482         }
483
484         *http_msg_iter = http_msg_response->head;
485         //      DA_LOG_VERBOSE(HTTPManager, "retrieve iter = 0x%x", (unsigned int)http_msg_iter);
486
487         return DA_RESULT_OK;
488 }
489
490 da_bool_t http_msg_get_field_with_iter(http_msg_iter_t *http_msg_iter,
491         char **out_field, char **out_value)
492 {
493         http_header_t *cur = *http_msg_iter;
494
495         //      DA_LOG_VERBOSE(HTTPManager, "getting iter = 0x%x", (unsigned int)cur);
496
497         if (cur) {
498                 *out_field = cur->field;
499                 *out_value = cur->value;
500                 *http_msg_iter = cur->next;
501
502                 return DA_TRUE;
503         } else {
504                 //      DA_LOG_VERBOSE(HTTPManager, "end of iter");
505                 return DA_FALSE;
506         }
507 }
508
509 da_bool_t http_msg_get_header_with_iter(http_msg_iter_t *http_msg_iter,
510         char **out_field, http_header_t **out_header)
511 {
512         http_header_t *cur = *http_msg_iter;
513
514         //      DA_LOG_VERBOSE(HTTPManager, "getting iter = 0x%x", (unsigned int)cur);
515
516         if (cur) {
517                 *out_field = cur->field;
518                 *out_header = cur;
519                 *http_msg_iter = cur->next;
520
521                 return DA_TRUE;
522         } else {
523                 //      DA_LOG_VERBOSE(HTTPManager, "end of iter");
524                 return DA_FALSE;
525         }
526 }
527
528 http_header_options_t *__parsing_N_create_option_str(char *org_str)
529 {
530         char *option_field = NULL;
531         char *option_value = NULL;
532         int option_field_len = 0;
533         int option_value_len = 0;
534
535         char *org_pos = NULL;
536         int org_str_len = 0;
537
538         char *working_str = NULL;
539         char *working_pos = NULL;
540         char *working_pos_field_start = NULL;
541         char *working_pos_value_start = NULL;
542
543         da_bool_t is_inside_quotation = DA_FALSE;
544         da_bool_t is_working_for_field = DA_TRUE;
545         int i = 0;
546         http_header_options_t *option = NULL;
547
548         DA_LOG_FUNC_LOGV(HTTPManager);
549
550         if (!org_str)
551                 return NULL;
552
553         org_str_len = strlen(org_str);
554         if (org_str_len <= 0)
555                 return NULL;
556
557         working_str = (char *)calloc(1, org_str_len + 1);
558         if (!working_str)
559                 return NULL;
560
561         org_pos = org_str;
562         working_pos_field_start = working_pos = working_str;
563
564         for (i = 0; i < org_str_len; i++) {
565                 if (*org_pos == '"')
566                         is_inside_quotation = !is_inside_quotation;
567
568                 if (is_inside_quotation) {
569                         // Leave anything including blank if it is inside of double quotation mark.
570                         *working_pos = *org_pos;
571                         is_working_for_field ? option_field_len++
572                                 : option_value_len++;
573                         working_pos++;
574                         org_pos++;
575                 } else {
576                         if (*org_pos == ' ') {
577                                 org_pos++;
578                         } else if (*org_pos == '=') {
579                                 if (is_working_for_field) {
580                                         is_working_for_field = DA_FALSE;
581                                         working_pos_value_start = working_pos;
582                                 }
583
584                                 org_pos++;
585                         } else {
586                                 *working_pos = *org_pos;
587                                 is_working_for_field ? option_field_len++
588                                         : option_value_len++;
589                                 working_pos++;
590                                 org_pos++;
591                         }
592                 }
593         }
594
595         if (option_field_len > 0 && working_pos_field_start) {
596                 option_field = (char *)calloc(1, option_field_len + 1);
597                 if (option_field)
598                         strncpy(option_field, working_pos_field_start,
599                                 option_field_len);
600         }
601
602         if (option_value_len > 0 && working_pos_value_start) {
603                 option_value = (char *)calloc(1, option_value_len + 1);
604                 if (option_value)
605                         strncpy(option_value, working_pos_value_start,
606                                 option_value_len);
607         }
608
609         if (working_str) {
610                 free(working_str);
611                 working_pos = working_str = NULL;
612         }
613
614 //      DA_SECURE_LOGD("option_field = [%s], option_value = [%s]",
615 //              option_field, option_value);
616
617         if (option_field || option_value) {
618                 option = __create_http_header_option(
619                         option_field, option_value);
620                 if (option_field) {
621                         free(option_field);
622                         option_field = NULL;
623                 }
624
625                 if (option_value) {
626                         free(option_value);
627                         option_value = NULL;
628                 }
629         }
630         return option;
631 }
632
633 http_header_options_t *__parsing_options(char *org_str)
634 {
635         da_result_t ret = DA_RESULT_OK;
636         http_header_options_t *head = NULL;
637         http_header_options_t *pre = NULL;
638         http_header_options_t *cur = NULL;
639
640         int wanted_str_len = 0;
641         char *wanted_str = NULL;
642         char *wanted_str_start = NULL;
643         char *wanted_str_end = NULL;
644         char *cur_pos = NULL;
645
646         DA_LOG_FUNC_LOGV(HTTPManager);
647
648         if (!org_str)
649                 return NULL;
650
651         /* Do Not use strtok(). It's not thread safe. */
652         //      DA_SECURE_LOGD("org_str = %s", org_str);
653
654         cur_pos = org_str;
655
656         while (cur_pos) {
657                 wanted_str_start = cur_pos;
658                 wanted_str_end = strchr(cur_pos, ';');
659                 if (wanted_str_end) {
660                         cur_pos = wanted_str_end + 1;
661                 } else {
662                         wanted_str_end = org_str + strlen(org_str);
663                         cur_pos = NULL;
664                 }
665
666                 wanted_str_len = wanted_str_end - wanted_str_start;
667                 wanted_str = (char *)calloc(1, wanted_str_len + 1);
668                 if (!wanted_str) {
669                         DA_LOG_ERR(HTTPManager, "DA_ERR_FAIL_TO_MEMALLOC");
670                         ret = DA_ERR_FAIL_TO_MEMALLOC;
671                         goto ERR;
672                 }
673                 strncpy(wanted_str, wanted_str_start, wanted_str_len);
674
675                 //              DA_SECURE_LOGD("wanted_str = [%s]", wanted_str);
676                 cur = __parsing_N_create_option_str(wanted_str);
677                 if (pre) {
678                         pre->next = cur;
679                         pre = cur;
680                 } else {
681                         head = pre = cur;
682                 }
683
684                 free(wanted_str);
685                 wanted_str = NULL;
686         }
687
688 ERR:
689         if (ret != DA_RESULT_OK)
690                 __http_header_destroy_all_option(&head);
691
692         return head;
693 }
694
695 void __parsing_raw_value(http_header_t *http_header_field)
696 {
697         char *raw_value = NULL;
698         char *option_str_start = NULL;
699
700         char *trimed_value = NULL;
701         int trimed_value_len = 0;
702
703         char *trimed_value_start = NULL;
704         char *trimed_value_end = NULL;
705
706         raw_value = http_header_field->raw_value;
707         //      DA_SECURE_LOGD("raw_value = [%s]", raw_value);
708
709         if (!raw_value)
710                 return;
711
712         trimed_value_start = raw_value;
713
714         trimed_value_end = strchr(raw_value, ';');
715         if (!trimed_value_end) {
716                 // No options
717                 http_header_field->value = strdup(raw_value);
718                 http_header_field->options = NULL;
719
720                 return;
721         }
722
723         // for trimed value
724         trimed_value_len = trimed_value_end - trimed_value_start;
725
726         trimed_value = (char *)calloc(1, trimed_value_len + 1);
727         if (!trimed_value) {
728                 DA_LOG_ERR(HTTPManager, "DA_ERR_FAIL_TO_MEMALLOC");
729                 return;
730         }
731         strncpy(trimed_value, trimed_value_start, trimed_value_len);
732         http_header_field->value = trimed_value;
733
734         // for option parsing
735         option_str_start = trimed_value_end + 1;
736
737         http_header_field->options = __parsing_options(option_str_start);
738
739         /////////////// show
740         http_header_options_t *cur = NULL;
741
742         cur = http_header_field->options;
743         while (cur) {
744 //              DA_SECURE_LOGD("field = [%s], value = [%s]", cur->field, cur->value);
745                 cur = cur->next;
746         }
747
748 }
749
750 da_bool_t __get_http_header_option_for_field(
751         http_header_options_t *header_option, const char *in_field,
752         char **out_value)
753 {
754         http_header_options_t *cur = NULL;
755
756         DA_LOG_FUNC_LOGV(HTTPManager);
757
758         if (!header_option) {
759                 DA_LOG_ERR(HTTPManager, "input header_option is NULL.");
760                 return DA_FALSE;
761         }
762
763         cur = header_option;
764         while (cur) {
765                 if (cur->field) {
766                         if (!strncasecmp(cur->field, in_field, strlen(cur->field)) &&
767                                         cur->value) {
768                                 DA_SECURE_LOGD("[%s][%s]", cur->field, cur->value);
769                                 *out_value = cur->value;
770                                 return DA_TRUE;
771                         }
772
773                 }
774                 cur = cur->next;
775         }
776
777         return DA_FALSE;
778 }
779
780 da_bool_t __get_http_header_for_field(http_msg_response_t *http_msg_response,
781         const char *in_field, http_header_t **out_header)
782 {
783         http_msg_iter_t http_msg_iter;
784         http_header_t *header = NULL;
785         char *field = NULL;
786
787         DA_LOG_FUNC_LOGV(HTTPManager);
788
789         http_msg_response_get_iter(http_msg_response, &http_msg_iter);
790         while (http_msg_get_header_with_iter(&http_msg_iter, &field, &header)) {
791                 if (field && header && !strncasecmp(field, in_field, strlen(field))) {
792 //                      DA_SECURE_LOGD("[%s][%s]", field, header->value);
793                         *out_header = header;
794                         return DA_TRUE;
795                 }
796         }
797
798         return DA_FALSE;
799 }
800
801 void __exchange_header_value(http_header_t *header, const char *in_raw_value)
802 {
803         DA_LOG_FUNC_LOGV(HTTPManager);
804
805         if (!header || !in_raw_value)
806                 return;
807
808         __http_header_destroy_all_option(&(header->options));
809
810         if (header->value) {
811                 free(header->value);
812                 header->value = DA_NULL;
813         }
814
815         if (header->raw_value)
816                 free(header->raw_value);
817         header->raw_value = strdup(in_raw_value);
818
819         __parsing_raw_value(header);
820 }
821
822 da_bool_t http_msg_response_get_content_type(
823         http_msg_response_t *http_msg_response, char **out_type)
824 {
825         da_bool_t b_ret = DA_FALSE;
826         http_header_t *header = NULL;
827
828         DA_LOG_FUNC_LOGV(HTTPManager);
829
830         b_ret = __get_http_header_for_field(http_msg_response, "Content-Type",
831                 &header);
832         if (!b_ret) {
833                 DA_LOG(HTTPManager, "no Content-Type");
834                 return DA_FALSE;
835         }
836
837         if (out_type)
838                 *out_type = strdup(header->value);
839
840         return DA_TRUE;
841 }
842
843 void http_msg_response_set_content_type(http_msg_response_t *http_msg_response,
844         const char *in_type)
845 {
846         da_bool_t b_ret = DA_FALSE;
847         http_header_t *header = NULL;
848
849         DA_LOG_FUNC_LOGV(HTTPManager);
850
851         if (!http_msg_response || !in_type)
852                 return;
853
854         b_ret = __get_http_header_for_field(http_msg_response, "Content-Type",
855                 &header);
856         if (b_ret) {
857                 if (header->raw_value && (!strncmp(header->raw_value, in_type,
858                         strlen(header->raw_value))))
859                         return;
860
861                 DA_SECURE_LOGD("exchange Content-Type to [%s] from [%s]", in_type, header->value);
862                 __exchange_header_value(header, in_type);
863         } else {
864                 __http_header_add_field(&(http_msg_response->head),
865                         "Content-Type", in_type, WITH_PARSING_OPTION);
866         }
867 }
868
869 da_bool_t http_msg_response_get_content_length(
870         http_msg_response_t *http_msg_response, unsigned long long *out_length)
871 {
872         da_bool_t b_ret = DA_FALSE;
873         http_header_t *header = NULL;
874
875         DA_LOG_FUNC_LOGV(HTTPManager);
876
877         b_ret = __get_http_header_for_field(http_msg_response,
878                 "Content-Length", &header);
879         if (!b_ret) {
880                 DA_LOG(HTTPManager, "no Content-Length");
881                 return DA_FALSE;
882         }
883
884         if (out_length)
885                 *out_length = atoll(header->value);
886
887         return DA_TRUE;
888 }
889
890 da_bool_t http_msg_response_get_content_disposition(
891         http_msg_response_t *http_msg_response, char **out_disposition,
892         char **out_file_name)
893 {
894         da_bool_t b_ret = DA_FALSE;
895         http_header_t *header = NULL;
896         char *file_name = NULL;
897
898         char *wanted_str = NULL;
899         char *wanted_str_start = NULL;
900         char *wanted_str_end = NULL;
901         char *decoded_str = NULL;
902         int wanted_str_len = 0;
903
904         DA_LOG_FUNC_LOGV(HTTPManager);
905
906         b_ret = __get_http_header_for_field(http_msg_response,
907                 "Content-Disposition", &header);
908         if (!b_ret) {
909                 DA_LOG_VERBOSE(HTTPManager, "no Content-Disposition");
910                 return DA_FALSE;
911         }
912
913         if (out_disposition)
914                 *out_disposition = strdup(header->value);
915
916         if (!out_file_name)
917                 return DA_FALSE;
918
919         b_ret = __get_http_header_option_for_field(header->options, "filename",
920                 &file_name);
921         if (!b_ret) {
922                 DA_LOG(HTTPManager, "no option");
923                 return DA_FALSE;
924         }
925
926         // eliminate double quotation mark if it exists on derived value
927         wanted_str_start = strchr(file_name, '"');
928         if (!wanted_str_start) {
929                 *out_file_name = strdup(file_name);
930                 return DA_TRUE;
931         } else {
932                 //              DA_SECURE_LOGD("wanted_str_start = [%s]", wanted_str_start);
933                 wanted_str_start++;
934                 wanted_str_end = strchr(wanted_str_start, '"');
935                 if (wanted_str_end) {
936                         wanted_str_len = wanted_str_end - wanted_str_start;
937                         wanted_str = (char*)calloc(1, wanted_str_len + 1);
938                         if (!wanted_str) {
939                                 DA_LOG_ERR(HTTPManager, "DA_ERR_FAIL_TO_MEMALLOC");
940                                 return DA_FALSE;
941                         }
942                         strncpy(wanted_str, wanted_str_start, wanted_str_len);
943
944                         b_ret = is_base64_encoded_word(wanted_str);
945                         if (b_ret) {
946                                 DA_LOG(HTTPManager, "It's base64 encoded-word string");
947                                 if (DA_RESULT_OK == decode_base64_encoded_str(
948                                         wanted_str, &decoded_str)) {
949                                         DA_SECURE_LOGD("base64 decoded str = [%s]", decoded_str);
950                                         free(wanted_str);
951                                         wanted_str = decoded_str;
952                                         decoded_str = NULL;
953                                 } else {
954                                         DA_LOG(HTTPManager, "Fail to base64 decode. Just use un-decoded string.");
955                                 }
956                         } else {
957                                 DA_LOG(HTTPManager, "It's NOT base64 encoded-word string");
958                         }
959                         decode_url_encoded_str(wanted_str, &decoded_str);
960                         /* If it is url encoded string */
961                         if (decoded_str) {
962                                 DA_SECURE_LOGD("Url decoded str = [%s]", decoded_str);
963                                 free(wanted_str);
964                                 wanted_str = decoded_str;
965                                 decoded_str = NULL;
966                         }
967
968                         *out_file_name = wanted_str;
969
970                         DA_SECURE_LOGD("out_file_name = [%s]", *out_file_name);
971
972                         return DA_TRUE;
973                 } else {
974                         DA_LOG_ERR(HTTPManager, "Not matched \" !");
975                         return DA_FALSE;
976                 }
977         }
978 }
979
980 da_bool_t http_msg_response_get_ETag(http_msg_response_t *http_msg_response,
981         char **out_value)
982 {
983         da_bool_t b_ret = DA_FALSE;
984         http_header_t *header = NULL;
985
986         DA_LOG_FUNC_LOGV(HTTPManager);
987
988         b_ret = __get_http_header_for_field(http_msg_response, "ETag", &header);
989         if (!b_ret) {
990                 DA_LOG_VERBOSE(HTTPManager, "no ETag");
991                 return DA_FALSE;
992         }
993
994         if (out_value)
995                 *out_value = strdup(header->value);
996
997         return DA_TRUE;
998 }
999
1000 da_bool_t http_msg_response_get_date(http_msg_response_t *http_msg_response,
1001         char **out_value)
1002 {
1003         da_bool_t b_ret = DA_FALSE;
1004         http_header_t *header = NULL;
1005
1006         DA_LOG_FUNC_LOGV(HTTPManager);
1007
1008         b_ret = __get_http_header_for_field(http_msg_response, "Date", &header);
1009         if (!b_ret) {
1010                 DA_LOG(HTTPManager, "no Date");
1011                 return DA_FALSE;
1012         }
1013
1014         if (out_value)
1015                 *out_value = strdup(header->value);
1016
1017         return DA_TRUE;
1018 }
1019
1020 da_bool_t http_msg_response_get_location(http_msg_response_t *http_msg_response,
1021         char **out_value)
1022 {
1023         da_bool_t b_ret = DA_FALSE;
1024         http_header_t *header = NULL;
1025
1026         DA_LOG_FUNC_LOGV(HTTPManager);
1027
1028         b_ret = __get_http_header_for_field(http_msg_response, "Location", &header);
1029         if (!b_ret) {
1030                 DA_LOG(HTTPManager, "no Location");
1031                 return DA_FALSE;
1032         }
1033         if (out_value)
1034                 *out_value = strdup(header->value);
1035
1036         return DA_TRUE;
1037 }
1038
1039 da_result_t http_msg_response_get_boundary(
1040         http_msg_response_t *http_msg_response, char **out_val)
1041 {
1042         da_result_t ret = DA_RESULT_OK;
1043
1044         http_msg_iter_t http_msg_iter;
1045         char *field = NULL;
1046         char *value = NULL;
1047         char *boundary = NULL;
1048
1049         DA_LOG_FUNC_LOGV(HTTPManager);
1050
1051         if (!http_msg_response) {
1052                 DA_LOG_ERR(HTTPManager, "DA_ERR_INVALID_ARGUMENT");
1053                 return DA_ERR_INVALID_ARGUMENT;
1054         }
1055
1056         http_msg_response_get_iter(http_msg_response, &http_msg_iter);
1057         while (http_msg_get_field_with_iter(&http_msg_iter, &field, &value)) {
1058                 if ((field != DA_NULL) && (value != DA_NULL)) {
1059                         if (!strncasecmp(field, "Content-Type",
1060                                 strlen("Content-Type"))) {
1061                                 char *org_str = NULL;
1062                                 char *boundary_str_start = NULL;
1063                                 char *boundary_value_start = NULL;
1064                                 char *boundary_value_end = NULL;
1065                                 int boundary_value_len = 0;
1066
1067                                 org_str = value;
1068
1069                                 boundary_str_start
1070                                         = strstr(org_str, "boundary");
1071                                 if (boundary_str_start) {
1072                                         DA_LOG(HTTPManager, "boundary_str_start = %s", boundary_str_start);
1073                                         // this "Content-Type" value has "boundary" in it, so get the value
1074                                         boundary_value_start = strchr(
1075                                                 boundary_str_start, '"');
1076                                         boundary_value_start += 1; // start without "
1077
1078                                         boundary_value_end = strchr(
1079                                                 boundary_value_start, '"');
1080                                         boundary_value_len = boundary_value_end
1081                                                 - boundary_value_start;
1082
1083                                         DA_LOG(HTTPManager, "boundary_value_start = %s", boundary_value_start);
1084                                         DA_LOG(HTTPManager, "boundary_value_end = %s", boundary_value_end);
1085                                         DA_LOG(HTTPManager, "boundary_value_len = %d", boundary_value_len);
1086
1087                                 } else {
1088                                         // no "boundary" field on this "Content-Type" value
1089                                         ret = DA_ERR_INVALID_ARGUMENT;
1090                                         goto ERR;
1091                                 }
1092                                 // end of clear
1093
1094                                 boundary = (char *)calloc(1,
1095                                         boundary_value_len + 1);
1096                                 if (!boundary) {
1097                                         DA_LOG_ERR(HTTPManager, "DA_ERR_FAIL_TO_MEMALLOC");
1098                                         ret = DA_ERR_FAIL_TO_MEMALLOC;
1099
1100                                         goto ERR;
1101                                 }
1102                                 strncpy(boundary, boundary_value_start,
1103                                         boundary_value_len);
1104                                 DA_SECURE_LOGD("[boundary][%s]", boundary);
1105                                 break;
1106                         }
1107                 }
1108         }
1109
1110         *out_val = boundary;
1111
1112 ERR:
1113         return ret;
1114 }
1115
1116 char *get_http_response_header_raw(http_msg_response_t *http_msg_response)
1117 {
1118         http_msg_iter_t http_msg_iter;
1119         http_header_t *header = NULL;
1120         char *field = NULL;
1121         char tmp_buf[1024*4] = {0,};
1122         char line_buf[1024] = {0,};
1123         int len = 0;
1124         char *buff = NULL;
1125
1126         DA_LOG_FUNC_LOGV(HTTPManager);
1127
1128         http_msg_response_get_iter(http_msg_response, &http_msg_iter);
1129         while (http_msg_get_header_with_iter(&http_msg_iter, &field, &header)) {
1130                 if (field && header) {
1131                         // FIXME later :: buffer length is more than total length. think about getting header's conent length from libsoup
1132                         len = strlen(field) + strlen(header->value) + 2;
1133                         snprintf(line_buf, len,"%s:%s", field, header->value);
1134                         strncat(tmp_buf, line_buf, len);
1135                         strcat(tmp_buf, "\n");
1136                 }
1137         }
1138         if (strlen(tmp_buf) > 0) {
1139                 buff = (char *)calloc(1, strlen(tmp_buf) + 1);
1140                 if (buff == DA_NULL) {
1141                         DA_LOG_ERR(HTTPManager, "DA_ERR_FAIL_TO_MEMALLOC");
1142                         return DA_NULL;
1143                 }
1144                 memcpy(buff, tmp_buf, strlen(tmp_buf));
1145                 DA_SECURE_LOGD("\n---raw response header---\n%s\n------\n",buff);
1146                 return buff;
1147         } else {
1148                 return DA_NULL;
1149         }
1150 }
1151
1152 char *_stristr(const char *long_str, const char *find_str)
1153 {
1154         int i = 0;
1155         int length_long = 0;
1156         int length_find = 0;
1157         char *ret_ptr = NULL;
1158         char *org_ptr = NULL;
1159         char *look_ptr = NULL;
1160
1161         if (long_str == NULL || find_str == NULL) {
1162                 DA_LOG_ERR(Default,"INVALID ARGUMENT");
1163                 return NULL;
1164         }
1165
1166         length_long = strlen(long_str);
1167         length_find = strlen(find_str);
1168
1169         org_ptr = (char*)calloc(1, length_long + 1);
1170
1171         if (org_ptr == NULL) {
1172                 DA_LOG_ERR(Default,"INVALID ARGUMENT");
1173                 return NULL;
1174         }
1175
1176         look_ptr = (char*)calloc(1, length_find + 1);
1177
1178         if (look_ptr == NULL) {
1179                 DA_LOG_ERR(Default,"INVALID ARGUMENT");
1180                 free(org_ptr);
1181                 return NULL;
1182         }
1183
1184         while (i < length_long) {
1185                 if (isalpha(long_str[i]) != 0) {
1186                         if (isupper(long_str[i]) != 0) {
1187                                 org_ptr[i] = long_str[i];
1188                         } else {
1189                                 org_ptr[i] = toupper(long_str[i]);
1190                         }
1191                 } else {
1192                         org_ptr[i] = long_str[i];
1193                 }
1194
1195                 i++;
1196         }
1197
1198         i = 0;
1199
1200         while (i < length_find) {
1201                 if (isalpha(find_str[i]) != 0) {
1202                         if (isupper(find_str[i]) != 0) {
1203                                 look_ptr[i] = find_str[i];
1204                         } else {
1205                                 look_ptr[i] = toupper(find_str[i]);
1206                         }
1207                 } else {
1208                         look_ptr[i] = find_str[i];
1209                 }
1210
1211                 i++;
1212         }
1213
1214         ret_ptr = strstr(org_ptr, look_ptr);
1215
1216         if (ret_ptr == 0) {
1217                 free(org_ptr);
1218                 free(look_ptr);
1219                 return NULL;
1220         } else {
1221                 i = ret_ptr - org_ptr;
1222         }
1223
1224         free(org_ptr);
1225         free(look_ptr);
1226
1227         return (char*)(long_str + i);
1228 }
1229
1230 /* This is not used. But it can be needed if there is no http header parser at http library.*/
1231 da_bool_t extract_attribute_from_header(
1232         char *szHeadStr,
1233         const char *szFindStr,
1234         char **ppRtnValue)
1235 {
1236
1237         char *pValuePos = NULL;
1238         int index = 0;
1239         int startPos = 0;
1240         int strLen = 0;
1241         int need_to_end_quataion_mark = 0;
1242
1243         if (szHeadStr == DA_NULL || szFindStr == DA_NULL) {
1244                 DA_LOG_ERR(Default,"INVALID ARGUMENT");
1245                 return DA_FALSE;
1246         }
1247
1248         if (strlen(szHeadStr) <= 0 || strlen(szFindStr) <= 0) {
1249                 DA_LOG_ERR(Default,"INVALID ARGUMENT");;
1250
1251                 return DA_FALSE;
1252         }
1253
1254         if (ppRtnValue == NULL) {
1255                 return DA_FALSE;
1256         }
1257
1258         pValuePos = _stristr(szHeadStr, (char*)szFindStr);
1259         if (pValuePos == NULL) {
1260                 *ppRtnValue = NULL;
1261                 goto ERR;
1262         }
1263
1264         index = strlen(szFindStr);
1265
1266         while (pValuePos[index] != ':' && pValuePos[index] != '=') {
1267                 index++;
1268
1269                 if (pValuePos[index] == '\0') {
1270                         return DA_FALSE;
1271                 }
1272         }
1273
1274         index++;
1275
1276         /* jump space */
1277         while (pValuePos[index] == ' ') {
1278                 index++;
1279         }
1280
1281         /* jump quatation mark */
1282         while (pValuePos[index] == '"') {
1283                 need_to_end_quataion_mark = 1;
1284                 index++;
1285         }
1286
1287         startPos = index;
1288
1289         /* Find the end of data. */
1290         if (0 == strncasecmp(szFindStr, "Location", strlen("Location")))//terminate character list does not contain ';' in case of URI
1291         {
1292                 while (DA_FALSE == IS_URI_TERMINATING_CHAR(pValuePos[index])) {
1293                         index++;
1294                 }
1295         } else if (need_to_end_quataion_mark) {
1296                 while (DA_FALSE == IS_TERMINATING_CHAR_EX(pValuePos[index])) {
1297                         index++;
1298                 }
1299         } else {
1300                 while (DA_FALSE == IS_TERMINATING_CHAR(pValuePos[index])) {
1301                         index++;
1302                 }
1303         }
1304
1305         strLen = index - startPos;
1306
1307         if (strLen < 1) {
1308                 DA_LOG_ERR(Default," strLen is < 1");
1309                 goto ERR;
1310         }
1311
1312         *ppRtnValue = (char*)calloc(1, sizeof(char) * (strLen + 1));
1313
1314         if (*ppRtnValue == NULL) {
1315                 DA_LOG_ERR(Default," *ppRtnValue is NULL");
1316                 goto ERR;
1317         }
1318
1319         strncpy(*ppRtnValue, pValuePos + startPos, strLen);
1320         *(*ppRtnValue + strLen) = '\0';
1321
1322         return DA_TRUE;
1323
1324 ERR:
1325
1326         if (*ppRtnValue) {
1327                 free(*ppRtnValue);
1328                 *ppRtnValue = NULL;
1329         }
1330
1331         return DA_FALSE;
1332 }
1333