<?php

/**
  * BLOG:CMS: PHP/MySQL Personal Content Management System (CMS)
  * http://blogcms.com/
  * ----------------------------------------------------------------
  *
  * Copyright (C) 2003-2005 Radek HULÁN
  * http://hulan.cz/contact/
  *
  * ----------------------------------------------------------------
  * 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.
**/

class NP_FancyText extends NucleusPlugin {

  var $js,$threads,$replytothistext,$commentinspired,$inspiredby,$class,$votes,$cvotes,$cbad;

  function getName( ){return 'FancyText';} 
  function getAuthor( ){return 'Radek HULAN';} 
  function getURL( ){return 'http://hulan.cz/';} 
  function getVersion( ){return '4.0';} 
  function getDescription( ){return 'Smilies, threaded-discussion in comments, article formatting, comment voting.';} 
  
  function install( ){
    $this->createOption( "commentinspired", "This comment inspired 'child':", "text", "this comment inspired");
    $this->createOption( "inspiredby", "Inspired by 'parent':", "text", "inspired by");
    $this->createOption( "replytothistext", "Reply to this comment text:", "text", "reply to this comment");
    $this->createOption( "allowthreads", "Enable threaded discussions for COMMENTS (yes/no):", "yesno", "yes");
    $this->createOption( "addp", "Convert line breaks to paragraphs in ARTICLE (yes/no):", "yesno", "no");
    $this->createOption( "smiliesarticles", "Convert smilies articles (yes/no):", "yesno", "no");
    $this->createOption( "smiliescomments", "Convert smilies comments (yes/no):", "yesno", "no");
    $this->createOption( "ampersands", "Encode ampersands?", "yesno", "yes");
    
    $this->createOption( "cvotes", "Enable comments voting?", "yesno", "yes");
    $this->createOption( "ctext", "Voting not allowed", "text", "Hodnocení komentářů není v tuto chvíli povoleno.");
    $this->createOption( "cvoted", "You have already voted", "text", "Pro tento komentář jste již hlasoval.");
    $this->createOption( "cok", "Your vote was saved", "text", "Váš hlas byl zaznamenán.");
    $this->createOption( "cown", "You cannot vote for you own comment", "text", "Nemůžete hlasovat pro váš vlastní komentář.");
    $this->createOption( "cban", "Comment banned", "text", "<p><em>komentář smazán administrátorem a ban IP adresy</em></p>");
    $this->createOption( "cbad", "Comment bad", "text", "<p><em>komentář byl vyhodnocen čtenáři jako brak</em></p>");
    
    // disable auto-linebreak conversions
    sql_query( "UPDATE " . sql_table( 'blog') . " SET bconvertbreaks=0");
    
    // comments votes
    global $SQL_TYPE;
	switch ($SQL_TYPE){
	   case 0:
	   case 1:
    		sql_query("CREATE TABLE ".sql_table("cvotes")." ( ".
    			" commentid int(11), ".
    			" ip varchar(15), ".
    			" vote varchar(1) NULL DEFAULT '+') ".
    			" Type=MyISAM COMMENT='Plugin: Comments votes'");
    		sql_query("ALTER TABLE ".sql_table("comment"). " ADD (cup int(11) default 0, cdown int(11) default 0)");
    		break;
	   case 2:
    		sql_query("CREATE TABLE ".sql_table("cvotes")." ( ".
    			" commentid int(11), ".
    			" ip varchar(15), ".
    			" vote varchar(1) NULL DEFAULT '+')");

    		sql_query("DROP TABLE ".sql_table("comment"));
    		sql_query("CREATE TABLE ".sql_table("comment")." ( ".
  				"cnumber INTEGER PRIMARY KEY, ".
  				"cbody text NOT NULL, ".
  				"cuser varchar(40), ".
  				"cmail varchar(100), ".
  				"cmember int(11), ".
  				"citem int(11), ".
  				"ctime text default '0000-00-00 00:00:00', ".
  				"chost varchar(60), ".
  				"cip varchar(15), ".
  				"cblog int(11), ".
  				"cup int(11) DEFAULT 0, ".
  				"cdown int(11) DEFAULT 0 )");
			sql_query("CREATE INDEX commentitem ON ".sql_table("comment")." (citem)");

    		break;
	}
    sql_query("create index idx_cvotes on ".sql_table('cvotes')." (commentid,ip)");
    
    sql_query("UPDATE ".sql_table("comment")." SET cup=10 where cmember=1");
  } 
  
  function uninstall() {
	sql_query("drop table if exists ".sql_table('cvotes'));
  }

  function supportsFeature($feature) { if ($feature=='SqlTablePrefix') return 1; else return 0;}
  
  function getEventList( ){
      return array( 
        'PreAddComment', 
        'PostAddComment',
        'PreComment', 
        'PreAddItem', 
        'PreUpdateItem', 
        'PreItem'
      );
  } 
  
  function autop( $text) {
      // encode ampersands
      if ( strtolower( $this->getOption( "addp") != 'yes'))
	  	if ($this->getOption( "ampersands") == 'yes' )
	  		return preg_replace( '/&([^#])(?![a-z]{1,8};)/', '&#38;$1', $text);
		else
			return $text;
      // linebreaks to paragraphs conversion
      return paragraph( $text, false);
  } 
  
  function event_PreAddItem(&$data){ 
    $parts=array('body','more');
    foreach ($parts as $part) $data[$part] = $this->autop($data[$part]);
  } 
  
  function event_PreUpdateItem(&$data){
    $this->event_PreAddItem($data);
  } 
  
  function event_PostAddComment(&$data){
  	// *******************************************
  	// set default comment votes
  	// *******************************************
  	$cid = intval($data['commentid']);
  	$cup = 0;
  	$cdown = 1;
  	if (intval($data['comment']['memberid']) > 0) {
  		$query = sql_query("SELECT mcanlogin, madmin FROM ".sql_table("member")." WHERE mnumber=".intval($data['comment']['memberid']));
  		if ($row = sql_fetch_object($query)) {
  			if (intval($row->mcanlogin) == 1) {
  				$cup = 5;
  				$cdown = 0;
  			}
  			if (intval($row->madmin) == 1) {
  				$cup = 10;
  				$cdown = 0;
  			}
  		}
  	} else {
  		// new member?
  		$i = quickQuery("SELECT count(*) as result FROM ".sql_table("comment")." WHERE cuser='".$data['comment']['user']."' AND cip='".$data['comment']['ip']."' AND cup-cdown>0");
  		if ($i <= 2) {
  			$cup = 0;
  			$cdown = 1;
  		} else {
  			$cup = 2;
  			$cdown = 0;
  		}
  	}
  	sql_query("UPDATE ".sql_table("comment")." SET cup=$cup, cdown=$cdown WHERE cnumber=$cid");
  } 

  function event_PreAddComment(&$data){
	// convert pseudo tags into real XHTML
	$data['comment']['body'] = commentformatting( $data['comment']['body'] );
  } 
  
  function init(){
    $this->threads=($this->getOption("allowthreads")!='no');
    $this->replytothistext=$this->getOption("replytothistext");
    $this->inspiredby=$this->getOption("inspiredby");
    $this->commentinspired=$this->getOption("commentinspired");
    $this->cvotes=$this->getOption("cvotes");
    $this->cbad=$this->getOption("cbad");
  }

  function event_PreComment($data) {
	if (!isset($this->curItem)) 
		return;
    
    /* comment id */
    $this->commentSeq++;
    $this->permacommentid=strval($data['comment']['commentid']);
    $id=strval($data['comment']['commentid']);

 	// *******************************************
  	// comment classes
  	// *******************************************	
	$query = sql_query("SELECT cmember, cup, cdown FROM ".sql_table("comment")." WHERE cnumber=".$this->permacommentid);
	$this->class = '';
	$this->votes = 0;
	if ($row = sql_fetch_object($query)) {
		$this->votes = $row->cup - $row->cdown;
		$admin = false;
		if ($row->cmember > 0) {
			$admin = quickQuery("SELECT madmin as result FROM ".sql_table("member")." WHERE mnumber=".$row->cmember);
			if ($admin)
				$this->votes = 10;
		}
		if ($this->votes >= 10)
			$this->class = ' class="comment-top" rel="comment-top"';
		elseif ($this->votes >= 0)
			$this->class = ' class="comment-ok" rel="comment-ok"';
		elseif ($this->votes > -10)
			$this->class = ' class="comment-bad" rel="comment-bad"';
		else
			$this->class = ' class="comment-ban" rel="comment-ban"';
		if ($admin)
			$this->class = ' class="comment-admin" rel="comment-admin"';
	}
	global $member;
	if ($this->votes <= -10) {
		if (! ($member->isAdmin() && $member->isLoggedIn()) )
			$data['comment']['body'] = $this->cbad;
	}

    /* old style comments? */
    $pos=strpos($data['comment']['body'],'<p>');
    if ($pos===false) $data['comment']['body']="<p>".trim($data['comment']['body'])."</p>";

    // *******************************************
    // threaded discussion - JavaScript - PARENTS
    // *******************************************
    if ($this->threads){
      $offset=0;
      do{
        $pos=strpos(substr($data['comment']['body'],$offset),'[');
        if ( !($pos===false) ){
          $pos=$pos+$offset;
          $offset=$pos+1;
          if ( ereg("^([0-9]+)].*$",substr($data['comment']['body'],$offset,10),$r) ){
            $cid=$r[1];
            if (intval($cid)<$this->commentSeq){
              /* get comment author name */
              $query=sql_query("SELECT cmember, cuser, cup-cdown as vote FROM ".sql_table('comment')." WHERE citem=".strval($this->curItem)." ORDER BY ctime, cnumber ASC LIMIT ".strval(intval($cid)-1).",1");
              $ok = false;
              if ($row=sql_fetch_object($query)){
              	$ok = ($row->vote > -10 || $row->cmember>0);
                if ($row->cmember>0){
                  $query=sql_query("SELECT mname FROM ".sql_table('member')." WHERE mnumber=".strval($row->cmember));
                  if ($row=sql_fetch_object($query)) $name=$row->mname;
                } else {
                  $name=$row->cuser;
                }
               }
               if ($ok)
                $data['comment']['body']=str_replace('['.$cid.']','<span>'.$this->inspiredby.' '.'<a href="#cmmnt'.$cid.'">'.$name.' &#8212; #'.$cid."</a></span>",$data['comment']['body']);
            } else {
              if (intval($cid)==$this->commentSeq){
                $data['comment']['body']=str_replace('['.$cid.']','<span>[self-reference not allowed: '.$cid.']</span>',$data['comment']['body']);
              } else {
                $data['comment']['body']=str_replace('['.$cid.']','<span>[future items not allowed: '.$cid.']</span>',$data['comment']['body']);
              }
            }
          }
        }
      } while (!($pos===false));
    }
    
    // *******************************************
    // threaded discussion - JavaScript - CHILDREN
    // *******************************************
    if ($this->threads){
      /* create links to childs */
	  $data['comment']['body'].="<a href=\"#commentform\" title=\"Reply\">".$this->replytothistext."</a>";
      
      $query=sql_query("SELECT cbody, cmember, cuser, cup-cdown as vote FROM ".sql_table('comment')." WHERE citem=".strval($this->curItem)." ORDER BY ctime, cnumber ASC LIMIT ".strval($this->commentSeq).",100");
      $rownumber=$this->commentSeq;
      $first=true;
      
      $children="";
      while ($row=sql_fetch_object($query)){
        $rownumber++;
        if ( (!(strpos(sql_unescape($row->cbody),'['.strval($this->commentSeq).']')===false) ||
             !(strpos(sql_unescape($row->cbody),'[<a href="#cmmnt'.strval($this->commentSeq).'">ad '.strval($this->commentSeq).'</a>]')===false))
             && ($row->vote>-10 || $row->cmember>0)
        ) {
          if ($first) $data['comment']['body'].="<ol>";
          if ($row->cmember>0){
            $queryname=sql_query("SELECT mname FROM ".sql_table('member')." WHERE mnumber=".strval($row->cmember));
            if ($rowname=sql_fetch_object($queryname)) $name=$rowname->mname;
          } else {
            $name=$row->cuser;
          }
          $first=false;
          $data['comment']['body'].='<li>'.$this->commentinspired.' <a href="#cmmnt'.strval($rownumber).'">'.$name.' &#8212; #'.strval($rownumber).' </a></li>';
          if (!empty($children)) $children.=',';
          $children.="'cmmnt".strval($rownumber)."'";
        }
      }
      if (!$first) $data['comment']['body'].='</ol>';
    }

    // *******************************************
    // emoticons 
    // *******************************************
	if ( $this->getOption( "smiliescomments") == 'yes' ) 
		$this->doSmilies($data['comment']['body']);

    // *******************************************
	// relative comment id 
    // *******************************************
	$pos=strpos($data['comment']['body'],'<p>');
	if ($pos===false) {
	    $data['comment']['body']="<p id='cmmnt".strval($this->commentSeq)."'>".trim($data['comment']['body'])."</p>";
	    $data['comment']['body']=str_replace("</p></p>","</p>",$data['comment']['body']);
	} else {
	    $pos=strpos($data['comment']['body'],'>');
	    if ($pos!==false)
	      $data['comment']['body'] = substr($data['comment']['body'],0,$pos)." id='cmmnt".strval($this->commentSeq)."' ".substr($data['comment']['body'],$pos);
    }
  }

  function event_PreItem( $data){
      /* item id */
      $this->curItem = $data['item']->itemid;
      /* relative comment number */
      $this->commentSeq = 0;
      /* smileys */
      if ( $this->getOption( "smiliesarticles") == 'yes' ) {
        $this->doSmilies( $data['item']->body);
        $this->doSmilies( $data['item']->more);
      }
  } 
  
  function doSmilies( &$data)
  {
      $smileys = array( 
          ':wink:' => 'icon_wink.gif',
          ':lol:' => 'icon_lol.gif',
          ':cry:' => 'icon_cry.gif',
          ':evil:' => 'icon_evil.gif',
          ':twisted:' => 'icon_twisted.gif',
          ':roll:' => 'icon_rolleyes.gif',
          ':idea:' => 'icon_idea.gif',
          ':arrow:' => 'icon_arrow.gif',
          ':mrgreen:' => 'icon_mrgreen.gif',
          ':-)' => 'icon_smile.gif',
          ':)' => 'icon_smile.gif',
          ':-(' => 'icon_sad.gif',
          ':(' => 'icon_sad.gif',
          ';-)' => 'icon_wink.gif',
          ';)' => 'icon_wink.gif',
          ':!:' => 'icon_exclaim.gif',
          ':?:' => 'icon_question.gif',
          ':oops:' => 'icon_redface.gif',
          ':o' => 'icon_surprised.gif',
          ':-D' => 'icon_biggrin.gif',
          ':D' => 'icon_biggrin.gif',
          '8O' => 'icon_eek.gif',
          '8)' => 'icon_cool.gif',
          ':?' => 'icon_confused.gif',
          ':x' => 'icon_mad.gif',
          ':P' => 'icon_razz.gif',
          ':|' => 'icon_neutral.gif',
          );
      $url = $this->getAdminURL( ) . 'smiles/';
      $data = str_replace( '&quot;)', '")', $data);
      foreach ( $smileys as $smile => $img) {
          if ( $smile == ":oops:") {
              $data = str_replace( $smile, "<img src='" . $url . $img . "' alt='()'/>", $data);
          } else {
              $data = str_replace( $smile, "<img src='" . $url . $img . "' alt='" . $smile . "'/>", $data);
          } 
      } 
      $data = str_replace( '")', '&quot;)', $data);
  } 
  
  function doTemplateCommentsVar( &$item, &$comments, $type){
  	if ($type == 'basic') {
     	echo "\n".'<li id="comment'.$this->permacommentid.'"'.$this->class.'><address>[<a href="#comment'.$this->permacommentid.'" title="Comment Permalink">'.($this->commentSeq).'</a>]';
     } elseif ($type == 'votes') {
     	$votes = quickQuery("SELECT cup-cdown as result FROM ".sql_table("comment")." WHERE cnumber=".$this->permacommentid);
     	echo "<span id='votes".$this->permacommentid."'>$votes</span>";
     } elseif ($type == 'ban') {
     	global $CONF, $member;
     	if ($member->isAdmin() && $member->isLoggedIn()) {
     		echo "<a href='".$CONF['ActionURL']."?action=plugin&amp;name=FancyText&amp;todo=ban&amp;cid=".$this->permacommentid."'>ban</a> ";
     		echo "<a href='".$CONF['ActionURL']."?action=plugin&amp;name=FancyText&amp;todo=low10&amp;cid=".$this->permacommentid."'>-10</a> ";
     		echo "<a href='".$CONF['ActionURL']."?action=plugin&amp;name=FancyText&amp;todo=low5&amp;cid=".$this->permacommentid."'>-5</a> ";
     		echo "<a href='".$CONF['ActionURL']."?action=plugin&amp;name=FancyText&amp;todo=zero&amp;cid=".$this->permacommentid."'>0</a> ";
     		echo "<a href='".$CONF['ActionURL']."?action=plugin&amp;name=FancyText&amp;todo=high5&amp;cid=".$this->permacommentid."'>+5</a> ";
     	}
     }
  } 

  function createResponse($arr) {
	header('Content-Type: text/xml');
	echo "<?xml version='1.0' encoding='UTF-8' standalone='yes'?>\n";
	echo "<feed>\n";
	foreach ($arr as $name => $value) {
		echo "<response>\n";
		echo "<method>$name</method>\n";
		echo "<result>$value</result>\n";
		echo "</response>\n";
	}
	echo "</feed>\n";
  }
  
  function doAction($actionType) {
	$todo = getVar('todo');
	if ($todo == 'vote') {
  		// do the voting
		if ($this->cvotes == 'yes') {
  			$commentid = intPostVar('cid');
  			$votetype = postvar('votetype');
  			$ip = serverVar("REMOTE_ADDR");
  			// cannot vote for my own comment
  			$votes = quickQuery("SELECT cip as result FROM ".sql_table("comment")." WHERE cnumber=$commentid");
  			if ($votes == $ip) {
  				$arr = array (
  					"type" => "0",
  					"response" => $this->getOption('cown'),
  					"commentid" => $commentid
  				);
  				$this->createResponse($arr);
  				return;
  			}
  			// already voted?
  			$votes = quickQuery("SELECT count(*) as result FROM ".sql_table("cvotes")." WHERE commentid=$commentid AND ip='$ip'");
  			if ($votes == 0) {
  				if ($votetype == 'up' || $votetype == 'down' || $votetype == 'neutral') {
  					$votes = quickQuery("SELECT cup - cdown as result FROM ".sql_table("comment")." WHERE cnumber=$commentid");
  					/*
  					$up = quickQuery("SELECT count(*) as result FROM ".sql_table("cvotes")." WHERE ip='$ip' AND vote='+'");
  					$down = quickQuery("SELECT count(*) as result FROM ".sql_table("cvotes")." WHERE ip='$ip' AND vote='-'");
  					*/
  					// do not allow more than 200% negative votes per IP
  					if ( ($votes <= -10) /* || ($votetype == 'down' && ($down <= $up*3)) */ ) {
  						// no change
  						$arr = array (
  							"type" => "1",
  							"response" => $this->getOption('cok'),
  							"commentid" => $commentid,
  							"votes" => $votes
  						);
  						$this->createResponse($arr);
  						return;
  					}
  					if ($votetype == 'up') 
  						$vote="+"; 
  					elseif ($votetype == 'down') 
  						$vote="-";
  					else 
  						$vote='.';
  					sql_query("INSERT INTO ".sql_table("cvotes")." (commentid,ip,vote) VALUES ($commentid,'$ip','$vote')");
  					if ($votetype == 'up') {
  						sql_query("UPDATE ".sql_table("comment")." SET cup=cup+1 WHERE cnumber=$commentid");
  						$votes++;
  					} elseif ($votetype == 'down') {
  						sql_query("UPDATE ".sql_table("comment")." SET cdown=cdown+1 WHERE cnumber=$commentid");
  						$votes--;
  					}
  					
  					$itemid = quickQuery("SELECT citem as result FROM ".sql_table("comment")." WHERE cnumber=$commentid");
  					cleanItemSimple($itemid);
  					
  					$arr = array (
  						"type" => "1",
  						"response" => $this->getOption('cok'),
  						"commentid" => $commentid,
  						"votes" => $votes
  					);
  				} else {
  					$arr = array (
  						"type" => "0",
  						"response" => "Invalid request.",
  						"commentid" => $commentid
  					);
  				}
  			} else {
  				$arr = array (
  					"type" => "0",
  					"response" => $this->getOption('cvoted'),
  					"commentid" => $commentid
  				);
  			}
			$this->createResponse($arr);
  		} else {
  			$commentid = intPostVar('cid');
  			$arr = array (
  				"type" => "0",
  				"response" => $this->getOption('ctext'),
  				"commentid" => $commentid
  			);
  			$this->createResponse($arr);
  		}
  		
	}

	// ban this IP
  	if ($todo == 'ban') {
  		$commentid = intval(getVar('cid'));
  		// update votes
  		sql_query("UPDATE ".sql_table("comment")." SET cup=0, cdown=10 WHERE cnumber=$commentid");
  		// ban ip
  		global $DIR_PLUGINS;
		if (!is_dir($DIR_PLUGINS)) die('System is not configured properly');
  		$dir = $DIR_PLUGINS.'blacklist/blacklist_lib.php';
  		if (is_file($dir)) {
  			require($dir);
  			$ip = quickQuery("SELECT cip as result FROM ".sql_table("comment")." WHERE cnumber=$commentid");
  			pbl_suspectIP(-1,$ip);
  		}
  		
  		$itemid = quickQuery("SELECT citem as result FROM ".sql_table("comment")." WHERE cnumber=$commentid");
  		cleanItemSimple($itemid);
  		header('Location: ' . createItemLink($itemid)."#comment".$commentid);
	}

	// reset this comment
  	if ( ($todo == 'zero') || ($todo == 'low5') || ($todo == 'low10') || ($todo == 'high5')) {
  		$commentid = intval(getVar('cid'));
  		switch ($todo) {
  			case 'zero': $cup=0; $cdown=0; break;
  			case 'low5': $cup=0; $cdown=5; break;
  			case 'low10': $cup=0; $cdown=10; break;
  			case 'high5': $cup=5; $cdown=0; break;
  			default: $cup=0; $cdown=0; break;
  		}
  		sql_query("UPDATE ".sql_table("comment")." SET cup=$cup, cdown=$cdown WHERE cnumber=$commentid");
  		$itemid = quickQuery("SELECT citem as result FROM ".sql_table("comment")." WHERE cnumber=$commentid");
  		cleanItemSimple($itemid);
  		header('Location: ' . createItemLink($itemid)."#comment".$commentid);
	}

  }

} 
?>