Commit 27307ed6 by Edward Thomson

ssh: use url parsing functionality

Instead of trying to figure out a repo's path from a URL by hand, parse
a URL using the parsing functionality.
parent e02e6a5c
...@@ -24,8 +24,6 @@ ...@@ -24,8 +24,6 @@
#define OWNING_SUBTRANSPORT(s) ((ssh_subtransport *)(s)->parent.subtransport) #define OWNING_SUBTRANSPORT(s) ((ssh_subtransport *)(s)->parent.subtransport)
static const char *ssh_prefixes[] = { "ssh://", "ssh+git://", "git+ssh://" };
static const char cmd_uploadpack[] = "git-upload-pack"; static const char cmd_uploadpack[] = "git-upload-pack";
static const char cmd_receivepack[] = "git-receive-pack"; static const char cmd_receivepack[] = "git-receive-pack";
...@@ -35,7 +33,7 @@ typedef struct { ...@@ -35,7 +33,7 @@ typedef struct {
LIBSSH2_SESSION *session; LIBSSH2_SESSION *session;
LIBSSH2_CHANNEL *channel; LIBSSH2_CHANNEL *channel;
const char *cmd; const char *cmd;
char *url; git_net_url url;
unsigned sent_command : 1; unsigned sent_command : 1;
} ssh_stream; } ssh_stream;
...@@ -63,39 +61,23 @@ static void ssh_error(LIBSSH2_SESSION *session, const char *errmsg) ...@@ -63,39 +61,23 @@ static void ssh_error(LIBSSH2_SESSION *session, const char *errmsg)
* *
* For example: git-upload-pack '/libgit2/libgit2' * For example: git-upload-pack '/libgit2/libgit2'
*/ */
static int gen_proto(git_str *request, const char *cmd, const char *url) static int gen_proto(git_str *request, const char *cmd, git_net_url *url)
{ {
const char *repo; const char *repo;
int len;
size_t i;
for (i = 0; i < ARRAY_SIZE(ssh_prefixes); ++i) {
const char *p = ssh_prefixes[i];
if (!git__prefixcmp(url, p)) { repo = url->path;
url = url + strlen(p);
repo = strchr(url, '/');
if (repo && repo[1] == '~')
++repo;
goto done; if (repo && repo[0] == '/' && repo[1] == '~')
} repo++;
}
repo = strchr(url, ':');
if (repo) repo++;
done: if (!repo || !repo[0]) {
if (!repo) {
git_error_set(GIT_ERROR_NET, "malformed git protocol URL"); git_error_set(GIT_ERROR_NET, "malformed git protocol URL");
return -1; return -1;
} }
len = strlen(cmd) + 1 /* Space */ + 1 /* Quote */ + strlen(repo) + 1 /* Quote */ + 1;
git_str_grow(request, len);
git_str_puts(request, cmd); git_str_puts(request, cmd);
git_str_puts(request, " '"); git_str_puts(request, " '");
git_str_decode_percent(request, repo, strlen(repo)); git_str_puts(request, repo);
git_str_puts(request, "'"); git_str_puts(request, "'");
if (git_str_oom(request)) if (git_str_oom(request))
...@@ -109,7 +91,7 @@ static int send_command(ssh_stream *s) ...@@ -109,7 +91,7 @@ static int send_command(ssh_stream *s)
int error; int error;
git_str request = GIT_STR_INIT; git_str request = GIT_STR_INIT;
error = gen_proto(&request, s->cmd, s->url); error = gen_proto(&request, s->cmd, &s->url);
if (error < 0) if (error < 0)
goto cleanup; goto cleanup;
...@@ -224,13 +206,12 @@ static void ssh_stream_free(git_smart_subtransport_stream *stream) ...@@ -224,13 +206,12 @@ static void ssh_stream_free(git_smart_subtransport_stream *stream)
s->io = NULL; s->io = NULL;
} }
git__free(s->url); git_net_url_dispose(&s->url);
git__free(s); git__free(s);
} }
static int ssh_stream_alloc( static int ssh_stream_alloc(
ssh_subtransport *t, ssh_subtransport *t,
const char *url,
const char *cmd, const char *cmd,
git_smart_subtransport_stream **stream) git_smart_subtransport_stream **stream)
{ {
...@@ -248,12 +229,6 @@ static int ssh_stream_alloc( ...@@ -248,12 +229,6 @@ static int ssh_stream_alloc(
s->cmd = cmd; s->cmd = cmd;
s->url = git__strdup(url);
if (!s->url) {
git__free(s);
return -1;
}
*stream = &s->parent; *stream = &s->parent;
return 0; return 0;
} }
...@@ -487,9 +462,7 @@ static int _git_ssh_setup_conn( ...@@ -487,9 +462,7 @@ static int _git_ssh_setup_conn(
const char *cmd, const char *cmd,
git_smart_subtransport_stream **stream) git_smart_subtransport_stream **stream)
{ {
git_net_url urldata = GIT_NET_URL_INIT;
int auth_methods, error = 0; int auth_methods, error = 0;
size_t i;
ssh_stream *s; ssh_stream *s;
git_credential *cred = NULL; git_credential *cred = NULL;
LIBSSH2_SESSION *session=NULL; LIBSSH2_SESSION *session=NULL;
...@@ -498,28 +471,22 @@ static int _git_ssh_setup_conn( ...@@ -498,28 +471,22 @@ static int _git_ssh_setup_conn(
t->current_stream = NULL; t->current_stream = NULL;
*stream = NULL; *stream = NULL;
if (ssh_stream_alloc(t, url, cmd, stream) < 0) if (ssh_stream_alloc(t, cmd, stream) < 0)
return -1; return -1;
s = (ssh_stream *)*stream; s = (ssh_stream *)*stream;
s->session = NULL; s->session = NULL;
s->channel = NULL; s->channel = NULL;
for (i = 0; i < ARRAY_SIZE(ssh_prefixes); ++i) { if (git_net_str_is_url(url))
const char *p = ssh_prefixes[i]; error = git_net_url_parse(&s->url, url);
else
if (!git__prefixcmp(url, p)) { error = git_net_url_parse_scp(&s->url, url);
if ((error = git_net_url_parse(&urldata, url)) < 0)
goto done;
goto post_extract; if (error < 0)
}
}
if ((error = git_net_url_parse_scp(&urldata, url)) < 0)
goto done; goto done;
post_extract: if ((error = git_socket_stream_new(&s->io, s->url.host, s->url.port)) < 0 ||
if ((error = git_socket_stream_new(&s->io, urldata.host, urldata.port)) < 0 ||
(error = git_stream_connect(s->io)) < 0) (error = git_stream_connect(s->io)) < 0)
goto done; goto done;
...@@ -603,7 +570,7 @@ post_extract: ...@@ -603,7 +570,7 @@ post_extract:
error = t->owner->connect_opts.callbacks.certificate_check( error = t->owner->connect_opts.callbacks.certificate_check(
(git_cert *)cert_ptr, (git_cert *)cert_ptr,
0, 0,
urldata.host, s->url.host,
t->owner->connect_opts.callbacks.payload); t->owner->connect_opts.callbacks.payload);
if (error < 0 && error != GIT_PASSTHROUGH) { if (error < 0 && error != GIT_PASSTHROUGH) {
...@@ -615,21 +582,21 @@ post_extract: ...@@ -615,21 +582,21 @@ post_extract:
} }
/* we need the username to ask for auth methods */ /* we need the username to ask for auth methods */
if (!urldata.username) { if (!s->url.username) {
if ((error = request_creds(&cred, t, NULL, GIT_CREDENTIAL_USERNAME)) < 0) if ((error = request_creds(&cred, t, NULL, GIT_CREDENTIAL_USERNAME)) < 0)
goto done; goto done;
urldata.username = git__strdup(((git_credential_username *) cred)->username); s->url.username = git__strdup(((git_credential_username *) cred)->username);
cred->free(cred); cred->free(cred);
cred = NULL; cred = NULL;
if (!urldata.username) if (!s->url.username)
goto done; goto done;
} else if (urldata.username && urldata.password) { } else if (s->url.username && s->url.password) {
if ((error = git_credential_userpass_plaintext_new(&cred, urldata.username, urldata.password)) < 0) if ((error = git_credential_userpass_plaintext_new(&cred, s->url.username, s->url.password)) < 0)
goto done; goto done;
} }
if ((error = list_auth_methods(&auth_methods, session, urldata.username)) < 0) if ((error = list_auth_methods(&auth_methods, session, s->url.username)) < 0)
goto done; goto done;
error = GIT_EAUTH; error = GIT_EAUTH;
...@@ -643,10 +610,10 @@ post_extract: ...@@ -643,10 +610,10 @@ post_extract:
cred = NULL; cred = NULL;
} }
if ((error = request_creds(&cred, t, urldata.username, auth_methods)) < 0) if ((error = request_creds(&cred, t, s->url.username, auth_methods)) < 0)
goto done; goto done;
if (strcmp(urldata.username, git_credential_get_username(cred))) { if (strcmp(s->url.username, git_credential_get_username(cred))) {
git_error_set(GIT_ERROR_SSH, "username does not match previous request"); git_error_set(GIT_ERROR_SSH, "username does not match previous request");
error = -1; error = -1;
goto done; goto done;
...@@ -656,7 +623,7 @@ post_extract: ...@@ -656,7 +623,7 @@ post_extract:
if (error == GIT_EAUTH) { if (error == GIT_EAUTH) {
/* refresh auth methods */ /* refresh auth methods */
if ((error = list_auth_methods(&auth_methods, session, urldata.username)) < 0) if ((error = list_auth_methods(&auth_methods, session, s->url.username)) < 0)
goto done; goto done;
else else
error = GIT_EAUTH; error = GIT_EAUTH;
...@@ -691,8 +658,6 @@ done: ...@@ -691,8 +658,6 @@ done:
if (cred) if (cred)
cred->free(cred); cred->free(cred);
git_net_url_dispose(&urldata);
return error; return error;
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment