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