1 /** \file uri.c \brief Funtions for file URI handling
2  *
3  *  $Author: peltotal $ $Date: 2007/02/28 08:58:01 $ $Revision: 1.13 $
4  *
5  *  MAD-FLUTELIB: Implementation of FLUTE protocol.
6  *  Copyright (c) 2003-2007 TUT - Tampere University of Technology
7  *  main authors/contacts: jani.peltotalo@tut.fi and sami.peltotalo@tut.fi
8  *
9  *  This program is free software; you can redistribute it and/or modify
10  *  it under the terms of the GNU General Public License as published by
11  *  the Free Software Foundation; either version 2 of the License, or
12  *  (at your option) any later version.
13  *
14  *  This program is distributed in the hope that it will be useful,
15  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
16  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  *  GNU General Public License for more details.
18  *
19  *  You should have received a copy of the GNU General Public License
20  *  along with this program; if not, write to the Free Software
21  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
22  *
23  *  In addition, as a special exception, TUT - Tampere University of Technology
24  *  gives permission to link the code of this program with the OpenSSL library (or
25  *  with modified versions of OpenSSL that use the same license as OpenSSL), and
26  *  distribute linked combinations including the two. You must obey the GNU
27  *  General Public License in all respects for all of the code used other than
28  *  OpenSSL. If you modify this file, you may extend this exception to your version
29  *  of the file, but you are not obligated to do so. If you do not wish to do so,
30  *  delete this exception statement from your version.
31  */
32 
33 #include <stdlib.h>
34 #include <stdio.h>
35 #include <string.h>
36 #include <ctype.h>
37 
38 #include "uri.h"
39 
40 /**
41  * This is a private function which sets port number.
42  *
43  * @param uri uri_t structure
44  * @param port port number
45  *
46  */
47 
set_uri_port(uri_t * uri,char * port)48 void set_uri_port(uri_t* uri, char* port) {
49 
50 	if(uri->port != NULL) {
51 		free(uri->port);
52 	}
53 
54 	if(!(uri->port = (char*)calloc((strlen(port) + 1), sizeof(char)))) {
55 		printf("Could not alloc memory for uri->port!\n");
56 		fflush(stdout);
57 	}
58 
59 	memcpy(uri->port, port, strlen(port));
60 }
61 
62 /**
63  * This is a private function which sets password.
64  *
65  * @param uri uri_t structure
66  * @param passwd password
67  *
68  */
69 
set_uri_passwd(uri_t * uri,char * passwd)70 void set_uri_passwd(uri_t* uri, char* passwd) {
71 
72 	if(uri->passwd != NULL) {
73 		free(uri->passwd);
74 	}
75 
76 	if(!(uri->passwd = (char*)calloc((strlen(passwd) + 1), sizeof(char)))) {
77 		printf("Could not alloc memory for uri->passwd!\n");
78 		fflush(stdout);
79 	}
80 
81 	memcpy(uri->passwd, passwd, strlen(passwd));
82 }
83 
84 /**
85  * This is a private function which sets parameter part.
86  *
87  * @param uri uri_t structure
88  * @param params parameter part
89  *
90  */
91 
set_uri_params(uri_t * uri,char * params)92 void set_uri_params(uri_t* uri, char* params) {
93 
94 	if(uri->params != NULL) {
95 		free(uri->params);
96 	}
97 
98 	if(!(uri->params = (char*)calloc((strlen(params) + 1), sizeof(char)))) {
99 		printf("Could not alloc memory for uri->params!\n");
100 		fflush(stdout);
101 	}
102 
103 	memcpy(uri->params, params, strlen(params));
104 }
105 
106 /**
107  * This is a private function which sets query part.
108  *
109  * @param uri uri_t structure
110  * @param query query part
111  *
112  */
113 
set_uri_query(uri_t * uri,char * query)114 void set_uri_query(uri_t* uri, char* query) {
115 
116 	if(uri->query != NULL) {
117 		free(uri->query);
118 	}
119 
120 	if(!(uri->query = (char*)calloc((strlen(query) + 1), sizeof(char)))) {
121 		printf("Could not alloc memory for uri->query!\n");
122 		fflush(stdout);
123 	}
124 
125 	memcpy(uri->query, query, strlen(query));
126 }
127 
128 /**
129  * This is a private function which sets fragment part.
130  *
131  * @param uri uri_t structure
132  * @param frag fragment
133  *
134  */
135 
set_uri_frag(uri_t * uri,char * frag)136 void set_uri_frag(uri_t* uri, char* frag) {
137 
138 	if(uri->frag != NULL) {
139 		free(uri->frag);
140 	}
141 
142 	if(!(uri->frag = (char*)calloc((strlen(frag) + 1), sizeof(char)))) {
143 		printf("Could not alloc memory for uri->frag!\n");
144 		fflush(stdout);
145 	}
146 
147 	memcpy(uri->frag, frag, strlen(frag));
148 }
149 
150 /**
151  * This is a private function which parses path part of the URI string
152  * and stores the result to the uri_t structure.
153  *
154  * @param uri uri_t structure
155  * @param uri_pointer pointer to path part of the URI string
156  *
157  * @return pointer to the next character after path part
158  *
159  */
160 
parse_path(uri_t * uri,char * uri_pointer)161 char* parse_path(uri_t* uri, char* uri_pointer) {
162 
163 	char *new_uri_pointer = NULL;
164 	char* start = uri_pointer;
165 	char* path_start = (char*)start;
166 	char* path_end;
167 
168 	if((path_end = strchr(start, '#'))) {
169 		*path_end = '\0';
170 
171 		set_uri_path(uri, path_start);
172 		new_uri_pointer = path_end + 1;
173 	}
174 	else {
175 		set_uri_path(uri, start);
176 		return NULL;
177 	}
178 
179 	return new_uri_pointer;
180 }
181 
182 /**
183  * This is a private function which parses parameter part of the URI string
184  * and stores the result to the uri_t structure.
185  *
186  * @param uri uri_t structure
187  * @param uri_pointer pointer to parameter part of the URI string
188  *
189  * @return pointer to the next character after parameter part
190  *
191  */
192 
parse_params(uri_t * uri,char * uri_pointer)193 char* parse_params(uri_t* uri, char* uri_pointer) {
194 
195 	char *new_uri_pointer = NULL;
196 	char *scheme = NULL;
197 	int scheme_length = 0;
198 
199 	char* start = uri_pointer;
200 	char* end;
201 
202 	while(*start && isspace((int)*start)) {
203 		start++;
204 	}
205 
206 	end = start;
207 
208 	while(*end && (isalnum((int)*end) || *end == '+' || *end == '-' || *end == '.')) {
209 		end++;
210 	}
211 
212 	if(*end != '\0' && end > start && *end == ':') {
213 		scheme = start;
214 		scheme_length = end - start;
215 		scheme[scheme_length] = '\0';
216 	}
217 	else {
218 		return NULL;
219 	}
220 
221 	if(scheme_length != 0) {
222 
223 		set_uri_scheme(uri, scheme);
224 		new_uri_pointer = scheme + scheme_length + 1;
225 	}
226 
227 	return new_uri_pointer;
228 }
229 
230 /**
231  * This is a private function which parses query part of the URI string
232  * and stores the result to the uri_t structure.
233  *
234  * @param uri uri_t structure
235  * @param uri_pointer pointer to query part of the URI string
236  *
237  * @return pointer to the next character after query part
238  *
239  */
240 
parse_query(uri_t * uri,char * uri_pointer)241 char* parse_query(uri_t* uri, char* uri_pointer) {
242 
243 	char *new_uri_pointer = NULL;
244 	char *scheme = NULL;
245 	int scheme_length = 0;
246 
247 	char* start = uri_pointer;
248 	char* end;
249 
250 	while(*start && isspace((int)*start)) {
251 		start++;
252 	}
253 
254 	end = start;
255 
256 	while(*end && (isalnum((int)*end) || *end == '+' || *end == '-' || *end == '.')) {
257 		end++;
258 	}
259 
260 	if(*end != '\0' && end > start && *end == ':') {
261 		scheme = start;
262 		scheme_length = end - start;
263 		scheme[scheme_length] = '\0';
264 	}
265 	else {
266 		return NULL;
267 	}
268 
269 	if(scheme_length != 0) {
270 
271 		set_uri_scheme(uri, scheme);
272 		new_uri_pointer = scheme + scheme_length + 1;
273 	}
274 
275 	return new_uri_pointer;
276 }
277 
278 /**
279  * This is a private function which parses fragment part of the URI string
280  * and stores the result to the uri_t structure.
281  *
282  * @param uri uri_t structure
283  * @param uri_pointer pointer to fragment part of the URI string
284  *
285  * @return pointer to the next character after fragment part
286  *
287  */
288 
parse_frag(uri_t * uri,char * uri_pointer)289 char* parse_frag(uri_t* uri, char* uri_pointer) {
290 
291 	set_uri_frag(uri, uri_pointer);
292 
293 	return NULL;
294 }
295 
296 /**
297  * This is a private function which parses scheme of the URI string
298  * and stores the result to the uri_t structure.
299  *
300  * @param uri uri_t structure
301  * @param uri_pointer pointer to scheme of the URI string
302  *
303  * @return pointer to the next character after scheme part
304  *
305  */
306 
parse_scheme(uri_t * uri,char * uri_pointer)307 char* parse_scheme(uri_t* uri, char* uri_pointer) {
308 
309 	char *new_uri_pointer = NULL;
310 	char *scheme = NULL;
311 	int scheme_length = 0;
312 
313 	char* start = uri_pointer;
314 	char* end;
315 
316 	while(*start && isspace((int)*start)) {
317 		start++;
318 	}
319 
320 	end = start;
321 
322 	while(*end && (isalnum((int)*end) || *end == '+' || *end == '-' || *end == '.')) {
323 		end++;
324 	}
325 
326 	if(*end != '\0' && end > start && *end == ':') {
327 		scheme = start;
328 		scheme_length = end - start;
329 		scheme[scheme_length] = '\0';
330 	}
331 	else {
332 		new_uri_pointer = uri_pointer;
333 	}
334 
335 	if(scheme_length != 0) {
336 
337 		end = scheme;
338 
339         	while(*end) {
340                 	*end = tolower((int)*end);
341                 	end++;
342         	}
343 
344 		set_uri_scheme(uri, scheme);
345 		new_uri_pointer = scheme + scheme_length + 1;
346 	}
347 
348 	return new_uri_pointer;
349 }
350 
351 /**
352  * This is a private function which parses userinfo part of the URI string
353  * and stores the result to the uri_t structure.
354  *
355  * @param uri uri_t structure
356  * @param uri_pointer pointer to userinfo part of the URI string
357  *
358  * @return pointer to the next character after userinfo part
359  *
360  */
361 
parse_userinfo(uri_t * uri,char * uri_pointer)362 char* parse_userinfo(uri_t *uri, char *uri_pointer) {
363 
364 	char *new_uri_pointer = NULL;
365 	char* start = uri_pointer;
366 	char* end;
367 	char* user_start = start;
368 	char* user_end;
369 
370 	if((end = strchr(start, '@'))) {
371 		*end = '\0';
372 
373 		if((user_end = strchr(user_start, ':'))) {
374 			*user_end = '\0';
375 
376 			set_uri_user(uri, user_start);
377 			set_uri_passwd(uri, (user_end + 1));
378 		}
379 		else {
380 			set_uri_user(uri, start);
381 		}
382 
383 		new_uri_pointer = end + 1;
384 	}
385 	else {
386 		new_uri_pointer = uri_pointer;
387 	}
388 
389 	return new_uri_pointer;
390 }
391 
392 /**
393  * This is a private function which parses host and port part of the URI string
394  * and stores the result to the uri_t structure.
395  *
396  * @param uri uri_t structure
397  * @param uri_pointer pointer to host and port part of the URI string
398  *
399  * @return pointer to the next character after host and port part
400  *
401  */
402 
parse_hostport(uri_t * uri,char * uri_pointer)403 char* parse_hostport(uri_t* uri, char* uri_pointer) {
404 
405 	char *new_uri_pointer = NULL;
406 	char* start;
407 	char* end;
408 	char* host_start;
409 	char* host_end;
410 
411 	start = uri_pointer;
412 	end = start + strlen(uri_pointer);
413 	host_start = start;
414 
415 	if((host_end = strchr(host_start, ':'))) {
416 		*host_end = '\0';
417 		set_uri_host(uri, host_start);
418 		set_uri_port(uri, (host_end + 1));
419 	}
420 	else {
421 		set_uri_host(uri, start);
422 	}
423 
424 	new_uri_pointer = end + 1;
425 
426 	return new_uri_pointer;
427 }
428 
429 /**
430  * This is a private function which parses authority part of the URI string
431  * and stores the result to the uri_t structure.
432  *
433  * @param uri uri_t structure
434  * @param uri_pointer pointer to authority part of the URI string
435  *
436  * @return pointer to the next character after authority part
437  *
438  */
439 
parse_authority(uri_t * uri,char * uri_pointer)440 char* parse_authority(uri_t* uri, char* uri_pointer) {
441 
442 	char *new_uri_pointer = NULL;
443 	char *userinfo = NULL;
444 	char *hostport = NULL;
445 	char* start = uri_pointer;
446 	char* end;
447 
448 	if(start[0] == '/' && start[1] == '/' && start[2] == '/') {
449 		/* Authority part not present */
450 		new_uri_pointer = start + 3;
451 	}
452 	else if(start[0] == '/' && start[1] == '/') {
453 		/* Authority part present */
454 
455 		start += 2;
456 		userinfo = start;
457 		end = start;
458 
459 		while(*end && *end != '/') {
460 			end++;
461 		}
462 
463 		*end = '\0';
464 
465 		new_uri_pointer = end + 1;
466 
467 		hostport = parse_userinfo(uri, userinfo);
468 		new_uri_pointer = parse_hostport(uri, hostport);
469 
470 	}
471 	else {
472 	  new_uri_pointer = start;
473 	}
474 
475 	return new_uri_pointer;
476 }
477 
478 /**
479  * This is a private function which returns hostname part of the URI.
480  *
481  * @param uri uri_t structure
482  *
483  * @return hostname part of the URI
484  *
485  */
486 
get_uri_host(uri_t * uri)487 char* get_uri_host(uri_t* uri) {
488 	return uri->host;
489 }
490 
491 /**
492  * This is a private function which returns port part of the URI.
493  *
494  * @param uri uri_t structure
495  *
496  * @return port part of the URI
497  *
498  */
499 
get_uri_port(uri_t * uri)500 char* get_uri_port(uri_t* uri) {
501 	return uri->port;
502 }
503 
504 /**
505  * This is a private function which returns path part of the URI.
506  *
507  * @param uri uri_t structure
508  *
509  * @return path part of the URI
510  *
511  */
512 
get_uri_path(uri_t * uri)513 char* get_uri_path(uri_t* uri) {
514 	return uri->path;
515 }
516 
517 /**
518  * This is a private function which returns parameter part of the URI.
519  *
520  * @param uri uri_t structure
521  *
522  * @return parameter part of the URI
523  *
524  */
525 
get_uri_params(uri_t * uri)526 char* get_uri_params(uri_t* uri) {
527 	return uri->params;
528 }
529 
530 /**
531  * This is a private function which returns query part of the URI.
532  *
533  * @param uri uri_t structure
534  *
535  * @return query part of the URI
536  *
537  */
538 
get_uri_query(uri_t * uri)539 char* get_uri_query(uri_t* uri) {
540 	return uri->query;
541 }
542 
543 /**
544  * This is a private function which returns fragment part of the URI.
545  *
546  * @param uri uri_t structure
547  *
548  * @return fragment part of the URI
549  *
550  */
551 
get_uri_frag(uri_t * uri)552 char* get_uri_frag(uri_t* uri) {
553 	return uri->frag;
554 }
555 
556 /**
557  * This is a private function which returns user part of the URI.
558  *
559  * @param uri uri_t structure
560  *
561  * @return user part of the URI
562  *
563  */
564 
get_uri_user(uri_t * uri)565 char* get_uri_user(uri_t* uri) {
566 	return uri->user;
567 }
568 
569 /**
570  * This is a private function which returns password part of the URI.
571  *
572  * @param uri uri_t structure
573  *
574  * @return password part of the URI
575  *
576  */
577 
get_uri_passwd(uri_t * uri)578 char* get_uri_passwd(uri_t* uri) {
579 	return uri->passwd;
580 }
581 
582 /**
583  * This is a private function which returns scheme part of the URI.
584  *
585  * @param uri uri_t structure
586  *
587  * @return scheme part of the URI
588  *
589  */
590 
get_uri_scheme(uri_t * uri)591 char* get_uri_scheme(uri_t* uri) {
592 	return uri->scheme;
593 }
594 
alloc_uri_struct(void)595 uri_t* alloc_uri_struct(void) {
596 
597 	uri_t *uri = NULL;
598 
599 	if(!(uri = (uri_t*)calloc(1, sizeof(uri_t)))) {
600 		printf("Could not alloc memory for uri structure!\n");
601 	}
602 
603 	return uri;
604 }
605 
parse_uri(char * uri_string,int len)606 uri_t* parse_uri(char* uri_string, int len) {
607 
608 	uri_t* uri = NULL;
609 	char* tmp_uri = NULL;
610 	char* uri_pointer = NULL;
611 
612 	if(!(tmp_uri = (char*)calloc((strlen(uri_string) + 1), sizeof(char)))) {
613 		printf("Could not alloc memory for tmp (uri string)!\n");
614 		return NULL;
615 	}
616 
617 	memcpy(tmp_uri, uri_string, strlen(uri_string));
618 
619 	if(!(uri = (uri_t*)calloc(1, sizeof(uri_t)))) {
620 		printf("Could not alloc memory for uri structure!\n");
621 		free(tmp_uri);
622 		return NULL;
623 	}
624 
625 	uri_pointer = parse_scheme(uri, tmp_uri);
626 
627 	if(strcmp(uri_pointer, uri_string) == 0) {
628 
629 		uri_pointer = parse_path(uri, uri_pointer);
630 
631 		if(uri_pointer != NULL) {
632 			uri_pointer = parse_frag(uri, uri_pointer);
633 		}
634 	}
635 	else {
636 		uri_pointer = parse_authority(uri, uri_pointer);
637 		uri_pointer = parse_path(uri, uri_pointer);
638 
639 		if(uri_pointer != NULL) {
640 			uri_pointer = parse_frag(uri, uri_pointer);
641 		}
642 	}
643 
644 	free(tmp_uri);
645 	return uri;
646 }
647 
uri_string(uri_t * uri)648 char* uri_string(uri_t *uri) {
649 
650 	char *uri_str;
651 	int len = 0;
652 
653 	if(uri->scheme != NULL) {
654 		len += strlen(uri->scheme);
655 		len += 3; /* '://' */
656 	}
657 
658 	if(strcmp(uri->scheme, "file") == 0) {
659 		if(uri->host != NULL) {
660 			len += strlen(uri->host);
661 		}
662 		if(uri->port != NULL) {
663 			len += strlen(uri->port);
664 			len += 1; /* ':' */
665 		}
666 		if(uri->path != NULL) {
667 			len += 1; /* '/' */
668 			len += strlen(uri->path);
669 		}
670 		/* TODO: add more */
671 	}
672 	if(strcmp(uri->scheme, "ftp") == 0) {
673 		/* TODO */
674 	}
675 	if(strcmp(uri->scheme, "http") == 0) {
676 		/* TODO */
677 	}
678 
679 	if(!(uri_str = (char*)calloc((len + 1), sizeof(char)))) {
680 		printf("Could not alloc memory for uri string!\n");
681 		fflush(stdout);
682 		return NULL;
683 	}
684 
685 	if(uri->scheme != NULL) {
686 		strcat(uri_str, uri->scheme);
687 		strcat(uri_str, "://");
688 	}
689 
690 	if(strcmp(uri->scheme, "file") == 0) {
691 		if(uri->host != NULL) {
692 			strcat(uri_str, uri->host);
693 		}
694 		if(uri->port != NULL) {
695 			strcat(uri_str, ":");
696 			strcat(uri_str, uri->port);
697 		}
698 		if(uri->path != NULL) {
699 			strcat(uri_str, "/");
700 			strcat(uri_str, uri->path);
701 		}
702 		/* TODO: add more */
703 	}
704 	if(strcmp(uri->scheme, "ftp") == 0) {
705 		/* TODO */
706 	}
707 	if(strcmp(uri->scheme, "http") == 0) {
708 		/* TODO */
709 	}
710 
711     return uri_str;
712 }
713 
free_uri(uri_t * uri)714 void free_uri(uri_t* uri) {
715 
716 	if(uri->scheme != NULL) {
717 		free(uri->scheme);
718 	}
719 	if(uri->host != NULL) {
720 		free(uri->host);
721 	}
722 	if(uri->port != NULL) {
723 		free(uri->port);
724 	}
725 	if(uri->path != NULL) {
726 		free(uri->path);
727 	}
728 	if(uri->params != NULL) {
729 		free(uri->params);
730 	}
731 	if(uri->query != NULL) {
732 		free(uri->query);
733 	}
734 	if(uri->frag != NULL) {
735 		free(uri->frag);
736 	}
737 	if(uri->user != NULL) {
738 		free(uri->user);
739 	}
740 	if(uri->passwd != NULL) {
741 		free(uri->passwd);
742 	}
743 
744 	free(uri);
745 }
746 
get_uri_host_and_path(uri_t * uri)747 char* get_uri_host_and_path(uri_t* uri) {
748 
749 	char *tmp = NULL;
750 	int len = 0;
751 
752 	if(uri->host != NULL) {
753 		len += strlen(uri->host);
754 		len += 1;
755 	}
756 
757 	len += strlen(uri->path);
758 
759 	if(!(tmp = (char*)calloc((len + 1), sizeof(char)))) {
760 		printf("Could not alloc memory for tmp (get_uri_host_and_path)!\n");
761 		fflush(stdout);
762 		return NULL;
763 	}
764 
765 	if(uri->host != NULL) {
766 		strcat(tmp, uri->host);
767 		strcat(tmp, "/");
768 	}
769 
770 	strcat(tmp, uri->path);
771 
772 	return tmp;
773 }
774 
set_uri_scheme(uri_t * uri,char * scheme)775 void set_uri_scheme(uri_t* uri, char* scheme) {
776 
777 	if(uri->scheme != NULL) {
778 		free(uri->scheme);
779 	}
780 
781 	if(!(uri->scheme = (char*)calloc((strlen(scheme) + 1), sizeof(char)))) {
782 		printf("Could not alloc memory for uri->scheme!\n");
783 		fflush(stdout);
784 	}
785 
786 	memcpy(uri->scheme, scheme, strlen(scheme));
787 }
788 
set_uri_user(uri_t * uri,char * user)789 void set_uri_user(uri_t* uri, char* user) {
790 
791 	if(uri->user != NULL) {
792 		free(uri->user);
793 	}
794 
795 	if(!(uri->user = (char*)calloc((strlen(user) + 1), sizeof(char)))) {
796 		printf("Could not alloc memory for uri->user!\n");
797 		fflush(stdout);
798 	}
799 
800 	memcpy(uri->user, user, strlen(user));
801 }
802 
set_uri_host(uri_t * uri,char * host)803 void set_uri_host(uri_t* uri, char* host) {
804 
805 	if(uri->host != NULL) {
806 		free(uri->host);
807 	}
808 
809 	if(!(uri->host = (char*)calloc((strlen(host) + 1), sizeof(char)))) {
810 		printf("Could not alloc memory for uri->host!\n");
811 		fflush(stdout);
812 	}
813 
814 	memcpy(uri->host, host, strlen(host));
815 }
816 
set_uri_path(uri_t * uri,char * path)817 void set_uri_path(uri_t* uri, char* path) {
818 
819 	if(uri->path != NULL) {
820 		free(uri->path);
821 	}
822 
823 	if(!(uri->path = (char*)calloc((strlen(path) + 1), sizeof(char)))) {
824 		printf("Could not alloc memory for uri->path!\n");
825 		fflush(stdout);
826 	}
827 
828 	memcpy(uri->path, path, strlen(path));
829 }
830