Trackback
Client / Serveur de trackback.
Ce module se compose de deux classes instanciables,
un serveur de trackback (TrackbackServer) qui fournit une URL de ping pour le recensement des trackback,
et un client (TrackbackClient) permettant justement d'envoyer un ping signalant un trackback vers un serveur suivant le même protocole.
Ces classes implémentent les spécifications Movabletype
basées sur XML.
Le client nécessite l'extension curl pour envoyer des requètes HTTP.
Le stockage des trackback peut se faire grâce aux bases de données
Sqlite, MySQL ou PostgreSQL
via les classes d'abstraction présentes sur ce site.
PHP 5 powa
Les Méthodes
- TrackbackServer :: TrackbackServer - Nouvelle Instance
- TrackbackServer :: PingResponse - Répondre à un ping
- TrackbackServer :: GetTrackbackPings - Récupérer les tracback pour une ressource précise
- TrackbackServer :: GenerateRdfInfos - Générer des meta données RDF pour une ressource
- TrackbackServer :: CreateSqlTable - Créer la table SQL
- TrackbackClient :: TrackbackClient - Nouvelle Instance
- TrackbackClient :: SendTrackbackPing - Envoyer un ping
- TrackbackClient :: RetreiveTrackbackPings - Récupérer la liste des trackback d'une ressource distante
- TrackbackClient :: DiscoverTB - Récupérer l'url de ping d'une ressource proposant un trackback
Exemples
- Server -- Création de la table SQL
- Client -- Envoi d'un ping vers un serveur
- Client -- Récupérer la liste des trackback d'une ressource
- Server -- Répondre à un ping
La Source
<?php
// Repertoire d installation de la (ou des ) classe(s) d' abstraction
// pour la classe SQLite par exemple , le fichier source doit s apeller CLASS_DIR sqlite.php
// terminer par un slash /
define( 'CLASS_DIR' , './' );
/**
* @return
* @param $class Nom de la classe apellée et non declarée
* @desc Mécanisme de chargement automatique d'une classe selon son nom
* @comment Nécessite PHP 5
* @status PRIVATE
*/
function __autoload($class){
$source = CLASS_DIR . $class . '.php';
if(@is_readable($source)) {
@include_once($source);
} else {
echo 'Impossible d\' inclure le fichier : ' . $source;
exit;
}
}
// Abstraction class for both the client and the server
abstract class TrackbackBase {
// ALL DB
public $Base = 'scriptsphp_org_1';
public $Table = 'trackback';
// MySQL & PGsql
public $Host = 'localhost';
public $User = '';
public $Password = '';
public $Port = 3306;
// do not end with a slash
public $SiteUrl = 'http://classes.scriptsphp.net:81';
public $XmlEncoding = 'iso-8859-1';
public $Language = 'fr';
private $DbType = '';
public function __construct($dbtype = '') {
if($dbtype) {
$this->DbType = $dbtype;
$this->OA = new $this->DbType($this->Host, $this->User, $this->Password, $this->Base, $this->Port);
}
if($_POST) {
$_POST = array_map(array($this, 'Addslashes__'), $_POST);
}
}
public function __call($name, $arguments) {
return call_user_func_array( array($this->OA, $name), $arguments);
}
private function VerifyExtension($extension) {
if(!extension_loaded($extension)) {
if(!@dl($extension)) {
die($extension.' extension not loaded');
}
}
}
protected function Addslashes__($value) {
$value = trim($value);
if(get_magic_quotes_gpc()) {
return $value;
}
switch(strtolower($this->DbType)) {
case 'mysql' :
case 'sqlite' :
$func = $this->DbType.'_escape_string';
break;
case 'pgsql' :
$func = 'pg_escape_string';
break;
default :
$func = 'addslashes';
}
return $func($value);
}
}
/**************************************************************************************************/
// server
class TrackbackServer extends TrackbackBase {
// Default activation for the trackback
public $Active = 1;
public function PingResponse($ids = array()) {
if(in_array($_GET['id'], $ids)) {
if($_POST['url'] == '') {
return $this->XmlErrorResponse('Some parameters are not indicated');
}
// to perform
$sql = "SELECT 1 FROM $this->Table WHERE id = '$_GET[id]' AND url = '$_POST[url]' ";
if($this->num_rows($this->Send_Query($sql))) {
return $this->XmlErrorResponse('This trackback is aleady saved.');
}
$sql = "INSERT INTO $this->Table VALUES
('$_GET[id]',
'$_POST[title]',
'$_POST[url]',
'$_POST[excerpt]',
'$_POST[blog_name]',
$this->Active )";
if(!$this->Send_Query($sql)) {
return $this->XmlErrorResponse('SQL error , please retry later.');
}
} else {
return $this->XmlErrorResponse('Id does not exist');
}
// ping successfully
return '<?xml version="1.0"?><response><error>0</error></response>';
}
public function GetTrackbackPings($id) {
$sql = "SELECT title, url, excerpt, blog_name
FROM $this->Table
WHERE id = '$id' AND active = 1 ";
if(!$Result = $this->Send_Query($sql)) {
return $this->XmlErrorResponse('SQL error : ' . $this->return_error());
}
$i = 0;
$T = array();
while($O = $this->get_array($Result)) {
//while($O = sqlite_fetch_array($Result)) {
$T[$i]['title'] = $O['title'];
$T[$i]['url'] = $O['url'];
$T[$i]['excerpt'] = $O['excerpt'];
$T[$i]['blog_name'] = $O['blog_name'];
$i++;
}
return $this->MakeRssResponse($id, $T);
}
private function XmlErrorResponse($message) {
return '<?xml version="1.0" encoding="'.$this->XmlEncoding.'"?>
<response>
<error>1</error>
<message>'.$message.'</message>
</response>';
}
private function MakeRssResponse($id , $items = array()) {
$response = '
<response>
<error>0</error>
<rss version="2.0"><channel>
<title>trackback list</title>
<link>'.$this->SiteUrl.$_SERVER['PHP_SELF'].'</link>
<description>...</description>
<language>'.$this->Language.'</language>';
foreach($items as $key => $val) {
$response .= '<item>
<title>'.$val['title'].'</title>
<link>'.$val['url'].'</link>
<description>'.$val['excerpt'].'</description>
</item>';
}
$response .= '</channel></rss>
</response>';
return $response;
}
public function GenerateRdfInfos($title, $ressource , $pingurl) {
$return = '<!--
<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/">
<rdf:Description
rdf:about="'.$ressource.'"
dc:identifier="'.$ressource.'"
dc:title="'.$title.'"
trackback:ping="'.$pingurl.'" />
</rdf:RDF>
-->';
return $return;
}
public function CreateSqlTable($type = 'mysql') {
if(strtolower($type) == 'sqlite') {
$int = 'INTEGER';
} else {
$int = 'INT';
}
$sql = 'CREATE TABLE '.$this->Table.' (
id varchar(70),
title varchar(70),
url varchar(100),
excerpt varchar(255),
blog_name varchar(70),
active '.$int.'(1)
)';
if(!@$this->send_Query($sql)) {
echo ('SQL error , query create.'. $this->return_error());
} else echo 'DONE';
}
}// end class
/***************************************************************************************************/
// client
class TrackbackClient extends TrackbackBase {
public function __construct() {
$this->VerifyExtension('curl');
}
public function SendTrackbackPing($pingurl, $params, $timeout=0) {
$T = array();
foreach($params as $key => $val) {
$T[] = $key.'='.urlencode($val);
}
$ch = curl_init();
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, implode('&', $T));
curl_setopt($ch, CURLOPT_URL, $pingurl);
//curl_setopt($ch, CURLOPT_USERAGENT, $user_agent);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$result = curl_exec($ch);
curl_close($ch);
return $result;
}
public function ParsePingResponse($response) {
$this->VerifyExtension('simplexml');
return $response;
}
public function RetreiveTrackbackPings($pingurl) {
$ch = curl_init();
// URL Rewriting problems ...
curl_setopt($ch, CURLOPT_URL, $pingurl.'&__mode=rss');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$result = curl_exec($ch);
curl_close($ch);
//echo $result;
return $result;
}
public static function DiscoverTB($url) {
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_USERAGENT, 'TrackBack/1.0');
$result = curl_exec($ch);
curl_close($ch);
preg_match_all('!(<rdf:RDF.*?</rdf:RDF>)!s',$result,$reg);
foreach($reg[0] as $rdf) {
preg_match('!dc:identifier="([^"]+)"!s',$rdf,$regid);
if ($regid[1]!=$url) continue;
if (preg_match('!trackback:ping="([^"]+)"!s',$rdf,$regtb)) return $regtb[1];
elseif (preg_match('!about="([^"]+)"!s',$rdf,$regab)) return $regab[1];
}
}
}// end class
?>
// Repertoire d installation de la (ou des ) classe(s) d' abstraction
// pour la classe SQLite par exemple , le fichier source doit s apeller CLASS_DIR sqlite.php
// terminer par un slash /
define( 'CLASS_DIR' , './' );
/**
* @return
* @param $class Nom de la classe apellée et non declarée
* @desc Mécanisme de chargement automatique d'une classe selon son nom
* @comment Nécessite PHP 5
* @status PRIVATE
*/
function __autoload($class){
$source = CLASS_DIR . $class . '.php';
if(@is_readable($source)) {
@include_once($source);
} else {
echo 'Impossible d\' inclure le fichier : ' . $source;
exit;
}
}
// Abstraction class for both the client and the server
abstract class TrackbackBase {
// ALL DB
public $Base = 'scriptsphp_org_1';
public $Table = 'trackback';
// MySQL & PGsql
public $Host = 'localhost';
public $User = '';
public $Password = '';
public $Port = 3306;
// do not end with a slash
public $SiteUrl = 'http://classes.scriptsphp.net:81';
public $XmlEncoding = 'iso-8859-1';
public $Language = 'fr';
private $DbType = '';
public function __construct($dbtype = '') {
if($dbtype) {
$this->DbType = $dbtype;
$this->OA = new $this->DbType($this->Host, $this->User, $this->Password, $this->Base, $this->Port);
}
if($_POST) {
$_POST = array_map(array($this, 'Addslashes__'), $_POST);
}
}
public function __call($name, $arguments) {
return call_user_func_array( array($this->OA, $name), $arguments);
}
private function VerifyExtension($extension) {
if(!extension_loaded($extension)) {
if(!@dl($extension)) {
die($extension.' extension not loaded');
}
}
}
protected function Addslashes__($value) {
$value = trim($value);
if(get_magic_quotes_gpc()) {
return $value;
}
switch(strtolower($this->DbType)) {
case 'mysql' :
case 'sqlite' :
$func = $this->DbType.'_escape_string';
break;
case 'pgsql' :
$func = 'pg_escape_string';
break;
default :
$func = 'addslashes';
}
return $func($value);
}
}
/**************************************************************************************************/
// server
class TrackbackServer extends TrackbackBase {
// Default activation for the trackback
public $Active = 1;
public function PingResponse($ids = array()) {
if(in_array($_GET['id'], $ids)) {
if($_POST['url'] == '') {
return $this->XmlErrorResponse('Some parameters are not indicated');
}
// to perform
$sql = "SELECT 1 FROM $this->Table WHERE id = '$_GET[id]' AND url = '$_POST[url]' ";
if($this->num_rows($this->Send_Query($sql))) {
return $this->XmlErrorResponse('This trackback is aleady saved.');
}
$sql = "INSERT INTO $this->Table VALUES
('$_GET[id]',
'$_POST[title]',
'$_POST[url]',
'$_POST[excerpt]',
'$_POST[blog_name]',
$this->Active )";
if(!$this->Send_Query($sql)) {
return $this->XmlErrorResponse('SQL error , please retry later.');
}
} else {
return $this->XmlErrorResponse('Id does not exist');
}
// ping successfully
return '<?xml version="1.0"?><response><error>0</error></response>';
}
public function GetTrackbackPings($id) {
$sql = "SELECT title, url, excerpt, blog_name
FROM $this->Table
WHERE id = '$id' AND active = 1 ";
if(!$Result = $this->Send_Query($sql)) {
return $this->XmlErrorResponse('SQL error : ' . $this->return_error());
}
$i = 0;
$T = array();
while($O = $this->get_array($Result)) {
//while($O = sqlite_fetch_array($Result)) {
$T[$i]['title'] = $O['title'];
$T[$i]['url'] = $O['url'];
$T[$i]['excerpt'] = $O['excerpt'];
$T[$i]['blog_name'] = $O['blog_name'];
$i++;
}
return $this->MakeRssResponse($id, $T);
}
private function XmlErrorResponse($message) {
return '<?xml version="1.0" encoding="'.$this->XmlEncoding.'"?>
<response>
<error>1</error>
<message>'.$message.'</message>
</response>';
}
private function MakeRssResponse($id , $items = array()) {
$response = '
<response>
<error>0</error>
<rss version="2.0"><channel>
<title>trackback list</title>
<link>'.$this->SiteUrl.$_SERVER['PHP_SELF'].'</link>
<description>...</description>
<language>'.$this->Language.'</language>';
foreach($items as $key => $val) {
$response .= '<item>
<title>'.$val['title'].'</title>
<link>'.$val['url'].'</link>
<description>'.$val['excerpt'].'</description>
</item>';
}
$response .= '</channel></rss>
</response>';
return $response;
}
public function GenerateRdfInfos($title, $ressource , $pingurl) {
$return = '<!--
<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/">
<rdf:Description
rdf:about="'.$ressource.'"
dc:identifier="'.$ressource.'"
dc:title="'.$title.'"
trackback:ping="'.$pingurl.'" />
</rdf:RDF>
-->';
return $return;
}
public function CreateSqlTable($type = 'mysql') {
if(strtolower($type) == 'sqlite') {
$int = 'INTEGER';
} else {
$int = 'INT';
}
$sql = 'CREATE TABLE '.$this->Table.' (
id varchar(70),
title varchar(70),
url varchar(100),
excerpt varchar(255),
blog_name varchar(70),
active '.$int.'(1)
)';
if(!@$this->send_Query($sql)) {
echo ('SQL error , query create.'. $this->return_error());
} else echo 'DONE';
}
}// end class
/***************************************************************************************************/
// client
class TrackbackClient extends TrackbackBase {
public function __construct() {
$this->VerifyExtension('curl');
}
public function SendTrackbackPing($pingurl, $params, $timeout=0) {
$T = array();
foreach($params as $key => $val) {
$T[] = $key.'='.urlencode($val);
}
$ch = curl_init();
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, implode('&', $T));
curl_setopt($ch, CURLOPT_URL, $pingurl);
//curl_setopt($ch, CURLOPT_USERAGENT, $user_agent);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$result = curl_exec($ch);
curl_close($ch);
return $result;
}
public function ParsePingResponse($response) {
$this->VerifyExtension('simplexml');
return $response;
}
public function RetreiveTrackbackPings($pingurl) {
$ch = curl_init();
// URL Rewriting problems ...
curl_setopt($ch, CURLOPT_URL, $pingurl.'&__mode=rss');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$result = curl_exec($ch);
curl_close($ch);
//echo $result;
return $result;
}
public static function DiscoverTB($url) {
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_USERAGENT, 'TrackBack/1.0');
$result = curl_exec($ch);
curl_close($ch);
preg_match_all('!(<rdf:RDF.*?</rdf:RDF>)!s',$result,$reg);
foreach($reg[0] as $rdf) {
preg_match('!dc:identifier="([^"]+)"!s',$rdf,$regid);
if ($regid[1]!=$url) continue;
if (preg_match('!trackback:ping="([^"]+)"!s',$rdf,$regtb)) return $regtb[1];
elseif (preg_match('!about="([^"]+)"!s',$rdf,$regab)) return $regab[1];
}
}
}// end class
?>