5. 00. Introduction
<?php
function isUrlSafe($api_key, $url) {
if (!filter_var($url, FILTER_VALIDATE_URL)) {
throw new Exception('Invalid URL specified.')
}
$api_uri = 'https://sb-ssl.google.com/'
. 'safebrowsing/api/lookup?client=api&apikey='
. $api_key . '&appver=1.0&pver=3.0&url='
. urlencode($url);
$result = file_get_contents($api_uri);
return strpos($result, 'malware') === false
&& strpos($result, 'phishing') === false;
}
When you've finished reading this code, touch your nose so I know when everyone is done.
6. 10. Security
●
Shouldn't be left till last
●
Unsure of how to do it properly
●
Worst thing that can happen to insecure open
source code is it becomes popular
7. 10. Security
●
Shouldn't be left till last
●
Unsure of how to do it properly
●
Worst thing that can happen to insecure open
source code is it becomes popular
8. 01. Security
●
Shouldn't be left till last
●
Unsure of how to do it properly
●
Worst thing that can happen to insecure open
source code is it becomes popular
18. 03. Managing your source
●
Source control (already determined)
●
Version
●
License
19. 03. Credentials
●
.gitignore to exclude sensitive data
●
If you've pushed sensitive data to github,
change your credentials asap
https://help.github.com/articles/remove-sensitive-data
Don't be that guy
20. 03. Licensing
●
MIT
– Do whatever you want with it
– Must attribute
– Don't blame me if it causes a zombie outbreak
●
Apache
– Same as MIT
– contributors grants patent rights to users
●
GPL
– Must release any changes or improvements
– Can't change license
– Ditto with the zombies
http://choosealicense.com/
21. 03. Versioning
MAJOR.MINOR.PATCH-STABILITY
●
Breaking backward compatibility? Increase MAJOR
●
Adding backwards compatible feature? Increase MINOR
●
Adding bugfix? Increase PATCH
●
Not production ready? Add stability value (alpha, beta,
preview)
http://semver.org/
23. 04. Package Management
●
PEAR
– No space for alternatives
– High requirement levels
– Package signing
●
Composer
– Easy to install/update dependencies
– Version locking
– Autoloading
– Your package becomes smaller
– Package signing (almost)
– Doubles as a distribution platform (https://packagist.org )
24. 04. Package Management
●
PEAR - NO
– No space for alternatives
– High requirement levels
– Package signing
●
Composer - YES
– Easy to install/update dependencies
– Version locking
– Autoloading
– Your package becomes smaller
– Package signing (almost)
– Doubles as a distribution platform (https://packagist.org )
25. 04. Composer
$ mkdir safebrowser && cd safebrowser
$ curl -s http://getcomposer.org/installer | php
#!/usr/bin/env php
All settings correct for using Composer
Downloading...
Composer successfully installed to:
/home/project/composer.phar
Use it: php composer.phar
26. 04. Composer
$ php composer.phar init
Welcome to the Composer config generator
This command will guide you through creating your
composer.json config.
Package name (<vendor>/<name>)
[thomas/project]:xsist10/SafeBrowsing
Description []: Google Safe Browsing Client
Author [Thomas Shone <xsist10@gmail.com>]:
Minimum Stability []:
License []: MIT
28. 04. Composer
$ php composer.phar install
Loading composer repositories with package
information
Installing dependencies (including require-dev)
Nothing to install or update
Generating autoload files
$ vi index.php
<?php
require 'vendor/autoload.php';
29. 04. Don't commit vendor/
# Your code
src/[Your Library]
vendor/[Dependencies]
$ echo "vendor" >> .gitignore
# Someone using your library
src/[Their Project Code]
vendor/xsist10/SafeBrowsing/[Your Library]
vendor/[Your Library Dependencies]
vendor/[Their Dependencies]
Some of these might be the same
# You don't want this
vendor/xsist10/SafeBrowsing/[Your Library]/vendor/
30. 04. Composer
$ mkdir src
$ vi src/SafeBrowsing.php
<?php
namespace xsist10SafeBrowsing;
class SafeBrowsing {
public function __construct($api_key) {
$this->api_key = $api_key;
}
public function isUrlSafe($url) {
// ...
}
}
38. 04. Package Signing
●
Currently being implemented in Composer
– https://github.com/composer/composer/pull/2814
●
Ensure that the package you're installing hasn't
been tampered with, like:
– Ruby Gem installs
– PEAR libraries
– Linux packages (deb, rpm, yum)
– Windows binaries
39. 04. Package Signing
# When you first setup your project
$ php composer.phar create-keys --directory /path/
--prefix=mykey --passphrase
passphrase to encrypt the private key:
$ php composer.phar add-dev-key /path/mykey-private.pem
$ php composer.phar sign-dev-keys
/path/mykey-private.pem
# Last thing you do before you release a new version
$ php composer.phar sign /path/mykey-private.pem
Enter a passphrase if the private key is encrypted:
$ git commit -m “Updated keys” keys.json manifest.json
$ git push
# Tag you release immediately
46. 05. Strategy
<?php
namespace xsist10SafeBrowsingStrategy;
class Post implements Strategy {
public function execute($url, $param) {
// Do some curl init stuff ...
// Do your security!
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, 1);
curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, 2);
curl_setopt($curl, CURLOPT_CAINFO, 'path/to/cafile');
$result = curl_exec($curl);
$code = curl_getinfo($curl, CURLINFO_HTTP_CODE);
curl_close($curl);
// check some result checks first ...
return $result;
}
}
47. 05. Strategy
<?php
require 'vendor/autoload.php';
use xsist10SafeBrowsingSafeBrowsing;
use xsist10SafeBrowsingStrategyGet;
$sb = new SafeBrowsing($api_key, new Get());
$sb->isUrlSafe('www.example.com');
use xsist10SafeBrowsingStrategyPost;
$sb = new SafeBrowsing($api_key, new Post());
$sb->isUrlSafe('www.example.com');
49. 05. Chain of Responsibility
<?php
namespace xsist10SafeBrowsingStrategy;
use Exception;
class UnavailableException extends Exception {}
https://en.wikipedia.org/wiki/Strategy_pattern
50. 05. Chain of Responsibility
<?php
namespace xsist10SafeBrowsingStrategy;
class Get implements Strategy {
public function execute($url, $param) {
if (!ini_get('allow_url_fopen')) {
throw new UnavailableException();
}
// ...
}
}
51. 05. Chain of Responsibility
<?php
namespace xsist10SafeBrowsingStrategy;
class Post implements Strategy {
public function execute($url, $param) {
if (!function_exists('curl_init')) {
throw new UnavailableException();
}
// ...
}
}
52. 05. Chain of Responsibility
<?php
namespace xsist10SafeBrowsing;
use xsist10SafeBrowsingStrategyStrategy;
class Chain implements Strategy {
public function append(Strategy $strat) {
$this->chain[] = $strat;
}
public function execute($url, $param) {
foreach ($this->chain as $strategy) {
try {
return $strategy->get($url, $param);
} catch (UnavailableException $exception) {
// We can ignore and move to the next
}
}
throw new Exception('No available strategy.');
}
}
53. 05. Put the chain links together
<?php
// ...
use xsist10SafeBrowsingChain;
$chain = new Chain();
$chain->append(new Post());
$chain->append(new Get());
$sb = new SafeBrowsing($api_key, $chain);
$sb->isUrlSafe('www.example.com');
// This still works
$sb = new SafeBrowsing($api_key, new Get());
$sb->isUrlSafe('www.example.com');
54. 05. The start of something
beautiful
<?php
// ...
use SomeOtherGuySomeOtherPackageCache;
$chain = new Chain();
$chain->append(new Cache());
$chain->append(new Post());
$chain->append(new Get());
$sb = new SafeBrowsing($api_key, $chain);
$sb->isUrlSafe('www.example.com');
56. So what next?
Shamelessly copied from http://thephpleague.com/
●
Follow PSR-2, we use League as our PSR-0 namespace.
●
List on Packagist, we list with league as the vendor namespace.
●
Shove code in a src folder.
●
Write unit tests. Aim for at least 80% coverage for v1.0.
●
DocBlock all the things.
●
Semantic versioning must be used to manage version numbers.
●
Use Travis-CI to automatically check coding standards and run tests.
●
Have an extensive README.
57. 06. Why Tests?
●
You will always find bugs
●
Confidence in libraries
●
Prevent regressions
●
Ensure new features have been thoroughly
vetted
60. 06. PHPUnit
$ vi phpunit.xml$ ./vendor/bin/phpunit
PHPUnit 4.0.13 by Sebastian Bergmann.
Configuration read from /path/to/project/phpunit.xml
Time: 116 ms, Memory: 2.00Mb
No tests executed!
61. 06. First Tests
use xsist10SafeBrowsingSafeBrowsing;
use xsist10SafeBrowsingStrategyChain;
class SafeBrowsingTest extends PHPUnit_Framework_TestCase
{
public function testInvalidUrl()
{
$chain = new Chain();
$safeBrowsing = new SafeBrowsing('', $chain);
$message = 'Invalid URL specified.';
$this->setExpectedException('Exception', $message);
$safeBrowsing->isUrlSafe('invalid-url');
}
}
$ vi tests/SafeBrowsingTest.php
62. 06. First Tests
public function testSecure()
{
$mock = $this->getMockBuilder(
'xsist10SafeBrowsingStrategyChain',
['execute']
)->getMock();
// API returns an empty result if the site is secure
$mock->expects($this->once())
->method('execute')
->will($this->returnValue(''));
$safeBrowsing = new SafeBrowsing('', $mock);
$url = 'http://www.google.com';
$response = $safeBrowsing->isUrlSafe($url);
$this->assertTrue($response);
}
63. 06. First Tests
$ vi phpunit.xml$ ./vendor/bin/phpunit
PHPUnit 4.0.13 by Sebastian Bergmann.
Configuration read from /path/to/project/phpunit.xml
.....
Time: 568 ms, Memory: 4.00Mb
OK (5 tests, 9 assertions)
64. 06. Testing Resources
●
Can't mock out resources
●
Wrap resources in class and mock the class
●
Wait! Don't write from scratch. Use your
package manager!
65. 06. cURL wrapper
$ ./composer.phar search curl
ext-curl The curl PHP extension
lib-curl The curl PHP library
kdyby/curl Curl wrapper for Nette Framework
shuber/curl PHP Wrapper for Curl
comvi/curl Work with remote servers via cURL much easier
than using the native PHP bindings.
anlutro/curl Simple OOP cURL wrapper.
jyggen/curl A simple and lightweight cURL library with
support for multiple requests in parallel.
bca/curl cURL wrapper for PHP applications.
unikent/curl Laravel Curl Helper Library.
mogetutu/curl Simple Curl PHP Helper Library
sweelix/curl PHP 5.3+ simple curl requestor
lib/curl A simple cURL wrapper for PHP
dvelopment/curl PHP OOP wrapper for cURL requests
php-curl-class/php-curl-class PHP Curl Class is an
object-oriented wrapper of the PHP cURL extension.
66. 06. cURL wrapper
$ php composer.phar require shuber/curl=dev-master
./composer.json has been updated
Loading composer repositories with package information
Updating dependencies (including require-dev)
- Installing shuber/curl (dev-master 6624992)
Cloning 6624992df201f9fd7262080117385dd09b0ecd2b
Writing lock file
Generating autoload files
67. 06. Personality
Chris Hartjes (@grmpyprogrammer)
Testing advocate
Being grumpy... so we don't have to
Itotallydidn'tgetpermissiontousethisphoto
69. 07. Code Coverage
●
Ensure you test all use cases
●
Useful to spot code smell
●
Helpful in identifying dead/unreachable code
●
Improves confidence in library
77. 08. CLI Tools
●
Copy paste detector
●
Code Sniffer
●
Mess Detector
●
And lots more at http://phpqatools.org/
78. 07 – Copy/paste detector
$ php composer.phar require --dev sebastian/phpcpd=dev-master
./composer.json has been updated
Loading composer repositories with package information
Updating dependencies (including require-dev)
- Installing sebastian/phpcpd (dev-master a946215)
Cloning a9462153f2dd90466a010179901d31fbff598365
Writing lock file
Generating autoload files
$ ./vendor/bin/phpcpd src/
phpcpd 2.0.1 by Sebastian Bergmann.
0.00% duplicated lines out of 195 total lines of code.
Time: 32 ms, Memory: 2.75Mb
79. 08. Code Sniffer
$ php composer.phar require --dev
squizlabs/php_codesniffer=dev-master
./composer.json has been updated
Loading composer repositories with package information
Updating dependencies (including require-dev)
- Installing squizlabs/php_codesniffer (dev-master 623905c)
Cloning 623905ce571d64a8cb873826d47b81321cd55011
Writing lock file
Generating autoload files
$ ./vendor/bin/phpcs -i
The installed coding standards are PSR1, PHPCS, Squiz, PEAR,
Zend, MySource and PSR2
$ ./vendor/bin/phpcs --standard=PSR2 src/
[WALL OF TEXT]
80. 08. Select a Standard
$ ./vendor/bin/phpcs --standard=PSR2 src/
FILE: /path/to/project/SafeBrowsing/src/SafeBrowsing.php
-------------------------------------------------------------------
FOUND 3 ERROR(S) AFFECTING 2 LINE(S)
-------------------------------------------------------------------
17 | ERROR | Opening brace should be on a new line
22 | ERROR | Visibility must be declared on method "isUrlSafe"
22 | ERROR | Opening brace should be on a new line
-------------------------------------------------------------------
[WALL OF TEXT OMITTED]
81. 08. Custom Standard
$ ./vendor/bin/phpcs --standard=/path/to/own/standard src/
FILE: /path/to/project/SafeBrowsing/src/SafeBrowsing.php
-------------------------------------------------------------------
FOUND 1 ERROR(S) AFFECTING 1 LINE(S)
-------------------------------------------------------------------
1 | ERROR | Homage to Cthulhu missing from doc header
-------------------------------------------------------------------
82. 08. Mess Detector
$ php composer.phar require --dev phpmd/phpmd=1.4.*
./composer.json has been updated
Loading composer repositories with package information
Updating dependencies (including require-dev)
- Installing phpmd/phpmd (1.4.1)
Downloading: 100%
Writing lock file
Generating autoload files
$ ./vendor/bin/phpmd src text codesize,unusedcode,naming,design
Strategy/Get.php:9 Classes should not have a constructor method
with the same name as the class
83. 08. Taking it further
●
Jenkins
– http://jenkins-ci.org/
– Automate all the things
●
Behat
– http://behat.org/
– Cucumber syntax
– Mink extension for website testing
– Write human-readable use cases
84. 08. Behat and Mink
Feature: Test the login page
In order to ensure that customer can use our system
I need to make sure that they can log in successfully
Scenario: Can I log in with valid details
Given I am on the “www.mywebsite.com”
When I click on “Login”
And I fill “username” with “bob”
And I fill “password” with “Password1”
And I press “Login”
Then I should see “Login Successful”
86. 10. Engage
●
Write a useful README.md
– First thing you see on Github
– How to install
– How to use
87. 10. Engage with developers
●
Encourage fork/pull requests
– Make sure they add tests
– Make sure the old tests still pass
– Travis-CI makes this simple
88. 10. Engage with developers
●
Promote your library
– Twitter?
– Google Plus?
– I have no idea. I'm still figuring this out. I'm a
developer dammit!