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 #include <arpa/inet.h>
47 /* Extract the hostname and username from the path */
48 /* path is in the form: [user@]hostname:port/remote-dir, e.g.:
50 * ftp://sunsite.unc.edu/pub/linux
51 * ftp://miguel@sphinx.nuclecu.unam.mx/c/nc
52 * ftp://tsx-11.mit.edu:8192/
53 * ftp://joe@foo.edu:11321/private
54 * ftp://joe:password@foo.se
56 * Returns malloc()ed host, user and pass they are present.
57 * If the user is empty, e.g. ftp://@roxanne/private, and URL_ALLOW_ANON
58 * is not set, then the current login name is supplied.
60 * Return value is a malloc()ed string with the pathname relative to the
64 char *vfs_split_url (const char *path
, char **host
, char **user
,
65 int *port
, char **pass
, int default_port
, int flags
)
67 struct passwd
*passwd_info
;
68 char *dir
, *colon
, *inner_colon
, *at
, *rest
;
70 char *pcopy
= g_strdup (path
);
71 char *pend
= pcopy
+ strlen (pcopy
);
80 if (!(flags
& URL_NOSLASH
)) {
81 /* locate path component */
82 while (*dir
!= PATH_SEP
&& *dir
)
85 retval
= g_strdup (dir
);
88 retval
= g_strdup (PATH_SEP_STR
);
91 /* search for any possible user */
92 at
= strchr (pcopy
, '@');
94 /* We have a username */
97 inner_colon
= strchr (pcopy
, ':');
102 *pass
= g_strdup (inner_colon
);
105 *user
= g_strdup (pcopy
);
114 if (!*user
&& !(flags
& URL_ALLOW_ANON
)) {
115 passwd_info
= getpwuid (geteuid ());
116 if (passwd_info
&& passwd_info
->pw_name
)
117 *user
= g_strdup (passwd_info
->pw_name
);
119 /* This is very unlikely to happen */
120 *user
= g_strdup ("anonymous");
125 /* Check if the host comes with a port spec, if so, chop it */
126 colon
= strchr (rest
, ':');
129 if (sscanf(colon
+1, "%d", port
)==1) {
130 if (*port
<= 0 || *port
>= 65536)
131 *port
= default_port
;
144 *host
= g_strdup (rest
);
150 #ifdef test_get_host_and_username
160 struct tt tests
[] = {
161 { "host", "host", "anonymous", NULL
, "/", 21 },
162 { "host/dir", "host", "anonymous", NULL
, "/dir", 21 },
163 { "host:40/", "host", "anonymous", NULL
, "/", 40 },
164 { "host:40/dir", "host", "anonymous", NULL
, "/dir", 40 },
165 { "user@host", "host", "user", NULL
, "/", 21 },
166 { "user@host/dir", "host", "user", NULL
, "/dir", 21 },
167 { "user@host:40/", "host", "user", NULL
, "/", 40 },
168 { "user@host:40/dir", "host", "user", NULL
, "/dir", 40 },
169 { "user:pass@host", "host", "user", "pass", "/", 21 },
170 { "user:pass@host/dir", "host", "user", "pass", "/dir", 21 },
171 { "user:pass@host:40", "host", "user", "pass", "/", 40 },
172 { "user:pass@host:40/dir", "host", "user", "pass", "/dir", 40 },
173 { "host/a@b", "host", "anonymous", NULL
, "/a@b", 21 },
174 { "host:40/a@b", "host", "anonymous", NULL
, "/a@b", 40 },
175 { "user@host/a@b", "host", "user", NULL
, "/a@b", 21 },
176 { "user@host:40/a@b", "host", "user", NULL
, "/a@b", 40 },
177 { "user:pass@host/a@b", "host", "user", "pass", "/a@b", 21 },
178 { "user:pass@host:40/a@b", "host", "user", "pass", "/a@b", 40 },
179 { "host/a:b", "host", "anonymous", NULL
, "/a:b", 21 },
180 { "host:40/a:b", "host", "anonymous", NULL
, "/a:b", 40 },
181 { "user@host/a:b", "host", "user", NULL
, "/a:b", 21 },
182 { "user@host:40/a:b", "host", "user", NULL
, "/a:b", 40 },
183 { "user:pass@host/a:b", "host", "user", "pass", "/a:b", 21 },
184 { "user:pass@host:40/a:b", "host", "user", "pass", "/a:b", 40 },
185 { "host/a/b", "host", "anonymous", NULL
, "/a/b", 21 },
186 { "host:40/a/b", "host", "anonymous", NULL
, "/a/b", 40 },
187 { "user@host/a/b", "host", "user", NULL
, "/a/b", 21 },
188 { "user@host:40/a/b", "host", "user", NULL
, "/a/b", 40 },
189 { "user:pass@host/a/b", "host", "user", "pass", "/a/b", 21 },
190 { "user:pass@host:40/a/b", "host", "user", "pass", "/a/b", 40 },
194 /* tests with implicit login name */
195 struct tt tests2
[] = {
196 { "@host", "host", "user", NULL
, "/", 21 },
197 { "@host/dir", "host", "user", NULL
, "/dir", 21 },
198 { "@host:40/", "host", "user", NULL
, "/", 40 },
199 { "@host:40/dir", "host", "user", NULL
, "/dir", 40 },
200 { ":pass@host", "host", "user", "pass", "/", 21 },
201 { ":pass@host/dir", "host", "user", "pass", "/dir", 21 },
202 { ":pass@host:40", "host", "user", "pass", "/", 40 },
203 { ":pass@host:40/dir", "host", "user", "pass", "/dir", 40 },
204 { "@host/a@b", "host", "user", NULL
, "/a@b", 21 },
205 { "@host:40/a@b", "host", "user", NULL
, "/a@b", 40 },
206 { ":pass@host/a@b", "host", "user", "pass", "/a@b", 21 },
207 { ":pass@host:40/a@b", "host", "user", "pass", "/a@b", 40 },
208 { "@host/a:b", "host", "user", NULL
, "/a:b", 21 },
209 { "@host:40/a:b", "host", "user", NULL
, "/a:b", 40 },
210 { ":pass@host/a:b", "host", "user", "pass", "/a:b", 21 },
211 { ":pass@host:40/a:b", "host", "user", "pass", "/a:b", 40 },
212 { "@host/a/b", "host", "user", NULL
, "/a/b", 21 },
213 { "@host:40/a/b", "host", "user", NULL
, "/a/b", 40 },
214 { ":pass@host/a/b", "host", "user", "pass", "/a/b", 21 },
215 { ":pass@host:40/a/b", "host", "user", "pass", "/a/b", 40 },
222 char *dir
, *host
, *user
, *pass
;
223 struct passwd
*passwd_info
;
226 if ((passwd_info
= getpwuid (geteuid ())) == NULL
)
227 current
= g_strdup ("anonymous");
229 current
= g_strdup (passwd_info
->pw_name
);
233 for (i
= 0; tests
[i
].url
; i
++){
235 dir
= get_host_and_username (tests
[i
].url
, &host
, &user
, &port
, 21, 1, &pass
);
237 if (strcmp (dir
, tests
[i
].r_dir
))
238 err
++, printf ("dir: test %d flunked\n", i
);
240 if (!err
&& strcmp (host
, tests
[i
].r_host
))
241 err
++, printf ("host: test %d flunked\n", i
);
243 if (!err
&& strcmp (user
, tests
[i
].r_user
))
244 err
++, printf ("user: test %d flunked\n", i
);
246 if (!err
&& tests
[i
].r_pass
)
247 if (strcmp (dir
, tests
[i
].r_dir
))
248 err
++, printf ("pass: test %d flunked\n", i
);
250 if (!err
& tests
[i
].r_port
!= port
)
251 err
++, printf ("port: test %d flunked\n", i
);
254 printf ("host=[%s] user=[%s] pass=[%s] port=[%d]\n",
255 host
, user
, pass
, port
);
259 printf ("%d tests ok\nExtra tests:", i
);
261 for (i
= 0; i
< 4; i
++){
262 dir
= get_host_and_username (tests
[i
].url
, &host
, &user
, &port
, 21, 0, &pass
);
263 if (strcmp (user
, current
))
264 printf ("ntest: flunked %d\n", i
);
267 printf ("%d tests ok\nTests with implicit login name\n", i
);
269 for (i
= 0; tests2
[i
].url
; i
++){
271 dir
= get_host_and_username (tests2
[i
].url
, &host
, &user
, &port
, 21, 1, &pass
);
273 if (strcmp (dir
, tests2
[i
].r_dir
))
274 err
++, printf ("dir: test %d flunked\n", i
);
276 if (!err
&& strcmp (host
, tests2
[i
].r_host
))
277 err
++, printf ("host: test %d flunked\n", i
);
279 if (!err
&& strcmp (user
, current
))
280 err
++, printf ("user: test %d flunked\n", i
);
282 if (!err
&& tests2
[i
].r_pass
)
283 if (strcmp (dir
, tests2
[i
].r_dir
))
284 err
++, printf ("pass: test %d flunked\n", i
);
286 if (!err
& tests2
[i
].r_port
!= port
)
287 err
++, printf ("port: test %d flunked\n", i
);
290 printf ("host=[%s] user=[%s] pass=[%s] port=[%d]\n",
291 host
, user
, pass
, port
);
294 printf ("%d tests ok\n", i
);