par hika - 2005-02-06 17:12:52
crée le 2005-02-06 17:12:52

wakka.class.php


<?php
/*
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU Library General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 */
 
/* 
 * Version 0.4
 * WAKKA_IMAGE_PROTECT; // default not defined
 * If this variable is true, the displayimg() method
 * only shows the real if the http referer is on the same realm
 * otherwise, it shows an empty image or a replaced image with
 * WAKKA_URL_IMAGE_DEFAULT as the URL // default not defined
 *
 * Version 0.3
 * - Wakka is now implemented as an object
 * - Upload image form is not always printed
 * - Add a preview and reedit button
 * - Add a cancel button
 * - Can manage external users
 *   You must provide either a function that returns a userid
 *   or a function that returns a username
 *
 * Version 0.2
 * - Add a new revision table to have a modification history
 * - Here are the variables that can affect this script :
 *   $force_getvar = true;  // défaut unset => true
 *     This variable force the use of $wakka_page
 *     instead of $_GET[WAKKA_PAGE_NAME] to select the wakka page
 *     (cf WAKKA_PAGE_NAME in wakka.inc.php)
 *   $force_postvar = true;  // défaut unset => true
 *     This variable force the use of $wakka_page
 *     instead of $_POST[WAKKA_PAGE_NAME] to select the wakka page
 *   In *ALL* case, the $_POST has the priority   
 *
 *   $wakka_page = NULL; // default NULL
 *   $wakka_nl2br = true;
 *   $wakka_can_do_revision = false
 *   $wakka_can_edit = false
 *   $only_upload_form = false
 *   $show_header = false
 *   $show_footer = false
 */

define("REGEXP_WAKKA_PAGE""[a-zA-Z0-9\-_]+");
define("REGEXP_WAKKA_IMG""[a-zA-Z0-9\-_]+");
// This is a more restrictive URL regexp that only match http links
define("REGEXP_WAKKA_URL""https{0,1}://[a-zA-Z0-9/\-\.\~\&\;\?:_\=]+");
define("REGEXP_WAKKA_INTERNAL_URL""[a-zA-Z0-9/\-\.\~\&\;\?:_\=]+");
define("REGEXP_WAKKA_EMAIL""[a-zA-Z0-9/\-\._\@]+");
define("REGEXP_WAKKA_CHAR""[a-zA-Z0-9\ 'éèê@\-\._]");

Class 
Wakka {
  
  private 
$wakka_gvars/* Must be an array */
  
private $Conn_wakka;  /* Must be a Connect object */
  
private $rewrite_rules;
  private 
$rewrite_rule_enable;
  
  public 
$wakka_page;
  public 
$nl2br;
  public 
$can_do_revision;
  public 
$can_edit;
  public 
$can_upload_img;
  public 
$only_upload_form;
  public 
$show_header;
  public 
$show_footer;
  
  function 
Wakka() {
    
$this->wakka_gvars = array();
    
$this->wakka_page NULL;
    
$this->nl2br true;
    
$this->can_do_revision false;
    
$this->can_edit false;
    
$this->can_upload_img false;
    
$this->only_upload_form false;
    
$this->show_header false;
    
$this->show_footer false;
    
    
$this->force_getvar true;
    
$this->force_postvar true;
    
    
$this->rewrite_rule_enable false;
  }

  function 
setConnect(&$Conn) {
    if ((
is_object($Conn))
    && (
get_class($Conn) == "Connect")) {
      
$this->Conn_wakka $Conn;
      return 
true;
    }
    return 
false;
  }
  
  function 
isConnected() {
    return (
is_object($this->Conn_wakka))
        && (
get_class($this->Conn_wakka) == "Connect");
  }
  
  function 
addRewriteRule($regexp$rewrite) {
    if (!
is_array($this->rewrite_rules))
      
$this->rewrite_rules = array(array($regexp$rewrite));
    else
      
array_push($this->rewrite_rules, array($regexp$rewrite));
  }
  
  function 
escape_string($valeur) {
    
$new_val str_replace("/""/"$valeur);
    
$new_val str_replace("*""*"$new_val);
    
$new_val str_replace("&""\&"$new_val);
    
$new_val str_replace("[""["$new_val);
    
$new_val str_replace("]""]"$new_val);
    
$new_val str_replace("(""\("$new_val);
    
$new_val str_replace(")""\)"$new_val);
    return 
str_replace("/""/"$valeur);
  }

/* -----------------------------------------------------------------------------
 * Callback functions for preg_replace_callback
 */ 
  
function getservervars(&$tags, &$values) {
    if (isset(
$_SERVER)) {
      
$tags = array();
      
$values = array();
      foreach (
$_SERVER as $name => $value) {
        
array_push($tags"/\\${".$name."}/");
        
array_push($values$value);
      }
      
reset($_SERVER);
      return 
true;
    }
    return 
false;
  }

  function 
include_php_source($matches) {
    if (
file_exists($matches[1])) {
      Include(
$matches[1]);
    }
  }

  function 
show_php_source($matches) {
    if (
substr($matches[1], 07) == "http://") {
      
$source highlight_file($matches[1], true);
    }
    else if (
file_exists($matches[1])) {
      
$source highlight_file($matches[1], true);
    }
    if (isset(
$source)) {
      return 
"<div class=\"".WAKKA_DIV_PHPSOURCE_CSS_CLASS."\">".$source."</div>";
    }
  }

  function 
show_php_source_string($matches) {
    
$source html_entity_decode($matches[1]);
    
$source str_replace("<br />"""$source);
    
$source highlight_string($sourcetrue);
    return 
"<div class=\"".WAKKA_DIV_PHPSOURCE_CSS_CLASS."\">".$source."</div>";
  }

  function 
mailto_email_protect($matches) {
    switch (
count($matches)) {
    case 
2:
      
$new_val str_replace("@"" AT "$matches[1]);
      
$new_val str_replace("."" DOT "$new_val);
      return 
"<a href=\"mailto:".$new_val."\">".$new_val."</a>";
      break;
    case 
3:
      
$new_val str_replace("@"" AT "$matches[1]);
      
$new_val str_replace("."" DOT "$new_val);
      return 
"<a href=\"mailto:".$new_val."\">".$matches[2]."</a>";    
      break;
    }
  }

  function 
tag_h_replace($matches) {
    if (
count($matches) == 4) {
      
$len1 strlen($matches[1]);
      
$len2 strlen($matches[3]);
      
      if (
$len1 == $len2 ) {
        return 
"<h".$len1.">".$matches[2]."</h".$len1.">";
      }
    }
  }

  function 
tag_ul_li_replace($matches) {
    
$li "";
    
$elements explode("\n"$matches[0]);
    for (
$i 0$i count($elements); $i++) {
      
$line str_replace("<br />"""$elements[$i]);
      
$line str_replace("* """$line);
      
$line trim($line);
      if (
$line != "")
        
$li .= "<li>".$line."</li>\n";
    }
    return 
"<ul>".$li."</ul>";
  }
  
  function 
process_internal_url($matches) {
    switch(
count($matches)) {
    case 
2:
      return 
"<a href=\"".$this->rewrite_url($matches[1])."\">".
             
$matches[1]."</a>";
      break;
    case 
3:
      return 
"<a href=\"".$this->rewrite_url($matches[1])."\">".
             
$matches[2]."</a>";
      break;
    }
  }
  
  function 
process_external_url($matches) {
    switch(
count($matches)) {
    case 
2:
      return 
"<a target=\"_blank\" href=\"".$matches[1]."\">".
             
$matches[1]."</a>";
      break;
    case 
3:
      return 
"<a target=\"_blank\" href=\"".$matches[1]."\">".
             
$matches[2]."</a>";
      break;
    }
  }
  
  function 
process_wakka_url($matches) {
    switch(
count($matches)) {
    case 
2:
      return 
"<a href=\"".$this->rewrite_url($_SERVER["SCRIPT_NAME"]."?".WAKKA_PAGE_NAME."=".$matches[1])."\">".
             
$matches[1]."</a>";
      break;
    case 
3:
      return 
"<a href=\"".$this->rewrite_url($_SERVER["SCRIPT_NAME"]."?".WAKKA_PAGE_NAME."=".$matches[1])."\">".
             
$matches[2]."</a>";
      break;
    }
  }
  
  function 
process_wakka_url_img($matches) {
    
$wakka_img_path $this->getwakkaimgpath();
    switch(
count($matches)) {
    case 
2:
      return 
"<img src=\"".$this->rewrite_url($wakka_img_path."?".WAKKA_IMG_NAME."=".$matches[1])."\" ".
        
"border=\"0\" alt=\"".$matches[1]."\" title=\"".$matches[1]."\" />";
      break;
    }
  }
  
  function 
process_wakka_url_img_href($matches) {
    
$wakka_img_path $this->getwakkaimgpath();
    switch(
count($matches)) {
    case 
3:
      return 
"<a target=\"_blank\" href=\"".$matches[2]."\">".
        
"<img src=\"".$this->rewrite_url($wakka_img_path."?".WAKKA_IMG_NAME."=".$matches[1])."\" ".
        
"border=\"0\" alt=\"".$matches[1]."\" title=\"".$matches[1]."\" /></a>";
      break;
    }
  }
/* -------------------------------------------------------------------------- */
  
/* -----------------------------------------------------------------------------
 * Functions that must be private
 */
  
function getauthorname($wakka_page$wakka_revision NULL) {
  
/* ---------------------------------------------------------------------------
   * Get the wakka page 's author name
   *
   * @param  string wakka page name
   * @param  int   (optional) wakka revision number
   * @return string author name or NULL
   * ------------------------------------------------------------------------ */
    
if (!$this->isConnected())
      return 
NULL;
    
    if (!
is_null($wakka_revision)) {
      
$SQL "SELECT wakka_author_id, wakka_author_name 
              FROM "
.WAKKA_TXT_REVISION_TABLE."
              WHERE wakka_key = "
.STRING_SQL($wakka_page)."
              AND wakka_revision = "
.NUM_SQL($wakka_revision);
    }
    else {
      
$SQL "SELECT wakka_author_id, wakka_author_name 
              FROM "
.WAKKA_TXT_TABLE."
              WHERE wakka_key = "
.STRING_SQL($wakka_page);
    }
    
$result $this->Conn_wakka->QueryDB($SQL);
    if (
$cur $this->Conn_wakka->CursorDB($result)) {
      
$this->Conn_wakka->FreeDB($result);
      
      
$username $this->getauthorname_byid($cur["wakka_author_id"]);
      if (!
is_null($username))
        return 
$username;
      if (!
is_null($cur["wakka_author_name"]))    
        return 
$cur["wakka_author_name"];
    }
    else
      
$this->Conn_wakka->FreeDB($result);
    return 
WAKKA_DEFAULT_UNKNOWN_USER;
  }
  
  function 
getauthorname_byid($id) {
  
/* ---------------------------------------------------------------------------
   * Get the wakka page 's author name by author_id
   *
   * @param  int   wakka_author_id
   * @return string author name or NULL
   * ------------------------------------------------------------------------ */
    
if ((defined("WAKKA_FUNCTION_GETUSERNAMEBYID"))
    && (!
is_null(WAKKA_FUNCTION_GETUSERNAMEBYID))
    && (
is_string(WAKKA_FUNCTION_GETUSERNAMEBYID))
    && (
WAKKA_FUNCTION_GETUSERNAMEBYID != "")
    && (
function_exists(WAKKA_FUNCTION_GETUSERNAMEBYID))
    && (
is_numeric($id))) {
      return 
call_user_func(WAKKA_FUNCTION_GETUSERNAMEBYID$id);
    }
    return 
NULL;
  }
  
  function 
getinfowakka($wakka_page$wakka_revision NULL) {
  
/* ---------------------------------------------------------------------------
   * Get the wakka page 's raw information
   *
   * @param  string wakka page name
   * @param  int   (optional) wakka revision number
   * @return array or NULL
   * ------------------------------------------------------------------------ */
    
if (!$this->isConnected())
      return 
NULL;
    if (!
is_null($wakka_revision)) {
      
$SQL "SELECT *
              FROM "
.WAKKA_TXT_REVISION_TABLE."
              WHERE wakka_key = "
.STRING_SQL($wakka_page)."
              AND wakka_revision = "
.NUM_SQL($wakka_revision);
    }
    else {
      
$SQL "SELECT *
              FROM "
.WAKKA_TXT_TABLE."
              WHERE wakka_key = "
.STRING_SQL($wakka_page);
    }
    
$result $this->Conn_wakka->QueryDB($SQL);
    if (
$cur $this->Conn_wakka->CursorDB($result)) {
      
$this->Conn_wakka->FreeDB($result);
      return 
$cur;
    }
    else
      
$this->Conn_wakka->FreeDB($result);
    return 
NULL;
  }
  
  function 
getwakkaimgpath() {
    
// We get the URL wakka_img_path
    
$dirname dirname($_SERVER["SCRIPT_NAME"]);
    
$included_files get_included_files();
    foreach (
$included_files as $included_file) {
      
$p str_replace($_SERVER["DOCUMENT_ROOT"], ""$included_file);
      
$p str_replace($dirname."/"""$p);  
      if (
basename($p) == "wakka.class.php") {
        return 
str_replace("wakka.class.php""wakka_img.php"$p);
        break;
      }
    }
  }
  
  function 
rewrite_url($url) {
    if (!
$this->rewrite_rule_enable)
      return 
$url;
    
    if (
is_array($this->rewrite_rules)) {
      foreach (
$this->rewrite_rules as $rewrite_rule) {
        
//echo $rewrite_rule[0].' to '.$rewrite_rule[1].'<br />';
        
$url_rewrite preg_replace('/'.$rewrite_rule[0].'/'$rewrite_rule[1], $url);
        
//echo $url.' => '.$url_rewrite.'<br />';
        
if ($url != $url_rewrite) {
          if (
$url_rewrite{0} != '/')
            return 
'/'.$url_rewrite;
          return 
$url_rewrite;
        }
      }
    }
    return 
$url
  }
  
  function 
resize_image($file_src, &$bin_dst, &$size$width NULL$height NULL) {
  
/* ---------------------------------------------------------------------------
   * Resize an image, by width, by height or both
   * and get the binary result
   *
   * @param  string
   * @param  ref       the binary result
   * @param  ref       the size of the binary result
   * @param  int (optional)
   * @param  int (optional)
   * @return boolean
   * ------------------------------------------------------------------------ */
    
if (!file_exists($file_src))
      return 
false;
          
    if (
$info getimagesize($file_src)) {
      switch(
$info[2]) {
      case 
1// GIF
        
if ((is_numeric($width)) || (is_numeric($height)))
          
$img_src imagecreatefromgif($file_src);
        break;
      case 
2// JPEG
        
if ((is_numeric($width)) || (is_numeric($height)))
          
$img_src imagecreatefromjpeg($file_src);
        break;
      case 
3// PNG
        
if ((is_numeric($width)) || (is_numeric($height)))
          
$img_src imagecreatefrompng($file_src);
        break;
      default:
        return 
false;
      }
      
      if ((!
is_numeric($width)) && (!is_numeric($height))) {
      
// Read the original file 
        
$fd fopen($file_src"rb");
        
$size filesize($file_src);
        
$bin_dst fread($fd$size);      
        
fclose($fd);
        return 
true;
      }
      else if (isset(
$img_src)) {
        if ((
is_numeric($width))
        && (!
is_numeric($height))
        && (
$info[0] > $width)) {
        
// Resize by width only        
          
$new_width $width;
          
$new_height = (int)($info[1] * $width $info[0]);
        }
        else if ((!
is_numeric($width))
        && (
is_numeric($height))
        && (
$info[1] > $height)) {
        
// Resize by height only
          
$new_width = (int)($info[0] * $height $info[1]);
          
$new_height $height;
        }
        else if ((
is_numeric($width))
        && (
is_numeric($height))
        && (
$info[0] > $width)
        && (
$info[1] > $height)) {
        
// Resize by width and height
          
$new_width $width;
          
$new_height $height;
        }
        
        if ((isset(
$new_height)) && (isset($new_width))) {
          
$img_dst imagecreatetruecolor($new_width$new_height);
          if (
imagecopyresampled($img_dst$img_src0000
                                 
$new_width$new_height$info[0], $info[1])) {
            
imagedestroy($img_src);                                   
            
ob_start();
            switch(
$info[2]) {
            case 
1// GIF
              
imagegif($img_dst);
              break;
            case 
2// JPEG
              
imagejpeg($img_dst);
              break;
            case 
3// PNG
              
imagepng($img_dst);
              break;
            }
            
$bin_dst ob_get_contents();
            
$size ob_get_length();
            
ob_end_clean();
            
            
imagedestroy($img_dst);
            
            return 
true;
          }
          else
            
imagedestroy($img_src);  
        }
        else
          
imagedestroy($img_src);  
      }
    }
    
    return 
false;
  }
  
/* -------------------------------------------------------------------------- */

  
function parse_rewritefile($rewrite_file) {
  
/* ---------------------------------------------------------------------------
   * parse file that contains rewrite rules
   * !! URL rewrite variable must be on the same order than expression in brackets !!
   * For example : we must have something like :
   * /index.php?rub=$1&year=$2&month=$3&day=$4
   * and not
   * /index.php?rub=$4&year=$1&month=$2&day=$3
   *
   * @param  string  file path
   * @return boolean
   * ------------------------------------------------------------------------ */
    
if (file_exists($rewrite_file)) {
      
$fd fopen($rewrite_file"r");
      
$content fread($fdfilesize($rewrite_file));
      
fclose($fd);
      
$lines explode("\n"$content);
      unset(
$content);
      foreach (
$lines as $line) {
        if ((
$line != "")
        && (
$line{0} != '#')) {
          
$words split("(\t|\ )+"$line);
          if ((
count($words) >= 3)
          && (
$words[0] == "RewriteRule")) {
          
/* Rewrite pattern replacement */
            //echo $words[1]." <-> ".$words[2]."<br />";
          
            /* Parse URL to rewrite  */
            
$url_from $words[2];
            
$url_from str_replace('?''\?'$url_from);
            
$url_from str_replace('/''/'$url_from);
            
$url_from str_replace('&''&amp;'$url_from);
            
$tmp_url_from "";
            
$array_n = array();
            while(
preg_match('/\$[1-9]/U'$url_from$array)) {
              
array_push($array_n$array[0]);
              
$url_from preg_replace('/\$[1-9]/U''(.+)'$url_from1);
            }
            
            
/* Parse URL rewrited  */
            
$url_to $words[1];
            
$url_to str_replace('\'''$url_to);
            
$url_to str_replace('^'''$url_to);
            
$url_to str_replace('$'''$url_to);
            
$n 1;
            while(
preg_match('/\(.+\)/U'$url_to)) {
              
$i array_search('$'.$n$array_n);
              
$url_to preg_replace('/\(.+\)/U''\$'.($i+1), $url_to1);
              
$n++;
            }
            
            
//echo "result : ".$url_from." => ".$url_to."<br />";
            
$this->addRewriteRule($url_from$url_to);
          }
          else if ((
count($words) == 2)
          && (
$words[0] == "RewriteEngine")) {
            if (
strtolower($words[1]) == "on") {
              
$this->rewrite_rule_enable true;  
            }
          }
        }
      }
      return 
true;
    }
    return 
false;
  }

  function 
diff($str_from$str_to) {
  
/* ---------------------------------------------------------------------------
   * diff between 2 strings
   *
   * @param  string
   * @param  string
   * @return string result after procession
   * ------------------------------------------------------------------------ */
   
    
$array_from explode("\n"$str_from);
    
$array_to explode("\n"$str_to);
    
    
$count_from count($array_from);
    
$count_to count($array_to);
    
    for(
$i 0$i $count_from$i++) {
      
$array_from[$i] = preg_replace('/<br />$/'''str_replace("\r"""$array_from[$i]));
    }
    for(
$i 0$i $count_to$i++) {
      
$array_to[$i] = preg_replace('/<br />$/'''str_replace("\r"""$array_to[$i]));
    }
    
    
$i 0;
    
$j 0;
    
$k 0;
    
    
    
$nl "<br />\n";
    
    
$result "";
    while ((
$i $count_from)
    && (
$j $count_to)) {
      
/* Line are equals */
            
      
if ($array_from[$i] == $array_to[$j]) {
        
$result .= $array_from[$i].$nl;
        
$i++;
        
$j++;
      }
      else {
      
/* Line are different */
        
if ($count_to $j == $count_from $i) {
          
$result .= "<span class=\"".WAKKA_TEXT_ADD_CLASS."\">".$array_to[$j]."</span>".$nl;
          
$result .= "<span class=\"".WAKKA_TEXT_DEL_CLASS."\">".$array_from[$i]."</span>".$nl;
          
$j++;
          
$i++;
        }
        else if (
$count_to $j $count_from $i) {
          
$result .= "<span class=\"".WAKKA_TEXT_ADD_CLASS."\">".$array_to[$j]."</span>".$nl;
          
$j++;
        }
        else {
          
$result .= "<span class=\"".WAKKA_TEXT_DEL_CLASS."\">".$array_from[$i]."</span>"