From 62875bdbecc633496c712bc2fc5e0ef8f54733e3 Mon Sep 17 00:00:00 2001 From: Christian Weiske Date: Sun, 30 Mar 2014 14:01:34 +0200 Subject: [PATCH] first work on option parsing --- README.rst | 84 ++++++++++++++++++ src/phancap/Autoloader.php | 57 +++++++++++++ src/phancap/Options.php | 171 +++++++++++++++++++++++++++++++++++++ www/get.php | 24 ++++++ www/index.php | 4 + 5 files changed, 340 insertions(+) create mode 100644 README.rst create mode 100644 src/phancap/Autoloader.php create mode 100644 src/phancap/Options.php create mode 100644 www/get.php create mode 100644 www/index.php diff --git a/README.rst b/README.rst new file mode 100644 index 0000000..606ed74 --- /dev/null +++ b/README.rst @@ -0,0 +1,84 @@ +************************************ +phancap - website screenshot service +************************************ + +Software to create screenshots and thumbnails of websites via an API. + +Self-hosted and written in PHP. Caching included. + + +======================= +Technical brainstorming +======================= + +Tools to make website screenshots +================================= +- `cutycapt `_ +- `khtml2png `_ (outdated) +- `phantomjs `_ +- `python-webkit2png `_ +- `wkhtmltopdf `_ +- wkhtmltoimage + + +Possible parameters +=================== + +Page request parameters +----------------------- +- url +- bwidth (browser width / resolution) +- bheight (browser height / resolution) +- delay (capture X seconds after page loaded) +- useragent (user agent header string) +- accepted languages (Accept-Language header) +- cookie (set cookie data) +- referer (custom referer header) +- post data (send POST data as if filled out a form) + +Screenshot configuration +------------------------ +- width (of thumbnail) +- height (of thumbnail) +- output format (jpg, png, pdf) +- mode: screen or page (full page height or screen size only) + - page aka fullpage +- quality (jpeg image quality) + +Misc +---- +- callback URL (to notify when screenshot is ready) +- sync/async (wait for response or just get a 202 accepted) +- cache (to force a fresh screenshot with cache=0, + otherwise seconds the cache may be old) +- api key +- token (md5 hash of query string) + +API parameter sources +--------------------- +- http://api1.thumbalizr.com/ +- http://url2png.com/docs/ +- http://webthumb.bluga.net/apidoc +- http://www.page2images.com/Create-website-screenshot-online-API +- http://browshot.com/api/documentation + + +Other website screenshot services +================================= +- http://browsershots.org/ +- http://browshot.com/ +- http://ctrlq.org/screenshots/ +- http://grabz.it/ +- http://url2png.com/ +- http://usersnap.com/ +- http://websnapr.com/ +- http://webthumb.bluga.net/ +- http://www.page2images.com/ +- http://www.shrinktheweb.com/ +- http://www.thumbalizr.com/ +- http://www.url2picture.com/ + + +Other website screenshot software +================================= +- https://github.com/microweber/screen diff --git a/src/phancap/Autoloader.php b/src/phancap/Autoloader.php new file mode 100644 index 0000000..fed2928 --- /dev/null +++ b/src/phancap/Autoloader.php @@ -0,0 +1,57 @@ + + * @copyright 2014 Christian Weiske + * @license http://www.gnu.org/licenses/agpl.html GNU AGPL v3 + * @link http://cweiske.de/phancap.htm + */ +namespace phancap; + +/** + * Class autoloader, PSR-0 compliant. + * + * @category Tools + * @package Phancap + * @author Christian Weiske + * @copyright 2014 Christian Weiske + * @license http://www.gnu.org/licenses/agpl.html GNU AGPL v3 + * @version Release: @package_version@ + * @link http://cweiske.de/phancap.htm + */ +class Autoloader +{ + /** + * Load the given class + * + * @param string $class Class name + * + * @return void + */ + public function load($class) + { + $file = strtr($class, '_\\', '//') . '.php'; + if (stream_resolve_include_path($file)) { + include $file; + } + } + + /** + * Register this autoloader + * + * @return void + */ + public static function register() + { + set_include_path( + get_include_path() . PATH_SEPARATOR . __DIR__ . '/../' + ); + spl_autoload_register(array(new self(), 'load')); + } +} +?> diff --git a/src/phancap/Options.php b/src/phancap/Options.php new file mode 100644 index 0000000..b5c96d9 --- /dev/null +++ b/src/phancap/Options.php @@ -0,0 +1,171 @@ + array( + 'title' => 'Website URL', + 'default' => null, + 'type' => 'url', + ), + 'bwidth' => array( + 'title' => 'Browser width', + 'default' => 1024, + 'type' => 'int', + 'min' => 16, + 'max' => 2048, + ), + 'bheight' => array( + 'title' => 'Browser height', + 'default' => null, + 'type' => 'int', + 'min' => 16, + 'max' => 8192, + ), + /** + * Screenshot settings + */ + 'swidth' => array( + 'title' => 'Screenshot width', + 'default' => 300, + 'type' => 'int', + 'min' => 16, + 'max' => 8192, + ), + 'sheight' => array( + 'title' => 'Screenshot height', + 'default' => null, + 'type' => 'int', + 'min' => 16, + 'max' => 8192, + ), + 'sformat' => array( + 'title' => 'Screenshot format', + 'default' => 'png', + 'type' => array('png', 'jpg', 'pdf'), + ), + 'smode' => array( + 'title' => 'Screenshot mode', + 'default' => 'screen', + 'type' => array('screen', 'page'), + ), + ); + + public $values = array(); + + + /** + * Parses an array of options, validates them and writes them into + * $this->values. + * + * @param array $arValues Array of options, e.g. $_GET + */ + public function parse($arValues) + { + foreach (static::$options as $name => $arOption) { + $this->values[$name] = $arOption['default']; + if (!isset($arValues[$name])) { + continue; + } + if ($arOption['type'] == 'url') { + $this->values[$name] = $this->validateUrl($arValues[$name]); + } else if ($arOption['type'] == 'int') { + $this->values[$name] = $this->validateInt( + $arValues[$name], $arOption['min'], $arOption['max'] + ); + } else if (gettype($arOption['type']) == 'array') { + $this->values[$name] = $this->validateArray( + $arValues[$name], $arOption['type'] + ); + } else { + throw new \InvalidArgumentException( + 'Unsupported option type: ' . $arOption['type'] + ); + } + unset($arValues[$name]); + } + + if (count($arValues) > 0) { + throw new \InvalidArgumentException( + 'Unsupported parameter: ' . implode(', ', array_keys($arValues)) + ); + } + + $this->calcPageSize(); + } + + protected function calcPageSize() + { + if ($this->values['smode'] == 'page') { + return; + } + + if ($this->values['sheight'] !== null) { + $this->values['bheight'] = intval( + $this->values['bwidth'] / $this->values['swidth'] + * $this->values['sheight'] + ); + } else if ($this->values['bheight'] !== null) { + $this->values['sheight'] = intval( + $this->values['swidth'] / $this->values['bwidth'] + * $this->values['bheight'] + ); + } else { + //no height set. use 4:3 + $this->values['sheight'] = $this->values['swidth'] / 4 * 3; + $this->values['bheight'] = $this->values['bwidth'] / 4 * 3; + } + } + + protected function validateArray($value, $options) + { + if (array_search($value, $options) === false) { + throw new \InvalidArgumentException( + 'Invalid value ' . $value . '.' + . ' Allowed: ' . implode(', ', $options) + ); + } + return $value; + } + + protected function validateInt($value, $min, $max) + { + if (!is_numeric($value)) { + throw new \InvalidArgumentException( + 'Value must be a number' + ); + } + $value = (int) $value; + if ($value < $min) { + throw new \InvalidArgumentException( + 'Value must be at least ' . $min + ); + } + if ($value > $max) { + throw new \InvalidArgumentException( + 'Value may be up to ' . $min + ); + } + return $value; + } + + protected function validateUrl($url) + { + $parts = parse_url($url); + if ($parts === false) { + throw new \InvalidArgumentException('Invalid URL'); + } + if (!isset($parts['scheme'])) { + throw new \InvalidArgumentException('URL scheme missing'); + } + if (!isset($parts['host'])) { + throw new \InvalidArgumentException('URL host missing'); + } + return $url; + } +} +?> diff --git a/www/get.php b/www/get.php new file mode 100644 index 0000000..5212e99 --- /dev/null +++ b/www/get.php @@ -0,0 +1,24 @@ +parse($_GET); +} catch (\InvalidArgumentException $e) { + header('HTTP/1.0 400 Bad Request'); + header('Content-type: text/plain'); + echo $e->getMessage(); + exit(1); +} + +var_dump($options->values); +?> diff --git a/www/index.php b/www/index.php new file mode 100644 index 0000000..6eff33c --- /dev/null +++ b/www/index.php @@ -0,0 +1,4 @@ + -- 2.30.2