8 * @package Adapter_Cutycapt
9 * @author Christian Weiske <cweiske@cweiske.de>
10 * @copyright 2014 Christian Weiske
11 * @license http://www.gnu.org/licenses/agpl.html GNU AGPL v3
12 * @link http://cweiske.de/phancap.htm
17 * Screenshot rendering using the "cutycapt" command line tool.
20 * @package Adapter_Cutycapt
21 * @author Christian Weiske <cweiske@cweiske.de>
22 * @copyright 2014 Christian Weiske
23 * @license http://www.gnu.org/licenses/agpl.html GNU AGPL v3
24 * @version Release: @package_version@
25 * @link http://cweiske.de/phancap.htm
27 class Adapter_Cutycapt
39 protected $lockFile = null;
42 * Check if all dependencies are available.
44 * @return mixed TRUE if all is fine, array with error messages otherwise
46 public function isAvailable()
48 $old = error_reporting(error_reporting() & ~E_STRICT);
50 if (\System::which('xvfb-run') === false) {
51 $arErrors[] = '"xvfb-run" is not installed';
53 if (\System::which('cutycapt') === false) {
54 $arErrors[] = '"cutycapt" is not installed';
56 if (\System::which('convert') === false) {
57 $arErrors[] = '"convert" (imagemagick) is not installed';
59 if (\System::which('timeout') === false) {
60 $arErrors[] = '"timeout" (GNU coreutils) is not installed';
63 error_reporting($old);
64 if (count($arErrors)) {
72 * Render a website screenshot
74 * @param Image $img Image configuration
75 * @param Options $options Screenshot configuration
78 * @throws \Exception When something fails
80 public function render(Image $img, Options $options)
82 $format = $options->values['sformat'];
83 if ($format == 'jpg') {
86 $maxWaitTime = 30;//seconds
88 $serverNumber = $this->getServerNumber($options);
89 $tmpPath = $img->getPath() . '-tmp';
91 . ' --url=' . escapeshellarg($options->values['url'])
92 . ' --out-format=' . escapeshellarg($format)
93 . ' --out=' . escapeshellarg($tmpPath)
94 . ' --max-wait=' . (($maxWaitTime - 1) * 1000)
95 . ' --min-width=' . $options->values['bwidth'];
96 if ($options->values['bheight'] !== null) {
97 $cmd .= ' --min-height=' . $options->values['bheight'];
100 $xvfbcmd = 'xvfb-run'
102 . ' --server-args="-screen 0, 1024x768x24"'
103 . ' --server-num=' . $serverNumber;
104 //cutycapt hangs sometimes - https://sourceforge.net/p/cutycapt/bugs/8/
105 // we kill it if it does not exit itself
106 Executor::runForSomeTime($xvfbcmd . ' ' . $cmd, $maxWaitTime);
108 $this->resize($tmpPath, $img, $options);
112 * Get a free X server number.
114 * Each xvfb-run process needs its own free server number.
115 * Needed for multiple parallel requests.
117 * @return integer Server number
119 protected function getServerNumber()
121 //clean stale lock files
128 $f = $this->config->cacheDir . 'tmp-curlycapt-server-' . $num . '.lock';
129 $this->lockHdl = fopen($f, 'w');
130 if (flock($this->lockHdl, LOCK_EX | LOCK_NB)) {
131 $this->lockFile = $f;
135 fclose($this->lockHdl);
137 } while ($num < 200);
140 throw new \Exception('Too many requests running');
143 $this->lockFile = $f;
148 * Unlock lock file and clean up old lock files
152 public function cleanup()
154 if ($this->lockFile !== null && $this->lockHdl) {
155 flock($this->lockHdl, LOCK_UN);
156 unlink($this->lockFile);
160 $this->config->cacheDir . 'tmp-curlycapt-server-*.lock'
164 foreach ($lockFiles as $file) {
165 if ($now - filemtime($file) > 120) {
166 //delete stale lock file; probably something crashed.
173 * Convert an image to the given size.
175 * Target file is the path of $img.
177 * @param string $tmpPath Path of image to be scaled.
178 * @param Image $img Image configuration
179 * @param Options $options Screenshot configuration
183 protected function resize($tmpPath, Image $img, Options $options)
185 if ($options->values['sformat'] == 'pdf') {
187 rename($tmpPath, $img->getPath());
192 if ($options->values['smode'] == 'screen') {
193 $crop = ' -crop ' . $options->values['swidth']
194 . 'x' . $options->values['sheight']
198 $convertcmd = 'convert'
199 . ' ' . escapeshellarg($tmpPath)
200 . ' -resize ' . $options->values['swidth']
202 . ' ' . escapeshellarg($img->getPath());
203 Executor::run($convertcmd);
204 //var_dump($convertcmd);die();
209 * Set phancap configuration
211 * @param Config $config Phancap configuration
215 public function setConfig(Config $config)
217 $this->config = $config;