"Fossies" - the Fresh Open Source Software Archive 
Member "zsync-0.6.2/url.c" (16 Sep 2010, 4868 Bytes) of package /linux/privat/old/zsync-0.6.2.tar.gz:
As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style:
standard) with prefixed line numbers and
code folding option.
Alternatively you can here
view or
download the uninterpreted source code file.
For more information about "url.c" see the
Fossies "Dox" file reference documentation.
1
2 /*
3 * zsync - client side rsync over http
4 * Copyright (C) 2004,2005,2009 Colin Phipps <cph@moria.org.uk>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the Artistic License v2 (see the accompanying
8 * file COPYING for the full license terms), or, at your option, any later
9 * version of the same license.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * COPYING file for details.
15 */
16
17 /* Very crude URL parsing module */
18
19 #include "zsglobal.h"
20
21 #include <string.h>
22 #include <stdlib.h>
23
24 #ifdef WITH_DMALLOC
25 # include <dmalloc.h>
26 #endif
27
28 #include "url.h"
29
30 const char http_scheme[] = { "http://" };
31
32 /* path_str = get_http_host_port(url_str, &host, host_len, &port_str)
33 * For the given url_str, returns:
34 * the hostname, in host[] array provided by caller (up to length host_len)
35 * the port (if any) as a malloced string, pointer to this stored in *port_str
36 * return value is the path part of the URL, a malloced string.
37 * Or return value NULL on failure (host and port could have been written to).
38 */
39 char *get_http_host_port(const char *url, char *hostn, int hnlen, char **port) {
40 char *p, *q;
41
42 /* Check it's HTTP */
43 if (memcmp(url, http_scheme, strlen(http_scheme)))
44 return NULL;
45
46 q = url + strlen(http_scheme);
47
48 p = strchr(q, ':');
49 if (p) { /* if : is after the first /, we have looked too far ahead */
50 char *r = strchr(q, '/');
51 if (r && r < p)
52 p = NULL;
53 }
54 if (!p) {
55 *port = strdup("http");
56 p = strchr(q, '/');
57 }
58
59 if (!p)
60 return NULL;
61
62 if (p - q < hnlen - 1) {
63 memcpy(hostn, q, p - q);
64 hostn[p - q] = 0;
65 }
66
67 if (*p == ':') {
68 size_t l;
69 q = p;
70 p = strchr(p, '/');
71 l = p ? (size_t) (p - q - 1) : strlen(q) - 1;
72 *port = malloc(l + 1);
73 if (!*port)
74 return NULL;
75 memcpy(*port, q + 1, l);
76 (*port)[l] = 0;
77 if (!p)
78 p = strdup("/");
79 }
80 return p;
81 }
82
83 /* abs_url_str = make_url_absolute(base_str, url_str)
84 * Returns an absolute version of url_str relative to base_str, as a malloced
85 * string. Or NULL on error. */
86 char * __attribute__ ((pure)) make_url_absolute(const char *base, const char *url) {
87 if (is_url_absolute(url))
88 return strdup(url);
89
90 /* Otherwise, we'll need a base URL to get the scheme and host */
91 if (!base)
92 return NULL;
93
94 /* Next, is it a full-path URL? */
95 if (*url == '/') {
96 size_t l;
97 char *newurl;
98
99 /* Find the end of the scheme of the base URL, then the end of the
100 * hostname[:port]/ */
101 const char *p = strchr(base, ':');
102 if (!p || p[1] != '/' || p[2] != '/')
103 return NULL;
104 p = strchr(p + 3, '/');
105 if (!p) /* We have a http://hostname URL (no trailing / or path) */
106 l = strlen(base);
107 else /* http://hostname/... , we want just http://hostname */
108 l = p - base;
109
110 /* assert */
111 if (base[l] != '/' && base[l] != '\0')
112 return NULL;
113
114 /* Append full path to the base http://hostname */
115 newurl = malloc(l + strlen(url) + 1);
116 memcpy(newurl, base, l);
117 strcpy(newurl + l, url);
118 return newurl;
119 }
120
121 /* No leading / or scheme - relative path */
122 {
123 int l;
124 char *newurl;
125
126 /* Find the end of the path part of the base URL */
127 const char *q;
128 const char *p = strchr(base, '?');
129 if (!p)
130 p = strchr(base, '#');
131 if (!p)
132 p = base + strlen(base);
133
134 /* Find the last / in the path part */
135 for (q = p; q > base && *q != '/'; q--);
136 if (*q != '/')
137 return NULL;
138
139 /* Take the base URL up to and including the last /, and append the relative URL */
140 l = q - base + 1;
141 newurl = malloc(l + strlen(url) + 1);
142 memcpy(newurl, base, l);
143 strcpy(newurl + l, url);
144 return newurl;
145 }
146 }
147
148 /* int n = is_url_absolute(url)
149 * Returns 0 if the supplied string is not an absolute URL.
150 * Returns the number of characters in the URL scheme if it is.
151 */
152 static const char special[] = { ":/?" };
153
154 int __attribute__ ((pure)) is_url_absolute(const char *url) {
155 /* find end of first no-special-URL-characters part of the string */
156 int n = strcspn(url, special);
157
158 /* If the first special character is a :, the start is a URL scheme */
159 if (n > 0 && url[n] == ':')
160 return n;
161
162 /* otherwise, it's a full path or relative path URL, or just a local file
163 * path (caller knows the context) */
164 return 0;
165 }