Rename e{malloc,realloc,free} to u{malloc,realloc,free}, to more obviously
[people/xl0/gpxe.git] / src / core / url.c
1 #include "string.h"
2 #include "resolv.h"
3 #include "etherboot.h" /* for arptable */
4 #include "url.h"
5
6 /*
7  * Parse a URL and deduce a struct protocol *, a struct sockaddr_in
8  * and a char *filename.
9  *
10  * We accept URLs of the form
11  *
12  *   [protocol://[host][:port]/]path/to/file
13  *
14  * Returns 1 for success, 0 for failure (e.g. unknown protocol).
15  *
16  */
17 int parse_url ( char *url, struct protocol **proto,
18                 struct sockaddr_in *server, char **filename ) {
19         char *p;
20         char *protocol = NULL;
21         char *host = NULL;
22         char *port = NULL;
23         int rc = 0;
24
25         DBG ( "URL parsing \"%s\"\n", url );
26
27         /* If no protocol is present, the whole URL will be a filename */
28         *filename = url;
29
30         /* Search for a protocol delimiter.  If found, parse out the
31          * host and port parts of the URL, inserting NULs to terminate
32          * the different sections.
33          */
34         for ( p = url ; *p ; p++ ) {
35                 if ( memcmp ( p, "://", 3 ) != 0 )
36                         continue;
37
38                 /* URL has an explicit protocol */
39                 *p = '\0';
40                 p += 3;
41                 protocol = url;
42                 host = p;
43
44                 /* Search for port and file delimiters */
45                 for ( ; *p ; p++ ) {
46                         if ( *p == ':' ) {
47                                 *p = '\0';
48                                 port = p + 1;
49                                 continue;
50                         }
51                         if ( *p == '/' ) {
52                                 *(p++) = '\0';
53                                 break;
54                         }
55                 }
56                 *filename = p;
57
58                 break;
59         }
60         DBG ( "URL protocol \"%s\" host \"%s\" port \"%s\" file \"%s\"\n",
61               protocol ? protocol : "(default)", host ? host : "(default)",
62               port ? port : "(default)", *filename );
63
64         /* Identify the protocol */
65         *proto = identify_protocol ( protocol );
66         if ( ! *proto ) {
67                 DBG ( "URL unknown protocol \"%s\"\n",
68                       protocol ? protocol : "(default)" );
69                 goto out;
70         }
71
72         /* Identify the host */
73         server->sin_addr = arptable[ARP_SERVER].ipaddr;
74         if ( host && host[0] ) {
75                 if ( ! resolv ( &server->sin_addr, host ) ) {
76                         DBG ( "URL unknown host \"%s\"\n", host );
77                         goto out;
78                 }
79         }
80
81         /* Identify the port */
82         server->sin_port = (*proto)->default_port;
83         if ( port && port[0] ) {
84                 server->sin_port = strtoul ( port, NULL, 10 );
85         }
86
87         rc = 1;
88
89  out:
90         /* Fill back in the original URL */
91         if ( protocol ) {
92                 (*filename)[-1] = '/';
93                 if ( port )
94                         port[-1] = ':';
95                 host[-3] = ':';
96         }
97         return rc;
98 }