);
}
+sub captcha_url {
+ my $self = shift;
+ my $google = $self->google_handle;
+ if (exists ($google->{'captcha_url'}) ) {
+ return 'http://www.google.com/accounts/'.$google->{'captcha_url'};
+ }
+ else {
+ return '';
+ }
+}
+
+sub captcha_auth {
+ my $self = shift;
+ my $response = shift;
+ my $google = $self->google_handle('captcha_response' => $response);
+ return (defined($google->{'token'}));
+}
my %google_error = (
1000 => 'unknown error',
sub google_request {
my ($self, $method, %opt) = @_;
- my $google = $self->google_handle;
+ my $google = $self->google_handle(
+ 'captcha_response' => delete $opt{'captcha_response'}
+ );
return $google->{'error'} if $google->{'error'};
# Throw away the result from this; we don't use it yet.
sub google_handle {
my $self = shift;
my $class = 'REST::Google::Apps::Provisioning';
+ my %opt = @_;
eval "use $class";
die "failed to load $class\n" if $@;
}
);
- my $cache_id = $self->exportnum . '_token';
- $google->{'token'} = $CACHE->get($cache_id);
+ my $cache_token = $self->exportnum . '_token';
+ my $cache_captcha = $self->exportnum . '_captcha_token';
+ $google->{'token'} = $CACHE->get($cache_token);
if ( !$google->{'token'} ) {
- eval {
- $google->authenticate(
- 'username' => $self->option('username'),
- 'password' => $self->option('password'),
- )
- };
+ my %login = (
+ 'username' => $self->option('username'),
+ 'password' => $self->option('password'),
+ );
+ if ( $opt{'captcha_response'} ) {
+ $login{'logincaptcha'} = $opt{'captcha_response'};
+ $login{'logintoken'} = $CACHE->get($cache_captcha);
+ }
+ eval { $google->captcha_auth(%login); };
if ( $@ ) {
- # XXX CAPTCHA
$google->{'error'} = $@->{'error'};
- $CACHE->remove($cache_id);
+ $google->{'captcha_url'} = $@->{'captchaurl'};
+ $CACHE->set($cache_captcha, $@->{'captchatoken'}, '1 minute');
return $google;
}
- $CACHE->set($cache_id, $google->{'token'}, '1 hour');
+ $CACHE->remove($cache_captcha);
+ $CACHE->set($cache_token, $google->{'token'}, '1 hour');
}
return $google;
}
+# REST::Google::Apps::Provisioning also lacks a way to do this
+sub REST::Google::Apps::Provisioning::captcha_auth {
+ my $self = shift;
+
+ return( 1 ) if $self->{'token'};
+
+ my ( $arg );
+ %{$arg} = @_;
+
+ map { $arg->{lc($_)} = $arg->{$_} } keys %{$arg};
+
+ foreach my $param ( qw/ username password / ) {
+ $arg->{$param} || croak( "Missing required '$param' argument" );
+ }
+
+ my @postargs = (
+ 'accountType' => 'HOSTED',
+ 'service' => 'apps',
+ 'Email' => $arg->{'username'} . '@' . $self->{'domain'},
+ 'Passwd' => $arg->{'password'},
+ );
+ if ( $arg->{'logincaptcha'} ) {
+ push @postargs,
+ 'logintoken' => $arg->{'logintoken'},
+ 'logincaptcha'=> $arg->{'logincaptcha'}
+ ;
+ }
+ my $response = $self->{'lwp'}->post(
+ 'https://www.google.com/accounts/ClientLogin',
+ \@postargs
+ );
+
+ $response->is_success() || return( 0 );
+
+ foreach ( split( /\n/, $response->content() ) ) {
+ $self->{'token'} = $1 if /^Auth=(.+)$/;
+ last if $self->{'token'};
+ }
+
+ return( 1 ) if $self->{'token'} || return( 0 );
+}
+
1;
my $error = '';
+# google captcha auth
+if ( $cgi->param('captcha_response') ) {
+ my $part_svc = $svcnum ?
+ $old->part_svc :
+ qsearchs( 'part_svc',
+ { 'svcpart' => $cgi->param('svcpart') }
+ );
+ my ($export) = $part_svc->part_export('acct_google');
+ if ( $export and
+ ! $export->captcha_auth($cgi->param('captcha_response')) ) {
+ $error = 'Re-enter the security word.';
+ }
+}
+
$new->_password($old->_password) if $old;
if ( $cgi->param('clear_password') eq '*HIDDEN*'
|| $cgi->param('clear_password') =~ /^\(.* encrypted\)$/ ) {
die "fatal: no previous account to recall hidden password from!" unless $old;
} else {
- $error = $new->set_password($cgi->param('clear_password'));
+ $error ||= $new->set_password($cgi->param('clear_password'));
}
-if ( $svcnum ) {
- foreach ( grep { $old->$_ != $new->$_ }
- qw( seconds upbytes downbytes totalbytes )
- )
- {
- my %hash = map { $_ => $new->$_ }
- grep { $new->$_ }
- qw( seconds upbytes downbytes totalbytes );
+if ( ! $error ) {
+ if ( $svcnum ) {
+ foreach ( grep { $old->$_ != $new->$_ }
+ qw( seconds upbytes downbytes totalbytes )
+ )
+ {
+ my %hash = map { $_ => $new->$_ }
+ grep { $new->$_ }
+ qw( seconds upbytes downbytes totalbytes );
- $error ||= "invalid $_" foreach grep { $hash{$_} !~ /^-?\d+$/ } keys %hash;
- $error ||= $new->set_usage(\%hash); #unoverlimit and trigger radius changes
- last; #once is enough
+ $error ||= "invalid $_" foreach grep { $hash{$_} !~ /^-?\d+$/ } keys %hash;
+ $error ||= $new->set_usage(\%hash); #unoverlimit and trigger radius changes
+ last; #once is enough
+ }
+ $error ||= $new->replace($old);
+ } else {
+ $error ||= $new->insert;
+ $svcnum = $new->svcnum;
}
- $error ||= $new->replace($old);
-} else {
- $error ||= $new->insert;
- $svcnum = $new->svcnum;
}
</%init>