You are not logged in. Login or Register for free.
Title only?
Strange sound and vision from here to the end of the world.
"We're fans first, journalists second."






  23 comments
  Email this



Posted on Monday, October 30th, 2006 23:56:43 GMT by: quietearth
Posted under: blog php pingback

Here's a tutorial (howto) on coding your own pingback mechanism for your blog using version 2.0 of the phpxmlrpc library available from sourceforge.

1. Receiving pingbacks
The pingback specs are available here:
http://www.hixie.ch/specs/pingback/pingback

When a client sends a pingback, it requests the page of the article being pinged and looks for either the X-Pingback header or a link the html header section of the page. This tells the client sending the pingback the url to actually send the pingback too. So first off we need to add these in to every page which serves articles.

This is part of the http header, so you need this before any html is served out:
header("X-Pingback: http://www.yoursite.com/pingback.php");
This is for the html header section:
<link rel="pingback" href="http://www.yoursite.com/pingback.php" />

The rest is simply making the pingback server itself. Here's the skeleton for pingback.php:
<?
header("Content-Type: application/xml");
require_once('/path/to/xmlrpc/lib/xmlrpc.inc');
require_once('/path/to/xmlrpc/lib/xmlrpcs.inc');

function pbprocess($m) {
        global $xmlrpcerruser;

        $x1 = $m->getParam(0);
        $x2 = $m->getParam(1);
        $source = $x1->scalarval(); # their article
        $dest = $x2->scalarval(); # your article

        # INSERT CODE
        # here we can check for valid urls in source and dest, security
        # lookup the dest article in our database etc.. 

        if (..) { # source uri does not exist
               return new xmlrpcresp(0, 16, "Source uri does not exist");
               }

        if (..) { # source uri does not have a link to target uri
               return new xmlrpcresp(0, 17, "Source uri does have link to target uri");
               }

        if (..) { # target uri does not exist
               return new xmlrpcresp(0, 32, "Target uri does not exist");
               }

        if (..) { # target uri cannot be used as target
               return new xmlrpcresp(0, 33, "Target uri cannot be used as target");
               }

        if (..) { # Pingback already registered
               return new xmlrpcresp(0, 48, "Target uri cannot be used as target");
               }

        if (..) { # Access denied
               return new xmlrpcresp(0, 49, "Access denied");
               }

        if (..) { # Could not communicate with upstream server or got error
               return new xmlrpcresp(0, 50, "Problem with upstream server");
               }

        if (..) { # Generic fault code if not applicable to above
               return new xmlrpcresp(0, 50, "Unkown error");
               }

        return new xmlrpcresp(new xmlrpcval("Pingback registered. May the force
be with you.", "string"));
        }

$a = array( "pingback.ping" => array( "function" => "pbprocess" ));

$s = new xmlrpc_server($a, false);
#$s->setdebug(3);
$s->service();
?>


The xmlrpc_server class from the xmlrpcphp module processes the post and uses pbprocess as a callback to return the data. From the pbprocess function we need to return a valid xmlrpcresp, and this gets passed off to the client. This is pretty straightforward. On a side note, I use the Access denied (error 49) as a generic error response in case none of the others fit.

2. Sending pingbacks
For sending pingbacks, we need to pass the entire text of a post put on the blog to a parsing routine. This routine send_pingback which is below, looks for all the html links and runs through each one of these pages looking for the X-Pingback header. (At this time I haven't implemented the html link reference.) If it finds this header, it will submit a pingback to the specified url.

<?
require_once('/path/to/xmlrpc/lib/xmlrpc.inc');

function do_send_pingback($myarticle, $url, $pdebug = 0) {
        $parts = parse_url($url);

        if (!isset($parts['scheme'])) {
                print "do_send_pingback: failed to get url scheme [".$url."]<br />\n";
                return(1);
                }
        if ($parts['scheme'] != 'http') {
                print "do_send_pingback: url scheme is not http [".$url."]<br />\n";
                return(1);
                }
        if (!isset($parts['host'])) {
                print "do_send_pingback: could not get host [".$url."]<br />\n";               
                return(1);
                }
        $host = $parts['host'];
        $port = 80;
        if (isset($parts['port'])) $port = $parts['port'];
        $path = "/";
        if (isset($parts['path'])) $path = $parts['path'];
        if (isset($parts['query'])) $path .="?".$parts['query'];
        if (isset($parts['fragment'])) $path .="#".$parts['fragment'];

        $fp = fsockopen($host, $port);
        fwrite($fp, "GET $path HTTP/1.0\r\nHost: $host\r\n\r\n");
        $response = "";
        while (is_resource($fp) && $fp && (!feof($fp))) {
                $response .= fread($fp, 1024);
                }
        fclose($fp);
        $lines = explode("\r\n", $response);
        foreach ($lines as $line) {
                if (ereg("X-Pingback: ", $line)) {
                        list($pburl) = sscanf($line, "X-Pingback: %s");
                        #print "pingback url is $pburl<br />\n";
                        }
                }

        if (empty($pburl)) {
                print "Could not get pingback url from [$url].<br />\n";
                return(1);
                }
        if (!isset($parts['scheme'])) {
                print "do_send_pingback: failed to get pingback url scheme [".$pburl."]<br />\n";
                return(1);
                }
        if ($parts['scheme'] != 'http') {
                print "do_send_pingback: pingback url scheme is not http[".$pburl."]<br />\n";
                return(1);
                }
        if (!isset($parts['host'])) {
                print "do_send_pingback: could not get pingback host [".$pburl."]<br />\n";
                return(1);
                }
        $host = $parts['host'];
        $port = 80;
        if (isset($parts['port'])) $port = $parts['port'];
        $path = "/";
        if (isset($parts['path'])) $path = $parts['path'];
        if (isset($parts['query'])) $path .="?".$parts['query'];
        if (isset($parts['fragment'])) $path .="#".$parts['fragment'];

        $m = new xmlrpcmsg("pingback.ping", array(new xmlrpcval($myarticle, "string"), new xmlrpcval($url, "string")));
        $c = new xmlrpc_client($path, $host, $port);
        $c->setRequestCompression(null);
        $c->setAcceptedCompression(null);
        if ($pdebug) $c->setDebug(2);
        $r = $c->send($m);
        if (!$r->faultCode()) {
                print "Pingback to $url succeeded.<br >\n";
                } else {
                $err = "code ".$r->faultCode()." message ".$r->faultString();
                print "Pingback to $url failed with error $err.<br >\n";
                }
        }

# call send_pingback() from your blog after adding a new post,
# $text will be the full text of your post
# $myurl will be the full url of your posting
function send_pingback($text, $myurl) {
        $m = array();
        preg_match_all ("/<a[^>]*href=[\"']([^\"']*)[\"'][^>]*>(.*?)<\/a>/i", $text, $m);
        $c = count($m[0]);
        for ($i = 0; $i < $c; $i++) {
                $ret = valid_url($m[1][$i]);
                if ($ret) do_send_pingback($myurl, $m[1][$i]);
                }
        }
?>


I have put up a page to allow you to test sending and receiving pingbacks from your blog:
http://www.quietearth.us/webtools

RSS Feed for comments

Comments

Hi! Thanks for sharing your ideas through your blog.

I've trying to implement your code in a hand-made blogging system, but I receive some errors. I see that at the final part of the ping sending part, you're using the post URL to send the request, so the XML client always receive the HTML code from the post as answer, not the XML pingback server response.

I've tried simply to add this line:

$parts = parse_url($pburl);

just after constructing the parameters for the call, and it works. I'm doing something wrong or was a mistake in the original code?

Thanks for your help & time ( and sorry about my poor english... :P )

Posted by: obokaman | January 15, 2007 08:57:07 am | permalink

Um... Where did u get the valid_url function?

Posted by: ikari | February 20, 2007 02:46:07 pm | permalink

user icon Sorry here's the valid_url code, it's not much in the way of security because it's you sending a pingback, not someone else:

function valid_url($url) {
if (!ereg('[()"'<>]', $url)) return(1);
return(0);
}

Posted by: quietearth | February 20, 2007 03:00:27 pm | permalink

Thanks,

This'll come in handy when adding the pingback class to the mindCMS

Posted by: Mindloop Webdesign | July 4, 2007 06:55:21 am | permalink

In the pingbacks.php, what goes in the "if (..)" portions of the script?

An example would be great for learning, thanks!

Posted by: Mike | August 6, 2007 10:54:37 pm | permalink

Sorry for the noob-i-ness, but shouldn't your valid_url() function be as follows:

function valid_url($url) {
if (!ereg('[()"'<>]', $url)) return(1);
return(0);
}

// Note the escaped ' character

Posted by: Mike | August 6, 2007 11:43:06 pm | permalink

Hi,
i have some questions. How pbprocess() function is call out. Can you give source code. Thanks

Posted by: Kestas | August 20, 2007 05:46:10 am | permalink

I found that function, but i have another problem. Script gives me 105 fault. What does it means, where can i find the problem?

Posted by: Kestas | August 20, 2007 07:23:37 am | permalink

user icon do you have the phpxmlrpc library installed and the paths for the requires set properly?

Posted by: quietearth | August 20, 2007 03:54:17 pm | permalink

I find that problem. It was some mistakes in code. Thanks for that great script :)

Posted by: Kestas | August 21, 2007 03:24:32 am | permalink

For some reason I am having troubles understanding how to get this to work. I mean you've done the skeleton of it but the little bits I'm currently stumped on.

You don't have a small working version I could take a look at do you?

Posted by: Tyler | October 16, 2007 08:56:19 am | permalink

hi,
i try to implement your code,,
when i try to pingback to my site, it said the pingback.php is forbiden,
i've chmod the pingback.php to 777

Posted by: snydez | December 5, 2007 12:05:59 am | permalink

Thanks for the code. I noticed that it was not working properly on sites that used x-header, but no html tag.. solution was that $parts needed to be reset to carry the values for the url provided by x-header:

foreach ($lines as $line) {
if (ereg("X-Pingback: ", $line)) {
list($pburl) = sscanf($line, "X-Pingback: %s");
$parts = parse_url($pburl);
//print "pingback url is $pburl<br />n";
}
}

Posted by: scott klarr | December 10, 2007 02:49:09 am | permalink

I wrote this yesterday to get the X-Pingback header value.

In: URL of site that you would like to get the X-Pingback header value from.
Out: URL of X-Pingback server.



function GetXPingback($sURL) {
$clSession = curl_init();
$iTimeout = 30;

curl_setopt ($clSession, CURLOPT_URL, $sURL);
curl_setopt ($clSession, CURLOPT_RETURNTRANSFER, 1);
curl_setopt ($clSession, CURLOPT_CONNECTTIMEOUT, $iTimeout);
curl_setopt ($clSession, CURLOPT_FOLLOWLOCATION, TRUE);
curl_setopt ($clSession, CURLOPT_HEADER, TRUE);
curl_setopt ($clSession, CURLOPT_NOBODY, TRUE);

$sScrape = curl_exec($clSession);
curl_close($clSession);

$sPingbackAddress = trim(TextBetween("X-Pingback: ", "n", $sScrape));

return $sPingbackAddress;
}

function TextBetween($s1,$s2,$s){
$s1 = strtolower($s1);
$s2 = strtolower($s2);
$L1 = strlen($s1);
$scheck = strtolower($s);
if($L1>0){$pos1 = strpos($scheck,$s1);} else {$pos1=0;}
if($pos1 !== false){
if($s2 == '') return substr($s,$pos1+$L1);
$pos2 = strpos(substr($scheck,$pos1+$L1),$s2);
if($pos2!==false) return substr($s,$pos1+$L1,$pos2);
}
return '';
}

Posted by: vivevtvivas | January 3, 2008 11:21:18 am | permalink

Thank you for this useful post and links to relevant tools. This page is now in my favorites!

Posted by: Lazar | February 8, 2008 05:14:17 pm | permalink

the other day I stumbled upon a pingback server/client implementation in php without the xmlrpc-bloat (see contact-url). I use the client in my blog, works flawlessly as far as I can tell.

Posted by: rio | February 18, 2008 07:54:34 am | permalink

I receive an error when I send pingback:

Pingback to http://some.url/ failed with error code 2 message Invalid return payload: enable debugging to examine incoming payload (XML error: > required at line 104, column 24).

Posted by: LukasS | March 1, 2008 11:28:23 am | permalink

okey, I remembe of this post fo future. $)

Posted by: Trezub | April 25, 2008 04:45:04 am | permalink

Hey!
Firstly, thanks for the tutorial. But I have the same problem as LukasS and I couldn't debug it.
My XML-RPC version is 2.2.1. Here is the error output:
XML error: not well-formed (invalid token) at line 8, column 35Pingback to http://xxx.com/foo.htm failed with error code 2 message Invalid return payload: enable debugging to examine incoming payload (XML error: not well-formed (invalid token) at line 8, column 35).
And there is my code: http://pastebin.com/m3a49fa67

Posted by: akifemre | May 25, 2008 03:10:35 am | permalink

I wrote a simple function for scanning a block of HTML and sending pingbacks to all of the links that it contained, without any libraries or includes. Link is in contact URL.

Posted by: Allan Wirth | June 24, 2008 11:12:19 pm | permalink

Get the X-Pingback value using a nice neat regex:

preg_match('/bX-Pingback: ([^s]+)/m', $sScrape , $match);

Where $match[1] will be your pingback server if it was present.

Posted by: Origin | October 3, 2008 05:12:40 am | permalink

Thank you so much !

I needed to create a response pingback server for my phpbb2 board. I allready had a pingback module but not the server. Your first snipplet helped me out !

Regards,

Ramon
http://www.ramonfincken.com

Posted by: Ramon Fincken | January 31, 2009 12:18:39 pm | permalink

In addition to finding the right pingback/trackback url ...

> http://www.ramonfincken.com/permalink/topic120.html

Posted by: Ramon Fincken | January 31, 2009 01:48:57 pm | permalink

Post a comment

Name:
(default is Anonymous)
Contact:
(email or url, optional)
Comment:
(no html or bbcode)
Captcha:



Related articles
Posted on Friday, November 3rd, 2006 18:49:06 GMT by: quietearth |   0 comments

Posted on Tuesday, August 15th, 2006 20:44:55 GMT by: quietearth |   3 comments

Posted on Saturday, August 19th, 2006 19:33:40 GMT by: quietearth |   0 comments

Posted on Tuesday, October 24th, 2006 0:22:03 GMT by: quietearth |   2 comments

Posted on Saturday, November 11th, 2006 0:27:41 GMT by: quietearth |   0 comments




rss | subscribe via email | the team | contact us | mobile
© 2006-2009 Don Neumann (except where applicable)
We are looking for free hosting with a cut of sales, you'll get a link right here.
If you want news of your film posted, use our contact page and we'll check it out
Permission is granted to use material from this site if you provide a reference to us via a link and DO NOT HOTLINK.


GenreBanners.com Banner Exchange