| line | stmt | bran | cond | sub | pod | time | code | 
| 1 |  |  |  |  |  |  | # -*- perl -*- | 
| 2 |  |  |  |  |  |  |  | 
| 3 |  |  |  |  |  |  | # Copyright (c) 2009 by Jeff Weisberg | 
| 4 |  |  |  |  |  |  | # Author: Jeff Weisberg | 
| 5 |  |  |  |  |  |  | # Created: 2009-Jun-18 12:38 (EDT) | 
| 6 |  |  |  |  |  |  | # Function: AC Puzzle Plugin | 
| 7 |  |  |  |  |  |  | # | 
| 8 |  |  |  |  |  |  | # $Id: SolveMedia.pm,v 1.1 2010/09/13 18:01:06 ilia Exp $ | 
| 9 |  |  |  |  |  |  |  | 
| 10 |  |  |  |  |  |  | package WWW::SolveMedia; | 
| 11 | 1 |  |  | 1 |  | 523 | use Carp; | 
|  | 1 |  |  |  |  | 2 |  | 
|  | 1 |  |  |  |  | 88 |  | 
| 12 | 1 |  |  | 1 |  | 1295 | use JSON; | 
|  | 1 |  |  |  |  | 22472 |  | 
|  | 1 |  |  |  |  | 7 |  | 
| 13 | 1 |  |  | 1 |  | 4855 | use LWP::UserAgent; | 
|  | 1 |  |  |  |  | 84138 |  | 
|  | 1 |  |  |  |  | 49 |  | 
| 14 | 1 |  |  | 1 |  | 1437 | use Digest::SHA1 'sha1_hex'; | 
|  | 1 |  |  |  |  | 1192 |  | 
|  | 1 |  |  |  |  | 79 |  | 
| 15 | 1 |  |  | 1 |  | 7 | use strict; | 
|  | 1 |  |  |  |  | 2 |  | 
|  | 1 |  |  |  |  | 1192 |  | 
| 16 |  |  |  |  |  |  |  | 
| 17 |  |  |  |  |  |  | our $VERSION 		= '1.1'; | 
| 18 |  |  |  |  |  |  |  | 
| 19 |  |  |  |  |  |  | my $AC_API_HTTP		= 'http://api.solvemedia.com'; | 
| 20 |  |  |  |  |  |  | my $AC_API_HTTPS	= 'https://api-secure.solvemedia.com'; | 
| 21 |  |  |  |  |  |  | my $AC_VFY_HTTP		= 'http://verify.solvemedia.com'; | 
| 22 |  |  |  |  |  |  | my $AC_SIGNUP_URL	= 'http://api.solvemedia.com/public/signup'; | 
| 23 |  |  |  |  |  |  |  | 
| 24 |  |  |  |  |  |  | # c-key, v-key, h-key, opts | 
| 25 |  |  |  |  |  |  | sub new { | 
| 26 | 0 |  |  | 0 | 1 |  | my $class = shift; | 
| 27 | 0 |  |  |  |  |  | my $ckey  = shift; | 
| 28 | 0 |  |  |  |  |  | my $vkey  = shift; | 
| 29 | 0 |  |  |  |  |  | my $hkey  = shift;		# optional | 
| 30 | 0 |  | 0 |  |  |  | my $opts  = shift || {};	# for dev/testing | 
| 31 |  |  |  |  |  |  |  | 
| 32 | 0 | 0 | 0 |  |  |  | croak "usage: new(ckey, vkey, hkey, [opts])\nyou may sign up for API keys at $AC_SIGNUP_URL" | 
| 33 |  |  |  |  |  |  | unless $ckey && $vkey; | 
| 34 |  |  |  |  |  |  |  | 
| 35 | 0 |  |  |  |  |  | return bless { | 
| 36 |  |  |  |  |  |  | ckey	=> $ckey, | 
| 37 |  |  |  |  |  |  | vkey	=> $vkey, | 
| 38 |  |  |  |  |  |  | hkey	=> $hkey, | 
| 39 |  |  |  |  |  |  | http	=> $AC_API_HTTP, | 
| 40 |  |  |  |  |  |  | https	=> $AC_API_HTTPS, | 
| 41 |  |  |  |  |  |  | verify	=> $AC_VFY_HTTP, | 
| 42 |  |  |  |  |  |  | %$opts, | 
| 43 |  |  |  |  |  |  | }, $class; | 
| 44 |  |  |  |  |  |  | } | 
| 45 |  |  |  |  |  |  |  | 
| 46 |  |  |  |  |  |  | # error_p, ssl_p, jsopts | 
| 47 |  |  |  |  |  |  | sub get_html { | 
| 48 | 0 |  |  | 0 | 1 |  | my $me   = shift; | 
| 49 | 0 |  |  |  |  |  | my $errp = shift; | 
| 50 | 0 |  |  |  |  |  | my $sslp = shift; | 
| 51 | 0 |  |  |  |  |  | my $opts = shift; | 
| 52 |  |  |  |  |  |  |  | 
| 53 | 0 |  |  |  |  |  | my $html = "\n"; | 
| 54 |  |  |  |  |  |  |  | 
| 55 | 0 | 0 |  |  |  |  | if( $opts ){ | 
| 56 | 0 |  |  |  |  |  | $html .= "  \n"; | 
| 59 |  |  |  |  |  |  | } | 
| 60 |  |  |  |  |  |  |  | 
| 61 | 0 | 0 |  |  |  |  | my $baseurl = $sslp ? $me->{https} : $me->{http}; | 
| 62 | 0 | 0 |  |  |  |  | my $param   = $errp ? ';error=1' : ''; | 
| 63 |  |  |  |  |  |  |  | 
| 64 | 0 |  |  |  |  |  | $html .= < | 
| 65 |  |  |  |  |  |  |  | 
| 68 |  |  |  |  |  |  |  | 
| 69 |  |  |  |  |  |  |  | 
| 70 |  |  |  |  |  |  |  | 
| 71 |  |  |  |  |  |  | height="300" width="500" frameborder="0"> 
 | 
| 72 |  |  |  |  |  |  |  | 
| 73 |  |  |  |  |  |  |  | 
| 74 |  |  |  |  |  |  |  | 
| 75 |  |  |  |  |  |  | value="manual_challenge"> | 
| 76 |  |  |  |  |  |  |  | 
| 77 |  |  |  |  |  |  |  | 
| 78 |  |  |  |  |  |  | WIDGET | 
| 79 |  |  |  |  |  |  | ; | 
| 80 |  |  |  |  |  |  |  | 
| 81 | 0 |  |  |  |  |  | return $html; | 
| 82 |  |  |  |  |  |  | } | 
| 83 |  |  |  |  |  |  |  | 
| 84 |  |  |  |  |  |  | # ip, challenge, answer | 
| 85 |  |  |  |  |  |  | sub check_answer { | 
| 86 | 0 |  |  | 0 | 1 |  | my $me     = shift; | 
| 87 | 0 |  |  |  |  |  | my $ipaddr = shift; | 
| 88 | 0 |  |  |  |  |  | my $ch     = shift; | 
| 89 | 0 |  |  |  |  |  | my $ans    = shift; | 
| 90 |  |  |  |  |  |  |  | 
| 91 |  |  |  |  |  |  | # QQQ - validate more before sending? | 
| 92 | 0 | 0 |  |  |  |  | return { is_valid => 0, error => 'missing challenge' } unless $ch; | 
| 93 | 0 | 0 |  |  |  |  | return { is_valid => 0, error => 'missing client-ip' } unless $ipaddr; | 
| 94 |  |  |  |  |  |  |  | 
| 95 | 0 |  |  |  |  |  | my $ua  = LWP::UserAgent->new( agent => "SolveMedia perl/$VERSION"); | 
| 96 | 0 |  |  |  |  |  | my $res =  $ua->post( "$AC_VFY_HTTP/papi/verify", { | 
| 97 |  |  |  |  |  |  | privatekey	=> $me->{vkey}, | 
| 98 |  |  |  |  |  |  | remoteip	=> $ipaddr, | 
| 99 |  |  |  |  |  |  | challenge	=> $ch, | 
| 100 |  |  |  |  |  |  | response	=> $ans, | 
| 101 |  |  |  |  |  |  | }); | 
| 102 |  |  |  |  |  |  |  | 
| 103 | 0 | 0 |  |  |  |  | unless( $res->is_success() ){ | 
| 104 |  |  |  |  |  |  | # QQQ - return what error? | 
| 105 | 0 |  |  |  |  |  | carp "check_answer - server error: " . $res->status_line; | 
| 106 | 0 |  |  |  |  |  | return { is_valid => 0, error => 'server error' }; | 
| 107 |  |  |  |  |  |  | } | 
| 108 |  |  |  |  |  |  |  | 
| 109 | 0 |  |  |  |  |  | my($pass, $msg, $check) = split /\n/, $res->content(); | 
| 110 | 0 |  |  |  |  |  | chomp($check); | 
| 111 |  |  |  |  |  |  |  | 
| 112 | 0 | 0 |  |  |  |  | unless( $pass eq 'true' ){ | 
| 113 | 0 |  |  |  |  |  | return { is_valid => 0, error => $msg }; | 
| 114 |  |  |  |  |  |  | } | 
| 115 |  |  |  |  |  |  |  | 
| 116 |  |  |  |  |  |  | # validate message authenticator | 
| 117 | 0 | 0 |  |  |  |  | if( $me->{hkey} ){ | 
| 118 | 0 |  |  |  |  |  | my $hash = sha1_hex("$pass$ch$me->{hkey}"); | 
| 119 | 0 | 0 |  |  |  |  | unless( $hash eq $check ){ | 
| 120 | 0 |  |  |  |  |  | carp "check_answer - message authentication failed. either: | 
| 121 |  |  |  |  |  |  | 1) you are using an incorrect hash-key, | 
| 122 |  |  |  |  |  |  | 2) evil hackers trying to attack the system."; | 
| 123 | 0 |  |  |  |  |  | return { is_valid => 0, error => 'message authentication check failed' }; | 
| 124 |  |  |  |  |  |  | } | 
| 125 |  |  |  |  |  |  | } | 
| 126 |  |  |  |  |  |  |  | 
| 127 |  |  |  |  |  |  | # Yay! | 
| 128 | 0 |  |  |  |  |  | return { is_valid => 1 }; | 
| 129 |  |  |  |  |  |  |  | 
| 130 |  |  |  |  |  |  | } | 
| 131 |  |  |  |  |  |  |  | 
| 132 |  |  |  |  |  |  | 1; | 
| 133 |  |  |  |  |  |  |  | 
| 134 |  |  |  |  |  |  | __END__ |