@ -0,0 +1,159 @@ |
||||
<?php |
||||
/** |
||||
* GoogleAnalytics Plugin |
||||
* |
||||
* @copyright Copyright (c) 2018 WeiCN (https://cuojue.org) |
||||
* @license GNU General Public License 3.0 |
||||
* |
||||
*/ |
||||
class GoogleAnalytics_Action extends Typecho_Widget implements Widget_Interface_Do |
||||
{ |
||||
|
||||
/** @var bool 请求适配器 */ |
||||
private static $_adapter = false; |
||||
|
||||
public function __construct($request, $response, $params = NULL) |
||||
{ |
||||
parent::__construct($request, $response, $params); |
||||
} |
||||
/** |
||||
* 添加新的链接转换 |
||||
* |
||||
*/ |
||||
public function ga(){ |
||||
|
||||
//拦截参数不完整 |
||||
if(empty($this->request->getReferer()) || |
||||
empty($this->request->getAgent()) || |
||||
empty($this->request->get('ga')) || |
||||
empty($this->request->get('dt')) || |
||||
empty($this->request->get('ul')) || |
||||
empty($this->request->get('sd')) || |
||||
empty($this->request->get('sr')) || |
||||
empty($this->request->get('vp')) || |
||||
empty($this->request->get('z'))) |
||||
{ |
||||
header('HTTP/1.1 403 Forbidden'); |
||||
exit(); |
||||
} |
||||
|
||||
if (!isset($_COOKIE["uuid"])) { |
||||
$str = md5(uniqid(mt_rand(), true)); |
||||
$uuid = substr($str,0,8) . '-'; |
||||
$uuid .= substr($str,8,4) . '-'; |
||||
$uuid .= substr($str,12,4) . '-'; |
||||
$uuid .= substr($str,16,4) . '-'; |
||||
$uuid .= substr($str,20,12); |
||||
setcookie("uuid", $uuid , time()+368400000); |
||||
}else{ |
||||
$uuid=$_COOKIE["uuid"]; |
||||
} |
||||
|
||||
header('content-type: image/jpg'); |
||||
header('HTTP/1.1 204 No Content'); |
||||
|
||||
if (function_exists("fastcgi_finish_request")) { |
||||
fastcgi_finish_request(); //对于fastcgi会提前返回请求结果,提高响应速度。 |
||||
} |
||||
|
||||
$url='v=1&t=pageview&'; |
||||
$url.='tid='.$this->request->get('ga').'&'; |
||||
$url.='cid='.$uuid.'&'; |
||||
$url.='dl='.rawurlencode(rawurldecode($this->request->getReferer())).'&'; |
||||
$url.='uip='.rawurlencode(rawurldecode($this->request->getip())).'&'; |
||||
$url.='ua='.rawurlencode(rawurldecode($this->request->getAgent())).'&'; |
||||
$url.='dt='.rawurlencode(rawurldecode($this->request->get('dt'))).'&'; |
||||
$url.='dr='.rawurlencode(rawurldecode($this->request->get('dr'))).'&'; |
||||
$url.='ul='.rawurlencode(rawurldecode($this->request->get('ul'))).'&'; |
||||
$url.='sd='.rawurlencode(rawurldecode($this->request->get('sd'))).'&'; |
||||
$url.='sr='.rawurlencode(rawurldecode($this->request->get('sr'))).'&'; |
||||
$url.='vp='.rawurlencode(rawurldecode($this->request->get('vp'))).'&'; |
||||
$url.='z='.$this->request->get('z'); |
||||
$url='https://www.google-analytics.com/collect?'.$url; |
||||
|
||||
self::asyncRequest($url); |
||||
} |
||||
|
||||
/** |
||||
* 检测 适配器 |
||||
* @return string |
||||
*/ |
||||
public static function isAvailable() |
||||
{ |
||||
function_exists('ini_get') && ini_get('allow_url_fopen') && (self::$_adapter = 'Socket'); |
||||
false == self::$_adapter && function_exists('curl_version') && (self::$_adapter = 'Curl'); |
||||
|
||||
return self::$_adapter; |
||||
} |
||||
|
||||
/** |
||||
* 发送异步请求 |
||||
* @param $url |
||||
*/ |
||||
public static function asyncRequest($url) |
||||
{ |
||||
self::isAvailable(); |
||||
self::$_adapter == 'Socket' ? self::socket($url) : self::curl($url); |
||||
} |
||||
|
||||
/** |
||||
* Socket 请求 |
||||
* @param $url |
||||
* @return bool |
||||
*/ |
||||
public static function socket($url) |
||||
{ |
||||
$params = parse_url($url); |
||||
$path = $params['path'] . '?' . $params['query']; |
||||
$host = $params['host']; |
||||
$port = 80; |
||||
$scheme = ''; |
||||
|
||||
if ('https' == $params['scheme']) { |
||||
$port = 443; |
||||
$scheme = 'ssl://'; |
||||
} |
||||
|
||||
if (function_exists('fsockopen')) { |
||||
$fp = @fsockopen ($scheme . $host, $port, $errno, $errstr, 30); |
||||
} elseif (function_exists('pfsockopen')) { |
||||
$fp = @pfsockopen ($scheme . $host, $port, $errno, $errstr, 30); |
||||
} else { |
||||
$fp = stream_socket_client($scheme . $host . ":$port", $errno, $errstr, 30); |
||||
} |
||||
|
||||
if ($fp === false) { |
||||
return false; |
||||
} |
||||
|
||||
$out = "GET " . $path . " HTTP/1.1\r\n"; |
||||
$out .= "Host: $host\r\n"; |
||||
$out .= "Connection: Close\r\n\r\n"; |
||||
|
||||
fwrite($fp, $out); |
||||
sleep(1); |
||||
fclose($fp); |
||||
} |
||||
|
||||
/** |
||||
* Curl 请求 |
||||
* @param $url |
||||
*/ |
||||
public static function curl($url) |
||||
{ |
||||
$ch = curl_init(); |
||||
curl_setopt($ch, CURLOPT_HTTPGET, 1); |
||||
curl_setopt($ch, CURLOPT_URL, $url); |
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); // 将curl_exec()获取的信息以文件流的形式返回,不直接输出。 |
||||
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 1); // 连接等待时间 |
||||
curl_setopt($ch, CURLOPT_TIMEOUT, 1); // curl允许执行时间 |
||||
|
||||
curl_exec($ch); |
||||
curl_close($ch); |
||||
|
||||
} |
||||
public function action(){ |
||||
$this->on($this->request->is('ga'))->ga(); |
||||
} |
||||
} |
||||
?> |
@ -0,0 +1,96 @@ |
||||
<?php |
||||
/** |
||||
* Typecho 的 Google Analytics 加速器 |
||||
* |
||||
* @package GoogleAnalytics |
||||
* @author WeiCN |
||||
* @version 1.0.0 |
||||
* @link https://cuojue.org/read/typecho_plugin_ga.html |
||||
*/ |
||||
class GoogleAnalytics_Plugin implements Typecho_Plugin_Interface |
||||
{ |
||||
|
||||
/** @var bool 请求适配器 */ |
||||
private static $_adapter = false; |
||||
|
||||
/** |
||||
* 激活插件方法,如果激活失败,直接抛出异常 |
||||
* |
||||
* @access public |
||||
* @return String |
||||
* @throws Typecho_Plugin_Exception |
||||
*/ |
||||
public static function activate() |
||||
{ |
||||
if (false == self::isAvailable()) { |
||||
throw new Typecho_Plugin_Exception(_t('对不起, 您的主机没有打开 allow_url_fopen 功能而且不支持 php-curl 扩展, 无法正常使用此功能')); |
||||
} |
||||
Helper::addRoute('Analytics', '/Analytics', 'GoogleAnalytics_Action', 'Action'); |
||||
Typecho_Plugin::factory('Widget_Archive')->footer = array('GoogleAnalytics_Plugin', 'footer'); |
||||
} |
||||
/** |
||||
* 禁用插件方法,如果禁用失败,直接抛出异常 |
||||
* |
||||
* @static |
||||
* @access public |
||||
* @return String |
||||
* @throws Typecho_Plugin_Exception |
||||
*/ |
||||
public static function deactivate() |
||||
{ |
||||
Helper::removeRoute('Analytics'); |
||||
} |
||||
/** |
||||
* 获取插件配置面板 |
||||
* |
||||
* @access public |
||||
* @param Typecho_Widget_Helper_Form $form 配置面板 |
||||
* @return void |
||||
*/ |
||||
public static function config(Typecho_Widget_Helper_Form $form) |
||||
{ |
||||
$gaid = new Typecho_Widget_Helper_Form_Element_Text('gaid', NULL, _t(''), _t('GoogleAnalytics ID'), _t('UA-XXXXXX-1')); |
||||
$form->addInput($gaid); |
||||
} |
||||
/** |
||||
* 个人用户的配置面板 |
||||
* |
||||
* @access public |
||||
* @param Typecho_Widget_Helper_Form $form |
||||
* @return void |
||||
*/ |
||||
public static function personalConfig(Typecho_Widget_Helper_Form $form){} |
||||
|
||||
/** |
||||
* 检测 适配器 |
||||
* @return string |
||||
*/ |
||||
public static function isAvailable() |
||||
{ |
||||
function_exists('ini_get') && ini_get('allow_url_fopen') && (self::$_adapter = 'Socket'); |
||||
false == self::$_adapter && function_exists('curl_version') && (self::$_adapter = 'Curl'); |
||||
|
||||
return self::$_adapter; |
||||
} |
||||
|
||||
public static function footer(){ |
||||
$options = Typecho_Widget::widget('Widget_Options'); |
||||
$pluginOption = Typecho_Widget::widget('Widget_Options')->Plugin('GoogleAnalytics'); |
||||
$pluginOption = unserialize($pluginOption); |
||||
$gaid = $pluginOption['gaid']; |
||||
$url = ($options->rewrite) ? $options->siteUrl : $options->siteUrl . 'index.php'; |
||||
$url = rtrim($url, '/') . '/Analytics'; |
||||
?> |
||||
<script> |
||||
function ga(c, d, e) { |
||||
var f = c.screen, |
||||
g = encodeURIComponent, |
||||
h = ["ga=<?=$gaid?>", "dt=" + g(d.title), "dr=" + g(d.referrer), "ul=" + (e.language || e.browserLanguage || e.userLanguage), "sd=" + f.colorDepth + "-bit", "sr=" + f.width + "x" + f.height, "vp=" + Math.max(d.documentElement.clientWidth, c.innerWidth || 0) + "x" + Math.max(d.documentElement.clientHeight, c.innerHeight || 0), "z=" + +new Date];
|
||||
c.__ga_img = new Image, c.__ga_img.src = "<?=$url?>?" + h.join("&")
|
||||
} |
||||
ga(window, document, navigator, location); |
||||
</script> |
||||
|
||||
<? |
||||
} |
||||
} |
@ -0,0 +1,104 @@ |
||||
<?php |
||||
/** |
||||
* typecho 博客的一款返回顶部插件 |
||||
* |
||||
* @package TopTop |
||||
* @author Heeeepin |
||||
* @version 1.0.0 |
||||
* @link http://heeeepin.com |
||||
*/ |
||||
|
||||
class TopTop_Plugin implements Typecho_Plugin_Interface |
||||
{ |
||||
/** |
||||
* 激活插件方法,如果激活失败,直接抛出异常 |
||||
* |
||||
* @access public |
||||
* @return void |
||||
* @throws Typecho_Plugin_Exception |
||||
*/ |
||||
public static function activate() { |
||||
Typecho_Plugin::factory('Widget_Archive')->header = array('TopTop_Plugin', 'header'); |
||||
Typecho_Plugin::factory('Widget_Archive')->footer = array('TopTop_Plugin', 'footer'); |
||||
return "插件启动成功"; |
||||
} |
||||
|
||||
/** |
||||
* 禁用插件方法,如果禁用失败,直接抛出异常 |
||||
* |
||||
* @static |
||||
* @access public |
||||
* @return void |
||||
* @throws Typecho_Plugin_Exception |
||||
*/ |
||||
public static function deactivate() { |
||||
return "插件禁用成功"; |
||||
} |
||||
|
||||
/** |
||||
* 获取插件配置面板 |
||||
* |
||||
* @access public |
||||
* @param Typecho_Widget_Helper_Form $form 配置面板 |
||||
* @return void |
||||
*/ |
||||
public static function config(Typecho_Widget_Helper_Form $form) { |
||||
$m1 = Helper::options()->pluginUrl . '/TopTop/models/1.png'; |
||||
$m2 = Helper::options()->pluginUrl . '/TopTop/models/2.png'; |
||||
$model1 = "<img src=$m1 alt='模型1'/>"; |
||||
$model2 = "<img src=$m2 alt='模型2'/>"; |
||||
$jquery = new Typecho_Widget_Helper_Form_Element_Checkbox('jquery', array('jquery' => '禁止加载jQuery'), false, _t('Jquery设置'), _t('插件需要加载jQuery,如果主题模板已经引用加载JQuery,则可以勾选。')); |
||||
$model = new Typecho_Widget_Helper_Form_Element_Radio('model', array('model1' => $model1,'model2'=>$model2), 'model2', _t('模型设置'), _t('选择一个你喜欢的模型')); |
||||
$form->addInput($jquery); |
||||
$form->addInput($model); |
||||
} |
||||
|
||||
|
||||
/** |
||||
* 个人用户的配置面板 |
||||
* |
||||
* @access public |
||||
* @param Typecho_Widget_Helper_Form $form |
||||
* @return void |
||||
*/ |
||||
public static function personalConfig(Typecho_Widget_Helper_Form $form) { |
||||
|
||||
} |
||||
|
||||
|
||||
/** |
||||
* 页头输出相关代码 |
||||
* |
||||
* @access public |
||||
* @param unknown header |
||||
* @return unknown |
||||
*/ |
||||
public static function header() { |
||||
$path = Helper::options()->pluginUrl . '/TopTop/'; |
||||
$options = Helper::options()->plugin('TopTop'); |
||||
$model = $options->model; |
||||
echo '<link rel="stylesheet" type="text/css" href="' . $path . 'css/'.$model.'.css" />'; |
||||
} |
||||
|
||||
|
||||
/** |
||||
* 页脚输出相关代码 |
||||
* |
||||
* @access public |
||||
* @param unknown footer |
||||
* @return unknown |
||||
*/ |
||||
public static function footer() { |
||||
$path = Helper::options()->pluginUrl . '/TopTop/'; |
||||
$options = Helper::options()->plugin('TopTop'); |
||||
echo '<div class="back-to-top" style="top: -700px;"></div>'; |
||||
if (!$options->jquery) { |
||||
echo '<script type="text/javascript" src="' . $path . 'js/jquery.min.js"></script>'; |
||||
} |
||||
echo '<script type="text/javascript" src="' . $path . 'js/toptop.js"></script>'; |
||||
} |
||||
} |
||||
|
||||
|
||||
|
||||
|
@ -0,0 +1,33 @@ |
||||
# TopTop |
||||
|
||||
typecho 博客的一款返回顶部插件 |
||||
|
||||
## 使用方法 |
||||
|
||||
Download ZIP, 解压 |
||||
|
||||
重命名文件夹为TopTop |
||||
|
||||
上传至usr/plugins目录 |
||||
|
||||
登录后台启用即可 |
||||
|
||||
## 主题 |
||||
|
||||
自带两套主题,欢迎提供想法 |
||||
|
||||
在线体验: [夜雨博客](https://heeeepin.com) |
||||
|
||||
![kk6h8K.png](https://s2.ax1x.com/2019/01/22/kk6h8K.png) |
||||
![kk64gO.png](https://s2.ax1x.com/2019/01/22/kk64gO.png) |
||||
|
||||
|
||||
## 感谢 |
||||
|
||||
[GoTop](https://github.com/NicoNicooooo/GoTop) |
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -0,0 +1,22 @@ |
||||
@media (max-width: 1000px) { |
||||
.back-to-top { |
||||
display: none !important; |
||||
} |
||||
} |
||||
|
||||
.topButton { |
||||
display: none; |
||||
} |
||||
|
||||
.back-to-top { |
||||
cursor: pointer; |
||||
position: fixed; |
||||
right: 80px; |
||||
top: -999px; |
||||
z-index: 2; |
||||
width: 70px; |
||||
height: 800px; |
||||
background: url(../images/1.png); |
||||
transition: all .5s ease-in-out; |
||||
opacity: 1; |
||||
} |
@ -0,0 +1,22 @@ |
||||
@media (max-width: 1000px) { |
||||
.back-to-top { |
||||
display: none !important; |
||||
} |
||||
} |
||||
|
||||
.topButton { |
||||
display: none; |
||||
} |
||||
|
||||
.back-to-top { |
||||
cursor: pointer; |
||||
position: fixed; |
||||
right: 80px; |
||||
top: -999px; |
||||
z-index: 2; |
||||
width: 70px; |
||||
height: 800px; |
||||
background: url(../images/2.png); |
||||
transition: all .5s ease-in-out; |
||||
opacity: 1; |
||||
} |
After Width: | Height: | Size: 9.4 KiB |
After Width: | Height: | Size: 11 KiB |
@ -0,0 +1,17 @@ |
||||
$(function () { |
||||
$(window).scroll(function () { |
||||
var scroHei = $(window).scrollTop(); |
||||
if (scroHei > 500) { |
||||
$('.back-to-top').css('top', '-200px'); |
||||
} else { |
||||
$('.back-to-top').fadeOut(); |
||||
} |
||||
}) |
||||
$('.back-to-top').click(function () { |
||||
$('body,html').animate({ |
||||
scrollTop: 0 |
||||
}, 600); |
||||
}) |
||||
}) |
||||
|
||||
|
After Width: | Height: | Size: 8.2 KiB |
After Width: | Height: | Size: 46 KiB |
@ -0,0 +1,92 @@ |
||||
<?php |
||||
/** |
||||
* reCAPTCHA验证码插件 |
||||
* |
||||
* @package reCAPTCHA |
||||
* @author D-Bood, 啸傲居士 |
||||
* @version 0.0.1 |
||||
* @link http://geaya.com |
||||
*/ |
||||
|
||||
require_once('lib/src/autoload.php'); |
||||
|
||||
class reCAPTCHA_Plugin implements Typecho_Plugin_Interface |
||||
{ |
||||
|
||||
/** |
||||
* 激活插件方法,如果激活失败,直接抛出异常 |
||||
* |
||||
* @access public |
||||
* @return void |
||||
* @throws Typecho_Plugin_Exception |
||||
*/ |
||||
public static function activate() { |
||||
Typecho_Plugin::factory('Widget_Feedback')->comment = array(__CLASS__, 'filter'); |
||||
} |
||||
|
||||
/** |
||||
* 禁用插件方法,如果禁用失败,直接抛出异常 |
||||
* |
||||
* @static |
||||
* @access public |
||||
* @return void |
||||
* @throws Typecho_Plugin_Exception |
||||
*/ |
||||
public static function deactivate() {} |
||||
|
||||
/** |
||||
* 个人用户的配置面板 |
||||
* |
||||
* @access public |
||||
* @param Typecho_Widget_Helper_Form $form |
||||
* @return void |
||||
*/ |
||||
public static function personalConfig(Typecho_Widget_Helper_Form $form) {} |
||||
|
||||
/** |
||||
* 获取插件配置面板 |
||||
* |
||||
* @access public |
||||
* @param Typecho_Widget_Helper_Form $form 配置面板 |
||||
* @return void |
||||
*/ |
||||
public static function config(Typecho_Widget_Helper_Form $form) { |
||||
$siteKeyDescription = _t("To use reCAPTCHA you must get an API key from <a href='https://www.google.com/recaptcha/admin/create'>https://www.google.com/recaptcha/admin/create</a>"); |
||||
$siteKey = new Typecho_Widget_Helper_Form_Element_Text('siteKey', NULL, '', _t('Site Key:'), $siteKeyDescription); |
||||
$secretKey = new Typecho_Widget_Helper_Form_Element_Text('secretKey', NULL, '', _t('Serect Key:'), _t('')); |
||||
|
||||
$form->addInput($siteKey); |
||||
$form->addInput($secretKey); |
||||
} |
||||
|
||||
/** |
||||
* 展示验证码 |
||||
*/ |
||||
public static function output() { |
||||
$siteKey = Typecho_Widget::widget('Widget_Options')->plugin('reCAPTCHA')->siteKey; |
||||
$secretKey = Typecho_Widget::widget('Widget_Options')->plugin('reCAPTCHA')->secretKey; |
||||
if ($siteKey != "" && $secretKey != "") { |
||||
echo '<script src="https://recaptcha.net/recaptcha/api.js" async defer data-no-instant></script> |
||||
<div class="g-recaptcha" data-sitekey=' . $siteKey . '></div>'; |
||||
} else { throw new Typecho_Widget_Exception(_t('No reCAPTCHA Site/Secret Keys! Please set it/them!')); } |
||||
} |
||||
|
||||
public static function filter($comments, $obj) { |
||||
$userObj = $obj->widget('Widget_User'); |
||||
if($userObj->hasLogin() && $userObj->pass('administrator', true)) { |
||||
return $comments; |
||||
} |
||||
elseif (isset($_POST['g-recaptcha-response'])) { |
||||
$siteKey = Typecho_Widget::widget('Widget_Options')->plugin('reCAPTCHA')->siteKey; |
||||
$secretKey = Typecho_Widget::widget('Widget_Options')->plugin('reCAPTCHA')->secretKey; |
||||
$recaptcha = new \ReCaptcha\ReCaptcha($secretKey); |
||||
$ip = $_SERVER['REMOTE_ADDR']; |
||||
$resp = $recaptcha->verify($_POST['g-recaptcha-response'], $ip); |
||||
|
||||
if (!$resp->isSuccess()) {throw new Typecho_Widget_Exception(_t('验证码不正确哦!'));} else {return $comments;} |
||||
} else { |
||||
throw new Typecho_Widget_Exception(_t('未成功加载验证码!请科学上网!')); |
||||
} |
||||
} |
||||
|
||||
} |
@ -0,0 +1,16 @@ |
||||
[typecho][1]评论验证码插件,使用Google的[reCAPTCHA][2]接口。 |
||||
====== |
||||
|
||||
#### 使用方法: |
||||
1. 到「[页面][3]」申请一个API key; |
||||
2. 激活该插件,并配置Public Key和Private Key; |
||||
3. 在适当地方添加如下代码: |
||||
|
||||
``` |
||||
<?php reCAPTCHA_Plugin::output(); ?> |
||||
``` |
||||
**注意:若未配置Public Key和Private Key而在页面中先添加上述代码,该页面会报错** |
||||
|
||||
[1]: http://typecho.org/about |
||||
[2]: https://www.google.com/recaptcha/ |
||||
[3]: https://www.google.com/recaptcha/admin/create |
@ -0,0 +1,3 @@ |
||||
/composer.lock |
||||
/nbproject/private/ |
||||
/vendor/ |
@ -0,0 +1,19 @@ |
||||
language: php |
||||
|
||||
sudo: false |
||||
|
||||
php: |
||||
- '5.5' |
||||
- '5.6' |
||||
- '7.0' |
||||
- '7.1' |
||||
- hhvm |
||||
- nightly |
||||
|
||||
before_script: |
||||
- composer install |
||||
- phpenv version-name | grep ^5.[34] && echo "extension=apc.so" >> ~/.phpenv/versions/$(phpenv version-name)/etc/php.ini ; true |
||||
- phpenv version-name | grep ^5.[34] && echo "apc.enable_cli=1" >> ~/.phpenv/versions/$(phpenv version-name)/etc/php.ini ; true |
||||
|
||||
script: |
||||
- vendor/bin/phpunit |
@ -0,0 +1,24 @@ |
||||
Want to contribute? Great! First, read this page (including the small print at the end). |
||||
|
||||
### Before you contribute |
||||
Before we can use your code, you must sign the |
||||
[Google Individual Contributor License Agreement](https://developers.google.com/open-source/cla/individual?csw=1) |
||||
(CLA), which you can do online. The CLA is necessary mainly because you own the |
||||
copyright to your changes, even after your contribution becomes part of our |
||||
codebase, so we need your permission to use and distribute your code. We also |
||||
need to be sure of various other things—for instance that you'll tell us if you |
||||
know that your code infringes on other people's patents. You don't have to sign |
||||
the CLA until after you've submitted your code for review and a member has |
||||
approved it, but you must do it before we can put your code into our codebase. |
||||
Before you start working on a larger contribution, you should get in touch with |
||||
us first through the issue tracker with your idea so that we can help out and |
||||
possibly guide you. Coordinating up front makes it much easier to avoid |
||||
frustration later on. |
||||
|
||||
### Code reviews |
||||
All submissions, including submissions by project members, require review. We |
||||
use GitHub pull requests for this purpose. |
||||
|
||||
### The small print |
||||
Contributions made by corporations are covered by a different agreement than |
||||
the one above, the Software Grant and Corporate Contributor License Agreement. |
@ -0,0 +1,29 @@ |
||||
Copyright 2014, Google Inc. |
||||
All rights reserved. |
||||
|
||||
Redistribution and use in source and binary forms, with or without |
||||
modification, are permitted provided that the following conditions are |
||||
met: |
||||
|
||||
* Redistributions of source code must retain the above copyright |
||||
notice, this list of conditions and the following disclaimer. |
||||
* Redistributions in binary form must reproduce the above |
||||
copyright notice, this list of conditions and the following disclaimer |
||||
in the documentation and/or other materials provided with the |
||||
distribution. |
||||
* Neither the name of Google Inc. nor the names of its |
||||
contributors may be used to endorse or promote products derived from |
||||
this software without specific prior written permission. |
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||||
|
@ -0,0 +1,115 @@ |
||||
# reCAPTCHA PHP client library |
||||
|
||||
[![Build Status](https://travis-ci.org/google/recaptcha.svg)](https://travis-ci.org/google/recaptcha) |
||||
[![Latest Stable Version](https://poser.pugx.org/google/recaptcha/v/stable.svg)](https://packagist.org/packages/google/recaptcha) |
||||
[![Total Downloads](https://poser.pugx.org/google/recaptcha/downloads.svg)](https://packagist.org/packages/google/recaptcha) |
||||
|
||||
* Project page: http://www.google.com/recaptcha/ |
||||
* Repository: https://github.com/google/recaptcha |
||||
* Version: 1.1.3 |
||||
* License: BSD, see [LICENSE](LICENSE) |
||||
|
||||
## Description |
||||
|
||||
reCAPTCHA is a free CAPTCHA service that protect websites from spam and abuse. |
||||
This is Google authored code that provides plugins for third-party integration |
||||
with reCAPTCHA. |
||||
|
||||
## Installation |
||||
|
||||
### Composer (Recommended) |
||||
|
||||
[Composer](https://getcomposer.org/) is a widely used dependency manager for PHP |
||||
packages. This reCAPTCHA client is available on Packagist as |
||||
[`google/recaptcha`](https://packagist.org/packages/google/recaptcha) and can be |
||||
installed either by running the `composer require` command or adding the library |
||||
to your `composer.json`. To enable Composer for you project, refer to the |
||||
project's [Getting Started](https://getcomposer.org/doc/00-intro.md) |
||||
documentation. |
||||
|
||||
To add this dependency using the command, run the following from within your |
||||
project directory: |
||||
``` |
||||
composer require google/recaptcha "~1.1" |
||||
``` |
||||
|
||||
Alternatively, add the dependency directly to your `composer.json` file: |
||||
```json |
||||
"require": { |
||||
"google/recaptcha": "~1.1" |
||||
} |
||||
``` |
||||
|
||||
### Direct download (no Composer) |
||||
|
||||
If you wish to install the library manually (i.e. without Composer), then you |
||||
can use the links on the main project page to either clone the repo or download |
||||
the [ZIP file](https://github.com/google/recaptcha/archive/master.zip). For |
||||
convenience, an autoloader script is provided in `src/autoload.php` which you |
||||
can require into your script instead of Composer's `vendor/autoload.php`. For |
||||
example: |
||||
|
||||
```php |
||||
require('/path/to/recaptcha/src/autoload.php'); |
||||
$recaptcha = new \ReCaptcha\ReCaptcha($secret); |
||||
``` |
||||
|
||||
The classes in the project are structured according to the |
||||
[PSR-4](http://www.php-fig.org/psr/psr-4/) standard, so you may of course also |
||||
use your own autoloader or require the needed files directly in your code. |
||||
|
||||
### Development install |
||||
|
||||
If you would like to contribute to this project or run the unit tests on within |
||||
your own environment you will need to install the development dependencies, in |
||||
this case that means [PHPUnit](https://phpunit.de/). If you clone the repo and |
||||
run `composer install` from within the repo, this will also grab PHPUnit and all |
||||
its dependencies for you. If you only need the autoloader installed, then you |
||||
can always specify to Composer not to run in development mode, e.g. `composer |
||||
install --no-dev`. |
||||
|
||||
*Note:* These dependencies are only required for development, there's no |
||||
requirement for them to be included in your production code. |
||||
|
||||
## Usage |
||||
|
||||
First, register keys for your site at https://www.google.com/recaptcha/admin |
||||
|
||||
When your app receives a form submission containing the `g-recaptcha-response` |
||||
field, you can verify it using: |
||||
```php |
||||
<?php |
||||
$recaptcha = new \ReCaptcha\ReCaptcha($secret); |
||||
$resp = $recaptcha->verify($gRecaptchaResponse, $remoteIp); |
||||
if ($resp->isSuccess()) { |
||||
// verified! |
||||
// if Domain Name Validation turned off don't forget to check hostname field |
||||
// if($resp->getHostName() === $_SERVER['SERVER_NAME']) { } |
||||
} else { |
||||
$errors = $resp->getErrorCodes(); |
||||
} |
||||
``` |
||||
|
||||
You can see an end-to-end working example in |
||||
[examples/example-captcha.php](examples/example-captcha.php) |
||||
|
||||
## Upgrading |
||||
|
||||
### From 1.0.0 |
||||
|
||||
The previous version of this client is still available on the `1.0.0` tag [in |
||||
this repo](https://github.com/google/recaptcha/tree/1.0.0) but it is purely for |
||||
reference and will not receive any updates. |
||||
|
||||
The major changes in 1.1.0 are: |
||||
* installation now via Composer; |
||||
* class loading also via Composer; |
||||
* classes now namespaced; |
||||
* old method call was `$rc->verifyResponse($remoteIp, $response)`, new call is |
||||
`$rc->verify($response, $remoteIp)` |
||||
|
||||
## Contributing |
||||
|
||||
We accept contributions via GitHub Pull Requests, but all contributors need to |
||||
be covered by the standard Google Contributor License Agreement. You can find |
||||
instructions for this in [CONTRIBUTING](CONTRIBUTING.md) |
@ -0,0 +1,28 @@ |
||||
{ |
||||
"name": "google/recaptcha", |
||||
"description": "Client library for reCAPTCHA, a free service that protect websites from spam and abuse.", |
||||
"type": "library", |
||||
"keywords": ["recaptcha", "captcha", "spam", "abuse"], |
||||
"homepage": "http://www.google.com/recaptcha/", |
||||
"license": "BSD-3-Clause", |
||||
"support": { |
||||
"forum": "https://groups.google.com/forum/#!forum/recaptcha", |
||||
"source": "https://github.com/google/recaptcha" |
||||
}, |
||||
"require": { |
||||
"php": ">=5.5" |
||||
}, |
||||
"require-dev": { |
||||
"phpunit/phpunit": "^4.8" |
||||
}, |
||||
"autoload": { |
||||
"psr-4": { |
||||
"ReCaptcha\\": "src/ReCaptcha" |
||||
} |
||||
}, |
||||
"extra": { |
||||
"branch-alias": { |
||||
"dev-master": "1.1.x-dev" |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,130 @@ |
||||
<?php |
||||
/** |
||||
* Working sample code to accompany the library. The instructions here assume |
||||
* you've just cloned the repo. If you've installed via composer, you will want |
||||
* to adjust the path to the autoloader. |
||||
* |
||||
* 1. Run the server. For example, under Linux you can probably use: |
||||
* /usr/bin/php -S "localhost:8000" "examples/example-captcha.php" |
||||
* 2. Point your browser at http://localhost:8000 |
||||
* 3. Follow the instructions |
||||
* |
||||
* @copyright Copyright (c) 2015, Google Inc. |
||||
* @link http://www.google.com/recaptcha |
||||
* |
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy |
||||
* of this software and associated documentation files (the "Software"), to deal |
||||
* in the Software without restriction, including without limitation the rights |
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
||||
* copies of the Software, and to permit persons to whom the Software is |
||||
* furnished to do so, subject to the following conditions: |
||||
* |
||||
* The above copyright notice and this permission notice shall be included in |
||||
* all copies or substantial portions of the Software. |
||||
* |
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN |
||||
* THE SOFTWARE. |
||||
*/ |
||||
// Initiate the autoloader. The file should be generated by Composer. |
||||
// You will provide your own autoloader or require the files directly if you did |
||||
// not install via Composer. |
||||
require_once __DIR__ . '/../vendor/autoload.php'; |
||||
|
||||
// Register API keys at https://www.google.com/recaptcha/admin |
||||
$siteKey = '6Le8yigUAAAAANf5EpB5kLb49-ZHcGpKw_w1HbaS'; |
||||
$secret = '6Le8yigUAAAAABK5xM4xF4gnBxpoIoLdWNHYbvgL'; |
||||
|
||||
// reCAPTCHA supported 40+ languages listed here: https://developers.google.com/recaptcha/docs/language |
||||
$lang = 'zh-CN'; |
||||
?> |
||||
<html> |
||||
<head> |
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/> |
||||
<title>reCAPTCHA Example</title> |
||||
<link rel="shortcut icon" href="//www.gstatic.com/recaptcha/admin/favicon.ico" type="image/x-icon"/> |
||||
<style type="text/css"> |
||||
body { |
||||
margin: 1em 5em 0 5em; |
||||
font-family: sans-serif; |
||||
} |
||||
fieldset { |
||||
display: inline; |
||||
padding: 1em; |
||||
} |
||||
</style> |
||||
</head> |
||||
<body> |
||||
<h1>reCAPTCHA Example</h1> |
||||
<?php if ($siteKey === '' || $secret === ''): ?> |
||||
<h2>Add your keys</h2> |
||||
<p>If you do not have keys already then visit <kbd> |
||||
<a href = "https://www.google.com/recaptcha/admin"> |
||||
https://www.google.com/recaptcha/admin</a></kbd> to generate them. |
||||
Edit this file and set the respective keys in <kbd>$siteKey</kbd> and |
||||
<kbd>$secret</kbd>. Reload the page after this.</p> |
||||
<?php |
||||
elseif (isset($_POST['g-recaptcha-response'])): |
||||
// The POST data here is unfiltered because this is an example. |
||||
// In production, *always* sanitise and validate your input' |
||||
?> |
||||
<h2><kbd>POST</kbd> data</h2> |
||||
<kbd><pre><?php var_export($_POST); ?></pre></kbd>
|
||||
<?php |
||||
// If the form submission includes the "g-captcha-response" field |
||||
// Create an instance of the service using your secret |
||||
$recaptcha = new \ReCaptcha\ReCaptcha($secret); |
||||
|
||||
// If file_get_contents() is locked down on your PHP installation to disallow |
||||
// its use with URLs, then you can use the alternative request method instead. |
||||
// This makes use of fsockopen() instead. |
||||
// $recaptcha = new \ReCaptcha\ReCaptcha($secret, new \ReCaptcha\RequestMethod\SocketPost()); |
||||
|
||||
// Make the call to verify the response and also pass the user's IP address |
||||
$resp = $recaptcha->verify($_POST['g-recaptcha-response'], $_SERVER['REMOTE_ADDR']); |
||||
|
||||
if ($resp->isSuccess()): |
||||
// If the response is a success, that's it! |
||||
?> |
||||
<h2>Success!</h2> |
||||
<p>That's it. Everything is working. Go integrate this into your real project.</p> |
||||
<p><a href="/">Try again</a></p> |
||||
<?php |
||||
else: |
||||
// If it's not successful, then one or more error codes will be returned. |
||||
?> |
||||
<h2>Something went wrong</h2> |
||||
<p>The following error was returned: <?php |
||||
foreach ($resp->getErrorCodes() as $code) { |
||||
echo '<kbd>' , $code , '</kbd> '; |
||||
} |
||||
?></p> |
||||
<p>Check the error code reference at <kbd><a href="https://developers.google.com/recaptcha/docs/verify#error-code-reference">https://developers.google.com/recaptcha/docs/verify#error-code-reference</a></kbd>. |
||||
<p><strong>Note:</strong> Error code <kbd>missing-input-response</kbd> may mean the user just didn't complete the reCAPTCHA.</p> |
||||
<p><a href="/">Try again</a></p> |
||||
<?php |
||||
endif; |
||||
else: |
||||
// Add the g-recaptcha tag to the form you want to include the reCAPTCHA element |
||||
?> |
||||
<p>Complete the reCAPTCHA then submit the form.</p> |
||||
<form action="/" method="post"> |
||||
<fieldset> |
||||
<legend>An example form</legend> |
||||
<p>Example input A: <input type="text" name="ex-a" value="foo"></p> |
||||
<p>Example input B: <input type="text" name="ex-b" value="bar"></p> |
||||
|
||||
<div class="g-recaptcha" data-sitekey="<?php echo $siteKey; ?>"></div>
|
||||
<script type="text/javascript" |
||||
src="https://www.google.com/recaptcha/api.js?hl=<?php echo $lang; ?>">
|
||||
</script> |
||||
<p><input type="submit" value="Submit" /></p> |
||||
</fieldset> |
||||
</form> |
||||
<?php endif; ?> |
||||
</body> |
||||
</html> |
@ -0,0 +1,17 @@ |
||||
<?xml version="1.0" encoding="UTF-8"?> |
||||
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" |
||||
xsi:noNamespaceSchemaLocation="http://schema.phpunit.de/4.4/phpunit.xsd" |
||||
colors="true" |
||||
verbose="true" |
||||
bootstrap="src/autoload.php"> |
||||
<testsuites> |
||||
<testsuite name="reCAPTCHA Test Suite"> |
||||
<directory>tests/ReCaptcha/</directory> |
||||
</testsuite> |
||||
</testsuites> |
||||
<filter> |
||||
<whitelist> |
||||
<directory suffix=".php">src/ReCaptcha/</directory> |
||||
</whitelist> |
||||
</filter> |
||||
</phpunit> |
@ -0,0 +1,98 @@ |
||||
<?php |
||||
/** |
||||
* This is a PHP library that handles calling reCAPTCHA. |
||||
* |
||||
* @copyright Copyright (c) 2015, Google Inc. |
||||
* @link http://www.google.com/recaptcha |
||||
* |
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy |
||||
* of this software and associated documentation files (the "Software"), to deal |
||||
* in the Software without restriction, including without limitation the rights |
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
||||
* copies of the Software, and to permit persons to whom the Software is |
||||
* furnished to do so, subject to the following conditions: |
||||
* |
||||
* The above copyright notice and this permission notice shall be included in |
||||
* all copies or substantial portions of the Software. |
||||
* |
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN |
||||
* THE SOFTWARE. |
||||
*/ |
||||
|
||||
namespace ReCaptcha; |
||||
|
||||
/** |
||||
* reCAPTCHA client. |
||||
*/ |
||||
class ReCaptcha |
||||
{ |
||||
/** |
||||
* Version of this client library. |
||||
* @const string |
||||
*/ |
||||
const VERSION = 'php_1.1.3'; |
||||
|
||||
/** |
||||
* Shared secret for the site. |
||||
* @var string |
||||
*/ |
||||
private $secretKey; |
||||
|
||||
/** |
||||
* Method used to communicate with service. Defaults to POST request. |
||||
* @var RequestMethod |
||||
*/ |
||||
private $requestMethod; |
||||
|
||||
/** |
||||
* Create a configured instance to use the reCAPTCHA service. |
||||
* |
||||
* @param string $secret shared secret between site and reCAPTCHA server. |
||||
* @param RequestMethod $requestMethod method used to send the request. Defaults to POST. |
||||
* @throws \RuntimeException if $secret is invalid |
||||
*/ |
||||
public function __construct($secretKey, RequestMethod $requestMethod = null) |
||||
{ |
||||
if (empty($secretKey)) { |
||||
throw new \RuntimeException('No secret provided'); |
||||
} |
||||
|
||||
if (!is_string($secretKey)) { |
||||
throw new \RuntimeException('The provided secret must be a string'); |
||||
} |
||||
|
||||
$this->secret = $secretKey; |
||||
|
||||
if (!is_null($requestMethod)) { |
||||
$this->requestMethod = $requestMethod; |
||||
} else { |
||||
$this->requestMethod = new RequestMethod\Post(); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Calls the reCAPTCHA siteverify API to verify whether the user passes |
||||
* CAPTCHA test. |
||||
* |
||||
* @param string $response The value of 'g-recaptcha-response' in the submitted form. |
||||
* @param string $remoteIp The end user's IP address. |
||||
* @return Response Response from the service. |
||||
*/ |
||||
public function verify($response, $remoteIp = null) |
||||
{ |
||||
// Discard empty solution submissions |
||||
if (empty($response)) { |
||||
$recaptchaResponse = new Response(false, array('missing-input-response')); |
||||
return $recaptchaResponse; |
||||
} |
||||
|
||||
$params = new RequestParameters($this->secret, $response, $remoteIp, self::VERSION); |
||||
$rawResponse = $this->requestMethod->submit($params); |
||||
return Response::fromJson($rawResponse); |
||||
} |
||||
} |
@ -0,0 +1,42 @@ |
||||
<?php |
||||
/** |
||||
* This is a PHP library that handles calling reCAPTCHA. |
||||
* |
||||
* @copyright Copyright (c) 2015, Google Inc. |
||||
* @link http://www.google.com/recaptcha |
||||
* |
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy |
||||
* of this software and associated documentation files (the "Software"), to deal |
||||
* in the Software without restriction, including without limitation the rights |
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
||||
* copies of the Software, and to permit persons to whom the Software is |
||||
* furnished to do so, subject to the following conditions: |
||||
* |
||||
* The above copyright notice and this permission notice shall be included in |
||||
* all copies or substantial portions of the Software. |
||||
* |
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN |
||||
* THE SOFTWARE. |
||||
*/ |
||||
|
||||
namespace ReCaptcha; |
||||
|
||||
/** |
||||
* Method used to send the request to the service. |
||||
*/ |
||||
interface RequestMethod |
||||
{ |
||||
|
||||
/** |
||||
* Submit the request with the specified parameters. |
||||
* |
||||
* @param RequestParameters $params Request parameters |
||||
* @return string Body of the reCAPTCHA response |
||||
*/ |
||||
public function submit(RequestParameters $params); |
||||
} |
@ -0,0 +1,74 @@ |
||||
<?php |
||||
/** |
||||
* This is a PHP library that handles calling reCAPTCHA. |
||||
* |
||||
* @copyright Copyright (c) 2015, Google Inc. |
||||
* @link http://www.google.com/recaptcha |
||||
* |
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy |
||||
* of this software and associated documentation files (the "Software"), to deal |
||||
* in the Software without restriction, including without limitation the rights |
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
||||
* copies of the Software, and to permit persons to whom the Software is |
||||
* furnished to do so, subject to the following conditions: |
||||
* |
||||
* The above copyright notice and this permission notice shall be included in |
||||
* all copies or substantial portions of the Software. |
||||
* |
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN |
||||
* THE SOFTWARE. |
||||
*/ |
||||
|
||||
namespace ReCaptcha\RequestMethod; |
||||
|
||||
/** |
||||
* Convenience wrapper around the cURL functions to allow mocking. |
||||
*/ |
||||
class Curl |
||||
{ |
||||
|
||||
/** |
||||
* @see http://php.net/curl_init |
||||
* @param string $url |
||||
* @return resource cURL handle |
||||
*/ |
||||
public function init($url = null) |
||||
{ |
||||
return curl_init($url); |
||||
} |
||||
|
||||
/** |
||||
* @see http://php.net/curl_setopt_array |
||||
* @param resource $ch |
||||
* @param array $options |
||||
* @return bool |
||||
*/ |
||||
public function setoptArray($ch, array $options) |
||||
{ |
||||
return curl_setopt_array($ch, $options); |
||||
} |
||||
|
||||
/** |
||||
* @see http://php.net/curl_exec |
||||
* @param resource $ch |
||||
* @return mixed |
||||
*/ |
||||
public function exec($ch) |
||||
{ |
||||
return curl_exec($ch); |
||||
} |
||||
|
||||
/** |
||||
* @see http://php.net/curl_close |
||||
* @param resource $ch |
||||
*/ |
||||
public function close($ch) |
||||
{ |
||||
curl_close($ch); |
||||
} |
||||
} |
@ -0,0 +1,88 @@ |
||||
<?php |
||||
/** |
||||
* This is a PHP library that handles calling reCAPTCHA. |
||||
* |
||||
* @copyright Copyright (c) 2015, Google Inc. |
||||
* @link http://www.google.com/recaptcha |
||||
* |
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy |
||||
* of this software and associated documentation files (the "Software"), to deal |
||||
* in the Software without restriction, including without limitation the rights |
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
||||
* copies of the Software, and to permit persons to whom the Software is |
||||
* furnished to do so, subject to the following conditions: |
||||
* |
||||
* The above copyright notice and this permission notice shall be included in |
||||
* all copies or substantial portions of the Software. |
||||
* |
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN |
||||
* THE SOFTWARE. |
||||
*/ |
||||
|
||||
namespace ReCaptcha\RequestMethod; |
||||
|
||||
use ReCaptcha\RequestMethod; |
||||
use ReCaptcha\RequestParameters; |
||||
|
||||
/** |
||||
* Sends cURL request to the reCAPTCHA service. |
||||
* Note: this requires the cURL extension to be enabled in PHP |
||||
* @see http://php.net/manual/en/book.curl.php |
||||
*/ |
||||
class CurlPost implements RequestMethod |
||||
{ |
||||
/** |
||||
* URL to which requests are sent via cURL. |
||||
* @const string |
||||
*/ |
||||
const SITE_VERIFY_URL = 'https://recaptcha.net/recaptcha/api/siteverify'; |
||||
|
||||
/** |
||||
* Curl connection to the reCAPTCHA service |
||||
* @var Curl |
||||
*/ |
||||
private $curl; |
||||
|
||||
public function __construct(Curl $curl = null) |
||||
{ |
||||
if (!is_null($curl)) { |
||||
$this->curl = $curl; |
||||
} else { |
||||
$this->curl = new Curl(); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Submit the cURL request with the specified parameters. |
||||
* |
||||
* @param RequestParameters $params Request parameters |
||||
* @return string Body of the reCAPTCHA response |
||||
*/ |
||||
public function submit(RequestParameters $params) |
||||
{ |
||||
$handle = $this->curl->init(self::SITE_VERIFY_URL); |
||||
|
||||
$options = array( |
||||
CURLOPT_POST => true, |
||||
CURLOPT_POSTFIELDS => $params->toQueryString(), |
||||
CURLOPT_HTTPHEADER => array( |
||||
'Content-Type: application/x-www-form-urlencoded' |
||||
), |
||||
CURLINFO_HEADER_OUT => false, |
||||
CURLOPT_HEADER => false, |
||||
CURLOPT_RETURNTRANSFER => true, |
||||
CURLOPT_SSL_VERIFYPEER => true |
||||
); |
||||
$this->curl->setoptArray($handle, $options); |
||||
|
||||
$response = $this->curl->exec($handle); |
||||
$this->curl->close($handle); |
||||
|
||||
return $response; |
||||
} |
||||
} |
@ -0,0 +1,70 @@ |
||||
<?php |
||||
/** |
||||
* This is a PHP library that handles calling reCAPTCHA. |
||||
* |
||||
* @copyright Copyright (c) 2015, Google Inc. |
||||
* @link http://www.google.com/recaptcha |
||||
* |
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy |
||||
* of this software and associated documentation files (the "Software"), to deal |
||||
* in the Software without restriction, including without limitation the rights |
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
||||
* copies of the Software, and to permit persons to whom the Software is |
||||
* furnished to do so, subject to the following conditions: |
||||
* |
||||
* The above copyright notice and this permission notice shall be included in |
||||
* all copies or substantial portions of the Software. |
||||
* |
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN |
||||
* THE SOFTWARE. |
||||
*/ |
||||
|
||||
namespace ReCaptcha\RequestMethod; |
||||
|
||||
use ReCaptcha\RequestMethod; |
||||
use ReCaptcha\RequestParameters; |
||||
|
||||
/** |
||||
* Sends POST requests to the reCAPTCHA service. |
||||
*/ |
||||
class Post implements RequestMethod |
||||
{ |
||||
/** |
||||
* URL to which requests are POSTed. |
||||
* @const string |
||||
*/ |
||||
const SITE_VERIFY_URL = 'https://recaptcha.net/recaptcha/api/siteverify'; |
||||
|
||||
/** |
||||
* Submit the POST request with the specified parameters. |
||||
* |
||||
* @param RequestParameters $params Request parameters |
||||
* @return string Body of the reCAPTCHA response |
||||
*/ |
||||
public function submit(RequestParameters $params) |
||||
{ |
||||
/** |
||||
* PHP 5.6.0 changed the way you specify the peer name for SSL context options. |
||||
* Using "CN_name" will still work, but it will raise deprecated errors. |
||||
*/ |
||||
$peer_key = version_compare(PHP_VERSION, '5.6.0', '<') ? 'CN_name' : 'peer_name'; |
||||
$options = array( |
||||
'http' => array( |
||||
'header' => "Content-type: application/x-www-form-urlencoded\r\n", |
||||
'method' => 'POST', |
||||
'content' => $params->toQueryString(), |
||||
// Force the peer to validate (not needed in 5.6.0+, but still works) |
||||
'verify_peer' => true, |
||||
// Force the peer validation to use www.google.com |
||||
$peer_key => 'www.google.com', |
||||
), |
||||
); |
||||
$context = stream_context_create($options); |
||||
return file_get_contents(self::SITE_VERIFY_URL, false, $context); |
||||
} |
||||
} |
@ -0,0 +1,104 @@ |
||||
<?php |
||||
/** |
||||
* This is a PHP library that handles calling reCAPTCHA. |
||||
* |
||||
* @copyright Copyright (c) 2015, Google Inc. |
||||
* @link http://www.google.com/recaptcha |
||||
* |
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy |
||||
* of this software and associated documentation files (the "Software"), to deal |
||||
* in the Software without restriction, including without limitation the rights |
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
||||
* copies of the Software, and to permit persons to whom the Software is |
||||
* furnished to do so, subject to the following conditions: |
||||
* |
||||
* The above copyright notice and this permission notice shall be included in |
||||
* all copies or substantial portions of the Software. |
||||
* |
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN |
||||
* THE SOFTWARE. |
||||
*/ |
||||
|
||||
namespace ReCaptcha\RequestMethod; |
||||
|
||||
/** |
||||
* Convenience wrapper around native socket and file functions to allow for |
||||
* mocking. |
||||
*/ |
||||
class Socket |
||||
{ |
||||
private $handle = null; |
||||
|
||||
/** |
||||
* fsockopen |
||||
* |
||||
* @see http://php.net/fsockopen |
||||
* @param string $hostname |
||||
* @param int $port |
||||
* @param int $errno |
||||
* @param string $errstr |
||||
* @param float $timeout |
||||
* @return resource |
||||
*/ |
||||
public function fsockopen($hostname, $port = -1, &$errno = 0, &$errstr = '', $timeout = null) |
||||
{ |
||||
$this->handle = fsockopen($hostname, $port, $errno, $errstr, (is_null($timeout) ? ini_get("default_socket_timeout") : $timeout)); |
||||
|
||||
if ($this->handle != false && $errno === 0 && $errstr === '') { |
||||
return $this->handle; |
||||
} |
||||
return false; |
||||
} |
||||
|
||||
/** |
||||
* fwrite |
||||
* |
||||
* @see http://php.net/fwrite |
||||
* @param string $string |
||||
* @param int $length |
||||
* @return int | bool |
||||
*/ |
||||
public function fwrite($string, $length = null) |
||||
{ |
||||
return fwrite($this->handle, $string, (is_null($length) ? strlen($string) : $length)); |
||||
} |
||||
|
||||
/** |
||||
* fgets |
||||
* |
||||
* @see http://php.net/fgets |
||||
* @param int $length |
||||
* @return string |
||||
*/ |
||||
public function fgets($length = null) |
||||
{ |
||||
return fgets($this->handle, $length); |
||||
} |
||||
|
||||
/** |
||||
* feof |
||||
* |
||||
* @see http://php.net/feof |
||||
* @return bool |
||||
*/ |
||||
public function feof() |
||||
{ |
||||
return feof($this->handle); |
||||
} |
||||
|
||||
/** |
||||
* fclose |
||||
* |
||||
* @see http://php.net/fclose |
||||
* @return bool |
||||
*/ |
||||
public function fclose() |
||||
{ |
||||
return fclose($this->handle); |
||||
} |
||||
} |
@ -0,0 +1,121 @@ |
||||
<?php |
||||
/** |
||||
* This is a PHP library that handles calling reCAPTCHA. |
||||
* |
||||
* @copyright Copyright (c) 2015, Google Inc. |
||||
* @link http://www.google.com/recaptcha |
||||
* |
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy |
||||
* of this software and associated documentation files (the "Software"), to deal |
||||
* in the Software without restriction, including without limitation the rights |
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
||||
* copies of the Software, and to permit persons to whom the Software is |
||||
* furnished to do so, subject to the following conditions: |
||||
* |
||||
* The above copyright notice and this permission notice shall be included in |
||||
* all copies or substantial portions of the Software. |
||||
* |
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN |
||||
* THE SOFTWARE. |
||||
*/ |
||||
|
||||
namespace ReCaptcha\RequestMethod; |
||||
|
||||
use ReCaptcha\RequestMethod; |
||||
use ReCaptcha\RequestParameters; |
||||
|
||||
/** |
||||
* Sends a POST request to the reCAPTCHA service, but makes use of fsockopen() |
||||
* instead of get_file_contents(). This is to account for people who may be on |
||||
* servers where allow_url_open is disabled. |
||||
*/ |
||||
class SocketPost implements RequestMethod |
||||
{ |
||||
/** |
||||
* reCAPTCHA service host. |
||||
* @const string |
||||
*/ |
||||
const RECAPTCHA_HOST = 'recaptcha.net'; |
||||
|
||||
/** |
||||
* @const string reCAPTCHA service path |
||||
*/ |
||||
const SITE_VERIFY_PATH = '/recaptcha/api/siteverify'; |
||||
|
||||
/** |
||||
* @const string Bad request error |
||||
*/ |
||||
const BAD_REQUEST = '{"success": false, "error-codes": ["invalid-request"]}'; |
||||
|
||||
/** |
||||
* @const string Bad response error |
||||
*/ |
||||
const BAD_RESPONSE = '{"success": false, "error-codes": ["invalid-response"]}'; |
||||
|
||||
/** |
||||
* Socket to the reCAPTCHA service |
||||
* @var Socket |
||||
*/ |
||||
private $socket; |
||||
|
||||
/** |
||||
* Constructor |
||||
* |
||||
* @param \ReCaptcha\RequestMethod\Socket $socket optional socket, injectable for testing |
||||
*/ |
||||
public function __construct(Socket $socket = null) |
||||
{ |
||||
if (!is_null($socket)) { |
||||
$this->socket = $socket; |
||||
} else { |
||||
$this->socket = new Socket(); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Submit the POST request with the specified parameters. |
||||
* |
||||
* @param RequestParameters $params Request parameters |
||||
* @return string Body of the reCAPTCHA response |
||||
*/ |
||||
public function submit(RequestParameters $params) |
||||
{ |
||||
$errno = 0; |
||||
$errstr = ''; |
||||
|
||||
if (false === $this->socket->fsockopen('ssl://' . self::RECAPTCHA_HOST, 443, $errno, $errstr, 30)) { |
||||
return self::BAD_REQUEST; |
||||
} |
||||
|
||||
$content = $params->toQueryString(); |
||||
|
||||
$request = "POST " . self::SITE_VERIFY_PATH . " HTTP/1.1\r\n"; |
||||
$request .= "Host: " . self::RECAPTCHA_HOST . "\r\n"; |
||||
$request .= "Content-Type: application/x-www-form-urlencoded\r\n"; |
||||
$request .= "Content-length: " . strlen($content) . "\r\n"; |
||||
$request .= "Connection: close\r\n\r\n"; |
||||
$request .= $content . "\r\n\r\n"; |
||||
|
||||
$this->socket->fwrite($request); |
||||
$response = ''; |
||||
|
||||
while (!$this->socket->feof()) { |
||||
$response .= $this->socket->fgets(4096); |
||||
} |
||||
|
||||
$this->socket->fclose(); |
||||
|
||||
if (0 !== strpos($response, 'HTTP/1.1 200 OK')) { |
||||
return self::BAD_RESPONSE; |
||||
} |
||||
|
||||
$parts = preg_split("#\n\s*\n#Uis", $response); |
||||
|
||||
return $parts[1]; |
||||
} |
||||
} |
@ -0,0 +1,103 @@ |
||||
<?php |
||||
/** |
||||
* This is a PHP library that handles calling reCAPTCHA. |
||||
* |
||||
* @copyright Copyright (c) 2015, Google Inc. |
||||
* @link http://www.google.com/recaptcha |
||||
* |
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy |
||||
* of this software and associated documentation files (the "Software"), to deal |
||||
* in the Software without restriction, including without limitation the rights |
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
||||
* copies of the Software, and to permit persons to whom the Software is |
||||
* furnished to do so, subject to the following conditions: |
||||
* |
||||
* The above copyright notice and this permission notice shall be included in |
||||
* all copies or substantial portions of the Software. |
||||
* |
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN |
||||
* THE SOFTWARE. |
||||
*/ |
||||
|
||||
namespace ReCaptcha; |
||||
|
||||
/** |
||||
* Stores and formats the parameters for the request to the reCAPTCHA service. |
||||
*/ |
||||
class RequestParameters |
||||
{ |
||||
/** |
||||
* Site secret. |
||||
* @var string |
||||
*/ |
||||
private $secret; |
||||
|
||||
/** |
||||
* Form response. |
||||
* @var string |
||||
*/ |
||||
private $response; |
||||
|
||||
/** |
||||
* Remote user's IP address. |
||||
* @var string |
||||
*/ |
||||
private $remoteIp; |
||||
|
||||
/** |
||||
* Client version. |
||||
* @var string |
||||
*/ |
||||
private $version; |
||||
|
||||
/** |
||||
* Initialise parameters. |
||||
* |
||||
* @param string $secret Site secret. |
||||
* @param string $response Value from g-captcha-response form field. |
||||
* @param string $remoteIp User's IP address. |
||||
* @param string $version Version of this client library. |
||||
*/ |
||||
public function __construct($secret, $response, $remoteIp = null, $version = null) |
||||
{ |
||||
$this->secret = $secret; |
||||
$this->response = $response; |
||||
$this->remoteIp = $remoteIp; |
||||
$this->version = $version; |
||||
} |
||||
|
||||
/** |
||||
* Array representation. |
||||
* |
||||
* @return array Array formatted parameters. |
||||
*/ |
||||
public function toArray() |
||||
{ |
||||
$params = array('secret' => $this->secret, 'response' => $this->response); |
||||
|
||||
if (!is_null($this->remoteIp)) { |
||||
$params['remoteip'] = $this->remoteIp; |
||||
} |
||||
|
||||
if (!is_null($this->version)) { |
||||
$params['version'] = $this->version; |
||||
} |
||||
|
||||
return $params; |
||||
} |
||||
|
||||
/** |
||||
* Query string representation for HTTP request. |
||||
* |
||||
* @return string Query string formatted parameters. |
||||
*/ |
||||
public function toQueryString() |
||||
{ |
||||
return http_build_query($this->toArray(), '', '&'); |
||||
} |
||||
} |
@ -0,0 +1,122 @@ |
||||
<?php |
||||
/** |
||||
* This is a PHP library that handles calling reCAPTCHA. |
||||
* |
||||
* @copyright Copyright (c) 2015, Google Inc. |
||||
* @link http://www.google.com/recaptcha |
||||
* |
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy |
||||
* of this software and associated documentation files (the "Software"), to deal |
||||
* in the Software without restriction, including without limitation the rights |
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
||||
* copies of the Software, and to permit persons to whom the Software is |
||||
* furnished to do so, subject to the following conditions: |
||||
* |
||||
* The above copyright notice and this permission notice shall be included in |
||||
* all copies or substantial portions of the Software. |
||||
* |
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN |
||||
* THE SOFTWARE. |
||||
*/ |
||||
|
||||
namespace ReCaptcha; |
||||
|
||||
/** |
||||
* The response returned from the service. |
||||
*/ |
||||
class Response |
||||
{ |
||||
/** |
||||
* Success or failure. |
||||
* @var boolean |
||||
*/ |
||||
private $success = false; |
||||
|
||||
/** |
||||
* Error code strings. |
||||
* @var array |
||||
*/ |
||||
private $errorCodes = array(); |
||||
|
||||
/** |
||||
* The hostname of the site where the reCAPTCHA was solved. |
||||
* @var string |
||||
*/ |
||||
private $hostname; |
||||
|
||||
/** |
||||
* Build the response from the expected JSON returned by the service. |
||||
* |
||||
* @param string $json |
||||
* @return \ReCaptcha\Response |
||||
*/ |
||||
public static function fromJson($json) |
||||
{ |
||||
$responseData = json_decode($json, true); |
||||
|
||||
if (!$responseData) { |
||||
return new Response(false, array('invalid-json')); |
||||
} |
||||
|
||||
$hostname = isset($responseData['hostname']) ? $responseData['hostname'] : null; |
||||
|
||||
if (isset($responseData['success']) && $responseData['success'] == true) { |
||||
return new Response(true, array(), $hostname); |
||||
} |
||||
|
||||
if (isset($responseData['error-codes']) && is_array($responseData['error-codes'])) { |
||||
return new Response(false, $responseData['error-codes'], $hostname); |
||||
} |
||||
|
||||
return new Response(false, array(), $hostname); |
||||
} |
||||
|
||||
/** |
||||
* Constructor. |
||||
* |
||||
* @param boolean $success |
||||
* @param array $errorCodes |
||||
* @param string $hostname |
||||
*/ |
||||
public function __construct($success, array $errorCodes = array(), $hostname = null) |
||||
{ |
||||
$this->success = $success; |
||||
$this->errorCodes = $errorCodes; |
||||
$this->hostname = $hostname; |
||||
} |
||||
|
||||
/** |
||||
* Is success? |
||||
* |
||||
* @return boolean |
||||
*/ |
||||
public function isSuccess() |
||||
{ |
||||
return $this->success; |
||||
} |
||||
|
||||
/** |
||||
* Get error codes. |
||||
* |
||||
* @return array |
||||
*/ |
||||
public function getErrorCodes() |
||||
{ |
||||
return $this->errorCodes; |
||||
} |
||||
|
||||
/** |
||||
* Get hostname. |
||||
* |
||||
* @return string |
||||
*/ |
||||
public function getHostname() |
||||
{ |
||||
return $this->hostname; |
||||
} |
||||
} |
@ -0,0 +1,38 @@ |
||||
<?php |
||||
|
||||
/* An autoloader for ReCaptcha\Foo classes. This should be required() |
||||
* by the user before attempting to instantiate any of the ReCaptcha |
||||
* classes. |
||||
*/ |
||||
|
||||
spl_autoload_register(function ($class) { |
||||
if (substr($class, 0, 10) !== 'ReCaptcha\\') { |
||||
/* If the class does not lie under the "ReCaptcha" namespace, |
||||
* then we can exit immediately. |
||||
*/ |
||||
return; |
||||
} |
||||
|
||||
/* All of the classes have names like "ReCaptcha\Foo", so we need |
||||
* to replace the backslashes with frontslashes if we want the |
||||
* name to map directly to a location in the filesystem. |
||||
*/ |
||||
$class = str_replace('\\', '/', $class); |
||||
|
||||
/* First, check under the current directory. It is important that |
||||
* we look here first, so that we don't waste time searching for |
||||
* test classes in the common case. |
||||
*/ |
||||
$path = dirname(__FILE__).'/'.$class.'.php'; |
||||
if (is_readable($path)) { |
||||
require_once $path; |
||||
} |
||||
|
||||
/* If we didn't find what we're looking for already, maybe it's |
||||
* a test class? |
||||
*/ |
||||
$path = dirname(__FILE__).'/../tests/'.$class.'.php'; |
||||
if (is_readable($path)) { |
||||
require_once $path; |
||||
} |
||||
}); |
@ -0,0 +1,75 @@ |
||||
<?php |
||||
/** |
||||
* This is a PHP library that handles calling reCAPTCHA. |
||||
* |
||||
* @copyright Copyright (c) 2015, Google Inc. |
||||
* @link http://www.google.com/recaptcha |
||||
* |
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy |
||||
* of this software and associated documentation files (the "Software"), to deal |
||||
* in the Software without restriction, including without limitation the rights |
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
||||
* copies of the Software, and to permit persons to whom the Software is |
||||
* furnished to do so, subject to the following conditions: |
||||
* |
||||
* The above copyright notice and this permission notice shall be included in |
||||
* all copies or substantial portions of the Software. |
||||
* |
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN |
||||
* THE SOFTWARE. |
||||
*/ |
||||
|
||||
namespace ReCaptcha; |
||||
|
||||
class ReCaptchaTest extends \PHPUnit_Framework_TestCase |
||||
{ |
||||
|
||||
/** |
||||
* @expectedException \RuntimeException |
||||
* @dataProvider invalidSecretProvider |
||||
*/ |
||||
public function testExceptionThrownOnInvalidSecret($invalid) |
||||
{ |
||||
$rc = new ReCaptcha($invalid); |
||||
} |
||||
|
||||
public function invalidSecretProvider() |
||||
{ |
||||
return array( |
||||
array(''), |
||||
array(null), |
||||
array(0), |
||||
array(new \stdClass()), |
||||
array(array()), |
||||
); |
||||
} |
||||
|
||||
public function testVerifyReturnsErrorOnMissingResponse() |
||||
{ |
||||
$rc = new ReCaptcha('secret'); |
||||
$response = $rc->verify(''); |
||||
$this->assertFalse($response->isSuccess()); |
||||
$this->assertEquals(array('missing-input-response'), $response->getErrorCodes()); |
||||
} |
||||
|
||||
public function testVerifyReturnsResponse() |
||||
{ |
||||
$method = $this->getMock('\\ReCaptcha\\RequestMethod', array('submit')); |
||||
$method->expects($this->once()) |
||||
->method('submit') |
||||
->with($this->callback(function ($params) { |
||||
|
||||
return true; |
||||
})) |
||||
->will($this->returnValue('{"success": true}')); |
||||
; |
||||
$rc = new ReCaptcha('secret', $method); |
||||
$response = $rc->verify('response'); |
||||
$this->assertTrue($response->isSuccess()); |
||||
} |
||||
} |
@ -0,0 +1,63 @@ |
||||
<?php |
||||
/** |
||||
* This is a PHP library that handles calling reCAPTCHA. |
||||
* |
||||
* @copyright Copyright (c) 2015, Google Inc. |
||||
* @link http://www.google.com/recaptcha |
||||
* |
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy |
||||
* of this software and associated documentation files (the "Software"), to deal |
||||
* in the Software without restriction, including without limitation the rights |
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
||||
* copies of the Software, and to permit persons to whom the Software is |
||||
* furnished to do so, subject to the following conditions: |
||||
* |
||||
* The above copyright notice and this permission notice shall be included in |
||||
* all copies or substantial portions of the Software. |
||||
* |
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN |
||||
* THE SOFTWARE. |
||||
*/ |
||||
|
||||
namespace ReCaptcha\RequestMethod; |
||||
|
||||
use \ReCaptcha\RequestParameters; |
||||
|
||||
class CurlPostTest extends \PHPUnit_Framework_TestCase |
||||
{ |
||||
|
||||
protected function setUp() |
||||
{ |
||||
if (!extension_loaded('curl')) { |
||||
$this->markTestSkipped( |
||||
'The cURL extension is not available.' |
||||
); |
||||
} |
||||
} |
||||
|
||||
public function testSubmit() |
||||
{ |
||||
$curl = $this->getMock('\\ReCaptcha\\RequestMethod\\Curl', |
||||
array('init', 'setoptArray', 'exec', 'close')); |
||||
$curl->expects($this->once()) |
||||
->method('init') |
||||
->willReturn(new \stdClass); |
||||
$curl->expects($this->once()) |
||||
->method('setoptArray') |
||||
->willReturn(true); |
||||
$curl->expects($this->once()) |
||||
->method('exec') |
||||
->willReturn('RESPONSEBODY'); |
||||
$curl->expects($this->once()) |
||||
->method('close'); |
||||
|
||||
$pc = new CurlPost($curl); |
||||
$response = $pc->submit(new RequestParameters("secret", "response")); |
||||
$this->assertEquals('RESPONSEBODY', $response); |
||||
} |
||||
} |
@ -0,0 +1,118 @@ |
||||
<?php |
||||
/** |
||||
* This is a PHP library that handles calling reCAPTCHA. |
||||
* |
||||
* @copyright Copyright (c) 2015, Google Inc. |
||||
* @link http://www.google.com/recaptcha |
||||
* |
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy |
||||
* of this software and associated documentation files (the "Software"), to deal |
||||
* in the Software without restriction, including without limitation the rights |
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
||||
* copies of the Software, and to permit persons to whom the Software is |
||||
* furnished to do so, subject to the following conditions: |
||||
* |
||||
* The above copyright notice and this permission notice shall be included in |
||||
* all copies or substantial portions of the Software. |
||||
* |
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN |
||||
* THE SOFTWARE. |
||||
*/ |
||||
|
||||
namespace ReCaptcha\RequestMethod; |
||||
|
||||
use ReCaptcha\RequestParameters; |
||||
|
||||
class PostTest extends \PHPUnit_Framework_TestCase |
||||
{ |
||||
public static $assert = null; |
||||
protected $parameters = null; |
||||
protected $runcount = 0; |
||||
|
||||
public function setUp() |
||||
{ |
||||
$this->parameters = new RequestParameters("secret", "response", "remoteip", "version"); |
||||
} |
||||
|
||||
public function tearDown() |
||||
{ |
||||
self::$assert = null; |
||||
} |
||||
|
||||
public function testHTTPContextOptions() |
||||
{ |
||||
$req = new Post(); |
||||
self::$assert = array($this, "httpContextOptionsCallback"); |
||||
$req->submit($this->parameters); |
||||
$this->assertEquals(1, $this->runcount, "The assertion was ran"); |
||||
} |
||||
|
||||
public function testSSLContextOptions() |
||||
{ |
||||
$req = new Post(); |
||||
self::$assert = array($this, "sslContextOptionsCallback"); |
||||
$req->submit($this->parameters); |
||||
$this->assertEquals(1, $this->runcount, "The assertion was ran"); |
||||
} |
||||
|
||||
public function httpContextOptionsCallback(array $args) |
||||
{ |
||||
$this->runcount++; |
||||
$this->assertCommonOptions($args); |
||||
|
||||
$options = stream_context_get_options($args[2]); |
||||
$this->assertArrayHasKey('http', $options); |
||||
|
||||
$this->assertArrayHasKey('method', $options['http']); |
||||
$this->assertEquals("POST", $options['http']['method']); |
||||
|
||||
$this->assertArrayHasKey('content', $options['http']); |
||||
$this->assertEquals($this->parameters->toQueryString(), $options['http']['content']); |
||||
|
||||
$this->assertArrayHasKey('header', $options['http']); |
||||
$headers = array( |
||||
"Content-type: application/x-www-form-urlencoded", |
||||
); |
||||
foreach ($headers as $header) { |
||||
$this->assertContains($header, $options['http']['header']); |
||||
} |
||||
} |
||||
|
||||
public function sslContextOptionsCallback(array $args) |
||||
{ |
||||
$this->runcount++; |
||||
$this->assertCommonOptions($args); |
||||
|
||||
$options = stream_context_get_options($args[2]); |
||||
$this->assertArrayHasKey('http', $options); |
||||
$this->assertArrayHasKey('verify_peer', $options['http']); |
||||
$this->assertTrue($options['http']['verify_peer']); |
||||
|
||||
$key = version_compare(PHP_VERSION, "5.6.0", "<") ? "CN_name" : "peer_name"; |
||||
|
||||
$this->assertArrayHasKey($key, $options['http']); |
||||
$this->assertEquals("www.google.com", $options['http'][$key]); |
||||
} |
||||
|
||||
protected function assertCommonOptions(array $args) |
||||
{ |
||||
$this->assertCount(3, $args); |
||||
$this->assertStringStartsWith("https://www.google.com/", $args[0]); |
||||
$this->assertFalse($args[1]); |
||||
$this->assertTrue(is_resource($args[2]), "The context options should be a resource"); |
||||
} |
||||
} |
||||
|
||||
function file_get_contents() |
||||
{ |
||||
if (PostTest::$assert) { |
||||
return call_user_func(PostTest::$assert, func_get_args()); |
||||
} |
||||
// Since we can't represent maxlen in userland... |
||||
return call_user_func_array('file_get_contents', func_get_args()); |
||||
} |
@ -0,0 +1,90 @@ |
||||
<?php |
||||
/** |
||||
* This is a PHP library that handles calling reCAPTCHA. |
||||
* |
||||
* @copyright Copyright (c) 2015, Google Inc. |
||||
* @link http://www.google.com/recaptcha |
||||
* |
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy |
||||
* of this software and associated documentation files (the "Software"), to deal |
||||
* in the Software without restriction, including without limitation the rights |
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
||||
* copies of the Software, and to permit persons to whom the Software is |
||||
* furnished to do so, subject to the following conditions: |
||||
* |
||||
* The above copyright notice and this permission notice shall be included in |
||||
* all copies or substantial portions of the Software. |
||||
* |
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN |
||||
* THE SOFTWARE. |
||||
*/ |
||||
|
||||
namespace ReCaptcha\RequestMethod; |
||||
|
||||
use ReCaptcha\RequestParameters; |
||||
|
||||
class SocketPostTest extends \PHPUnit_Framework_TestCase |
||||
{ |
||||
|
||||
public function testSubmitSuccess() |
||||
{ |
||||
$socket = $this->getMock('\\ReCaptcha\\RequestMethod\\Socket', array('fsockopen', 'fwrite', 'fgets', 'feof', 'fclose')); |
||||
$socket->expects($this->once()) |
||||
->method('fsockopen') |
||||
->willReturn(true); |
||||
$socket->expects($this->once()) |
||||
->method('fwrite'); |
||||
$socket->expects($this->once()) |
||||
->method('fgets') |
||||
->willReturn("HTTP/1.1 200 OK\n\nRESPONSEBODY"); |
||||
$socket->expects($this->exactly(2)) |
||||
->method('feof') |
||||
->will($this->onConsecutiveCalls(false, true)); |
||||
$socket->expects($this->once()) |
||||
->method('fclose') |
||||
->willReturn(true); |
||||
|
||||
$ps = new SocketPost($socket); |
||||
$response = $ps->submit(new RequestParameters("secret", "response", "remoteip", "version")); |
||||
$this->assertEquals('RESPONSEBODY', $response); |
||||
} |
||||
|
||||
public function testSubmitBadResponse() |
||||
{ |
||||
$socket = $this->getMock('\\ReCaptcha\\RequestMethod\\Socket', array('fsockopen', 'fwrite', 'fgets', 'feof', 'fclose')); |
||||
$socket->expects($this->once()) |
||||
->method('fsockopen') |
||||
->willReturn(true); |
||||
$socket->expects($this->once()) |
||||
->method('fwrite'); |
||||
$socket->expects($this->once()) |
||||
->method('fgets') |
||||
->willReturn("HTTP/1.1 500 NOPEn\\nBOBBINS"); |
||||
$socket->expects($this->exactly(2)) |
||||
->method('feof') |
||||
->will($this->onConsecutiveCalls(false, true)); |
||||
$socket->expects($this->once()) |
||||
->method('fclose') |
||||
->willReturn(true); |
||||
|
||||
$ps = new SocketPost($socket); |
||||
$response = $ps->submit(new RequestParameters("secret", "response", "remoteip", "version")); |
||||
$this->assertEquals(SocketPost::BAD_RESPONSE, $response); |
||||
} |
||||
|
||||
public function testSubmitBadRequest() |
||||
{ |
||||
$socket = $this->getMock('\\ReCaptcha\\RequestMethod\\Socket', array('fsockopen')); |
||||
$socket->expects($this->once()) |
||||
->method('fsockopen') |
||||
->willReturn(false); |
||||
$ps = new SocketPost($socket); |
||||
$response = $ps->submit(new RequestParameters("secret", "response", "remoteip", "version")); |
||||
$this->assertEquals(SocketPost::BAD_REQUEST, $response); |
||||
} |
||||
} |
@ -0,0 +1,61 @@ |
||||
<?php |
||||
/** |
||||
* This is a PHP library that handles calling reCAPTCHA. |
||||
* |
||||
* @copyright Copyright (c) 2015, Google Inc. |
||||
* @link http://www.google.com/recaptcha |
||||
* |
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy |
||||
* of this software and associated documentation files (the "Software"), to deal |
||||
* in the Software without restriction, including without limitation the rights |
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
||||
* copies of the Software, and to permit persons to whom the Software is |
||||
* furnished to do so, subject to the following conditions: |
||||
* |
||||
* The above copyright notice and this permission notice shall be included in |
||||
* all copies or substantial portions of the Software. |
||||
* |
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN |
||||
* THE SOFTWARE. |
||||
*/ |
||||
|
||||
namespace ReCaptcha; |
||||
|
||||
class RequestParametersTest extends \PHPUnit_Framework_TestCase |
||||
{ |
||||
|
||||
public function provideValidData() |
||||
{ |
||||
return array( |
||||
array('SECRET', 'RESPONSE', 'REMOTEIP', 'VERSION', |
||||
array('secret' => 'SECRET', 'response' => 'RESPONSE', 'remoteip' => 'REMOTEIP', 'version' => 'VERSION'), |
||||
'secret=SECRET&response=RESPONSE&remoteip=REMOTEIP&version=VERSION'), |
||||
array('SECRET', 'RESPONSE', null, null, |
||||
array('secret' => 'SECRET', 'response' => 'RESPONSE'), |
||||
'secret=SECRET&response=RESPONSE'), |
||||
); |
||||
} |
||||
|
||||
/** |
||||
* @dataProvider provideValidData |
||||
*/ |
||||
public function testToArray($secret, $response, $remoteIp, $version, $expectedArray, $expectedQuery) |
||||
{ |
||||
$params = new RequestParameters($secret, $response, $remoteIp, $version); |
||||
$this->assertEquals($params->toArray(), $expectedArray); |
||||
} |
||||
|
||||
/** |
||||
* @dataProvider provideValidData |
||||
*/ |
||||
public function testToQueryString($secret, $response, $remoteIp, $version, $expectedArray, $expectedQuery) |
||||
{ |
||||
$params = new RequestParameters($secret, $response, $remoteIp, $version); |
||||
$this->assertEquals($params->toQueryString(), $expectedQuery); |
||||
} |
||||
} |
@ -0,0 +1,84 @@ |
||||
<?php |
||||
/** |
||||
* This is a PHP library that handles calling reCAPTCHA. |
||||
* |
||||
* @copyright Copyright (c) 2015, Google Inc. |
||||
* @link http://www.google.com/recaptcha |
||||
* |
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy |
||||
* of this software and associated documentation files (the "Software"), to deal |
||||
* in the Software without restriction, including without limitation the rights |
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
||||
* copies of the Software, and to permit persons to whom the Software is |
||||
* furnished to do so, subject to the following conditions: |
||||
* |
||||
* The above copyright notice and this permission notice shall be included in |
||||
* all copies or substantial portions of the Software. |
||||
* |
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN |
||||
* THE SOFTWARE. |
||||
*/ |
||||
|
||||
namespace ReCaptcha; |
||||
|
||||
class ResponseTest extends \PHPUnit_Framework_TestCase |
||||
{ |
||||
|
||||
/** |
||||
* @dataProvider provideJson |
||||
*/ |
||||
public function testFromJson($json, $success, $errorCodes, $hostname) |
||||
{ |
||||
$response = Response::fromJson($json); |
||||
$this->assertEquals($success, $response->isSuccess()); |
||||
$this->assertEquals($errorCodes, $response->getErrorCodes()); |
||||
$this->assertEquals($hostname, $response->getHostname()); |
||||
} |
||||
|
||||
public function provideJson() |
||||
{ |
||||
return array( |
||||
array('{"success": true}', true, array(), null), |
||||
array('{"success": true, "hostname": "google.com"}', true, array(), 'google.com'), |
||||
array('{"success": false, "error-codes": ["test"]}', false, array('test'), null), |
||||
array('{"success": false, "error-codes": ["test"], "hostname": "google.com"}', false, array('test'), 'google.com'), |
||||
array('{"success": true, "error-codes": ["test"]}', true, array(), null), |
||||
array('{"success": true, "error-codes": ["test"], "hostname": "google.com"}', true, array(), 'google.com'), |
||||
array('{"success": false}', false, array(), null), |
||||
array('{"success": false, "hostname": "google.com"}', false, array(), 'google.com'), |
||||
array('BAD JSON', false, array('invalid-json'), null), |
||||
); |
||||
} |
||||
|
||||
public function testIsSuccess() |
||||
{ |
||||
$response = new Response(true); |
||||
$this->assertTrue($response->isSuccess()); |
||||
|
||||
$response = new Response(false); |
||||
$this->assertFalse($response->isSuccess()); |
||||
|
||||
$response = new Response(true, array(), 'example.com'); |
||||
$this->assertEquals('example.com', $response->getHostName()); |
||||
} |
||||
|
||||
public function testGetErrorCodes() |
||||
{ |
||||
$errorCodes = array('test'); |
||||
$response = new Response(true, $errorCodes); |
||||
$this->assertEquals($errorCodes, $response->getErrorCodes()); |
||||
} |
||||
|
||||
public function testGetHostname() |
||||
{ |
||||
$hostname = 'google.com'; |
||||
$errorCodes = array(); |
||||
$response = new Response(true, $errorCodes, $hostname); |
||||
$this->assertEquals($hostname, $response->getHostname()); |
||||
} |
||||
} |
Before Width: | Height: | Size: 5.8 KiB |
Before Width: | Height: | Size: 359 B After Width: | Height: | Size: 1.5 KiB |
Before Width: | Height: | Size: 359 B After Width: | Height: | Size: 889 B |
After Width: | Height: | Size: 359 B |
After Width: | Height: | Size: 359 B |