pl_dir=FP_CONTENT.'plugin_commentcenter/'; if(!file_exists($this->pl_dir)) { fs_mkdir($this->pl_dir); } } /** * This function loads the configuration of the plugin. * * @param boolean $foce: Force to load it? * @return array: The configuration */ function getConf($force=false) { if(!empty($this->conf) && $force) { return $this->conf; } $this->conf=plugin_getoptions('commentcenter'); return $this->conf; } /** * This function check if comment must be locked. */ function lock() { global $fp_params, $post, $smarty; $this->loadPolicies(); $cats=is_array($post['categories']) ? $post['categories'] : array(); $behavoir=$this->behavoirFromPolicies($fp_params['entry'], $cats); if($behavoir==-1 && !user_loggedin()) { $smarty->assign('entry_commslock', true); } } /** * This function validates a comment. * * @param boolean $status: The current status of the comment validation * @param array $comment: The comment data * @return boolean: Is the comment valid? */ function validate($status, $comment) { global $smarty, $fp_params, $lang; # If the comment has been already stopped or this is the contact page, stop here our check if(!$status || function_exists('contact_display')) { return $status; } # If the comment has been made from an administrator, don't check it if(@$comment['loggedin']) { return true; } $entry=$fp_params['entry']; if (!isset($comment['date'])) { $comment['date'] = date_time(); } $comment['id']=bdb_idfromtime(BDB_COMMENT, $comment['date']); $conf=$this->getConf(); # This variables defines how the system has to behave. $behavoir=1; $this->loadPolicies(); # To get categories of the entry, we use the same method of PrettyURLs... global $post; $behavoir=$this->behavoirFromPolicies($entry, $post['categories']); // If comments are locked we don't send to Akismet if(@$conf['akismet_check'] && $behavoir!=-1) { $akismet=$this->akismetCheck($comment, $entry); if(!$akismet) { $smarty->append('error', $lang['plugin']['commentcenter']['akismet_error']); $this->logComment($comment, $entry, 'akismet'); return false; } } if($behavoir==0) { $this->logComment($comment, $entry, 'confirm'); $smarty->append('warnings', $lang['plugin']['commentcenter']['approvation']); if(@$conf['email_alert']) { $this->commentMail($comment, $post['subject']); } } elseif($behavoir==-1 && @$conf['log_all']) { $this->logComment($comment, $entry, 'denided'); $smarty->append('error', $lang['plugin']['commentcenter']['lock']); } if($behavoir!=1) { // Delete the comment content $_POST['content']=''; } # Also if the comment need to be approved, we return false. return $behavoir==1; } /** * This function create an akismet instance. * An Akismet object is returned by reference. But if an error * happens, the function return a negative integer: * -1 if we can't find the key * -2 if we can't contact Akismet servers * -3 if the response failed * -4 if the key isn't valid * * @param string $key: A key for the service * @return object: The akismet object */ function &akismetLoad($key='') { $conf=$this->getConf(); if(!empty($key)) { } elseif(empty($conf['akismet_key'])) { $e=-1; return $e; } else { $key=$conf['akismet_key']; } $url=empty($conf['akismet_url']) ? BLOG_BASEURL : $conf['akismet_url']; include_once dirname(__FILE__).'/inc/akismet.class.php'; $akismet=new Akismet($url, $key); if($akismet->errorsExist()) { $e=0; switch(true) { case $akismet->isError(AKISMET_SERVER_NOT_FOUND): $e=-2; break; case $akismet->isError(AKISMET_RESPONSE_FAILED): $e=-3; break; case $akismet->isError(AKISMET_INVALID_KEY): $e=-4; break; } return $e; } else { return $akismet; } } /** * This function clean a comment to send it to Akismet. * * @param array $comment: The comment data * @param string $entry: The entry id * @return array: $comment cleaned */ function akismetClean($comment, $entry) { global $post; $conf=$this->getConf(); $oldpost=$post; $o=new FPDB_Query("id:{$entry},fullparse:false", null); $arr=$o->getEntry(); $post=$arr[1]; $link=get_permalink($entry); if(!empty($conf['akismet_url'])) { $link=$conf['akismet_url'].substr($link, strlen(BLOG_BASEURL)); } $post=$oldpost; $clean=array( 'author'=>$comment['name'], 'email'=>@$comment['email'], 'website'=>@$comment['url'], 'body'=>$comment['content'], 'user_ip'=>@$comment['ip-address'], 'permalink'=>$link ); return $clean; } /** * This function manages the Akismet Check * * @param array $comment: The comment data * @param string $entry: The entry id * @return boolean: Is the comment allowed? */ function akismetCheck($comment, $entry) { $akismet=&$this->akismetLoad(); if(!is_object($akismet)) { # Failed to load it. We return true, but the comment isn't checked // TODO: Add an error logger? Or make different, configurable behaves? return true; } $clean=$this->akismetClean($comment, $entry); $akismet->setComment($clean); if($akismet->isSpam()) { # Akismet sign the comment as spam. Let's stop it. return false; } else { return true; } } /** * This function loads the comment policies. * * @param boolean $force: Force to load them? * @return array: The policies */ function &loadPolicies($force=false) { if(!$force && !empty($this->policies)) { return $this->policies; } if(!file_exists($f=$this->pl_dir.'policies.txt')) { $this->policies=array(); return $this->policies; } include $f; $this->policies=$policies; return $this->policies; } /** * This function saves the policies. * * @return boolean */ function savePolicies() { $this->policies=array_values($this->policies); return system_save($this->pl_dir.'policies.txt', array('policies'=>$this->policies)); } /** * This function adds a policy in a certain position. * * @param mixed $policy: The policy * @param integer $position: The position */ function addPolicyAt($policy, $position) { if($position<0) { $position=count($this->policies)+$position+1; } $before=array_slice($this->policies, 0, $position); $after=array_slice($this->policies, $position); $this->policies=array_merge($before, array($policy), $after); } /** * This function moves a policy from a postition to another one. * * @param integer $old: The old position * @param integer $new: The new position */ function policyMove($old, $new) { if(!isset($this->policies[$old])) { return false; } $new=$new>$old ? $new+1 : $new; $del=$new>$old ? $old : $old+1; $this->addPolicyAt($this->policies[$old], $new); if(isset($this->policies[$del])) { unset($this->policies[$del]); } $this->policies=array_values($this->policies); return true; } /** * Get behavoir from policies. * 1: The user can comment * 0: The comment need to be approved * -1: The user can't comment * * @param string $entry: The entry id * @param array $cats: The categories * @return integer: The behavoir */ function behavoirFromPolicies($entry, $cats=array()) { $date=date_from_id($entry); $time=$date['time']; $return=1; $pols=&$this->policies; if(count($pols)) { foreach($pols as $policy) { if(@$policy['is_all']) { $return=$policy['do']; } elseif(!empty($policy['entry']) && is_array($policy['entry'])) { if(in_array($entry, $policy['entry'])) { $return=$policy['do']; } } elseif(!empty($policy['entry'])) { if($entry==$policy['entry']) { $return=$policy['do']; } } else { $consider=true; if(!empty($policy['categories'])) { $consider=count(array_intersect($policy['categories'], $cats))>0; } if(!empty($policy['older'])) { $consider=(time()-$time)>$policy['older']; } else { if(!empty($policy['time_less'])) { $consider=$time>$policy['time_less']; } if(!empty($policy['time_more'])) { $consider=$time<$policy['time_more']; } } $return=$consider ? $policy['do'] : $return; } } } return $return; } /** * This function saves a comment into the plugin directory. * Maybe it's considered SPAM by Akismet or the comment requires * the Administrator's approvation. * * @param array $comment: The comment data * @param string $entry: The entry id * @param string $why: The reason of the log * @return boolean: Can it saves the log? */ function logComment($comment, $entry, $why='') { $f=$this->pl_dir."e{$entry}_c{$comment['id']}.txt"; if(!empty($why)) { $comment['log_reason']=$why; } return system_save($f, array('comment'=>$comment)); } /** * This function send an email to the administrator with the comment data. * It's based on the code of comment.php * * @param array $comment: The comment data * @param string $entry_title: The title of the entry * @return boolean */ function commentMail($comment, $entry_title) { global $lang, $fp_config; $subject=$lang['plugin']['commentcenter']['mail_subj']; $subject=sprintf($subject, $fp_config['general']['title']); $comm_mail=empty($comment['email'])? '' : "<{$comment['email']}>"; $from_mail=$fp_config['general']['email']; $text=$lang['plugin']['commentcenter']['mail_text']; $text=str_replace(array('%toname%', '%fromname%', '%frommail%', '%entrytitle%', '%content%', '%blogtitle%' ), array($fp_config['general']['author'], $comment['name'], $comm_mail, $entry_title, $comment['content'], $fp_config['general']['title'] ), $text ); return @utils_mail($from_mail, $subject, $text); } } $GLOBALS['plugin_commentcenter']=new plugin_commentcenter(); /** * This class makes the list of comments that needs to be approved. */ class commentcenter_list extends fs_filelister { /** * This is the constructor of the class. * * @params string $dir: The directory to list */ function commentcenter_list($dir) { parent::__construct($dir); } function _checkFile($directory, $file) { if(fnmatch('eentry*.txt', $file)) { $entry=substr($file, 1, 18); $comment=substr($file, 21, 20); $this->_list[$entry][]=$comment; } return 0; } function toDetails($entry=null) { $list=array(); if(!is_null($entry) && @is_array($this->_list[$entry])) { foreach($this->_list[$entry] as $commentid) { include $this->_directory."/e{$entry}_c{$commentid}.txt"; if(empty($comment['log_reason'])) { $comment['log_reason']='nd'; } $list[$comment['log_reason']][$commentid]=$comment; } } else { foreach($this->_list as $key=>$comments) { $list[$key]=$this->toDetails($key); } } return $list; } } # If we're in administration area, we load admin panel if(defined('MOD_ADMIN_PANEL')) { include dirname(__FILE__).'/inc/admin.php'; include dirname(__FILE__).'/inc/jslang.php'; include dirname(__FILE__).'/inc/editor.php'; }