* based on the format plugin * * * text to feed into the program * * * program_alias is defined in conf/default.php similat to: * $conf['']=array('name' => "", * '' => array('iext' => "", 'oext' => "", * 'pre' => "
",
*                               'post'           => "",
                                'command_wintel' => ""
*                               'command'        => "" ));
* 
*
**/
     
// 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 syntax_plugin_chain extends DokuWiki_Syntax_Plugin 
  {
     
  function getInfo() 
    {
    return array('author' => 'Riccardo Pisanu',
                 'email'  => 'rkpisanu@yahoo.it',
                 'date'   => '2010-01-16',
                 'name'   => 'Chain Plugin',
                 'desc'   => 'Execute a sys command and create output file in a current directory for a next chain command.',
                 'url'    => 'http://www.dokuwiki.org/plugin:chain');
    }
     
  function getType() 
    { 
    return 'substition'; 
    }
        
  function getSort() 
    { 
    return 32; 
    }

  function connectTo($mode) 
    {
    $this->Lexer->addEntryPattern('.*?)',$mode,'plugin_chain');
    }

  function postConnect()
    {
    $this->Lexer->addExitPattern('','plugin_chain');
    }

  function handle($match, $state, $pos, &$handler) 
    {
    return array($match, $state, $pos);
    }

  function render($mode, &$renderer, $data) 
    {
	//Query not have time limit
	set_time_limit(0);
	//No cache pages
	$renderer->info['cache'] = false;
    //Refer to global Dokuwiki vars to get directory configuration and namespace:page
    global $conf;
    global $ID;
    //Only xhtml
    if ($mode!='xhtml') return;
    //Split data received from handle function
    @list($match, $state, $pos) = $data;
    switch ($state) 
      {
      case DOKU_LEXER_ENTER:
        break;
      case DOKU_LEXER_UNMATCHED:
        //** Split $match in Parameters $matches[0] and Text $matches[1] ** 
        $matches = preg_split('/>/u',$match,2);
        $matches[0] = trim($matches[0]);
        if ( trim($matches[0]) == '' ) 
          {
	  $matches[0] = NULL;
          }
        //** Parsing Parameters **
        preg_match('/alias=([a-zA-Z_0-9]+)/i',  $matches[0], $match_alias);
        preg_match('/output=([a-zA-Z_0-9]+)/i', $matches[0], $match_output);
        preg_match('/render=([a-zA-Z_0-9]+)/i', $matches[0], $match_render);
        preg_match('/delim=([a-zA-Z_0-9]+)/i',  $matches[0], $match_delim);
        preg_match('/debug=([a-zA-Z_0-9]+)/i',  $matches[0], $match_debug);
		//Manage Delimitator
		switch (trim($match_delim[1])) 
          {
          case 'tab'  : $match_delim[1] = "\t";     break;
          case 'mtab' : $match_delim[1] = "[ \t]+"; break;
          case 'pipe' : $match_delim[1] = "\|";     break;
          case 'scol' : $match_delim[1] = ";";      break;
		  default     : $match_delim[1] = ",";
		  } 
		  //** Begin Application Logic Plugin **
        //Get alias configuration array conf[$match_alias[1]] in conf/default.php and exit with error message if it not well configured
        $config = $this->getConf($match_alias[1]);
        if(!$config || !$config[$mode]) 
          {
		  //_xmlEntities encode html correctly 
  	      $renderer->doc .= $renderer->_xmlEntities($match_alias[1].' **  not configured for '.$mode.' output in /lib/plugins/chain/default.php **');
	      return true;
          }
        //Create/Verify Directory to store files
        $ns_path = $ID;
        $ns_path = str_replace(":","/",$ns_path); // Work out the namespace and page
        $dirname = $conf['mediadir'].'/temp/chain'.$program.'/'.$ns_path;
		//Set relative url_base for image path rendering
		list($drive_path,$url_base) = split(DOKU_BASE,$dirname);
        $url_base = DOKU_BASE.$url_base;	
        //If directory not exist then create it and grant permission with .htaccess		
        if(!is_dir($dirname))
          {		
		  io_mkdir_p($dirname); //Using dokuwiki framework
		  }
        //Output Filename
        $OutFileName = $dirname.'/'.$match_output[1].'.'.$config[$mode]['oext'];
		$RelFileName = $url_base.'/'.$match_output[1].'.'.$config[$mode]['oext'];
        //Delete old OutFileName if exist
        if (is_file($OutFileName)) unlink($OutFileName);
        //Input Filename with contain all data wrapped pre + text + post
        $InpFileName = $dirname.'/'.$match_output[1].'.'.$config[$mode]['iext'];
		$NSPath = $dirname.'/';
		if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') $NSPath=str_replace('/', '\\', $NSPath);
        $pre = str_replace(array('@InputFile@','@OutputFile@','@Path@'),
		           array($InpFileName, $OutFileName, $NSPath),
		           $config[$mode]['pre']);
        $post = str_replace(array('@InputFile@','@OutputFile@','@Path@'),
			    array($InpFileName, $OutFileName, $NSPath),
		            $config[$mode]['post']);
        $text = str_replace(array('@InputFile@','@OutputFile@','@Path@'),
			    array($InpFileName, $OutFileName, $NSPath),
		            $matches[1]);					
        $wrappeddata = $pre.$text.$post;
        //Save File Using Dokuwiki Framework
        io_saveFile($InpFileName, $wrappeddata); 
        // Replace the variable strings
		if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') 
          {
          //This is a command using Windows!
          $command=str_replace(array('@InputFile@','@OutputFile@','@Path@'),
			       array($InpFileName, $OutFileName, $NSPath),
			       $config[$mode]['command_wintel']);
		  $command=str_replace('/', '\\', $command);
		  $command=str_replace('Program Files','progra~1', $command);
          } 
          else 
          {
          //This is a command not using Windows!
          $command=str_replace(array('@InputFile@','@OutputFile@','@Path@'),
			       array($InpFileName, $OutFileName, $NSPath),
			       $config[$mode]['command']);
		  }
        $output = shell_exec($command);
        //** Trace vars for debug **
        if ( trim($match_debug[1]) == 'yes' ) 
          {
		  $DebProgs=1;
		  $this->DebugWindowsOpen();
		  $this->DebugWindowsWrite("\n");
		  $this->DebugWindowsWrite("
CHAIN DEBUG CONSOLE"); $this->DebugWindowsWrite(" Begin Trace Chain Plugin: ".date('l jS \of F Y h:i:s A')); $this->DebugWindowsWrite("".$DebProgs++.") ns_path =-->$ns_path"); $this->DebugWindowsWrite("".$DebProgs++.") dirname =-->$dirname"); $this->DebugWindowsWrite("".$DebProgs++.") DOKU_BASE =-->".DOKU_BASE); $this->DebugWindowsWrite("".$DebProgs++.") url_base =-->$url_base"); $this->DebugWindowsWrite("".$DebProgs++.") The pre text is:-->$pre"); $this->DebugWindowsWrite("".$DebProgs++.") The input text is:-->$matches[1]"); $this->DebugWindowsWrite("".$DebProgs++.") The post text is:-->$post"); $this->DebugWindowsWrite("".$DebProgs++.") Parameters:-->$matches[0]"); $this->DebugWindowsWrite("".$DebProgs++.") alias =-->$match_alias[1]"); $this->DebugWindowsWrite("".$DebProgs++.") output =-->$match_output[1]"); $this->DebugWindowsWrite("".$DebProgs++.") render =-->$match_render[1]"); $this->DebugWindowsWrite("".$DebProgs++.") delim =-->$match_delim[1]"); $this->DebugWindowsWrite("".$DebProgs++.") NSPath =-->$NSPath"); $this->DebugWindowsWrite("".$DebProgs++.") The input file is:-->$InpFileName"); $this->DebugWindowsWrite("".$DebProgs++.") The output file is:-->$OutFileName"); $this->DebugWindowsWrite("".$DebProgs++.") The command is:-->$command"); $this->DebugWindowsWrite("".$DebProgs++.") The output is:-->$output"); $this->DebugWindowsWrite("End Trace Chain Plugin: ".date('l jS \of F Y h:i:s A')); } //** Rendering ** //Save Always File Output for next chain command except png,tbl files if ($config[$mode]['oext'] !== 'png' && $config[$mode]['oext'] !== 'tbl' ) io_saveFile($OutFileName, $output); //if render=yes then render it if ( trim($match_render[1]) == 'yes' ) { switch ($config[$mode]['oext']) { case 'out' : $renderer->doc .= "
$output
"; break; case 'csv' : if ( trim($match_debug[1]) == 'yes' ) { $renderer->doc .= "
$output
"; } //Convert csv to html table //Clean sqlplus standard output string session $output = preg_replace("/Session altered\./","",$output); if (trim($match_delim[1]) == "[ \t]+") //mtab { //Clean sqlplus standard output string session $output = preg_replace("/[0-9]+ rows selected\./","",$output); $output = preg_replace("/[-]+\s/","",$output); } //$renderer->doc .= "
$output
"; //Clean any trailing or leading empty lines from the data set $output = preg_replace("/[\r\n]*$/","",$output); $output = preg_replace("/^\s*[\r\n]*/","",$output); //Replace EOL for all O.S. $output = preg_replace("/(? is optional if (strpos($output, '')) { $lines = preg_split("/\\r\\n/", $output); } else { $lines = preg_split("/\\r\\n/", $output); } //Loop for each line $numlines = 0; $table =""; foreach ($lines as $line) { if ($numlines===0) { //First line is table header $line = "
".$line."\r\n"; $table .= preg_replace("/$match_delim[1]/","",$line); } else { //Other lines are data $line = "
".$line."\r\n"; $table .= preg_replace("/$match_delim[1]/","",$line); } ++$numlines; } $renderer->doc .= "\r\n\r\n".$table."
"; break; case 'tbl' : if ( trim($match_debug[1]) == 'yes' ) { $renderer->doc .= "
$output
"; } //Convert csv to html table //$renderer->doc .= "
$output
"; //Clean any trailing or leading empty lines from the data set $output = preg_replace("/[\r\n]*$/","",$output); $output = preg_replace("/^\s*[\r\n]*/","",$output); //Replace EOL for all O.S. $output = preg_replace("/(?
".$line."\r\n"; $table .= preg_replace("/$match_delim[1]/","",$line); } else { //Other lines are data $line = "
".$line."\r\n"; $line_temp = preg_replace("/$match_delim[1]/","",$line); $table .= preg_replace("//","",$line_temp); } ++$numlines; } $renderer->doc .= "\r\n\r\n".$table."
"; break; case 'png' : //To avoid browser cache insert random number in a filename $random=rand(); $OutFileNameRnd =$dirname.'/'.'tempchain_'.$random.'_'.$match_output[1].'.'.$config[$mode]['oext']; //Copy file copy($OutFileName, $OutFileNameRnd); //Render a file png $OutFileNamePng = 'temp/chain'.$program.'/'.$ns_path.'/'.'tempchain_'.$random.'_'.$match_output[1].'.'.$config[$mode]['oext']; $OutFileNamePng = str_replace("/",":",$OutFileNamePng); // Work out the namespace and page $renderer->doc .= 'Png Image Chain Plugin Error'; break; } } break; case DOKU_LEXER_EXIT: break; } return true; } function DebugWindowsOpen() { $GLOBALS[status_window_open] = 1; ?>