Skip to content

Commit 27307ed

Browse files
committed
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.
1 parent e02e6a5 commit 27307ed

File tree

1 file changed

+26
-61
lines changed

1 file changed

+26
-61
lines changed

src/transports/ssh.c

Lines changed: 26 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,6 @@
2424

2525
#define OWNING_SUBTRANSPORT(s) ((ssh_subtransport *)(s)->parent.subtransport)
2626

27-
static const char *ssh_prefixes[] = { "ssh://", "ssh+git://", "git+ssh://" };
28-
2927
static const char cmd_uploadpack[] = "git-upload-pack";
3028
static const char cmd_receivepack[] = "git-receive-pack";
3129

@@ -35,7 +33,7 @@ typedef struct {
3533
LIBSSH2_SESSION *session;
3634
LIBSSH2_CHANNEL *channel;
3735
const char *cmd;
38-
char *url;
36+
git_net_url url;
3937
unsigned sent_command : 1;
4038
} ssh_stream;
4139

@@ -63,39 +61,23 @@ static void ssh_error(LIBSSH2_SESSION *session, const char *errmsg)
6361
*
6462
* For example: git-upload-pack '/libgit2/libgit2'
6563
*/
66-
static int gen_proto(git_str *request, const char *cmd, const char *url)
64+
static int gen_proto(git_str *request, const char *cmd, git_net_url *url)
6765
{
6866
const char *repo;
69-
int len;
70-
size_t i;
71-
72-
for (i = 0; i < ARRAY_SIZE(ssh_prefixes); ++i) {
73-
const char *p = ssh_prefixes[i];
7467

75-
if (!git__prefixcmp(url, p)) {
76-
url = url + strlen(p);
77-
repo = strchr(url, '/');
78-
if (repo && repo[1] == '~')
79-
++repo;
68+
repo = url->path;
8069

81-
goto done;
82-
}
83-
}
84-
repo = strchr(url, ':');
85-
if (repo) repo++;
70+
if (repo && repo[0] == '/' && repo[1] == '~')
71+
repo++;
8672

87-
done:
88-
if (!repo) {
73+
if (!repo || !repo[0]) {
8974
git_error_set(GIT_ERROR_NET, "malformed git protocol URL");
9075
return -1;
9176
}
9277

93-
len = strlen(cmd) + 1 /* Space */ + 1 /* Quote */ + strlen(repo) + 1 /* Quote */ + 1;
94-
95-
git_str_grow(request, len);
9678
git_str_puts(request, cmd);
9779
git_str_puts(request, " '");
98-
git_str_decode_percent(request, repo, strlen(repo));
80+
git_str_puts(request, repo);
9981
git_str_puts(request, "'");
10082

10183
if (git_str_oom(request))
@@ -109,7 +91,7 @@ static int send_command(ssh_stream *s)
10991
int error;
11092
git_str request = GIT_STR_INIT;
11193

112-
error = gen_proto(&request, s->cmd, s->url);
94+
error = gen_proto(&request, s->cmd, &s->url);
11395
if (error < 0)
11496
goto cleanup;
11597

@@ -224,13 +206,12 @@ static void ssh_stream_free(git_smart_subtransport_stream *stream)
224206
s->io = NULL;
225207
}
226208

227-
git__free(s->url);
209+
git_net_url_dispose(&s->url);
228210
git__free(s);
229211
}
230212

231213
static int ssh_stream_alloc(
232214
ssh_subtransport *t,
233-
const char *url,
234215
const char *cmd,
235216
git_smart_subtransport_stream **stream)
236217
{
@@ -248,12 +229,6 @@ static int ssh_stream_alloc(
248229

249230
s->cmd = cmd;
250231

251-
s->url = git__strdup(url);
252-
if (!s->url) {
253-
git__free(s);
254-
return -1;
255-
}
256-
257232
*stream = &s->parent;
258233
return 0;
259234
}
@@ -487,9 +462,7 @@ static int _git_ssh_setup_conn(
487462
const char *cmd,
488463
git_smart_subtransport_stream **stream)
489464
{
490-
git_net_url urldata = GIT_NET_URL_INIT;
491465
int auth_methods, error = 0;
492-
size_t i;
493466
ssh_stream *s;
494467
git_credential *cred = NULL;
495468
LIBSSH2_SESSION *session=NULL;
@@ -498,28 +471,22 @@ static int _git_ssh_setup_conn(
498471
t->current_stream = NULL;
499472

500473
*stream = NULL;
501-
if (ssh_stream_alloc(t, url, cmd, stream) < 0)
474+
if (ssh_stream_alloc(t, cmd, stream) < 0)
502475
return -1;
503476

504477
s = (ssh_stream *)*stream;
505478
s->session = NULL;
506479
s->channel = NULL;
507480

508-
for (i = 0; i < ARRAY_SIZE(ssh_prefixes); ++i) {
509-
const char *p = ssh_prefixes[i];
510-
511-
if (!git__prefixcmp(url, p)) {
512-
if ((error = git_net_url_parse(&urldata, url)) < 0)
513-
goto done;
481+
if (git_net_str_is_url(url))
482+
error = git_net_url_parse(&s->url, url);
483+
else
484+
error = git_net_url_parse_scp(&s->url, url);
514485

515-
goto post_extract;
516-
}
517-
}
518-
if ((error = git_net_url_parse_scp(&urldata, url)) < 0)
486+
if (error < 0)
519487
goto done;
520488

521-
post_extract:
522-
if ((error = git_socket_stream_new(&s->io, urldata.host, urldata.port)) < 0 ||
489+
if ((error = git_socket_stream_new(&s->io, s->url.host, s->url.port)) < 0 ||
523490
(error = git_stream_connect(s->io)) < 0)
524491
goto done;
525492

@@ -603,7 +570,7 @@ static int _git_ssh_setup_conn(
603570
error = t->owner->connect_opts.callbacks.certificate_check(
604571
(git_cert *)cert_ptr,
605572
0,
606-
urldata.host,
573+
s->url.host,
607574
t->owner->connect_opts.callbacks.payload);
608575

609576
if (error < 0 && error != GIT_PASSTHROUGH) {
@@ -615,21 +582,21 @@ static int _git_ssh_setup_conn(
615582
}
616583

617584
/* we need the username to ask for auth methods */
618-
if (!urldata.username) {
585+
if (!s->url.username) {
619586
if ((error = request_creds(&cred, t, NULL, GIT_CREDENTIAL_USERNAME)) < 0)
620587
goto done;
621588

622-
urldata.username = git__strdup(((git_credential_username *) cred)->username);
589+
s->url.username = git__strdup(((git_credential_username *) cred)->username);
623590
cred->free(cred);
624591
cred = NULL;
625-
if (!urldata.username)
592+
if (!s->url.username)
626593
goto done;
627-
} else if (urldata.username && urldata.password) {
628-
if ((error = git_credential_userpass_plaintext_new(&cred, urldata.username, urldata.password)) < 0)
594+
} else if (s->url.username && s->url.password) {
595+
if ((error = git_credential_userpass_plaintext_new(&cred, s->url.username, s->url.password)) < 0)
629596
goto done;
630597
}
631598

632-
if ((error = list_auth_methods(&auth_methods, session, urldata.username)) < 0)
599+
if ((error = list_auth_methods(&auth_methods, session, s->url.username)) < 0)
633600
goto done;
634601

635602
error = GIT_EAUTH;
@@ -643,10 +610,10 @@ static int _git_ssh_setup_conn(
643610
cred = NULL;
644611
}
645612

646-
if ((error = request_creds(&cred, t, urldata.username, auth_methods)) < 0)
613+
if ((error = request_creds(&cred, t, s->url.username, auth_methods)) < 0)
647614
goto done;
648615

649-
if (strcmp(urldata.username, git_credential_get_username(cred))) {
616+
if (strcmp(s->url.username, git_credential_get_username(cred))) {
650617
git_error_set(GIT_ERROR_SSH, "username does not match previous request");
651618
error = -1;
652619
goto done;
@@ -656,7 +623,7 @@ static int _git_ssh_setup_conn(
656623

657624
if (error == GIT_EAUTH) {
658625
/* refresh auth methods */
659-
if ((error = list_auth_methods(&auth_methods, session, urldata.username)) < 0)
626+
if ((error = list_auth_methods(&auth_methods, session, s->url.username)) < 0)
660627
goto done;
661628
else
662629
error = GIT_EAUTH;
@@ -691,8 +658,6 @@ static int _git_ssh_setup_conn(
691658
if (cred)
692659
cred->free(cred);
693660

694-
git_net_url_dispose(&urldata);
695-
696661
return error;
697662
}
698663

0 commit comments

Comments
 (0)