244 lines
9.6 KiB
PHP
244 lines
9.6 KiB
PHP
<?php # A class for getting and sending Pingbacks
|
|
$HTTP_RAW_POST_DATA = trim($HTTP_RAW_POST_DATA);
|
|
if(!defined('JLOG_BASEPATH')) require_once('.'.DIRECTORY_SEPARATOR.'scripts'.DIRECTORY_SEPARATOR.'prepend.inc.php');
|
|
require_once(JLOG_BASEPATH.'scripts'.DIRECTORY_SEPARATOR.'ixr-library.inc.php');
|
|
require_once(JLOG_BASEPATH.'scripts'.DIRECTORY_SEPARATOR.'jlogHTTP_Request.php');
|
|
|
|
|
|
if(defined("JLOG_ADMIN") === false) {
|
|
function ping($args) {
|
|
|
|
$pingback = new Jlog_GetPingback(JLOG_DB_CONTENT, JLOG_DB_COMMENTS, JLOG_PATH, new_sid());
|
|
$pingback->get_ping($args);
|
|
if($pingback->validate()) {
|
|
$pingback->write_to_db();
|
|
return "Thanks for your ping.";
|
|
}
|
|
}
|
|
$server = new IXR_Server(array('pingback.ping' => 'ping'));
|
|
}
|
|
|
|
class Jlog_GetPingback {
|
|
|
|
var $errors = array(); // array
|
|
var $method = ""; // string
|
|
var $sourceURI = ""; // string
|
|
var $targetURI = array(); // array incl: orginal, parsed [array from parse_url()], y, m, url
|
|
var $title = ""; // string
|
|
var $sid = ""; // string
|
|
|
|
function Jlog_GetPingback($db_content, $db_comments, $path, $sid = NULL) {
|
|
$this->db_content = $db_content;
|
|
$this->db_comments = $db_comments;
|
|
$this->path = $path;
|
|
if($sid != NULL) $this->sid = $sid;
|
|
}
|
|
|
|
function get_ping($uris) {
|
|
|
|
$ymurls = array();
|
|
$tmp_host_got = "";
|
|
$tmp_host_path_parsed = array();
|
|
$tmp_host_path = "";
|
|
|
|
$this->sourceURI = trim($uris[0]);
|
|
$this->targetURI['orginal'] = trim(str_replace(array('"','<', '>', '&'), array('"', '<', '>', '&'), $uris[1]));
|
|
$this->targetURI['parsed'] = parse_url($this->targetURI['orginal']);
|
|
$tmp_host_got = str_replace('www.', '', $this->targetURI['parsed']['host']).$this->targetURI['parsed']['path'];
|
|
$tmp_host_path_parsed = parse_url($this->path);
|
|
$tmp_host_path = str_replace('www.', '', $tmp_host_path_parsed['host']).'/log.php';
|
|
|
|
if(!empty($this->targetURI['parsed']['query']) AND ($tmp_host_got == $tmp_host_path)) {
|
|
|
|
$ymurls = explode('&', $this->targetURI['parsed']['query']);
|
|
$this->_counter = count($ymurls);
|
|
|
|
foreach($ymurls AS $ymurl) {
|
|
if(substr($ymurl, 0, 2) == 'y=') $this->targetURI['y'] = substr($ymurl, 2);
|
|
elseif(substr($ymurl, 0, 2) == 'm=') $this->targetURI['m'] = substr($ymurl, 2);
|
|
elseif(substr($ymurl, 0, 4) == 'url=') $this->targetURI['url'] = substr($ymurl, 4);
|
|
}
|
|
}
|
|
else {
|
|
### Plugin Hook
|
|
global $plugins;
|
|
$tmp_URI = $plugins->callHook('xmlrpcPermalink', $this->targetURI['orginal']);
|
|
|
|
$regex = "#^".$this->path."/([0-9]{4})/?([0-9]{2})/?([a-z0-9_\-]+)$#";
|
|
preg_match($regex, $tmp_URI, $matches);
|
|
$this->targetURI['y'] = $matches[1];
|
|
$this->targetURI['m'] = $matches[2];
|
|
$this->targetURI['url'] = $matches[3];
|
|
}
|
|
|
|
}
|
|
|
|
function validate() {
|
|
|
|
|
|
if(!strpos($this->targetURI['orginal'], str_replace(array('http://', 'https://'), '', str_replace('www.', '', $this->path))))
|
|
$this->send_error(0, 'Target URI ('.$this->targetURI['orginal'].') is not this page: '.$this->path);
|
|
|
|
|
|
// is there such a post?
|
|
$sql = "SELECT id, allowpingback FROM ".$this->db_content." WHERE
|
|
YEAR(date) = '".escape_for_mysql($this->targetURI['y'])."' AND
|
|
MONTH(date) = '".escape_for_mysql($this->targetURI['m'])."' AND
|
|
url = '".escape_for_mysql($this->targetURI['url'])."' AND
|
|
section = 'weblog'
|
|
LIMIT 1";
|
|
$blog = new Query($sql);
|
|
if($blog->error()) $this->send_error(0, 'Could not read my database.');
|
|
$blogrow = $blog->fetch();
|
|
|
|
if($blog->numRows() != 1) $this->send_error(32, 'The specified target URI does not exist.'.$this->targetURI['orginal']);
|
|
if($blogrow['allowpingback'] === 0) $this->send_error(33, 'The specified target URI cannot be used as a target. It it is not a pingback-enabled resource.');
|
|
else $this->reference = $blogrow['id'];
|
|
|
|
$s =& new HTTP_Request($this->sourceURI);
|
|
if(PEAR::isError($s->sendRequest())) $this->send_error(16, 'The source URI does not exist.');
|
|
else {
|
|
$source = $s->getResponseBody();
|
|
$source = strip_tags(str_replace('<!DOCTYPE','<DOCTYPE', $source), '<title><a>');
|
|
|
|
if (!$this->isLinkInHTML($this->targetURI['orginal'], $source))
|
|
$this->send_error(17, 'The source URI does not contain a link to the target URI, and so cannot be used as a source.');
|
|
|
|
preg_match('|<title>([^<]*?)</title>|is', $source, $title);
|
|
|
|
if(! $utf8 = preg_match ('/charset\s*=\s*utf-8/i', $s->getResponseHeader("Content-Type")))
|
|
$utf8 = 'application/xhtml+xml' == strtolower(trim($s->getResponseHeader("Content-Type")));
|
|
|
|
// since text in database is utf8 encoded, we need to *en*code the title to utf8 if it isn't already, not *de*code it
|
|
$this->title = empty($title[1]) ? $this->sourceURI : html_entity_decode($utf8 ? $title[1] : utf8_encode($title[1]));
|
|
}
|
|
|
|
$sql = "SELECT COUNT(*) AS ping FROM ".$this->db_comments." WHERE
|
|
reference = '".escape_for_mysql($blogrow['id'])."' AND
|
|
homepage = '".escape_for_mysql($this->sourceURI)."' AND
|
|
name = '".escape_for_mysql($this->title)."' AND
|
|
type = 'pingback'
|
|
LIMIT 1";
|
|
$p = new Query($sql);
|
|
if($p->error()) $this->send_error(0, 'Could not read my database.');
|
|
$f = $p->fetch();
|
|
|
|
if($f['ping'] > 0) $this->send_error(48, 'The pingback has already been registered.');
|
|
|
|
if(count($this->errors) > 0) return false;
|
|
else return true;
|
|
}
|
|
|
|
function write_to_db() {
|
|
$sql = "INSERT INTO ".$this->db_comments." (
|
|
sid,
|
|
name,
|
|
homepage,
|
|
reference,
|
|
date,
|
|
type
|
|
)
|
|
VALUES (
|
|
'".escape_for_mysql($this->sid)."',
|
|
'".escape_for_mysql($this->title)."',
|
|
'".escape_for_mysql($this->sourceURI)."',
|
|
'".escape_for_mysql($this->reference)."',
|
|
NOW(),
|
|
'pingback'
|
|
)";
|
|
$ping = new Query($sql);
|
|
|
|
if($ping->error()) $this->send_error(0, 'Could not write to database.');
|
|
|
|
}
|
|
|
|
function send_error($nr, $string) {
|
|
$this->errors[] = $nr." ".$string;
|
|
$error = new IXR_Error($nr, $string);
|
|
$this->send_xml($error->getXml());
|
|
}
|
|
|
|
function get_errors() {
|
|
return $this->errors;
|
|
}
|
|
|
|
function send_xml($xml) {
|
|
header('Connection: close');
|
|
header('Content-Length: '.strlen($xml));
|
|
header('Content-Type: text/xml');
|
|
header('Date: '.date('r'));
|
|
echo $xml;
|
|
exit;
|
|
}
|
|
|
|
function isLinkInHTML($search, $html) {
|
|
preg_match_all('#<a[^>]+href\s*=\s*("([^"]+)"|\'([^\']+)\')[^>]*>(.+)</a>#Ui', $html, $matches);
|
|
$links = array_unique(array_merge($matches[2], $matches[3]));
|
|
|
|
foreach($links as $link) {
|
|
if($search === str_replace('&', '&', $link)) return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
}
|
|
|
|
class Jlog_SendPingback {
|
|
|
|
var $pageslinkedto = array();
|
|
var $useragent = "";
|
|
|
|
function Jlog_SendPingback($html, $pagelinkedfrom, $useragent) {
|
|
// neet to prevent & in url
|
|
$this->pagelinkedfrom = htmlspecialchars_decode($pagelinkedfrom);
|
|
$this->useragent = $useragent;
|
|
|
|
preg_match_all('#<a[^>]+href\s*=\s*("([^"]+)"|\'([^\']+)\')[^>]*>(.+)</a>#Ui', $html, $matches);
|
|
$pageslinkedto = array();
|
|
$pageslinkedto = array_unique(array_merge($matches[2], $matches[3]));
|
|
$count = count($pageslinkedto);
|
|
for($i = 0; $count > $i; $i++) {
|
|
if(substr($pageslinkedto[$i], 0, 4) !== "http") unset($pageslinkedto[$i]);
|
|
// htmlspecialchars_decode is easier than str_replace
|
|
else $pageslinkedto[$i] = htmlspecialchars_decode($pageslinkedto[$i]);
|
|
}
|
|
$this->pageslinkedto = $pageslinkedto;
|
|
}
|
|
|
|
function doPingbacks() {
|
|
foreach($this->pageslinkedto as $pagelinkedto) {
|
|
$feedback[] = $this->send($pagelinkedto);
|
|
}
|
|
return $feedback;
|
|
}
|
|
|
|
function send($pagelinkedto) {
|
|
|
|
$s =& new HTTP_Request($pagelinkedto);
|
|
if(PEAR::isError($s->sendRequest())) return $pagelinkedto." — Error: The source URI does not exist.";
|
|
else {
|
|
$xmlrpcserver = $s->getResponseHeader("X-Pingback");
|
|
if(!empty($xmlrpcserver));
|
|
else {
|
|
if(preg_match('<link rel="pingback" href="([^"]+)" ?/?>', $s->getResponseBody(), $matches)) {
|
|
$xmlrpcserver = $matches[1];
|
|
}
|
|
else return $pagelinkedto." — This is not a pingback-enabled resource.";
|
|
}
|
|
|
|
$client = new IXR_Client($xmlrpcserver);
|
|
$client->timeout = 3;
|
|
$client->useragent = $this->useragent;
|
|
|
|
// when set to true, this outputs debug messages by itself
|
|
$client->debug = false;
|
|
|
|
if (! $client->query('pingback.ping', $this->pagelinkedfrom, $pagelinkedto ) )
|
|
return $pagelinkedto." — Error: ".$client->getErrorMessage();
|
|
|
|
else return $pagelinkedto." — ".$client->getResponse();
|
|
}
|
|
}
|
|
|
|
}
|
|
?>
|