refactoring download-provider alloc/free
[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 #include <curl/curl.h>
21
22 #include "download-agent-http-msg-handler.h"
23 #include "download-agent-debug.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_ret_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 static http_header_options_t *__create_http_header_option(const char *field,
45         const char *value);
46 static void __http_header_destroy_all_option(http_header_options_t **head);
47 static da_bool_t __get_http_header_option_for_field(
48         http_header_options_t *header_option, const char *in_field,
49         char **out_value);
50 static http_header_options_t *__parsing_N_create_option_str(char *org_str);
51 static http_header_options_t *__parsing_options(char *org_str);
52 static void __parsing_raw_value(http_header_t *http_header);
53
54 da_ret_t http_msg_request_create(http_msg_request_t **http_msg_request)
55 {
56         http_msg_request_t *temp_http_msg_request = NULL;
57
58 //      DA_LOGV("");
59
60         temp_http_msg_request = (http_msg_request_t *)calloc(1,
61                 sizeof(http_msg_request_t));
62         if (!temp_http_msg_request) {
63                 *http_msg_request = NULL;
64                 DA_LOGE("DA_ERR_FAIL_TO_MEMALLOC");
65                 return DA_ERR_FAIL_TO_MEMALLOC;
66         }
67
68         temp_http_msg_request->http_method = NULL;
69         temp_http_msg_request->url = NULL;
70         temp_http_msg_request->head = NULL;
71         temp_http_msg_request->http_body = NULL;
72
73         *http_msg_request = temp_http_msg_request;
74         DA_LOGV( "http_msg_request: %x", (unsigned int)(*http_msg_request));
75
76         return DA_RESULT_OK;
77 }
78
79 void http_msg_request_destroy(http_msg_request_t **http_msg_request)
80 {
81         http_msg_request_t *temp_http_msg_request = *http_msg_request;
82
83         DA_LOGV("");
84
85         if (temp_http_msg_request) {
86                 if (temp_http_msg_request->http_method) {
87                         free(temp_http_msg_request->http_method);
88                         temp_http_msg_request->http_method = NULL;
89                 }
90                 if (temp_http_msg_request->url) {
91                         free(temp_http_msg_request->url);
92                         temp_http_msg_request->url = NULL;
93                 }
94                 if (temp_http_msg_request->http_body) {
95                         free(temp_http_msg_request->http_body);
96                         temp_http_msg_request->http_body = NULL;
97                 }
98                 __http_header_destroy_all_field(&(temp_http_msg_request->head));
99                 free(*http_msg_request);
100                 *http_msg_request = NULL;
101         }
102 }
103
104 da_ret_t http_msg_request_set_url(http_msg_request_t *http_msg_request,
105         const char *url)
106 {
107         DA_LOGV("");
108
109         if (!http_msg_request) {
110                 DA_LOGE("http_msg_request is NULL; DA_ERR_INVALID_ARGUMENT");
111                 return DA_ERR_INVALID_ARGUMENT;
112         }
113
114         if (!url) {
115                 DA_LOGE("url is NULL; DA_ERR_INVALID_ARGUMENT");
116                 return DA_ERR_INVALID_URL;
117         }
118
119         http_msg_request->url = strdup(url);
120         DA_SECURE_LOGI("http url[%s]", http_msg_request->url);
121         return DA_RESULT_OK;
122 }
123
124 da_ret_t http_msg_request_get_url(http_msg_request_t *http_msg_request,
125         const char **url)
126 {
127         DA_LOGV("");
128
129         if (!http_msg_request) {
130                 DA_LOGE("http_msg_request is NULL; DA_ERR_INVALID_ARGUMENT");
131                 return DA_ERR_INVALID_ARGUMENT;
132         }
133
134         if (http_msg_request->url) {
135                 *url = http_msg_request->url;
136                 return DA_RESULT_OK;
137         } else {
138                 *url = DA_NULL;
139                 return DA_ERR_INVALID_ARGUMENT;
140         }
141 }
142
143 da_ret_t http_msg_request_add_field(http_msg_request_t *http_msg_request,
144         const char *field, const char *value)
145 {
146         //      DA_LOGV("");
147
148         if (!http_msg_request) {
149                 DA_LOGE("Check NULL! : http_msg_request");
150                 return DA_ERR_INVALID_ARGUMENT;
151         }
152
153         return __http_header_add_field(&(http_msg_request->head), field, value, WITHOUT_PARSING_OPTION);
154 }
155
156 da_ret_t http_msg_response_create(http_msg_response_t **http_msg_response)
157 {
158         http_msg_response_t *temp_http_msg_response = NULL;
159
160         DA_LOGV("");
161
162         temp_http_msg_response = (http_msg_response_t *)calloc(1,
163                 sizeof(http_msg_response_t));
164         if (!temp_http_msg_response) {
165                 DA_LOGE("DA_ERR_FAIL_TO_MEMALLOC");
166                 return DA_ERR_FAIL_TO_MEMALLOC;
167         } else {
168                 temp_http_msg_response->status_code = 0;
169                 temp_http_msg_response->head = NULL;
170                 *http_msg_response = temp_http_msg_response;
171                 return DA_RESULT_OK;
172         }
173 }
174
175 void http_msg_response_destroy(http_msg_response_t **http_msg_response)
176 {
177         http_msg_response_t *temp_http_msg_response = *http_msg_response;
178
179         DA_LOGV("");
180         if (temp_http_msg_response) {
181                 __http_header_destroy_all_field(&(temp_http_msg_response->head));
182                 free(*http_msg_response);
183                 *http_msg_response = DA_NULL;
184         }
185 }
186
187 da_ret_t http_msg_response_add_field(http_msg_response_t *http_msg_response,
188         const char *field, const char *value)
189 {
190         DA_LOGV("");
191
192         if (!http_msg_response) {
193                 DA_LOGE("DA_ERR_INVALID_ARGUMENT");
194                 return DA_ERR_INVALID_ARGUMENT;
195         }
196         return __http_header_add_field(&(http_msg_response->head), field, value, WITH_PARSING_OPTION);
197 }
198
199 da_ret_t __http_header_add_field(http_header_t **head,
200         const char *field, const char *value, enum parsing_type type)
201 {
202         http_header_t *pre = NULL;
203         http_header_t *cur = NULL;
204
205         //DA_SECURE_LOGD("[%s][%s]", field, value);
206
207         pre = cur = *head;
208         while (cur) {
209                 pre = cur;
210                 /* Replace default value with user wanted value
211                  * Remove the value which is stored before and add a new value.
212                 */
213                 if (cur->field && cur->raw_value &&
214                                 strncasecmp(cur->field, field, strlen(field)) == 0) {
215                         DA_SECURE_LOGD("Remove value for replacement [%s][%s]", cur->field, cur->raw_value);
216                         if (cur->field) {
217                                 free(cur->field);
218                                 cur->field = NULL;
219                         }
220                         if (cur->raw_value) {
221                                 free(cur->raw_value);
222                                 cur->raw_value= NULL;
223                         }
224                 }
225                 cur = cur->next;
226         }
227
228         cur = (http_header_t *)calloc(1, sizeof(http_header_t));
229         if (cur) {
230                 cur->field = strdup(field);
231                 cur->raw_value = strdup(value);
232                 cur->options = NULL;
233                 cur->next = NULL;
234
235                 if (type == WITHOUT_PARSING_OPTION) {
236                         cur->value = strdup(value);
237                         cur->options = NULL;
238                 } else {
239                         __parsing_raw_value(cur);
240                 }
241
242                 if (pre)
243                         pre->next = cur;
244                 else
245                         *head = cur;
246         } else {
247                 DA_LOGE("DA_ERR_FAIL_TO_MEMALLOC");
248                 return DA_ERR_FAIL_TO_MEMALLOC;
249         }
250
251         return DA_RESULT_OK;
252 }
253
254 void __http_header_destroy_all_field(http_header_t **head)
255 {
256         http_header_t *pre = NULL;
257         http_header_t *cur = NULL;
258
259         cur = *head;
260
261         while (cur) {
262                 if (cur->field) {
263                         free(cur->field);
264                         cur->field = DA_NULL;
265                 }
266                 if (cur->value) {
267                         free(cur->value);
268                         cur->value = DA_NULL;
269                 }
270                 if (cur->raw_value) {
271                         free(cur->raw_value);
272                         cur->raw_value = DA_NULL;
273                 }
274                 __http_header_destroy_all_option(&(cur->options));
275                 free(cur->options);
276                 cur->options = DA_NULL;
277                 pre = cur;
278                 cur = cur->next;
279                 free(pre);
280         }
281         *head = DA_NULL;
282 }
283
284 http_header_options_t *__create_http_header_option(const char *field,
285         const char *value)
286 {
287         http_header_options_t *option = NULL;
288
289         option = (http_header_options_t *)calloc(1,
290                 sizeof(http_header_options_t));
291         if (option) {
292                 if (field)
293                         option->field = strdup(field);
294                 if (value)
295                         option->value = strdup(value);
296                 option->next = NULL;
297         }
298         return option;
299 }
300
301 void __http_header_destroy_all_option(http_header_options_t **head)
302 {
303         http_header_options_t *pre = NULL;
304         http_header_options_t *cur = NULL;
305
306         //      DA_LOGV("");
307
308         cur = *head;
309
310         while (cur) {
311                 if (cur->field) {
312                         DA_SECURE_LOGD("field= %s", cur->field);
313                         free(cur->field);
314                         cur->field = DA_NULL;
315                 }
316                 if (cur->value) {
317                         free(cur->value);
318                         cur->value = DA_NULL;
319                 }
320                 pre = cur;
321                 cur = cur->next;
322                 free(pre);
323         }
324         *head = DA_NULL;
325 }
326
327 da_ret_t http_msg_request_get_iter(http_msg_request_t *http_msg_request,
328         http_msg_iter_t *http_msg_iter)
329 {
330         DA_LOGV("");
331
332         if (!http_msg_request) {
333                 DA_LOGE("DA_ERR_INVALID_ARGUMENT");
334                 return DA_ERR_INVALID_ARGUMENT;
335         }
336
337         *http_msg_iter = http_msg_request->head;
338
339         return DA_RESULT_OK;
340 }
341
342 da_ret_t http_msg_response_get_iter(http_msg_response_t *http_msg_response,
343         http_msg_iter_t *http_msg_iter)
344 {
345         if (!http_msg_response) {
346                 DA_LOGE("DA_ERR_INVALID_ARGUMENT");
347                 return DA_ERR_INVALID_ARGUMENT;
348         }
349
350         *http_msg_iter = http_msg_response->head;
351         return DA_RESULT_OK;
352 }
353
354 da_bool_t http_msg_get_field_with_iter(http_msg_iter_t *http_msg_iter,
355         char **out_field, char **out_value)
356 {
357         http_header_t *cur = *http_msg_iter;
358
359         if (cur) {
360                 *out_field = cur->field;
361                 *out_value = cur->value;
362                 *http_msg_iter = cur->next;
363                 return DA_TRUE;
364         } else {
365                 return DA_FALSE;
366         }
367 }
368
369 da_bool_t http_msg_get_header_with_iter(http_msg_iter_t *http_msg_iter,
370         char **out_field, http_header_t **out_header)
371 {
372         http_header_t *cur = *http_msg_iter;
373
374         if (cur) {
375                 *out_field = cur->field;
376                 *out_header = cur;
377                 *http_msg_iter = cur->next;
378                 return DA_TRUE;
379         } else {
380                 return DA_FALSE;
381         }
382 }
383
384 http_header_options_t *__parsing_N_create_option_str(char *org_str)
385 {
386         char *option_field = NULL;
387         char *option_value = NULL;
388         int option_field_len = 0;
389         int option_value_len = 0;
390         char *org_pos = NULL;
391         int org_str_len = 0;
392         char *working_str = NULL;
393         char *working_pos = NULL;
394         char *working_pos_field_start = NULL;
395         char *working_pos_value_start = NULL;
396         da_bool_t is_inside_quotation = DA_FALSE;
397         da_bool_t is_working_for_field = DA_TRUE;
398         int i = 0;
399         http_header_options_t *option = NULL;
400
401         //      DA_LOGV("");
402
403         if (!org_str)
404                 return NULL;
405
406         org_str_len = strlen(org_str);
407         if (org_str_len <= 0)
408                 return NULL;
409
410         working_str = (char *)calloc(1, org_str_len + 1);
411         if (!working_str)
412                 return NULL;
413
414         org_pos = org_str;
415         working_pos_field_start = working_pos = working_str;
416
417         for (i = 0; i < org_str_len; i++) {
418                 if (*org_pos == '"')
419                         is_inside_quotation = !is_inside_quotation;
420                 if (is_inside_quotation) {
421                         // Leave anything including blank if it is inside of double quotation mark.
422                         *working_pos = *org_pos;
423                         is_working_for_field ? option_field_len++
424                                 : option_value_len++;
425                         working_pos++;
426                         org_pos++;
427                 } else {
428                         if (*org_pos == ' ') {
429                                 org_pos++;
430                         } else if (*org_pos == '=') {
431                                 if (is_working_for_field) {
432                                         is_working_for_field = DA_FALSE;
433                                         working_pos_value_start = working_pos;
434                                 }
435                                 org_pos++;
436                         } else {
437                                 *working_pos = *org_pos;
438                                 is_working_for_field ? option_field_len++
439                                         : option_value_len++;
440                                 working_pos++;
441                                 org_pos++;
442                         }
443                 }
444         }
445
446         if (option_field_len > 0 && working_pos_field_start) {
447                 option_field = (char *)calloc(1, option_field_len + 1);
448                 if (option_field)
449                         strncpy(option_field, working_pos_field_start,
450                                 option_field_len);
451         }
452         if (option_value_len > 0 && working_pos_value_start) {
453                 option_value = (char *)calloc(1, option_value_len + 1);
454                 if (option_value)
455                         strncpy(option_value, working_pos_value_start,
456                                 option_value_len);
457         }
458         if (working_str) {
459                 free(working_str);
460                 working_pos = working_str = NULL;
461         }
462
463         DA_SECURE_LOGD("option_field = [%s], option_value = [%s]",
464                 option_field, option_value);
465
466         if (option_field || option_value) {
467                 option = __create_http_header_option(
468                         option_field, option_value);
469                 if (option_field) {
470                         free(option_field);
471                         option_field = NULL;
472                 }
473                 if (option_value) {
474                         free(option_value);
475                         option_value = NULL;
476                 }
477         }
478         return option;
479 }
480
481 http_header_options_t *__parsing_options(char *org_str)
482 {
483         da_ret_t ret = DA_RESULT_OK;
484         http_header_options_t *head = NULL;
485         http_header_options_t *pre = NULL;
486         http_header_options_t *cur = NULL;
487
488         int wanted_str_len = 0;
489         char *wanted_str = NULL;
490         char *wanted_str_start = NULL;
491         char *wanted_str_end = NULL;
492         char *cur_pos = NULL;
493
494         DA_LOGV("");
495
496         if (!org_str)
497                 return NULL;
498
499         /* Do Not use strtok(). It's not thread safe. */
500         //      DA_SECURE_LOGD("org_str = %s", org_str);
501
502         cur_pos = org_str;
503
504         while (cur_pos) {
505                 wanted_str_start = cur_pos;
506                 wanted_str_end = strchr(cur_pos, ';');
507                 if (wanted_str_end) {
508                         cur_pos = wanted_str_end + 1;
509                 } else {
510                         wanted_str_end = org_str + strlen(org_str);
511                         cur_pos = NULL;
512                 }
513                 wanted_str_len = wanted_str_end - wanted_str_start;
514                 wanted_str = (char *)calloc(1, wanted_str_len + 1);
515                 if (!wanted_str) {
516                         DA_LOGE("DA_ERR_FAIL_TO_MEMALLOC");
517                         ret = DA_ERR_FAIL_TO_MEMALLOC;
518                         goto ERR;
519                 }
520                 strncpy(wanted_str, wanted_str_start, wanted_str_len);
521
522                 //              DA_SECURE_LOGD("wanted_str = [%s]", wanted_str);
523                 cur = __parsing_N_create_option_str(wanted_str);
524                 if (pre) {
525                         pre->next = cur;
526                         pre = cur;
527                 } else {
528                         head = pre = cur;
529                 }
530
531                 free(wanted_str);
532                 wanted_str = NULL;
533         }
534
535 ERR:
536         if (ret != DA_RESULT_OK)
537                 __http_header_destroy_all_option(&head);
538         return head;
539 }
540
541 void __parsing_raw_value(http_header_t *http_header_field)
542 {
543         char *raw_value = NULL;
544         char *option_str_start = NULL;
545         char *trimed_value = NULL;
546         int trimed_value_len = 0;
547         char *trimed_value_start = NULL;
548         char *trimed_value_end = NULL;
549
550         raw_value = http_header_field->raw_value;
551         //      DA_SECURE_LOGD("raw_value = [%s]", raw_value);
552
553         if (!raw_value)
554                 return;
555
556         trimed_value_start = raw_value;
557         trimed_value_end = strchr(raw_value, ';');
558         if (!trimed_value_end) {
559                 // No options
560                 http_header_field->value = strdup(raw_value);
561                 http_header_field->options = NULL;
562
563                 return;
564         }
565
566         // for trimed value
567         trimed_value_len = trimed_value_end - trimed_value_start;
568         trimed_value = (char *)calloc(1, trimed_value_len + 1);
569         if (!trimed_value) {
570                 DA_LOGE("DA_ERR_FAIL_TO_MEMALLOC");
571                 return;
572         }
573         strncpy(trimed_value, trimed_value_start, trimed_value_len);
574         http_header_field->value = trimed_value;
575
576         // for option parsing
577         option_str_start = trimed_value_end + 1;
578         http_header_field->options = __parsing_options(option_str_start);
579
580         /////////////// show
581         http_header_options_t *cur = NULL;
582         cur = http_header_field->options;
583         while (cur) {
584 //              DA_SECURE_LOGD("field = [%s], value = [%s]", cur->field, cur->value);
585                 cur = cur->next;
586         }
587 }
588
589 da_bool_t __get_http_header_option_for_field(
590         http_header_options_t *header_option, const char *in_field,
591         char **out_value)
592 {
593         http_header_options_t *cur = NULL;
594
595         //      DA_LOGV("");
596
597         if (!header_option) {
598                 DA_LOGE("input header_option is NULL.");
599                 return DA_FALSE;
600         }
601
602         cur = header_option;
603         while (cur) {
604                 if (cur->field) {
605                         if (!strncasecmp(cur->field, in_field, strlen(cur->field)) &&
606                                         cur->value) {
607                                 DA_SECURE_LOGD("[%s][%s]", cur->field, cur->value);
608                                 *out_value = cur->value;
609                                 return DA_TRUE;
610                         }
611
612                 }
613                 cur = cur->next;
614         }
615         return DA_FALSE;
616 }
617
618 da_bool_t __get_http_header_for_field(http_msg_response_t *http_msg_response,
619         const char *in_field, http_header_t **out_header)
620 {
621         http_msg_iter_t http_msg_iter;
622         http_header_t *header = NULL;
623         char *field = NULL;
624
625         //DA_LOGV("");
626
627         http_msg_response_get_iter(http_msg_response, &http_msg_iter);
628         while (http_msg_get_header_with_iter(&http_msg_iter, &field, &header)) {
629                 if (field && header && !strncasecmp(field, in_field, strlen(field))) {
630                         //DA_SECURE_LOGD("[%s][%s]", field, header->value);
631                         *out_header = header;
632                         return DA_TRUE;
633                 }
634         }
635
636         return DA_FALSE;
637 }
638
639 da_bool_t __get_http_req_header_for_field(http_msg_request_t *http_msg_request,
640         const char *in_field, http_header_t **out_header)
641 {
642         http_msg_iter_t http_msg_iter;
643         http_header_t *header = NULL;
644         char *field = NULL;
645
646         //DA_LOGV("");
647
648         http_msg_request_get_iter(http_msg_request, &http_msg_iter);
649         while (http_msg_get_header_with_iter(&http_msg_iter, &field, &header)) {
650                 if (field && header && !strncasecmp(field, in_field, strlen(field))) {
651                         //DA_SECURE_LOGD("[%s][%s]", field, header->value);
652                         *out_header = header;
653                         return DA_TRUE;
654                 }
655         }
656
657         return DA_FALSE;
658 }
659
660 void __exchange_header_value(http_header_t *header, const char *in_raw_value)
661 {
662         DA_LOGV("");
663
664         if (!header || !in_raw_value)
665                 return;
666
667         __http_header_destroy_all_option(&(header->options));
668
669         if (header->value) {
670                 free(header->value);
671                 header->value = DA_NULL;
672         }
673         if (header->raw_value)
674                 free(header->raw_value);
675         header->raw_value = strdup(in_raw_value);
676
677         __parsing_raw_value(header);
678 }
679
680 da_bool_t http_msg_response_get_content_type(
681         http_msg_response_t *http_msg_response, char **out_type)
682 {
683         da_bool_t b_ret = DA_FALSE;
684         http_header_t *header = NULL;
685
686         DA_LOGV("");
687
688         b_ret = __get_http_header_for_field(http_msg_response,
689                         HTTP_FIELD_CONTENT_TYPE, &header);
690         if (!b_ret) {
691                 DA_LOGV("no Content-Type");
692                 return DA_FALSE;
693         }
694         if (out_type)
695                 *out_type = strdup(header->value);
696
697         return DA_TRUE;
698 }
699
700 void http_msg_response_set_content_type(http_msg_response_t *http_msg_response,
701         const char *in_type)
702 {
703         da_bool_t b_ret = DA_FALSE;
704         http_header_t *header = NULL;
705
706         DA_LOGV("");
707
708         if (!http_msg_response || !in_type)
709                 return;
710
711         b_ret = __get_http_header_for_field(http_msg_response,
712                         HTTP_FIELD_CONTENT_TYPE, &header);
713         if (b_ret) {
714                 if (header->raw_value && (!strncmp(header->raw_value, in_type,
715                         strlen(header->raw_value))))
716                         return;
717
718                 DA_SECURE_LOGD("exchange Content-Type to [%s] from [%s]", in_type, header->value);
719                 __exchange_header_value(header, in_type);
720         } else {
721                 __http_header_add_field(&(http_msg_response->head),
722                                 HTTP_FIELD_CONTENT_TYPE, in_type, WITH_PARSING_OPTION);
723         }
724 }
725
726 da_bool_t http_msg_response_get_content_length(
727         http_msg_response_t *http_msg_response, da_size_t *out_length)
728 {
729         da_bool_t b_ret = DA_FALSE;
730         http_header_t *header = NULL;
731
732         DA_LOGV("");
733
734         b_ret = __get_http_header_for_field(http_msg_response,
735                         HTTP_FIELD_CONTENT_LENGTH, &header);
736         if (!b_ret) {
737                 DA_LOGV( "no Content-Length");
738                 return DA_FALSE;
739         }
740
741         if (out_length)
742                 *out_length = atoll(header->value);
743
744         return DA_TRUE;
745 }
746
747 da_bool_t http_msg_response_get_content_disposition(
748         http_msg_response_t *http_msg_response, http_msg_t *http_msg, char **out_disposition,
749         char **out_file_name)
750 {
751         da_bool_t b_ret = DA_FALSE;
752         http_header_t *header = NULL;
753         char *file_name = NULL;
754         char *wanted_str = NULL;
755         char *wanted_str_start = NULL;
756         char *wanted_str_end = NULL;
757         char *decoded_str = NULL;
758         int wanted_str_len = 0;
759
760         DA_LOGV("");
761
762         b_ret = __get_http_header_for_field(http_msg_response,
763                         HTTP_FIELD_CONTENT_DISPOSITION, &header);
764         if (!b_ret) {
765                 DA_LOGV( "no Content-Disposition");
766                 return DA_FALSE;
767         }
768         if (out_disposition)
769                 *out_disposition = strdup(header->value);
770         if (!out_file_name)
771                 return DA_FALSE;
772
773         b_ret = __get_http_header_option_for_field(header->options, "filename",
774                 &file_name);
775         if (!b_ret) {
776                 DA_LOGV( "no option");
777                 return DA_FALSE;
778         }
779
780         // eliminate double quotation mark if it exists on derived value
781         wanted_str_start = strchr(file_name, '"');
782         if (!wanted_str_start) {
783                 *out_file_name = strdup(file_name);
784                 return DA_TRUE;
785         } else {
786                 //              DA_SECURE_LOGD("wanted_str_start = [%s]", wanted_str_start);
787                 wanted_str_start++;
788                 wanted_str_end = strchr(wanted_str_start, '"');
789                 if (wanted_str_end) {
790                         wanted_str_len = wanted_str_end - wanted_str_start;
791                         wanted_str = (char*)calloc(1, wanted_str_len + 1);
792                         if (!wanted_str) {
793                                 DA_LOGE("DA_ERR_FAIL_TO_MEMALLOC");
794                                 return DA_FALSE;
795                         }
796                         strncpy(wanted_str, wanted_str_start, wanted_str_len);
797
798                         b_ret = is_base64_encoded_word(wanted_str);
799                         if (b_ret) {
800                                 DA_LOGV("It's base64 encoded-word string");
801                                 if (DA_RESULT_OK == decode_base64_encoded_str(
802                                         wanted_str, &decoded_str)) {
803                                         DA_SECURE_LOGD("base64 decoded str = [%s]", decoded_str);
804                                         free(wanted_str);
805                                         wanted_str = decoded_str;
806                                         decoded_str = NULL;
807                                 } else {
808                                         DA_LOGV("Fail to base64 decode. Just use un-decoded string.");
809                                 }
810                         } else {
811                                 DA_LOGV("It's NOT base64 encoded-word string");
812                         }
813
814                         if(http_msg->curl){
815                                 decoded_str = curl_easy_unescape(http_msg->curl, wanted_str, wanted_str_len, NULL);
816                         }
817                         else{
818                                 CURL* handle = curl_easy_init();
819                                 decoded_str = curl_easy_unescape(handle, wanted_str, wanted_str_len, NULL);
820                                 curl_easy_cleanup(handle);
821                         }
822
823                         /* If it is url encoded string */
824                         if (decoded_str) {
825                                 char* file_name;
826                                 DA_SECURE_LOGD("Url decoded str = [%s]", decoded_str);
827                                 file_name = (char*)calloc(1, strlen(decoded_str) + 1);
828                                 strncpy(file_name, decoded_str, strlen(decoded_str));
829
830                                 NULL_CHECK_AND_FREE(wanted_str);
831                                 curl_free(decoded_str);
832                                 decoded_str = NULL;
833
834                                 *out_file_name = file_name;
835                                 return DA_TRUE;
836                         }
837                         else{
838                                 DA_LOGE("Fail to url decode.");
839                                 NULL_CHECK_AND_FREE(wanted_str);
840                                 *out_file_name = NULL;
841                                 return DA_FALSE;
842                         }
843                 } else {
844                         DA_LOGE("Not matched \" !");
845                         return DA_FALSE;
846                 }
847         }
848 }
849
850 da_bool_t http_msg_response_get_ETag(http_msg_response_t *http_msg_response,
851         char **out_value)
852 {
853         da_bool_t b_ret = DA_FALSE;
854         http_header_t *header = NULL;
855
856         DA_LOGV("");
857
858         b_ret = __get_http_header_for_field(http_msg_response, HTTP_FIELD_ETAG,
859                         &header);
860         if (!b_ret) {
861                 DA_LOGV( "no ETag");
862                 return DA_FALSE;
863         }
864         if (out_value)
865                 *out_value = strdup(header->value);
866
867         return DA_TRUE;
868 }
869
870 #ifdef _RAF_SUPPORT
871 da_bool_t http_msg_response_get_RAF_mode(http_msg_response_t *http_msg_response,
872         char **out_value)
873 {
874         da_bool_t b_ret = DA_FALSE;
875         http_header_t *header = NULL;
876
877         DA_LOGV("");
878
879         b_ret = __get_http_header_for_field(http_msg_response, HTTP_FIELD_RAF_MODE,
880                         &header);
881         if (!b_ret) {
882                 DA_LOGV( "no RAF mode");
883                 return DA_FALSE;
884         }
885         if (out_value)
886                 *out_value = strdup(header->value);
887
888         return DA_TRUE;
889 }
890 #endif
891
892 da_bool_t http_msg_response_get_date(http_msg_response_t *http_msg_response,
893         char **out_value)
894 {
895         da_bool_t b_ret = DA_FALSE;
896         http_header_t *header = NULL;
897
898         DA_LOGV("");
899
900         b_ret = __get_http_header_for_field(http_msg_response,
901                         HTTP_FIELD_DATA, &header);
902         if (!b_ret) {
903                 DA_LOGV( "no Date");
904                 return DA_FALSE;
905         }
906         if (out_value)
907                 *out_value = strdup(header->value);
908
909         return DA_TRUE;
910 }
911
912 da_bool_t http_msg_response_get_location(http_msg_response_t *http_msg_response,
913         char **out_value)
914 {
915         da_bool_t b_ret = DA_FALSE;
916         http_header_t *header = NULL;
917
918         DA_LOGV("");
919
920         b_ret = __get_http_header_for_field(http_msg_response,
921                         HTTP_FIELD_LOCATION, &header);
922         if (!b_ret) {
923                 DA_LOGV( "no Location");
924                 return DA_FALSE;
925         }
926         if (out_value)
927                 *out_value = strdup(header->value);
928
929         return DA_TRUE;
930 }
931
932 char *__stristr(const char *long_str, const char *find_str)
933 {
934         int i = 0;
935         int length_long = 0;
936         int length_find = 0;
937         char *ret_ptr = NULL;
938         char *org_ptr = NULL;
939         char *look_ptr = NULL;
940
941         if (long_str == NULL || find_str == NULL) {
942                 DA_LOGE("INVALID ARGUMENT");
943                 return NULL;
944         }
945
946         length_long = strlen(long_str);
947         length_find = strlen(find_str);
948
949         org_ptr = (char*)calloc(1, length_long + 1);
950
951         if (org_ptr == NULL) {
952                 DA_LOGE("INVALID ARGUMENT");
953                 return NULL;
954         }
955
956         look_ptr = (char*)calloc(1, length_find + 1);
957
958         if (look_ptr == NULL) {
959                 DA_LOGE("INVALID ARGUMENT");
960                 free(org_ptr);
961                 return NULL;
962         }
963
964         while (i < length_long) {
965                 if (isalpha(long_str[i]) != 0) {
966                         if (isupper(long_str[i]) != 0) {
967                                 org_ptr[i] = long_str[i];
968                         } else {
969                                 org_ptr[i] = toupper(long_str[i]);
970                         }
971                 } else {
972                         org_ptr[i] = long_str[i];
973                 }
974                 i++;
975         }
976
977         i = 0;
978
979         while (i < length_find) {
980                 if (isalpha(find_str[i]) != 0) {
981                         if (isupper(find_str[i]) != 0) {
982                                 look_ptr[i] = find_str[i];
983                         } else {
984                                 look_ptr[i] = toupper(find_str[i]);
985                         }
986                 } else {
987                         look_ptr[i] = find_str[i];
988                 }
989                 i++;
990         }
991
992         ret_ptr = strstr(org_ptr, look_ptr);
993
994         if (ret_ptr == 0) {
995                 free(org_ptr);
996                 free(look_ptr);
997                 return NULL;
998         } else {
999                 i = ret_ptr - org_ptr;
1000         }
1001
1002         free(org_ptr);
1003         free(look_ptr);
1004
1005         return (char*)(long_str + i);
1006 }
1007
1008 /* This is not used. But it can be needed if there is no http header parser at http library.*/
1009 da_bool_t extract_attribute_from_header(
1010         char *szHeadStr,
1011         const char *szFindStr,
1012         char **ppRtnValue)
1013 {
1014         char *pValuePos = NULL;
1015         int index = 0;
1016         int startPos = 0;
1017         int strLen = 0;
1018         int need_to_end_quataion_mark = 0;
1019
1020         if (szHeadStr == DA_NULL || szFindStr == DA_NULL) {
1021                 DA_LOGE("INVALID ARGUMENT");
1022                 return DA_FALSE;
1023         }
1024         if (strlen(szHeadStr) <= 0 || strlen(szFindStr) <= 0) {
1025                 DA_LOGE("INVALID ARGUMENT");;
1026
1027                 return DA_FALSE;
1028         }
1029         if (ppRtnValue == NULL) {
1030                 return DA_FALSE;
1031         }
1032
1033         pValuePos = __stristr(szHeadStr, (char*)szFindStr);
1034         if (pValuePos == NULL) {
1035                 *ppRtnValue = NULL;
1036                 goto ERR;
1037         }
1038
1039         index = strlen(szFindStr);
1040
1041         while (pValuePos[index] != ':' && pValuePos[index] != '=') {
1042                 index++;
1043
1044                 if (pValuePos[index] == '\0') {
1045                         return DA_FALSE;
1046                 }
1047         }
1048
1049         index++;
1050
1051         /* jump space */
1052         while (pValuePos[index] == ' ') {
1053                 index++;
1054         }
1055
1056         /* jump quatation mark */
1057         while (pValuePos[index] == '"') {
1058                 need_to_end_quataion_mark = 1;
1059                 index++;
1060         }
1061
1062         startPos = index;
1063
1064         /* Find the end of data. */
1065         if (0 == strncasecmp(szFindStr, HTTP_FIELD_LOCATION,
1066                         strlen(HTTP_FIELD_LOCATION)))//terminate character list does not contain ';' in case of URI
1067         {
1068                 while (DA_FALSE == IS_URI_TERMINATING_CHAR(pValuePos[index])) {
1069                         index++;
1070                 }
1071         } else if (need_to_end_quataion_mark) {
1072                 while (DA_FALSE == IS_TERMINATING_CHAR_EX(pValuePos[index])) {
1073                         index++;
1074                 }
1075         } else {
1076                 while (DA_FALSE == IS_TERMINATING_CHAR(pValuePos[index])) {
1077                         index++;
1078                 }
1079         }
1080
1081         strLen = index - startPos;
1082
1083         if (strLen < 1) {
1084                 DA_LOGE(" strLen is < 1");
1085                 goto ERR;
1086         }
1087
1088         *ppRtnValue = (char*)calloc(1, sizeof(char) * (strLen + 1));
1089
1090         if (*ppRtnValue == NULL) {
1091                 DA_LOGE(" *ppRtnValue is NULL");
1092                 goto ERR;
1093         }
1094
1095         strncpy(*ppRtnValue, pValuePos + startPos, strLen);
1096         *(*ppRtnValue + strLen) = '\0';
1097
1098         return DA_TRUE;
1099 ERR:
1100         if (*ppRtnValue) {
1101                 free(*ppRtnValue);
1102                 *ppRtnValue = NULL;
1103         }
1104         return DA_FALSE;
1105 }
1106
1107 da_bool_t http_msg_request_get_if_range(http_msg_request_t *http_msg_request,
1108         char **out_value)
1109 {
1110         da_bool_t b_ret = DA_FALSE;
1111         http_header_t *header = NULL;
1112
1113         DA_LOGV("");
1114
1115         b_ret = __get_http_req_header_for_field(http_msg_request, HTTP_FIELD_IF_RANGE,
1116                         &header);
1117         if (!b_ret) {
1118                 DA_LOGV( "no If Range");
1119                 return DA_FALSE;
1120         }
1121         if (out_value)
1122                 *out_value = strdup(header->value);
1123
1124         return DA_TRUE;
1125 }
1126
1127 da_bool_t http_msg_request_get_range(http_msg_request_t *http_msg_request,
1128         char **out_value)
1129 {
1130         da_bool_t b_ret = DA_FALSE;
1131         http_header_t *header = NULL;
1132
1133         DA_LOGV("");
1134
1135         b_ret = __get_http_req_header_for_field(http_msg_request, HTTP_FIELD_RANGE,
1136                         &header);
1137         if (!b_ret) {
1138                 DA_LOGV( "no Range");
1139                 return DA_FALSE;
1140         }
1141         if (out_value)
1142                 *out_value = strdup(header->value);
1143
1144         return DA_TRUE;
1145 }