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