Skip to content

Commit

Permalink
git-remote-mediawiki: add credential support
Browse files Browse the repository at this point in the history
The previous version implemented the possibility to log in a wiki, but
the username and password had to be provided as configuration variables.
We add the possibility to use the Git credential system to prompt
the password.

The support if implemented with generic functions that mimic the C API,
designed to be usable from other contexts in the future (i.e. they may
migrate to Git.pm if someone is interested).

While we're there, do a bit of refactoring in mw_connect_maybe.

Based on patch by: Javier Roucher Iglesias <Javier.Roucher-Iglesias@ensimag.imag.fr>

Signed-off-by: Junio C Hamano <gitster@pobox.com>
  • Loading branch information
Matthieu Moy authored and Junio C Hamano committed Jun 25, 2012
1 parent 2d6dc18 commit a7271ad
Showing 1 changed file with 94 additions and 12 deletions.
106 changes: 94 additions & 12 deletions contrib/mw-to-git/git-remote-mediawiki
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ use encoding 'utf8';
binmode STDERR, ":utf8";

use URI::Escape;
use IPC::Open2;

use warnings;

# Mediawiki filenames can contain forward slashes. This variable decides by which pattern they should be replaced
Expand Down Expand Up @@ -151,28 +153,108 @@ while (<STDIN>) {

########################## Functions ##############################

## credential API management (generic functions)

sub credential_from_url {
my $url = shift;
my $parsed = URI->new($url);
my %credential;

if ($parsed->scheme) {
$credential{protocol} = $parsed->scheme;
}
if ($parsed->host) {
$credential{host} = $parsed->host;
}
if ($parsed->path) {
$credential{path} = $parsed->path;
}
if ($parsed->userinfo) {
if ($parsed->userinfo =~ /([^:]*):(.*)/) {
$credential{username} = $1;
$credential{password} = $2;
} else {
$credential{username} = $parsed->userinfo;
}
}

return %credential;
}

sub credential_read {
my %credential;
my $reader = shift;
my $op = shift;
while (<$reader>) {
my ($key, $value) = /([^=]*)=(.*)/;
if (not defined $key) {
die "ERROR receiving response from git credential $op:\n$_\n";
}
$credential{$key} = $value;
}
return %credential;
}

sub credential_write {
my $credential = shift;
my $writer = shift;
while (my ($key, $value) = each(%$credential) ) {
if ($value) {
print $writer "$key=$value\n";
}
}
}

sub credential_run {
my $op = shift;
my $credential = shift;
my $pid = open2(my $reader, my $writer, "git credential $op");
credential_write($credential, $writer);
print $writer "\n";
close($writer);

if ($op eq "fill") {
%$credential = credential_read($reader, $op);
} else {
if (<$reader>) {
die "ERROR while running git credential $op:\n$_";
}
}
close($reader);
waitpid($pid, 0);
my $child_exit_status = $? >> 8;
if ($child_exit_status != 0) {
die "'git credential $op' failed with code $child_exit_status.";
}
}

# MediaWiki API instance, created lazily.
my $mediawiki;

sub mw_connect_maybe {
if ($mediawiki) {
return;
return;
}
$mediawiki = MediaWiki::API->new;
$mediawiki->{config}->{api_url} = "$url/api.php";
if ($wiki_login) {
if (!$mediawiki->login({
lgname => $wiki_login,
lgpassword => $wiki_passwd,
lgdomain => $wiki_domain,
})) {
print STDERR "Failed to log in mediawiki user \"$wiki_login\" on $url\n";
print STDERR "(error " .
$mediawiki->{error}->{code} . ': ' .
$mediawiki->{error}->{details} . ")\n";
exit 1;
my %credential = credential_from_url($url);
$credential{username} = $wiki_login;
$credential{password} = $wiki_passwd;
credential_run("fill", \%credential);
my $request = {lgname => $credential{username},
lgpassword => $credential{password},
lgdomain => $wiki_domain};
if ($mediawiki->login($request)) {
credential_run("approve", \%credential);
print STDERR "Logged in mediawiki user \"$credential{username}\".\n";
} else {
print STDERR "Logged in with user \"$wiki_login\".\n";
print STDERR "Failed to log in mediawiki user \"$credential{username}\" on $url\n";
print STDERR " (error " .
$mediawiki->{error}->{code} . ': ' .
$mediawiki->{error}->{details} . ")\n";
credential_run("reject", \%credential);
exit 1;
}
}
}
Expand Down

0 comments on commit a7271ad

Please sign in to comment.