[Security vulnerability] Replace strncmp() with strcmp()
[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 = DA_NULL;
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 = DA_NULL;
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 && !strcmp(header->raw_value, in_type))
715                         return;
716
717                 DA_SECURE_LOGD("exchange Content-Type to [%s] from [%s]", in_type, header->value);
718                 __exchange_header_value(header, in_type);
719         } else {
720                 __http_header_add_field(&(http_msg_response->head),
721                                 HTTP_FIELD_CONTENT_TYPE, in_type, WITH_PARSING_OPTION);
722         }
723 }
724
725 da_bool_t http_msg_response_get_content_length(
726                 http_msg_response_t *http_msg_response, da_size_t *out_length)
727 {
728         da_bool_t b_ret = DA_FALSE;
729         http_header_t *header = NULL;
730
731         DA_LOGV("");
732
733         b_ret = __get_http_header_for_field(http_msg_response,
734                         HTTP_FIELD_CONTENT_LENGTH, &header);
735         if (!b_ret) {
736                 DA_LOGV("no Content-Length");
737                 return DA_FALSE;
738         }
739
740         if (out_length)
741                 *out_length = atoll(header->value);
742
743         return DA_TRUE;
744 }
745
746 da_bool_t http_msg_response_get_content_disposition(
747                 http_msg_response_t *http_msg_response, http_msg_t *http_msg, char **out_disposition,
748                 char **out_file_name)
749 {
750         da_bool_t b_ret = DA_FALSE;
751         http_header_t *header = NULL;
752         char *file_name = NULL;
753         char *wanted_str = NULL;
754         char *wanted_str_start = NULL;
755         char *wanted_str_end = NULL;
756         char *decoded_str = NULL;
757         int wanted_str_len = 0;
758
759         DA_LOGV("");
760
761         b_ret = __get_http_header_for_field(http_msg_response,
762                         HTTP_FIELD_CONTENT_DISPOSITION, &header);
763         if (!b_ret) {
764                 DA_LOGV("no Content-Disposition");
765                 return DA_FALSE;
766         }
767         if (out_disposition)
768                 *out_disposition = strdup(header->value);
769         if (!out_file_name)
770                 return DA_FALSE;
771
772         b_ret = __get_http_header_option_for_field(header->options, "filename",
773                         &file_name);
774         if (!b_ret) {
775                 DA_LOGV("no option");
776                 return DA_FALSE;
777         }
778
779         // eliminate double quotation mark if it exists on derived value
780         wanted_str_start = strchr(file_name, '"');
781         if (!wanted_str_start) {
782                 *out_file_name = strdup(file_name);
783                 return DA_TRUE;
784         } else {
785                 //              DA_SECURE_LOGD("wanted_str_start = [%s]", wanted_str_start);
786                 wanted_str_start++;
787                 wanted_str_end = strchr(wanted_str_start, '"');
788                 if (wanted_str_end) {
789                         wanted_str_len = wanted_str_end - wanted_str_start;
790                         wanted_str = (char*)calloc(1, wanted_str_len + 1);
791                         if (!wanted_str) {
792                                 DA_LOGE("DA_ERR_FAIL_TO_MEMALLOC");
793                                 return DA_FALSE;
794                         }
795                         strncpy(wanted_str, wanted_str_start, wanted_str_len);
796
797                         b_ret = is_base64_encoded_word(wanted_str);
798                         if (b_ret) {
799                                 DA_LOGV("It's base64 encoded-word string");
800                                 if (DA_RESULT_OK == decode_base64_encoded_str(
801                                                         wanted_str, &decoded_str)) {
802                                         DA_SECURE_LOGD("base64 decoded str = [%s]", decoded_str);
803                                         free(wanted_str);
804                                         wanted_str = decoded_str;
805                                         decoded_str = NULL;
806                                 } else {
807                                         DA_LOGV("Fail to base64 decode. Just use un-decoded string.");
808                                 }
809                         } else {
810                                 DA_LOGV("It's NOT base64 encoded-word string");
811                         }
812
813                         if (http_msg->curl) {
814                                 decoded_str = curl_easy_unescape(http_msg->curl, wanted_str, wanted_str_len, NULL);
815                         } else{
816                                 CURL* handle = curl_easy_init();
817                                 decoded_str = curl_easy_unescape(handle, wanted_str, wanted_str_len, NULL);
818                                 curl_easy_cleanup(handle);
819                         }
820
821                         /* If it is url encoded string */
822                         if (decoded_str) {
823                                 char* file_name;
824                                 DA_SECURE_LOGD("Url decoded str = [%s]", decoded_str);
825                                 file_name = (char*)calloc(1, strlen(decoded_str) + 1);
826                                 strncpy(file_name, decoded_str, strlen(decoded_str));
827
828                                 NULL_CHECK_AND_FREE(wanted_str);
829                                 curl_free(decoded_str);
830                                 decoded_str = NULL;
831
832                                 *out_file_name = file_name;
833                                 return DA_TRUE;
834                         } else{
835                                 DA_LOGE("Fail to url decode.");
836                                 NULL_CHECK_AND_FREE(wanted_str);
837                                 *out_file_name = NULL;
838                                 return DA_FALSE;
839                         }
840                 } else {
841                         DA_LOGE("Not matched \" !");
842                         return DA_FALSE;
843                 }
844         }
845 }
846
847 da_bool_t http_msg_response_get_ETag(http_msg_response_t *http_msg_response,
848                 char **out_value)
849 {
850         da_bool_t b_ret = DA_FALSE;
851         http_header_t *header = NULL;
852
853         DA_LOGV("");
854
855         b_ret = __get_http_header_for_field(http_msg_response, HTTP_FIELD_ETAG,
856                         &header);
857         if (!b_ret) {
858                 DA_LOGV("no ETag");
859                 return DA_FALSE;
860         }
861         if (out_value)
862                 *out_value = strdup(header->value);
863
864         return DA_TRUE;
865 }
866
867 #ifdef _RAF_SUPPORT
868 da_bool_t http_msg_response_get_RAF_mode(http_msg_response_t *http_msg_response,
869                 char **out_value)
870 {
871         da_bool_t b_ret = DA_FALSE;
872         http_header_t *header = NULL;
873
874         DA_LOGV("");
875
876         b_ret = __get_http_header_for_field(http_msg_response, HTTP_FIELD_RAF_MODE,
877                         &header);
878         if (!b_ret) {
879                 DA_LOGV("no RAF mode");
880                 return DA_FALSE;
881         }
882         if (out_value)
883                 *out_value = strdup(header->value);
884
885         return DA_TRUE;
886 }
887 #endif
888
889 da_bool_t http_msg_response_get_date(http_msg_response_t *http_msg_response,
890                 char **out_value)
891 {
892         da_bool_t b_ret = DA_FALSE;
893         http_header_t *header = NULL;
894
895         DA_LOGV("");
896
897         b_ret = __get_http_header_for_field(http_msg_response,
898                         HTTP_FIELD_DATA, &header);
899         if (!b_ret) {
900                 DA_LOGV("no Date");
901                 return DA_FALSE;
902         }
903         if (out_value)
904                 *out_value = strdup(header->value);
905
906         return DA_TRUE;
907 }
908
909 da_bool_t http_msg_response_get_location(http_msg_response_t *http_msg_response,
910                 char **out_value)
911 {
912         da_bool_t b_ret = DA_FALSE;
913         http_header_t *header = NULL;
914
915         DA_LOGV("");
916
917         b_ret = __get_http_header_for_field(http_msg_response,
918                         HTTP_FIELD_LOCATION, &header);
919         if (!b_ret) {
920                 DA_LOGV("no Location");
921                 return DA_FALSE;
922         }
923         if (out_value)
924                 *out_value = strdup(header->value);
925
926         return DA_TRUE;
927 }
928
929 da_bool_t http_msg_response_get_transfer_encoding(http_msg_response_t *http_msg_response,
930                 char **out_value)
931 {
932         da_bool_t b_ret = DA_FALSE;
933         http_header_t *header = NULL;
934
935         DA_LOGV("");
936
937         b_ret = __get_http_header_for_field(http_msg_response,
938                         HTTP_FIELD_TRANSFER_ENCODING, &header);
939         if (!b_ret) {
940                 DA_LOGE("no Transfer-Encoding");
941                 return DA_FALSE;
942         }
943         if (out_value)
944                 *out_value = strdup(header->value);
945
946         return DA_TRUE;
947 }
948
949 char *__stristr(const char *long_str, const char *find_str)
950 {
951         int i = 0;
952         int length_long = 0;
953         int length_find = 0;
954         char *ret_ptr = NULL;
955         char *org_ptr = NULL;
956         char *look_ptr = NULL;
957
958         if (long_str == NULL || find_str == NULL) {
959                 DA_LOGE("INVALID ARGUMENT");
960                 return NULL;
961         }
962
963         length_long = strlen(long_str);
964         length_find = strlen(find_str);
965
966         org_ptr = (char*)calloc(1, length_long + 1);
967
968         if (org_ptr == NULL) {
969                 DA_LOGE("INVALID ARGUMENT");
970                 return NULL;
971         }
972
973         look_ptr = (char*)calloc(1, length_find + 1);
974
975         if (look_ptr == NULL) {
976                 DA_LOGE("INVALID ARGUMENT");
977                 free(org_ptr);
978                 return NULL;
979         }
980
981         while (i < length_long) {
982                 if (isalpha(long_str[i]) != 0) {
983                         if (isupper(long_str[i]) != 0)
984                                 org_ptr[i] = long_str[i];
985                         else
986                                 org_ptr[i] = toupper(long_str[i]);
987                 } else {
988                         org_ptr[i] = long_str[i];
989                 }
990                 i++;
991         }
992
993         i = 0;
994
995         while (i < length_find) {
996                 if (isalpha(find_str[i]) != 0) {
997                         if (isupper(find_str[i]) != 0)
998                                 look_ptr[i] = find_str[i];
999                         else
1000                                 look_ptr[i] = toupper(find_str[i]);
1001                 } else {
1002                         look_ptr[i] = find_str[i];
1003                 }
1004                 i++;
1005         }
1006
1007         ret_ptr = strstr(org_ptr, look_ptr);
1008
1009         if (ret_ptr == 0) {
1010                 free(org_ptr);
1011                 free(look_ptr);
1012                 return NULL;
1013         } else {
1014                 i = ret_ptr - org_ptr;
1015         }
1016
1017         free(org_ptr);
1018         free(look_ptr);
1019
1020         return (char*)(long_str + i);
1021 }
1022
1023 /* This is not used. But it can be needed if there is no http header parser at http library.*/
1024 da_bool_t extract_attribute_from_header(
1025                 char *szHeadStr,
1026                 const char *szFindStr,
1027                 char **ppRtnValue)
1028 {
1029         char *pValuePos = NULL;
1030         int index = 0;
1031         int startPos = 0;
1032         int strLen = 0;
1033         int need_to_end_quataion_mark = 0;
1034
1035         if (szHeadStr == DA_NULL || szFindStr == DA_NULL) {
1036                 DA_LOGE("INVALID ARGUMENT");
1037                 return DA_FALSE;
1038         }
1039         if (strlen(szHeadStr) <= 0 || strlen(szFindStr) <= 0) {
1040                 DA_LOGE("INVALID ARGUMENT");;
1041
1042                 return DA_FALSE;
1043         }
1044         if (ppRtnValue == NULL)
1045                 return DA_FALSE;
1046
1047         pValuePos = __stristr(szHeadStr, (char*)szFindStr);
1048         if (pValuePos == NULL) {
1049                 *ppRtnValue = NULL;
1050                 goto ERR;
1051         }
1052
1053         index = strlen(szFindStr);
1054
1055         while (pValuePos[index] != ':' && pValuePos[index] != '=') {
1056                 index++;
1057
1058                 if (pValuePos[index] == '\0')
1059                         return DA_FALSE;
1060         }
1061
1062         index++;
1063
1064         /* jump space */
1065         while (pValuePos[index] == ' ')
1066                 index++;
1067
1068         /* jump quatation mark */
1069         while (pValuePos[index] == '"') {
1070                 need_to_end_quataion_mark = 1;
1071                 index++;
1072         }
1073
1074         startPos = index;
1075
1076         /* Find the end of data.
1077          * terminate character list does not contain ';' in case of URI
1078          */
1079         if (0 == strncasecmp(szFindStr, HTTP_FIELD_LOCATION, strlen(HTTP_FIELD_LOCATION))) {
1080                 while (DA_FALSE == IS_URI_TERMINATING_CHAR(pValuePos[index]))
1081                         index++;
1082         } else if (need_to_end_quataion_mark) {
1083                 while (DA_FALSE == IS_TERMINATING_CHAR_EX(pValuePos[index]))
1084                         index++;
1085         } else {
1086                 while (DA_FALSE == IS_TERMINATING_CHAR(pValuePos[index]))
1087                         index++;
1088         }
1089
1090         strLen = index - startPos;
1091
1092         if (strLen < 1) {
1093                 DA_LOGE(" strLen is < 1");
1094                 goto ERR;
1095         }
1096
1097         *ppRtnValue = (char*)calloc(1, sizeof(char) * (strLen + 1));
1098
1099         if (*ppRtnValue == NULL) {
1100                 DA_LOGE(" *ppRtnValue is NULL");
1101                 goto ERR;
1102         }
1103
1104         strncpy(*ppRtnValue, pValuePos + startPos, strLen);
1105         *(*ppRtnValue + strLen) = '\0';
1106
1107         return DA_TRUE;
1108 ERR:
1109         if (*ppRtnValue) {
1110                 free(*ppRtnValue);
1111                 *ppRtnValue = NULL;
1112         }
1113         return DA_FALSE;
1114 }
1115
1116 da_bool_t http_msg_request_get_if_range(http_msg_request_t *http_msg_request,
1117                 char **out_value)
1118 {
1119         da_bool_t b_ret = DA_FALSE;
1120         http_header_t *header = NULL;
1121
1122         DA_LOGV("");
1123
1124         b_ret = __get_http_req_header_for_field(http_msg_request, HTTP_FIELD_IF_RANGE,
1125                         &header);
1126         if (!b_ret) {
1127                 DA_LOGV("no If Range");
1128                 return DA_FALSE;
1129         }
1130         if (out_value)
1131                 *out_value = strdup(header->value);
1132
1133         return DA_TRUE;
1134 }
1135
1136 da_bool_t http_msg_request_get_range(http_msg_request_t *http_msg_request,
1137                 char **out_value)
1138 {
1139         da_bool_t b_ret = DA_FALSE;
1140         http_header_t *header = NULL;
1141
1142         DA_LOGV("");
1143
1144         b_ret = __get_http_req_header_for_field(http_msg_request, HTTP_FIELD_RANGE,
1145                         &header);
1146         if (!b_ret) {
1147                 DA_LOGV("no Range");
1148                 return DA_FALSE;
1149         }
1150         if (out_value)
1151                 *out_value = strdup(header->value);
1152
1153         return DA_TRUE;
1154 }