1 /***********************************************************************
2 * url.c: url utility functions
3 ***********************************************************************
4 * Copyright (C) 2008 metro <me_t_ro@yahoo.com>
5 *
6 * This file is part of msdl, media stream downloader
7 *
8 * url related utility functions, and url parser
9 *
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc.,
24 * 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
25 *
26 ***********************************************************************/
27
28
29 /*
30 * Copyright notice of MPlayer project
31 * which some part of msdl is based on.
32 * (from MPlayer-1.0rc2/url.c)
33 */
34
35 /*
36 * URL Helper
37 * by Bertrand Baudet <bertrand_baudet@yahoo.com>
38 * (C) 2001, MPlayer team.
39 */
40
41
42 #include <stdio.h>
43 #include <stdlib.h>
44 #include <string.h>
45 #include <unistd.h>
46 #include <ctype.h>
47
48 #include "msdllib.h"
49 #include "network.h"
50 #include "display.h"
51
52
53
54 static void string_separate(const char *original,const char *needle,
55 char **pre,char **post);
56 static void free_url_members(struct url_t *u);
57
string_separate(const char * original,const char * needle,char ** pre,char ** post)58 static void string_separate(const char *original,const char *needle,
59 char **pre,char **post)
60 {
61 char *p = NULL;
62 int len = 0;
63
64 p = strstr(original,needle);
65 if(p) { /* found */
66 len = p - original;
67 *pre = xmalloc(len + 1);
68 strncpy(*pre,original,len);
69 (*pre)[len] = '\0';
70
71 p += strlen(needle);
72 *post = strdup(p);
73 }
74 else { /* cannot separate */
75 *pre = NULL;
76 *post = NULL;
77 }
78 }
79
free_url_members(struct url_t * u)80 static void free_url_members(struct url_t *u)
81 {
82 if(u->url) free(u->url);
83 if(u->protocol) free(u->protocol);
84 if(u->hostname) free(u->hostname);
85 if(u->file) free(u->file);
86 if(u->filepath) free(u->filepath);
87 if(u->username) free(u->username);
88 if(u->password) free(u->password);
89 }
90
91
copy_url_t(struct url_t * url,struct url_t * srcurl)92 void copy_url_t(struct url_t *url,struct url_t *srcurl)
93 {
94 free_url_members(url);
95 url->url = (srcurl->url) ? strdup(srcurl->url) : NULL;
96 url->protocol = (srcurl->protocol) ? strdup(srcurl->protocol) : NULL;
97 url->hostname = (srcurl->hostname) ? strdup(srcurl->hostname) : NULL;
98 url->file = (srcurl->file) ? strdup(srcurl->file) : NULL;
99 url->filepath = (srcurl->filepath) ? strdup(srcurl->filepath) : NULL;
100 url->username = (srcurl->username) ? strdup(srcurl->username) : NULL;
101 url->password = (srcurl->password) ? strdup(srcurl->password) : NULL;
102 }
103
104
105 /*
106 * prot://user:password@host:port/path
107 */
new_url_t(const char * url_str)108 struct url_t *new_url_t(const char *url_str)
109 {
110 struct url_t *url = NULL;
111 char *pre = NULL,*post = NULL;
112 char *server_part = NULL;
113 char *path_part = NULL;
114 char *user_pass = NULL;
115 char *host_port = NULL;
116
117 if(!strstr(url_str,"://")) {
118 return NULL; /* invalid url*/
119 }
120
121 url = (struct url_t *)xmalloc(sizeof(struct url_t));
122
123 /* exmp://foo.bar.com/example/hoge.asf */
124 url->url = strdup(url_str);
125
126 string_separate(url->url,"://",&pre,&post);
127 if(pre) {
128 url->protocol = strdup(pre);
129 url->file = strdup(post);
130 free(pre);
131 free(post);
132
133 string_separate(url->file,"/",&pre,&post);
134 if(pre) {
135 server_part = strdup(pre);
136 path_part = strdup(post);
137 free(pre);
138 free(post);
139 }
140 else {
141 server_part = strdup(url->file);
142 }
143 }
144
145 /* interpret server_part */
146 if(server_part) {
147 string_separate(server_part,"@",&pre,&post);
148 if(pre) { /* user[:pass]'@'host[:port] */
149 user_pass = strdup(pre);
150 host_port = strdup(post);
151
152 free(pre);
153 free(post);
154 }
155 else { /* host[:port] */
156 host_port = strdup(server_part);
157 }
158
159
160 /* interpret user_pass */
161 if(user_pass) {
162 string_separate(user_pass,":",&pre,&post);
163 if(pre) {
164 url->username = strdup(pre);
165 url->password = strdup(post);
166 free(pre);
167 free(post);
168 }
169 else {
170 url->username = strdup(user_pass);
171 }
172 }
173
174 /* interpret host_port */
175 if(host_port) {
176 string_separate(host_port,":",&pre,&post);
177 if(pre) {
178 url->hostname = strdup(pre);
179 url->port = atoi(post);
180 free(pre);
181 free(post);
182 }
183 else {
184 url->hostname = strdup(host_port);
185 url->port = 0;
186 }
187 }
188 }
189
190 /* interpret path_part */
191 if(path_part) {
192 int len = strlen(path_part) + 2;
193 url->filepath = xmalloc(len);
194 strncpy(url->filepath,"/",len);
195 strncat(url->filepath,path_part,len);
196 }
197
198 url->protocol_type = protocol_type_from_string(url->protocol);
199
200 /*
201 printf("url :%s\n"
202 "prot:%s\n"
203 "host:%s\n"
204 "port:%d\n"
205 "file:%s\n"
206 "path:%s\n"
207 "type:%d\n"
208 "user:%s\n"
209 "pass:%s\n"
210 ,url->url,url->protocol,url->hostname,url->port,url->file,url->filepath,url->protocol_type,
211 url->username,url->password);
212 */
213
214 if(server_part) free(server_part);
215 if(path_part) free(path_part);
216 if(user_pass) free(user_pass);
217 if(host_port) free(host_port);
218
219 return url;
220
221 }
222
223
free_url_t(struct url_t * u)224 void free_url_t(struct url_t *u)
225 {
226 if(!u) return;
227
228 free_url_members(u);
229 free(u);
230 }
231
232
233
234 /*
235 * unescape url string.
236 * such as : change '%41' to 'A'.
237 */
url_unescape_string(char * dst,char * src)238 void url_unescape_string(char *dst,char *src)
239 {
240 uint8_t ch,ch1,ch2;
241 int i,len;
242
243 len = strlen(src);
244
245 for(i = 0; i < len; i++) {
246 ch = src[i];
247 if(ch == '%' && (i < len - 2)) { /* need two more chars after '%' */
248 ch1 = toupper(src[i+1]);
249 ch2 = toupper(src[i+2]); /* uppercase chars */
250
251 if((('0' <= ch1 && ch1 <= '9') || ('A' <= ch1 && ch1 <= 'F')) &&
252 (('0' <= ch2 && ch2 <= '9') || ('A' <= ch2 && ch2 <= 'F'))) {
253 ch1 = ('0' <= ch1 && ch1 <= '9') ? ch1 - '0' : ch1 - 'A';
254 ch2 = ('0' <= ch2 && ch2 <= '9') ? ch2 - '0' : ch2 - 'A';
255 ch = (ch1 << 4) | ch2;
256 i += 2;
257 }
258 }
259 *dst++ = ch;
260 }
261 *dst++='\0';
262 }
263
264
265
266 /*
267 * return true if 'c' is valid url character
268 */
is_url_valid_char(int c)269 inline int is_url_valid_char(int c)
270 {
271 return (isalpha(c) ||
272 isdigit(c) ||
273 c == '_' ||
274 c == '%' ||
275 c == '+' ||
276 c == '*' ||
277 c == '!' ||
278 c == '?' ||
279 c == ':' ||
280 c == ';' ||
281 c == '.' ||
282 c == ',' ||
283 c == '/' ||
284 c == '~' ||
285 c == '-' ||
286 c == '=' ||
287 c == '&' ||
288 c == '#' ||
289 c == '@' ||
290 c == '$');
291
292 }
293
294