- First teaser for Tyson Johnston’s first contact flick EXIST
- First teaser for Tyson Johnston’s first contact flick EXIST
- Apartment Complex Becomes Lost in Time, Descends in Chaos in THE LOCKDOWN TOWER (La Tour) [Trailer]
- First Trailer for THE WALKING DEAD: DEAD CITY
- New Neill Blomkamp Movie on the Way with Joel Kinnaman!
- TWISTED METAL Adaptation Gets a Teaser Trailer
- New Neill Blomkamp Movie on the Way with Joel Kinnaman!
- Hollywood Crosses The Rubicon with Harry Potter Reboot
- Possibly the Bleakest Movie I've Ever Seen
- Possibly the Bleakest Movie I've Ever Seen
- Re: Falcon Rock Command...
- Re: Occupation, Australian Sci Fi movie
- Slice of Life, Blade Runner inspired short
- Is Snowpeircer a sequel to Willy Wonka?
- Re: Yesterday
- Re: Yesterday
- Yesterday
- Re: White Night (or where do I get my 30 + from now?)
- Re: White Night (or where do I get my 30 + from now?)
- Re: White Night (or where do I get my 30 + from now?)
- First Trailer for THE WALKING DEAD: DEAD CITY
- TWISTED METAL Adaptation Gets a Teaser Trailer
- Korean Post-Apocalyptic Netflix Series BLACK KNIGHT Gets a Trailer
- Possibly the Bleakest Movie I've Ever Seen
- Here's What's New on Blu-ray and 4K UHD Steelbook [March 23, 2023]
- SILO Trailer - Apple's Series Based on Hugh Howey's Books
- New Blu-ray and 4K Releases [January 31, 2023]
- MAD MAX: HOPE AND GLORY Short Film Funding on Kickstarter
- Dawn of the Dead 4K Coming in January!
- Here's What's New on Blu-ray and 4K this Week! [October 18, 2022]
- Sony Released A Bunch of Limited Edition Steelbooks This Week
- VIFF 2021: THE IN-LAWS, MIRACLE, SALOUM, SECRETS FROM PUTUMAYO [Capsule Reviews]
- TIFF 2021: SILENT NIGHT Review
- VIFF 2021: Documentary Preview [Capsule Reviews]
- TIFF 2021: THE PINK CLOUD, THE HOLE IN THE FENCE [Capsule Reviews]
- TIFF 2021: JAGGED Review
- TIFF 2021: SUNDOWN Review
- VIFF 2021: Animation Preview [Capsule Reviews]
- SAINT-NARCISSE is Bruce LaBruce at His Most Accomplished [Review]
- TIFF 2021: DASHCAM Review
- TIFF 2021: THE DAUGHTER Review
- First Look at Neil Marshall's DUCHESS
- New Blu-ray and 4K Releases [January 31, 2023]
- New this week on Blu-ray and 4K UHD This week! [January 24, 2023]
- Famous Fist Films: Before SKINAMARINK Kyle Edward Ball Directed its Progenitor
- Must Watch: Terrifying Skinamarink Trailer
- DRAGONSLAYER Gets a 4K Steelbook!
- New on Blu-ray and 4K UHD this Week [December 20, 2022]
- Trailer for Brandon Cronenberg's INFINITY POOL
- Is Apple TV+ Eyeing Neuromancer Trilogy for Series
- Battle for Pandora Trailer!
- Trailer: Indiana Jones and the Dial of Destiny
- MAD MAX: HOPE AND GLORY Short Film Funding on Kickstarter
- Here's What's New on Blu-ray and 4K This Week! [November 1, 2022]
- War on the Waves: AVATAR 2: THE WAY OF THE WATER Trailer
- Dawn of the Dead 4K Coming in January!
- Watch Trailer for XYZ Psychological Thriller PRESENCE
- Here's What's New on Blu-ray and 4K This Week! [October 25, 2022]
- Watch Rare William Gibson Documentary NO MAPS FOR THESE TERRITORIES
- Here's What's New on Blu-ray and 4K this Week! [October 18, 2022]
- Vestron Announces SILENT NIGHT DEADLY NIGHT Sequel Collection
Jack In
Latest Comments
Latest Forum Posts
PA News
Latest Reviews
Older News
Crew
Marina Antunes
Editor in Chief
Vancouver, British Columbia
Christopher Webster
Managing Editor
Edmonton, Alberta
DN aka quietearth
Founder / Asst. Managing Editor
Denver, Colorado
Simon Read
UK Correspondent
Edinburgh, Scotland
Rick McGrath
Toronto Correspondent
Toronto, Ontario
Manuel de Layet
France Correspondent
Paris, France
rochefort
Austin Correspondent
Austin, Texas
Daniel Olmos
Corrispondente in Italia
Italy
Griffith Maloney aka Griffith Maloney
New York Correspondent
New York, NY
Stephanie O
Floating Correspondent
Quiet Earth Bunker
Jason Widgington
Montreal Correspondent
Montreal, Quebec
Carlos Prime
Austin Correspondent
Austin, TX







quietearth [General News 10.30.06]
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

obokaman (16 years ago) Reply
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 )

ikari (16 years ago) Reply
Um... Where did u get the valid_url function?

quietearth (16 years ago) Reply
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);
}

Mindloop Webdesign (15 years ago) Reply
Thanks,
This'll come in handy when adding the pingback class to the mindCMS

Mike (15 years ago) Reply
In the pingbacks.php, what goes in the "if (..)" portions of the script?
An example would be great for learning, thanks!

Mike (15 years ago) Reply
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

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

Kestas (15 years ago) Reply
I found that function, but i have another problem. Script gives me 105 fault. What does it means, where can i find the problem?

quietearth (15 years ago) Reply
do you have the phpxmlrpc library installed and the paths for the requires set properly?

Kestas (15 years ago) Reply
I find that problem. It was some mistakes in code. Thanks for that great script :)

Tyler (15 years ago) Reply
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?

snydez (15 years ago) Reply
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

scott klarr (15 years ago) Reply
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";
}
}

vivevtvivas (15 years ago) Reply
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 '';
}

Lazar (15 years ago) Reply
Thank you for this useful post and links to relevant tools. This page is now in my favorites!

rio (15 years ago) Reply
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.

LukasS (15 years ago) Reply
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).


akifemre (15 years ago) Reply
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

Allan Wirth (14 years ago) Reply
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.

Origin (14 years ago) Reply
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.

Ramon Fincken (14 years ago) Reply
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

Ramon Fincken (14 years ago) Reply
In addition to finding the right pingback/trackback url ...
> http://www.ramonfincken.com/permalink/topic120.html

angelxmoreno (12 years ago) Reply
is this still valid 4 years later?

jarmen (12 years ago) Reply
How fix http://www.mysite.com/wp-app.php/service error 401 ?
thanks for assist

Anonymous (12 years ago) Reply
How to get the infos into the database?

Dane (12 years ago) Reply
Hey, thanks for this great tutorial. But i can't get it to work. Always receiving a Code 5 error message.
"Failed with error code 5 message Didn't receive 200 OK from remote server."
Maybe it's because I'm just using this to ping and don't have implemented a pingback server on my site.

christian louboutin outlet (12 years ago) Reply
How to get the infos into the database?

bop da (11 years ago) Reply
[...]I had a few different options. I could have manually made a POST request to the endpoint, hand-coding the XML (this brute force method). Or I could stand on the shoulders of giants and leverage the power of open-source libraries. I chose the latter, in keeping with my new guiding principle of pursuing beauty, truth and goodness.[...]

Outlet Moncler (11 years ago) Reply
=

Haider M Rizvi (10 years ago) Reply
Thanks for the code....

Full indir (6 years ago) Reply
Thanks, good article.

Martin (6 years ago) Reply
This looks interesting but I'm not familiar with php, so where do I have to put my own code to handle the pingback? Is it this part `$s->service();`?