<?php
if(!defined('DOKU_INC')) define('DOKU_INC',realpath(dirname(__FILE__).'/../../../').'/');
if(!defined('DOKU_PLUGIN')) define('DOKU_PLUGIN',DOKU_INC.'lib/plugins/');
require_once(DOKU_PLUGIN.'action.php');

/**
 * @license    GPL 2 (http://www.gnu.org/licenses/gpl.html)
 * @author     Pierre Spring <pierre.spring@liip.ch>
 * @author     Myron Turner <turnermm02@shaw.ca>
 */

class action_plugin_fckg_edit extends DokuWiki_Action_Plugin {
    //store the namespaces for sorting
    var $fck_location = "fckeditor";
    var $helper       = false;
    var $fckg_bak_file = "";
    /**
     * Constructor
     */
    function action_plugin_fckg_edit()
    {
        $this->setupLocale();
        $this->helper =& plugin_load('helper', 'fckg');
    }

    function getInfo()
    {
        return confToHash(dirname(__FILE__).'../info.txt');
    }

    function register(&$controller)
    {
     global $FCKG_show_preview;      
     global  $Using_FCKG_EDITOR;  // TRUE if this an FCKG file or we are in the editor

     $FCKG_show_preview=false;
     list($ns, $b_no) = explode('.',  $_REQUEST['id']);    

    $Using_FCKG_EDITOR = $this->isFCKG();  // if false, it is set to true in fckg editor

     $b_no = isset($b_no) ? ++$b_no: 1;
     $this->fckg_bak_file = $ns . ".$b_no";   // used in the edit page for check box title popup
  
        if(isset($_REQUEST['fckg_bak']) && $_REQUEST['fckg_bak'] == 'fckg_bak') {
          // create backups when switching from FCKG editor to Native DW editor
          // backups are numbered incrementally
     
              $file = str_replace(':', '/', $_REQUEST['id']);
              $orig = DOKU_INC . "data/pages/$file";              
              $bak = str_replace(':', '/', $this->fckg_bak_file);  
              $bak = DOKU_INC . "data/pages/$bak";    
                    
              $handle = $handle = fopen("$bak.txt", "w");
              fwrite($handle,file_get_contents("$orig.txt"));
              fclose($handle); 
        }

        if(isset($_REQUEST['mode']) && $_REQUEST['mode'] == 'dwiki') {
           if(isset($_REQUEST['fck_convert'])) {
              $controller->register_hook('IO_WIKIPAGE_READ', 'BEFORE', $this, 'fck_convert_text');  
           }

          $FCKG_show_preview=true;
          return;
        }
        elseif(isset($_COOKIE['FCKW_USE'])) {
             preg_match('/_\w+_/',  $_COOKIE['FCKW_USE'], $matches);
             if($matches[0] == '_false_') {
               if(isset($_REQUEST['fck_convert'])) {
                  $controller->register_hook('IO_WIKIPAGE_READ', 'BEFORE', $this, 'fck_convert_text');  
               }
                   $FCKG_show_preview=true;
                   return;
             }
        }

        // $Using_FCKG_EDITOR = true;
        $controller->register_hook('TPL_ACT_RENDER', 'BEFORE', $this, 'fckg_edit');
        $controller->register_hook('TPL_METAHEADER_OUTPUT', 'BEFORE', $this, 'fckg_edit_meta');
    }

    function isFCKG() {
      $file = str_replace(':', '/', $_REQUEST['id']);
      $file = DOKU_INC . "data/pages/$file.txt";     
      if(!file_exists($file)) {          
           return true;
      }
      $text = file_get_contents($file);

      $pos = strpos($text, '<align');    
      if($pos !== false) {                    
           return true;
      }

      $pos = strpos($text, '<fckg>');  
      if ($pos === false) {
           $pos = strpos($text, 'fckgCodeBLOCK'); 
           if ($pos === false) {  
               return false;
           }
      }
      
      return true;
    }

    /**
     * fckg_edit_meta 
     *
     * load fck js
     * 
     * @param mixed $event 
     * @access public
     * @return void
     */
    function fckg_edit_meta(&$event)
    {

        global $ACT;
        // we only change the edit behaviour
        if ($ACT != 'edit'){
            return;
        }
        global $ID;
        global $REV;
        global $INFO;
        if(!isset($INFO['userinfo'])) {
        //   return;
        }
        global $WASSHOW;
        // load the text and check if it is a fck
        if($INFO['exists']){
            if($RANGE){
                list($PRE,$text,$SUF) = rawWikiSlices($RANGE,$ID,$REV);
            }else{
                $text = rawWiki($ID,$REV);
            }
        }
        $event->data['script'][] = 
            array( 
                'type'=>'text/javascript', 
                'charset'=>'utf-8', 
                '_data'=>'',
        //        'src'=>DOKU_BASE.'lib/scripts/' .$this->fck_location. '/fckeditor.js'
                 'src'=>DOKU_BASE.'lib/plugins/fckg/' .$this->fck_location. '/fckeditor.js'
            );
        return;
    }

    /**
     * fckg_edit
     *
     * edit screen using fck
     *
     * @param & $event
     * @access public
     * @return void
     */
    function fckg_edit(&$event)
    {
  
        // we only change the edit behaviour
        if ($event->data != 'edit') {
            return;
        }
        // load xml and acl
        if (!$this->_preprocess()){
            return;
        }
        // print out the edit screen
        $this->_print();
        // prevent Dokuwiki normal processing of $ACT (it would clean the variable and destroy our 'index' value.
        $event->preventDefault();
        // index command belongs to us, there is no need to hold up Dokuwiki letting other plugins see if its for them
        $event->stopPropagation();
    }

    function _preprocess()
    {
        global $ID;
        global $REV;
        global $DATE;
        global $RANGE;
        global $PRE;
        global $SUF;
        global $INFO;
        global $SUM;
        global $lang;
        global $conf;

        //set summary default
        if(!$SUM){
            if($REV){
                $SUM = $lang['restored'];
            }elseif(!$INFO['exists']){
                $SUM = $lang['created'];
            }
        }
        //no text? Load it!
        if(!isset($text)){
            $pr = false; //no preview mode
            if($INFO['exists']){
                if($RANGE){
                    list($PRE,$text,$SUF) = rawWikiSlices($RANGE,$ID,$REV);
                }else{
                    $text = rawWiki($ID,$REV);
                }
            }else{
                //try to load a pagetemplate
                $data = array($ID);
                $text = trigger_event('HTML_PAGE_FROMTEMPLATE',$data,'pageTemplate',true);
            }
        }else{
            $pr = true; //preview mode
        }

       /* fix indents for Firefox so that they contain proper color information */
         $user_agent = $_SERVER['HTTP_USER_AGENT'];
         if(preg_match('/Firefox/i', $user_agent)) {
         $pat = '<color rgb\(\d+,\s*\d+,\s*\d+\)\/(rgb\(\d+,\s*\d+,\s*\d+\))>\s*<indent style=[\'"]color:(white)[\'"]>\W+<\/indent>';

         $text = preg_replace_callback('/'. $pat . '/',  
                  create_function(
                      '$matches',
                      'return preg_replace("/" .$matches[2] . "/", $matches[1], $matches[0]);'
                  ),          
                  $text);
         }
        
       // $text = preg_replace('/%%/',"&#37;&#37;", $text); 
                    
        $this->xhtml = $this->_render_xhtml($text);

        return true;
    }

    function _print()
    {
        global $INFO;
        global $lang;
        global $ID;
        global $REV;
        global $DATE;
        global $PRE;
        global $SUF;
        global $SUM;
        $wr = $INFO['writable'];
        if($wr){
            if ($REV) print p_locale_xhtml('editrev');
            print p_locale_xhtml($include);
            $ro=false;
        }else{
            // check pseudo action 'source'
            if(!actionOK('source')){
                msg('Command disabled: source',-1);
                return false;
            }
            print p_locale_xhtml('read');
            $ro='readonly="readonly"';
        }
        if(!$DATE) $DATE = $INFO['lastmod'];
         if(!$DATE) $DATE = $INFO['lastmod'];
        $guest_toolbar = $this->getConf('guest_toolbar');
        $guest_media  = $this->getConf('guest_media');
        if(!isset($INFO['userinfo']) && !$guest_toolbar) {        
            
                echo  $this->helper->registerOnLoad(
                    ' fck = new FCKeditor("wiki__text", "100%", "600"); 
                     fck.BasePath = "'.DOKU_BASE.'lib/plugins/fckg/'.$this->fck_location.'/"; 
                     fck.ToolbarSet = "DokuwikiNoGuest";  
                     fck.ReplaceTextarea();'
                     );
        }
        else if(!isset($INFO['userinfo']) && !$guest_media) {            

            echo  $this->helper->registerOnLoad(
                ' fck = new FCKeditor("wiki__text", "100%", "600"); 
                 fck.BasePath = "'.DOKU_BASE.'lib/plugins/fckg/'.$this->fck_location.'/"; 
                 fck.ToolbarSet = "DokuwikiGuest";  
                 fck.ReplaceTextarea();'
                 );
        }
        
        else {
            echo  $this->helper->registerOnLoad(
                ' fck = new FCKeditor("wiki__text", "100%", "600"); 
                 fck.BasePath = "'.DOKU_BASE.'lib/plugins/fckg/'.$this->fck_location.'/"; 
                 fck.ToolbarSet = "Dokuwiki";  
                 fck.ReplaceTextarea();'
                 );
        }

 
?>

   <form id="dw__editform" method="post" action="<?php echo script()?>" accept-charset="<?php echo $lang['encoding']?>"><div class="no">
      <input type="hidden" name="id"   value="<?php echo $ID?>" />
      <input type="hidden" name="rev"  value="<?php echo $REV?>" />
      <input type="hidden" name="date" value="<?php echo $DATE?>" />
      <input type="hidden" name="prefix" value="<?php echo formText($PRE)?>" />
      <input type="hidden" name="suffix" value="<?php echo formText($SUF)?>" />
      <input type="hidden" id="fckg_mode_type"  name="mode" value="" />
      <input type="hidden" id="fckEditor_text"  name="fckEditor_text" value="" />
      <?php
      if(function_exists('formSecurityToken')) {
           formSecurityToken();  
      }
      ?>
    </div>

    <textarea name="wikitext" id="wiki__text" <?php echo $ro?> cols="80" rows="10" class="edit" tabindex="1"><?php echo "\n".$this->xhtml?></textarea>

<?php 

$temp=array();
trigger_event('HTML_EDITFORM_INJECTION', $temp);

$DW_EDIT_disabled = '';
if($INFO['client'] == 'guest') $DW_EDIT_disabled = 'disabled';
?>

    <div id="wiki__editbar">
      <div id="size__ctl"></div>
      <div id = "fck_size__ctl" style="display: none">
       
       <img src = "<?php echo DOKU_BASE ?>lib/images/smaller.gif"
                    title="edit window smaller"
                    onclick="dwfck_size_ctl('smaller');"   
                    >
       <img src = "<?php echo DOKU_BASE ?>lib/images/larger.gif"
                    title="edit window larger"
                    onclick="dwfck_size_ctl('larger');"   
           >
      </div>
      <?php if($wr){?>
         <div class="editButtons">
            <input type="checkbox" name="fckg" value="fckg" checked="checked" style="display: none;"/>
            <input class="button" id="edbtn__save" type="submit" name="do[save]" value="<?php echo $lang['btn_save']?>" accesskey="s"
                      <?php echo $DW_EDIT_disabled; ?>
                      title="<?php echo $lang['btn_save']?> [ALT+S]" tabindex="4" />
            <input class="button" id="ebtn__delete" type="submit" 
                   <?php echo $DW_EDIT_disabled; ?>
                   name="do[delete]" value="<?php echo $lang['btn_delete']?>"
                   accesskey="p" title="<?php echo "Delete Page" ?> [ALT+D]" tabindex="5" />

<?php
/*
We use the preview event, to trigger back to wiki syntax ;)
<input class="button" id="edbtn__preview" type="submit" name="do[preview]" value="<?php echo $lang['btn_preview']?>" accesskey="p" title="<?php echo $lang['btn_preview']?> [ALT+P]" tabindex="5" />
 */

 
global $INFO;


$disabled = 'Disabled';
$users = $this->getConf('groups');
$users = trim($users);
if(strtoupper($users) == 'ANY') {
    $disabled = '';
}
elseif(isset($INFO['userinfo'])) {
  $user_groups = $INFO['userinfo']['grps'];
  $allowed_groups = explode(',',$users);
  foreach($allowed_groups as $group) {
          $group = trim($group);
          if(in_array ($group, $user_groups) ) {
            $disabled ="";
            break;
          }
  }  
}

$BIG_FILE_disabled="";
if($this->big_file()) {
  $BIG_FILE_disabled='disabled';
}

$FCK_PREVIEW_DISPLAY = "";

$fck_preview = $this->getConf('fck_preview');
if(isset($INFO['userinfo'])) {
    if(in_array($fck_preview, $INFO['userinfo']['grps'])) {  
       $FCK_PREVIEW_DISPLAY = ' style="display:inline"; ';
    }
}
?>
            <input class="button" type="submit" name="do[draftdel]"
             value="<?php echo $lang['btn_cancel']?>" tabindex="8" 
            />

            <input class="button" id="edbtn__preview" type="submit" name="do[preview]"  
                     <?php echo $DW_EDIT_disabled; ?>
                     onmousedown="saveFCKEditorNode(this);return true;"  
                     <?php echo $BIG_FILE_disabled; ?>
                     <?php echo $FCK_PREVIEW_DISPLAY; ?>
                     value="FCK Preview" accesskey="p" title="<?php echo $lang['btn_preview']?> 
                     [ALT+P]" tabindex="7" />

  
            <input class="button" type="button" value = "Language"
                   title="Select language for spell checker"  
                   onclick="aspell_window();"  
                  /> 

            <br />
             <input class="button" type="button" value = "Refresh"
                   title="Reset lock timer"  
                   onclick="renewLock();"  
                  />&nbsp;&nbsp;&nbsp;
 
                <input class="button"   <?php echo $DW_EDIT_disabled; ?>
                 onclick ="setDWEditCookie(2, this);this.form.submit();" 
                 type="submit" name="do[edit]" value="DW Edit" accesskey="p" 
                 title="Switch from FCK Editor to Native DokuWiki Editor"
                 tabindex="6" />
            &nbsp;<input type="checkbox" id="fck_convert" name="fck_convert" value="fck_convert"
                              <?php echo $DW_EDIT_disabled; ?>
                             CHECKED  
                             onchange="document.getElementById('fckg_bak').checked=false;"
                             onmouseup="document.getElementById('fckg_bak').checked=false;"
                             title="Conversion will not be perfect"
                             />  Convert FCK to DokuWiki Syntax
            &nbsp;&nbsp;<input type="checkbox" name="fckg_bak" value="fckg_bak" id="fckg_bak"
                              <?php echo $DW_EDIT_disabled; ?>
                              onchange="document.getElementById('fck_convert').checked=false;"
                              onmouseup="document.getElementById('fck_convert').checked=false;"
                              title="Your work will be saved as <?php echo $this->fckg_bak_file ?>"
                             /> Backup FCK and open blank editor&nbsp;&nbsp;&nbsp;&nbsp;
 <br/ >
<input type="checkbox" name="fckg_timer" value="fckg_timer"  id = "fckg_timer"
                      style = 'display:none;'
                      onclick="disableDokuWikiLockTimer();";  <?php echo $disabled  ?>
                / > <span id='fckg_timer_label'
                    style = 'display:none;'>Disable editor time-out messsages </span> 
     

  <script language="javascript">
        function aspell_window() {
          window.open("lib/plugins/fckg/fckeditor/aspell.php","smallwin", "width=600,height=500,scrollbars=yes");
        }
        unsetDokuWikiLockTimer();  

       /**
             Saves contents of the FCKeditor text area so that unsave edits in FCK TextArea are
             not lost when switching from the FCKEditor to DokuWiki preview mode: FCK Preview             
        */
        function saveFCKEditorNode(e) {
           var dwform = $('dw__editform');
           if(dwform && dwform.elements && dwform.elements.fckEditor_text && ourFCKEditorNode) {           
               dwform.elements.fckEditor_text.value = ourFCKEditorNode.innerHTML; 
         }
        
           return true;
        }

  var dwform = $('dw__editform');
  var text = dwform.elements.wikitext.value;

  var pre = text.indexOf('<pre');  
  // var table = text.indexOf('<table');  
  var table = -1;   // these conversions no longer needed for table ?
  if(pre != -1 || table != -1) {
      text = text.replace(/\n/g, "__NL___");  // string replace balks at newlines
      if(pre != -1) {
            text = text.replace(/(<pre\s+class=\"code\">)(.*?)(<\/pre>)/g, repl_cb);
      }
      if(table != -1) {
        text = text.replace(/(<td.*?>)(.*?)(<\/td>)/g, repl_cb);
      }
      text = text.replace(/__NL___/g,"\n");   // replace the newlines
      dwform.elements.wikitext.value = text;
  }

function repl_cb(one,two,three,four) {
// one is the entire match

   var code = one.match(/<pre/) ? true : false;

    three = three.replace(/<a(?=\s)/g,'__openURL__');
    three = three.replace(/<\/a>/g,'__closedURL__'); 
 
   //three = three.replace(/_<([^\<]+)_>/g,"<$1>");
   three = three.replace(/</g,'&lt;')   
   three = three.replace(/>/g,'&gt;')

   if(!code) {
      three = three.replace(/&lt;([biu]{1,1})&gt;/g,'<$1>') ;
      three = three.replace(/&lt;\/([biu]{1,1})&gt;/g,'</$1>') ;
      three = three.replace(/&lt;br \/&gt;/g,'<br />'); 
      three = three.replace(/&lt;(strong|em|strike|del|sup|sub)&gt;/g,'<$1>'); 
      three = three.replace(/&lt;\/(strong|em|strike|del|sup|sub)&gt;/g,'<\/$1>');   
   }
   else {
       three = three.replace(/fckgOpenPAREN/g,'&lt;');
       three = three.replace(/&lt;em&gt;(\\+)&lt;\/em&gt;/g,'<em>$1</em>');
   }

    three = three.replace(/__openURL__/g,'<a');
    three = three.replace(/__closedURL__/g,'</a>');

    var str =  two + three + four;
    return  str;
}

function dwfck_size_ctl(which) {
   var height = parseInt(document.getElementById('wiki__text___Frame').style.height); 
   if(which == 'smaller') {
       height -= 50;
   }
   else {
      height += 50;
   }
   document.getElementById('wiki__text___Frame').style.height = height + 'px'; 
   
}
  </script>


         </div>
<?php } ?>

      <?php if($wr){ ?>
        <div class="summary">
           <label for="edit__summary" class="nowrap"><?php echo $lang['summary']?>:</label>
           <input type="text" class="edit" name="summary" id="edit__summary" size="50" value="<?php echo formText($SUM)?>" tabindex="2" />
           <?php html_minoredit()?>
        </div>
      <?php }?>
    </div>
  </form>
  <div id="draft__status"></div>
  
<?php
    }

    /**
     * Renders a list of instruction to minimal xhtml
     *
     */
    function _render_xhtml($text){
        $mode = 'fckg';
        $instructions = p_get_instructions($text);
        if(is_null($instructions)) return '';

        // try default renderer first:
        $file = DOKU_INC."inc/parser/$mode.php";

        if(@file_exists($file)){
	
            require_once $file;
            $rclass = "Doku_Renderer_$mode";

            if ( !class_exists($rclass) ) {
                trigger_error("Unable to resolve render class $rclass",E_USER_WARNING);
                msg("Renderer for $mode not valid",-1);
                return null;
            }
            $Renderer = & new $rclass();
        }else{
            // Maybe a plugin is available?
            $Renderer =& plugin_load('renderer',$mode);
	    //echo "\$Renderer: $Renderer";
            if(is_null($Renderer)){
                msg("No renderer for $mode found",-1);
                return null;
            }
        }
        $Renderer->notoc();

        $Renderer->smileys = getSmileys();
        $Renderer->entities = getEntities();
        $Renderer->acronyms = getAcronyms();
        $Renderer->interwiki = getInterwiki();
        #$Renderer->badwords = getBadWords();

        // Loop through the instructions
        foreach ( $instructions as $instruction ) {
            // Execute the callback against the Renderer
            call_user_func_array(array(&$Renderer, $instruction[0]),$instruction[1]);
        }


        //set info array
        $info = $Renderer->info;

        // Post process and return the output
        $data = array($mode,& $Renderer->doc);
        trigger_event('RENDERER_CONTENT_POSTPROCESS',$data);
        $xhtml = $Renderer->doc;


        return $xhtml;
    }

 /**
  *  @author Myron Turner <turnermm02@shaw.ca>
  *  Converts FCK extended syntax to native DokuWiki syntax
 */
  function fck_convert_text(&$event) {
     if(!isset($_REQUEST['fck_convert'])) return;
     
     $text = io_readFile($event->data[0][0]);

    
     $text = preg_replace('/~(<)+~/',"$1", $text);
     $text = preg_replace('/~(>)+~/',"$1", $text);
     $text = preg_replace('/<move>\d+<\/move>/',"", $text);
     $text = preg_replace('/<block\s+\d+:\d+.*?>/ms',"<code>", $text);
     $text = preg_replace('/<\/block>/','</code>', $text);
     $text = preg_replace('/&#183;/', "", $text);
     $text = preg_replace('/<indent.*?>[\s\xa0-\xff\W]+<\/indent>/ms', "", $text);     
     $text = preg_replace('/<font _dummy_\/.*?courier New>(.*?)<\/font>/ms', "''$1''", $text);  
     $text = preg_replace('/<align\s+left>(?!\\{2})\s*/ms', "\\\\\\\\  ", $text);  
     $text = preg_replace('/<align\s+0px>\s*/ms', "\\\\\\\\ ", $text);  
     $text = preg_replace('/&nbsp;/ms', " ", $text);  //  remove &nbsp;    
     $text = preg_replace('/<(?=\w+@.*?>)/ms', "&lt;", $text);   
     $text =  strip_tags($text, '<code>,<del>');
     $text = preg_replace('/&lt;(?=\w+@.*?>)/ms', "<", $text);  
   
    
   
     $text = preg_replace_callback(
          '/^\s+(.*?)$/ms',
           "trim_fck_convert_cb",
          $text
      );
    $text = preg_replace('/\s*#([LCR]).*?#(.*?)(?=[\|^])/e', "trim_fck_align_cell('\\1','\\2')", $text);

    $line_break = '\\\\\\\\';
    $text = preg_replace ('/(' . $line_break . '[\s\n]+)+/', "$line_break\n", $text);

     $text = preg_replace_callback(
          '/<code>(.*?)<\/code>/ms',
           "trim_code_escapes",
          $text
      );  
     $text = preg_replace('/\|\+\+THEAD\+\+ ALIGN=\w+\|\|/',"",$text);
     // process td's
     $text = preg_replace_callback(
          '/\|(.*?)\|/ms',
           "trim_code_escapes",
          $text
      );  
   
    io_SaveFile($event->data[0][0], $text);  

  }


 function big_file() {
   $big_files = $this->getConf('big_files');
   if (!$big_files) return false;
  
  $ns = str_replace(':','/', $_REQUEST['id']);
  $path = DOKU_INC . 'data/pages/' . $ns . '.txt';
  if(!file_exists($path)) return false;
  
  $fsz = filesize($path);  
  $big_sz = $this->getConf('big_file_sz'); 
 // echo "$path, $fsz, $big_sz";
  if($fsz >= $big_sz) return true;
  return false;   
 }



} //end of action class


function trim_fck_align_cell($align, $str) {

  $str =  trim($str);

  switch($align) {
      case "L":
       $str = $str . "   " ;   
       break;
      case "R":
       $str =  "   " . $str;    
       break;
      case "C":
       $str = "   $str   ";
       break;
  }

  return $str;
}

  function trim_fck_convert_cb($matches) {

        $text = ltrim($matches[0]);

        $pos = strpos($text, '-');
        if($pos === false) {
          $pos =   strpos($text, '*'); 
        }

        if($pos === false) {
              return $text . "\n";
        }
 
        if($pos == 0) return $matches[0];
        return $text . "\n";
  }

  function trim_code_escapes($matches) {
     $text = $matches[0];  
     $text = str_replace('fckgOpen_C_COMMENT', '/*', $text);
     $text = str_replace('fckgClosed_C_COMMENT', '*/', $text);
     $text = str_replace('fckgCodeBLOCK', "", $text);
     $text = str_replace('fckgOpenPAREN', '<', $text);    
     $text = str_replace("%%", "", $text);
     $text = str_replace('fckgTableOpenBRACKET', "<", $text);   
     
     return $text;
  }
?>
