insertCode($tb_id);
break;
// Insert TrackBack URL
case 'tburl':
case 'url':
echo $this->getTrackBackUrl($tb_id);
break;
// Insert manual ping URL
case 'form':
case 'manualpingformlink':
echo $this->getManualPingUrl($tb_id);
break;
// Insert TrackBack count
case 'count':
$count = $this->getTrackBackCount($tb_id);
switch ($count) {
case 0: echo TEMPLATE::fill($this->getOption('tplTbNone'), array('number' => $count)); break;
case 1: echo TEMPLATE::fill($this->getOption('tplTbOne'), array('number' => $count)); break;
default: echo TEMPLATE::fill($this->getOption('tplTbMore'), array('number' => $count)); break;
}
break;
// Shows the TrackBack list
case 'list':
case '':
$this->showList($tb_id);
break;
default:
return;
}
}
/*
* When used in templates, the tb_id will be determined by the itemid there
*/
function doTemplateVar(&$item, $what = '') {
$this->doSkinVar('template', $what, $item->itemid);
}
/*
* A trackback ping is to be received on the URL
* http://yourdomain.com/item/1234.trackback
* Extra variables to be passed along are url, title, excerpt, blog_name
*/
function event_InitSkinParse(&$data) {
global $CONF, $itemid;
$format = requestVar('format');
if ($CONF['URLMode'] == 'pathinfo') {
if (preg_match('/(\/|\.)(trackback)(\/|$)/', serverVar('PATH_INFO'), $matches)) {
$format = $matches[2];
}
}
if ($format == 'trackback' && $data['type'] == 'item')
{
$errorMsg = $this->handlePing($itemid);
if ($errorMsg != '')
$this->xmlResponse($errorMsg);
else
$this->xmlResponse();
exit;
}
}
/*
* A trackback ping is to be received on the URL
* http://yourdomain.com/action.php?action=plugin&name=TrackBack&tb_id=1234
* Extra variables to be passed along are url, title, excerpt, blog_name
*/
function doAction($type)
{
global $CONF;
switch ($type) {
// When no action type is given, assume it's a ping
case '':
$errorMsg = $this->handlePing();
if ($errorMsg != '')
$this->xmlResponse($errorMsg);
else
$this->xmlResponse();
break;
// Manual ping
case 'ping':
$errorMsg = $this->handlePing();
if ($errorMsg != '')
$this->showManualPingError(intRequestVar('tb_id'), $errorMsg);
else
$this->showManualPingSuccess(intRequestVar('tb_id'));
break;
// Show manual ping form
case 'form':
$this->showManualPingForm(intRequestVar('tb_id'));
break;
// Detect trackback
case 'detect':
list($url, $title) =
$this->getURIfromLink(html_entity_decode(requestVar('tb_link')));
$url = addslashes($url);
$url = $this->_utf8_to_javascript($url);
$title = addslashes($title);
$title = $this->_utf8_to_javascript($title);
echo "tbDone('" . requestVar('tb_link') . "', '" . $url . "', '" . $title . "');";
break;
}
exit;
}
/**************************************************************************************
* OUTPUT
*/
/*
* Show a list of all trackbacks for this ID
*/
function showList($tb_id) {
global $manager, $blog, $CONF;
$res = mysql_query('
SELECT
url,
blog_name,
excerpt,
title,
UNIX_TIMESTAMP(timestamp) AS timestamp
FROM
'.sql_table('plugin_tb').'
WHERE
tb_id = '.$tb_id .' AND
block = 0
ORDER BY
timestamp ASC
');
$gVars = array(
'action' => $this->getTrackBackUrl($tb_id),
'form' => $this->getManualPingUrl($tb_id)
);
echo TEMPLATE::fill($this->getOption('tplHeader'), $gVars);
while ($row = mysql_fetch_array($res))
{
$row['blog_name'] = htmlspecialchars($row['blog_name']);
$row['title'] = htmlspecialchars($row['title']);
$row['excerpt'] = htmlspecialchars($row['excerpt']);
if (_CHARSET != 'UTF-8') {
$row['blog_name'] = $this->_utf8_to_entities($row['blog_name']);
$row['title'] = $this->_utf8_to_entities($row['title']);
$row['excerpt'] = $this->_utf8_to_entities($row['excerpt']);
}
$iVars = array(
'action' => $this->getTrackBackUrl($tb_id),
'form' => $this->getManualPingUrl($tb_id),
'name' => $row['blog_name'],
'title' => $row['title'],
'excerpt' => $row['excerpt'],
'url' => htmlspecialchars($row['url'], ENT_QUOTES),
'date' => htmlspecialchars(strftime($this->getOption('dateFormat'), $row['timestamp'] + ($blog->getTimeOffset() * 3600)), ENT_QUOTES)
);
echo TEMPLATE::fill($this->getOption('tplItem'), $iVars);
}
if (mysql_num_rows($res) == 0)
{
echo TEMPLATE::fill($this->getOption('tplEmpty'), $gVars);
}
echo TEMPLATE::fill($this->getOption('tplFooter'), $gVars);
}
/*
* Returns the TrackBack count for a TrackBack item
*/
function getTrackBackCount($tb_id) {
return quickQuery('SELECT COUNT(*) as result FROM ' . sql_table('plugin_tb') . ' WHERE tb_id='.$tb_id.' AND block = 0');
}
/**
* Returns the manual ping URL
*/
function getManualPingUrl($itemid) {
global $CONF;
return $CONF['ActionURL'] . '?action=plugin&name=TrackBack&type=form&tb_id='.$itemid;
}
/**
* Show the manual ping form
*/
function showManualPingError($itemid, $status = '') {
global $CONF;
$form = true; $error = true; $success = false;
sendContentType('text/html', 'admin-trackback', _CHARSET);
include ($this->getDirectory() . '/templates/form.html');
}
function showManualPingSuccess($itemid, $status = '') {
global $CONF;
$form = false; $error = false; $success = true;
sendContentType('text/html', 'admin-trackback', _CHARSET);
include ($this->getDirectory() . '/templates/form.html');
}
function showManualPingForm($itemid, $text = '') {
global $CONF;
$form = true; $error = false; $success = false;
// Check if we are allowed to accept pings
if ($this->getOption('AcceptPing') == 'no') {
$text = 'Sorry, no trackback pings are accepted';
$form = false; $error = true;
}
sendContentType('text/html', 'admin-trackback', _CHARSET);
include ($this->getDirectory() . '/templates/form.html');
}
/**
* Returns the trackback URL
*/
function getTrackBackUrl($itemid) {
global $CONF;
return $CONF['ActionURL'] . '?action=plugin&name=TrackBack&tb_id='.$itemid;
}
/*
* Insert RDF code for item
*/
function insertCode($itemid) {
global $manager, $CONF;
$item = & $manager->getItem($itemid, 0, 0);
$blog = & $manager->getBlog(getBlogIDFromItemID($item['itemid']));
$CONF['ItemURL'] = preg_replace('/\/$/', '', $blog->getURL());
$uri = createItemLink($item['itemid'],'');
$title = strip_tags($item['title']);
$desc = strip_tags($item['body']);
$desc = $this->_cut_string($desc, 200);
$desc = htmlspecialchars($desc, ENT_QUOTES);
?>
getItem($tb_id, 0, 0);
if($item)
{
$blog =& $manager->getBlog(getBlogIDFromItemID($item['itemid']));
$blog_name = $blog->getName();
$title = $item['title'];
$excerpt = $item['body'];
if (_CHARSET != 'UTF-8')
{
$title = $this->_convert_to_utf8($title, $encoding);
$excerpt = $this->_convert_to_utf8($excerpt, $encoding);
$blog_name = $this->_convert_to_utf8($blog_name, $encoding);
}
$title = $this->_decode_entities(strip_tags($title));
$excerpt = $this->_decode_entities(strip_tags($excerpt));
$blog_name = $this->_decode_entities(strip_tags($blog_name));
$excerpt = $this->_cut_string($excerpt, 200);
$CONF['ItemURL'] = preg_replace('/\/$/', '', $blog->getURL());
$url = createItemLink($item['itemid'],'');
// Use UTF-8 charset for output
header('Content-Type: text/xml');
echo "<","?xml version='1.0' encoding='UTF-8'?",">\n";
echo "\n";
echo "\t0 \n";
echo "\t\n";
echo "\t\t\n";
echo "\t\t\t".htmlspecialchars($title)." \n";
echo "\t\t\t ".htmlspecialchars($url)."\n";
echo "\t\t\t".htmlspecialchars($excerpt)." \n";
$query = 'SELECT url, blog_name, excerpt, title, UNIX_TIMESTAMP(timestamp) as timestamp FROM '.sql_table('plugin_tb').' WHERE tb_id='.$tb_id .' AND block = 0 ORDER BY timestamp DESC';
$res = mysql_query($query);
while ($o = mysql_fetch_object($res))
{
// No need to do conversion, because it is already UTF-8
$data = array (
'url' => htmlspecialchars($o->url),
'blogname' => htmlspecialchars($o->blog_name),
'timestamp' => strftime('%Y-%m-%d',$o->timestamp),
'title' => htmlspecialchars($o->title),
'excerpt' => htmlspecialchars($o->excerpt),
'tburl' => $this->getTrackBackUrl($tb_id)
);
echo "\n";
echo "\t\t\t- \n";
echo "\t\t\t\t
".$data['title']." \n";
echo "\t\t\t\t ".$data['url']."\n";
echo "\t\t\t\t".$data['excerpt']." \n";
echo "\t\t\t \n";
}
echo "\t\t \n";
echo "\t \n";
echo " ";
exit;
}
else
{
$this->xmlResponse(_ERROR_NOSUCHITEM);
}
}
/**************************************************************************************
* SENDING AND RECEIVING TRACKBACK PINGS
*/
/*
* Send a Trackback ping to another website
*/
function sendPing($itemid, $title, $url, $excerpt, $blog_name, $ping_url)
{
// 1. Check some basic things
if (!$this->canSendPing()) {
return 'You\'re not allowed to send pings';
}
if ($this->getOption('SendPings') == 'no') {
return 'Sending trackback pings is disabled';
}
if ($ping_url == '') {
return 'No ping URL';
}
// 2. Check if protocol is correct http URL
$parsed_url = parse_url($ping_url);
if ($parsed_url['scheme'] != 'http' || $parsed_url['host'] == '')
return 'Bad ping URL';
$port = ($parsed_url['port']) ? $parsed_url['port'] : 80;
// 3. Create contents
$content = 'title=' . urlencode( $title );
$content .= '&url=' . urlencode( $url );
$content .= '&excerpt=' . urlencode( $excerpt );
$content .= '&blog_name=' . urlencode( $blog_name );
$user_agent = 'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)';
// 4. Prepare HTTP request
$request = 'POST ' . $parsed_url['path'];
if ($parsed_url['query'] != '')
$request .= '?' . $parsed_url['query'];
$request .= " HTTP/1.1\r\n";
$request .= "Accept: */*\r\n";
$request .= "User-Agent: " . $user_agent . "\r\n";
$request .= "Host: " . $parsed_url['host'] . ":" . $port . "\r\n";
$request .= "Connection: Keep-Alive\r\n";
$request .= "Cache-Control: no-cache\r\n";
$request .= "Connection: Close\r\n";
$request .= "Content-Length: " . strlen( $content ) . "\r\n";
$request .= "Content-Type: application/x-www-form-urlencoded; charset="._CHARSET."\r\n";
$request .= "\r\n";
$request .= $content;
$socket = fsockopen( $parsed_url['host'], $port, $errno, $errstr );
if ( ! $socket )
return 'Could not send ping: '.$errstr.' ('.$errno.')';
// 5. Execute HTTP request
fputs($socket, $request);
// 6. Receive response
$result = '';
while (!feof($socket)) {
$result .= fgets($socket, 4096);
}
fclose($socket);
// instead of parsing the XML, just check for the error string
// [TODO] extract real error message and return that
if ( strstr($result,'1 ') )
return 'An error occurred: '.htmlspecialchars($result);
}
/*
* Handle a Trackback ping sent to this website
*/
function handlePing($tb_id = 0) {
global $manager;
// Check if we are allowed to accept pings
if ($this->getOption('AcceptPing') == 'no') {
return 'Sorry, no trackback pings are accepted';
}
// Defaults
$spam = false;
$link = false;
$block = true;
if ($tb_id == 0)
$tb_id = intRequestVar('tb_id');
$rss = requestVar('__mode') == 'rss';
if (!$tb_id) {
return 'TrackBack ID is missing (tb_id)';
}
if ((!$manager->existsItem($tb_id,0,0)) && ($this->getOption('CheckIDs') == 'yes')) {
return _NOSUCH_ITEM;
}
// 0. Check if we need to output the list as rss
if ($rss) {
$this->rssResponse($tb_id);
return;
}
// 1. Get attributes
$url = requestVar('url');
$title = requestVar('title');
$excerpt = requestVar('excerpt');
$blog_name = requestVar('blog_name');
if (!$url) {
return 'URL is missing (url)';
}
// 2. Conversion of encoding...
if (preg_match ("/;\s*charset=([^\n]+)/is", $_SERVER["CONTENT_TYPE"], $regs))
$encoding = strtoupper(trim($regs[1]));
else
$encoding = $this->_detect_encoding($excerpt);
$title = $this->_convert_to_utf8($title, $encoding);
$excerpt = $this->_convert_to_utf8($excerpt, $encoding);
$blog_name = $this->_convert_to_utf8($blog_name, $encoding);
$title = $this->_decode_entities(strip_tags($title));
$excerpt = $this->_decode_entities(strip_tags($excerpt));
$blog_name = $this->_decode_entities(strip_tags($blog_name));
// 4. Save data in the DB
$res = @mysql_query('
SELECT
block
FROM
'.sql_table('plugin_tb').'
WHERE
url = "'.addslashes($url).'" AND
tb_id = "'.$tb_id.'"
');
if (mysql_num_rows($res) != 0)
{
// Existing TB, update it
$row = mysql_fetch_row($res);
$block = $row[0] == 1;
$res = @mysql_query('
UPDATE
'.sql_table('plugin_tb').'
SET
title = "'.addslashes($title).'",
excerpt = "'.addslashes($excerpt).'",
blog_name = "'.addslashes($blog_name).'",
timestamp = '.mysqldate(time()).'
WHERE
url = "'.addslashes($url).'" AND
tb_id = "'.$tb_id.'"
');
if (!$res) {
return 'Could not update trackback data: '.mysql_error();
}
}
else
{
// 4. SPAM check
$spamcheck = array (
'type' => 'trackback',
'id' => $tb_id,
'title' => $title,
'excerpt' => $excerpt,
'blogname' => $blog_name,
'url' => $url,
'return' => true,
'live' => true,
/* Backwards compatibility with SpamCheck API 1*/
'data' => $url . ' ' . $title . ' ' . $excerpt . ' ' . $blog_name,
);
$manager->notify('SpamCheck', array ('spamcheck' => & $spamcheck));
if (isset($spamcheck['result']) && $spamcheck['result'] == true)
{
$spam = true;
}
// 5. Content check (TO DO)
$contents = $this->retrieveUrl ($url);
if (preg_match("/(".preg_quote($_SERVER["REQUEST_URI"], '/').")|(".preg_quote($_SERVER["SERVER_NAME"], '/').")/i", $contents)) {
$link = true;
}
// 6. Determine if Trackback is safe...
$block = $spam == true || $link == false;
// New TB, insert it
$query = '
INSERT INTO
'.sql_table('plugin_tb').'
SET
tb_id = "'.$tb_id.'",
block = "'.($block ? '1' : '0').'",
spam = "'.($spam ? '1' : '0').'",
link = "'.($link ? '1' : '0').'",
url = "'.addslashes($url).'",
title = "'.addslashes($title).'",
excerpt = "'.addslashes($excerpt).'",
blog_name = "'.addslashes($blog_name).'",
timestamp = '.mysqldate(time()).'
';
$res = @mysql_query($query);
if (!$res) {
return 'Could not save trackback data, possibly because of a double entry: ' . mysql_error() . $query;
}
}
// 7. Send notification e-mail if needed
if (($block == false || $this->getOption('NoNotifyBlocked') == 'no')
&& $this->getOption('Notify') == 'yes')
{
$destAddress = $this->getOption('NotifyEmail');
$vars = array (
'tb_id' => $tb_id,
'url' => $url,
'title' => $title,
'excerpt' => $excerpt,
'blogname' => $blog_name
);
$mailto_title = TEMPLATE::fill($this->notificationMailTitle, $vars);
$mailto_msg = TEMPLATE::fill($this->notificationMail, $vars);
global $CONF, $DIR_LIBS;
// make sure notification class is loaded
if (!class_exists('notification'))
include($DIR_LIBS . 'NOTIFICATION.php');
$notify = new NOTIFICATION($destAddress);
$notify->notify($mailto_title, $mailto_msg , $CONF['AdminEmail']);
}
return '';
}
function xmlResponse($errorMessage = '')
{
header('Content-Type: text/xml');
echo "<","?xml version='1.0' encoding='UTF-8'?",">\n";
echo "\n";
if ($errorMessage)
echo "\t1 \n\t",htmlspecialchars($errorMessage)," \n";
else
echo "\t0 \n";
echo " ";
exit;
}
/*
* Check if member may send ping (check if logged in)
*/
function canSendPing() {
global $member;
return $member->isLoggedIn() || $this->xmlrpc;
}
/**************************************************************************************
* EVENTS
*/
function event_SendTrackback($data) {
global $manager;
// Enable sending trackbacks for the XML-RPC API, otherwise we would
// get an error because the current user is not exactly logged in.
$this->xmlrpc = true;
$itemid = $data['tb_id'];
$item = &$manager->getItem($itemid, 0, 0);
if (!$item) return; // don't ping for draft & future
if ($item['draft']) return; // don't ping on draft items
// gather some more information, needed to send the ping (blog name, etc)
$blog =& $manager->getBlog(getBlogIDFromItemID($itemid));
$blog_name = $blog->getName();
$title = $data['title'] != '' ? $data['title'] : $item['title'];
$title = strip_tags($title);
$excerpt = $data['body'] != '' ? $data['body'] : $item['body'];
$excerpt = strip_tags($excerpt);
$excerpt = $this->_cut_string($excerpt, 200);
$CONF['ItemURL'] = preg_replace('/\/$/', '', $blog->getURL());
$url = createItemLink($itemid);
while (list(,$url) = each($data['urls'])) {
$res = $this->sendPing($itemid, $title, $url, $excerpt, $blog_name, $url);
if ($res) ACTIONLOG::add(WARNING, 'TrackBack Error:' . $res . ' (' . $url . ')');
}
}
function event_RetrieveTrackback($data) {
$res = mysql_query('
SELECT
url,
title,
UNIX_TIMESTAMP(timestamp) AS timestamp
FROM
'.sql_table('plugin_tb').'
WHERE
tb_id = '.$data['tb_id'].' AND
block = 0
ORDER BY
timestamp ASC
');
while ($row = mysql_fetch_array($res)) {
$trackback = array(
'title' => $row['title'],
'url' => $row['url'],
'ip' => ''
);
$data['trackbacks'][] = $trackback;
}
}
function event_BookmarkletExtraHead($data) {
global $NP_TB_URL;
list ($NP_TB_URL,) = $this->getURIfromLink(requestVar('loglink'));
}
function event_PrepareItemForEdit($data) {
if (!$this->getOption('AutoXMLHttp'))
{
// The space between body and more is to make sure we didn't join 2 words accidently....
$this->larray = $this->autoDiscovery($data['item']['body'].' '.$data['item']['more']);
}
}
/*
* After an item has been added to the database, send out a ping if requested
* (trackback_ping_url variable in request)
*/
function event_PostAddItem($data) {
$this->pingTrackback($data);
}
function event_PreUpdateItem($data) {
$this->pingTrackback($data);
}
/**
* Add trackback options to add item form/bookmarklet
*/
function event_AddItemFormExtras($data) {
global $NP_TB_URL;
?>
TrackBack
TrackBack Ping URL:
getOption('AutoXMLHttp'))
{
?>
Auto Discovered Ping URL's:
jsautodiscovery();
}
?>
TrackBack
TrackBack Ping URL:
getOption('AutoXMLHttp'))
{
?>
Auto Discovered Ping URL's:
jsautodiscovery();
}
else
{
if (count($this->larray) > 0)
{
?>
Auto Discovered Ping URL's:
larray).'" />';
$i = 0;
while (list($url, $title) = each ($this->larray))
{
echo ''.$title.' ';
$i++;
}
}
}
?>
getItem($itemid, 0, 0);
if (!$item) return; // don't ping for draft & future
if ($item['draft']) return; // don't ping on draft items
// gather some more information, needed to send the ping (blog name, etc)
$blog =& $manager->getBlog(getBlogIDFromItemID($itemid));
$blog_name = $blog->getName();
$title = $data['title'] != '' ? $data['title'] : $item['title'];
$title = strip_tags($title);
$excerpt = $data['body'] != '' ? $data['body'] : $item['body'];
$excerpt = strip_tags($excerpt);
$excerpt = $this->_cut_string($excerpt, 200);
$CONF['ItemURL'] = preg_replace('/\/$/', '', $blog->getURL());
$url = createItemLink($itemid);
// send the ping(s) (add errors to actionlog)
for ($i=0; $isendPing($itemid, $title, $url, $excerpt, $blog_name, $ping_urls[$i]);
if ($res) ACTIONLOG::add(WARNING, 'TrackBack Error:' . $res . ' (' . $ping_urls[$i] . ')');
}
}
/**************************************************************************************
* AUTO-DISCOVERY
*/
/*
* Auto-Discovery of TrackBack Ping URLs based on HTML story
*/
function autoDiscovery($text)
{
$links = $this->getPermaLinksFromText($text);
$result = array();
for ($i = 0; $i < count($links); $i++)
{
list ($url, $title) = $this->getURIfromLink($links[$i]);
if ($url != '')
$result[$url] = $title;
}
return $result;
}
/*
* Auto-Discovery of TrackBack Ping URLs based on single link
*/
function getURIfromLink($link)
{
// Check to see if the cache contains this link
$res = mysql_query('SELECT url, title FROM '.sql_table('plugin_tb_lookup').' WHERE link="'.$link.'"');
if ($row = mysql_fetch_array($res))
{
if ($row['title'] != '')
{
return array (
$row['url'], $row['title']
);
}
else
{
return array (
$row['url'], $row['url']
);
}
}
// Retrieve RDF
if (($rdf = $this->getRDFFromLink($link)) !== false)
{
// Get PING attribute
if (($uri = $this->getAttributeFromRDF($rdf, 'trackback:ping')) !== false)
{
// Get TITLE attribute
if (($title = $this->getAttributeFromRDF($rdf, 'dc:title')) !== false)
{
// Get CREATOR attribute
if (($author = $this->getAttributeFromRDF($rdf, 'dc:creator')) !== false)
{
$title = $author. ": " . $title;
}
$uri = $this->_decode_entities($uri);
$title = $this->_decode_entities($title);
// Store in cache
$res = mysql_query("INSERT INTO ".sql_table('plugin_tb_lookup')." (link, url, title) VALUES ('".addslashes($link)."','".addslashes($uri)."','".addslashes($title)."')");
return array (
$uri, $title
);
}
else
{
$uri = html_entity_decode($uri, ENT_COMPAT);
// Store in cache
$res = mysql_query("INSERT INTO ".sql_table('plugin_tb_lookup')." (link, url, title) VALUES ('".addslashes($link)."','".addslashes($uri)."','')");
return array (
$uri, $uri
);
}
}
}
// Store in cache
$res = mysql_query("INSERT INTO ".sql_table('plugin_tb_lookup')." (link, url, title) VALUES ('".addslashes($link)."','','')");
return array ('', '');
}
/*
* Detect links used in HTML code
*/
function getPermaLinksFromText($text)
{
$links = array();
if (preg_match_all('/]+)>/', $text, $array, PREG_SET_ORDER))
{
for ($i = 0; $i < count($array); $i++)
{
preg_match('/href="http:\/\/(.+)"/', $array[$i][1], $matches);
$links['http://'.$matches[1]] = 1;
}
}
return array_keys($links);
}
/*
* Retrieve RDF code from external link
*/
function getRDFFromLink($link)
{
if ($content = $this->getContents($link))
{
preg_match_all('/()/sm', $content, $rdfs, PREG_SET_ORDER);
if (count($rdfs) > 1)
{
for ($i = 0; $i < count($rdfs); $i++)
{
if (preg_match('|dc:identifier="'.preg_quote($link).'"|ms',$rdfs[$i][1]))
{
return $rdfs[$i][1];
}
}
}
else
{
// No need to check the identifier
return $rdfs[0][1];
}
}
return false;
}
/**
* Retrieve the contents of an external (X)HTML document
*/
function getContents($link) {
// Use cURL extention if available
if (function_exists("curl_init"))
{
// Make HEAD request
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $link);
curl_setopt($ch, CURLOPT_HEADER, true);
curl_setopt($ch, CURLOPT_NOBODY, true);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$headers = curl_exec($ch);
curl_close($ch);
// Check if the link points to a (X)HTML document
if (preg_match('/Content-Type: (text\/html|application\/xhtml+xml)/i', $headers))
{
return $this->retrieveUrl ($link);
}
return false;
}
else
{
return $this->retrieveUrl ($link);
}
}
/*
* Get a single attribute from RDF
*/
function getAttributeFromRDF($rdf, $attribute)
{
if (preg_match('/'.$attribute.'="([^"]+)"/', $rdf, $matches))
{
return $matches[1];
}
return false;
}
/**************************************************************************************/
/* Internal helper functions for dealing with external file retrieval */
function retrieveUrl ($url) {
if (function_exists('curl_init'))
{
// Set options
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_HEADER, 1);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_BINARYTRANSFER, 1);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
curl_setopt($ch, CURLOPT_TIMEOUT, 20);
// Retrieve response
$raw = curl_exec($ch);
$info = curl_getinfo($ch);
// Split into headers and contents
$headers = substr($raw, 0, $info['header_size']);
$contents = substr($raw, $info['header_size']);
curl_close($ch);
}
elseif ($fp = @fopen ($url, "r"))
{
$contents = fread($fp, 8192);
$headers = '';
fclose($fp);
}
// Next normalize the encoding to UTF8...
$contents = $this->_convert_to_utf8_auto($contents, $headers);
return $contents;
}
/**************************************************************************************/
/* Internal helper functions for dealing with encodings and entities */
var $entities_cp1251 = array (
'' => '€',
'' => '‚',
'' => 'ƒ',
'' => '„',
'
' => '…',
'' => '†',
'' => '‡',
'' => 'ˆ',
'' => '‰',
'' => 'Š',
'' => '‹',
'' => 'Œ',
'' => 'Ž',
'' => '‘',
'' => '’',
'' => '“',
'' => '”',
'' => '•',
'' => '–',
'' => '—',
'' => '˜',
'' => '™',
'' => 'š',
'' => '›',
'' => 'œ',
'' => 'ž',
'' => 'Ÿ',
);
var $entities_default = array (
'"' => '"',
'&' => '&',
''' => ''',
'<' => '<',
'>' => '>',
);
var $entities_latin = array (
' ' => ' ',
'¡' => '¡',
'¢' => '¢',
'£' => '£',
'¤' => '¤',
'¥' => '¥',
'¦' => '¦',
'§' => '§',
'¨' => '¨',
'©' => '©',
'ª' => 'ª',
'«' => '«',
'¬' => '¬',
'' => '',
'®' => '®',
'¯' => '¯',
'°' => '°',
'±' => '±',
'²' => '²',
'³' => '³',
'´' => '´',
'µ' => 'µ',
'¶' => '¶',
'·' => '·',
'¸' => '¸',
'¹' => '¹',
'º' => 'º',
'»' => '»',
'¼' => '¼',
'½' => '½',
'¾' => '¾',
'¿' => '¿',
'À' => 'À',
'Á' => 'Á',
'Â' => 'Â',
'Ã' => 'Ã',
'Ä' => 'Ä',
'Å' => 'Å',
'Æ' => 'Æ',
'Ç' => 'Ç',
'È' => 'È',
'É' => 'É',
'Ê' => 'Ê',
'Ë' => 'Ë',
'Ì' => 'Ì',
'Í' => 'Í',
'Î' => 'Î',
'Ï' => 'Ï',
'Ð' => 'Ð',
'Ñ' => 'Ñ',
'Ò' => 'Ò',
'Ó' => 'Ó',
'Ô' => 'Ô',
'Õ' => 'Õ',
'Ö' => 'Ö',
'×' => '×',
'Ø' => 'Ø',
'Ù' => 'Ù',
'Ú' => 'Ú',
'Û' => 'Û',
'Ü' => 'Ü',
'Ý' => 'Ý',
'Þ' => 'Þ',
'ß' => 'ß',
'à' => 'à',
'á' => 'á',
'â' => 'â',
'ã' => 'ã',
'ä' => 'ä',
'å' => 'å',
'æ' => 'æ',
'ç' => 'ç',
'è' => 'è',
'é' => 'é',
'ê' => 'ê',
'ë' => 'ë',
'ì' => 'ì',
'í' => 'í',
'î' => 'î',
'ï' => 'ï',
'ð' => 'ð',
'ñ' => 'ñ',
'ò' => 'ò',
'ó' => 'ó',
'ô' => 'ô',
'õ' => 'õ',
'ö' => 'ö',
'÷' => '÷',
'ø' => 'ø',
'ù' => 'ù',
'ú' => 'ú',
'û' => 'û',
'ü' => 'ü',
'ý' => 'ý',
'þ' => 'þ',
'ÿ' => 'ÿ',
);
var $entities_extended = array (
'Œ' => 'Œ',
'œ' => 'å',
'Š' => 'Š',
'š' => 'š',
'Ÿ' => 'Ÿ',
'ˆ' => 'ˆ',
'˜' => '˜',
'&esnp;' => ' ',
' ' => ' ',
' ' => ' ',
'' => '',
'' => '',
'' => '',
'' => '',
'–' => '–',
'—' => '—',
'‘' => '‘',
'’' => '’',
'‚' => '‚',
'“' => '“',
'”' => '”',
'„' => '„',
'†' => '†',
'‡' => '‡',
'‰' => '‰',
'‹' => '‹',
'›' => '›',
'€' => '€',
'ƒ' => 'ƒ',
'Α' => 'Α',
'Β' => 'Β',
'Γ' => 'Γ',
'Δ' => 'Δ',
'Ε' => 'Ε',
'Ζ' => 'Ζ',
'Η' => 'Η',
'Θ' => 'Θ',
'Ι' => 'Ι',
'Κ' => 'Κ',
'Λ' => 'Λ',
'Μ' => 'Μ',
'Ν' => 'Ν',
'Ξ' => 'Ξ',
'Ο' => 'Ο',
'Π' => 'Π',
'Ρ' => 'Ρ',
'Σ' => 'Σ',
'Τ' => 'Τ',
'Υ' => 'Υ',
'Φ' => 'Φ',
'Χ' => 'Χ',
'Ψ' => 'Ψ',
'Ω' => 'Ω',
'α' => 'α',
'β' => 'β',
'γ' => 'γ',
'δ' => 'δ',
'ε' => 'ε',
'ζ' => 'ζ',
'η' => 'η',
'θ' => 'θ',
'ι' => 'ι',
'κ' => 'κ',
'λ' => 'λ',
'μ' => 'μ',
'ν' => 'ν',
'ξ' => 'ξ',
'ο' => 'ο',
'π' => 'π',
'ρ' => 'ρ',
'ς' => 'ς',
'σ' => 'σ',
'τ' => 'τ',
'υ' => 'υ',
'φ' => 'φ',
'χ' => 'χ',
'ψ' => 'ψ',
'ω' => 'ω',
'ϑ' => 'ϑ',
'ϒ' => 'ϒ',
'ϖ' => 'ϖ',
'•' => '•',
'…' => '…',
'′' => '′',
'″' => '″',
'‾' => '‾',
'⁄' => '⁄',
'℘' => '℘',
'ℑ' => 'ℑ',
'ℜ' => 'ℜ',
'™' => '™',
'ℵ' => 'ℵ',
'←' => '←',
'↑' => '↑',
'→' => '→',
'↓' => '↓',
'↔' => '↔',
'↵' => '↵',
'⇐' => '⇐',
'⇑' => '⇑',
'⇒' => '⇒',
'⇓' => '⇓',
'⇔' => '⇔',
'∀' => '∀',
'∂' => '∂',
'∃' => '∃',
'∅' => '∅',
'∇' => '∇',
'∈' => '∈',
'∉' => '∉',
'∋' => '∋',
'∏' => '∏',
'∑' => '∑',
'−' => '−',
'∗' => '∗',
'√' => '√',
'∝' => '∝',
'∞' => '∞',
'∠' => '∠',
'∧' => '∧',
'∨' => '∨',
'∩' => '∩',
'∪' => '∪',
'∫' => '∫',
'∴' => '∴',
'∼' => '∼',
'≅' => '≅',
'≈' => '≈',
'≠' => '≠',
'≡' => '≡',
'≤' => '≤',
'≥' => '≥',
'⊂' => '⊂',
'⊃' => '⊃',
'⊄' => '⊄',
'⊆' => '⊆',
'⊇' => '⊇',
'⊕' => '⊕',
'⊗' => '⊗',
'⊥' => '⊥',
'⋅' => '⋅',
'⌈' => '⌈',
'⌉' => '⌉',
'⌊' => '⌊',
'⌋' => '⌋',
'〈' => '〈',
'〉' => '〉',
'◊' => '◊',
'♠' => '♠',
'♣' => '♣',
'♥' => '♥',
'♦' => '♦',
);
function _detect_encoding($string)
{
if (!ereg("[\x80-\xFF]", $string) && !ereg("\x1B", $string))
return 'US-ASCII';
if (!ereg("[\x80-\xFF]", $string) && ereg("\x1B", $string))
return 'ISO-2022-JP';
if (preg_match("/^([\x01-\x7F]|[\xC0-\xDF][\x80-\xBF]|[\xE0-\xEF][\x80-\xBF][\x80-\xBF])+$/", $string) == 1)
return 'UTF-8';
if (preg_match("/^([\x01-\x7F]|\x8E[\xA0-\xDF]|\x8F[xA1-\xFE][\xA1-\xFE]|[\xA1-\xFE][\xA1-\xFE])+$/", $string) == 1)
return 'EUC-JP';
if (preg_match("/^([\x01-\x7F]|[\xA0-\xDF]|[\x81-\xFC][\x40-\xFC])+$/", $string) == 1)
return 'Shift_JIS';
return 'ISO-8859-1';
}
function _convert_to_utf8($contents, $encoding)
{
$done = false;
if (!$done && function_exists('iconv'))
{
$result = @iconv($encoding, 'UTF-8//IGNORE', $contents);
if ($result)
{
$contents = $result;
$done = true;
}
}
if(!$done && function_exists('mb_convert_encoding'))
{
@mb_substitute_character('none');
$result = @mb_convert_encoding($contents, 'UTF-8', $encoding );
if ($result)
{
$contents = $result;
}
}
return $contents;
}
function _convert_to_utf8_auto($contents, $headers = '')
{
/* IN: string in unknown encoding, headers received during transfer
* OUT: string in UTF-8 encoding
*/
$str = substr($contents, 0, 4096);
$len = strlen($str);
$pos = 0;
$out = '';
while ($pos < $len)
{
$ord = ord($str[$pos]);
if ($ord > 32 && $ord < 128)
$out .= $str[$pos];
$pos++;
}
// Detection of encoding, check headers
if (preg_match ("/;\s*charset=([^\n]+)/is", $headers, $regs))
$encoding = strtoupper(trim($regs[1]));
// Then check meta inside document
if (preg_match ("/;\s*charset=([^\"']+)/is", $out, $regs))
$encoding = strtoupper(trim($regs[1]));
// Then check xml declaration
if (preg_match("/<\?xml.+encoding\s*=\s*[\"|']([^\"']+)[\"|']\s*\?>/i", $out, $regs))
$encoding = strtoupper(trim($regs[1]));
// Converts
return $this->_convert_to_utf8($contents, $encoding);
}
function _decode_entities($string)
{
/* IN: string in UTF-8 containing entities
* OUT: string in UTF-8 without entities
*/
/// Convert all hexadecimal entities to decimal entities
$string = preg_replace('/[Xx]([0-9A-Fa-f]+);/e', "''.hexdec('\\1').';'", $string);
// Deal with invalid cp1251 numeric entities
$string = strtr($string, $this->entities_cp1251);
// Convert all named entities to numeric entities
$string = strtr($string, $this->entities_default);
$string = strtr($string, $this->entities_latin);
$string = strtr($string, $this->entities_extended);
// Convert all numeric entities to UTF-8
$string = preg_replace('/([0-9]+);/e', "''.dechex('\\1').';'", $string);
$string = preg_replace('/[Xx]([0-9A-Fa-f]+);/e', "NP_Trackback::_hex_to_utf8('\\1')", $string);
return $string;
}
function _hex_to_utf8($s)
{
/* IN: string containing one hexadecimal Unicode character
* OUT: string containing one binary UTF-8 character
*/
$c = hexdec($s);
if ($c < 0x80) {
$str = chr($c);
}
else if ($c < 0x800) {
$str = chr(0xC0 | $c>>6) . chr(0x80 | $c & 0x3F);
}
else if ($c < 0x10000) {
$str = chr(0xE0 | $c>>12) . chr(0x80 | $c>>6 & 0x3F) . chr(0x80 | $c & 0x3F);
}
else if ($c < 0x200000) {
$str = chr(0xF0 | $c>>18) . chr(0x80 | $c>>12 & 0x3F) . chr(0x80 | $c>>6 & 0x3F) . chr(0x80 | $c & 0x3F);
}
return $str;
}
function _utf8_to_entities($string)
{
/* IN: string in UTF-8 encoding
* OUT: string consisting of only characters ranging from 0x00 to 0x7f,
* using numeric entities to represent the other characters
*/
$len = strlen ($string);
$pos = 0;
$out = '';
while ($pos < $len)
{
$ascii = ord (substr ($string, $pos, 1));
if ($ascii >= 0xF0)
{
$byte[1] = ord(substr ($string, $pos, 1)) - 0xF0;
$byte[2] = ord(substr ($string, $pos + 1, 1)) - 0x80;
$byte[3] = ord(substr ($string, $pos + 2, 1)) - 0x80;
$byte[4] = ord(substr ($string, $pos + 3, 1)) - 0x80;
$char_code = ($byte[1] << 18) + ($byte[2] << 12) + ($byte[3] << 6) + $byte[4];
$pos += 4;
}
elseif (($ascii >= 0xE0) && ($ascii < 0xF0))
{
$byte[1] = ord(substr ($string, $pos, 1)) - 0xE0;
$byte[2] = ord(substr ($string, $pos + 1, 1)) - 0x80;
$byte[3] = ord(substr ($string, $pos + 2, 1)) - 0x80;
$char_code = ($byte[1] << 12) + ($byte[2] << 6) + $byte[3];
$pos += 3;
}
elseif (($ascii >= 0xC0) && ($ascii < 0xE0))
{
$byte[1] = ord(substr ($string, $pos, 1)) - 0xC0;
$byte[2] = ord(substr ($string, $pos + 1, 1)) - 0x80;
$char_code = ($byte[1] << 6) + $byte[2];
$pos += 2;
}
else
{
$char_code = ord(substr ($string, $pos, 1));
$pos += 1;
}
if ($char_code < 0x80)
$out .= chr($char_code);
else
$out .= ''. str_pad($char_code, 5, '0', STR_PAD_LEFT) . ';';
}
return $out;
}
function _utf8_to_javascript($string)
{
/* IN: string in UTF-8 encoding
* OUT: string consisting of only characters ranging from 0x00 to 0x7f,
* using javascript escapes to represent the other characters
*/
$len = strlen ($string);
$pos = 0;
$out = '';
while ($pos < $len)
{
$ascii = ord (substr ($string, $pos, 1));
if ($ascii >= 0xF0)
{
$byte[1] = ord(substr ($string, $pos, 1)) - 0xF0;
$byte[2] = ord(substr ($string, $pos + 1, 1)) - 0x80;
$byte[3] = ord(substr ($string, $pos + 2, 1)) - 0x80;
$byte[4] = ord(substr ($string, $pos + 3, 1)) - 0x80;
$char_code = ($byte[1] << 18) + ($byte[2] << 12) + ($byte[3] << 6) + $byte[4];
$pos += 4;
}
elseif (($ascii >= 0xE0) && ($ascii < 0xF0))
{
$byte[1] = ord(substr ($string, $pos, 1)) - 0xE0;
$byte[2] = ord(substr ($string, $pos + 1, 1)) - 0x80;
$byte[3] = ord(substr ($string, $pos + 2, 1)) - 0x80;
$char_code = ($byte[1] << 12) + ($byte[2] << 6) + $byte[3];
$pos += 3;
}
elseif (($ascii >= 0xC0) && ($ascii < 0xE0))
{
$byte[1] = ord(substr ($string, $pos, 1)) - 0xC0;
$byte[2] = ord(substr ($string, $pos + 1, 1)) - 0x80;
$char_code = ($byte[1] << 6) + $byte[2];
$pos += 2;
}
else
{
$char_code = ord(substr ($string, $pos, 1));
$pos += 1;
}
if ($char_code < 0x80)
$out .= chr($char_code);
else
$out .= '\\u'. str_pad(dechex($char_code), 4, '0', STR_PAD_LEFT);
}
return $out;
}
function _cut_string($string, $dl = 0) {
$defaultLength = $dl > 0 ? $dl : $this->getOption('defaultLength');
if ($defaultLength < 1)
return $string;
$border = 6;
$count = 0;
$lastvalue = 0;
for ($i = 0; $i < strlen($string); $i++)
{
$value = ord($string[$i]);
if ($value > 127)
{
if ($value >= 192 && $value <= 223)
$i++;
elseif ($value >= 224 && $value <= 239)
$i = $i + 2;
elseif ($value >= 240 && $value <= 247)
$i = $i + 3;
if ($lastvalue <= 223 && $value >= 223 &&
$count >= $defaultLength - $border)
{
return substr($string, 0, $i) . '...';
}
// Chinese and Japanese characters are
// wider than Latin characters
if ($value >= 224)
$count++;
}
elseif ($string[$i] == '/' || $string[$i] == '?' ||
$string[$i] == '-' || $string[$i] == ':' ||
$string[$i] == ',' || $string[$i] == ';')
{
if ($count >= $defaultLength - $border)
return substr($string, 0, $i) . '...';
}
elseif ($string[$i] == ' ')
{
if ($count >= $defaultLength - $border)
return substr($string, 0, $i) . '...';
}
if ($count == $defaultLength)
return substr($string, 0, $i + 1) . '...';
$lastvalue = $value;
$count++;
}
return $string;
}
/**************************************************************************************/
/* Plugin API calls, for installation, configuration and setup */
function getName() { return 'TrackBack'; }
function getAuthor() { return 'rakaz'; }
function getURL() { return 'http://www.rakaz.nl/'; }
function getVersion() { return '2.0.3'; }
function getDescription() { return 'Send trackbacks to other weblogs and receive tracbacks from others.'; }
function getTableList() { return array(sql_table("plugin_tb"), sql_table("plugin_tb_lookup")); }
function getEventList() { return array('QuickMenu','PostAddItem','AddItemFormExtras','EditItemFormExtras','PreUpdateItem','PrepareItemForEdit', 'BookmarkletExtraHead', 'RetrieveTrackback', 'SendTrackback', 'InitSkinParse'); }
function getMinNucleusVersion() { return 200; }
function supportsFeature($feature) {
switch($feature) {
case 'SqlTablePrefix':
return 1;
case 'HelpPage':
return 1;
default:
return 0;
}
}
function hasAdminArea() { return 1; }
function event_QuickMenu(&$data) {
global $member, $nucleus, $blogid;
// only show to admins
if (!$member->isLoggedIn() || !$member->isAdmin()) return;
array_push(
$data['options'],
array(
'title' => 'Trackback',
'url' => $this->getAdminURL(),
'tooltip' => 'Manage your trackbacks'
)
);
}
function install() {
$this->createOption('AcceptPing', 'Accept pings','yesno','yes');
$this->createOption('SendPings', 'Allow sending pings','yesno','yes');
$this->createOption('AutoXMLHttp', 'Auto-detect Trackback URLs as you type', 'yesno', 'yes');
$this->createOption('CheckIDs', 'Only allow valid itemids as trackback-ids','yesno','yes');
$this->createOption('tplHeader', 'Header', 'textarea', "\n\t
Trackback
\n\n");
$this->createOption('tplEmpty', 'Empty', 'textarea', "\t
\n\t\tThere are currently no trackbacks for this item.\n\t
\n\n");
$this->createOption('tplItem', 'Item', 'textarea', "\t
\n\t\t
<%name%>
\n\t\t
\n\t\t\t
<%title%>: <%excerpt%>\n\t\t
\n\t\t
\n\t\t\t<%date%>\n\t\t
\n\t
\n\n");
$this->createOption('tplFooter', 'Footer', 'textarea', "\t
\n\t\tUse this
TrackBack url to ping this item (right-click, copy link target).\n\t\tIf your blog does not support Trackbacks you can manually add your trackback by using
this form .\n\t
\n
");
$this->createOption('tplTbNone', 'Trackback count (none)', 'text', "No Trackbacks");
$this->createOption('tplTbOne', 'Trackback count (one)', 'text', "1 Trackback");
$this->createOption('tplTbMore', 'Trackback count (more)', 'text', "<%number%> Trackbacks");
$this->createOption('dateFormat', 'Date format', 'text', "%e/%m/%g");
$this->createOption('Notify', 'Send e-mail notification on ping receipt','yesno','no');
$this->createOption('NoNotifyBlocked', 'Don'."'".'t send e-mail notification for blocked pings','yesno','no');
$this->createOption('NotifyEmail', 'Which e-mail address to send these notification to?','text','');
$this->createOption('DropTable', 'Clear the database when uninstalling','yesno','no');
/* Create tables */
mysql_query("
CREATE TABLE IF NOT EXISTS
".sql_table('plugin_tb')."
(
`id` INT(11) NOT NULL AUTO_INCREMENT,
`tb_id` INT(11) NOT NULL,
`url` TEXT NOT NULL,
`block` TINYINT(4) NOT NULL,
`spam` TINYINT(4) NOT NULL,
`link` TINYINT(4) NOT NULL,
`title` TEXT,
`excerpt` TEXT,
`blog_name` TEXT,
`timestamp` DATETIME,
PRIMARY KEY (`id`)
)
");
mysql_query("
CREATE TABLE IF NOT EXISTS
".sql_table('plugin_tb_lookup')."
(
`link` TEXT NOT NULL,
`url` TEXT NOT NULL,
`title` TEXT,
PRIMARY KEY (`link` (100))
)
");
}
function uninstall() {
if ($this->getOption('DropTable') == 'yes') {
mysql_query ('DROP TABLE '.sql_table('plugin_tb'));
mysql_query ('DROP TABLE '.sql_table('plugin_tb_lookup'));
}
}
function init() {
$this->notificationMail = "Your weblog received a new trackback from <%blogname%> for ID <%tb_id%>. Below are the full details:\n\nURL:\t<%url%>\nTitle:\t<%title%>\nExcerpt:\t<%excerpt%>\nBlogname:\t<%blogname%>";
$this->notificationMailTitle = "New Trackback received for ID <%tb_id%>";
}
}
?>