diff --git a/.coveralls.yml b/.coveralls.yml new file mode 100644 index 0000000..9160059 --- /dev/null +++ b/.coveralls.yml @@ -0,0 +1 @@ +service_name: travis-ci diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..1c7898f --- /dev/null +++ b/.travis.yml @@ -0,0 +1,26 @@ +language: php + +php: + - 5.3 + - 5.4 + - 5.5 + - 5.6 + - hhvm + +matrix: + allow_failures: + - php: 5.6 + - php: hhvm + +install: + - composer install + +before_script: + - mkdir -p build/logs + - cd tests + +script: + - phpunit --colors --coverage-clover /home/travis/build/joshtronic/php-projecthoneypot/build/logs/clover.xml . + +after_success: + - php ../vendor/bin/coveralls --config ../.coveralls.yml -v diff --git a/README.md b/README.md index fef8d25..3bf6451 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,41 @@ -php-projecthoneypot -=================== +# php-projecthoneypot [![Build Status](https://travis-ci.org/joshtronic/php-projecthoneypot.svg)](https://travis-ci.org/joshtronic/php-projecthoneypot) [![Coverage Status](https://coveralls.io/repos/joshtronic/php-projecthoneypot/badge.png)](https://coveralls.io/r/joshtronic/php-projecthoneypot) -PHP Wrapper for Project Honey Pot \ No newline at end of file +PHP Wrapper for Project Honey Pot + +## Installation + +The preferred installation method is via `composer`. First add the following to your `composer.json` + +```json +"require": { + "joshtronic/php-projecthoneypot": "dev-master" +} +``` + +Then run `composer update` + +## Usage + +### Getting Started + +```php +require_once 'joshtronic/ProjectHoneyPot.php'; +$php = new joshtronic\ProjectHoneyPot(); +``` + +### Performing a Lookup + +```php +$results = $php->query('1.2.3.4'); +print_r($results); +``` + +### Results + +Queries will return an array of information about the IP address. The array will contain `last_activity`, `threat_score` and an array of `categories`. + +## Contributing + +Suggestions and bug reports are always welcome, but karma points are earned for pull requests. + +Unit tests are required for all contributions. You can run the test suite from the `tests` directory simply by running `phpunit .` diff --git a/composer.json b/composer.json new file mode 100644 index 0000000..ef1fc0f --- /dev/null +++ b/composer.json @@ -0,0 +1,16 @@ +{ + "name": "joshtronic/php-projecthoneypot", + "description": "PHP Wrapper for Project Honey Pot", + "license": "MIT", + "authors": [{ + "name": "Josh Sherman", + "email": "josh@gravityblvd.com", + "homepage": "https://github.com/joshtronic/php-projecthoneypot" + }], + "autoload": { + "classmap": ["src/"] + }, + "require-dev": { + "satooshi/php-coveralls": "dev-master" + } +} diff --git a/src/.ProjectHoneyPot.php.swp b/src/.ProjectHoneyPot.php.swp new file mode 100644 index 0000000..f564ac1 Binary files /dev/null and b/src/.ProjectHoneyPot.php.swp differ diff --git a/src/ProjectHoneyPot.php b/src/ProjectHoneyPot.php index d53fe64..fc4618e 100644 --- a/src/ProjectHoneyPot.php +++ b/src/ProjectHoneyPot.php @@ -43,7 +43,7 @@ class ProjectHoneyPot } else { - throw new Exception('You must specify a valid API key.'); + throw new \Exception('You must specify a valid API key.'); } } @@ -67,7 +67,7 @@ class ProjectHoneyPot $reversed_ip = implode('.', $octets); // Performs the query - $results = dns_get_record($this->api_key . '.' . $reversed_ip . '.dnsbl.httpbl.org', DNS_A); + $results = $this->dns_get_record($reversed_ip); // Processes the results if (isset($results[0]['ip'])) @@ -127,13 +127,29 @@ class ProjectHoneyPot return $results; } } - else - { - return false; - } + } + else + { + return array('error' => 'Invalid IP address.'); } - return array('error' => 'Invalid IP address.'); + return false; + } + + /** + * DNS Get Record + * + * Wrapper method for dns_get_record() to allow fo easy mocking of the + * results in our tests. Takes an already reversed IP address and does a + * DNS lookup for A records against the http:BL API. + * + * @access public + * @param string $reversed_ip reversed IPv4 address to check + * @return array results from the DNS lookup + */ + public function dns_get_record($reversed_ip) + { + return dns_get_record($this->api_key . '.' . $reversed_ip . '.dnsbl.httpbl.org', DNS_A); } } diff --git a/tests/ProjectHoneyPotTest.php b/tests/ProjectHoneyPotTest.php new file mode 100644 index 0000000..e5c4943 --- /dev/null +++ b/tests/ProjectHoneyPotTest.php @@ -0,0 +1,236 @@ +assertEquals( + array('error' => 'Invalid IP address.'), + $object->query('foo') + ); + } + + public function testMissingResults() + { + $mock = $this->getMock( + 'joshtronic\ProjectHoneyPot', + array('dns_get_record'), + array('foobarfoobar') + ); + + $mock->expects($this->once()) + ->method('dns_get_record') + ->will($this->returnValue('foo')); + + $this->assertFalse($mock->query('1.2.3.4')); + } + + public function testCategory0() + { + $mock = $this->getMock( + 'joshtronic\ProjectHoneyPot', + array('dns_get_record'), + array('foobarfoobar') + ); + + $mock->expects($this->once()) + ->method('dns_get_record') + ->will($this->returnValue(array(array('ip' => '127.0.0.0')))); + + $results = $mock->query('1.2.3.4'); + + $this->assertEquals(array('Search Engine'), $results['categories']); + } + + public function testCategory1() + { + $mock = $this->getMock( + 'joshtronic\ProjectHoneyPot', + array('dns_get_record'), + array('foobarfoobar') + ); + + $mock->expects($this->once()) + ->method('dns_get_record') + ->will($this->returnValue(array(array('ip' => '127.0.0.1')))); + + $results = $mock->query('1.2.3.4'); + + $this->assertEquals(array('Suspicious'), $results['categories']); + } + + public function testCategory2() + { + $mock = $this->getMock( + 'joshtronic\ProjectHoneyPot', + array('dns_get_record'), + array('foobarfoobar') + ); + + $mock->expects($this->once()) + ->method('dns_get_record') + ->will($this->returnValue(array(array('ip' => '127.0.0.2')))); + + $results = $mock->query('1.2.3.4'); + + $this->assertEquals(array('Harvester'), $results['categories']); + } + + public function testCategory3() + { + $mock = $this->getMock( + 'joshtronic\ProjectHoneyPot', + array('dns_get_record'), + array('foobarfoobar') + ); + + $mock->expects($this->once()) + ->method('dns_get_record') + ->will($this->returnValue(array(array('ip' => '127.0.0.3')))); + + $results = $mock->query('1.2.3.4'); + + $this->assertEquals( + array('Suspicious', 'Harvester'), + $results['categories'] + ); + } + + public function testCategory4() + { + $mock = $this->getMock( + 'joshtronic\ProjectHoneyPot', + array('dns_get_record'), + array('foobarfoobar') + ); + + $mock->expects($this->once()) + ->method('dns_get_record') + ->will($this->returnValue(array(array('ip' => '127.0.0.4')))); + + $results = $mock->query('1.2.3.4'); + + $this->assertEquals( + array('Comment Spammer'), + $results['categories'] + ); + } + + public function testCategory5() + { + $mock = $this->getMock( + 'joshtronic\ProjectHoneyPot', + array('dns_get_record'), + array('foobarfoobar') + ); + + $mock->expects($this->once()) + ->method('dns_get_record') + ->will($this->returnValue(array(array('ip' => '127.0.0.5')))); + + $results = $mock->query('1.2.3.4'); + + $this->assertEquals( + array('Suspicious', 'Comment Spammer'), + $results['categories'] + ); + } + + public function testCategory6() + { + $mock = $this->getMock( + 'joshtronic\ProjectHoneyPot', + array('dns_get_record'), + array('foobarfoobar') + ); + + $mock->expects($this->once()) + ->method('dns_get_record') + ->will($this->returnValue(array(array('ip' => '127.0.0.6')))); + + $results = $mock->query('1.2.3.4'); + + $this->assertEquals( + array('Harvester', 'Comment Spammer'), + $results['categories'] + ); + } + + public function testCategory7() + { + $mock = $this->getMock( + 'joshtronic\ProjectHoneyPot', + array('dns_get_record'), + array('foobarfoobar') + ); + + $mock->expects($this->once()) + ->method('dns_get_record') + ->will($this->returnValue(array(array('ip' => '127.0.0.7')))); + + $results = $mock->query('1.2.3.4'); + + $this->assertEquals( + array('Suspicious', 'Harvester', 'Comment Spammer'), + $results['categories'] + ); + } + + public function testCategoryDefault() + { + $mock = $this->getMock( + 'joshtronic\ProjectHoneyPot', + array('dns_get_record'), + array('foobarfoobar') + ); + + $mock->expects($this->once()) + ->method('dns_get_record') + ->will($this->returnValue(array(array('ip' => '127.0.0.255')))); + + $results = $mock->query('1.2.3.4'); + + $this->assertEquals( + array('Reserved for Future Use'), + $results['categories'] + ); + } + + public function testWithout127() + { + $mock = $this->getMock( + 'joshtronic\ProjectHoneyPot', + array('dns_get_record'), + array('foobarfoobar') + ); + + $mock->expects($this->once()) + ->method('dns_get_record') + ->will($this->returnValue(array(array('ip' => '1.0.0.0')))); + + $this->assertFalse($mock->query('1.2.3.4')); + } + + // Doesn't serve much purpose aside from helping achieve 100% coverage + public function testDnsGetRecord() + { + $object = new joshtronic\ProjectHoneyPot('foobarfoobar'); + + $object->dns_get_record('1.2.3.4'); + } +} + +?>