xref: /plugin/ditaa/syntax.php (revision e2392f8a5950c6a56d50bdd16f1b8e84463213a8)
1a34ed36bSDennis Ploeger<?php
2a34ed36bSDennis Ploeger/**
3a34ed36bSDennis Ploeger * Ditaa-Plugin: Converts Ascii-Flowcharts into a png-File
4a34ed36bSDennis Ploeger *
5a34ed36bSDennis Ploeger * @license     GPL 2 (http://www.gnu.org/licenses/gpl.html)
6a34ed36bSDennis Ploeger * @author      Dennis Ploeger <develop [at] dieploegers [dot] de>
7a34ed36bSDennis Ploeger * @author      Christoph Mertins <c [dot] mertins [at] gmail [dot] com>
8c5eb4ae0SGerry Weißbach * @author      Gerry Weißbach / i-net software <tools [at] inetsoftware [dot] de>
9c9ea14c6Seinhirn * @author      Christian Marg <marg@rz.tu-clausthal.de>
10d402f512SAndreas Gohr * @author      Andreas Gohr <andi@splitbrain.org>
11a34ed36bSDennis Ploeger */
12a34ed36bSDennis Ploeger
13a34ed36bSDennis Ploegerif(!defined('DOKU_INC')) define('DOKU_INC', realpath(dirname(__FILE__) . '/../../') . '/');
14a34ed36bSDennis Ploegerif(!defined('DOKU_PLUGIN')) define('DOKU_PLUGIN', DOKU_INC . 'lib/plugins/');
15a34ed36bSDennis Ploegerrequire_once(DOKU_PLUGIN . 'syntax.php');
16a34ed36bSDennis Ploeger
1735cad792SAndreas Gohr/**
1835cad792SAndreas Gohr * Class syntax_plugin_ditaa
1935cad792SAndreas Gohr */
20a34ed36bSDennis Ploegerclass syntax_plugin_ditaa extends DokuWiki_Syntax_Plugin {
21a34ed36bSDennis Ploeger
22a34ed36bSDennis Ploeger    /**
23a34ed36bSDennis Ploeger     * What about paragraphs?
24a34ed36bSDennis Ploeger     */
2535cad792SAndreas Gohr    public function getPType() {
26a34ed36bSDennis Ploeger        return 'normal';
27a34ed36bSDennis Ploeger    }
28a34ed36bSDennis Ploeger
29a34ed36bSDennis Ploeger    /**
30a34ed36bSDennis Ploeger     * What kind of syntax are we?
31a34ed36bSDennis Ploeger     */
3235cad792SAndreas Gohr    public function getType() {
33a34ed36bSDennis Ploeger        return 'substition';
34a34ed36bSDennis Ploeger    }
35a34ed36bSDennis Ploeger
36a34ed36bSDennis Ploeger    /**
37a34ed36bSDennis Ploeger     * Where to sort in?
38a34ed36bSDennis Ploeger     */
3935cad792SAndreas Gohr    public function getSort() {
40a34ed36bSDennis Ploeger        return 200;
41a34ed36bSDennis Ploeger    }
42a34ed36bSDennis Ploeger
43a34ed36bSDennis Ploeger    /**
4472a2bf1dSAndreas Gohr     * Connect pattern to lexer
4535cad792SAndreas Gohr     *
4635cad792SAndreas Gohr     * @param string $mode
47a34ed36bSDennis Ploeger     */
4835cad792SAndreas Gohr    public function connectTo($mode) {
4972a2bf1dSAndreas Gohr        $this->Lexer->addSpecialPattern('<ditaa.*?>\n.*?\n</ditaa>', $mode, 'plugin_ditaa');
50a34ed36bSDennis Ploeger    }
51a34ed36bSDennis Ploeger
52a34ed36bSDennis Ploeger    /**
5335cad792SAndreas Gohr     * Stores all infor about the diagram in two files. One is the actual ditaa data, the other
5435cad792SAndreas Gohr     * contains the options.
5535cad792SAndreas Gohr     *
5635cad792SAndreas Gohr     * @param   string $match The text matched by the patterns
5735cad792SAndreas Gohr     * @param   int $state The lexer state for the match
5835cad792SAndreas Gohr     * @param   int $pos The character position of the matched text
5935cad792SAndreas Gohr     * @param   Doku_Handler $handler The Doku_Handler object
6035cad792SAndreas Gohr     * @return  bool|array Return an array with all data you want to use in render, false don't add an instruction
61a34ed36bSDennis Ploeger     */
6235cad792SAndreas Gohr    public function handle($match, $state, $pos, Doku_Handler $handler) {
632a956e66SAndreas Gohr        $info = $this->getInfo();
642a956e66SAndreas Gohr
6572a2bf1dSAndreas Gohr        // prepare default data
6672a2bf1dSAndreas Gohr        $return = array(
6772a2bf1dSAndreas Gohr            'width' => 0,
6872a2bf1dSAndreas Gohr            'height' => 0,
6972a2bf1dSAndreas Gohr            'antialias' => true,
7072a2bf1dSAndreas Gohr            'edgesep' => true,
7172a2bf1dSAndreas Gohr            'round' => false,
7272a2bf1dSAndreas Gohr            'shadow' => true,
7372a2bf1dSAndreas Gohr            'scale' => 1,
7472a2bf1dSAndreas Gohr            'align' => '',
75*e2392f8aSAndreas Gohr            'version' => $info['date'],
76*e2392f8aSAndreas Gohr            'now' => time()
7772a2bf1dSAndreas Gohr        );
78a34ed36bSDennis Ploeger
7972a2bf1dSAndreas Gohr        // prepare input
8072a2bf1dSAndreas Gohr        $lines = explode("\n", $match);
8172a2bf1dSAndreas Gohr        $conf = array_shift($lines);
8272a2bf1dSAndreas Gohr        array_pop($lines);
8372a2bf1dSAndreas Gohr
8472a2bf1dSAndreas Gohr        // match config options
8572a2bf1dSAndreas Gohr        if(preg_match('/\b(left|center|right)\b/i', $conf, $match)) $return['align'] = $match[1];
8672a2bf1dSAndreas Gohr        if(preg_match('/\b(\d+)x(\d+)\b/', $conf, $match)) {
8772a2bf1dSAndreas Gohr            $return['width'] = $match[1];
8872a2bf1dSAndreas Gohr            $return['height'] = $match[2];
89a34ed36bSDennis Ploeger        }
902a956e66SAndreas Gohr        if(preg_match('/\b(\d+(\.\d+)?)X\b/', $conf, $match)) $return['scale'] = $match[1];
9172a2bf1dSAndreas Gohr        if(preg_match('/\bwidth=([0-9]+)\b/i', $conf, $match)) $return['width'] = $match[1];
9272a2bf1dSAndreas Gohr        if(preg_match('/\bheight=([0-9]+)\b/i', $conf, $match)) $return['height'] = $match[1];
9372a2bf1dSAndreas Gohr        // match boolean toggles
9472a2bf1dSAndreas Gohr        if(preg_match_all('/\b(no)?(antialias|edgesep|round|shadow)\b/i', $conf, $matches, PREG_SET_ORDER)) {
9572a2bf1dSAndreas Gohr            foreach($matches as $match) {
9672a2bf1dSAndreas Gohr                $return[$match[2]] = !$match[1];
9772a2bf1dSAndreas Gohr            }
9872a2bf1dSAndreas Gohr        }
9972a2bf1dSAndreas Gohr
10005cbae88SAndreas Gohr        $input = join("\n", $lines);
101*e2392f8aSAndreas Gohr        $return['md5'] = md5($input.$this->_prepareData($return)); // we only pass a hash around
10205cbae88SAndreas Gohr
10335cad792SAndreas Gohr        // store input for later use in _imagefile()
10435cad792SAndreas Gohr        io_saveFile(getCacheName($return['md5'], '.ditaa.txt'), $input);
10535cad792SAndreas Gohr        io_saveFile(getCacheName($return['md5'], '.ditaa.cfg'), serialize($return));
10672a2bf1dSAndreas Gohr
10772a2bf1dSAndreas Gohr        return $return;
108a34ed36bSDennis Ploeger    }
109a34ed36bSDennis Ploeger
110a34ed36bSDennis Ploeger    /**
11135cad792SAndreas Gohr     * Output the image
11235cad792SAndreas Gohr     *
11335cad792SAndreas Gohr     * @param string $format output format being rendered
11435cad792SAndreas Gohr     * @param Doku_Renderer $R the current renderer object
11535cad792SAndreas Gohr     * @param array $data data created by handler()
11635cad792SAndreas Gohr     * @return  boolean                 rendered correctly?
117c5eb4ae0SGerry Weißbach     */
11835cad792SAndreas Gohr    public function render($format, Doku_Renderer $R, $data) {
11938c92790SGerry Weißbach        global $ID;
12095615d6cSAndreas Gohr        if($format == 'xhtml') {
12138c92790SGerry Weißbach            // Only use the md5 key
122*e2392f8aSAndreas Gohr            $img = ml($ID, array('ditaa' => $data['md5'], 't' => $data['now']));
12395615d6cSAndreas Gohr            $R->doc .= '<img src="' . $img . '" class="media' . $data['align'] . '" alt=""';
12495615d6cSAndreas Gohr            if($data['width']) $R->doc .= ' width="' . $data['width'] . '"';
12595615d6cSAndreas Gohr            if($data['height']) $R->doc .= ' height="' . $data['height'] . '"';
126c77baa73SWilli Schönborn            if($data['align'] == 'right') $R->doc .= ' align="right"';
127c77baa73SWilli Schönborn            if($data['align'] == 'left') $R->doc .= ' align="left"';
12895615d6cSAndreas Gohr            $R->doc .= '/>';
12995615d6cSAndreas Gohr            return true;
13095615d6cSAndreas Gohr        } else if($format == 'odt') {
13135cad792SAndreas Gohr            $src = $this->_imgfile($data['md5']);
13235cad792SAndreas Gohr            /** @var  renderer_plugin_odt $R */
13395615d6cSAndreas Gohr            $R->_odtAddImage($src, $data['width'], $data['height'], $data['align']);
13495615d6cSAndreas Gohr            return true;
13595615d6cSAndreas Gohr        }
13695615d6cSAndreas Gohr        return false;
13795615d6cSAndreas Gohr    }
13895615d6cSAndreas Gohr
13995615d6cSAndreas Gohr    /**
140*e2392f8aSAndreas Gohr     * Prepares the Data that is used for the cache name
141*e2392f8aSAndreas Gohr     * Width, height and scale are left out.
142*e2392f8aSAndreas Gohr     * Ensures sanity.
143*e2392f8aSAndreas Gohr     */
144*e2392f8aSAndreas Gohr    protected function _prepareData($input) {
145*e2392f8aSAndreas Gohr        $output = array();
146*e2392f8aSAndreas Gohr        foreach($input as $key => $value) {
147*e2392f8aSAndreas Gohr            switch($key) {
148*e2392f8aSAndreas Gohr                case 'scale':
149*e2392f8aSAndreas Gohr                case 'antialias':
150*e2392f8aSAndreas Gohr                case 'edgesep':
151*e2392f8aSAndreas Gohr                case 'round':
152*e2392f8aSAndreas Gohr                case 'shadow':
153*e2392f8aSAndreas Gohr                case 'version':
154*e2392f8aSAndreas Gohr                    $output[$key] = $value;
155*e2392f8aSAndreas Gohr            };
156*e2392f8aSAndreas Gohr        }
157*e2392f8aSAndreas Gohr        ksort($output);
158*e2392f8aSAndreas Gohr        return $output;
159*e2392f8aSAndreas Gohr    }
160*e2392f8aSAndreas Gohr
161*e2392f8aSAndreas Gohr    /**
16295615d6cSAndreas Gohr     * Return path to the rendered image on our local system
16335cad792SAndreas Gohr     *
16435cad792SAndreas Gohr     * @param string $md5 MD5 of the input data, used to identify the cache files
16535cad792SAndreas Gohr     * @return false|string path to file or fals on error
16695615d6cSAndreas Gohr     */
16735cad792SAndreas Gohr    public function _imgfile($md5) {
16835cad792SAndreas Gohr        $file_cfg = getCacheName($md5, '.ditaa.cfg'); // configs
16935cad792SAndreas Gohr        $file_txt = getCacheName($md5, '.ditaa.txt'); // input
17035cad792SAndreas Gohr        $file_png = getCacheName($md5, '.ditaa.png'); // ouput
17138c92790SGerry Weißbach
17235cad792SAndreas Gohr        if(!file_exists($file_cfg) || !file_exists($file_txt)) {
17335cad792SAndreas Gohr            return false;
17438c92790SGerry Weißbach        }
17535cad792SAndreas Gohr        $data = unserialize(io_readFile($file_cfg, false));
17635cad792SAndreas Gohr
17735cad792SAndreas Gohr        // file does not exist or is outdated
17835cad792SAndreas Gohr        if(@filemtime($file_png) < filemtime($file_cfg)) {
17938c92790SGerry Weißbach
18095615d6cSAndreas Gohr            if($this->getConf('java')) {
18135cad792SAndreas Gohr                $ok = $this->_runJava($data, $file_txt, $file_png);
18295615d6cSAndreas Gohr            } else {
18335cad792SAndreas Gohr                $ok = $this->_runGo($data, $file_txt, $file_png);
184967610bbSAndreas Gohr                #$ok = $this->_remote($data, $in, $cache);
18595615d6cSAndreas Gohr            }
18695615d6cSAndreas Gohr            if(!$ok) return false;
18735cad792SAndreas Gohr
18835cad792SAndreas Gohr            clearstatcache($file_png);
18995615d6cSAndreas Gohr        }
19095615d6cSAndreas Gohr
19195615d6cSAndreas Gohr        // resized version
19295615d6cSAndreas Gohr        if($data['width']) {
19335cad792SAndreas Gohr            $file_png = media_resize_image($file_png, 'png', $data['width'], $data['height']);
19495615d6cSAndreas Gohr        }
19595615d6cSAndreas Gohr
19695615d6cSAndreas Gohr        // something went wrong, we're missing the file
19735cad792SAndreas Gohr        if(!file_exists($file_png)) return false;
19895615d6cSAndreas Gohr
19935cad792SAndreas Gohr        return $file_png;
20095615d6cSAndreas Gohr    }
20195615d6cSAndreas Gohr
20295615d6cSAndreas Gohr    /**
20305cbae88SAndreas Gohr     * Render the output remotely at ditaa.org
20435cad792SAndreas Gohr     *
20535cad792SAndreas Gohr     * @deprecated ditaa.org is no longer available, so this defunct
20635cad792SAndreas Gohr     * @param array $data The config settings
20735cad792SAndreas Gohr     * @param string $in Path to the ditaa input file (txt)
20835cad792SAndreas Gohr     * @param string $out Path to the output file (PNG)
20935cad792SAndreas Gohr     * @return bool true if the image was created, false otherwise
21005cbae88SAndreas Gohr     */
21135cad792SAndreas Gohr    protected function _remote($data, $in, $out) {
212967610bbSAndreas Gohr        global $conf;
213967610bbSAndreas Gohr
21495615d6cSAndreas Gohr        if(!file_exists($in)) {
21595615d6cSAndreas Gohr            if($conf['debug']) {
21695615d6cSAndreas Gohr                dbglog($in, 'no such ditaa input file');
21795615d6cSAndreas Gohr            }
21895615d6cSAndreas Gohr            return false;
21995615d6cSAndreas Gohr        }
22095615d6cSAndreas Gohr
22105cbae88SAndreas Gohr        $http = new DokuHTTPClient();
22205cbae88SAndreas Gohr        $http->timeout = 30;
22305cbae88SAndreas Gohr
22405cbae88SAndreas Gohr        $pass = array();
22505cbae88SAndreas Gohr        $pass['scale'] = $data['scale'];
22605cbae88SAndreas Gohr        $pass['timeout'] = 25;
22705cbae88SAndreas Gohr        $pass['grid'] = io_readFile($in);
22805cbae88SAndreas Gohr        if(!$data['antialias']) $pass['A'] = 'on';
22905cbae88SAndreas Gohr        if(!$data['shadow']) $pass['S'] = 'on';
23005cbae88SAndreas Gohr        if($data['round']) $pass['r'] = 'on';
23105cbae88SAndreas Gohr        if(!$data['edgesep']) $pass['E'] = 'on';
23205cbae88SAndreas Gohr
23305cbae88SAndreas Gohr        $img = $http->post('http://ditaa.org/ditaa/render', $pass);
23405cbae88SAndreas Gohr        if(!$img) return false;
23505cbae88SAndreas Gohr
23695615d6cSAndreas Gohr        return io_saveFile($out, $img);
23705cbae88SAndreas Gohr    }
23805cbae88SAndreas Gohr
239a34ed36bSDennis Ploeger    /**
2402a956e66SAndreas Gohr     * Run the ditaa Java program
24135cad792SAndreas Gohr     *
24235cad792SAndreas Gohr     * @param array $data The config settings
24335cad792SAndreas Gohr     * @param string $in Path to the ditaa input file (txt)
24435cad792SAndreas Gohr     * @param string $out Path to the output file (PNG)
24535cad792SAndreas Gohr     * @return bool true if the image was created, false otherwise
246a34ed36bSDennis Ploeger     */
24735cad792SAndreas Gohr    protected function _runJava($data, $in, $out) {
2482a956e66SAndreas Gohr        global $conf;
249a34ed36bSDennis Ploeger
25005cbae88SAndreas Gohr        if(!file_exists($in)) {
25105cbae88SAndreas Gohr            if($conf['debug']) {
25205cbae88SAndreas Gohr                dbglog($in, 'no such ditaa input file');
25305cbae88SAndreas Gohr            }
25405cbae88SAndreas Gohr            return false;
25505cbae88SAndreas Gohr        }
256a34ed36bSDennis Ploeger
2572a956e66SAndreas Gohr        $cmd = $this->getConf('java');
25836721e14SAndreas Gohr        $cmd .= ' -Djava.awt.headless=true -Dfile.encoding=UTF-8 -jar';
259c65b5f53SAndreas Gohr        $cmd .= ' ' . escapeshellarg(__DIR__ . '/ditaa/ditaa.jar');
26036721e14SAndreas Gohr        $cmd .= ' --encoding UTF-8';
26105cbae88SAndreas Gohr        $cmd .= ' ' . escapeshellarg($in); //input
26205cbae88SAndreas Gohr        $cmd .= ' ' . escapeshellarg($out); //output
2632a956e66SAndreas Gohr        $cmd .= ' -s ' . escapeshellarg($data['scale']);
2642a956e66SAndreas Gohr        if(!$data['antialias']) $cmd .= ' -A';
2652a956e66SAndreas Gohr        if(!$data['shadow']) $cmd .= ' -S';
2662a956e66SAndreas Gohr        if($data['round']) $cmd .= ' -r';
2672a956e66SAndreas Gohr        if(!$data['edgesep']) $cmd .= ' -E';
268a34ed36bSDennis Ploeger
269a34ed36bSDennis Ploeger        exec($cmd, $output, $error);
270a34ed36bSDennis Ploeger
2713c74ed32SAndreas Gohr        if($error != 0) {
2723c74ed32SAndreas Gohr            if($conf['debug']) {
2733c74ed32SAndreas Gohr                dbglog(join("\n", $output), 'ditaa command failed: ' . $cmd);
2743c74ed32SAndreas Gohr            }
2753c74ed32SAndreas Gohr            return false;
2763c74ed32SAndreas Gohr        }
27705cbae88SAndreas Gohr
278a34ed36bSDennis Ploeger        return true;
279a34ed36bSDennis Ploeger    }
280a34ed36bSDennis Ploeger
281967610bbSAndreas Gohr    /**
282967610bbSAndreas Gohr     * Run the ditaa Go program
28335cad792SAndreas Gohr     *
28435cad792SAndreas Gohr     * @param array $data The config settings - currently not used because the Go relase supports no options
28535cad792SAndreas Gohr     * @param string $in Path to the ditaa input file (txt)
28635cad792SAndreas Gohr     * @param string $out Path to the output file (PNG)
28735cad792SAndreas Gohr     * @return bool true if the image was created, false otherwise
288967610bbSAndreas Gohr     */
28935cad792SAndreas Gohr    protected function _runGo($data, $in, $out) {
290967610bbSAndreas Gohr        global $conf;
291967610bbSAndreas Gohr
292967610bbSAndreas Gohr        if(!file_exists($in)) {
293967610bbSAndreas Gohr            if($conf['debug']) {
294967610bbSAndreas Gohr                dbglog($in, 'no such ditaa input file');
295967610bbSAndreas Gohr            }
296967610bbSAndreas Gohr            return false;
297967610bbSAndreas Gohr        }
298967610bbSAndreas Gohr
299967610bbSAndreas Gohr        $cmd = $this->getLocalBinary();
300967610bbSAndreas Gohr        if(!$cmd) return false;
301967610bbSAndreas Gohr        $cmd .= ' ' . escapeshellarg($in); //input
302967610bbSAndreas Gohr        $cmd .= ' ' . escapeshellarg($out); //output
303967610bbSAndreas Gohr
304967610bbSAndreas Gohr        exec($cmd, $output, $error);
305967610bbSAndreas Gohr
306967610bbSAndreas Gohr        if($error != 0) {
307967610bbSAndreas Gohr            if($conf['debug']) {
308967610bbSAndreas Gohr                dbglog(join("\n", $output), 'ditaa command failed: ' . $cmd);
309967610bbSAndreas Gohr            }
310967610bbSAndreas Gohr            return false;
311967610bbSAndreas Gohr        }
312967610bbSAndreas Gohr
313967610bbSAndreas Gohr        return true;
314967610bbSAndreas Gohr    }
315967610bbSAndreas Gohr
316967610bbSAndreas Gohr    /**
317967610bbSAndreas Gohr     * Detects the platform of the PHP host and constructs the appropriate binary name
318967610bbSAndreas Gohr     *
319967610bbSAndreas Gohr     * @return false|string
320967610bbSAndreas Gohr     */
321967610bbSAndreas Gohr    protected function getBinaryName() {
322967610bbSAndreas Gohr        $ext = '';
323967610bbSAndreas Gohr
324967610bbSAndreas Gohr        $os = php_uname('s');
325967610bbSAndreas Gohr        if(preg_match('/darwin/i', $os)) {
326967610bbSAndreas Gohr            $os = 'darwin';
327967610bbSAndreas Gohr        } elseif(preg_match('/win/i', $os)) {
328967610bbSAndreas Gohr            $os = 'windows';
329967610bbSAndreas Gohr            $ext = '.exe';
330967610bbSAndreas Gohr        } elseif(preg_match('/linux/i', $os)) {
331967610bbSAndreas Gohr            $os = 'linux';
332967610bbSAndreas Gohr        } elseif(preg_match('/freebsd/i', $os)) {
333967610bbSAndreas Gohr            $os = 'freebsd';
334967610bbSAndreas Gohr        } elseif(preg_match('/openbsd/i', $os)) {
335967610bbSAndreas Gohr            $os = 'openbsd';
336967610bbSAndreas Gohr        } elseif(preg_match('/netbsd/i', $os)) {
337967610bbSAndreas Gohr            $os = 'netbsd';
338967610bbSAndreas Gohr        } elseif(preg_match('/(solaris|netbsd)/i', $os)) {
339967610bbSAndreas Gohr            $os = 'freebsd';
340967610bbSAndreas Gohr        } else {
341967610bbSAndreas Gohr            return false;
342967610bbSAndreas Gohr        }
343967610bbSAndreas Gohr
344967610bbSAndreas Gohr        $arch = php_uname('m');
345967610bbSAndreas Gohr        if($arch == 'x86_64') {
346967610bbSAndreas Gohr            $arch = 'amd64';
347967610bbSAndreas Gohr        } elseif(preg_match('/arm/i', $arch)) {
348967610bbSAndreas Gohr            $arch = 'amd';
349967610bbSAndreas Gohr        } else {
350967610bbSAndreas Gohr            $arch = '386';
351967610bbSAndreas Gohr        }
352967610bbSAndreas Gohr
353967610bbSAndreas Gohr        return "ditaa-$os-$arch$ext";
354967610bbSAndreas Gohr    }
355967610bbSAndreas Gohr
356967610bbSAndreas Gohr    /**
357967610bbSAndreas Gohr     * Returns the local binary to use
358967610bbSAndreas Gohr     *
35935cad792SAndreas Gohr     * Downloads it if necessary
36035cad792SAndreas Gohr     *
361967610bbSAndreas Gohr     * @return bool|string
362967610bbSAndreas Gohr     */
363967610bbSAndreas Gohr    protected function getLocalBinary() {
364967610bbSAndreas Gohr        global $conf;
365967610bbSAndreas Gohr
366967610bbSAndreas Gohr        $bin = $this->getBinaryName();
367967610bbSAndreas Gohr        if(!$bin) return false;
368967610bbSAndreas Gohr
369967610bbSAndreas Gohr        // check distributed files first
370967610bbSAndreas Gohr        if(file_exists(__DIR__ . '/ditaa/' . $bin)) {
371967610bbSAndreas Gohr            return __DIR__ . '/ditaa/' . $bin;
372967610bbSAndreas Gohr        }
373967610bbSAndreas Gohr
374967610bbSAndreas Gohr        $info = $this->getInfo();
375967610bbSAndreas Gohr        $cache = getCacheName($info['date'], ".$bin");
376967610bbSAndreas Gohr
377967610bbSAndreas Gohr        if(file_exists($cache)) return $cache;
378967610bbSAndreas Gohr
379400b2bf3SAndreas Gohr        $url = 'https://github.com/akavel/ditaa/releases/download/g1.0.0/' . $bin;
380967610bbSAndreas Gohr        if(io_download($url, $cache, false, '', 0)) {
381967610bbSAndreas Gohr            @chmod($cache, $conf['dmode']);
382967610bbSAndreas Gohr            return $cache;
383967610bbSAndreas Gohr        }
384967610bbSAndreas Gohr
385967610bbSAndreas Gohr        return false;
386967610bbSAndreas Gohr    }
387a34ed36bSDennis Ploeger}
388a34ed36bSDennis Ploeger
389