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