Tizen 2.1 base
[platform/framework/web/download-provider.git] / src / agent / download-agent-encoding.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 <glib.h>
20
21 #include "download-agent-encoding.h"
22 #include "download-agent-debug.h"
23
24 da_result_t _parsing_base64_encoded_str(const char *in_encoded_str,
25         char **out_charset_type,
26         char *out_encoding_type,
27         char **out_raw_encoded_str);
28
29 da_bool_t is_base64_encoded_word(const char *in_str)
30 {
31         const char *haystack = DA_NULL;
32         char first_needle[8] = {0,};
33         char second_needle[8] = {0,};
34         char *found_str = DA_NULL;
35
36         if (!in_str) {
37                 DA_LOG_ERR(Default, "input string is NULL");
38                 return DA_FALSE;
39         }
40
41         haystack = in_str;
42         if (haystack[0] == '"') {
43                 snprintf(first_needle, sizeof(first_needle), "%s", "\"=?");     // "=?
44                 snprintf(second_needle, sizeof(second_needle), "%s", "?=\"");   // ?="
45         } else {
46                 snprintf(first_needle, sizeof(first_needle), "%s", "=?");       // =?
47                 snprintf(second_needle, sizeof(second_needle), "%s", "?=");     // ?=
48         }
49
50 //      DA_LOG(Default, "needle = [%s], haystack = [%s]", first_needle, haystack);
51
52         found_str = strstr(haystack, first_needle);
53         if (found_str) {
54                 if (found_str == haystack) {
55 //                      DA_LOG(Default, "Input string is starting with %s", needle);
56                         haystack = haystack + strlen(haystack) - strlen(second_needle);
57 //                      DA_LOG(Default, "second haystack is [%s]", haystack);
58                         if(!strcmp(haystack, second_needle))
59                                 return DA_TRUE;
60                 }
61         }
62         return DA_FALSE;
63 }
64
65 da_result_t decode_base64_encoded_str(const char *in_encoded_str,
66         char **out_decoded_ascii_str)
67 {
68         da_result_t ret = DA_RESULT_OK;
69
70         const char *org_str = DA_NULL;
71         char *charset_type = NULL;
72         char encoding_type = '\0';
73         char *raw_encoded_str = NULL;
74         char *decoded_str = NULL;
75         const gchar *g_encoded_text = NULL;
76         guchar *g_decoded_text = NULL;
77         gsize g_decoded_text_len = 0;
78
79         DA_LOG(Default, "input str = [%s]", in_encoded_str);
80
81         org_str = in_encoded_str;
82         if(!org_str) {
83                 DA_LOG_ERR(Default, "Input string is NULL");
84                 ret = DA_ERR_INVALID_ARGUMENT;
85                 goto ERR;
86         }
87
88         ret = _parsing_base64_encoded_str(org_str, &charset_type,
89                 &encoding_type, &raw_encoded_str);
90         if(ret != DA_RESULT_OK) {
91                 goto ERR;
92         }
93
94 //      DA_LOG(Default, "charset = [%s], encoding = [%c], raw = [%s]", charset_type, encoding_type, raw_encoded_str);
95
96         if(encoding_type != 'B') {
97                 DA_LOG_ERR(Default, "Encoded Word is not encoded with Base64, but %c. We can only handle Base64.", encoding_type);
98                 ret = DA_ERR_INVALID_ARGUMENT;
99                 goto ERR;
100         }
101
102         /*
103          * on glib/gtype.h
104          * typedef char   gchar;
105          * typedef unsigned char   guchar;
106          *
107          */
108         g_encoded_text = (const gchar*)raw_encoded_str;
109         g_decoded_text = g_base64_decode(g_encoded_text, &g_decoded_text_len);
110
111         if(g_decoded_text) {
112                 DA_LOG(Default, "g_decoded_text = [%s]", g_decoded_text);
113                 decoded_str = (char*)calloc(1, g_decoded_text_len+1);
114                 if(!decoded_str) {
115                         DA_LOG_ERR(Default, "DA_ERR_FAIL_TO_MEMALLOC");
116                         ret = DA_ERR_FAIL_TO_MEMALLOC;
117                         goto ERR;
118                 } else {
119                         memcpy(decoded_str, g_decoded_text, g_decoded_text_len);
120                 }
121         }
122         DA_LOG(Default, "decoded_str = [%s]", decoded_str);
123
124 ERR:
125         *out_decoded_ascii_str = decoded_str;
126
127         if(charset_type) {
128                 free(charset_type);
129                 charset_type = NULL;
130         }
131
132         if(raw_encoded_str) {
133                 free(raw_encoded_str);
134                 raw_encoded_str = NULL;
135         }
136
137         if(g_decoded_text) {
138                 g_free(g_decoded_text);
139         }
140
141         return ret;
142 }
143
144
145 da_result_t _parsing_base64_encoded_str(const char *in_encoded_str,
146         char **out_charset_type,
147         char *out_encoding_type,
148         char **out_raw_encoded_str)
149 {
150         da_result_t ret = DA_RESULT_OK;
151
152         const char *org_str = DA_NULL;  // e.g. =?UTF-8?B?7Jew7JWE7JmA7IKs7J6QLmpwZw==?=
153         char *charset_type = NULL;              // e.g. UTF-8
154         char encoding_type = '\0';              // e.g. B (means Base64)
155         char *raw_encoded_str = NULL;   // e.g. 7Jew7JWE7JmA7IKs7J6QLmpwZw==
156
157         char *haystack = DA_NULL;
158         char needle[8] = {0,};
159
160         char *wanted_str = DA_NULL;
161         int wanted_str_len = 0;
162         char *wanted_str_start = DA_NULL;
163         char *wanted_str_end = DA_NULL;
164
165         org_str = in_encoded_str;
166         if (!org_str) {
167                 DA_LOG_ERR(Default, "Input string is NULL");
168                 ret = DA_ERR_INVALID_ARGUMENT;
169                 goto ERR;
170         }
171
172         // strip "=?"
173         haystack = (char*)org_str;
174         snprintf(needle, sizeof(needle), "=?");
175         wanted_str_end = strstr(haystack, needle);
176         if (!wanted_str_end) {
177                 DA_LOG_ERR(Default, "DA_ERR_INVALID_ARGUMENT");
178                 ret = DA_ERR_INVALID_ARGUMENT;
179                 goto ERR;
180         } else {
181                 wanted_str = wanted_str_end + strlen(needle);
182                 DA_LOG(Default, "strip [%s]", wanted_str);
183         }
184
185         // for charset
186         haystack = wanted_str_start = wanted_str;
187         needle[0] = '?';
188         wanted_str_end = strchr(haystack, needle[0]);
189         if (!wanted_str_end) {
190                 DA_LOG_ERR(Default, "DA_ERR_INVALID_ARGUMENT");
191                 ret = DA_ERR_INVALID_ARGUMENT;
192                 goto ERR;
193         } else {
194                 wanted_str_len = wanted_str_end - wanted_str_start + 1;
195                 wanted_str = (char*)calloc(1, wanted_str_len+1);
196                 if (!wanted_str) {
197                         DA_LOG_ERR(Default, "DA_ERR_FAIL_TO_MEMALLOC");
198                         ret = DA_ERR_FAIL_TO_MEMALLOC;
199                         goto ERR;
200                 } else {
201                         snprintf(wanted_str, wanted_str_len+1, "%s", wanted_str_start);
202                         charset_type = wanted_str;
203                         wanted_str = DA_NULL;
204                 }
205
206                 DA_LOG(Default, "charset [%s]", charset_type);
207         }
208
209
210         // for encoding
211         encoding_type = *(++wanted_str_end);
212         DA_LOG(Default, "encoding [%c]", encoding_type);
213
214         // for raw encoded str
215         haystack = wanted_str_start = wanted_str_end + 1;
216         snprintf(needle, sizeof(needle), "?=");
217         wanted_str_end = strstr(haystack, needle);
218         if (!wanted_str_end) {
219                 DA_LOG_ERR(Default, "DA_ERR_INVALID_ARGUMENT");
220                 ret = DA_ERR_INVALID_ARGUMENT;
221                 goto ERR;
222         } else {
223                 wanted_str_len = wanted_str_end - wanted_str_start + 1;
224                 wanted_str = (char*)calloc(1, wanted_str_len+1);
225                 if (!wanted_str) {
226                         DA_LOG_ERR(Default, "DA_ERR_FAIL_TO_MEMALLOC");
227                         ret = DA_ERR_FAIL_TO_MEMALLOC;
228                         goto ERR;
229                 } else {
230                         snprintf(wanted_str, wanted_str_len+1, "%s", wanted_str_start);
231                         raw_encoded_str = wanted_str;
232                         wanted_str = NULL;
233                 }
234
235                 DA_LOG(Default, "raw encoded str [%s]", raw_encoded_str);
236         }
237
238 ERR:
239         if (ret != DA_RESULT_OK) {
240                 if (charset_type) {
241                         free(charset_type);
242                         charset_type = NULL;
243                 }
244         }
245
246         *out_charset_type = charset_type;
247         *out_encoding_type = encoding_type;
248         *out_raw_encoded_str = raw_encoded_str;
249
250         return ret;
251 }
252
253 void decode_url_encoded_str(const char *in_encoded_str, char **out_str)
254 {
255     char *in = NULL;
256         char *out = NULL;
257         *out_str = calloc(1, strlen(in_encoded_str) + 1);
258         if (*out_str == NULL)
259                 return;
260     out = *out_str;
261     in = (char *)in_encoded_str;
262         while (*in)
263         {
264                 if (*in == '%') {
265                         int hex = 0;
266                         in++;
267                         if (sscanf(in, "%2x", &hex) <= 0) {
268                                 return;
269                         } else {
270                                 *out = hex;
271                                 in++;
272                         }
273                 } else if (*in == '+') {
274                         *out = ' ';
275                 } else {
276                         *out = *in;
277                 }
278                 in++;
279                 out++;
280         }
281 }
282