1 /* Utilities for VFS modules.
3 Currently includes login and tcp open socket routines.
5 Copyright (C) 1995, 1996 Miguel de Icaza
7 This program is free software; you can redistribute it and/or
8 modify it under the terms of the GNU Library General Public License
9 as published by the Free Software Foundation; either version 2 of
10 the License, or (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU Library General Public License for more details.
17 You should have received a copy of the GNU Library General Public
18 License along with this program; if not, write to the Free Software
19 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
21 /* Namespace: exports vfs_split_url */
23 #ifndef test_get_host_and_username
33 #include <sys/types.h>
35 #include <sys/socket.h>
36 #include <netinet/in.h>
37 #ifdef HAVE_ARPA_INET_H
38 #include <arpa/inet.h>
46 /* Extract the hostname and username from the path */
47 /* path is in the form: [user@]hostname:port/remote-dir, e.g.:
49 * ftp://sunsite.unc.edu/pub/linux
50 * ftp://miguel@sphinx.nuclecu.unam.mx/c/nc
51 * ftp://tsx-11.mit.edu:8192/
52 * ftp://joe@foo.edu:11321/private
53 * ftp://joe:password@foo.se
55 * Returns malloc()ed host, user and pass they are present.
56 * If the user is empty, e.g. ftp://@roxanne/private, and URL_ALLOW_ANON
57 * is not set, then the current login name is supplied.
59 * Return value is a malloc()ed string with the pathname relative to the
63 char *vfs_split_url (const char *path
, char **host
, char **user
,
64 int *port
, char **pass
, int default_port
, int flags
)
66 struct passwd
*passwd_info
;
67 char *dir
, *colon
, *inner_colon
, *at
, *rest
;
69 char *pcopy
= g_strdup (path
);
70 char *pend
= pcopy
+ strlen (pcopy
);
79 if (!(flags
& URL_NOSLASH
)) {
80 /* locate path component */
81 while (*dir
!= PATH_SEP
&& *dir
)
84 retval
= g_strdup (dir
);
87 retval
= g_strdup (PATH_SEP_STR
);
90 /* search for any possible user */
91 at
= strchr (pcopy
, '@');
93 /* We have a username */
96 inner_colon
= strchr (pcopy
, ':');
101 *pass
= g_strdup (inner_colon
);
104 *user
= g_strdup (pcopy
);
113 if (!*user
&& !(flags
& URL_ALLOW_ANON
)) {
114 passwd_info
= getpwuid (geteuid ());
115 if (passwd_info
&& passwd_info
->pw_name
)
116 *user
= g_strdup (passwd_info
->pw_name
);
118 /* This is very unlikely to happen */
119 *user
= g_strdup ("anonymous");
124 /* Check if the host comes with a port spec, if so, chop it */
125 colon
= strchr (rest
, ':');
128 if (sscanf(colon
+1, "%d", port
)==1) {
129 if (*port
<= 0 || *port
>= 65536)
130 *port
= default_port
;
143 *host
= g_strdup (rest
);
149 #ifdef test_get_host_and_username
159 struct tt tests
[] = {
160 { "host", "host", "anonymous", NULL
, "/", 21 },
161 { "host/dir", "host", "anonymous", NULL
, "/dir", 21 },
162 { "host:40/", "host", "anonymous", NULL
, "/", 40 },
163 { "host:40/dir", "host", "anonymous", NULL
, "/dir", 40 },
164 { "user@host", "host", "user", NULL
, "/", 21 },
165 { "user@host/dir", "host", "user", NULL
, "/dir", 21 },
166 { "user@host:40/", "host", "user", NULL
, "/", 40 },
167 { "user@host:40/dir", "host", "user", NULL
, "/dir", 40 },
168 { "user:pass@host", "host", "user", "pass", "/", 21 },
169 { "user:pass@host/dir", "host", "user", "pass", "/dir", 21 },
170 { "user:pass@host:40", "host", "user", "pass", "/", 40 },
171 { "user:pass@host:40/dir", "host", "user", "pass", "/dir", 40 },
172 { "host/a@b", "host", "anonymous", NULL
, "/a@b", 21 },
173 { "host:40/a@b", "host", "anonymous", NULL
, "/a@b", 40 },
174 { "user@host/a@b", "host", "user", NULL
, "/a@b", 21 },
175 { "user@host:40/a@b", "host", "user", NULL
, "/a@b", 40 },
176 { "user:pass@host/a@b", "host", "user", "pass", "/a@b", 21 },
177 { "user:pass@host:40/a@b", "host", "user", "pass", "/a@b", 40 },
178 { "host/a:b", "host", "anonymous", NULL
, "/a:b", 21 },
179 { "host:40/a:b", "host", "anonymous", NULL
, "/a:b", 40 },
180 { "user@host/a:b", "host", "user", NULL
, "/a:b", 21 },
181 { "user@host:40/a:b", "host", "user", NULL
, "/a:b", 40 },
182 { "user:pass@host/a:b", "host", "user", "pass", "/a:b", 21 },
183 { "user:pass@host:40/a:b", "host", "user", "pass", "/a:b", 40 },
184 { "host/a/b", "host", "anonymous", NULL
, "/a/b", 21 },
185 { "host:40/a/b", "host", "anonymous", NULL
, "/a/b", 40 },
186 { "user@host/a/b", "host", "user", NULL
, "/a/b", 21 },
187 { "user@host:40/a/b", "host", "user", NULL
, "/a/b", 40 },
188 { "user:pass@host/a/b", "host", "user", "pass", "/a/b", 21 },
189 { "user:pass@host:40/a/b", "host", "user", "pass", "/a/b", 40 },
193 /* tests with implicit login name */
194 struct tt tests2
[] = {
195 { "@host", "host", "user", NULL
, "/", 21 },
196 { "@host/dir", "host", "user", NULL
, "/dir", 21 },
197 { "@host:40/", "host", "user", NULL
, "/", 40 },
198 { "@host:40/dir", "host", "user", NULL
, "/dir", 40 },
199 { ":pass@host", "host", "user", "pass", "/", 21 },
200 { ":pass@host/dir", "host", "user", "pass", "/dir", 21 },
201 { ":pass@host:40", "host", "user", "pass", "/", 40 },
202 { ":pass@host:40/dir", "host", "user", "pass", "/dir", 40 },
203 { "@host/a@b", "host", "user", NULL
, "/a@b", 21 },
204 { "@host:40/a@b", "host", "user", NULL
, "/a@b", 40 },
205 { ":pass@host/a@b", "host", "user", "pass", "/a@b", 21 },
206 { ":pass@host:40/a@b", "host", "user", "pass", "/a@b", 40 },
207 { "@host/a:b", "host", "user", NULL
, "/a:b", 21 },
208 { "@host:40/a:b", "host", "user", NULL
, "/a:b", 40 },
209 { ":pass@host/a:b", "host", "user", "pass", "/a:b", 21 },
210 { ":pass@host:40/a:b", "host", "user", "pass", "/a:b", 40 },
211 { "@host/a/b", "host", "user", NULL
, "/a/b", 21 },
212 { "@host:40/a/b", "host", "user", NULL
, "/a/b", 40 },
213 { ":pass@host/a/b", "host", "user", "pass", "/a/b", 21 },
214 { ":pass@host:40/a/b", "host", "user", "pass", "/a/b", 40 },
221 char *dir
, *host
, *user
, *pass
;
222 struct passwd
*passwd_info
;
225 if ((passwd_info
= getpwuid (geteuid ())) == NULL
)
226 current
= g_strdup ("anonymous");
228 current
= g_strdup (passwd_info
->pw_name
);
232 for (i
= 0; tests
[i
].url
; i
++){
234 dir
= get_host_and_username (tests
[i
].url
, &host
, &user
, &port
, 21, 1, &pass
);
236 if (strcmp (dir
, tests
[i
].r_dir
))
237 err
++, printf ("dir: test %d flunked\n", i
);
239 if (!err
&& strcmp (host
, tests
[i
].r_host
))
240 err
++, printf ("host: test %d flunked\n", i
);
242 if (!err
&& strcmp (user
, tests
[i
].r_user
))
243 err
++, printf ("user: test %d flunked\n", i
);
245 if (!err
&& tests
[i
].r_pass
)
246 if (strcmp (dir
, tests
[i
].r_dir
))
247 err
++, printf ("pass: test %d flunked\n", i
);
249 if (!err
& tests
[i
].r_port
!= port
)
250 err
++, printf ("port: test %d flunked\n", i
);
253 printf ("host=[%s] user=[%s] pass=[%s] port=[%d]\n",
254 host
, user
, pass
, port
);
258 printf ("%d tests ok\nExtra tests:", i
);
260 for (i
= 0; i
< 4; i
++){
261 dir
= get_host_and_username (tests
[i
].url
, &host
, &user
, &port
, 21, 0, &pass
);
262 if (strcmp (user
, current
))
263 printf ("ntest: flunked %d\n", i
);
266 printf ("%d tests ok\nTests with implicit login name\n", i
);
268 for (i
= 0; tests2
[i
].url
; i
++){
270 dir
= get_host_and_username (tests2
[i
].url
, &host
, &user
, &port
, 21, 1, &pass
);
272 if (strcmp (dir
, tests2
[i
].r_dir
))
273 err
++, printf ("dir: test %d flunked\n", i
);
275 if (!err
&& strcmp (host
, tests2
[i
].r_host
))
276 err
++, printf ("host: test %d flunked\n", i
);
278 if (!err
&& strcmp (user
, current
))
279 err
++, printf ("user: test %d flunked\n", i
);
281 if (!err
&& tests2
[i
].r_pass
)
282 if (strcmp (dir
, tests2
[i
].r_dir
))
283 err
++, printf ("pass: test %d flunked\n", i
);
285 if (!err
& tests2
[i
].r_port
!= port
)
286 err
++, printf ("port: test %d flunked\n", i
);
289 printf ("host=[%s] user=[%s] pass=[%s] port=[%d]\n",
290 host
, user
, pass
, port
);
293 printf ("%d tests ok\n", i
);