'notify only the post author on new comments, uncheck to notify also administrators and editors', 'logfile'=>'log comment activity to file, useful for debugging comment spam together with the PostCommentDebug plugin', 'openid'=>'activate openid', 'openid_tmpdir' => 'temporary directory for openid storage', 'openid_default_host' => 'default openid server', 'openid_error_nourl' => 'the message to display when no OpenId URL is given', 'openid_error_urlinvalid' => 'the message to display when the URL is not a valid URL', 'openid_error_nocomment' => 'the message to display when no comment', 'openid_error_cancelled' => 'the message to display when openid cancelled', 'openid_error_failed' => 'the message to display when openid failure', 'openid_error_noemail' => 'the message to display when openid has not supplied email', 'openid_error_nonick' => 'the message to display when openid has not supplied nickname' ); var $default_context = 24; // LP_CONTEXT_POST | LP_CONTEXT_STATIC var $description = 'Manage posts comments'; var $active = true; var $hooks = array('parse_post'); var $logfile = ''; var $_logfile; var $_uniqid; var $errors; var $mail_post_author_only = false; // openid configuration var $openid = true; var $openid_tmpdir = '/tmp/openid'; var $openid_default_host = 'http://openid.blogs.es'; // openid error messages var $openid_error_nourl = 'The OpenID URL is empty. You have to input a valid URL'; var $openid_error_urlinvalid = 'The OpenID URL is not valid.'; var $openid_error_nocomment = 'The comment text is empty. You have to input a comment'; var $openid_error_cancelled = 'Openid error cancelled'; var $openid_error_failed = 'Openid error failed'; var $openid_error_noemail = 'Openid error failed: no email'; var $openid_error_nonick = 'Openid error failed: no nick'; var $_post; var $_comment_id; var $_wp_htmltranswinuni = array( '€' => '€', // the Euro sign '' => '', '‚' => '‚', // these are Windows CP1252 specific characters 'ƒ' => 'ƒ', // they would look weird on non-Windows browsers '„' => '„', '…' => '…', '†' => '†', '‡' => '‡', 'ˆ' => 'ˆ', '‰' => '‰', 'Š' => 'Š', '‹' => '‹', 'Œ' => 'Œ', '' => '', 'Ž' => 'ž', '' => '', '' => '', '‘' => '‘', '’' => '’', '“' => '“', '”' => '”', '•' => '•', '–' => '–', '—' => '—', '˜' => '˜', '™' => '™', 'š' => 'š', '›' => '›', 'œ' => 'œ', '' => '', 'ž' => '', 'Ÿ' => 'Ÿ'); function PostCommentOpenID(&$frontend, $args, $dummy_run=false) { $this->PostGenericAction($frontend, $args, $dummy_run); } function run($hook, &$post) { if (!empty($this->logfile)) { $f = @fopen($this->logfile, 'a'); if (is_resource($f)) { $this->_logfile =& $f; $this->_uniqid = strftime("%Y%m%d%H%M%S") . '_' . uniqid(); } } $this->_post =& $post; $this->_comment_id = null; $tpl =& $this->_frontend->tpl; $messages =& $this->_frontend->messages; $options =& $this->_frontend->options; $action =& $this->_action; session_start(); // a trackback? $trackback = ($action == 'trackback') ? true : false; $now = time(); if ($trackback) { $this->debug("trackback received", __LINE__); if ($post['ping_status'] != 'open') $this->trackback_error("Trackbacks closed for this post"); $tb_fields = array('title', 'excerpt', 'url', 'blog_name', 'charset'); $this->_bootstrap($post, '', true, false, $tb_fields); // check trackback $user_data =& $this->_user_data; if (empty($user_data['ud_url'])) $this->trackback_error("No URL in request vars"); if (!preg_match('/^[a-zA-Z]+:\/\//', $user_data['ud_url'])) $this->trackback_error("Incorrect URL format."); // fix encoding in received field values $tb_charset = strtoupper(trim($user_data['ud_charset'])); if (!empty($tb_charset) && function_exists('mb_convert_encoding') && $tb_charset != $options['charset']) { foreach ($tb_fields as $tb_var) $user_data[$tb_var] = mb_convert_encoding($user_data[$tb_var], $options['charset'], $tb_charset); } $comment = array( 'post_id'=>$this->_post['post_id'], 'date'=>$now, 'author'=>'Anonymous Trackback', 'email'=>'', 'url'=>$user_data['ud_url'], 'comment'=>$user_data['ud_excerpt'], 'type'=>'trackback', 'approved'=>'0'); if (!empty($user_data['ud_blog_name'])) $comment['author'] = $user_data['ud_blog_name']; if (!empty($user_data['ud_title'])) { $comment['comment'] = "{$user_data['ud_title']}{$comment['comment']}"; } $comment['comment'] = $this->wp_formatting($comment['comment']); $comment['post_tstamp'] = $post['post_tstamp']; $comment['post_permalink'] = $post['post_permalink']; $this->debug("inserting trackback", __LINE__); // TODO: build the comment array structure here, and pass it as a reference to insertComment // TODO: check query result $this->_frontend->insertComment($comment, true); $this->debug("sending notification", __LINE__); $this->sendNotification($comment); $this->trackback_success(); } else { $this->debug("comment received", __LINE__); $comment_add_block = $tpl->setBlock('index', 'comment_add', 'BLOCK_COMMENT_ADD', false); if ($post['skip_form']) { // we can't display the form as something else is happening // (eg the "send post to a friend" form) $tpl->setVar('PLUGIN_POSTCOMMENT', ' '); if ($comment_add_block) $tpl->setVar('BLOCK_COMMENT_ADD', $messages['comments_closed']); return; } if ($post['comment_status'] != 'open') { $this->debug("comment status closed", __LINE__, true); // comments are closed, let's hide the plugin's template tag $tpl->setVar('PLUGIN_POSTCOMMENT', ' '); // and change the link above the comennts list if ($comment_add_block) $tpl->setVar('BLOCK_COMMENT_ADD', $messages['comments_closed']); return; } if ($comment_add_block) $tpl->parse('BLOCK_COMMENT_ADD', 'comment_add'); $this->_bootstrap($post, $messages['comment_form_message']); // too lazy to add $this->_ to every variable $message =& $this->_message; $message_class =& $this->_message_class; $user_data =& $this->_user_data; $labels =& $this->_labels; // openid stuff if ($this->openid) { $path_extra = dirname(__FILE__); $path = ini_get('include_path'); $path = $path_extra . ':' . $path; ini_set('include_path', $path); require_once "Auth/OpenID/Consumer.php"; require_once "Auth/OpenID/FileStore.php"; $store_path = $this->openid_tmpdir; if (!file_exists($store_path) && !mkdir($store_path)) { exit(0); } $store = new Auth_OpenID_FileStore($store_path); $consumer = new Auth_OpenID_Consumer($store); if ($action == 'post_comment') { $error = ''; // Render a default page if we got a submission without an openid if (empty($user_data['ud_url'])) { $error = "Expected an OpenID URL."; $user_data['ud_label_url'] = $error; $message = $messages['comment_required_fields']; // . implode(", ", $empty_fields); $message_class = 'comment_form_warning'; $this->errors[] = $this->openid_error_nourl; } // Check if Openid url contains garbage //if ( !preg_match("|^(https?://)?([a-zA-Z_-/\.])*|i",$user_data['ud_url'],$matches)) { else if ( !preg_match("|^(https?://)?([a-z0-9A-Z\-\.\_/])*$|i",$user_data['ud_url'],$matches)) { $error = "OpenID invalid"; $this->errors[] = $this->openid_error_urlinvalid; } if (empty ($user_data['ud_text']) || trim( $user_data['ud_text']) == '' ) { $error = "No comment"; $user_data['ud_label_text'] = 'comment missing'; $message = $messages['comment_required_fields']; // . implode(", ", $empty_fields); $message_class = 'comment_form_warning'; $this->errors[] = $this->openid_error_nocomment; } $_SESSION['comment_text'] = $user_data["ud_text"]; $process_url = sprintf("%s/%s", $this->_frontend->options['url'], $post['post_permalink'] . '?action=finish' ); $trust_root = $this->_frontend->options['url']; // Begin the OpenID authentication process. $openid = $user_data['ud_url']; // Prepend the default openid host if it is not an url if (!strpos($openid,'.') && $this->openid_default_host ) { $openid = $this->openid_default_host . '/' . $openid; } if (!$error) { $auth_request = $consumer->begin($openid); } // Handle failure status return values. if (!$auth_request) { $this->errors[] = $this->openid_error_urlinvalid; } elseif (!$error) { $auth_request->addExtensionArg('sreg', 'required', 'nickname,email'); // Redirect the user to the OpenID server for authentication. Store // the token for this authentication so we can verify the response. $redirect_url = $auth_request->redirectURL($trust_root, $process_url); header("Location: ".$redirect_url); } } if ($action == 'finish') { // Complete the authentication process using the server's response. $response = $consumer->complete($_GET); if ($response->status == Auth_OpenID_CANCEL) { // This means the authentication was cancelled. $this->errors[] = $this->openid_error_cancelled; } else if ($response->status == Auth_OpenID_FAILURE) { $msg = "OpenID authentication failed: " . $response->message; $user_data["ud_label_url"] = $msg; $message = $messages['comment_required_fields']; // . implode(", ", $empty_fields); $message_class = 'comment_form_warning'; $this->errors[] = $this->openid_error_failed; } else if ($response->status == Auth_OpenID_SUCCESS) { // This means the authentication succeeded. $openid = $response->identity_url; $esc_identity = htmlspecialchars($openid, ENT_QUOTES); $sreg = $response->extensionResponse('sreg'); // TODO sanity checking of the incoming data : email and nickname $comment_text = $_SESSION['comment_text']; if (empty($sreg['nickname'])) { // Todo test for validity $this->errors[] = $this->openid_error_nonick; } else if (empty($sreg['email'])) { // Todo test for validity $this->errors[] = $this->openid_error_noemail; } else { $comment = array( 'post_id'=>$this->_post['post_id'], 'date'=>$now, 'author'=>$sreg['nickname'], 'email'=>$sreg['email'], 'url'=>$openid, 'comment'=>$this->wp_formatting($comment_text ), 'type'=>'', 'approved'=>'0'); $comment['post_tstamp'] = $post['post_tstamp']; $comment['post_permalink'] = $post['post_permalink']; $this->_frontend->insertComment($comment); $this->sendNotification($comment); // redirect user so that he does not insert the comment twice $this->_frontend->redirectToPost($post['post_permalink'], $messages['comment_accepted']); } } } } elseif ($action == 'post_comment') { $this->debug("handling comment submission", __LINE__); // check comment fields $empty_fields = array(); foreach (array('name', 'email', 'text') as $key) { if (empty($user_data["ud_$key"])) $empty_fields[] = $key; } if (count($empty_fields) == 0) { $comment = array( 'post_id'=>$this->_post['post_id'], 'date'=>$now, 'author'=>$user_data['ud_name'], 'email'=>$user_data['ud_email'], 'url'=>$user_data['ud_url'], 'comment'=>$this->wp_formatting($user_data['ud_text']), 'type'=>'', 'approved'=>'0'); $this->_frontend->insertComment($comment); //$this->sendNotification($comment); // check if we have to remove the user cookie if (!isset($_REQUEST['remember']) || $_REQUEST['remember'] != '1') $this->_frontend->removeUserCookie(); // redirect user so that he does not insert the comment twice $this->_frontend->redirectToPost($post['post_permalink'], $messages['comment_accepted']); } else { $this->debug("comment errors, redisplaying comment form", __LINE__, true); // we have errors, let's set warnings foreach ($empty_fields as $empty_field) $user_data["ud_label_$empty_field"] = "warning"; $message = $messages['comment_required_fields']; // . implode(", ", $empty_fields); $message_class = 'comment_form_warning'; } } // no action, let's set user data and display the form $this->debug("no action, redisplaying comment form", __LINE__, true); if($this->errors) { $show_errors = '
'; $tpl->setVar('PLUGIN_POSTCOMMENT_ERRORS', $show_errors); } else { $tpl->setVar('PLUGIN_POSTCOMMENT_ERRORS', ''); } $tpl->setVar($user_data); $tpl->setVar(array( 'comment_form_message' => $message, 'comment_form_message_class' => $message_class)); $tpl->setFile('plugin_postcomment', 'plugins/post_comment_openid.xml'); $tpl->parse('PLUGIN_POSTCOMMENT', 'plugin_postcomment'); } } function sendNotification(&$comment) { // TODO: check for approval status and mail sending options // TODO: use different templates based on approval status $this->debug("checking if we have to send a notification", __LINE__); $options =& $this->_frontend->options; // no comment inserted if (is_null($comment['id'])) return; // approval status switch ($comment['approved']) { case '1': // approved if (!$options['mail_on_comment']) return; break; case '0': case 'spam': if (!$options['comment_spam_mail']) return; } $this->debug("sending notification", __LINE__); $messages =& $this->_frontend->messages; $tpl =& $this->_frontend->tpl; $db =& $this->_frontend->db; $recipients = array(); $q = "select u.user_email from {$this->_frontend->tables['posts']} p inner join {$this->_frontend->tables['users']} u on p.post_author = u.id where p.id = {$this->_post['post_id']}"; if ($db->query($q)) $recipients[$db->get('user_email')] = ''; if (count($recipients) == 0 || !$this->mail_post_author_only) { $users =& $this->_frontend->getUserPerms(); foreach ($users as $user_id=>$user_data) { if ($user_data['user_level'] >= 3) $recipients[$user_data['user_email']] = ''; else if (isset($user_data['capabilities']['administrator']) || isset($user_data['capabilities']['editor'])) $recipients[$user_data['user_email']] = ''; } } $to = implode(', ', array_keys($recipients)); $this->debug("sending notification, recipients $to", __LINE__); $mh =& $this->_frontend->getMailHelper(); $this->debug("sending notification, got mail helper", __LINE__); $shortname = $mh->htent2qp($options['shortname']); $shortname_hdr = $mh->encoded2hdr($options['shortname']); $tpl->setVar(array( 'notify_shortname' => $shortname, 'notify_useremails' => $to, 'notify_post_title' => $mh->htent2qp($this->_post['post_title']), 'notify_post_name' => $mh->htent2qp($this->_post['post_name']), 'notify_post_permalink' => $mh->htent2qp($this->_post['post_permalink']), 'notify_comment_date' => $mh->htent2qp(strftime($options['date_format'], $comment['date'])), 'notify_comment_time' => $mh->htent2qp(strftime($options['time_format'], $comment['date'])), 'notify_comment_user' => $mh->htent2qp($comment['author']), 'notify_comment_email' => $mh->htent2qp($comment['email']), 'notify_comment_ip' => $_SERVER['REMOTE_ADDR'], 'notify_comment_agent' => $_SERVER['HTTP_USER_AGENT'], 'notify_comment_url' => $mh->htent2qp($comment['url']), 'notify_comment_id' => $comment['id'], 'notify_comment_type' => $comment['type'], 'notify_comment_approved' => $comment['approved'], 'notify_comment_text' => strip_tags($comment['comment']) )); $headers = array( 'Content-Type: text/plain; charset="' . $options['charset'] . '"', 'MIME-Version: 1.0', 'Content-Transfer-Encoding: quoted-printable', 'From: "'. $shortname_hdr . '" <' . $options['mail_from'] . '>'); $this->debug("sending notification, mail ready to send", __LINE__); if ($comment['approved'] == '1') $tpl->setFile('notify_email', 'plugins/post_comment_notification.txt'); else $tpl->setFile('notify_email', 'plugins/post_comment_notification_spam.txt'); $content = $tpl->parse('NOTIFY_EMAIL', 'notify_email', false, false); if (!$content) { $tpl->setFile('notify_email', 'plugins/post_comment_notification.txt'); $content = $tpl->parse('NOTIFY_EMAIL', 'notify_email'); } $title = "[$shortname_hdr] " . $this->_post['post_name'] . " " . $mh->encoded2hdr($messages['comment_mail_subject']) . ($comment['approved'] != '1' ? ' (spam)' : ''); $ret = $mh->send_mail($to, $title, $content, implode("\r\n", $headers)); $this->debug("sending notification, mail sent return $ret", __LINE__, true); return $ret; } function trackback_success() { $this->debug("trackback success", __LINE__, true); header('Content-Type: text/xml'); echo '_frontend->options['charset'] . '"?>' . "\n0\n"; exit; } function trackback_error($error="Error inserting trackback") { $this->debug("trackback error $error", __LINE__, true); header('Content-Type: text/xml'); echo '_frontend->options['charset'] . '"?>' . "\n1" . "" . htmlspecialchars($error, ENT_QUOTES) . "" . "\n"; exit; } function wp_formatting(&$text) { // stripped down version of WP's wp_formatting // will have to code this properly sooner or later... $output = ''; // Capture tags and everything inside them $textarr = preg_split("/(<[^>]+>)/s", $text, -1, PREG_SPLIT_DELIM_CAPTURE); $next = true; foreach ($textarr as $curl) { if (empty($curl)) continue; if ($curl[0] == '<') { if (strstr($curl, '_wp_htmltranswinuni); // Just a little XHTML help $output = str_replace('
', '
', $output); $output = str_replace('
', '
', $output); return $output; } function debug($message, $line, $close=false) { if (is_null($this->_logfile)) return; @fwrite($this->_logfile, "{$this->_uniqid} $line $message\r\n"); if ($close) { @fwrite($this->_logfile, "\r\n"); @fclose($this->_logfile); } } } ?>