Revision [862]
This is an old revision of WikiPing made by JsnX on 2004-08-02 23:28:29.
the whole wikiping-specification is still beta and any suggestion how to improve this idea is welcomed!
to get in touch with the wikiping-server you need to implement a little xml-rpc-engine which is called at the end of the $wakka->SavePage()-function just after saving a page to the database:
<?
if ($pingdata = $this->GetPingParams($this->config["wikiping_server"], $tag, $user, $note))
$this->WikiPing($pingdata);
?>
if ($pingdata = $this->GetPingParams($this->config["wikiping_server"], $tag, $user, $note))
$this->WikiPing($pingdata);
?>
this function-call will stay inactive unless you have defined one or more wikiping-servers in your configs.
<? "wikiping_server" => "http://recentchanges.net/rpc/wikiping.php", ?>
and here is the ping-mechanism itself, which has to be added to the wakka-class:
<?
function HTTPpost($host, $data, $contenttype="application/x-www-form-urlencoded", $maxAttempts = 5) {
$attempt =0; $status = 300; $result = "";
while ($status >= 300 && $status < 400 && $attempt++ <= $maxAttempts) {
$url = parse_url($host);
if (isset($url["path"]) == false) $url["path"] = "/";
if (isset($url["port"]) == false) $url["port"] = 80;
if ($socket = fsockopen ($url["host"], $url["port"], $errno, $errstr, 15)) {
$strQuery = "POST ".$url["path"]." HTTP/1.1\n";
$strQuery .= "Host: ".$url["host"]."\n";
$strQuery .= "Content-Length: ".strlen($data)."\n";
$strQuery .= "Content-Type: ".$contenttype."\n";
$strQuery .= "Connection: close\n\n";
$strQuery .= $data;
// send request & get response
fputs($socket, $strQuery);
$bHeader = true;
while (!feof($socket)) {
$strLine = trim(fgets($socket, 512));
if (strlen($strLine) == 0) $bHeader = false; // first empty line ends header-info
if ($bHeader) {
if (!$status) $status = $strLine;
if (preg_match("/^Location:\s(.*)/", $strLine, $matches)) $location = $matches[1];
} else $result .= trim($strLine)."\n";
}
fclose ($socket);
} else $status = "999 timeout";
if ($status) {
if(preg_match("/(\d){3}/", $status, $matches)) $status = $matches[1];
} else $status = 999;
$host = $location;
}
if (preg_match("/^[\da-fA-F]+(.*)$/", $result, $matches)) $result = $matches[1];
return $result;
}
function WikiPing($ping, $debug = false) {
if ($ping) {
$rpcRequest .= "<methodCall>\n";
$rpcRequest .= "<methodName>wiki.ping</methodName>\n";
$rpcRequest .= "<params>\n";
$rpcRequest .= "<param>\n<value>\n<struct>\n";
$rpcRequest .= "<member>\n<name>tag</name>\n<value>".$ping["tag"]."</value>\n</member>\n";
$rpcRequest .= "<member>\n<name>url</name>\n<value>".$ping["taglink"]."</value>\n</member>\n";
$rpcRequest .= "<member>\n<name>wiki</name>\n<value>".$ping["wiki"]."</value>\n</member>\n";
if ($ping["author"]) {
$rpcRequest .= "<member>\n<name>author</name>\n<value>".$ping["author"]."</value>\n</member>\n";
if ($ping["authorpage"]) $rpcRequest .= "<member>\n<name>authorpage</name>\n<value>".$ping["authorpage"]."</value>\n</member>\n";
}
if ($ping["history"]) $rpcRequest .= "<member>\n<name>history</name>\n<value>".$ping["history"]."</value>\n</member>\n";
if ($ping["changelog"]) $rpcRequest .= "<member>\n<name>changelog</name>\n<value>".$ping["changelog"]."</value>\n</member>\n";
$rpcRequest .= "</struct>\n</value>\n</param>\n";
$rpcRequest .= "</params>\n";
$rpcRequest .= "</methodCall>\n";
foreach (explode(" ", $ping["server"]) as $server) {
$response = $this->HTTPpost($server, $rpcRequest, "text/xml");
if ($debug) print $response;
}
}
}
function GetPingParams($server, $tag, $user, $changelog = "") {
$ping = array();
if ($server) {
$ping["server"] = $server;
if ($tag) $ping["tag"] = $tag; else return false; // set page-title
if (!$ping["taglink"] = $this->href("", $tag)) return false; // set page-url
if (!$ping["wiki"] = $this->config["wakka_name"]) return false; // set site-name
$ping["history"] = $this->href("revisions", $tag); // set url to history
if ($user) {
$ping["author"] = $user; // set username
if ($this->LoadPage($user)) $ping["authorpage"] = $this->href("", $user); // set link to user page
}
if ($changelog) $ping["changelog"] = $changelog;
return $ping;
} else return false;
}
?>
function HTTPpost($host, $data, $contenttype="application/x-www-form-urlencoded", $maxAttempts = 5) {
$attempt =0; $status = 300; $result = "";
while ($status >= 300 && $status < 400 && $attempt++ <= $maxAttempts) {
$url = parse_url($host);
if (isset($url["path"]) == false) $url["path"] = "/";
if (isset($url["port"]) == false) $url["port"] = 80;
if ($socket = fsockopen ($url["host"], $url["port"], $errno, $errstr, 15)) {
$strQuery = "POST ".$url["path"]." HTTP/1.1\n";
$strQuery .= "Host: ".$url["host"]."\n";
$strQuery .= "Content-Length: ".strlen($data)."\n";
$strQuery .= "Content-Type: ".$contenttype."\n";
$strQuery .= "Connection: close\n\n";
$strQuery .= $data;
// send request & get response
fputs($socket, $strQuery);
$bHeader = true;
while (!feof($socket)) {
$strLine = trim(fgets($socket, 512));
if (strlen($strLine) == 0) $bHeader = false; // first empty line ends header-info
if ($bHeader) {
if (!$status) $status = $strLine;
if (preg_match("/^Location:\s(.*)/", $strLine, $matches)) $location = $matches[1];
} else $result .= trim($strLine)."\n";
}
fclose ($socket);
} else $status = "999 timeout";
if ($status) {
if(preg_match("/(\d){3}/", $status, $matches)) $status = $matches[1];
} else $status = 999;
$host = $location;
}
if (preg_match("/^[\da-fA-F]+(.*)$/", $result, $matches)) $result = $matches[1];
return $result;
}
function WikiPing($ping, $debug = false) {
if ($ping) {
$rpcRequest .= "<methodCall>\n";
$rpcRequest .= "<methodName>wiki.ping</methodName>\n";
$rpcRequest .= "<params>\n";
$rpcRequest .= "<param>\n<value>\n<struct>\n";
$rpcRequest .= "<member>\n<name>tag</name>\n<value>".$ping["tag"]."</value>\n</member>\n";
$rpcRequest .= "<member>\n<name>url</name>\n<value>".$ping["taglink"]."</value>\n</member>\n";
$rpcRequest .= "<member>\n<name>wiki</name>\n<value>".$ping["wiki"]."</value>\n</member>\n";
if ($ping["author"]) {
$rpcRequest .= "<member>\n<name>author</name>\n<value>".$ping["author"]."</value>\n</member>\n";
if ($ping["authorpage"]) $rpcRequest .= "<member>\n<name>authorpage</name>\n<value>".$ping["authorpage"]."</value>\n</member>\n";
}
if ($ping["history"]) $rpcRequest .= "<member>\n<name>history</name>\n<value>".$ping["history"]."</value>\n</member>\n";
if ($ping["changelog"]) $rpcRequest .= "<member>\n<name>changelog</name>\n<value>".$ping["changelog"]."</value>\n</member>\n";
$rpcRequest .= "</struct>\n</value>\n</param>\n";
$rpcRequest .= "</params>\n";
$rpcRequest .= "</methodCall>\n";
foreach (explode(" ", $ping["server"]) as $server) {
$response = $this->HTTPpost($server, $rpcRequest, "text/xml");
if ($debug) print $response;
}
}
}
function GetPingParams($server, $tag, $user, $changelog = "") {
$ping = array();
if ($server) {
$ping["server"] = $server;
if ($tag) $ping["tag"] = $tag; else return false; // set page-title
if (!$ping["taglink"] = $this->href("", $tag)) return false; // set page-url
if (!$ping["wiki"] = $this->config["wakka_name"]) return false; // set site-name
$ping["history"] = $this->href("revisions", $tag); // set url to history
if ($user) {
$ping["author"] = $user; // set username
if ($this->LoadPage($user)) $ping["authorpage"] = $this->href("", $user); // set link to user page
}
if ($changelog) $ping["changelog"] = $changelog;
return $ping;
} else return false;
}
?>
Testing WikiPing .... nice idea! -- JsnX
Nope.... I implemented as described above, and it didn't work. I'll have to check into it tonight when I have more time.
got the error! i didn't change the variable $this->config["mind_name"] to $this->config["wakka_name"] in the wikiping()-function (now in the getpingparams()-function). this causes the ping to be dropped, while the sitename is one of the three mandatory fields. sorry!
i have improved the ping-mechanism a bit to ease the migration to other wiki-engines. the functions httppost() and wikiping() now don't contain any stuff related to the wiki-engine. this is done completely in the function getpingparams() which returns an associative array with all nessecary parameters (or false if the parameter-record is incomplete). that should (hopefully) limit the debugging-efforts to this single function.
additionally i have set up a second wikiping-server http://sandbox.recentchanges.net for testing purposes. the url to the rpc-interface is located at
this sandbox-server will be modified in the next days to support debugging. perhaps it may "accept" failed pings and tell everyone what silly errors have been made by the ping clients ;)
Testing WikiPing, take 2.....