1<?php
2/**
3 * snap plugin : Affiche un lien sous forme de miniature.
4 *
5 * @license    GPL 2 (http://www.gnu.org/licenses/gpl.html)
6 * @author     Etienne M. <emauvaisfr@yahoo.fr>
7 */
8
9// based on http://wiki.splitbrain.org/plugin:tutorial
10
11// must be run within Dokuwiki
12if (!defined('DOKU_INC')) die();
13
14if (!defined('DOKU_PLUGIN')) define('DOKU_PLUGIN', DOKU_INC . 'lib/plugins/');
15require_once(DOKU_PLUGIN . 'syntax.php');
16
17/**
18 * All DokuWiki plugins to extend the parser/rendering mechanism
19 * need to inherit from this class
20 */
21class syntax_plugin_snap extends DokuWiki_Syntax_Plugin {
22    function getInfo() {
23        return array(
24        'author'  => 'Etienne M.',
25        'email'   => 'emauvaisfr@yahoo.fr',
26        'date'    => @file_get_contents(DOKU_PLUGIN.'snap/VERSION'),
27        'name'    => 'snap Plugin',
28        'desc'    => html_entity_decode($this->getLang('snap_description')),
29        'url'     => 'http://www.dokuwiki.org/plugin:snap'
30        );
31    }
32
33    function connectTo($mode) { $this->Lexer->addEntryPattern('{{\[\[(?=.*?\]\]}})',$mode,'plugin_snap'); }
34    function postConnect() { $this->Lexer->addExitPattern('\]\]}}','plugin_snap'); }
35
36    function getType() { return 'disabled'; }
37
38    function getSort() { return 100; }
39
40   /**
41    * Handle the match
42    */
43    function handle($match, $state, $pos, &$handler){
44        if ($state == DOKU_LEXER_ENTER){
45            $match = trim(substr($match,4,-1)); // strip markup
46            $handler->status['plugin_snap'] = true;
47        }
48        return array($state, $match);
49    }
50
51   /**
52    * Create output
53    */
54    function render($mode, &$renderer, $data) {
55        global $conf;
56
57        list($state, $cdata) = $data;
58
59        //Parametres ///////////////////////////////
60        //Taille de l'ecran du navigateur
61        //Browser screen size
62        $screenx=1280;
63        $screeny=1024;
64
65        //Proportions largeur/hauteur de l'image de la capture
66        //Proportions width/height of the snap
67        $imFactor=4/3;
68
69        //Taille de l'image par defaut
70        //Default image size
71        $defLarg=300;
72        $defHaut=round($defLarg/$imFactor,0);
73
74        //Taille maximale autorisee pour l'image
75        //Max allowed image size
76        $maxLarg=400;
77        $maxHaut=round($maxLarg/$imFactor,0);
78
79        //Serveur de capture (voir le parametrage de server.sh)
80        //Snap server (see server.sh parameters)
81        $snapServer="localhost";
82        $snapPort=8888;
83        $tryTimeout=3;             //Secondes
84
85        //Utiliser le cache ?
86        //Use cache?
87        $checkCache=true;
88        ////////////////////////////////////////////
89
90        $defaultWiki=DOKU_URL."doku.php?id=";
91
92        $chem=realpath($conf['datadir']).'/../snap/';
93        if (!file_exists($chem.".")) mkdir($chem);
94
95        $snapServer="localhost";
96        $snapPort=8888;
97
98        if($mode == 'xhtml') {
99            switch ($state){
100              case DOKU_LEXER_ENTER:
101                break;
102
103              case DOKU_LEXER_UNMATCHED:
104                $param=$cdata;
105
106                //Recuperation des options
107                //(ex : url ou url|larg ou url|xhaut ou url|largxhaut; + un ! pour forcer la capture sans recherche dans le cache)
108                $param=explode("|",$param);
109                if ($param) $url=$param[0];
110                else {
111                  //FIXME !!!
112                  $renderer->doc .= "Erreur de syntaxe";
113                  return false;
114                }
115                if (isset($param[1])) $options=$param[1];
116                $param=$url;
117
118                if (preg_match("/!/",$options)) {
119                  $checkCache=false;
120                  $options=preg_replace("/!/","",$options);
121                }
122
123                if ($options) $options=explode("x",$options);
124                if ($options[0]) $larg=$options[0]*1;
125                if ($options[1]) $haut=$options[1]*1;
126
127                if (!$larg && !$haut) {
128                  $larg=$defLarg;
129                  $haut=$defHaut;
130                }
131                else if (!$larg) $larg=round($haut*$imFactor,0);
132                else if (!$haut) $haut=round($larg/$imFactor,0);
133
134                if ($larg>$maxLarg) $larg=$maxLarg;
135                if ($haut>$maxHaut) $haut=$maxHaut;
136
137                if (!preg_match('/^http:\/\//',$param)) {
138                  $url=$defaultWiki.$param."&u=".urlencode($_SESSION[DOKU_COOKIE]['auth']['user'])."&phash=".urlencode($_SESSION[DOKU_COOKIE]['auth']['pass']);
139
140                  $pagelist = plugin_load('helper', 'pagelist');
141                  if (!$pagelist) {
142                    $titrePage=explode(":",$param);
143                    $titrePage=$titrePage[sizeof($titrePage)-1];
144                    $titrePage=str_replace('_',' ',$titrePage);
145                  }
146                  else {
147                    $pagelist->page['id']=$param;
148                    $pagelist->page['exists'] = 1;
149                    $pagelist->_meta=NULL;
150                    $titrePage = $pagelist->_getMeta('title');
151                    if (!$titrePage) $titrePage = str_replace('_', ' ', noNS($param));
152                    $titrePage = hsc($titrePage);
153                  }
154                  $titrePage=" - $titrePage";
155                }
156                else {
157                  $url=$param;
158                  $titrePage="";
159                }
160
161                if ($url==$param) $image="web_".rawurlencode($param);
162                else $image=$param;
163                $image.="_".$larg."x".$haut.".jpg";
164
165                $imagePath=realpath($conf['datadir']).'/../snap/'.$image;
166
167                if (file_exists($imagePath)) list($imLarg, $imHaut, $imType, $imAttr) = getimagesize($imagePath);
168
169                //Si l'image n'existe pas ou qu'elle est trop vieille ou qu'on demande une taille differente de celle existante, on la capture
170                if (!$checkCache ||
171                    !file_exists($imagePath) ||
172                    ((time()-filemtime($imagePath))>$conf['cachetime']) ||
173                    $imLarg != $larg ||
174                    $imHaut != $haut) {
175                  $try=0;
176                  $fp = fsockopen($snapServer, $snapPort, $errno, $errstr, 30);
177                  while (!$fp && $try<$tryTimeout) {
178                    error_log("$image try #$try");
179                    sleep(1);
180                    $fp = fsockopen($snapServer, $snapPort, $errno, $errstr, 30);
181                    $try++;
182                  }
183                  if (!$fp) {
184                    error_log("$image aborting");
185                    //FIXME !!!
186                    $renderer->doc .= "Serveur snap $snapServer:$snapPort non trouv&eacute; $errstr ($errno)<br />\n";
187                    return;
188                  } else {
189                    error_log("$image launch snap");
190                    fwrite($fp, "$url $imagePath $screenx $screeny 5000 $larg $haut\n");
191                    while (!feof($fp)) fgets($fp, 128);
192                    fclose($fp);
193                  }
194                }
195                else error_log("$image found in cache");
196
197                if (file_exists($imagePath)) {
198                  $titrePage.=" (".strftime($conf['dformat'],filemtime($imagePath)).")";
199                }
200
201                if ($url==$param) $renderer->doc .= "<a href=\"$url\" title=\"$param$titrePage\" target=\"_new\">";
202                else $renderer->doc .= "<a href=\"$defaultWiki$param\" title=\"$param$titrePage\">";
203
204                $renderer->doc .= "<img src=\"".DOKU_URL."lib/plugins/snap/image.php?image=".rawurlencode($imagePath)."\" style=\"border:1px solid #C0C0C0; margin:2px;\" />";
205                $renderer->doc .= "</a>";
206                break;
207
208              case DOKU_LEXER_EXIT:
209                break;
210            }
211            return true;
212        }
213        return false;
214    }
215}
216?>
217