/** * Handle a pingback for an entry. * Also takes care of the speedlimit and spam. Assumes that the caller of this * function has already checked permissions! * * @param string $id ID of entry that got pinged * @param string $type type of that entry ('article' for stories, etc.) * @param string $url URL of the page that pinged us * @param string $oururl URL that got pinged on our site * @return object XML-RPC response */ function PNB_handlePingback($id, $type, $url, $oururl) { global $_CONF, $_TABLES, $PNB_ERROR; require_once 'HTTP/Request.php'; if (!isset($_CONF['check_trackback_link'])) { $_CONF['check_trackback_link'] = 2; } // handle pingbacks to articles on our own site $skip_speedlimit = false; if ($_SERVER['REMOTE_ADDR'] == $_SERVER['SERVER_ADDR']) { if (!isset($_CONF['pingback_self'])) { $_CONF['pingback_self'] = 0; // default: skip self-pingbacks } if ($_CONF['pingback_self'] == 0) { return new XML_RPC_Response(new XML_RPC_Value($PNB_ERROR['skipped'])); } elseif ($_CONF['pingback_self'] == 2) { $skip_speedlimit = true; } } COM_clearSpeedlimit($_CONF['commentspeedlimit'], 'pingback'); if (!$skip_speedlimit) { $last = COM_checkSpeedlimit('pingback'); if ($last > 0) { return new XML_RPC_Response(0, 49, sprintf($PNB_ERROR['speedlimit'], $last, $_CONF['commentspeedlimit'])); } } // update speed limit in any case COM_updateSpeedlimit('pingback'); if ($_SERVER['REMOTE_ADDR'] != $_SERVER['SERVER_ADDR']) { if ($_CONF['check_trackback_link'] & 4) { $parts = parse_url($url); if (empty($parts['host'])) { TRB_logRejected('Pingback: No valid URL', $url); return new XML_RPC_Response(0, 33, $PNB_ERROR['uri_invalid']); } else { $ip = gethostbyname($parts['host']); if ($ip != $_SERVER['REMOTE_ADDR']) { TRB_logRejected('Pingback: IP address mismatch', $url); return new XML_RPC_Response(0, 49, $PNB_ERROR['spam']); } } } } // See if we can read the page linking to us and extract at least // the page's title out of it ... $title = ''; $excerpt = ''; $req = new HTTP_Request2($url, HTTP_Request2::METHOD_GET); $req->setHeader('User-Agent', 'Geeklog/' . VERSION); try { $response = $req->send(); $status = $response->getStatus(); if ($status == 200) { $body = $response->getBody(); if ($_CONF['check_trackback_link'] & 3) { if (!TRB_containsBacklink($body, $oururl)) { TRB_logRejected('Pingback: No link to us', $url); $comment = TRB_formatComment($url); PLG_spamAction($comment, $_CONF['spamx']); return new XML_RPC_Response(0, 49, $PNB_ERROR['spam']); } } preg_match(':<title>(.*)</title>:i', $body, $content); if (empty($content[1])) { $title = ''; // no title found } else { $title = trim(COM_undoSpecialChars($content[1])); } if ($_CONF['pingback_excerpt']) { // Check which character set the site that sent the Pingback // is using $charset = 'ISO-8859-1'; // default, see RFC 2616, 3.7.1 $ctype = $response->getHeader('content-type'); $c = explode(';', $ctype); foreach ($c as $ct) { $ch = explode('=', trim($ct)); if (count($ch) === 2) { if (trim($ch[0]) === 'charset') { $charset = trim($ch[1]); break; } } } if (!empty($charset) && strcasecmp($charset, COM_getCharset()) !== 0) { if (function_exists('mb_convert_encoding')) { $body = @mb_convert_encoding($body, COM_getCharset(), $charset); } elseif (function_exists('iconv')) { $body = @iconv($charset, COM_getCharset(), $body); } // else: tough luck ... } $excerpt = PNB_makeExcerpt($body, $oururl); } // we could also run the rest of the other site's page // through the spam filter here ... } elseif ($_CONF['check_trackback_link'] & 3) { COM_errorLog("Pingback verification: Got HTTP response code " . $response->getStatus() . " when requesting {$url}"); return new XML_RPC_Response(0, 33, $PNB_ERROR['uri_invalid']); } } catch (HTTP_Request2_Exception $e) { if ($_CONF['check_trackback_link'] & 3) { // we were supposed to check for backlinks but didn't get the page COM_errorLog("Pingback verification: " . $e->getMessage() . " when requesting {$url}"); return new XML_RPC_Response(0, 33, $PNB_ERROR['uri_invalid']); } } // check for spam first $saved = TRB_checkForSpam($url, $title, '', $excerpt); if ($saved == TRB_SAVE_SPAM) { return new XML_RPC_Response(0, 49, $PNB_ERROR['spam']); } // save as a trackback comment $saved = TRB_saveTrackbackComment($id, $type, $url, $title, '', $excerpt); if ($saved == TRB_SAVE_REJECT) { return new XML_RPC_Response(0, 49, $PNB_ERROR['multiple']); } if (isset($_CONF['notification']) && in_array('pingback', $_CONF['notification'])) { TRB_sendNotificationEmail($saved, 'pingback'); } return new XML_RPC_Response(new XML_RPC_Value($PNB_ERROR['success'])); }
/** * Handles a trackback ping for an entry. * * Also takes care of the speedlimit and spam. Assumes that the caller of this * function has already checked permissions! * * Note: Error messages are XML-formatted and echo'd out directly, as they * are supposed to be processed by some sort of software. * * @param string $sid ID of entry that got pinged * @param string $type type of that entry ('article' for stories, etc.) * @return boolean true = success, false = an error occured * * P.S. "Critical" errors are rejected with a HTTP 403 Forbidden status code. * According to RFC2616, this status code means * "The server understood the request, but is refusing to fulfill it. * Authorization will not help and the request SHOULD NOT be repeated." * See http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.4.4 * */ function TRB_handleTrackbackPing($sid, $type = 'article') { global $_CONF, $_TABLES; // Note: Error messages are hard-coded in English since there is no way of // knowing which language the sender of the trackback ping may prefer. $TRB_ERROR = array('no_url' => 'No URL given.', 'rejected' => 'Multiple posts not allowed.', 'spam' => 'Spam detected.', 'speedlimit' => 'Your last trackback comment was %d seconds ago. This site requires at least %d seconds between trackback comments.', 'no_link' => 'Trackback rejected as you do not seem to link to us.'); // the speed limit applies to trackback comments, too if (isset($_CONF['trackbackspeedlimit'])) { $speedlimit = $_CONF['trackbackspeedlimit']; } else { $speedlimit = $_CONF['commentspeedlimit']; } COM_clearSpeedlimit($speedlimit, 'trackback'); $last = COM_checkSpeedlimit('trackback'); if ($last > 0) { TRB_sendTrackbackResponse(1, sprintf($TRB_ERROR['speedlimit'], $last, $speedlimit), 403, 'Forbidden'); TRB_logRejected('Speedlimit', $_POST['url']); return false; } // update speed limit now in any case COM_updateSpeedlimit('trackback'); if (isset($_POST['url'])) { // a URL is mandatory ... if (substr($_POST['url'], 0, 4) != 'http') { TRB_sendTrackbackResponse(1, $TRB_ERROR['no_url'], 403, 'Forbidden'); TRB_logRejected('No valid URL', $_POST['url']); return false; } // do spam check on the unfiltered post $result = TRB_checkForSpam($_POST['url'], $_POST['title'], $_POST['blog_name'], $_POST['excerpt']); if ($result == TRB_SAVE_SPAM) { TRB_sendTrackbackResponse(1, $TRB_ERROR['spam'], 403, 'Forbidden'); TRB_logRejected('Spam detected', $_POST['url']); return false; } if (!isset($_CONF['check_trackback_link'])) { $_CONF['check_trackback_link'] = 2; } if ($_CONF['check_trackback_link'] & 4) { $parts = parse_url($_POST['url']); if (empty($parts['host'])) { TRB_sendTrackbackResponse(1, $TRB_ERROR['no_url'], 403, 'Forbidden'); TRB_logRejected('No valid URL', $_POST['url']); return false; } else { $ip = gethostbyname($parts['host']); if ($ip != $_SERVER['REMOTE_ADDR']) { TRB_sendTrackbackResponse(1, $TRB_ERROR['spam'], 403, 'Forbidden'); TRB_logRejected('IP address mismatch', $_POST['url']); return false; } } } if ($_CONF['check_trackback_link'] & 3) { if (!TRB_linksToUs($sid, $type, $_POST['url'])) { TRB_sendTrackbackResponse(1, $TRB_ERROR['no_link'], 403, 'Forbidden'); $comment = TRB_formatComment($_POST['url'], $_POST['title'], $_POST['blog_name'], $_POST['excerpt']); PLG_spamAction($comment, $_CONF['spamx']); TRB_logRejected('No link to us', $_POST['url']); return false; } } $saved = TRB_saveTrackbackComment($sid, $type, $_POST['url'], $_POST['title'], $_POST['blog_name'], $_POST['excerpt']); if ($saved == TRB_SAVE_REJECT) { TRB_sendTrackbackResponse(1, $TRB_ERROR['rejected'], 403, 'Forbidden'); TRB_logRejected('Multiple Trackbacks', $_POST['url']); return false; } if (isset($_CONF['notification']) && in_array('trackback', $_CONF['notification'])) { TRB_sendNotificationEmail($saved, 'trackback'); } TRB_sendTrackbackResponse(0); return true; } else { TRB_sendTrackbackResponse(1, $TRB_ERROR['no_url']); TRB_logRejected('No URL', $_POST['url']); } return false; }
/** * Handle a pingback for an entry. * Also takes care of the speedlimit and spam. Assumes that the caller of this * function has already checked permissions! * * @param string $id ID of entry that got pinged * @param string $type type of that entry ('article' for stories, etc.) * @param string $url URL of the page that pinged us * @param string $oururl URL that got pinged on our site * @return object XML-RPC response */ function PNB_handlePingback($id, $type, $url, $oururl) { global $_CONF, $_TABLES, $PNB_ERROR; require_once 'HTTP/Request.php'; if (!isset($_CONF['check_trackback_link'])) { $_CONF['check_trackback_link'] = 2; } // handle pingbacks to articles on our own site $skip_speedlimit = false; if ($_SERVER['REMOTE_ADDR'] == $_SERVER['SERVER_ADDR']) { if (!isset($_CONF['pingback_self'])) { $_CONF['pingback_self'] = 0; // default: skip self-pingbacks } if ($_CONF['pingback_self'] == 0) { return new XML_RPC_Response(new XML_RPC_Value($PNB_ERROR['skipped'])); } elseif ($_CONF['pingback_self'] == 2) { $skip_speedlimit = true; } } COM_clearSpeedlimit($_CONF['commentspeedlimit'], 'pingback'); if (!$skip_speedlimit) { $last = COM_checkSpeedlimit('pingback'); if ($last > 0) { return new XML_RPC_Response(0, 49, sprintf($PNB_ERROR['speedlimit'], $last, $_CONF['commentspeedlimit'])); } } // update speed limit in any case COM_updateSpeedlimit('pingback'); if ($_SERVER['REMOTE_ADDR'] != $_SERVER['SERVER_ADDR']) { if ($_CONF['check_trackback_link'] & 4) { $parts = parse_url($url); if (empty($parts['host'])) { TRB_logRejected('Pingback: No valid URL', $url); return new XML_RPC_Response(0, 33, $PNB_ERROR['uri_invalid']); } else { $ip = gethostbyname($parts['host']); if ($ip != $_SERVER['REMOTE_ADDR']) { TRB_logRejected('Pingback: IP address mismatch', $url); return new XML_RPC_Response(0, 49, $PNB_ERROR['spam']); } } } } // See if we can read the page linking to us and extract at least // the page's title out of it ... $title = ''; $excerpt = ''; $http = new http_class(); $http->timeout = 0; $http->data_timeout = 0; $http->debug = 0; $http->html_debug = 0; $http->user_agent = 'glFusion/' . GVERSION; $error = $http->GetRequestArguments($url, $arguments); $error = $http->Open($arguments); $error = $http->SendRequest($arguments); if ($error == "") { $http->ReadReplyHeaders($headers); if ($http->response_status == 200) { $error = $http->ReadWholeReplyBody($body); if ($error == "" || strlen($body) > 0) { if ($_CONF['check_trackback_link'] & 3) { if (!TRB_containsBacklink($body, $oururl)) { TRB_logRejected('Pingback: No link to us', $url); $comment = TRB_formatComment($url); PLG_spamAction($comment, $_CONF['spamx']); return new XML_RPC_Response(0, 49, $PNB_ERROR['spam']); } } preg_match(':<title>(.*)</title>:i', $body, $content); if (empty($content[1])) { $title = ''; // no title found } else { $title = trim(COM_undoSpecialChars($content[1])); } if ($_CONF['pingback_excerpt']) { // Check which character set the site that sent the Pingback // is using $charset = 'ISO-8859-1'; // default, see RFC 2616, 3.7.1 $ctype = $headers['content-type']; $c = explode(';', $ctype); foreach ($c as $ct) { $ch = explode('=', trim($ct)); if (count($ch) === 2) { if (trim($ch[0]) === 'charset') { $charset = trim($ch[1]); break; } } } if (!empty($charset) && strcasecmp($charset, COM_getCharset()) !== 0) { if (function_exists('mb_convert_encoding')) { $body = @mb_convert_encoding($body, COM_getCharset(), $charset); } elseif (function_exists('iconv')) { $body = @iconv($charset, COM_getCharset(), $body); } } $excerpt = PNB_makeExcerpt($body, $oururl); } // we could also run the rest of the other site's page // through the spam filter here ... } else { COM_errorLog("Pingback verification: unable to retrieve response body"); return new XML_RPC_Response(0, 33, $PNB_ERROR['uri_invalid']); } } else { COM_errorLog("Pingback verification: Got HTTP response code " . $http->response_status . " when requesting {$url}"); return new XML_RPC_Response(0, 33, $PNB_ERROR['uri_invalid']); } } else { COM_errorLog("Pingback verification: " . $error . " when requesting " . $url); return new XML_RPC_Response(0, 33, $PNB_ERROR['uri_invalid']); } // check for spam first $saved = TRB_checkForSpam($url, $title, '', $excerpt); if ($saved == TRB_SAVE_SPAM) { return new XML_RPC_Response(0, 49, $PNB_ERROR['spam']); } // save as a trackback comment $saved = TRB_saveTrackbackComment($id, $type, $url, $title, '', $excerpt); if ($saved == TRB_SAVE_REJECT) { return new XML_RPC_Response(0, 49, $PNB_ERROR['multiple']); } if (isset($_CONF['notification']) && in_array('pingback', $_CONF['notification'])) { TRB_sendNotificationEmail($saved, 'pingback'); } return new XML_RPC_Response(new XML_RPC_Value($PNB_ERROR['success'])); }
/** * Handle a pingback for an entry. * * Also takes care of the speedlimit and spam. Assumes that the caller of this * function has already checked permissions! * * @param string $id ID of entry that got pinged * @param string $type type of that entry ('article' for stories, etc.) * @param string $url URL of the page that pinged us * @param string $oururl URL that got pinged on our site * @return object XML-RPC response * */ function PNB_handlePingback($id, $type, $url, $oururl) { global $_CONF, $_TABLES, $PNB_ERROR; require_once 'HTTP/Request.php'; if (!isset($_CONF['check_trackback_link'])) { $_CONF['check_trackback_link'] = 2; } // handle pingbacks to articles on our own site $skip_speedlimit = false; if ($_SERVER['REMOTE_ADDR'] == $_SERVER['SERVER_ADDR']) { if (!isset($_CONF['pingback_self'])) { $_CONF['pingback_self'] = 0; // default: skip self-pingbacks } if ($_CONF['pingback_self'] == 0) { return new XML_RPC_Response(new XML_RPC_Value($PNB_ERROR['skipped'])); } else { if ($_CONF['pingback_self'] == 2) { $skip_speedlimit = true; } } } COM_clearSpeedlimit($_CONF['commentspeedlimit'], 'pingback'); if (!$skip_speedlimit) { $last = COM_checkSpeedlimit('pingback'); if ($last > 0) { return new XML_RPC_Response(0, 49, sprintf($PNB_ERROR['speedlimit'], $last, $_CONF['commentspeedlimit'])); } } // update speed limit in any case COM_updateSpeedlimit('pingback'); if ($_SERVER['REMOTE_ADDR'] != $_SERVER['SERVER_ADDR']) { if ($_CONF['check_trackback_link'] & 4) { $parts = parse_url($url); if (empty($parts['host'])) { TRB_logRejected('Pingback: No valid URL', $url); return new XML_RPC_Response(0, 33, $PNB_ERROR['uri_invalid']); } else { $ip = gethostbyname($parts['host']); if ($ip != $_SERVER['REMOTE_ADDR']) { TRB_logRejected('Pingback: IP address mismatch', $url); return new XML_RPC_Response(0, 49, $PNB_ERROR['spam']); } } } } // See if we can read the page linking to us and extract at least // the page's title out of it ... $title = ''; $excerpt = ''; $req = new HTTP_Request($url); $req->addHeader('User-Agent', 'glFusion/' . GVERSION); $response = $req->sendRequest(); if (PEAR::isError($response)) { if ($_CONF['check_trackback_link'] & 3) { // we were supposed to check for backlinks but didn't get the page COM_errorLog("Pingback verification: " . $response->getMessage() . " when requesting {$url}"); return new XML_RPC_Response(0, 33, $PNB_ERROR['uri_invalid']); } // else: silently ignore errors - we'll simply do without the title } else { if ($req->getResponseCode() == 200) { $body = $req->getResponseBody(); if ($_CONF['check_trackback_link'] & 3) { if (!TRB_containsBacklink($body, $oururl)) { TRB_logRejected('Pingback: No link to us', $url); $comment = TRB_formatComment($url); PLG_spamAction($comment, $_CONF['spamx']); return new XML_RPC_Response(0, 49, $PNB_ERROR['spam']); } } preg_match(':<title>(.*)</title>:i', $body, $content); if (empty($content[1])) { $title = ''; // no title found } else { $title = trim(COM_undoSpecialChars($content[1])); } if (isset($_CONF['pingback_excerpt']) && $_CONF['pingback_excerpt']) { $excerpt = PNB_makeExcerpt($body, $oururl); } // we could also run the rest of the other site's page // through the spam filter here ... } else { if ($_CONF['check_trackback_link'] & 3) { COM_errorLog("Pingback verification: Got HTTP response code " . $req->getResponseCode() . " when requesting {$url}"); return new XML_RPC_Response(0, 33, $PNB_ERROR['uri_invalid']); } } // else: silently ignore errors - we'll simply do without the title } // check for spam first $saved = TRB_checkForSpam($url, $title, '', $excerpt); if ($saved == TRB_SAVE_SPAM) { return new XML_RPC_Response(0, 49, $PNB_ERROR['spam']); } // save as a trackback comment $saved = TRB_saveTrackbackComment($id, $type, $url, $title, '', $excerpt); if ($saved == TRB_SAVE_REJECT) { return new XML_RPC_Response(0, 49, $PNB_ERROR['multiple']); } if (isset($_CONF['notification']) && in_array('pingback', $_CONF['notification'])) { TRB_sendNotificationEmail($saved, 'pingback'); } return new XML_RPC_Response(new XML_RPC_Value($PNB_ERROR['success'])); }