Revision: 41584
Initial Code
Initial URL
Initial Description
Initial Title
Initial Tags
Initial Language
at February 20, 2011 07:48 by laszlograd
Initial Code
<?php
/**
* This file contains the HelloCaptcha class that is the essential
* PHP class for embedding HelloCaptcha CAPTCHAs.
*
* The most recent version of this file can be downloaded from:
* http://www.hellocaptcha.com/dl/HelloCaptcha.class.php
*
* A sample file that demonstrates how to use this class can be
* downloaded from:
* http://www.hellocaptcha.com/dl/sample-captcha.php
*
* PHP versions before 5.2 do not have JSON support enabled. To solve
* this issue download JSON.php from our server and place it near the
* HelloCaptcha.class.php file. The HelloCaptcha.class.php file
* automatically includes it if neccessary. The file can be downloaded
* from:
* http://www.hellocaptcha.com/dl/JSON.php
*
* @see http://www.hellocaptcha.com
* @see http://www.hellocaptcha.com/doc/embedding
* @Copyright Program Produkt, 2010-2011
*/
/** Version */
define("HELLOCAPTCHA_VERSION", "1.0");
/** Release date */
define("HELLOCAPTCHA_RELEASE_DATE", "2011-02-07");
/**
* This if will be used, if profile is not set. You can override this
* constant by defining it before including this file.
*/
define("HELLOCAPTCHA_TRIAL_PROFILE_ID", "hellocaptchatrialprofile");
/** HelloCaptcha service domain */
define("HELLOCAPTCHA_SERVER_DOMAIN", "service.hellocaptcha.com");
/** Path for verifying user's answer */
define("HELLOCAPTCHA_GET_NEW_TEST_PATH", "/getnewtest/");
/** Path for verifying user's answer */
define("HELLOCAPTCHA_VERIFY_ANSWER_PATH", "/verifyanswer/");
/** Error codes for getNewTest */
define("HELLOCAPTCHA_ERROR_1", "The profile named profileid does not exist.");
define("HELLOCAPTCHA_ERROR_2", "There is no pre-rendered CAPTCHA in the profile pool, yet. Please wait, until HelloCaptcha server generates the CAPTCHA animations.");
/** Error codes for verifyAnswer */
define("HELLOCAPTCHA_ERROR_3", "The Turing test identified by turingtestid does not exist.");
define("HELLOCAPTCHA_ERROR_4", "Either test turingtestid or answer is empty.");
define("HELLOCAPTCHA_ERROR_5", "The Turing test was already verified once.");
define("HELLOCAPTCHA_ERROR_6", "The Turing test is expired.");
define("HELLOCAPTCHA_ERROR_7", "There are too many bad tries (on a retryable CAPTCHA).");
/**
* Class that wraps functionality of HelloCaptcha service by implementing HTTP based
* communication and creating wrapper methods for HelloCaptcha service. This class
* should be used if someone needs custom functionality of this service. The HelloCaptcha
* class is based on the functions of this class.
*
* @version 1.0
*/
class HelloCaptchaWrapper {
/**
* Converts an error code to string
*
* @param int $p_error_code
* @return string response
*/
public static function errorCodeToString( $p_errorcode ) {
$cn = "HELLOCAPTCHA_ERROR_" . $p_errorcode;
if ( defined( $cn ) )
return constant( $cn );
else
return "Unknown error.";
}
/**
* Submits an HTTP POST to a server and returns its result.
*
* @param string $p_host
* @param string $p_path
* @param array $p_data
* @param int $p_port
* @return string response
*/
private static function doHTTPPost( $p_host, $p_path, $p_data, $p_port = 80 ) {
// Url encode the passed values
$request = Array();
foreach ( $p_data as $key => $value ) {
$request[] = $key . '=' . urlencode( stripslashes($value) );
}
$request = implode('&', $request);
// Create HTTP request string
$http_request = "POST $p_path HTTP/1.0
";
$http_request .= "Host: $p_host
";
$http_request .= "Content-Type: application/x-www-form-urlencoded;
";
$http_request .= "Content-Length: " . strlen($request) . "
";
$http_request .= "User-Agent: HELLOCAPTCHA/PHP
";
$http_request .= "
";
$http_request .= $request;
// Connect to server
if( false == ( $fs = @fsockopen($p_host, $p_port, $errno, $errstr, 10) ) )
throw new Exception( __METHOD__ . ': Cannot connect to server: ' . $p_host . ' on port: ' . $p_port . '.' );
// Do the request
fwrite($fs, $http_request);
// Get the response
$response = '';
while ( !feof($fs) ) {
// One TCP-IP packet
$response .= fgets($fs, 1160);
}
// Disconnect from the server
fclose($fs);
// Return the response
return $response;
}
/**
* Decodes a server response response is valid. If the response contains an exception
* then throws it.
*/
protected static function decodeResponse( $p_response ) {
$p_response = explode("
", $p_response, 2);
$p_response = $p_response[1];
// Check response for trivial errors
if ( is_null( $p_response ) )
throw new Exception( __METHOD__ . ': Server response is NULL.' );
if ( empty( $p_response ) )
throw new Exception( __METHOD__ . ': Server response is EMPTY.' );
// JSON decode
$response = json_decode( $p_response, TRUE );
if ( NULL === $response )
throw new Exception( __METHOD__ . ': Error decoding server response.' );
// Check for exception
if ( !empty( $response['e'] ) )
throw new Exception( __METHOD__ . ': Server returned an error: ' . $response['e']['message'], $response['e']['code'] );
// Return value if not empty
if ( empty( $response['d'] ) )
throw new Exception( __METHOD__ . ': Server returned empty data' );
return $response['d'];
}
/**
* Calls remote service and return the result.
*
* @param string $p_path
* @param array $p_data
* @return array response
*/
protected static function callRemote( $p_path, $p_data ) {
// Post data over HTTP
$response = self::doHTTPPost( HELLOCAPTCHA_SERVER_DOMAIN, $p_path, $p_data );
// Decode and return response
$response = self::decodeResponse( $response );
return $response;
}
/**
* Creates a new Turing test and returns the received result.
*
* @param string $p_profileid
* @return array response
*/
public function getNewTest( $p_profileid = HELLOCAPTCHA_TRIAL_PROFILE_ID ) {
// Call remote service
return self::callRemote(
HELLOCAPTCHA_GET_NEW_TEST_PATH,
Array( 'profileid' => $p_profileid )
);
}
/**
* Checks the answer for a given Turing test.
*
* @param string $p_turingtestid
* @param string $p_answer
* @return array response
*/
public function verifyAnswer( $p_turingtestid, $p_answer ) {
// Assert Turing test id is not empty
if ( empty( $p_turingtestid ) )
die (__METHOD__ . ": Turing test id is empty. Please specify Turing test id to let the system know which test was completed. A new test id can be obtained on http://www.hellocaptcha.com/registration/ .");
// Assert answer is not empty
if ( empty( $p_answer ) )
die (__METHOD__ . ": Answer is empty. Please specify answer to let the system know what to evaluate.");
// Call remote service
return self::callRemote(
HELLOCAPTCHA_VERIFY_ANSWER_PATH,
Array( 'turingtestid' => $p_turingtestid, 'answer' => $p_answer )
);
}
}
/**
* Class that provides high level functionality for HelloCaptcha service.
* This class uses the low level methods of HelloCaptchaWrapper class. If you need
* custom behaviour, you can create a custom class (MyHelloCaptcha) by modifying this
* class or by derivating from it.
*/
class HelloCaptcha extends HelloCaptchaWrapper {
/**
* Asks for a new test on HelloCaptcha server and returns a default
* embedding code for the CAPTCHA of the given profile.
*/
public static function getEmbedCode( $p_profileid = HELLOCAPTCHA_TRIAL_PROFILE_ID ) {
try {
// Call wrapper method, and return the ready-made part of the answer.
$res = self::getNewTest( $p_profileid );
return $res['html'];
} catch (Exception $e) {
echo "Error acquiring HelloCaptcha embedding code. " . self::errorCodeToString( $e->getCode() );
error_log( __METHOD__ . ": Unexpected error occured. Error message: " . self::errorCodeToString( $e->getCode() ) );
error_log( __METHOD__ . ": Unexpected error occured. HelloCaptcha server said: " . $e->getMessage() );
}
}
public static function checkAnswer( $p_turingtestid, $p_answer ) {
try {
// Call wrapper method, and return the validity of the answer.
$res = self::verifyAnswer( $p_turingtestid, $p_answer );
return $res['is_valid'];
} catch (Exception $e) {
echo "Error checking user answer for HelloCaptcha. " . self::errorCodeToString( $e->getCode() ) . "<br />";
error_log( __METHOD__ . ": Unexpected error occured. Error message: " . self::errorCodeToString( $e->getCode() ) );
error_log( __METHOD__ . ": Unexpected error occured. HelloCaptcha server said: " . $e->getMessage() );
return false;
}
}
}
if ( !function_exists('json_decode') ) {
function json_decode($p_content, $p_assoc = true) {
require_once 'JSON.php';
if ( $p_assoc ) {
$json = new Services_JSON(SERVICES_JSON_LOOSE_TYPE);
} else {
$json = new Services_JSON;
}
return $json->decode($p_content);
}
}
if ( !function_exists('json_encode') ){
function json_encode($p_content){
require_once 'JSON.php';
$json = new Services_JSON;
return $json->encode($p_content);
}
}
?>
Initial URL
www.hellocaptcha.com
Initial Description
PHP class to create animated CAPTCHAs
Initial Title
Free Animated Captcha - HelloCaptcha
Initial Tags
Initial Language
PHP