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 __construct($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'; }