<?php
/**
 * snap helper : Affiche un lien sous forme de miniature.
 *
 * @license    GPL 2 (http://www.gnu.org/licenses/gpl.html)
 * @author     Etienne M. <emauvaisfr@yahoo.fr>
 */

// based on http://wiki.splitbrain.org/plugin:tutorial

// must be run within Dokuwiki
if (!defined('DOKU_INC')) die();

if (!defined('DOKU_PLUGIN')) define('DOKU_PLUGIN', DOKU_INC . 'lib/plugins/');
require_once(DOKU_PLUGIN . 'syntax.php');

/**
 * All DokuWiki plugins to extend the parser/rendering mechanism
 * need to inherit from this class
 */
class helper_plugin_snap extends DokuWiki_Syntax_Plugin {

        //Parametres ///////////////////////////////
        //Chemin vers votre Dokuwiki (voir le constructeur ci-dessous)
        //Path to your Dokuwiki (see constructor below)
        var $defaultWiki=false;

        //Taille de l'ecran du navigateur
        //Browser screen size
        var $screenx=1280;
        var $screeny=1024;

        //Proportions largeur/hauteur de l'image de la capture
        //Proportions width/height of the snap
        var $imFactor=1.333333333333333333333; //4/3

        //Taille de l'image par defaut
        //Default image size
        var $defLarg=200;
        var $defHaut=150;

        //Taille maximale autorisee pour l'image
        //Max allowed image size
        var $maxLarg=400;
        var $maxHaut=300;

        //Serveur de capture (voir le parametrage de server.sh)
        //Snap server (see server.sh parameters)
        var $snapServer="localhost";
        var $snapPorts="8888 8889 8890 8891 8892";
        var $snapTimeout=5;            //Secondes
        var $tryTimeout=3;             //Secondes

        //Utiliser le cache ?
        //Use cache?
        var $checkCache=true;

        //Autres variables
        var $outputPath=false;
        var $imagePath=false;
        var $titrePage=false;
        var $snapTime=false;
        var $snapTimeFormatted=false;
        var $fromCache=false;
        var $succeed=false;
        var $target=false;
        var $selectedPort=false;
        var $snapLog=false;
        var $timeout=false;
        var $snapDuration=false;
        var $snapTotalDuration=false;
        var $tries=false;
        var $url=false;
        var $width=false;
        var $height=false;
        ////////////////////////////////////////////


    function getInfo() {
        return array(
        'author'  => 'Etienne M.',
        'email'   => 'emauvaisfr@yahoo.fr',
        'date'    => @file_get_contents(DOKU_PLUGIN.'snap/VERSION'),
        'name'    => 'snap Helper',
        'desc'    => html_entity_decode($this->getLang('snap_description')),
        'url'     => 'http://www.dokuwiki.org/plugin:snap'
        );
    }


    function getMethods(){
      $result = array();
      $result[] = array(
        'name'   => 'getSnap',
        'desc'   => $this->lang('snap_getSnap'),
        'params' => array(
          'url to snap (page id or full url starting with http://)' => 'string',
          'width' => 'integer',
          'height' => 'integer',
          'checkCache' => 'boolean')
      );
      return $result;
    }


    //Constructor
    function helper_plugin_snap() {
      global $conf;

      //Chemin vers votre Dokuwiki
      //Path to your Dokuwiki
      $this->defaultWiki=DOKU_URL."doku.php?id=";

      $this->outputPath=realpath($conf['datadir']).'/../snap/';
      if (!file_exists($this->outputPath.".")) mkdir($this->outputPath);
    }


    function getSnap($param, $larg, $haut, $checkCache=NULL) {
      global $conf;

      $this->imagePath=false;
      $this->titrePage=false;
      $this->snapTime=false;
      $this->snapTimeFormatted=false;
      $this->fromCache=false;
      $this->succeed=false;
      $this->target=false;
      $this->selectedPort=false;
      $this->snapLog=false;
      $this->timeout=false;
      $this->snapDuration=false;
      $this->snapTotalDuration=false;
      $this->tries=false;
      $this->url=false;
      $this->width=false;
      $this->height=false;

      if ($checkCache === NULL) $checkCache=$this->checkCache;

      if (!preg_match('/^.*?:\/\//',$param)) {
        $this->url=$this->defaultWiki.$param;

        //Il vous faut appliquer cette astuce pour utiliser cette adresse avec authentification: http://www.dokuwiki.org/tips:phashlogin 
        //You have to apply this tip to use this url with authentication: http://www.dokuwiki.org/tips:phashlogin
        $url=$this->defaultWiki.$param."&u=".urlencode($_SESSION[DOKU_COOKIE]['auth']['user'])."&phash=".urlencode($_SESSION[DOKU_COOKIE]['auth']['pass']);

        //Si vos pages sont en libre accès sans authentification, vous pouvez utiliser cette adresse à la place
        //If your pages are fully readable without authentication, you can use this adresse instead
        //$url=$this->defaultWiki.$param;

        //Ne pas utiliser la ligne ci-dessous à moins d'être vraiment sûr
        //(les mots de passe des utilisateurs sera utilisé en clair !!!)
        //Do not use the line below unless you are really sure
        //(the clear users password will be used!!!)
        //$url=$this->defaultWiki.$param."&u=".urlencode($_SESSION[DOKU_COOKIE]['auth']['user'])."&p=".PMA_blowfish_decrypt(urlencode($_SESSION[DOKU_COOKIE]['auth']['pass'], auth_cookiesalt());

        $pagelist = plugin_load('helper', 'pagelist');
        if (!$pagelist) {
          $titrePage=explode(":",$param);
          $titrePage=$titrePage[sizeof($titrePage)-1];
          $titrePage=str_replace('_',' ',$titrePage);
        }
        else {
          $pagelist->page['id']=$param;
          $pagelist->page['exists'] = 1;
          $pagelist->_meta=NULL;
          $titrePage = $pagelist->_getMeta('title');
          if (!$titrePage) $titrePage = str_replace('_', ' ', noNS($param));
          $titrePage = hsc($titrePage);
        }
      }
      else {
        $this->url=$param;
        $url=$param;
        $titrePage="";
      }

      if (!$larg && !$haut) {
        $larg=$this->defLarg;
        $haut=$this->defHaut;
      }      
      else if (!$larg) $larg=round($haut*$this->imFactor,0);
      else if (!$haut) $haut=round($larg/$this->imFactor,0);

      if ($larg>$this->maxLarg) $larg=$this->maxLarg;
      if ($haut>$this->maxHaut) $haut=$this->maxHaut;

      $this->width=$larg;
      $this->height=$haut;

      if ($url==$param) $image="web_".rawurlencode($param);
      else $image=$param;
      $image.="_".$larg."x".$haut.".jpg";
      $imagePath=$this->outputPath.$image;
      if (file_exists($imagePath)) list($imLarg, $imHaut, $imType, $imAttr) = getimagesize($imagePath);

      //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
      if (!$checkCache || 
          !file_exists($imagePath) ||
          ((time()-filemtime($imagePath))>$conf['cachetime']) ||
          $imLarg != $larg ||
          $imHaut != $haut) {

        $totalStart=time();
        $try=0;

        //Build the ports list
        $ports=explode(" ",$this->snapPorts);

        while (!$fp && $try<$this->tryTimeout) {
          //Pause d'un quart de seconde si on est en retry
          if ($try) usleep(250000);
          error_log("SNAP: $image try #$try");
          $this->selectedPort=$ports[array_rand($ports)];
          $fp = fsockopen($this->snapServer, $this->selectedPort, $errno, $errstr, 30);
          $try++;
        }
        if (!$fp) {
          error_log("SNAP: $image aborting");
          $this->tries=$try;
          $this->width=false;
          $this->height=false;
          return false;
        } else {
          error_log("SNAP: $image launch snap");
          $start=time();
          fwrite($fp, "$url $imagePath $this->screenx $this->screeny ".($this->snapTimeout*1000)." $larg $haut\n");
          while (!feof($fp)) $this->snapLog.=fgets($fp, 128);
            fclose($fp);
          }
          $this->snapDuration=time()-$start;
          $this->snapTotalDuration=time()-$totalStart;
          $this->tries=$try;
        }
        else {
          error_log("SNAP: $image found in cache");
          $this->fromCache=true;
        }

        //Remove password from snapLog
        $this->snapLog=preg_replace_callback("/&phash=(.*)/",
                                               create_function('',
                                                 'return "&phash=******";'
                                             ),
                                             $this->snapLog);
        $this->snapLog=preg_replace_callback("/&p=(.*)/",
                                               create_function('',
                                                 'return "&p=******";'
                                             ),
                                             $this->snapLog);

        //timeout occurs during snap? (even if true, the snap image may be ok)
        if (preg_match("/html2image error: time out/i",$this->snapLog)) $this->timeout=true;

        //timeout occurs during snap? (even if true, the snap image may be ok)
        if (preg_match("/html2image error: time out/i",$this->snapLog)) $this->timeout=true;

        if (!file_exists($imagePath)) {
          error_log("SNAP: $image not found after snap");
          return false;
        }

        error_log("SNAP: $image available");
        $this->snapTime=filemtime($imagePath);
        $this->snapTimeFormatted=strftime($conf['dformat'],$this->snapTime);

        if ($url==$param) {
          if ($conf['target']['extern']) $this->target="target=\"".$conf['target']['extern']."\"";
        }
        else {
          if ($conf['target']['wiki']) $this->target="target=\"".$conf['target']['wiki']."\"";
        }

        $this->imagePath=$imagePath;
        $this->titrePage=$titrePage;
        $this->succeed=true;

        return array($this->imagePath, $this->titrePage, $this->target);
    }
}
?>
