├── .gitignore ├── LICENSE.txt ├── README.md ├── composer.json ├── composer.lock ├── phpunit.xml.dist ├── src └── CHH │ └── Stack │ └── Honeypot.php └── tests ├── bootstrap.php └── functional └── HoneypotTest.php /.gitignore: -------------------------------------------------------------------------------- 1 | /vendor 2 | /phpunit.xml 3 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | Copyright © 2013 Christoph Hochstrasser 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy 5 | of this software and associated documentation files (the “Software”), to deal 6 | in the Software without restriction, including without limitation the rights 7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the Software is 9 | furnished to do so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in 12 | all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | THE SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Stack\Honeypot 2 | 3 | A port of [Rack::Honeypot](https://github.com/sunlightlabs/rack-honeypot) to Stack for PHP. 4 | 5 | ## Install 6 | 7 | composer require stack/honey-pot:~1.0 8 | 9 | ## Usage 10 | 11 | Wrap your HttpKernelInterface app in an instance of `CHH\Stack\Honeypot` or add it to your middleware stack. 12 | 13 | With [stack/builder](https://github.com/stackphp/builder): 14 | 15 | ```php 16 | push(CHH\Stack\Honeypot::class, $options) 22 | ->resolve($app); 23 | ``` 24 | 25 | Without the builder: 26 | 27 | ```php 28 | $app = new Stack\Honeypot($app, $options); 29 | ``` 30 | 31 | ### From [Rack::Honeypot](https://github.com/sunlightlabs/rack-honeypot): 32 | 33 | This middleware acts as a spam trap. It inserts, into every outputted `
`, a text field that a spambot will really want to fill in, but is actually not used by the app. The field is hidden to humans via CSS, and includes a warning label for screenreading software. 34 | 35 | In the ``: 36 | 37 | 38 |
39 | 40 | 41 |
42 | [...] 43 | 44 | In the ``: 45 | 46 | 51 | 52 | Then, for incoming requests, the middleware will check if the text field has been set to an unexpected value. If it has, that means a spambot has altered the field, and the spambot is booted to a dead end blank page. 53 | 54 | There are a few options you can pass to the constructor (or to the Stack 55 | Builder): 56 | 57 | * `class_name` is the class assigned to the parent div of the honeypot. Defaults to "phonetoy", an anagram of honeypot. 58 | * `label` is the warning label displayed to those with CSS disabled. Defaults to "Don't fill in this field". 59 | * `input_name` is the name of the form field. Ensure that this is tempting to a spambot if you modify it. Defaults to "email". 60 | * `input_value` is the value of the form field that would only be modified by a spambot. Defaults to blank. 61 | * `always_enabled` (defaults to `true`) set to `false` if you don't 62 | want to insert the trap into all responses returned by your app. 63 | Just add `X-Honeypot: enabled` to your response headers to enable the 64 | trap for this response. 65 | 66 | ## License 67 | 68 | See [LICENSE.txt](LICENSE.txt). 69 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "chh/stack-honeypot", 3 | "description": "Sets up a form honeypot for spambots and redirects them to a blank page", 4 | "authors": [ 5 | { 6 | "name": "Christoph Hochstrasser", 7 | "email": "christoph.hochstrasser@gmail.com" 8 | } 9 | ], 10 | "keywords": ["stack"], 11 | "license": "MIT", 12 | "autoload": { 13 | "psr-0": { 14 | "CHH\\Stack\\": "src" 15 | } 16 | }, 17 | "require": { 18 | "php": ">=5.4.0", 19 | "symfony/http-kernel": "~2.1", 20 | "symfony/http-foundation": "~2.1" 21 | }, 22 | "require-dev": { 23 | "stack/callable-http-kernel": "~1.0@dev", 24 | "symfony/css-selector": "~2.0", 25 | "symfony/browser-kit": "~2.0" 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /composer.lock: -------------------------------------------------------------------------------- 1 | { 2 | "_readme": [ 3 | "This file locks the dependencies of your project to a known state", 4 | "Read more about it at http://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file" 5 | ], 6 | "hash": "11b5b1ee6aed71ed82c1651ada993f2d", 7 | "packages": [ 8 | { 9 | "name": "psr/log", 10 | "version": "1.0.0", 11 | "source": { 12 | "type": "git", 13 | "url": "https://github.com/php-fig/log", 14 | "reference": "1.0.0" 15 | }, 16 | "dist": { 17 | "type": "zip", 18 | "url": "https://github.com/php-fig/log/archive/1.0.0.zip", 19 | "reference": "1.0.0", 20 | "shasum": "" 21 | }, 22 | "type": "library", 23 | "autoload": { 24 | "psr-0": { 25 | "Psr\\Log\\": "" 26 | } 27 | }, 28 | "notification-url": "https://packagist.org/downloads/", 29 | "license": [ 30 | "MIT" 31 | ], 32 | "authors": [ 33 | { 34 | "name": "PHP-FIG", 35 | "homepage": "http://www.php-fig.org/" 36 | } 37 | ], 38 | "description": "Common interface for logging libraries", 39 | "keywords": [ 40 | "log", 41 | "psr", 42 | "psr-3" 43 | ], 44 | "time": "2012-12-21 11:40:51" 45 | }, 46 | { 47 | "name": "symfony/debug", 48 | "version": "v2.4.1", 49 | "target-dir": "Symfony/Component/Debug", 50 | "source": { 51 | "type": "git", 52 | "url": "https://github.com/symfony/Debug.git", 53 | "reference": "74110be5ec681a83fc5bd66dd5fd29fe85fe9c1f" 54 | }, 55 | "dist": { 56 | "type": "zip", 57 | "url": "https://api.github.com/repos/symfony/Debug/zipball/74110be5ec681a83fc5bd66dd5fd29fe85fe9c1f", 58 | "reference": "74110be5ec681a83fc5bd66dd5fd29fe85fe9c1f", 59 | "shasum": "" 60 | }, 61 | "require": { 62 | "php": ">=5.3.3" 63 | }, 64 | "require-dev": { 65 | "symfony/http-foundation": "~2.1", 66 | "symfony/http-kernel": "~2.1" 67 | }, 68 | "suggest": { 69 | "symfony/http-foundation": "", 70 | "symfony/http-kernel": "" 71 | }, 72 | "type": "library", 73 | "extra": { 74 | "branch-alias": { 75 | "dev-master": "2.4-dev" 76 | } 77 | }, 78 | "autoload": { 79 | "psr-0": { 80 | "Symfony\\Component\\Debug\\": "" 81 | } 82 | }, 83 | "notification-url": "https://packagist.org/downloads/", 84 | "license": [ 85 | "MIT" 86 | ], 87 | "authors": [ 88 | { 89 | "name": "Fabien Potencier", 90 | "email": "fabien@symfony.com" 91 | }, 92 | { 93 | "name": "Symfony Community", 94 | "homepage": "http://symfony.com/contributors" 95 | } 96 | ], 97 | "description": "Symfony Debug Component", 98 | "homepage": "http://symfony.com", 99 | "time": "2014-01-01 09:02:49" 100 | }, 101 | { 102 | "name": "symfony/event-dispatcher", 103 | "version": "v2.4.1", 104 | "target-dir": "Symfony/Component/EventDispatcher", 105 | "source": { 106 | "type": "git", 107 | "url": "https://github.com/symfony/EventDispatcher.git", 108 | "reference": "e3ba42f6a70554ed05749e61b829550f6ac33601" 109 | }, 110 | "dist": { 111 | "type": "zip", 112 | "url": "https://api.github.com/repos/symfony/EventDispatcher/zipball/e3ba42f6a70554ed05749e61b829550f6ac33601", 113 | "reference": "e3ba42f6a70554ed05749e61b829550f6ac33601", 114 | "shasum": "" 115 | }, 116 | "require": { 117 | "php": ">=5.3.3" 118 | }, 119 | "require-dev": { 120 | "symfony/dependency-injection": "~2.0" 121 | }, 122 | "suggest": { 123 | "symfony/dependency-injection": "", 124 | "symfony/http-kernel": "" 125 | }, 126 | "type": "library", 127 | "extra": { 128 | "branch-alias": { 129 | "dev-master": "2.4-dev" 130 | } 131 | }, 132 | "autoload": { 133 | "psr-0": { 134 | "Symfony\\Component\\EventDispatcher\\": "" 135 | } 136 | }, 137 | "notification-url": "https://packagist.org/downloads/", 138 | "license": [ 139 | "MIT" 140 | ], 141 | "authors": [ 142 | { 143 | "name": "Fabien Potencier", 144 | "email": "fabien@symfony.com" 145 | }, 146 | { 147 | "name": "Symfony Community", 148 | "homepage": "http://symfony.com/contributors" 149 | } 150 | ], 151 | "description": "Symfony EventDispatcher Component", 152 | "homepage": "http://symfony.com", 153 | "time": "2013-12-28 08:12:03" 154 | }, 155 | { 156 | "name": "symfony/http-foundation", 157 | "version": "v2.4.1", 158 | "target-dir": "Symfony/Component/HttpFoundation", 159 | "source": { 160 | "type": "git", 161 | "url": "https://github.com/symfony/HttpFoundation.git", 162 | "reference": "6c6b8a7bcd7e2cc920cd6acace563fdbf121d844" 163 | }, 164 | "dist": { 165 | "type": "zip", 166 | "url": "https://api.github.com/repos/symfony/HttpFoundation/zipball/6c6b8a7bcd7e2cc920cd6acace563fdbf121d844", 167 | "reference": "6c6b8a7bcd7e2cc920cd6acace563fdbf121d844", 168 | "shasum": "" 169 | }, 170 | "require": { 171 | "php": ">=5.3.3" 172 | }, 173 | "type": "library", 174 | "extra": { 175 | "branch-alias": { 176 | "dev-master": "2.4-dev" 177 | } 178 | }, 179 | "autoload": { 180 | "psr-0": { 181 | "Symfony\\Component\\HttpFoundation\\": "" 182 | }, 183 | "classmap": [ 184 | "Symfony/Component/HttpFoundation/Resources/stubs" 185 | ] 186 | }, 187 | "notification-url": "https://packagist.org/downloads/", 188 | "license": [ 189 | "MIT" 190 | ], 191 | "authors": [ 192 | { 193 | "name": "Fabien Potencier", 194 | "email": "fabien@symfony.com" 195 | }, 196 | { 197 | "name": "Symfony Community", 198 | "homepage": "http://symfony.com/contributors" 199 | } 200 | ], 201 | "description": "Symfony HttpFoundation Component", 202 | "homepage": "http://symfony.com", 203 | "time": "2014-01-05 02:10:50" 204 | }, 205 | { 206 | "name": "symfony/http-kernel", 207 | "version": "v2.4.1", 208 | "target-dir": "Symfony/Component/HttpKernel", 209 | "source": { 210 | "type": "git", 211 | "url": "https://github.com/symfony/HttpKernel.git", 212 | "reference": "0605eedeb52c4d3a3144128d8336395a57be60d4" 213 | }, 214 | "dist": { 215 | "type": "zip", 216 | "url": "https://api.github.com/repos/symfony/HttpKernel/zipball/0605eedeb52c4d3a3144128d8336395a57be60d4", 217 | "reference": "0605eedeb52c4d3a3144128d8336395a57be60d4", 218 | "shasum": "" 219 | }, 220 | "require": { 221 | "php": ">=5.3.3", 222 | "psr/log": "~1.0", 223 | "symfony/debug": "~2.3", 224 | "symfony/event-dispatcher": "~2.1", 225 | "symfony/http-foundation": "~2.4" 226 | }, 227 | "require-dev": { 228 | "symfony/browser-kit": "~2.2", 229 | "symfony/class-loader": "~2.1", 230 | "symfony/config": "~2.0", 231 | "symfony/console": "~2.2", 232 | "symfony/dependency-injection": "~2.0", 233 | "symfony/finder": "~2.0", 234 | "symfony/process": "~2.0", 235 | "symfony/routing": "~2.2", 236 | "symfony/stopwatch": "~2.2", 237 | "symfony/templating": "~2.2" 238 | }, 239 | "suggest": { 240 | "symfony/browser-kit": "", 241 | "symfony/class-loader": "", 242 | "symfony/config": "", 243 | "symfony/console": "", 244 | "symfony/dependency-injection": "", 245 | "symfony/finder": "" 246 | }, 247 | "type": "library", 248 | "extra": { 249 | "branch-alias": { 250 | "dev-master": "2.4-dev" 251 | } 252 | }, 253 | "autoload": { 254 | "psr-0": { 255 | "Symfony\\Component\\HttpKernel\\": "" 256 | } 257 | }, 258 | "notification-url": "https://packagist.org/downloads/", 259 | "license": [ 260 | "MIT" 261 | ], 262 | "authors": [ 263 | { 264 | "name": "Fabien Potencier", 265 | "email": "fabien@symfony.com" 266 | }, 267 | { 268 | "name": "Symfony Community", 269 | "homepage": "http://symfony.com/contributors" 270 | } 271 | ], 272 | "description": "Symfony HttpKernel Component", 273 | "homepage": "http://symfony.com", 274 | "time": "2014-01-05 02:12:11" 275 | } 276 | ], 277 | "packages-dev": [ 278 | { 279 | "name": "stack/callable-http-kernel", 280 | "version": "dev-master", 281 | "source": { 282 | "type": "git", 283 | "url": "https://github.com/stackphp/CallableHttpKernel.git", 284 | "reference": "97f6bd2aaf0f173a902dfd6bd4ffa558a799531d" 285 | }, 286 | "dist": { 287 | "type": "zip", 288 | "url": "https://api.github.com/repos/stackphp/CallableHttpKernel/zipball/97f6bd2aaf0f173a902dfd6bd4ffa558a799531d", 289 | "reference": "97f6bd2aaf0f173a902dfd6bd4ffa558a799531d", 290 | "shasum": "" 291 | }, 292 | "require": { 293 | "php": ">=5.3.0", 294 | "symfony/http-foundation": "~2.1", 295 | "symfony/http-kernel": "~2.1" 296 | }, 297 | "type": "library", 298 | "extra": { 299 | "branch-alias": { 300 | "dev-master": "1.0-dev" 301 | } 302 | }, 303 | "autoload": { 304 | "psr-0": { 305 | "Stack": "src" 306 | } 307 | }, 308 | "notification-url": "https://packagist.org/downloads/", 309 | "license": [ 310 | "MIT" 311 | ], 312 | "authors": [ 313 | { 314 | "name": "Igor Wiedler", 315 | "email": "igor@wiedler.ch", 316 | "homepage": "http://wiedler.ch/igor/" 317 | } 318 | ], 319 | "description": "HttpKernelInterface implementation based on callables.", 320 | "keywords": [ 321 | "stack" 322 | ], 323 | "time": "2013-10-25 14:27:17" 324 | }, 325 | { 326 | "name": "symfony/browser-kit", 327 | "version": "v2.4.1", 328 | "target-dir": "Symfony/Component/BrowserKit", 329 | "source": { 330 | "type": "git", 331 | "url": "https://github.com/symfony/BrowserKit.git", 332 | "reference": "0248b2dfc9cd6b259555d232eedfb1283eb496c3" 333 | }, 334 | "dist": { 335 | "type": "zip", 336 | "url": "https://api.github.com/repos/symfony/BrowserKit/zipball/0248b2dfc9cd6b259555d232eedfb1283eb496c3", 337 | "reference": "0248b2dfc9cd6b259555d232eedfb1283eb496c3", 338 | "shasum": "" 339 | }, 340 | "require": { 341 | "php": ">=5.3.3", 342 | "symfony/dom-crawler": "~2.0" 343 | }, 344 | "require-dev": { 345 | "symfony/css-selector": "~2.0", 346 | "symfony/process": "~2.0" 347 | }, 348 | "suggest": { 349 | "symfony/process": "" 350 | }, 351 | "type": "library", 352 | "extra": { 353 | "branch-alias": { 354 | "dev-master": "2.4-dev" 355 | } 356 | }, 357 | "autoload": { 358 | "psr-0": { 359 | "Symfony\\Component\\BrowserKit\\": "" 360 | } 361 | }, 362 | "notification-url": "https://packagist.org/downloads/", 363 | "license": [ 364 | "MIT" 365 | ], 366 | "authors": [ 367 | { 368 | "name": "Fabien Potencier", 369 | "email": "fabien@symfony.com" 370 | }, 371 | { 372 | "name": "Symfony Community", 373 | "homepage": "http://symfony.com/contributors" 374 | } 375 | ], 376 | "description": "Symfony BrowserKit Component", 377 | "homepage": "http://symfony.com", 378 | "time": "2013-12-28 21:39:51" 379 | }, 380 | { 381 | "name": "symfony/css-selector", 382 | "version": "v2.4.1", 383 | "target-dir": "Symfony/Component/CssSelector", 384 | "source": { 385 | "type": "git", 386 | "url": "https://github.com/symfony/CssSelector.git", 387 | "reference": "352552da1f50a79f6a6fa427e4a85ee2ea1945f6" 388 | }, 389 | "dist": { 390 | "type": "zip", 391 | "url": "https://api.github.com/repos/symfony/CssSelector/zipball/352552da1f50a79f6a6fa427e4a85ee2ea1945f6", 392 | "reference": "352552da1f50a79f6a6fa427e4a85ee2ea1945f6", 393 | "shasum": "" 394 | }, 395 | "require": { 396 | "php": ">=5.3.3" 397 | }, 398 | "type": "library", 399 | "extra": { 400 | "branch-alias": { 401 | "dev-master": "2.4-dev" 402 | } 403 | }, 404 | "autoload": { 405 | "psr-0": { 406 | "Symfony\\Component\\CssSelector\\": "" 407 | } 408 | }, 409 | "notification-url": "https://packagist.org/downloads/", 410 | "license": [ 411 | "MIT" 412 | ], 413 | "authors": [ 414 | { 415 | "name": "Fabien Potencier", 416 | "email": "fabien@symfony.com" 417 | }, 418 | { 419 | "name": "Symfony Community", 420 | "homepage": "http://symfony.com/contributors" 421 | }, 422 | { 423 | "name": "Jean-François Simon", 424 | "email": "jeanfrancois.simon@sensiolabs.com" 425 | } 426 | ], 427 | "description": "Symfony CssSelector Component", 428 | "homepage": "http://symfony.com", 429 | "time": "2014-01-01 08:14:50" 430 | }, 431 | { 432 | "name": "symfony/dom-crawler", 433 | "version": "v2.4.1", 434 | "target-dir": "Symfony/Component/DomCrawler", 435 | "source": { 436 | "type": "git", 437 | "url": "https://github.com/symfony/DomCrawler.git", 438 | "reference": "58e85928ad277c67102a41a046160de86df44d55" 439 | }, 440 | "dist": { 441 | "type": "zip", 442 | "url": "https://api.github.com/repos/symfony/DomCrawler/zipball/58e85928ad277c67102a41a046160de86df44d55", 443 | "reference": "58e85928ad277c67102a41a046160de86df44d55", 444 | "shasum": "" 445 | }, 446 | "require": { 447 | "php": ">=5.3.3" 448 | }, 449 | "require-dev": { 450 | "symfony/css-selector": "~2.0" 451 | }, 452 | "suggest": { 453 | "symfony/css-selector": "" 454 | }, 455 | "type": "library", 456 | "extra": { 457 | "branch-alias": { 458 | "dev-master": "2.4-dev" 459 | } 460 | }, 461 | "autoload": { 462 | "psr-0": { 463 | "Symfony\\Component\\DomCrawler\\": "" 464 | } 465 | }, 466 | "notification-url": "https://packagist.org/downloads/", 467 | "license": [ 468 | "MIT" 469 | ], 470 | "authors": [ 471 | { 472 | "name": "Fabien Potencier", 473 | "email": "fabien@symfony.com" 474 | }, 475 | { 476 | "name": "Symfony Community", 477 | "homepage": "http://symfony.com/contributors" 478 | } 479 | ], 480 | "description": "Symfony DomCrawler Component", 481 | "homepage": "http://symfony.com", 482 | "time": "2013-12-29 20:33:52" 483 | } 484 | ], 485 | "aliases": [ 486 | 487 | ], 488 | "minimum-stability": "stable", 489 | "stability-flags": { 490 | "stack/callable-http-kernel": 20 491 | }, 492 | "platform": { 493 | "php": ">=5.4.0" 494 | }, 495 | "platform-dev": [ 496 | 497 | ] 498 | } 499 | -------------------------------------------------------------------------------- /phpunit.xml.dist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | tests 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /src/CHH/Stack/Honeypot.php: -------------------------------------------------------------------------------- 1 | 'phonetoy', 18 | 'input_name' => 'email', 19 | 'input_value' => '', 20 | 'label' => "Don't fill in this field", 21 | 'always_enabled' => true 22 | ]; 23 | 24 | function __construct(HttpKernelInterface $app, array $options = []) 25 | { 26 | $this->app = $app; 27 | 28 | $options = array_merge($this->defaultOptions, $options); 29 | 30 | $this->className = $options['class_name']; 31 | $this->inputName = $options['input_name']; 32 | $this->inputValue = $options['input_value']; 33 | $this->label = $options['label']; 34 | $this->alwaysEnabled = $options['always_enabled']; 35 | } 36 | 37 | function handle(Request $request, $type = HttpKernelInterface::MASTER_REQUEST, $catch = true) 38 | { 39 | if ($this->isSpamBotRequest($request)) { 40 | return new Response(""); 41 | } 42 | 43 | $response = $this->app->handle($request, $type, $catch); 44 | 45 | if ($this->alwaysEnabled or $response->headers->get('X-Honeypot') === 'enabled') { 46 | $response->setContent($this->insertHoneypot($response->getContent())); 47 | } 48 | 49 | return $response; 50 | } 51 | 52 | function isSpamBotRequest(Request $request) 53 | { 54 | return 55 | $request->request->count() > 0 56 | && $request->request->get($this->inputName) !== $this->inputValue; 57 | } 58 | 59 | function insertHoneypot($body) 60 | { 61 | $body = preg_replace('/()+/', << 64 | 68 | 69 | HTML 70 | , $body); 71 | 72 | $body = preg_replace('/()/', << 75 | div.{$this->className} { 76 | display: none; 77 | } 78 | 79 | HTML 80 | , $body); 81 | 82 | return $body; 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /tests/bootstrap.php: -------------------------------------------------------------------------------- 1 | template = << 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | EOF; 34 | 35 | $this->app = handler(function (Request $request) { 36 | return new Response($this->template, 200); 37 | }); 38 | } 39 | 40 | function testSpambotRequest() 41 | { 42 | $request = Request::create('/foo', 'POST', [ 43 | 'email' => 'test', 44 | ]); 45 | 46 | $response = (new Honeypot($this->app))->handle($request); 47 | 48 | $this->assertTrue($response->isOk()); 49 | $this->assertEquals("", $response->getContent()); 50 | } 51 | 52 | function testInsert() 53 | { 54 | $client = new Client(new Honeypot($this->app)); 55 | $dom = $client->request('GET', '/foo'); 56 | 57 | $this->assertCount(1, $dom->filter('div.phonetoy')); 58 | $this->assertCount(1, $dom->filter('input[name=email]')); 59 | } 60 | 61 | function testOnlyInsertWhenHeaderIsSet() 62 | { 63 | $doNotInsert = handler(function() { 64 | return new Response($this->template, 200); 65 | }); 66 | 67 | $client = new Client(new Honeypot($doNotInsert, ['always_enabled' => false])); 68 | $dom = $client->request('GET', '/foo'); 69 | 70 | $this->assertCount(0, $dom->filter('div.phonetoy')); 71 | $this->assertCount(0, $dom->filter('input[name=email]')); 72 | 73 | $insert = handler(function() { 74 | return new Response($this->template, 200, ['X-Honeypot' => 'enabled']); 75 | }); 76 | 77 | $client = new Client(new Honeypot($insert, ['always_enabled' => false])); 78 | $dom = $client->request('GET', '/foo'); 79 | 80 | $this->assertCount(1, $dom->filter('div.phonetoy')); 81 | $this->assertCount(1, $dom->filter('input[name=email]')); 82 | } 83 | 84 | function testConfigureClassName() 85 | { 86 | $client = new Client(new Honeypot($this->app, ['class_name' => 'honeypot'])); 87 | $dom = $client->request('GET', '/foo'); 88 | 89 | $this->assertCount(1, $dom->filter('div.honeypot')); 90 | } 91 | 92 | function testConfigureInputName() 93 | { 94 | $client = new Client(new Honeypot($this->app, ['input_name' => 'foobar'])); 95 | $dom = $client->request('GET', '/foo'); 96 | 97 | $this->assertCount(1, $dom->filter('input[name=foobar]')); 98 | } 99 | } 100 | --------------------------------------------------------------------------------