merge with master
[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_START(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(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_START(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_START(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_START(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_START(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_LOG(HTTPManager, "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_START(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_START(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_LOG(HTTPManager, "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_START(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_START(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_START(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_START(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_START(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_START(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_START(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_LOG_FUNC_START(HTTPManager);
327         DA_LOG(HTTPManager, "[%s][%s]", field, value);
328
329         pre = cur = *head;
330         while (cur) {
331                 pre = cur;
332                 /* Replace default value with user wanted value
333                  * Remove the value which is stored before and add a new value.
334                 */
335                 if (cur->field && cur->raw_value &&
336                                 strncmp(cur->field, field, strlen(field)) == 0) {
337                         DA_LOG(HTTPManager, "Remove value for replacement [%s][%s]", cur->field, cur->raw_value);
338                         if (cur->field) {
339                                 free(cur->field);
340                                 cur->field = NULL;
341                         }
342                         if (cur->raw_value) {
343                                 free(cur->raw_value);
344                                 cur->raw_value= NULL;
345                         }
346                 }
347                 cur = cur->next;
348         }
349
350         cur = (http_header_t *)calloc(1, sizeof(http_header_t));
351         if (cur) {
352                 cur->field = strdup(field);
353                 cur->raw_value = strdup(value);
354                 cur->options = NULL;
355                 cur->next = NULL;
356
357                 if (type == WITHOUT_PARSING_OPTION) {
358                         cur->value = strdup(value);
359                         cur->options = NULL;
360                 } else {
361                         __parsing_raw_value(cur);
362                 }
363
364                 if (pre)
365                         pre->next = cur;
366                 else
367                         *head = cur;
368         } else {
369                 DA_LOG_ERR(HTTPManager, "DA_ERR_FAIL_TO_MEMALLOC");
370                 return DA_ERR_FAIL_TO_MEMALLOC;
371         }
372
373         return DA_RESULT_OK;
374 }
375
376 void __http_header_destroy_all_field(http_header_t **head)
377 {
378         http_header_t *pre = NULL;
379         http_header_t *cur = NULL;
380
381         //      DA_LOG_FUNC_START(HTTPManager);
382
383         cur = *head;
384
385         while (cur) {
386                 if (cur->field) {
387                         DA_LOG_VERBOSE(HTTPManager, "field= %s", cur->field);
388                         free(cur->field);
389                         cur->field = DA_NULL;
390                 }
391
392                 if (cur->value) {
393                         free(cur->value);
394                         cur->value = DA_NULL;
395                 }
396
397                 if (cur->raw_value) {
398                         free(cur->raw_value);
399                         cur->raw_value = DA_NULL;
400                 }
401
402                 __http_header_destroy_all_option(&(cur->options));
403
404                 pre = cur;
405                 cur = cur->next;
406
407                 free(pre);
408         }
409
410         *head = DA_NULL;
411 }
412
413 http_header_options_t *__create_http_header_option(const char *field,
414         const char *value)
415 {
416         http_header_options_t *option = NULL;
417
418         option = (http_header_options_t *)calloc(1,
419                 sizeof(http_header_options_t));
420         if (option) {
421                 if (field)
422                         option->field = strdup(field);
423
424                 if (value)
425                         option->value = strdup(value);
426
427                 option->next = NULL;
428         }
429
430         return option;
431 }
432
433 void __http_header_destroy_all_option(http_header_options_t **head)
434 {
435         http_header_options_t *pre = NULL;
436         http_header_options_t *cur = NULL;
437
438         //      DA_LOG_FUNC_START(HTTPManager);
439
440         cur = *head;
441
442         while (cur) {
443                 if (cur->field) {
444                         DA_LOG_VERBOSE(HTTPManager, "field= %s", cur->field);
445                         free(cur->field);
446                         cur->field = DA_NULL;
447                 }
448
449                 if (cur->value) {
450                         free(cur->value);
451                         cur->value = DA_NULL;
452                 }
453
454                 pre = cur;
455                 cur = cur->next;
456
457                 free(pre);
458         }
459
460         *head = DA_NULL;
461 }
462
463 da_result_t http_msg_request_get_iter(http_msg_request_t *http_msg_request,
464         http_msg_iter_t *http_msg_iter)
465 {
466         DA_LOG_FUNC_START(HTTPManager);
467
468         if (!http_msg_request) {
469                 DA_LOG_ERR(HTTPManager, "DA_ERR_INVALID_ARGUMENT");
470                 return DA_ERR_INVALID_ARGUMENT;
471         }
472
473         *http_msg_iter = http_msg_request->head;
474
475         return DA_RESULT_OK;
476 }
477
478 da_result_t http_msg_response_get_iter(http_msg_response_t *http_msg_response,
479         http_msg_iter_t *http_msg_iter)
480 {
481         //      DA_LOG_FUNC_START(HTTPManager);
482
483         if (!http_msg_response) {
484                 DA_LOG_ERR(HTTPManager, "DA_ERR_INVALID_ARGUMENT");
485                 return DA_ERR_INVALID_ARGUMENT;
486         }
487
488         *http_msg_iter = http_msg_response->head;
489         //      DA_LOG(HTTPManager, "retrieve iter = 0x%x", (unsigned int)http_msg_iter);
490
491         return DA_RESULT_OK;
492 }
493
494 da_bool_t http_msg_get_field_with_iter(http_msg_iter_t *http_msg_iter,
495         char **out_field, char **out_value)
496 {
497         http_header_t *cur = *http_msg_iter;
498
499         //      DA_LOG_FUNC_START(HTTPManager);
500
501         //      DA_LOG(HTTPManager, "getting iter = 0x%x", (unsigned int)cur);
502
503         if (cur) {
504                 *out_field = cur->field;
505                 *out_value = cur->value;
506                 *http_msg_iter = cur->next;
507
508                 return DA_TRUE;
509         } else {
510                 //              DA_LOG(HTTPManager, "end of iter");
511                 return DA_FALSE;
512         }
513 }
514
515 da_bool_t http_msg_get_header_with_iter(http_msg_iter_t *http_msg_iter,
516         char **out_field, http_header_t **out_header)
517 {
518         http_header_t *cur = *http_msg_iter;
519
520         //      DA_LOG_FUNC_START(HTTPManager);
521
522         //      DA_LOG(HTTPManager, "getting iter = 0x%x", (unsigned int)cur);
523
524         if (cur) {
525                 *out_field = cur->field;
526                 *out_header = cur;
527                 *http_msg_iter = cur->next;
528
529                 return DA_TRUE;
530         } else {
531                 //              DA_LOG(HTTPManager, "end of iter");
532                 return DA_FALSE;
533         }
534 }
535
536 http_header_options_t *__parsing_N_create_option_str(char *org_str)
537 {
538         char *option_field = NULL;
539         char *option_value = NULL;
540         int option_field_len = 0;
541         int option_value_len = 0;
542
543         char *org_pos = NULL;
544         int org_str_len = 0;
545
546         char *working_str = NULL;
547         char *working_pos = NULL;
548         char *working_pos_field_start = NULL;
549         char *working_pos_value_start = NULL;
550
551         da_bool_t is_inside_quotation = DA_FALSE;
552         da_bool_t is_working_for_field = DA_TRUE;
553         int i = 0;
554         http_header_options_t *option = NULL;
555
556         //      DA_LOG_FUNC_START(HTTPManager);
557
558         if (!org_str)
559                 return NULL;
560
561         org_str_len = strlen(org_str);
562         if (org_str_len <= 0)
563                 return NULL;
564
565         working_str = (char *)calloc(1, org_str_len + 1);
566         if (!working_str)
567                 return NULL;
568
569         org_pos = org_str;
570         working_pos_field_start = working_pos = working_str;
571
572         for (i = 0; i < org_str_len; i++) {
573                 if (*org_pos == '"')
574                         is_inside_quotation = !is_inside_quotation;
575
576                 if (is_inside_quotation) {
577                         // Leave anything including blank if it is inside of double quotation mark.
578                         *working_pos = *org_pos;
579                         is_working_for_field ? option_field_len++
580                                 : option_value_len++;
581                         working_pos++;
582                         org_pos++;
583                 } else {
584                         if (*org_pos == ' ') {
585                                 org_pos++;
586                         } else if (*org_pos == '=') {
587                                 if (is_working_for_field) {
588                                         is_working_for_field = DA_FALSE;
589                                         working_pos_value_start = working_pos;
590                                 }
591
592                                 org_pos++;
593                         } else {
594                                 *working_pos = *org_pos;
595                                 is_working_for_field ? option_field_len++
596                                         : option_value_len++;
597                                 working_pos++;
598                                 org_pos++;
599                         }
600                 }
601         }
602
603         if (option_field_len > 0 && working_pos_field_start) {
604                 option_field = (char *)calloc(1, option_field_len + 1);
605                 if (option_field)
606                         strncpy(option_field, working_pos_field_start,
607                                 option_field_len);
608         }
609
610         if (option_value_len > 0 && working_pos_value_start) {
611                 option_value = (char *)calloc(1, option_value_len + 1);
612                 if (option_value)
613                         strncpy(option_value, working_pos_value_start,
614                                 option_value_len);
615         }
616
617         if (working_str) {
618                 free(working_str);
619                 working_pos = working_str = NULL;
620         }
621
622         DA_LOG(HTTPManager, "option_field = [%s], option_value = [%s]",
623                 option_field, option_value);
624
625         if (option_field || option_value) {
626                 option = __create_http_header_option(
627                         option_field, option_value);
628                 if (option_field) {
629                         free(option_field);
630                         option_field = NULL;
631                 }
632
633                 if (option_value) {
634                         free(option_value);
635                         option_value = NULL;
636                 }
637         }
638         return option;
639 }
640
641 http_header_options_t *__parsing_options(char *org_str)
642 {
643         da_result_t ret = DA_RESULT_OK;
644         http_header_options_t *head = NULL;
645         http_header_options_t *pre = NULL;
646         http_header_options_t *cur = NULL;
647
648         int wanted_str_len = 0;
649         char *wanted_str = NULL;
650         char *wanted_str_start = NULL;
651         char *wanted_str_end = NULL;
652         char *cur_pos = NULL;
653
654         DA_LOG_FUNC_START(HTTPManager);
655
656         if (!org_str)
657                 return NULL;
658
659         /* Do Not use strtok(). It's not thread safe. */
660         //      DA_LOG_CRITICAL(HTTPManager, "org_str = %s", org_str);
661
662         cur_pos = org_str;
663
664         while (cur_pos) {
665                 wanted_str_start = cur_pos;
666                 wanted_str_end = strchr(cur_pos, ';');
667                 if (wanted_str_end) {
668                         cur_pos = wanted_str_end + 1;
669                 } else {
670                         wanted_str_end = org_str + strlen(org_str);
671                         cur_pos = NULL;
672                 }
673
674                 wanted_str_len = wanted_str_end - wanted_str_start;
675                 wanted_str = (char *)calloc(1, wanted_str_len + 1);
676                 if (!wanted_str) {
677                         DA_LOG_ERR(HTTPManager, "DA_ERR_FAIL_TO_MEMALLOC");
678                         ret = DA_ERR_FAIL_TO_MEMALLOC;
679                         goto ERR;
680                 }
681                 strncpy(wanted_str, wanted_str_start, wanted_str_len);
682
683                 //              DA_LOG_CRITICAL(HTTPManager, "wanted_str = [%s]", wanted_str);
684                 cur = __parsing_N_create_option_str(wanted_str);
685                 if (pre) {
686                         pre->next = cur;
687                         pre = cur;
688                 } else {
689                         head = pre = cur;
690                 }
691
692                 free(wanted_str);
693                 wanted_str = NULL;
694         }
695
696 ERR:
697         if (ret != DA_RESULT_OK)
698                 __http_header_destroy_all_option(&head);
699
700         return head;
701 }
702
703 void __parsing_raw_value(http_header_t *http_header_field)
704 {
705         char *raw_value = NULL;
706         char *option_str_start = NULL;
707
708         char *trimed_value = NULL;
709         int trimed_value_len = 0;
710
711         char *trimed_value_start = NULL;
712         char *trimed_value_end = NULL;
713
714         //      DA_LOG_FUNC_START(HTTPManager);
715
716         raw_value = http_header_field->raw_value;
717         //      DA_LOG_CRITICAL(HTTPManager, "raw_value = [%s]", raw_value);
718
719         if (!raw_value)
720                 return;
721
722         trimed_value_start = raw_value;
723
724         trimed_value_end = strchr(raw_value, ';');
725         if (!trimed_value_end) {
726                 // No options
727                 http_header_field->value = strdup(raw_value);
728                 http_header_field->options = NULL;
729
730                 return;
731         }
732
733         // for trimed value
734         trimed_value_len = trimed_value_end - trimed_value_start;
735
736         trimed_value = (char *)calloc(1, trimed_value_len + 1);
737         if (!trimed_value) {
738                 DA_LOG_ERR(HTTPManager, "DA_ERR_FAIL_TO_MEMALLOC");
739                 return;
740         }
741         strncpy(trimed_value, trimed_value_start, trimed_value_len);
742         http_header_field->value = trimed_value;
743
744         // for option parsing
745         option_str_start = trimed_value_end + 1;
746
747         http_header_field->options = __parsing_options(option_str_start);
748
749         /////////////// show
750         http_header_options_t *cur = NULL;
751
752         cur = http_header_field->options;
753         while (cur) {
754                 DA_LOG(HTTPManager, "field = [%s], value = [%s]", cur->field, cur->value);
755                 cur = cur->next;
756         }
757
758 }
759
760 da_bool_t __get_http_header_option_for_field(
761         http_header_options_t *header_option, const char *in_field,
762         char **out_value)
763 {
764         http_header_options_t *cur = NULL;
765
766         //      DA_LOG_FUNC_START(HTTPManager);
767
768         if (!header_option) {
769                 DA_LOG_ERR(HTTPManager, "input header_option is NULL.");
770                 return DA_FALSE;
771         }
772
773         cur = header_option;
774         while (cur) {
775                 if (cur->field) {
776                         if (!strncmp(cur->field, in_field, strlen(cur->field)) &&
777                                         cur->value) {
778                                 DA_LOG(HTTPManager, "[%s][%s]", cur->field, cur->value);
779                                 *out_value = cur->value;
780                                 return DA_TRUE;
781                         }
782
783                 }
784                 cur = cur->next;
785         }
786
787         return DA_FALSE;
788 }
789
790 da_bool_t __get_http_header_for_field(http_msg_response_t *http_msg_response,
791         const char *in_field, http_header_t **out_header)
792 {
793         http_msg_iter_t http_msg_iter;
794         http_header_t *header = NULL;
795         char *field = NULL;
796
797         //DA_LOG_FUNC_START(HTTPManager);
798
799         http_msg_response_get_iter(http_msg_response, &http_msg_iter);
800         while (http_msg_get_header_with_iter(&http_msg_iter, &field, &header)) {
801                 if (field && header && !strncmp(field, in_field, strlen(field))) {
802                         DA_LOG_VERBOSE(HTTPManager, "[%s][%s]", field, header->value);
803                         *out_header = header;
804                         return DA_TRUE;
805                 }
806         }
807
808         return DA_FALSE;
809 }
810
811 void __exchange_header_value(http_header_t *header, const char *in_raw_value)
812 {
813         DA_LOG_FUNC_START(HTTPManager);
814
815         if (!header || !in_raw_value)
816                 return;
817
818         __http_header_destroy_all_option(&(header->options));
819
820         if (header->value) {
821                 free(header->value);
822                 header->value = DA_NULL;
823         }
824
825         if (header->raw_value)
826                 free(header->raw_value);
827         header->raw_value = strdup(in_raw_value);
828
829         __parsing_raw_value(header);
830 }
831
832 da_bool_t http_msg_response_get_content_type(
833         http_msg_response_t *http_msg_response, char **out_type)
834 {
835         da_bool_t b_ret = DA_FALSE;
836         http_header_t *header = NULL;
837
838         DA_LOG_FUNC_START(HTTPManager);
839
840         b_ret = __get_http_header_for_field(http_msg_response, "Content-Type",
841                 &header);
842         if (!b_ret) {
843                 DA_LOG(HTTPManager, "no Content-Type");
844                 return DA_FALSE;
845         }
846
847         if (out_type)
848                 *out_type = strdup(header->value);
849
850         return DA_TRUE;
851 }
852
853 void http_msg_response_set_content_type(http_msg_response_t *http_msg_response,
854         const char *in_type)
855 {
856         da_bool_t b_ret = DA_FALSE;
857         http_header_t *header = NULL;
858
859         DA_LOG_FUNC_START(HTTPManager);
860
861         if (!http_msg_response || !in_type)
862                 return;
863
864         b_ret = __get_http_header_for_field(http_msg_response, "Content-Type",
865                 &header);
866         if (b_ret) {
867                 if (header->raw_value && (!strncmp(header->raw_value, in_type,
868                         strlen(header->raw_value))))
869                         return;
870
871                 DA_LOG(HTTPManager, "exchange Content-Type to [%s] from [%s]", in_type, header->value);
872                 __exchange_header_value(header, in_type);
873         } else {
874                 __http_header_add_field(&(http_msg_response->head),
875                         "Content-Type", in_type, WITH_PARSING_OPTION);
876         }
877 }
878
879 da_bool_t http_msg_response_get_content_length(
880         http_msg_response_t *http_msg_response, unsigned long long *out_length)
881 {
882         da_bool_t b_ret = DA_FALSE;
883         http_header_t *header = NULL;
884
885         DA_LOG_FUNC_START(HTTPManager);
886
887         b_ret = __get_http_header_for_field(http_msg_response,
888                 "Content-Length", &header);
889         if (!b_ret) {
890                 DA_LOG(HTTPManager, "no Content-Length");
891                 return DA_FALSE;
892         }
893
894         if (out_length)
895                 *out_length = atoll(header->value);
896
897         return DA_TRUE;
898 }
899
900 da_bool_t http_msg_response_get_content_disposition(
901         http_msg_response_t *http_msg_response, char **out_disposition,
902         char **out_file_name)
903 {
904         da_bool_t b_ret = DA_FALSE;
905         http_header_t *header = NULL;
906         char *file_name = NULL;
907
908         char *wanted_str = NULL;
909         char *wanted_str_start = NULL;
910         char *wanted_str_end = NULL;
911         char *decoded_str = NULL;
912         int wanted_str_len = 0;
913
914         DA_LOG_FUNC_START(HTTPManager);
915
916         b_ret = __get_http_header_for_field(http_msg_response,
917                 "Content-Disposition", &header);
918         if (!b_ret) {
919                 DA_LOG(HTTPManager, "no Content-Disposition");
920                 return DA_FALSE;
921         }
922
923         if (out_disposition)
924                 *out_disposition = strdup(header->value);
925
926         if (!out_file_name)
927                 return DA_FALSE;
928
929         b_ret = __get_http_header_option_for_field(header->options, "filename",
930                 &file_name);
931         if (!b_ret) {
932                 DA_LOG(HTTPManager, "no option");
933                 return DA_FALSE;
934         }
935
936         // eliminate double quotation mark if it exists on derived value
937         wanted_str_start = strchr(file_name, '"');
938         if (!wanted_str_start) {
939                 *out_file_name = strdup(file_name);
940                 return DA_TRUE;
941         } else {
942                 //              DA_LOG(HTTPManager, "wanted_str_start = [%s]", wanted_str_start);
943                 wanted_str_start++;
944                 wanted_str_end = strchr(wanted_str_start, '"');
945                 if (wanted_str_end) {
946                         wanted_str_len = wanted_str_end - wanted_str_start;
947                         wanted_str = (char*)calloc(1, wanted_str_len + 1);
948                         if (!wanted_str) {
949                                 DA_LOG_ERR(HTTPManager, "DA_ERR_FAIL_TO_MEMALLOC");
950                                 return DA_FALSE;
951                         }
952                         strncpy(wanted_str, wanted_str_start, wanted_str_len);
953
954                         b_ret = is_base64_encoded_word(wanted_str);
955                         if (b_ret) {
956                                 DA_LOG(HTTPManager, "It's base64 encoded-word string");
957                                 if (DA_RESULT_OK == decode_base64_encoded_str(
958                                         wanted_str, &decoded_str)) {
959                                         DA_LOG(HTTPManager, "base64 decoded str = [%s]", decoded_str);
960                                         free(wanted_str);
961                                         wanted_str = decoded_str;
962                                         decoded_str = NULL;
963                                 } else {
964                                         DA_LOG(HTTPManager, "Fail to base64 decode. Just use un-decoded string.");
965                                 }
966                         } else {
967                                 DA_LOG(HTTPManager, "It's NOT base64 encoded-word string");
968                         }
969                         decode_url_encoded_str(wanted_str, &decoded_str);
970                         /* If it is url encoded string */
971                         if (decoded_str) {
972                                 DA_LOG(HTTPManager, "Url decoded str = [%s]", decoded_str);
973                                 free(wanted_str);
974                                 wanted_str = decoded_str;
975                                 decoded_str = NULL;
976                         }
977
978                         *out_file_name = wanted_str;
979
980                         DA_LOG(HTTPManager, "out_file_name = [%s]", *out_file_name);
981
982                         return DA_TRUE;
983                 } else {
984                         DA_LOG_ERR(HTTPManager, "Not matched \" !");
985                         return DA_FALSE;
986                 }
987         }
988 }
989
990 da_bool_t http_msg_response_get_ETag(http_msg_response_t *http_msg_response,
991         char **out_value)
992 {
993         da_bool_t b_ret = DA_FALSE;
994         http_header_t *header = NULL;
995
996         DA_LOG_FUNC_START(HTTPManager);
997
998         b_ret = __get_http_header_for_field(http_msg_response, "ETag", &header);
999         if (!b_ret) {
1000                 DA_LOG(HTTPManager, "no ETag");
1001                 return DA_FALSE;
1002         }
1003
1004         if (out_value)
1005                 *out_value = strdup(header->value);
1006
1007         return DA_TRUE;
1008 }
1009
1010 da_bool_t http_msg_response_get_date(http_msg_response_t *http_msg_response,
1011         char **out_value)
1012 {
1013         da_bool_t b_ret = DA_FALSE;
1014         http_header_t *header = NULL;
1015
1016         DA_LOG_FUNC_START(HTTPManager);
1017
1018         b_ret = __get_http_header_for_field(http_msg_response, "Date", &header);
1019         if (!b_ret) {
1020                 DA_LOG(HTTPManager, "no Date");
1021                 return DA_FALSE;
1022         }
1023
1024         if (out_value)
1025                 *out_value = strdup(header->value);
1026
1027         return DA_TRUE;
1028 }
1029
1030 da_bool_t http_msg_response_get_location(http_msg_response_t *http_msg_response,
1031         char **out_value)
1032 {
1033         da_bool_t b_ret = DA_FALSE;
1034         http_header_t *header = NULL;
1035
1036         DA_LOG_FUNC_START(HTTPManager);
1037
1038         b_ret = __get_http_header_for_field(http_msg_response, "Location", &header);
1039         if (!b_ret) {
1040                 DA_LOG(HTTPManager, "no Location");
1041                 return DA_FALSE;
1042         }
1043         if (out_value)
1044                 *out_value = strdup(header->value);
1045
1046         return DA_TRUE;
1047 }
1048
1049 da_result_t http_msg_response_get_boundary(
1050         http_msg_response_t *http_msg_response, char **out_val)
1051 {
1052         da_result_t ret = DA_RESULT_OK;
1053
1054         http_msg_iter_t http_msg_iter;
1055         char *field = NULL;
1056         char *value = NULL;
1057         char *boundary = NULL;
1058
1059         DA_LOG_FUNC_START(HTTPManager);
1060
1061         if (!http_msg_response) {
1062                 DA_LOG_ERR(HTTPManager, "DA_ERR_INVALID_ARGUMENT");
1063                 return DA_ERR_INVALID_ARGUMENT;
1064         }
1065
1066         http_msg_response_get_iter(http_msg_response, &http_msg_iter);
1067         while (http_msg_get_field_with_iter(&http_msg_iter, &field, &value)) {
1068                 if ((field != DA_NULL) && (value != DA_NULL)) {
1069                         if (!strncmp(field, "Content-Type",
1070                                 strlen("Content-Type"))) {
1071                                 char *org_str = NULL;
1072                                 char *boundary_str_start = NULL;
1073                                 char *boundary_value_start = NULL;
1074                                 char *boundary_value_end = NULL;
1075                                 int boundary_value_len = 0;
1076
1077                                 org_str = value;
1078
1079                                 boundary_str_start
1080                                         = strstr(org_str, "boundary");
1081                                 if (boundary_str_start) {
1082                                         DA_LOG(HTTPManager, "boundary_str_start = %s", boundary_str_start);
1083                                         // this "Content-Type" value has "boundary" in it, so get the value
1084                                         boundary_value_start = strchr(
1085                                                 boundary_str_start, '"');
1086                                         boundary_value_start += 1; // start without "
1087
1088                                         boundary_value_end = strchr(
1089                                                 boundary_value_start, '"');
1090                                         boundary_value_len = boundary_value_end
1091                                                 - boundary_value_start;
1092
1093                                         DA_LOG(HTTPManager, "boundary_value_start = %s", boundary_value_start);
1094                                         DA_LOG(HTTPManager, "boundary_value_end = %s", boundary_value_end);
1095                                         DA_LOG(HTTPManager, "boundary_value_len = %d", boundary_value_len);
1096
1097                                 } else {
1098                                         // no "boundary" field on this "Content-Type" value
1099                                         ret = DA_ERR_INVALID_ARGUMENT;
1100                                         goto ERR;
1101                                 }
1102                                 // end of clear
1103
1104                                 boundary = (char *)calloc(1,
1105                                         boundary_value_len + 1);
1106                                 if (!boundary) {
1107                                         DA_LOG_ERR(HTTPManager, "DA_ERR_FAIL_TO_MEMALLOC");
1108                                         ret = DA_ERR_FAIL_TO_MEMALLOC;
1109
1110                                         goto ERR;
1111                                 }
1112                                 strncpy(boundary, boundary_value_start,
1113                                         boundary_value_len);
1114                                 DA_LOG(HTTPManager, "[boundary][%s]", boundary);
1115                                 break;
1116                         }
1117                 }
1118         }
1119
1120         *out_val = boundary;
1121
1122 ERR:
1123         return ret;
1124 }
1125
1126 char *get_http_response_header_raw(http_msg_response_t *http_msg_response)
1127 {
1128         http_msg_iter_t http_msg_iter;
1129         http_header_t *header = NULL;
1130         char *field = NULL;
1131         char tmp_buf[1024*4] = {0,};
1132         char line_buf[1024] = {0,};
1133         int len = 0;
1134         char *buff = NULL;
1135
1136         DA_LOG_FUNC_START(HTTPManager);
1137
1138         http_msg_response_get_iter(http_msg_response, &http_msg_iter);
1139         while (http_msg_get_header_with_iter(&http_msg_iter, &field, &header)) {
1140                 if (field && header) {
1141                         // FIXME later :: buffer length is more than total length. think about getting header's conent length from libsoup
1142                         len = strlen(field) + strlen(header->value) + 2;
1143                         snprintf(line_buf, len,"%s:%s", field, header->value);
1144                         strncat(tmp_buf, line_buf, len);
1145                         strcat(tmp_buf, "\n");
1146                 }
1147         }
1148         if (strlen(tmp_buf) > 0) {
1149                 buff = (char *)calloc(1, strlen(tmp_buf) + 1);
1150                 if (buff == DA_NULL) {
1151                         DA_LOG_ERR(HTTPManager, "DA_ERR_FAIL_TO_MEMALLOC");
1152                         return DA_NULL;
1153                 }
1154                 memcpy(buff, tmp_buf, strlen(tmp_buf));
1155                 DA_LOG(HTTPManager, "\n---raw response header---\n%s\n------\n",buff);
1156                 return buff;
1157         } else {
1158                 return DA_NULL;
1159         }
1160 }
1161
1162 char *_stristr(const char *long_str, const char *find_str)
1163 {
1164         int i = 0;
1165         int length_long = 0;
1166         int length_find = 0;
1167         char *ret_ptr = NULL;
1168         char *org_ptr = NULL;
1169         char *look_ptr = NULL;
1170
1171         if (long_str == NULL || find_str == NULL) {
1172                 DA_LOG_ERR(Default,"INVALID ARGUMENT");
1173                 return NULL;
1174         }
1175
1176         length_long = strlen(long_str);
1177         length_find = strlen(find_str);
1178
1179         org_ptr = (char*)calloc(1, length_long + 1);
1180
1181         if (org_ptr == NULL) {
1182                 DA_LOG_ERR(Default,"INVALID ARGUMENT");
1183                 return NULL;
1184         }
1185
1186         look_ptr = (char*)calloc(1, length_find + 1);
1187
1188         if (look_ptr == NULL) {
1189                 DA_LOG_ERR(Default,"INVALID ARGUMENT");
1190                 free(org_ptr);
1191                 return NULL;
1192         }
1193
1194         while (i < length_long) {
1195                 if (isalpha(long_str[i]) != 0) {
1196                         if (isupper(long_str[i]) != 0) {
1197                                 org_ptr[i] = long_str[i];
1198                         } else {
1199                                 org_ptr[i] = toupper(long_str[i]);
1200                         }
1201                 } else {
1202                         org_ptr[i] = long_str[i];
1203                 }
1204
1205                 i++;
1206         }
1207
1208         i = 0;
1209
1210         while (i < length_find) {
1211                 if (isalpha(find_str[i]) != 0) {
1212                         if (isupper(find_str[i]) != 0) {
1213                                 look_ptr[i] = find_str[i];
1214                         } else {
1215                                 look_ptr[i] = toupper(find_str[i]);
1216                         }
1217                 } else {
1218                         look_ptr[i] = find_str[i];
1219                 }
1220
1221                 i++;
1222         }
1223
1224         ret_ptr = strstr(org_ptr, look_ptr);
1225
1226         if (ret_ptr == 0) {
1227                 free(org_ptr);
1228                 free(look_ptr);
1229                 return NULL;
1230         } else {
1231                 i = ret_ptr - org_ptr;
1232         }
1233
1234         free(org_ptr);
1235         free(look_ptr);
1236
1237         return (char*)(long_str + i);
1238 }
1239
1240 /* This is not used. But it can be needed if there is no http header parser at http library.*/
1241 da_bool_t extract_attribute_from_header(
1242         char *szHeadStr,
1243         const char *szFindStr,
1244         char **ppRtnValue)
1245 {
1246
1247         char *pValuePos = NULL;
1248         int index = 0;
1249         int startPos = 0;
1250         int strLen = 0;
1251         int need_to_end_quataion_mark = 0;
1252
1253         if (szHeadStr == DA_NULL || szFindStr == DA_NULL) {
1254                 DA_LOG_ERR(Default,"INVALID ARGUMENT");
1255                 return DA_FALSE;
1256         }
1257
1258         if (strlen(szHeadStr) <= 0 || strlen(szFindStr) <= 0) {
1259                 DA_LOG_ERR(Default,"INVALID ARGUMENT");;
1260
1261                 return DA_FALSE;
1262         }
1263
1264         if (ppRtnValue == NULL) {
1265                 return DA_FALSE;
1266         }
1267
1268         pValuePos = _stristr(szHeadStr, (char*)szFindStr);
1269         if (pValuePos == NULL) {
1270                 *ppRtnValue = NULL;
1271                 goto ERR;
1272         }
1273
1274         index = strlen(szFindStr);
1275
1276         while (pValuePos[index] != ':' && pValuePos[index] != '=') {
1277                 index++;
1278
1279                 if (pValuePos[index] == '\0') {
1280                         return DA_FALSE;
1281                 }
1282         }
1283
1284         index++;
1285
1286         /* jump space */
1287         while (pValuePos[index] == ' ') {
1288                 index++;
1289         }
1290
1291         /* jump quatation mark */
1292         while (pValuePos[index] == '"') {
1293                 need_to_end_quataion_mark = 1;
1294                 index++;
1295         }
1296
1297         startPos = index;
1298
1299         /* Find the end of data. */
1300         if (0 == strcmp(szFindStr, "Location"))//terminate character list does not contain ';' in case of URI
1301         {
1302                 while (DA_FALSE == IS_URI_TERMINATING_CHAR(pValuePos[index])) {
1303                         index++;
1304                 }
1305         } else if (need_to_end_quataion_mark) {
1306                 while (DA_FALSE == IS_TERMINATING_CHAR_EX(pValuePos[index])) {
1307                         index++;
1308                 }
1309         } else {
1310                 while (DA_FALSE == IS_TERMINATING_CHAR(pValuePos[index])) {
1311                         index++;
1312                 }
1313         }
1314
1315         strLen = index - startPos;
1316
1317         if (strLen < 1) {
1318                 DA_LOG_ERR(Default," strLen is < 1");
1319                 goto ERR;
1320         }
1321
1322         *ppRtnValue = (char*)calloc(1, sizeof(char) * (strLen + 1));
1323
1324         if (*ppRtnValue == NULL) {
1325                 DA_LOG_ERR(Default," *ppRtnValue is NULL");
1326                 goto ERR;
1327         }
1328
1329         strncpy(*ppRtnValue, pValuePos + startPos, strLen);
1330         *(*ppRtnValue + strLen) = '\0';
1331
1332         return DA_TRUE;
1333
1334 ERR:
1335
1336         if (*ppRtnValue) {
1337                 free(*ppRtnValue);
1338                 *ppRtnValue = NULL;
1339         }
1340
1341         return DA_FALSE;
1342 }
1343