Revision [863]
This is an old revision of WikiPing made by JsnX on 2004-08-02 23:34: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.....
Yup, working fine. Now, the question is, do you want me to turn this on to point to your server in the release version? Or would you prefer that it be an option that admins will have to toggle on? -- JsnX