Location: PHPKode > scripts > Weblog_Pinger > Weblog_Pinger.php
<?
/* weblog_pinger.php

Weblog_Pinger PHP Class Library by Rogers Cadenhead
Version 1.6
Web: http://workbench.cadenhead.org/weblog-pinger

Copyright (C) 2009 Rogers Cadenhead

The Weblog_Pinger class can send a ping message over XML-RPC to
weblog notification services such as Weblogs.Com, Blo.gs,
and Technorati.

This class should be stored in a directory accessible to
the PHP scripts that will use it.

This software requires the XML-RPC for PHP class library by
Usefulinc: http://xmlrpc.usefulinc.com/php.html.

On a server equipped with MySQL, Weblog_Pinger can ensure not
to overload a ping notification service by hitting it too
often.

Example use:

require('weblog_pinger.php');
$pinger = new Weblog_Pinger();
echo $pinger->ping_ping_o_matic("Ekzemplo",
    "http://www.ekzemplo.com/");

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA. */

// include the XML-RPC class library
require_once('xmlrpc-1.2.1/xmlrpc.inc');

class Weblog_Pinger {
    // Weblogs.Com XML-RPC settings
    var $weblogs_com_server = "rpc.weblogs.com";
    var $weblogs_com_port = 80;
    var $weblogs_com_path = "/RPC2";
    var $weblogs_com_method = "weblogUpdates.ping";
    var $weblogs_com_extended_method = "weblogUpdates.extendedPing";
    // Blo.gs XML-RPC settings
    var $blo_gs_server = "ping.blo.gs";
    var $blo_gs_port = 80;
    var $blo_gs_path = "/";
    var $blo_gs_method = "weblogUpdates.ping";
    // Feedburner XML-RPC settings
    var $feedburner_server = "ping.feedburner.com";
    var $feedburner_port = 80;
    var $feedburner_path = "/RPC2";
    var $feedburner_method = "weblogUpdates.ping";
    // Ping-o-Matic XML-RPC settings
    var $ping_o_matic_server = "rpc.pingomatic.com";
    var $ping_o_matic_port = 80;
    var $ping_o_matic_path = "/RPC2";
    var $ping_o_matic_method = "weblogUpdates.ping";
    // Technorati XML-RPC settings
    var $technorati_server = "rpc.technorati.com";
    var $technorati_port = 80;
    var $technorati_path = "/rpc/ping";
    var $technorati_method = "weblogUpdates.ping";
    // Audio.Weblogs.Com XML-RPC settings
    var $audio_weblogs_com_server = "audiorpc.weblogs.com";
    var $audio_weblogs_com_port = 80;
    var $audio_weblogs_com_path = "/RPC2";
    var $audio_weblogs_com_method = "weblogUpdates.ping";
    // Simplaris Blogcast XML-RPC settings
    var $simplaris_blogcast_server = "blogcast.simplaris.com";
    var $simplaris_blogcast_port = 80;
    var $simplaris_blogcast_path = "/ping";
    var $simplaris_blogcast_method = "weblogUpdates.ping";
    // log settings
    var $log_file = "/var/log/ping.log";
    var $log_level = "short"; // full, short, or none;
    // database settings
    // the machine hosting the MySQL server
    var $database_server = "";
    // the MySQL database
    var $database_name = "";
    // the MySQL user with access to the database
    var $database_user = "";
    // the MySQL user password
    var $database_password = "";

    var $software_version = "1.6";
    var $debug = false;

    // report errors
    function report_error($message) {
        error_log("Weblog Pinger: " . $message);
    }

    /* Ping Weblogs.Com to indicate that a weblog has been updated. Returns true
    on success and false on failure. */
    function ping_weblogs_com($weblog_name, $weblog_url, $changes_url = "", $category = "") {
        return $this->ping($this->weblogs_com_server, $this->weblogs_com_port,
            $this->weblogs_com_path, $this->weblogs_com_method, $weblog_name,
            $weblog_url, $changes_url, $category);
    }

    /* Ping Blo.gs to indicate that a weblog has been updated. Returns true on success
    and false on failure. */
    function ping_blo_gs($weblog_name, $weblog_url, $changes_url = "", $category = "") {
        return $this->ping($this->blo_gs_server, $this->blo_gs_port,
            $this->blo_gs_path, $this->blo_gs_method, $weblog_name, $weblog_url,
            $changes_url, $category);
    }

    /* Ping Technorati to indicate that a weblog has been updated. Returns true on
    success and false on failure. */
    function ping_technorati($weblog_name, $weblog_url, $changes_url = "", $category = "") {
        return $this->ping($this->technorati_server, $this->technorati_port,
            $this->technorati_path, $this->technorati_method, $weblog_name, $weblog_url,
            $changes_url, $category);
    }

    /* Ping Pingomatic to indicate that a weblog has been updated. Returns true on success
    and false on failure. */
    function ping_ping_o_matic($weblog_name, $weblog_url, $changes_url = "", $category = "") {
        return $this->ping($this->ping_o_matic_server, $this->ping_o_matic_port,
            $this->ping_o_matic_path, $this->ping_o_matic_method, $weblog_name,
            $weblog_url, $changes_url, $category);
    }

    /* Ping Simplaris Blogcast to indicate that a weblog has been updated. Returns true on success
    and false on failure. */
    function ping_simplaris_blogcast($weblog_name, $weblog_url, $ping_id, $changes_url = "", $category = "") {
        return $this->ping($this->simplaris_blogcast_server, $this->simplaris_blogcast_port,
            "{$this->simplaris_blogcast_path}/{$ping_id}/", $this->ping_o_matic_method, $weblog_name,
            $weblog_url, $changes_url, $category);
    }

    /* Ping most of the above services to indicate that a weblog has been updated.
    Returns true on success and false on failure. */
    function ping_all($weblog_name, $weblog_url, $changes_url = "", $category = "") {
        $error[0] = $this->ping_technorati($weblog_name, $weblog_url, $changes_url, $category);
        $error[1] = $this->ping_weblogs_com($weblog_name, $weblog_url, $changes_url, $category);
        $error[2] = $this->ping_ping_o_matic($weblog_name, $weblog_url, $changes_url, $category);
	    $all_ok = $error[0] & $error[1];
	    return array($all_ok, $error);
    }

    /* Ping Feedburner to indicate that a weblog has been updated. Returns true on success
    and false on failure. */
    function ping_feedburner($weblog_name, $weblog_url, $changes_url = "", $category = "") {
        return $this->ping($this->feedburner_server, $this->feedburner_port,
            $this->feedburner_path, $this->feedburner_method, $weblog_name,
            $weblog_url, $changes_url, $category);
    }

    /* Ping Audio.Weblogs.Com to indicate that a weblog with a podcast has been updated.
    Returns true on success and false on failure. */
    function ping_audio_weblogs_com($weblog_name, $weblog_url, $changes_url = "",
        $category = "") {

        return $this->ping($this->audio_weblogs_com_server, $this->audio_weblogs_com_port,
            $this->audio_weblogs_com_path, $this->audio_weblogs_com_method, $weblog_name,
            $weblog_url, $changes_url, $category);
    }

    /* Ping Weblogs.Com (extended version) to indicate that a weblog has been updated.
    Returns true on success and false on failure. */
    function ping_weblogs_com_extended($weblog_name, $weblog_url, $changes_url, $rss_url) {
        if ($this->debug) $this->report_error(
            "Sending extended ping to Weblogs.Com for "
            . "$weblog_name, $weblog_url, $changes_url, $rss_url");
        return $this->ping($this->weblogs_com_server, $this->weblogs_com_port,
            $this->weblogs_com_path, $this->weblogs_com_extended_method, $weblog_name,
            $weblog_url, $changes_url, $rss_url, true);
    }


    /* Multi-purpose ping for any XML-RPC server that supports the Weblogs.Com interface. */
    function ping($xml_rpc_server, $xml_rpc_port, $xml_rpc_path, $xml_rpc_method,
        $weblog_name, $weblog_url, $changes_url, $cat_or_rss, $extended = false) {

        // see how recently a ping was sent to the server for this url
        $db_response = $this->check_ping($xml_rpc_server, $weblog_url);
        $db_dex = 0;
        if ($db_response['timechecked'] > 0) {
        	$when = strtotime($db_response['timechecked']);
        	$db_dex = $db_response['dex'];
        	if (time() - $when < 300) {
        		// last ping less than 5 minutes ago, so don't send another ping
        		return true;
        	}
        }

        // build the parameters
        $name_param = new xmlrpcval($weblog_name, 'string');
        $url_param = new xmlrpcval($weblog_url, 'string');
        $changes_param = new xmlrpcval($changes_url, 'string');
        $cat_or_rss_param = new xmlrpcval($cat_or_rss, 'string');
        $method_name = "weblogUpdates.ping";
        if ($extended) $method_name = "weblogUpdates.extendedPing";

        if ($cat_or_rss != "") {
            $params = array($name_param, $url_param, $changes_param, $cat_or_rss_param);
            $call_text = "$method_name(\"$weblog_name\", \"$weblog_url\", \"$changes_url\", \"$cat_or_rss\")";
        } else {
            if ($changes_url != "") {
              $params = array($name_param, $url_param, $changes_param);
              $call_text = "$method_name(\"$weblog_name\", \"$weblog_url\", \"$changes_url\")";
          } else {
              $params = array($name_param, $url_param);
              $call_text = "$method_name(\"$weblog_name\", \"$weblog_url\")";
            }
        }

        // create the message
        $message = new xmlrpcmsg($xml_rpc_method, $params);
        $client = new xmlrpc_client($xml_rpc_path, $xml_rpc_server,
            $xml_rpc_port);
        $response = $client->send($message);
        // log the message
        $this->log_ping("Request: " . strftime("%D %T") . " " . $xml_rpc_server . $xml_rpc_path . " " . $call_text);
        $this->log_ping($message->serialize(), true);
        // record the ping in the database
        $this->update_ping($db_dex, $xml_rpc_server, $weblog_url);
        if ($response == 0) {
            $error_text = "Error: " . $xml_rpc_server . ": " . $client->errno . " "
                . $client->errstring;
            $this->report_error($error_text);
            $this->log_ping($error_text);
            return false;
        }
        if ($response->faultCode() != 0)  {
            $error_text = "Error: " . $xml_rpc_server . ": " . $response->faultCode()
                . " " . $response->faultString();
            $this->report_error($error_text);
            return false;
        }
        $response_value = $response->value();
        if ($this->debug) $this->report_error($response_value->serialize());
        $this->log_ping($response_value->serialize(), true);
        $fl_error = $response_value->structmem('flerror');
        $message = $response_value->structmem('message');

        // read the response
        if ($fl_error->scalarval() != false) {
            $error_text = "Error: " . $xml_rpc_server . ": " . $message->scalarval();
            $this->report_error($error_text);
            $this->log_ping($error_text);
            return false;
        }

        return true;
    }

    /* Ping any server that supports PubSubHubbub's REST interface. The first argument can be a single URL of an RSS feed
       that has been updated or an array of several feeds. The second argument is the URL of the hub. */
    function ping_rest($updated_urls, $ping_server = "http://pubsubhubbub.appspot.com/") {
        // log the ping
        $this->log_ping("Request: " . strftime("%D %T") . " " . $ping_server);

    	if (!isset($updated_urls)) {
        	return false;
        }
        if (!is_array($updated_urls)) {
            $updated_urls = array($updated_urls);
        }

        // set up the HTTP request parameters
        $params = "hub.mode=publish";
        foreach ($updated_urls as $updated_url) {
            $params .= "&hub.url=" . urlencode($updated_url);
        }
		// make the request
		$options = array(CURLOPT_URL => $ping_server,
             CURLOPT_POST => true,
             CURLOPT_POSTFIELDS => $params,
             CURLOPT_USERAGENT => "Weblog-Pinger/{$this->$software_version}");
		$ch = curl_init();
        curl_setopt_array($ch, $options);
        $response = curl_exec($ch);

        // receive the response
        $info = curl_getinfo($ch);
        curl_close($ch);
        if ($info['http_code'] != 204) {
            // log the error
            $this->log_ping($response);
            return false;
        }
        return true;
    }

    /* Save ping data to a log file */
    function log_ping($message, $xml_data = false) {
        if ($this->log_level == "none") {
            return;
        }
        if (($this->log_level == "short") & ($xml_data)) {
            return;
        }
        if (!is_writable($this->log_file)) {
            $this->report_error("File {$this->log_file} is not writable");
            return;
        }
        $fhandle = fopen($this->log_file, "a");
        fwrite($fhandle, $message . "\r\n");
        fclose($fhandle);
    }


    /* Configure the MySQL database */
    function configure_database($database_server, $database_user, $database_password, $database_name) {
    	$this->database_server = $database_server;
    	$this->database_user = $database_user;
    	$this->database_password = $database_password;
    	$this->database_name = $database_name;
    	// $this->report_error("$database_server, $database_user, $database_password, $database_name");
    }

    /* Connect to the MySQL database */
    function connect_to_database() {
    	// make sure the database has been configured
    	if ($this->database_name == "") {
    		return false;
    	}
        $db = mysql_connect($this->database_server, $this->database_user,
            $this->database_password);
        if (!$db) {
            $this->report_error("Could not connect to database.");
            return false;
        } else {
            mysql_select_db($this->database_name);
            return true;
        }
    }

    /* Process a MySQL query */
    function process_query($query) {
        if (!$this->connect_to_database()) return false;
        $result = mysql_query($query);
        if ($result === false) {
            $this->report_error(mysql_error());
            $this->report_error($query);
        }
        return $result;
    }

    /* Lock the database */
    function lock_table($read_only = false) {
        $query = "LOCK TABLES $this->database_name WRITE";
        if ($read_only) {
            $query = "LOCK TABLES $this->database_name READ";
        }
        $result = mysql_query($query);
    }

    /* Unlock the database */
    function unlock_table() {
        $query = "UNLOCK TABLES";
        $result = mysql_query($query);
    }

    /* Create the MySQL database */
    function create_database() {
    	$query = "CREATE TABLE pingcheck ("
    		. "dex MEDIUMINT UNSIGNED AUTO_INCREMENT PRIMARY KEY, "
    		. "url TINYTEXT, "
    		. "server TINYTEXT, "
    		. "timechecked DATETIME"
    		. ");";
    	return $this->process_query($query);
    }

    /* Check the last time a server was pinged for a URL */
    function check_ping($server, $url) {
    	if (($server == "") | ($url == "")) {
    		return false;
    	}
    	$query = "SELECT dex, timechecked FROM pingcheck WHERE server = '$server' AND url = '$url'";
    	$result = $this->process_query($query);
    	if ($result === false) {
    		return false;
    	}
    	return mysql_fetch_array($result);
    }

    /* Record a ping in the database */
    function update_ping($dex, $server, $url) {
    	$when = strftime("%Y/%m/%d %H:%M:%S", time());
    	$query = "REPLACE INTO pingcheck VALUES($dex, '$url', '$server', '$when')";
    	return $this->process_query($query);
	}
}
?>
Return current item: Weblog_Pinger