[pLog-svn] r822 - in plugins/trunk: . authentication backup bestposts blogstatistics blogstatistics/templates blogstatistics/templates/statistics blogstatistics/templates/statistics/img blogstatistics/templates/statistics/lang emailencryption emailencryption/js emailencryption/js/emailHider galleryimages google google/docs haiku jsdictionary jsdictionary/docs whoonline

oscar at devel.plogworld.net oscar at devel.plogworld.net
Mon Jan 24 16:31:02 GMT 2005


Author: oscar
Date: 2005-01-24 16:31:02 +0000 (Mon, 24 Jan 2005)
New Revision: 822

Added:
   plugins/trunk/authentication/
   plugins/trunk/authentication/pluginauthentication.class.php
   plugins/trunk/backup/
   plugins/trunk/backup/pluginbackup.class.php
   plugins/trunk/bestposts/
   plugins/trunk/bestposts/pluginbestposts.class.php
   plugins/trunk/blogstatistics/
   plugins/trunk/blogstatistics/pluginblogstatistics.class.php
   plugins/trunk/blogstatistics/templates/
   plugins/trunk/blogstatistics/templates/statistics/
   plugins/trunk/blogstatistics/templates/statistics/drawgraph.php
   plugins/trunk/blogstatistics/templates/statistics/footer.template
   plugins/trunk/blogstatistics/templates/statistics/header.template
   plugins/trunk/blogstatistics/templates/statistics/img/
   plugins/trunk/blogstatistics/templates/statistics/img/Thumbs.db
   plugins/trunk/blogstatistics/templates/statistics/img/bar1.gif
   plugins/trunk/blogstatistics/templates/statistics/img/bar2.gif
   plugins/trunk/blogstatistics/templates/statistics/img/bar3.gif
   plugins/trunk/blogstatistics/templates/statistics/img/bar4.gif
   plugins/trunk/blogstatistics/templates/statistics/img/bar5.gif
   plugins/trunk/blogstatistics/templates/statistics/img/barh1.gif
   plugins/trunk/blogstatistics/templates/statistics/img/barh2.gif
   plugins/trunk/blogstatistics/templates/statistics/img/barh3.gif
   plugins/trunk/blogstatistics/templates/statistics/img/barh4.gif
   plugins/trunk/blogstatistics/templates/statistics/img/barh5.gif
   plugins/trunk/blogstatistics/templates/statistics/lang/
   plugins/trunk/blogstatistics/templates/statistics/lang/english.php
   plugins/trunk/blogstatistics/templates/statistics/lang/zh_CN.php
   plugins/trunk/blogstatistics/templates/statistics/lang/zh_TW.php
   plugins/trunk/blogstatistics/templates/statistics/statistics.template
   plugins/trunk/emailencryption/
   plugins/trunk/emailencryption/js/
   plugins/trunk/emailencryption/js/emailHider/
   plugins/trunk/emailencryption/js/emailHider/demo.htm
   plugins/trunk/emailencryption/js/emailHider/emailHider.js
   plugins/trunk/emailencryption/pluginemailecryption.class.php
   plugins/trunk/galleryimages/
   plugins/trunk/galleryimages/plugingalleryimages.class.php
   plugins/trunk/google/
   plugins/trunk/google/docs/
   plugins/trunk/google/docs/readme.html
   plugins/trunk/google/plugingoogle.class.php
   plugins/trunk/haiku/
   plugins/trunk/haiku/docs/
   plugins/trunk/haiku/pluginhaiku.class.php
   plugins/trunk/haiku/readme.html
   plugins/trunk/jsdictionary/
   plugins/trunk/jsdictionary/docs/
   plugins/trunk/jsdictionary/docs/readme.html
   plugins/trunk/jsdictionary/pluginjsdictionary.class.php
   plugins/trunk/whoonline/
   plugins/trunk/whoonline/pluginwhoonline.class.php
Log:
added a lot of missing plugins


Added: plugins/trunk/authentication/pluginauthentication.class.php
===================================================================
--- plugins/trunk/authentication/pluginauthentication.class.php	2005-01-24 14:00:45 UTC (rev 821)
+++ plugins/trunk/authentication/pluginauthentication.class.php	2005-01-24 16:31:02 UTC (rev 822)
@@ -0,0 +1,85 @@
+<?php
+
+	include_once( PLOG_CLASS_PATH."class/plugin/pluginbase.class.php" );
+    include_once( PLOG_CLASS_PATH."class/plugin/pluginmanager.class.php" );
+
+    /**
+     * Plugin that is used to limit display of text to only the person who posted the blog
+     * entry when he or she has logged in. To test, add the example to a template, then 
+     * login to view the admin pages, then return to a blog page and the hidden text will 
+     * be visible.
+     *
+     * It is exported with "auth" as its identifier.
+     *
+     * Usage:
+     *
+     * 		{assign var=poster value=$post->getUserInfo()}
+     * 		{if $auth->posterIsLoggedIn($poster)}
+     * 		Poster: {$auth->getPosterName($poster)}
+     * 		User: {$auth->getUserName()}
+     * 		{/if}
+     */
+    class PluginAuthentication extends PluginBase {
+
+    	function PluginAuthentication()
+        {
+        	$this->PluginBase();
+
+            $this->desc = "Used to limit display of text to only 
+            	the person who posted the blog entry when he or she has logged in.
+            	To test, add the example to a template, then login to view the admin pages,
+                then return to a blog page and the hidden text will be visible.
+                Usage:<br/><br/>
+                {assign var=poster value=\$post->getUserInfo()}<br/>
+				{if \$auth->posterIsLoggedIn(\$poster)}<br/>
+				Poster: {\$auth->getPosterName(\$poster)}<br/>
+				User: {\$auth->getUserName()}<br/>
+				{/if}";
+            $this->author = "Daniel Kehoe <kehoe at fortuity.com>";
+        }
+
+        /**
+         * Returns "true" if the person who posted has logged in.
+         *
+         * @param object of type UserInfo
+         * @return true or false
+         */
+        function posterIsLoggedIn($poster)
+        { 	
+        	$allow = false;
+         	$sessionInfo = $_SESSION["SessionInfo"];
+			$userInfo = $sessionInfo->getValue("userInfo");
+			if (isset($userInfo)) {
+				if ($userInfo->getId() == $poster->getId()) $allow = true;
+			}
+        	return $allow;
+        }
+
+        /**
+         * Returns the name of the person who posted.
+         *
+         * @param object of type UserInfo
+         * @return poster's name
+         */        
+        function getPosterName($poster)
+        { 	
+        	return $poster->getUsername();
+        }
+
+        /**
+         * Returns the name of the person who is logged in.
+         *
+         * @return user's name
+         */          
+		function getUserName()
+        { 	
+        	$name = 'unknown';
+        	$sessionInfo = $_SESSION["SessionInfo"];
+			$userInfo = $sessionInfo->getValue("userInfo");
+			if (isset($userInfo)) $name = $userInfo->getUsername();
+        	return $name;
+        }
+    }
+
+    PluginManager::registerPlugin( "auth", "PluginAuthentication" );
+?>

Added: plugins/trunk/backup/pluginbackup.class.php
===================================================================
--- plugins/trunk/backup/pluginbackup.class.php	2005-01-24 14:00:45 UTC (rev 821)
+++ plugins/trunk/backup/pluginbackup.class.php	2005-01-24 16:31:02 UTC (rev 822)
@@ -0,0 +1,247 @@
+<?php
+
+		include_once( PLOG_CLASS_PATH."class/plugin/pluginbase.class.php" );
+		include_once( PLOG_CLASS_PATH."class/plugin/pluginmanager.class.php" );
+		include_once( PLOG_CLASS_PATH."class/config/config.class.php" );
+		include_once( PLOG_CLASS_PATH."class/dao/model.class.php" );
+		include_once( PLOG_CLASS_PATH."class/data/timestamp.class.php" );
+
+    /**
+     * plugin Backup allows users to backup their pLog journals.
+     */
+    class PluginBackup extends PluginBase
+    {
+    
+        var $_includeDropDatabase;
+        var $_includeDropTables;
+        var $_destination;
+        var $_pluginOp;
+
+        function PluginBackup()
+        {
+          $this->connectDb();
+	    $this->author = "Bradley Liang";
+	    $this->desc   = "The plugin backs up all of pLog's databases (including any created by plugins), but does not backup other tables.  If you are looking to restore database structure, it will be easier to purge your database and run the wizard over with a fresh installation.<br /><br />  ".
+	    			    "Usage: Unfortunately, I've not much idea on how to implement plugin versatility from within pLog's Administrative interface.  Instead, place the following command in a temporary template..<br />".
+	    			    "&nbsp;&nbsp;&nbsp;&nbsp;{\$dbbackup->Backup()}<br />".
+				    "A file entitled 'backup.sql' will be created in your main pLog directory.  To restore simply run the commands from the file from SQL.<br /><br />".
+	    			    "TODO:<br />&nbsp;&nbsp;&nbsp;&nbsp;-Use of the admin configuration panel to back data up.<br />&nbsp;&nbsp;&nbsp;&nbsp;-Option to restore entries to DB<br />";
+	    $this->pluginBase();
+	  }
+	  
+	  //
+	  // generates a very nice configuration message
+	  //
+	  function getConfigurationMessage()
+	  {
+	   // security check 
+	   if( !$this->userInfo->isSiteAdmin()) {
+	       $message = "<h1>Error</h1><p>Only site administrators are allowed to use this plugin</p>";
+	       return $message;
+	   }
+	   
+	   if( $this->_pluginOp == "backup" ) {
+	       $backup = new PluginBackupLib( $this->_includeDropDatabase, $this->_includeDropTables );
+	       $backupQuery = $backup->Backup();
+	       if( $this->_destination == "1" ) {
+	           // show results on the screen
+	           $message = nl2br(htmlspecialchars($backupQuery));
+	       }
+	       else {
+	           $t = new Timestamp();
+	           $fileName = PLOG_CLASS_PATH."tmp/backup_".$t->getYear().$t->getMonth().$t->getDay()."-".$t->getHour().$t->getMinutes().".sql";
+    	      if( !$backup->save( $fileName )) {
+    	           $message .= "There was an error saving the backup to file $fileName";
+    	      }
+    	      else {
+    	           $message .= "Backup saved to file $fileName";
+	               $message .= "<br/><br/>The following tables were backed up:<br/><br/>".$backup->getMessage();
+	          }
+	       }
+	   }
+	   else {
+           // otherwise, we can proceed as usual
+           $savePath = PLOG_CLASS_PATH."tmp/";
+           $message = "<p>This plugin will back up the whole pLog database. Enable any of the following features and then click the Backup button</p>
+                       <form name=\"backupOptions\" action=\"admin.php\" method=\"post\">
+                        <input type=\"checkbox\" name=\"includeDropDatabase\" value=\"1\" /> Include a DROP DATABASE command.<br/><br/>
+                        <input type=\"checkbox\" name=\"includeDropTables\" value=\"1\" checked=\"checked\" /> Include a DROP TABLE IF EXISTS for every table.<br/><br/>
+                        <select name=\"destination\">
+                         <option value=\"1\">Show results on the screen</option>
+                         <option value=\"2\">Save results to a file in $savePath</option>
+                        </select><br/><br/>
+                        <input type=\"submit\" name=\"Backup\" value=\"Backup\" />
+                        <input type=\"hidden\" name=\"op\" value=\"updatePluginConfig\" />
+                        <input type=\"hidden\" name=\"pluginOp\" value=\"backup\" />
+                        <input type=\"hidden\" name=\"pluginId\" value=\"dbbackup\" />
+                       </form>";
+	   }
+	   
+	   return $message;
+	  }
+	  
+	  function configure( $params )
+	  {
+	   $this->_includeDropDatabase = $params->getValue( "includeDropDatabase" );
+	   $this->_includeDropTables = $params->getValue( "includeDropTables" );
+	   $this->_destination = $params->getValue( "destination" );
+	   $this->_pluginOp = $params->getValue( "pluginOp" );
+	   
+	   return true;
+ 	  }
+	}
+	
+	// ---
+	// class that does all the dirty work
+	// ---
+	class PluginBackupLib extends Model
+	{
+	
+	 var $_message;
+	 var $_includeDropDatabase;
+	 var $_includeDropTables;
+	 var $_result;
+	
+     function PluginBackupLib( $includeDropDatabase = true, $includeDropTables = true )
+     {
+        $this->_includeDropDatabase = $includeDropDatabase;
+        $this->_includeDropTables = $includeDropTables;
+        $this->Model();
+    }
+	  
+
+	 function _buildInsertQuery( $table , $row_data) {
+		$query = "INSERT INTO $table VALUES(\n";
+
+		foreach ($row_data as $entry) {
+			if (!isset($entry))		$query .= "     NULL,\n";
+			else if ($entry != "") 	$query .= "     '".addslashes($entry)."',\n";
+			else					$query .= "     '',\n";
+		}
+
+		$query = ereg_replace(",\n$","",$query);
+
+		$query .= ");\n\n";
+
+		return $query;
+	 }
+
+	 function _buildFieldQuery($table, $fields) {
+	    	$def = "";
+	    	if( $this->_includeDropTables ) $def .= "DROP TABLE IF EXISTS $table;\n";
+    		$def .= "CREATE TABLE $table (\n";
+
+    		while( $field = $fields->FetchRow() ) {
+        	   $def .= "   $field[Field] $field[Type]";
+        	   if ($field["Default"] != "") 	$def .= " DEFAULT '$field[Default]'";
+        	   if ($field["Null"] != "YES") 	$def .= " NOT NULL";
+       	   if ($field[Extra] != "") 		$def .= " $field[Extra]";
+        	   						$def .= ",\n";
+		}
+
+     		$def = ereg_replace(",\n$","", $def);
+     		return $def;
+	 }
+
+	function _buildKeyQuery($table, $keys)
+	{
+	     while($row = $keys->FetchRow()) {
+	          $kname=$row[Key_name];
+
+	          if(($kname != "PRIMARY") && ($row[Non_unique] == 0)) {
+			$kname="UNIQUE|$kname";
+		   }
+
+	          if(!isset($index[$kname])) {
+			$index[$kname] = array();
+		   }
+
+	          $index[$kname][] = $row[Column_name];
+	     }
+
+        // if the table has keys, then proceed to dump them to the db
+        if( is_array($index)) {
+	     while(list($x, $columns) = @each($index)) {
+	          $def .= ",\n";
+	          if ($x == "PRIMARY") 			$def .= "    PRIMARY KEY (" . implode($columns, ", ") . ")";
+	          else if (substr($x,0,6) == "UNIQUE") 	$def .= "    UNIQUE ".substr($x,7)." (" . implode($columns, ", ") . ")";
+	          else 						$def .= "    KEY $x (" . implode($columns, ", ") . ")";
+	      }
+	     }
+
+	     $def .= "\n);";
+	     return (stripslashes($def));
+	}
+
+
+	 function backupTable($table)
+	 {
+	     $content = "# begin table '$table'\n";
+	     $this->_db->Execute("LOCK TABLES $table WRITE;");
+
+	     $result = $this->_db->Execute("SHOW FIELDS FROM $table");
+	     $content .= $this->_buildFieldQuery($table, $result);
+
+	     $result = $this->_db->Execute("SHOW KEYS FROM $table");
+	     $content .= $this->_buildKeyQuery($table, $result);
+
+	     $result = $this->_db->Execute("SELECT * FROM $table");
+	     $content .= "\n\n";
+
+	     while($row = $result->FetchRow()) {
+	         $content .= $this->_buildInsertQuery($table, $row);
+	     }
+
+	     $this->_db->Execute("UNLOCK TABLES;");
+	     return $content."# end table '$table'\n\n";
+ 	 }
+
+	 function Backup()
+	 {
+		$query   = "# Backup of all pLog entries in DB\n".
+		 	  "# pLog.....:  http://plogworld.org\n".
+			  "# Created..:  ".date("d-M-Y h:s",time())."\n\n";
+			  
+		$config =& Config::getConfig();	  
+        if( $this->_includeDropDatabase ) $query .= "DROP DATABASE ".$config->getValue( "db_database" ).";\n";
+		
+		$prefix = $this->getPrefix();
+		
+		$result = $this->_db->MetaTables('TABLES');
+		foreach ($result as $tablename) {
+
+			if (strstr($tablename, $prefix))
+			{
+				$this->_message .= $tablename."<br />";
+			   $query .= $this->backupTable($tablename);
+			}
+		}
+		
+		$this->_result = $query;
+
+   		return $query;
+	 }
+	 
+	 function getMessage()
+	 {
+	   return $this->_message;
+	 }
+	 
+	 // ---
+	 // save the contents of our export operation to a file
+	 // ---
+	 function save( $fileName )
+	 {
+	   $t = new Timestamp();
+	   $f = new File( $fileName );
+	   $f->open( "w" );
+	   if( !$f->write( $this->_result ))
+	       return false;
+	   $f->close();
+	   
+	   return true;
+	 }
+	}
+	
+	PluginManager::registerPlugin( "dbbackup", "PluginBackup" );
+?>


Property changes on: plugins/trunk/backup/pluginbackup.class.php
___________________________________________________________________
Name: svn:executable
   + *

Added: plugins/trunk/bestposts/pluginbestposts.class.php
===================================================================
--- plugins/trunk/bestposts/pluginbestposts.class.php	2005-01-24 14:00:45 UTC (rev 821)
+++ plugins/trunk/bestposts/pluginbestposts.class.php	2005-01-24 16:31:02 UTC (rev 822)
@@ -0,0 +1,239 @@
+<?php
+     
+    include_once( PLOG_CLASS_PATH."class/plugin/pluginbase.class.php" );
+    include_once( PLOG_CLASS_PATH."class/plugin/pluginmanager.class.php" );
+     
+    /**
+    * Plugin that generates a form that is used to give a posting a rating
+    * or score as a way of identifying a blog's "best posts." Originally intended
+    * to be used in conjunction with the PluginAuthentication plugin to give only
+    * the person posting to the blog the privilege to identify the "best posts."
+    *
+    * It is exported with "bestposts" as its identifier.
+    *
+    * Usage:
+    *
+    *   {assign var=poster value=$post->getUserInfo()}
+    *   {assign var=articleId value=$post->getId()}
+    *   {assign var=categoryId value=$post->getCategoryId()}
+    *   {if $auth->posterIsLoggedIn($poster)}
+    *   Rating: {$bestposts->displayForm($articleId,$categoryId))}
+    *   {/if}
+    */
+    class PluginBestPosts extends PluginBase {
+         
+        function PluginBestPosts() {
+            $this->PluginBase();
+             
+            $this->desc = "Generates a form that is used to give a posting a rating
+                or score as a way of identifying a blog's &quot;best posts.&quot;
+                Can be used in conjunction with PluginAuthentication to give only
+                the person posting to the blog the privilege to identify the
+                &quot;best posts.&quot;
+                Usage:<br/><br/>
+                {assign var=poster value=\$post->getUserInfo()}<br/>
+                {assign var=articleId value=\$post->getId()}<br/>
+                {assign var=categoryId value=\$post->getCategoryId()}<br/>
+                {if \$auth->posterIsLoggedIn(\$poster)}<br/>
+                Rating: {\$bestposts->displayForm(\$articleId,\$categoryId)}<br/>
+                {/if}";
+            $this->author = "Daniel Kehoe <kehoe at fortuity.com>";
+             
+            $this->connectDb();
+            if ($this->_databaseExists() == true ) {
+                $this->_setDefaultConfigMessage();
+                return true;
+            } else {
+                $this->_setCreateDbConfigMessage();
+                return true;
+            }
+        }
+         
+        /**
+        * Returns a form that can be used to give a score or rating to a blog entry.
+        *
+        * @param article ID (passed from the template)
+        * @param category ID (passed from the template)
+        * @return HTML string to generate a form
+        */
+        function displayForm($articleId, $categoryId) {
+            $form = '<form action="admin.php" method="post" name="bestposts_form">
+                <input type="text" size="5" name="bestposts_score" value=""/>
+                <input type="hidden" name="bestposts_articleId" value="'.$articleId.'"/>
+                <input type="hidden" name="bestposts_categoryId" value="'.$categoryId.'"/>
+                <input type="hidden" name="pluginId" value="bestposts"/>
+                <input type="hidden" name="op" value="updatePluginConfig"/>
+                <input type="submit" name="bestposts_action" value="Submit"/>
+                </form>';
+            return $form;
+        }
+         
+        /**
+        * Handles submission of the rating form, recording a score for the blog entry.
+        *
+        * @param form elements
+        * @return always true
+        */
+        function configure($params) {
+            $action = $params->getValue('bestposts_action');
+            $score = $params->getValue('bestposts_score');
+             
+            switch ($params->getValue('bestposts_action')) {
+                case 'Submit':
+                {
+                    if ($this->_setScore($params) == true ) {
+                        return true;
+                    } else {
+                        return false;
+                    }
+                }
+                break;
+                 
+                case 'Create':
+                {
+                    if ($this->_createDataTable() == true ) {
+                        return true;
+                    } else {
+                        return false;
+                    }
+                }
+                break;
+                 
+                default:
+                {
+                    if ($this->_databaseExists() == true ) {
+                        $this->_setDefaultConfigMessage();
+                        return true;
+                    } else {
+                        $this->_setCreateDbConfigMessage();
+                        return true;
+                    }
+                }
+                 
+            }
+             
+        }
+         
+        /**
+        * This message shows in the admin interface if the database is set up properly.
+        *
+        * @private
+        */
+        function _setDefaultConfigMessage() {
+            $this->configMessage = '&quot;Best Posts&quot; plugin has been configured.';
+        }
+         
+        /**
+        * This message shows in the admin interface after a score has been submitted.
+        *
+        * @private
+        */
+        function _setAcknowledgementConfigMessage($score) {
+            $this->configMessage = 'Score set to '.$score.'.';
+        }
+         
+        /**
+        * This message shows in the admin interface if the necessary data table does not exist.
+        *
+        * @private
+        */
+        function _setCreateDbConfigMessage() {
+            $this->configMessage = '
+                <form name="pluginConfiguration" method="POST" action="admin.php">
+                <strong>No &quot;Best Posts&quot; table found... shall I create it?</strong><br>
+                <br/>
+                <input type="hidden" name="pluginId" value="bestposts"/>
+                <input type="hidden" name="op" value="updatePluginConfig"/>
+                <input type="submit" name="bestposts_action" value="Create"/>
+                <input type="submit" name="bestposts_action" value="Cancel"/>
+                </form>
+                ';
+        }
+         
+        /**
+        * Add a score or rating to the database for this article.
+        *
+        * @private
+        * @return true unless the operation fails
+        */
+        function _setScore($params) {
+            // Get the config values
+            $config = new Config();
+            $dbPrefix = $config->getValue('db_prefix');
+            $table = $dbPrefix.'scores';
+             
+            // fetch parameters coming from the user
+            $score = $params->getValue('bestposts_score');
+            $articleId = $params->getValue('bestposts_articleId');
+            $categoryId = $params->getValue('bestposts_categoryId');
+             
+            // check that parameter is set
+            if (!isset($score)) {
+                $this->setConfigurationErrorMessage('No score or rating value was submitted.');
+                return false;
+            }
+             
+            // get the current blog_id
+            $blogId = $this->blogInfo->getId();
+             
+            // if everything is ok, save the score
+            $query = "INSERT INTO $table (blog_id, category_id, article_id, score) VALUES ('$blogId','$categoryId','$articleId','$score')";
+            $this->db->Execute($query);
+            $this->_setAcknowledgementConfigMessage($score);
+            return true;
+        }
+         
+        /**
+        * Check if the necessary data table exists.
+        *
+        * @private
+        * @return true if the database exists
+        */
+        function _databaseExists() {
+            // Get the config values
+            $config = new Config();
+            $dbPrefix = $config->getValue("db_prefix");
+            $table = $dbPrefix.'scores';
+            $query = 'SELECT count(*) FROM '.$table;
+            if ($this->db->Execute($query)) {
+                return true;
+            } else {
+                $this->setConfigurationErrorMessage($table.' table does not exist.');
+                return false;
+            }
+        }
+         
+        /**
+        * Create the necessary data table using ADOdb's data dictionary features.
+        *
+        * @private
+        * @return always true
+        */
+        function _createDataTable() {
+            // Get the config values
+            $config = new Config();
+            $dbPrefix = $config->getValue('db_prefix');
+            $table = $dbPrefix.'scores';
+            // for background, see http://phplens.com/lens/adodb/docs-datadict.htm
+            $fields = "
+                blog_id I(10) NOTNULL,
+                category_id I(10) NOTNULL,
+                article_id I(10) NOTNULL,
+                score I(5) NOTNULL
+                ";
+            // create a data dictionary object
+            $dict = NewDataDictionary($this->db);
+            // Checks to see if table exists, if table does not exist,
+            // adds the table. If table exists, generates appropriate
+            // ALTER TABLE MODIFY COLUMN commands if field already exists,
+            // or ALTER TABLE ADD $column if field does not exist.
+            $sqlarray = $dict->ChangeTableSQL($table, $fields);
+            $dict->ExecuteSQLArray($sqlarray);
+            $this->configMessage = 'Created new data table '.$table.'.';
+            return true;
+        }
+         
+    }
+     
+    PluginManager::registerPlugin("bestposts", "PluginBestPosts" );
+?>

Added: plugins/trunk/blogstatistics/pluginblogstatistics.class.php
===================================================================
--- plugins/trunk/blogstatistics/pluginblogstatistics.class.php	2005-01-24 14:00:45 UTC (rev 821)
+++ plugins/trunk/blogstatistics/pluginblogstatistics.class.php	2005-01-24 16:31:02 UTC (rev 822)
@@ -0,0 +1,479 @@
+<?php
+//
+// blogstatistics - pLog Blog Statistics and Traffic Statistics
+//
+// Copyright 2004 by Minstrel Chiu. All rights reserved.
+//
+// Licensed under the GNU GPL License, Version 2.0 (the "License");
+// Everyone is permitted to copy and distribute verbatim copies
+// of this license document, but changing it is not allowed.
+// You may obtain a copy of the License at
+//
+//   http://www.fsf.org/copyleft/gpl.html
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+	include_once( PLOG_CLASS_PATH."class/plugin/pluginbase.class.php" );
+	include_once( PLOG_CLASS_PATH."class/plugin/pluginmanager.class.php" );
+	include_once( PLOG_CLASS_PATH."class/dao/model.class.php" );
+	include_once( PLOG_CLASS_PATH."class/data/Date.class.php" );
+	include_once( PLOG_CLASS_PATH."class/net/client.class.php" );
+	include_once( PLOG_CLASS_PATH."class/net/url.class.php" );
+	include_once( PLOG_CLASS_PATH."class/net/httpvars.class.php" );
+	include_once( PLOG_CLASS_PATH."class/data/timestamp.class.php" );
+
+	class PluginBlogStatistics extends PluginBase
+	{
+		var $_prefix;
+		var $_now;
+		var $_date;
+		var $_prevdate;
+		var $_weekdate;
+		var $_month;
+		var $_onlinestamp;
+
+		function PluginBlogStatistics()
+		{
+			$this->author = "Minstrel Chiu";
+			$this->desc = "
+			<p>This plugin offers a statistics of plog. Part of code is originally written by Mark Wu. And also thanks to Reic Wang.<br>
+			Add the following code in header.template<br><br>
+			<b>{\$blogstatistics->logStatistics()}</b><br>
+			<br>
+			Several functions are available:<br>
+			 1. <b>Totoal Read Number</b>: <b><i>getTotalReadNumber()</i></b><br>
+			 2. <b>Totoal Post Number</b>: <b><i>getTotalPostNumber()</i></b><br>
+			 3. <b>Totoal Comment Number</b>: <b><i>getTotalCommentNumber()</i></b><br>
+			 4. <b>Totoal Trackback Number</b>: <b><i>getTotalTrackbackNumber()</i></b><br>
+			 5. <b>Total Referer Number</b>: <b><i>getTotalRefererNumber()</i></b><br>
+			 6. <b>Today Visitor</b>: <b><i>getTodayVisitor()</i></b><br>
+			 7. <b>Today Distinct Visitor</b>: <b><i>getTodayDistinctVisitor()</i></b><br>
+			 8. <b>Yesterday Visitor</b>: <b><i>getYesterdayVisitor()</i></b><br>
+			 9. <b>Yesterday Distinct Visitor</b>: <b><i>getYesterdayDistinctVisitor()</i></b><br>
+			10. <b>This Week Visitor</b>: <b><i>getThisWeekVisitor()</i></b><br>
+			11. <b>This Week Distinct Visitor</b>: <b><i>getThisWeekDistinctVisitor()</i></b><br>
+			12. <b>This Month Visitor</b>: <b><i>getThisMonthVisitor()</i></b><br>
+			13. <b>This Month Distinct Visitor</b>: <b><i>getThisMonthDistinctVisitor()</i></b><br>
+			14. <b>Total Visitor</b>: <b><i>getTotalVisitor()</i></b><br>
+			15. <b>Total Distinct Visitor</b>: <b><i>getTotalDistinctVisitor()</i></b><br>
+			16. <b>Current Online Visitor</b>: <b><i>getOnlineVisitor()</i></b><br>
+			<br>
+			All above function default return all site statistics. If wanna get particular blog statistics,<br>
+			can pass <b>{\$blog->getId()}</b> in, to get the particular blog statistics data.<br>
+			<br>
+			Examples:<br>
+			<br>
+			<p><b>
+			Total Read: {\$blogstatistics->getTotalReadNumber()} Times<br />
+			Total Post: {\$blogstatistics->getTotalPostNumber(()} Posts<br />
+			Total Comments: {\$blogstatistics->getTotalCommentNumber()} Comments<br />
+			Total Trackbacks: {\$blogstatistics->getTotalTrackbackNumber()} Trackbacks<br />
+			Total Referers: {\$blogstatistics->getTotalRefererNumber()} Referers<br />
+			<br />
+			Today Visitors: {\$blogstatistics->getTodayVisitor()}<br />
+			Yesterday Visitors: {\$blogstatistics->getYesterdayVisitor()}<br />
+			This Week Visitors: {\$blogstatistics->getThisWeekVisitor()}<br />
+			This Month Visitors: {\$blogstatistics->getThisMonthVisitor()}<br />
+			Total Visitors: {\$blogstatistics->getTotalVisitor()}<br />
+			Online Visitors: {\$blogstatistics->getOnlineVisitor()}<br />
+			</b></p>
+			</p>";
+
+			$config = new Config();
+			$this->_prefix = $config->getValue('db_prefix');
+
+			$this->_now = new Date();
+
+			$prevday = $this->_now->getPrevDay();
+
+			$this->_date = $this->_now->format("%Y%m%d");
+			$this->_month = $this->_now->format("%Y%m");
+			$this->_prevdate = $prevday->format("%Y%m%d");
+
+			$weekdate = $this->_now;
+			$weekday = $this->_now->getDayOfWeek();
+
+			for($day=$weekday; $day>0; $day--)
+				$weekdate = $weekdate->getPrevDay();
+
+			$this->_weekdate = $weekdate->format("%Y%m%d");
+			
+			$online = $this->_now;
+			$online->subtractSeconds(360);
+			
+			$this->_onlinestamp = $online->getDate(DATE_FORMAT_TIMESTAMP);
+
+			$this->PluginBase();
+		}
+
+		function register()
+		{
+			$this->connectDb();
+			$stat = new BlogStatistics();
+			$stat->createTable();
+		}
+
+		function logStatistics()
+		{
+			$blog = $this->blogInfo->getId();
+			$timestamp = $this->_now->getDate(DATE_FORMAT_TIMESTAMP);
+			$clientip = Client::getIp();
+			$refer = $_SERVER["HTTP_REFERER"];
+			$ourHost = $_SERVER["HTTP_HOST"];
+			$agent = $_SERVER["HTTP_USER_AGENT"];
+
+			$refererUrl = new Url( $refer );
+
+			if( $refererUrl->getHost() == $ourHost || $refererUrl->getHost() == "" )
+			{
+				$refer = "";
+			}
+
+			$params = HttpVars::getRequest();
+			$articleId = $params["articleId"];
+
+			if($articleId == "")
+				$articleId = 0;
+
+			$this->injectSql("(`blog_id`, `article_id`, `time`, `ip`,  `refer`, `agent`) VALUES ('$blog', '$articleId', '$timestamp', '$clientip', '$refer', '$agent');");
+		}
+
+		function injectSql($dbqry)
+		{
+			$query = "INSERT INTO ".$this->_prefix."statistics $dbqry";
+			$result = $this->db->Execute( $query );
+		}
+
+		////////////////////////////////////////////////////////////////////////////////////////////
+		//
+		//
+		// Blog Static Statistics
+		//
+		//
+		////////////////////////////////////////////////////////////////////////////////////////////
+
+		function getTotalPostNumber($blogId = -1)
+		{
+			$query = "SELECT * FROM ".$this->_prefix."articles WHERE status='published'";
+
+			if( $blogId != -1 )
+				$query .= " AND blog_id = ".$blogId;
+
+			$query .= ";";
+
+			$result = $this->db->Execute( $query );
+
+			if( $result )
+				$count = $result->RecordCount();
+
+			return $count;
+		}
+
+		function getTotalCommentNumber($blogId = -1)
+		{
+			$query = "SELECT * FROM ".$this->_prefix."articles_comments,".$this->_prefix."articles WHERE ".$this->_prefix."articles_comments.article_id=".$this->_prefix."articles.id AND ".$this->_prefix."articles.status='published'";
+
+			if( $blogId != -1 )
+				$query .= " AND ".$this->_prefix."articles.blog_id=".$blogId;
+
+			$query .= ";";
+
+			$result = $this->db->Execute( $query );
+
+			if( $result )
+				$count = $result->RecordCount();
+
+			return $count;
+		}
+
+		function getTotalReadNumber($blogId = -1)
+		{
+			$query = "SELECT SUM(num_reads) AS readNumber FROM ".$this->_prefix."articles WHERE status='published'";
+
+			if( $blogId != -1 )
+				$query .= " AND blog_id = ".$blogId;
+
+			$query .= ";";
+
+			$result = $this->db->Execute( $query );
+
+			if( !$result )
+				return false;
+
+			$row = $result->FetchRow();
+			return $row["readNumber"];
+		}
+
+		function getTotalRefererNumber($blogId = -1)
+		{
+			$query = "SELECT * FROM ".$this->_prefix."referers";
+
+			if( $blogId != -1 )
+				$query .= " WHERE blog_id = ".$blogId;
+
+			$query .= ";";
+
+			$result = $this->db->Execute( $query );
+
+			if( $result )
+				$count = $result->RecordCount();
+
+			return $count;
+		}
+
+		function getTotalTrackbackNumber($blogId = -1)
+		{
+			$query = "SELECT * FROM ".$this->_prefix."trackbacks,".$this->_prefix."articles WHERE ".$this->_prefix."trackbacks.article_id=".$this->_prefix."articles.id AND ".$this->_prefix."articles.status='published'";
+
+			if( $blogId != -1 )
+				$query .= " AND ".$this->_prefix."articles.blog_id=".$blogId;
+
+			$query .= ";";
+
+			$result = $this->db->Execute( $query );
+
+			if( $result )
+				$count = $result->RecordCount();
+
+			return $count;
+		}
+
+		////////////////////////////////////////////////////////////////////////////////////////////
+		//
+		//
+		// Blog Dynamic Statistics
+		//
+		//
+		////////////////////////////////////////////////////////////////////////////////////////////
+
+		function getOnlineVisitor($blogId = -1)
+		{
+			$query = "SELECT DISTINCT ip FROM ".$this->_prefix."statistics WHERE date_format(time, '%Y%m%d%H%i%S') >= ".$this->_onlinestamp;
+			
+			if( $blogId != -1 )
+				$query .= " AND blog_id = ".$blogId;
+
+			$query .= ";";
+
+			$result = $this->db->Execute( $query );
+
+			if( $result )
+				$count = $result->RecordCount();
+
+			return $count;
+		}
+		
+		function getTotalVisitor($blogId = -1)
+		{
+			$query = "SELECT * FROM ".$this->_prefix."statistics";
+
+			if( $blogId != -1 )
+				$query .= " WHERE blog_id = ".$blogId;
+
+			$query .= ";";
+
+			$result = $this->db->Execute( $query );
+
+			if( $result )
+				$count = $result->RecordCount();
+
+			return $count;
+		}
+
+		function getTotalDistinctVisitor($blogId = -1)
+		{
+			$query = "SELECT DISTINCT ip FROM ".$this->_prefix."statistics";
+
+			if( $blogId != -1 )
+				$query .= " WHERE blog_id = ".$blogId;
+
+			$query .= ";";
+
+			$result = $this->db->Execute( $query );
+
+			if( $result )
+				$count = $result->RecordCount();
+
+			return $count;
+		}
+
+		function getTodayVisitor($blogId = -1)
+		{
+			$query = "SELECT * FROM ".$this->_prefix."statistics WHERE date_format(time, '%Y%m%d') = ".$this->_date;
+
+			if( $blogId != -1 )
+				$query .= " AND blog_id = ".$blogId;
+
+			$query .= ";";
+
+			$result = $this->db->Execute( $query );
+
+			if( $result )
+				$count = $result->RecordCount();
+
+			return $count;
+		}
+
+		function getTodayDistinctVisitor($blogId = -1)
+		{
+			$query = "SELECT DISTINCT ip FROM ".$this->_prefix."statistics WHERE date_format(time, '%Y%m%d') = ".$this->_date;
+
+			if( $blogId != -1 )
+				$query .= " AND blog_id = ".$blogId;
+
+			$query .= ";";
+
+			$result = $this->db->Execute( $query );
+
+			if( $result )
+				$count = $result->RecordCount();
+
+			return $count;
+		}
+
+		function getYesterdayVisitor($blogId = -1)
+		{
+			$query = "SELECT * FROM ".$this->_prefix."statistics WHERE date_format(`time`, '%Y%m%d' ) = ".$this->_prevdate;
+			if( $blogId != -1 )
+				$query .= " AND blog_id = ".$blogId;
+
+			$query .= ";";
+
+			$result = $this->db->Execute( $query );
+
+			if( $result )
+				$count = $result->RecordCount();
+
+			return $count;
+		}
+
+		function getYesterdayDistinctVisitor($blogId = -1)
+		{
+			$query = "SELECT DISTINCT ip FROM ".$this->_prefix."statistics WHERE date_format(`time`, '%Y%m%d' ) =".$this->_prevdate;
+
+			if( $blogId != -1 )
+				$query .= " AND blog_id = ".$blogId;
+
+			$query .= ";";
+
+			$result = $this->db->Execute( $query );
+
+			if( $result )
+				$count = $result->RecordCount();
+
+			return $count;
+		}
+
+		function getThisWeekVisitor($blogId = -1)
+		{
+			$query = "SELECT * FROM ".$this->_prefix."statistics WHERE (date_format(`time`, '%Y%m%d')) >= ".$this->_weekdate;
+
+			if( $blogId != -1 )
+				$query .= " AND blog_id = ".$blogId;
+
+			$query .= ";";
+
+			$result = $this->db->Execute( $query );
+
+			if( $result )
+				$count = $result->RecordCount();
+
+			return $count;
+		}
+
+		function getThisWeekDistinctVisitor($blogId = -1)
+		{
+			$query = "SELECT DISTINCT ip FROM ".$this->_prefix."statistics WHERE (date_format(`time`, '%Y%m%d')) >= ".$this->_weekdate;
+
+			if( $blogId != -1 )
+				$query .= " AND blog_id = ".$blogId;
+
+			$query .= ";";
+
+			$result = $this->db->Execute( $query );
+
+			if( $result )
+				$count = $result->RecordCount();
+
+			return $count;
+		}
+
+		function getThisMonthVisitor($blogId = -1)
+		{
+			$query = "SELECT * FROM ".$this->_prefix."statistics WHERE date_format(`time`, '%Y%m') = ".$this->_month;
+
+			if( $blogId != -1 )
+				$query .= " AND blog_id = ".$blogId;
+
+			$query .= ";";
+
+			$result = $this->db->Execute( $query );
+
+			if( $result )
+				$count = $result->RecordCount();
+
+			return $count;
+		}
+
+		function getThisMonthDistinctVisitor($blogId = -1)
+		{
+			$query = "SELECT DISTINCT ip FROM ".$this->_prefix."statistics WHERE date_format(`time`, '%Y%m') = ".$this->_month;
+
+			if( $blogId != -1 )
+				$query .= " AND blog_id = ".$blogId;
+
+			$query .= ";";
+
+			$result = $this->db->Execute( $query );
+
+			if( $result )
+				$count = $result->RecordCount();
+
+			return $count;
+		}
+	}
+
+	class BlogStatistics extends Model
+	{
+		function BlogStatistics()
+		{
+			$this->Model();
+		}
+
+		function checkTable($table, $field)
+		{
+			$dbPrefix = $this->getPrefix();
+			$tableName = $dbPrefix.$table;
+
+			// create the data dictionary and create the table if necessary
+			$dict = NewDataDictionary( $this->_db );
+			$sqlArray = $dict->ChangeTableSQL( $tableName, $field );
+			$result = $dict->ExecuteSQLArray( $sqlArray );
+
+			if( $result == 0 )
+				$this->_desc = "There was an error initializing the tables.";
+		}
+
+		function createTable()
+		{
+			$table = "statistics";
+			$field = "blog_id I(10) NOT NULL default '-1',
+				article_id I(10) NOT NULL default '-1',
+				time timestamp(14),
+				ip varchar(15) default '0.0.0.0',
+				refer text NOT NULL,
+				agent text NOT NULL";
+
+			$this->checkTable( $table, $field );
+
+			return true;
+		}
+	}
+
+	PluginManager::registerPlugin( "blogstatistics", "PluginBlogStatistics" );
+?>

Added: plugins/trunk/blogstatistics/templates/statistics/drawgraph.php
===================================================================
--- plugins/trunk/blogstatistics/templates/statistics/drawgraph.php	2005-01-24 14:00:45 UTC (rev 821)
+++ plugins/trunk/blogstatistics/templates/statistics/drawgraph.php	2005-01-24 16:31:02 UTC (rev 822)
@@ -0,0 +1,131 @@
+<?php
+//
+// Statistics - pLog Blog Statistics and Traffic Statistics
+//
+// Copyright 2004 by Minstrel Chiu. All rights reserved.
+// Modified Sep 2004 by Matthew Chin - Hong Kong.
+//
+// Licensed under the GNU GPL License, Version 2.0 (the "License");
+// Everyone is permitted to copy and distribute verbatim copies
+// of this license document, but changing it is not allowed.
+// You may obtain a copy of the License at
+//
+//   http://www.fsf.org/copyleft/gpl.html
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+//  MC0409 START - Matthew Chin 
+
+function vertical($title, $file, $php_for, $full, $get, $img, $plus, $empt, $top_php, $bottom, $bott_php, $maxtext, $avgtext, $mintext, $footer) {
+         echo "<table border='0' cellspacing='0' cellpadding='0' width='790' align='center'><tr><td class='base'>";
+         echo "<table width='100%' align='center' cellspacing='0' cellpadding='5' height='250' border='0'>";
+         echo "<tr class='base'><td colspan='".$file."'>&nbsp;</td></tr>";
+         echo "<tr><td class='base' align='center' colspan='".$file."' height='10'>".$title;
+         echo "<hr size=1 width=100%></hr></td></tr>";
+         echo "<tr valign='bottom'>";
+
+                  $td_width = round(100/$file, 0);  /* round for <td width=?> */
+                  $min      = $full;
+                  $max      = 0;
+                  $php_for  = count($get)-1;  
+
+                  for($x=1; $x<=$php_for; $x++) {
+                      if($get[$x] > $max) $max = $get[$x];
+                      if($get[$x] < $min) $min = $get[$x];
+                  }
+
+
+                  for($n=0; $n<$file; $n++) {
+                            #
+                            if($plus == 0)
+                               $k = $n;
+                            else
+                               $k = $n+1;
+                            #
+                            if(!empty($max)) // so height
+                               $p_round = round((200*$get[$n+1]/$max));
+                            else
+                               $p_round = 1;
+                               echo ('<td valign= \'bottom\' align=\'center\' width=\''.$td_width.'%'.'\' class=\'');
+                            #
+                            if($k <= $php_for)
+                               echo('small');
+                            else
+                               echo('small_x');
+                            #
+                            if($top_php == 0)
+                               $top = $get[$n+1];
+                            else
+                               $top = round(100*$get[$n+1]/$get[0], 0).'%';
+                            #
+                            if($bottom == 0)
+                               $text = $k;
+                            else
+                               $text = $bottom[$n];
+                            #
+                            if($bott_php == 1)
+                               $bp = round(100*$get[$n+1]/$get[0], 0).'%';
+                               echo ('\'><font class=\'small_x\'>'.$top.'</font><br>');
+                            #
+                            if($k <= $php_for)
+                            
+                               echo ('<img src=\'./templates/statistics/img/'.$img.'\' border=\'0\' alt=\''.$top.'\' height=\''.$p_round.'\' width=\'10\'><br>');
+                            #
+                            if($k == $php_for)  
+                               echo ($text);
+                            else
+                               echo ($text);
+                            #
+                            if($bott_php == 1)
+                               echo ('<br>'.$bp);
+                               echo ('</td>');
+                  } // end for
+
+
+         echo "</tr>";
+
+         if($empt == 0) {
+            echo "<tr valign='bottom'><td colspan='$file' class='base'>&nbsp;</td></tr>";
+         }
+
+         echo "</table>";
+
+         if($empt == 1)
+         maximal($max, $min, $file, $get[0], $maxtext, $avgtext, $mintext, $footer);
+
+         echo "</td></tr>";
+         echo "<tr class='base'><td colspan='".$file."'>&nbsp;</td></tr>";
+         echo "</table>";
+         echo "</td></tr></table>";
+
+} 
+
+function maximal($max, $min, $paul, $paula, $maxtext, $avgtext, $mintext, $footer) {
+
+        if(empty($max)) $max = 0;
+        if(empty($min)) $min = 0;
+        if(empty($paula)) $paula = 0;
+
+        if(!empty($paul))
+           $p_round = round($paula/$paul);
+        else
+           $p_round = 0;
+
+        echo ('<table border=\'0\' width=\'100%\' cellspacing=\'0\' align=\'center\' class=\'bgbase\' cellpadding=\'3\'><tr align=\'center\'><td class=\'middle\'>');
+
+        echo ($footer.': '.$paula.' | ');
+        echo ($maxtext.': '.$max.' | ');
+        echo ($avgtext.': '.$p_round.' | ');
+        echo ($mintext.': '.$min);
+
+        echo ('</td></tr></table>');
+        
+} 
+
+//  MC0409 END - Matthew Chin
+
+?>
\ No newline at end of file

Added: plugins/trunk/blogstatistics/templates/statistics/footer.template
===================================================================
--- plugins/trunk/blogstatistics/templates/statistics/footer.template	2005-01-24 14:00:45 UTC (rev 821)
+++ plugins/trunk/blogstatistics/templates/statistics/footer.template	2005-01-24 16:31:02 UTC (rev 822)
@@ -0,0 +1,3 @@
+ </div>
+</body>
+</html>

Added: plugins/trunk/blogstatistics/templates/statistics/header.template
===================================================================
--- plugins/trunk/blogstatistics/templates/statistics/header.template	2005-01-24 14:00:45 UTC (rev 821)
+++ plugins/trunk/blogstatistics/templates/statistics/header.template	2005-01-24 16:31:02 UTC (rev 822)
@@ -0,0 +1,110 @@
+<!--
+// ******************************************************************************************************
+// * Ref       Date    By             Details
+// * ======  ========  ============== ===================================================================
+// *         04/07/01  Minstrel Chiu  First Release
+// * MC0904  04/09/24  Matthew Chin   Add Graph and Language Files
+// ******************************************************************************************************
+// -->
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="{$locale->getLanguageId()}" 
+      lang="{$locale->getLanguageId()}-TW" dir="{$locale->getDirection()}">
+ <head>
+ <meta name="robots" content="noindex,nofollow" />
+ <meta http-equiv="Content-Type" content="text/html;charset={$locale->getCharset()}" />
+ <meta http-equiv="Content-Language" content="{$locale->getLanguageId()}" />
+  <title>plog BlogStatistics and TrafficStatistics</title>
+  <style type="text/css" media="print,screen">
+   {literal}
+body {
+	margin:0px	0px;
+	margin-top: 20px;
+	margin-bottom: 20px;
+	padding:0px;
+	text-align:center;
+	font:11px arial, times new roman, lucida sans unicode, sans-serif;
+	color:#333;
+	background:#ffffff
+	}
+
+h3 {
+	font: bold 13px  georgia, lucida sans unicode, times new roman, times, sans-serif;
+	margin-top: 0px;
+	margin-bottom: 2px;
+	background: transparent;
+    background-color:#E0E0E0;
+	border: 1px solid #666;
+    border-width: 0px 0px 1px 0px;
+	}
+
+h4 {
+	font: 12px times new roman, arial, sans-serif;
+	font-weight: bold;
+	letter-spacing: 0.09em;
+	margin: 0px;
+	padding: 0px;
+	}
+
+#Container {
+	width:800px;
+	margin:0px auto;
+	text-align:left;
+	padding: 0px;
+	border:	1px	solid #ccc;
+	background:#ffffff
+	color: #333;
+	}
+
+a {
+	color:#666;
+	text-decoration:none;
+	background:	transparent;
+	}
+
+a:link {color: #666; border-bottom:	1px	solid #666; background: transparent;}
+a:visited {color: #777;	border-bottom: 1px solid #666;	background:	transparent;}
+a:hover	{color:	#aaa; border-bottom: 1px solid #666; background: transparent;}
+
+<!--  MC0409 START - Matthew Chin -->
+
+ .bgbase{
+   background-color:blue;
+   color:white;
+   font-size:11px;
+   font-weight: bold;
+   font-family: Verdana, Tahoma, Trebuchet MS, Arial, sans-serif;
+  }
+
+ .base{
+   background-color:white;
+   color:darkblue;
+   font-size:11px;
+   font-family: Verdana, Tahoma, Trebuchet MS, Arial, sans-serif;
+  }
+
+ .small{
+   color:purple;
+   font-size:9px;
+   font-family: Verdana, Tahoma, Trebuchet MS, Arial, sans-serif;
+  }
+
+ .small_x{
+   color:darkblue;
+   font-size:8px;
+   font-family: Small Fonts, Verdana, Tahoma, Trebuchet MS, Arial, sans-serif;
+  }
+
+ .error{
+   background-color:white;
+   color:red;
+   font-size:11px;
+   font-family: Verdana, Tahoma, Trebuchet MS, Arial, sans-serif;
+  }
+
+<!--  MC0409 END - Matthew Chin -->
+
+   {/literal}
+  </style>
+ </head>
+ <body>
+  <div id="Container">

Added: plugins/trunk/blogstatistics/templates/statistics/img/Thumbs.db
===================================================================
(Binary files differ)


Property changes on: plugins/trunk/blogstatistics/templates/statistics/img/Thumbs.db
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: plugins/trunk/blogstatistics/templates/statistics/img/bar1.gif
===================================================================
(Binary files differ)


Property changes on: plugins/trunk/blogstatistics/templates/statistics/img/bar1.gif
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: plugins/trunk/blogstatistics/templates/statistics/img/bar2.gif
===================================================================
(Binary files differ)


Property changes on: plugins/trunk/blogstatistics/templates/statistics/img/bar2.gif
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: plugins/trunk/blogstatistics/templates/statistics/img/bar3.gif
===================================================================
(Binary files differ)


Property changes on: plugins/trunk/blogstatistics/templates/statistics/img/bar3.gif
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: plugins/trunk/blogstatistics/templates/statistics/img/bar4.gif
===================================================================
(Binary files differ)


Property changes on: plugins/trunk/blogstatistics/templates/statistics/img/bar4.gif
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: plugins/trunk/blogstatistics/templates/statistics/img/bar5.gif
===================================================================
(Binary files differ)


Property changes on: plugins/trunk/blogstatistics/templates/statistics/img/bar5.gif
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: plugins/trunk/blogstatistics/templates/statistics/img/barh1.gif
===================================================================
(Binary files differ)


Property changes on: plugins/trunk/blogstatistics/templates/statistics/img/barh1.gif
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: plugins/trunk/blogstatistics/templates/statistics/img/barh2.gif
===================================================================
(Binary files differ)


Property changes on: plugins/trunk/blogstatistics/templates/statistics/img/barh2.gif
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: plugins/trunk/blogstatistics/templates/statistics/img/barh3.gif
===================================================================
(Binary files differ)


Property changes on: plugins/trunk/blogstatistics/templates/statistics/img/barh3.gif
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: plugins/trunk/blogstatistics/templates/statistics/img/barh4.gif
===================================================================
(Binary files differ)


Property changes on: plugins/trunk/blogstatistics/templates/statistics/img/barh4.gif
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: plugins/trunk/blogstatistics/templates/statistics/img/barh5.gif
===================================================================
(Binary files differ)


Property changes on: plugins/trunk/blogstatistics/templates/statistics/img/barh5.gif
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: plugins/trunk/blogstatistics/templates/statistics/lang/english.php
===================================================================
--- plugins/trunk/blogstatistics/templates/statistics/lang/english.php	2005-01-24 14:00:45 UTC (rev 821)
+++ plugins/trunk/blogstatistics/templates/statistics/lang/english.php	2005-01-24 16:31:02 UTC (rev 822)
@@ -0,0 +1,92 @@
+<?php
+#############################################################################################
+//
+// blogstatistics - pLog Blog Statistics and Traffic Statistics
+//
+// Copyright 2004 by Minstrel Chiu. All rights reserved.
+// Modified Sep 2004 by Matthew Chin - Hong Kong.
+//
+// Licensed under the GNU GPL License, Version 2.0 (the "License");
+// Everyone is permitted to copy and distribute verbatim copies
+// of this license document, but changing it is not allowed.
+// You may obtain a copy of the License at
+//
+//   http://www.fsf.org/copyleft/gpl.html
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+#############################################################################################
+// Please do your own translation file based on the english file - use UTF-8 to encode
+// and change this lang default in /statistics/conf.php : $blogstat['lang'] = 'english';
+
+
+$rmsg['plogstat']				 = 'pLog Static Record';
+$rmsg['traffic']                 = 'Traffic Record';
+$rmsg['monthtop']                = 'This Month Top Visitors';
+$rmsg['weektop']                 = 'This Week Top Visitors';
+$rmsg['todaytop']                = 'Today Top Visitors';
+$rmsg['recentvisit']             = 'Recent Visit';
+$rmsg['monthtraffic']            = 'Monthly Traffic Record';
+$rmsg['daytraffic']              = 'Daily Traffic Record';
+$rmsg['weekdaytraffic']          = 'Total Traffic Record (By WeekDay)';
+$rmsg['hourtraffic']             = 'Total Traffic Record (By Hour)';
+
+$rmsg['currenttime']			 = "Current Time:";
+$rmsg['reporttime']				 = "Report Time:";
+$rmsg['category']                = 'Category';
+$rmsg['count']                   = 'Count';
+$rmsg['visitor']                 = 'Visitors';
+$rmsg['hit']                     = 'Hits';
+
+$rmsg['totartread']				 = 'Total Article Read Numbers';
+$rmsg['totart']                  = 'Total Articles';
+$rmsg['totcomment']              = 'Total Comments';
+$rmsg['tottrack']                = 'Total Trackbacks';
+$rmsg['totref']                  = 'Total Referers';
+$rmsg['totonline']               = 'Current Online';
+
+$rmsg['today']                   = 'Today';
+$rmsg['yesterday']               = 'Yesterday';
+$rmsg['thisweek']                = 'This Week';
+$rmsg['thismonth']               = 'This Month';
+$rmsg['total']                   = 'Total';
+
+$rmsg['rank']                    = 'Rank';
+$rmsg['ipaddress']               = 'IP Address';
+$rmsg['browser']                 = "Browser/Search Engine";
+$rmsg['ossystem']                = 'Operating System';
+$rmsg['recentvisittime']         = 'Recent Visit Time';
+$rmsg['time']                    = 'Time';
+$rmsg['artread']                 = 'Article Read';
+$rmsg['referer']                 = 'Referer';
+$rmsg['month']                   = 'Month';
+$rmsg['date']                    = 'Date';
+$rmsg['weekday']                 = 'Weekday';
+$rmsg['hour']                    = 'Hour';
+$rmsg['incorrect']               = 'Incorrect Article';
+$rmsg['home']                    = 'Main Page';
+$rmsg['none']                    = 'None';
+$rmsg['view']			         = 'View';
+
+
+$rmsg['title']['year']           = 'Visitors per month in the year - ';
+$rmsg['title']['month']          = 'Visitors per day in the month - ';
+$rmsg['title']['weekday']        = 'Visitors per weekday in the month - ';
+$rmsg['title']['hour']           = 'Visitors per hour in the month - ';
+$rmsg['monthdesc']               = array('Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec');
+$rmsg['weekdesc']                = array('Sun','Mon','Tue','Wed','Thu','Fri','Sat');
+$rmsg['hourdesc']                = array('00','01','02','03','04','05','06','07','08','09','10','11','12','13','14','15','16','17','18','19','20','21','22','23');
+
+
+$rmsg['tail']['visitors']        = 'Total Visitors';
+$rmsg['tail']['hits']            = 'Total Hits';
+$rmsg['tail']['avg']             = 'Average';
+$rmsg['tail']['max']             = 'Max';
+$rmsg['tail']['min']             = 'Min';
+
+
+?>

Added: plugins/trunk/blogstatistics/templates/statistics/lang/zh_CN.php
===================================================================
--- plugins/trunk/blogstatistics/templates/statistics/lang/zh_CN.php	2005-01-24 14:00:45 UTC (rev 821)
+++ plugins/trunk/blogstatistics/templates/statistics/lang/zh_CN.php	2005-01-24 16:31:02 UTC (rev 822)
@@ -0,0 +1,91 @@
+<?php
+#############################################################################################
+//
+// blogstatistics - pLog Blog Statistics and Traffic Statistics
+//
+// Copyright 2004 by Minstrel Chiu. All rights reserved.
+// Modified Sep 2004 by Matthew Chin - Hong Kong.
+//
+// Licensed under the GNU GPL License, Version 2.0 (the "License");
+// Everyone is permitted to copy and distribute verbatim copies
+// of this license document, but changing it is not allowed.
+// You may obtain a copy of the License at
+//
+//   http://www.fsf.org/copyleft/gpl.html
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+#############################################################################################
+// Please do your own translation file based on the english file - use UTF-8 to encode
+// and change this lang default in /statistics/conf.php : $blogstat['lang'] = 'zh_CN';
+
+
+$rmsg['plogstat']				 = '网志记录';
+$rmsg['traffic']                 = '总流量记录';
+$rmsg['monthtop']                = '本月拜访排行';
+$rmsg['weektop']                 = '本周拜访排行';
+$rmsg['todaytop']                = '本日拜访排行';
+$rmsg['recentvisit']             = '最近拜访';
+$rmsg['monthtraffic']            = '每月记录';
+$rmsg['daytraffic']              = '每日记录';
+$rmsg['weekdaytraffic']          = '总流量记录(每周日)';
+$rmsg['hourtraffic']             = '总流量记录(每小时)';
+
+$rmsg['currenttime']			 = "目前时间:";
+$rmsg['reporttime']				 = "报表日期:";
+$rmsg['category']                = '区分';
+$rmsg['count']                   = '数目';
+$rmsg['visitor']                 = '拜访人数';
+$rmsg['hit']                     = '拜访次数';
+
+$rmsg['totartread']				 = '网志被阅读次数';
+$rmsg['totart']                  = '目前共有文章';
+$rmsg['totcomment']              = '目前共有回响';
+$rmsg['tottrack']                = '共有逆向连结';
+$rmsg['totref']                  = '目前共被引用';
+$rmsg['totonline']               = '目前线上人数';
+
+$rmsg['today']                   = '今日拜访';
+$rmsg['yesterday']               = '昨日拜访';
+$rmsg['thisweek']                = '本周拜访';
+$rmsg['thismonth']               = '本月拜访';
+$rmsg['total']                   = '所有拜访';
+
+$rmsg['rank']                    = '排名';
+$rmsg['ipaddress']               = 'IP位址';
+$rmsg['browser']                 = '浏览器';
+$rmsg['ossystem']                = '作业系统';
+$rmsg['recentvisittime']         = '最近拜访时间';
+$rmsg['time']                    = '拜访时间';
+$rmsg['artread']                 = '阅读文章';
+$rmsg['referer']                 = '来源';
+$rmsg['month']                   = '月份';
+$rmsg['date']                    = '日期';
+$rmsg['weekday']                 = '星期';
+$rmsg['hour']                    = '每小时';
+$rmsg['incorrect']               = '不正确的文章';
+$rmsg['home']                    = '首页';
+$rmsg['none']                    = '无';
+$rmsg['view']			         = '察看';
+
+$rmsg['monthdesc']               = array('一月','二月','三月','四月','五月','六月','七月','八月','九月','十月','十一月','十二月');
+$rmsg['weekdesc']                = array('星期日','星期一','星期二','星期三','星期四','星期五','星期六');
+$rmsg['hourdesc']                = array('00','01','02','03','04','05','06','07','08','09','10','11','12','13','14','15','16','17','18','19','20','21','22','23');
+$rmsg['title']['year']           = '本年每月总流量 - ';
+$rmsg['title']['month']          = '本月每日总流量 - ';
+$rmsg['title']['weekday']        = '本月每周总流量 - ';
+$rmsg['title']['hour']           = '本月每小时总流量 - ';
+
+
+$rmsg['tail']['visitors']        = '拜访人数';
+$rmsg['tail']['hits']            = '拜访次数';
+$rmsg['tail']['avg']             = '平均';
+$rmsg['tail']['max']             = '最多';
+$rmsg['tail']['min']             = '最少';
+
+
+?>

Added: plugins/trunk/blogstatistics/templates/statistics/lang/zh_TW.php
===================================================================
--- plugins/trunk/blogstatistics/templates/statistics/lang/zh_TW.php	2005-01-24 14:00:45 UTC (rev 821)
+++ plugins/trunk/blogstatistics/templates/statistics/lang/zh_TW.php	2005-01-24 16:31:02 UTC (rev 822)
@@ -0,0 +1,91 @@
+<?php
+#############################################################################################
+//
+// blogstatistics - pLog Blog Statistics and Traffic Statistics
+//
+// Copyright 2004 by Minstrel Chiu. All rights reserved.
+// Modified Sep 2004 by Matthew Chin - Hong Kong.
+//
+// Licensed under the GNU GPL License, Version 2.0 (the "License");
+// Everyone is permitted to copy and distribute verbatim copies
+// of this license document, but changing it is not allowed.
+// You may obtain a copy of the License at
+//
+//   http://www.fsf.org/copyleft/gpl.html
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+#############################################################################################
+// Please do your own translation file based on the english file - use UTF-8 to encode
+// and change this lang default in /statistics/conf.php : $blogstat['lang'] = 'zh_TW';
+
+
+$rmsg['plogstat']				 = '網誌記錄';
+$rmsg['traffic']                 = '總流量記錄';
+$rmsg['monthtop']                = '本月拜訪排行';
+$rmsg['weektop']                 = '本週拜訪排行';
+$rmsg['todaytop']                = '本日拜訪排行';
+$rmsg['recentvisit']             = '最近拜訪';
+$rmsg['monthtraffic']            = '每月記錄';
+$rmsg['daytraffic']              = '每日記錄';
+$rmsg['weekdaytraffic']          = '總流量記錄(每週日)';
+$rmsg['hourtraffic']             = '總流量記錄(每小時)';
+
+$rmsg['currenttime']			 = "目前時間:";
+$rmsg['reporttime']				 = "報表日期:";
+$rmsg['category']                = '區分';
+$rmsg['count']                   = '數目';
+$rmsg['visitor']                 = '拜訪人數';
+$rmsg['hit']                     = '拜訪次數';
+
+$rmsg['totartread']				 = '網誌被閱讀次數';
+$rmsg['totart']                  = '目前共有文章';
+$rmsg['totcomment']              = '目前共有迴響';
+$rmsg['tottrack']                = '共有逆向連結';
+$rmsg['totref']                  = '目前共被引用';
+$rmsg['totonline']               = '目前線上人數';
+
+$rmsg['today']                   = '今日拜訪';
+$rmsg['yesterday']               = '昨日拜訪';
+$rmsg['thisweek']                = '本週拜訪';
+$rmsg['thismonth']               = '本月拜訪';
+$rmsg['total']                   = '所有拜訪';
+
+$rmsg['rank']                    = '排名';
+$rmsg['ipaddress']               = 'IP位址';
+$rmsg['browser']                 = '瀏覽器';
+$rmsg['ossystem']                = '作業系統';
+$rmsg['recentvisittime']         = '最近拜訪時間';
+$rmsg['time']                    = '拜訪時間';
+$rmsg['artread']                 = '閱讀文章';
+$rmsg['referer']                 = '來源';
+$rmsg['month']                   = '月份';
+$rmsg['date']                    = '日期';
+$rmsg['weekday']                 = '星期';
+$rmsg['hour']                    = '每小時';
+$rmsg['incorrect']               = '不正確的文章';
+$rmsg['home']                    = '首頁';
+$rmsg['none']                    = '無';
+$rmsg['view']			         = '察看';
+
+$rmsg['monthdesc']               = array('一月','二月','三月','四月','五月','六月','七月','八月','九月','十月','十一月','十二月');
+$rmsg['weekdesc']                = array('星期日','星期一','星期二','星期三','星期四','星期五','星期六');
+$rmsg['hourdesc']                = array('00','01','02','03','04','05','06','07','08','09','10','11','12','13','14','15','16','17','18','19','20','21','22','23');
+$rmsg['title']['year']           = '本年毎月總流量 - ';
+$rmsg['title']['month']          = '本月毎日總流量 - ';
+$rmsg['title']['weekday']        = '本月毎週總流量 - ';
+$rmsg['title']['hour']           = '本月毎小時總流量 - ';
+
+
+$rmsg['tail']['visitors']        = '拜訪人數';
+$rmsg['tail']['hits']            = '拜訪次數';
+$rmsg['tail']['avg']             = '平均';
+$rmsg['tail']['max']             = '最多';
+$rmsg['tail']['min']             = '最少';
+
+
+?>

Added: plugins/trunk/blogstatistics/templates/statistics/statistics.template
===================================================================
--- plugins/trunk/blogstatistics/templates/statistics/statistics.template	2005-01-24 14:00:45 UTC (rev 821)
+++ plugins/trunk/blogstatistics/templates/statistics/statistics.template	2005-01-24 16:31:02 UTC (rev 822)
@@ -0,0 +1,363 @@
+<!--
+// ******************************************************************************************************
+// * Ref       Date    By             Details
+// * ======  ========  ============== ===================================================================
+// *         04/07/01  Minstrel Chiu  First Release
+// * MC0904  04/09/24  Matthew Chin   Add Graph and Language Files
+// ******************************************************************************************************
+// -->
+{include file="statistics/header.template"}
+
+<!-- MC0409 START - Matthew Chin -->
+
+{assign var=langId value=$locale->getLanguageId()}
+{assign var=countryId value=$locale->getCountryId()}
+ 
+{php}
+$getlang=$this->get_template_vars('langId');
+$getcountry=$this->get_template_vars('countryId');
+$under='_';
+
+if (file_exists( "./templates/statistics/lang/".$getlang.$under.$getcountry.".php" ))
+   { include( "./templates/statistics/lang/".$getlang.$under.$getcountry.".php" ); }
+else
+   { include( "./templates/statistics/lang/english.php" ); }
+{/php}
+
+{php}
+include( "./templates/statistics/drawgraph.php" );
+{/php}
+
+<!-- MC0409 END - Matthew Chin -->
+
+<form name="Form" action="statistics.php" style="padding: 0px 0px 0px 0px; margin-top: 0" target="_parent">
+<table class="aws_border" border="0" cellpadding="2" cellspacing="0" width="100%">
+<tr><td>
+<table class="aws_data" border="0" cellpadding="1" cellspacing="0" width="100%">
+<tr valign="middle">
+<td valign="middle" width="150"><b>{php}echo $rmsg['currenttime']; {/php}</b>&nbsp;</td>
+<td valign="middle"><h4>{$now->getDate()}</h4></tr>
+<tr valign="middle">
+<td valign="middle" width="150"><b>{php}echo $rmsg['reporttime']; {/php}</b>&nbsp;</td>
+<td valign="middle">
+<select name="month">
+{foreach name=months from=$monthnames item=monthname}
+{if $selectmonth==$smarty.foreach.months.iteration}
+<option selected="true" value="{$smarty.foreach.months.iteration|string_format:"%02d"}">{$monthname}</option>
+{else}
+<option value="{$smarty.foreach.months.iteration|string_format:"%02d"}">{$monthname}</option>
+{/if}
+{/foreach}
+</select>
+<select name="year">
+<option {if $selectyear==$year-2}selected="true"{/if} value="{$year-2}">{$year-2}</option>
+<option {if $selectyear==$year-1}selected="true"{/if} value="{$year-1}">{$year-1}</option>
+<option {if $selectyear==$year}selected="true"{/if} value="{$year}">{$year}</option>
+</select>
+<input type="hidden" name="blogId" value="{$blogId}">
+<input type="submit" value="{php}echo $rmsg['view']; {/php}"></td></tr>
+</table>
+</td></tr>
+</table> 
+</form>
+<br/>
+
+{assign var=blogId value=$blog->getId()}
+{assign var=totalreadnumber value=$blogstatistics->getTotalReadNumber()}
+{assign var=totalpostnumber value=$blogstatistics->getTotalPostNumber()}
+{assign var=totalcommentnumber value=$blogstatistics->getTotalCommentNumber()}
+{assign var=totaltrackbacknumber value=$blogstatistics->getTotalTrackbackNumber()}
+{assign var=totalreferernumber value=$blogstatistics->getTotalRefererNumber()}
+{assign var=todayvisitor value=$blogstatistics->getTodayVisitor()}
+{assign var=yesterdayvisitor value=$blogstatistics->getYesterdayVisitor()}
+{assign var=weekvisitor value=$blogstatistics->getThisWeekVisitor()}
+{assign var=monthvisitor value=$blogstatistics->getThisMonthVisitor()}
+{assign var=totalvisitor value=$blogstatistics->getTotalVisitor()}
+{assign var=todaydistinctvisitor value=$blogstatistics->getTodayDistinctVisitor()}
+{assign var=yesterdaydistinctvisitor value=$blogstatistics->getYesterdayDistinctVisitor()}
+{assign var=weekdistinctvisitor value=$blogstatistics->getThisWeekDistinctVisitor()}
+{assign var=monthdistinctvisitor value=$blogstatistics->getThisMonthDistinctVisitor()}
+{assign var=totaldistinctvisitor value=$blogstatistics->getTotalDistinctVisitor()}
+{assign var=onlinevisitor value=$blogstatistics->getOnlineVisitor()}
+<br/>
+
+<center>
+<table border="0" cellpadding="2" cellspacing="0" width="100%">
+<tr><td><h3>{php}echo $rmsg['plogstat'];{/php}</h3></td></tr>
+<tr><td colspan="2">
+<table border="1" bordercolor="#C0C0C0"> 
+<tr bgcolor="#C0C0C0">
+<td width=8%><h4>{php}echo $rmsg['category'];{/php}</h4></td>
+<td width=8%><h4>{php}echo $rmsg['count'];{/php}</h4></td></tr>
+<tr>
+<td>{php}echo $rmsg['totartread'];{/php}</td>
+<td>{$totalreadnumber}</td></tr>
+<tr bgcolor="#ECECEC">
+<td>{php}echo $rmsg['totart'];{/php}</td>
+<td>{$totalpostnumber}</td></tr>
+<tr>
+<td>{php}echo $rmsg['totcomment'];{/php}</td>
+<td>{$totalcommentnumber}</td></tr>
+<tr bgcolor="#ECECEC">
+<td>{php}echo $rmsg['tottrack'];{/php}</td>
+<td>{$totaltrackbacknumber}</td></tr>
+<tr>
+<td>{php}echo $rmsg['totref'];{/php}</td>
+<td>{$totalreferernumber}</td></tr>
+<tr bgcolor="#ECECEC">
+<td>{php}echo $rmsg['totonline'];{/php}</td>
+<td>{$onlinevisitor}</td></tr>
+</table>
+</td></tr>
+</table> 
+</center>
+<br />
+
+<center>
+<table border="0" cellpadding="2" cellspacing="0" width="100%">
+<tr><td><h3>{php}echo $rmsg['traffic']; {/php}</h3></td></tr>
+<tr><td colspan="2">
+<table border="1" bordercolor="#C0C0C0">
+<tr bgcolor="#C0C0C0">
+<td width=8%><h4>{php}echo $rmsg['category']; {/php}</h4></td>
+<td width=8%><h4>{php}echo $rmsg['visitor']; {/php}</h4></td>
+<td width=8%><h4>{php}echo $rmsg['hit']; {/php}</h4></td></tr>
+<tr>
+<td>{php}echo $rmsg['today']; {/php}</td>
+<td>{$todaydistinctvisitor}</td><td>{$todayvisitor}</td></tr>
+<tr bgcolor="#ECECEC">
+<td>{php}echo $rmsg['yesterday']; {/php}</td>
+<td>{$yesterdaydistinctvisitor}</td><td>{$yesterdayvisitor}</td></tr>
+<tr>
+<td>{php}echo $rmsg['thisweek']; {/php}</td>
+<td>{$weekdistinctvisitor}</td><td>{$weekvisitor}</td></tr>
+<tr bgcolor="#ECECEC">
+<td>{php}echo $rmsg['thismonth']; {/php}</td>
+<td>{$monthdistinctvisitor}</td><td>{$monthvisitor}</td></tr>
+<tr>
+<td>{php}echo $rmsg['total']; {/php}</td>
+<td>{$totaldistinctvisitor}</td><td>{$totalvisitor}</td></tr>
+</table>
+</td></tr>
+</table>
+</center>
+<br />
+
+<center>
+<table border="0" cellpadding="2" cellspacing="0" width="100%">
+<tr><td><h3>{php}echo $rmsg['monthtop']; {/php}</h3></td></tr>
+<tr><td colspan="2">
+<table border="1" bordercolor="#C0C0C0">
+<tr bgcolor="#C0C0C0">
+<td width=10%><h4>{php}echo $rmsg['rank']; {/php}</h4></td>
+<td width=10%><h4>{php}echo $rmsg['ipaddress']; {/php}</h4></td>
+<td width=10%><h4>{php}echo $rmsg['hit']; {/php}</h4></td>
+<td width=20%><h4>{php}echo $rmsg['browser']; {/php}</h4></td>
+<td width=20%><h4>{php}echo $rmsg['ossystem']; {/php}</h4></td>
+<td width=20%><h4>{php}echo $rmsg['recentvisittime']; {/php}</h4></td></tr>
+{foreach name=topmonthvisitor from=$topmonthvisitor item=visitor}
+<tr bgcolor="{cycle values="#ffffff,#ececec"}">
+<td>{$smarty.foreach.topmonthvisitor.iteration}</td>
+<td align="left">{$visitor->getIp()}</td>
+<td>{$visitor->getHits()}</td>
+<td align="left">{$visitor->getBrowser()}</td>
+<td align="left">{$visitor->getOS()}</td>
+<td>{$visitor->getTime()}</td></tr>
+{/foreach}
+</table>
+</td></tr>
+</table>
+</center>
+<br />
+
+<center>
+<table border="0" cellpadding="2" cellspacing="0" width="100%">
+<tr><td><h3>{php}echo $rmsg['weektop']; {/php}</h3></td></tr>
+<tr><td colspan="2">
+<table border="1" bordercolor="#C0C0C0">
+<tr bgcolor="#C0C0C0"><td width=10%><h4>{php}echo $rmsg['rank']; {/php}</h4></td>
+<td width=10%><h4>{php}echo $rmsg['ipaddress']; {/php}</h4></td>
+<td width=10%><h4>{php}echo $rmsg['hit']; {/php}</h4></td>
+<td width=20%><h4>{php}echo $rmsg['browser']; {/php}</h4></td>
+<td width=20%><h4>{php}echo $rmsg['ossystem']; {/php}</h4></td>
+<td width=20%><h4>{php}echo $rmsg['recentvisittime']; {/php}</h4></td></tr>
+{foreach name=topweekvisitor from=$topweekvisitor item=visitor}
+<tr bgcolor="{cycle values="#ffffff,#ececec"}"><td>{$smarty.foreach.topweekvisitor.iteration}</td>
+<td align="left">{$visitor->getIp()}</td><td>{$visitor->getHits()}</td>
+<td align="left">{$visitor->getBrowser()}</td><td align="left">{$visitor->getOS()}</td>
+<td>{$visitor->getTime()}</td></tr>
+{/foreach}
+</table>
+</td></tr>
+</table>
+</center>
+<br />
+
+<center>
+<table border="0" cellpadding="2" cellspacing="0" width="100%">
+<tr><td><h3>{php}echo $rmsg['todaytop']; {/php}</h3></td></tr>
+<tr><td colspan="2">
+<table border="1" bordercolor="#C0C0C0">
+<tr bgcolor="#C0C0C0"><td width=10%><h4>{php}echo $rmsg['rank']; {/php}</h4></td>
+<td width=10%><h4>{php}echo $rmsg['ipaddress']; {/php}</h4></td>
+<td width=10%><h4>{php}echo $rmsg['hit']; {/php}</h4></td>
+<td width=20%><h4>{php}echo $rmsg['browser']; {/php}</h4></td>
+<td width=20%><h4>{php}echo $rmsg['ossystem']; {/php}</h4></td>
+<td width=20%><h4>{php}echo $rmsg['recentvisittime']; {/php}</h4></td></tr>
+{foreach name=topdayvisitor from=$topdayvisitor item=visitor}
+<tr bgcolor="{cycle values="#ffffff,#ececec"}"><td>{$smarty.foreach.topdayvisitor.iteration}</td>
+<td align="left">{$visitor->getIp()}</td>
+<td>{$visitor->getHits()}</td>
+<td align="left">{$visitor->getBrowser()}</td>
+<td align="left">{$visitor->getOS()}</td>
+<td>{$visitor->getTime()}</td></tr>
+{/foreach}
+</table>
+</td></tr>
+</table>
+</center>
+<br />
+
+<center>
+<table border="0" cellpadding="2" cellspacing="0" width="100%">
+<tr><td><h3>{php}echo $rmsg['recentvisit']; {/php}</h3></td></tr>
+<tr><td colspan="2">
+<table border="1" bordercolor="#C0C0C0">
+<tr bgcolor="#C0C0C0"><td width=10%><h4>{php}echo $rmsg['time']; {/php}</h4></td>
+<td width=10%><h4>{php}echo $rmsg['ipaddress']; {/php}</h4></td>
+<td width=30%><h4>{php}echo $rmsg['artread']; {/php}</h4></td>
+<td width=15%><h4>{php}echo $rmsg['referer']; {/php}</h4></td>
+<td width=20%><h4>{php}echo $rmsg['browser']; {/php}</h4></td>
+<td width=20%><h4>{php}echo $rmsg['ossystem']; {/php}</h4></td></tr>
+{foreach name=lastvisitor from=$lastvisitor item=visitor}
+<tr bgcolor="{cycle values="#ffffff,#ececec"}"><td>{$visitor->getTime()}</td>
+<td align="left">{$visitor->getIp()}</td>
+<td align="left">{if $visitor->getArticle()}{if $visitor->getArticleName()}{$visitor->getArticleName()}{else}Incorrect Article{/if}{else}Main Page{/if}</td>
+<td align="left">{if $visitor->getRefer()=="Referer Spam"}Referer Spam{elseif $visitor->getRefer()}<a href="{$visitor->getRefer()}" title="{$visitor->getRefer()|truncate:60:"..."}">{$visitor->getRefer()|truncate:30:"..."}</a>{else}None{/if}</td>
+<td align="left">{$visitor->getBrowser()}</td><td align="left">{$visitor->getOS()}</td></tr>
+{/foreach}
+</table>
+</td></tr>
+</table>
+</center>
+<br />
+
+<center>
+<table border="0" cellpadding="2" cellspacing="0" width="100%">
+<tr><td><h3>{php}echo $rmsg['monthtraffic']; {/php}</h3></td></tr>
+<tr><td colspan="2">
+<table border="1" bordercolor="#C0C0C0">
+<tr bgcolor="#C0C0C0"><td width=8%><h4>{php}echo $rmsg['month']; {/php}</h4></td>
+<td width=8%><h4>{php}echo $rmsg['visitor']; {/php}</h4></td>
+<td width=8%><h4>{php}echo $rmsg['hit']; {/php}</h4></td></tr>
+{foreach from=$visitorsmonth item=visitor}
+<tr bgcolor="{cycle values="#ffffff,#ececec"}">
+<td>{$visitor->getYear()}/{$visitor->getMonth()|string_format:"%02d"}</td>
+<td>{$visitor->getVisitors()}</td><td>{$visitor->getHits()}</td></tr>
+{/foreach}
+</table>
+</td></tr>
+</table>
+</center>
+<br />
+
+<center>
+<table border="0" cellpadding="2" cellspacing="0" width="100%">
+<tr><td><h3>{php}echo $rmsg['daytraffic']; {/php}</h3></td></tr>
+<tr><td colspan="2">
+<table border="1" bordercolor="#C0C0C0">
+<tr bgcolor="#C0C0C0"><td width=8%><h4>{php}echo $rmsg['date']; {/php}</h4></td>
+<td width=8%><h4>{php}echo $rmsg['visitor']; {/php}</h4></td>
+<td width=8%><h4>{php}echo $rmsg['hit']; {/php}</h4></td></tr>
+{foreach from=$visitorsday item=visitor}
+<tr bgcolor="{cycle values="#ffffff,#ececec"}">
+<td>{$visitor->getYear()}/{$visitor->getMonth()|string_format:"%02d"}/{$visitor->getDay()|string_format:"%02d"}</td>
+<td>{$visitor->getVisitors()}</td><td>{$visitor->getHits()}</td></tr>
+{/foreach}
+</table>
+</td></tr>
+</table>
+</center>
+<br />
+
+<center>
+<table border="0" cellpadding="2" cellspacing="0" width="100%">
+<tr><td><h3>{php}echo $rmsg['weekdaytraffic']; {/php}</h3></td></tr>
+<tr><td colspan="2">
+<table border="1" bordercolor="#C0C0C0">
+<tr bgcolor="#C0C0C0"><td width=8%><h4>{php}echo $rmsg['weekday']; {/php}</h4></td>
+<td width=8%><h4>{php}echo $rmsg['visitor']; {/php}</h4></td>
+<td width=8%><h4>{php}echo $rmsg['hit']; {/php}</h4></td></tr>
+{foreach from=$visitorsweekday item=visitor}
+<tr bgcolor="{cycle values="#ffffff,#ececec"}">
+<td>{$visitor->getWeekDay()}</td><td>{$visitor->getVisitors()}</td>
+<td>{$visitor->getHits()}</td></tr>
+{/foreach}
+</table>
+</td></tr>
+</table>
+</center>
+<br />
+
+<center>
+<table border="0" cellpadding="2" cellspacing="0" width="100%">
+<tr><td><h3>{php}echo $rmsg['hourtraffic']; {/php}</h3></td></tr>
+<tr><td colspan="2">
+<table border="1" bordercolor="#C0C0C0">
+<tr bgcolor="#C0C0C0"><td width=8%><h4>{php}echo $rmsg['hour']; {/php}</h4></td>
+<td width=8%><h4>{php}echo $rmsg['visitor']; {/php}</h4></td>
+<td width=8%><h4>{php}echo $rmsg['hit']; {/php}</h4></td></tr>
+{foreach from=$visitorshour item=visitor}
+<tr bgcolor="{cycle values="#ffffff,#ececec"}">
+<td>{$visitor->getHour()|string_format:"%02d"}</td>
+<td>{$visitor->getVisitors()}</td><td>{$visitor->getHits()}</td></tr>
+{/foreach}
+</table>
+</td></tr>
+</table>
+</center>
+<br />
+
+<!-- MC0904 START - Matthew Chin -->
+<!-- print_r(array_values($getmonth)); -->
+{php}
+
+$getmonth=$this->get_template_vars('visitorsmonth');
+$getm[0]=0;
+for ($i=1; $i<=12; $i++) 
+     $getm[$i]=($getmonth[$i]->_visitor);
+for ($i=1; $i<=12; $i++) 
+     $getm[0]+=$getm[$i]; 
+vertical($rmsg['title']['year'].$getmonth[1]->_year, 12, 12, 999999, $getm, 'bar1.gif', 1, 1, 0, $rmsg['monthdesc'], 0, $rmsg['tail']['max'], $rmsg['tail']['avg'], $rmsg['tail']['min'], $rmsg['tail']['visitors']);
+     
+$getday=$this->get_template_vars('visitorsday');
+$getd[0]=0; 
+$days = count($getday);
+for ($i=1; $i<=$days; $i++) 
+     $getd[$i]=($getday[$i]->_visitor);
+for ($i=1; $i<=$days; $i++) 
+     $getd[0]+=$getd[$i];
+vertical($rmsg['title']['month'].$rmsg['monthdesc'][$getday[1]->_month-1], $days, $days, 999999, $getd, 'bar2.gif', 1, 1, 0, 0, 0, $rmsg['tail']['max'], $rmsg['tail']['avg'], $rmsg['tail']['min'], $rmsg['tail']['visitors']);
+
+$getweekday=$this->get_template_vars('visitorsweekday');
+$getw[0]=0;
+for ($i=0; $i<7; $i++) 
+     $getw[$i+1]=($getweekday[$i]->_visitor);
+for ($i=1; $i<=7; $i++) 
+     $getw[0]+=$getw[$i];
+vertical($rmsg['title']['weekday'].$rmsg['monthdesc'][$getweekday[1]->_month-1], 7, 7, 999999, $getw, 'bar5.gif', 1, 1, 0, $rmsg['weekdesc'], 0, $rmsg['tail']['max'], $rmsg['tail']['avg'], $rmsg['tail']['min'], $rmsg['tail']['visitors']);
+
+$gethour=$this->get_template_vars('visitorshour');
+$geth[0]=0;
+for ($i=0; $i<24; $i++) 
+     $geth[$i+1]=($gethour[$i]->_visitor);
+for ($i=1; $i<=24; $i++) 
+     $geth[0]+=$geth[$i]; 
+vertical($rmsg['title']['hour'].$rmsg['monthdesc'][$gethour[1]->_month-1], 24, 24, 999999, $geth, 'bar4.gif', 1, 1, 0, $rmsg['hourdesc'], 0, $rmsg['tail']['max'], $rmsg['tail']['avg'], $rmsg['tail']['min'], $rmsg['tail']['visitors']);
+
+{/php}
+
+<!-- MC0904 END - Matthew Chin -->
+
+
+{include file="statistics/footer.template"}

Added: plugins/trunk/emailencryption/js/emailHider/demo.htm
===================================================================
--- plugins/trunk/emailencryption/js/emailHider/demo.htm	2005-01-24 14:00:45 UTC (rev 821)
+++ plugins/trunk/emailencryption/js/emailHider/demo.htm	2005-01-24 16:31:02 UTC (rev 822)
@@ -0,0 +1,24 @@
+<!-- Demo provided by CodeHouse.com -->
+
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "xhtml11.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
+<head>
+<title>E-mail Hider Demo</title>
+
+<script type="text/javascript" src="emailHider.js"></script>
+</head>
+
+<body>
+<div>
+<p>
+   <script type="text/javascript">email("webmaster", "example", "com")</script>
+</p>
+
+<p>
+   <script type="text/javascript">email("bill", "example", "org", "E-mail Me")</script>
+</p>
+
+</div>
+</body>
+</html>


Property changes on: plugins/trunk/emailencryption/js/emailHider/demo.htm
___________________________________________________________________
Name: svn:executable
   + *

Added: plugins/trunk/emailencryption/js/emailHider/emailHider.js
===================================================================
--- plugins/trunk/emailencryption/js/emailHider/emailHider.js	2005-01-24 14:00:45 UTC (rev 821)
+++ plugins/trunk/emailencryption/js/emailHider/emailHider.js	2005-01-24 16:31:02 UTC (rev 822)
@@ -0,0 +1,38 @@
+/**
+ * Copyright (C) 2004, CodeHouse.com. All rights reserved.
+ * CodeHouse(TM) is a registered trademark.
+ *
+ * THIS SOURCE CODE MAY BE USED FREELY PROVIDED THAT
+ * IT IS NOT MODIFIED OR DISTRIBUTED, AND IT IS USED
+ * ON A PUBLICLY ACCESSIBLE INTERNET WEB SITE.
+ *
+ * Script Name: E-mail Hider
+ *
+ * You can obtain this script at http://www.codehouse.com
+ */
+ 
+function email_text(name, domain, suffix, text)
+{
+   var address = name + "\u0040" + domain + "." + suffix;
+   var url = "mailto:" + address;
+
+   if( ! text )
+   {
+      text = address;
+   }
+
+   document.write("<a href=\"" + url + "\">" + text + "</a>");
+}
+
+function email_image(name, domain, suffix, text)
+{
+   var address = name + "\u0040" + domain + "." + suffix;
+   var url = "mailto:" + address;
+
+   if( ! text )
+   {
+      text = address;
+   }
+
+   document.write("<a href=\"" + url + "\">" + "<img src=\"" + text + "\">" + "</a>");
+}
\ No newline at end of file


Property changes on: plugins/trunk/emailencryption/js/emailHider/emailHider.js
___________________________________________________________________
Name: svn:executable
   + *

Added: plugins/trunk/emailencryption/pluginemailecryption.class.php
===================================================================
--- plugins/trunk/emailencryption/pluginemailecryption.class.php	2005-01-24 14:00:45 UTC (rev 821)
+++ plugins/trunk/emailencryption/pluginemailecryption.class.php	2005-01-24 16:31:02 UTC (rev 822)
@@ -0,0 +1,57 @@
+<?php
+
+    include_once( PLOG_CLASS_PATH."class/plugin/pluginbase.class.php" );
+    include_once( PLOG_CLASS_PATH."class/plugin/pluginmanager.class.php" );
+    
+    /**
+     * Plugin that offers you to encrypt e-mail address with javascript to prevent spam spider to get the real e-mail address from your blog
+     */
+    class PluginEmailEncryption extends PluginBase
+    {
+    
+        function PluginEmailEncryption()
+        {
+            $this->author = "Mark Wu";
+            $this->desc = "This plugin offers you to encrypt e-mail address with javascript to prevent spam spider to get the real e-mail address from your blog. Usage as follow:<br /><br />Add the following code to header.template<br /><br /><strong>&lt;script type=&quot;text/javascript&quot; src=&quot;js/emailhider/emailHider.js&quot;&gt;&lt;/script&gt;<br /></strong><br />And, also place the following code in postandcomments.template<br /><br /><strong>{\$comment-&gt;getUsername()} | {\$locale-&gt;formatDate(\$postDate, &quot;%d/%m/%Y, %H:%M&quot;)}</strong><br /><br />with<br /><br /><strong>{if \$comment-&gt;getUserEmail()}<br />&lt;script type=&quot;text/javascript&quot;&gt;<br />{assign var=&quot;email&quot; value=\$comment-&gt;getUserEmail()}<br />{\$emailencryption-&gt;getEmailEncryptionImageLink(\$email,&quot;/imgs/aemail.gif&quot;)}<br />&lt;/script&gt;<br />{/if} <br />{if \$comment-&gt;getUserUrl()}<br />&lt;a href=&quot;{\$comment-&gt;getUserUrl()}&quot;&gt;{\$comment-&gt;getUsername()}&lt;/a&gt; | {\$locale-&gt;formatDate(\$postDate, &quot;%d/%m/%Y, %H:%M&quot;)}<br />{else}<br />{\$comment-&gt;getUsername()} | {\$locale-&gt;formatDate(\$postDate, &quot;%d/%m/%Y, %H:%M&quot;)}<br />{/if}</strong><br /><br />And, you can use <br /><br /><strong>{\$emailencryption-&gt;getEmailEncryptionTextLink(\$email,\$text)}</strong> to generate a URL with text, or use <br /><strong>{\$emailencryption-&gt;getEmailEncryptionImageLink(\$email,\$full_image_path_or_url)}</strong> to generate URL with image.<br /><br />";
+             
+            $this->PluginBase();
+        }
+ 
+        /**
+         * Encryption with Text Presentation
+         */
+        function getEmailEncryptionTextLink( $email, $text )
+        {
+            list($name,$site) = explode("@",$email);
+            $site_element = explode(".","$site");
+            $site_element_count = count($site_element)-1;
+            $suffix = $site_element[$site_element_count];
+            unset($site_element[$site_element_count]);
+            $domain = implode(".", $site_element);
+
+            $email_encryption = 'email_text("'.$name.'","'.$domain.'","'.$suffix.'","'.$text.'")';
+                        
+            return $email_encryption;
+        }
+
+        /**
+         * Encryption with Image Presentation
+         */
+        function getEmailEncryptionImageLink( $email, $text )
+        {
+            list($name,$site) = explode("@",$email);
+            $site_element = explode(".","$site");
+            $site_element_count = count($site_element)-1;
+            $suffix = $site_element[$site_element_count];
+            unset($site_element[$site_element_count]);
+            $domain = implode(".", $site_element);
+
+            $email_encryption = 'email_image("'.$name.'","'.$domain.'","'.$suffix.'","'.$text.'")';
+                        
+            return $email_encryption;
+        }
+        
+    }
+    
+    PluginManager::registerPlugin( "emailencryption", "PluginEmailEncryption" );
+?>
\ No newline at end of file


Property changes on: plugins/trunk/emailencryption/pluginemailecryption.class.php
___________________________________________________________________
Name: svn:executable
   + *

Added: plugins/trunk/galleryimages/plugingalleryimages.class.php
===================================================================
--- plugins/trunk/galleryimages/plugingalleryimages.class.php	2005-01-24 14:00:45 UTC (rev 821)
+++ plugins/trunk/galleryimages/plugingalleryimages.class.php	2005-01-24 16:31:02 UTC (rev 822)
@@ -0,0 +1,92 @@
+<?php
+
+    include_once( PLOG_CLASS_PATH."class/plugin/pluginbase.class.php" );
+    include_once( PLOG_CLASS_PATH."class/plugin/pluginmanager.class.php" );
+    include_once( PLOG_CLASS_PATH."class/gallery/dao/galleryresources.class.php" );
+    
+    /**
+     * Plugin that offers features such as to return a random image from the 
+     * public collections/albums, the latest image added, and so on
+     */
+    class PluginGalleryImages extends PluginBase
+    {
+    
+        function PluginGalleryImages()
+        {
+            $this->author = "The pLog Team";
+            $this->desc = "This plugin offers two methods, one for fetching the most recently uploaded image and another one for retrieving a random image from our collection. Needless to say, this plugin only returns images and not any other type of resource. Only images that belong to public albums will be used. <br /><br />You can use the following snippet of template code to show the latest uploaded image in your templates:<br /><br /><b>{assign var=latestImage value=\$galleryimages-&gt;latestImage(8)}<br />&lt;a href=&quot;{\$url-&gt;resourceLink(\$latestImage)}&quot;&gt;<br />&lt;img style=&quot;border:0px;&quot; src=&quot;{\$url-&gt;resourcePreviewLink(\$latestImage)}&quot; alt=&quot;{\$latestImage-&gt;getDescription()}&quot; /&gt;<br />&lt;/a&gt;</b> <br /><br />To show a random image from your collection, you can use the following snippet: <br /><br /><b>{assign var=randomImage value=\$galleryimages-&gt;randomImage(9)}<br />&lt;a href=&quot;{\$url-&gt;resourceLink(\$randomImage)}&quot;&gt;<br />&lt;img style=&quot;border:0px;&quot; src=&quot;{\$url-&gt;resourcePreviewLink(\$randomImage)}&quot; alt=&quot;{\$randomImage-&gt;getDescription()}&quot; /&gt;<br />&lt;/a&gt;</b></p><p>And, you can use <br /><br /><strong>{\$galleryimages-&gt;randomImage(8)}</strong> to get 1 random image from album id=8, or use <br /><strong>{\$galleryimages-&gt;randomImage(10,3)}</strong> to get the 3 random images from album id=10 </p><p>Or, you also can use</p><p><strong>{\$galleryimages-&gt;lastImage(8)}</strong> to get last 1 upload image from album id=8, or use <br /><strong>{\$galleryimages-&gt;lastImage(10,3)}</strong> to get last 3 upload images from album id=10 <br /><br />";
+            
+            $this->PluginBase();
+        }
+ 
+        /**
+         * Returns the GalleryResource object of the latest image uploaded to the database
+         */
+        function latestImage( $album_id, $maxImages = 1)
+        {
+            $resources = new GalleryResources();
+            $prefix = $resources->getPrefix();
+            $blogId = $this->blogInfo->getId();
+            
+            // quite a long query here... but we have to choose only images, and from those
+            // images, only those that belong to albums that have been set to be shown
+            // in the public side
+            $query = "SELECT r.id AS id, r.owner_id AS owner_id, r.album_id AS album_id,
+                      r.description AS description, r.date AS date, r.flags AS flags,
+                      r.resource_type AS resource_type, r.file_path AS file_path,
+                      r.file_name AS file_name, r.metadata AS metadata, 
+                      r.thumbnail_format AS thumbnail_format
+                      FROM {$prefix}gallery_resources r, {$prefix}gallery_albums a
+                      WHERE r.resource_type = 1 AND a.show_album = 1 AND r.album_id = {$album_id} AND a.id = {$album_id}
+                      AND r.owner_id = $blogId
+                      ORDER BY r.date DESC LIMIT 0, {$maxImages}";
+            // just to make things easier, we'll cheat a little here...
+
+            $result = $resources->_db->Execute( $query );
+
+            if( !$result )
+                return false;
+                
+            $latestimages = Array();
+            while( $row = $result->FetchRow()) { 
+               array_push( $latestimages, $resources->_fillResourceInformation( $row )); 
+            } 
+            
+            return $latestimages;
+        }         
+        
+        /**
+         * Returns the GalleryResource object of a random image from one of the public albums
+         */
+        function randomImage( $album_id, $maxImages = 1 )
+        {
+            $resources = new GalleryResources();
+            $prefix = $resources->getPrefix();
+            $blogId = $this->blogInfo->getId();
+            
+            $query = "SELECT r.id AS id, r.owner_id AS owner_id, r.album_id AS album_id,
+                      r.description AS description, r.date AS date, r.flags AS flags,
+                      r.resource_type AS resource_type, r.file_path AS file_path,
+                      r.file_name AS file_name, r.metadata AS metadata, 
+                      r.thumbnail_format AS thumbnail_format
+                      FROM {$prefix}gallery_resources r, {$prefix}gallery_albums a
+                      WHERE r.resource_type = 1 AND a.show_album = 1 AND r.album_id = {$album_id} AND a.id = {$album_id}
+                      AND r.owner_id = $blogId
+                      ORDER BY RAND() LIMIT 0, {$maxImages}";
+            // just to make things easier, we'll cheat a little here...
+            $result = $resources->_db->Execute( $query );
+            if( !$result )
+                return false;
+                
+            $randomimages = Array();
+            while( $row = $result->FetchRow()) { 
+               array_push( $randomimages, $resources->_fillResourceInformation( $row )); 
+            } 
+            
+            return $randomimages;
+        }
+    }
+    
+    PluginManager::registerPlugin( "galleryimages", "PluginGalleryImages" );
+
+?>
\ No newline at end of file


Property changes on: plugins/trunk/galleryimages/plugingalleryimages.class.php
___________________________________________________________________
Name: svn:executable
   + *

Added: plugins/trunk/google/docs/readme.html
===================================================================
--- plugins/trunk/google/docs/readme.html	2005-01-24 14:00:45 UTC (rev 821)
+++ plugins/trunk/google/docs/readme.html	2005-01-24 16:31:02 UTC (rev 822)
@@ -0,0 +1,51 @@
+<html>
+ <head>
+  <title>pLog Google Plugin</title>
+ </head>
+ <body>
+ <h1>pLog Google Plugin</h1>
+ <p>
+  The pLog Google plugin is a very simple plugin that will highlight all the search terms if
+  somebody is coming to our page from Google (it will scan the referer) At the moment, Google
+  is the only search engine detected and handled correctly but more will be added in the future.
+ </p>
+ <p>
+  The plugin must be copied to the root folder of pLog. You will know that it works because
+  you will see a new plugin in the "Plugin Center" section in the administration interface of
+  you blog. pLog 0.2 or higher is required for this plugin to work.
+ </p>
+ <p>
+  The Google plugin will automatically highlight all the words from the search string, using a set
+  of colours similar to what the "real" Google users. Additionally, we can make the plugin to show
+  a greeting text to Google visitors, showing which words have been highlighted and which colours
+  have been used.
+ </p>
+ <p>
+  First of all, to get the plugin working we have to add the following to the <b>header.template</b>
+  file:
+  <pre>
+{$google->start()}
+  </pre>
+  And the following to the <b>footer.template</b> file:
+  <pre>
+{$google->end()}
+  </pre>
+  This is done to tell the plugin where our page starts and where our page ends. Should you wish
+  to reduce the places where the plugin searches for matches, then place those "markers" somewhere
+  else in the page but do not forget one of them, otherwise the client browser will probably only
+  receive a blank page.
+ </p>
+ <p>
+  To enable the greeting text, we have to <b>literally</b> add the following string anywhere
+  in the page where we'd like to show the greeting to Google users:
+ <pre>
+[googleplugin]
+ </pre>
+ It is recommeded to add it somewhere close to the top. The Google plugin will replace that text
+ for a nicer greeting text if there was any match found. If not, the text will be replaced with an
+ empty string (so that it will not appear if there are no matches) At the moment the text is in
+ English and it can only be changed by editing the code of the plugin but future versions of the plugin
+ will allow to configure the text too.
+ </p>
+ </body>
+</html>
\ No newline at end of file

Added: plugins/trunk/google/plugingoogle.class.php
===================================================================
--- plugins/trunk/google/plugingoogle.class.php	2005-01-24 14:00:45 UTC (rev 821)
+++ plugins/trunk/google/plugingoogle.class.php	2005-01-24 16:31:02 UTC (rev 822)
@@ -0,0 +1,136 @@
+<?php
+
+	include_once( PLOG_CLASS_PATH."class/plugin/pluginbase.class.php" );
+    include_once( PLOG_CLASS_PATH."class/plugin/pluginmanager.class.php" );
+    include_once( PLOG_CLASS_PATH."class/net/url.class.php" );
+
+    /**
+     * Implementation to highlight the search terms if the user is coming from google.
+     *
+     * Based on google_hilite from Textism, http://www.textism.com/tools/google_hilite/
+     */
+    class PluginGoogle extends PluginBase {
+
+    	var $colors = Array( "yellow",
+                             "lightpink",
+                             "aquamarine",
+                             "darkgoldenrod",
+                             "darkseagreen",
+                             "lightgreen",
+                             "rosybrown",
+                             "seagreen",
+                             "chocolate",
+                             "violet" );
+
+    	function PluginGoogle()
+        {
+        	$this->PluginBase();
+
+            $this->desc = <<<EOD
+This plugin will highlight the search terms entered by a Google user when arriving to
+your blog.<br/><br/>To enable the plugin, you must include \{\$google->start()} somewhere in the
+beginning of your page and \{\$google->end()} somewhere near the end. Anything else
+outside the boundaries marked by the calls to the start() and end() methods will not
+be highlighted by the plugin. A very effective solutions is to put \{\$google->start()}
+in the very beginning of the header.template file and \{\$google->end()} and the very end
+of the footer.template file, to ensure that all the content of your pages will be scanned.<br/>
+<br/>
+The plugin will automatically highlight the search terms and should you wish to display
+a generated message containing information about the terms that have been highlighted, in the
+same way Google does, then you can place the string <b>[googleplugin]</b> anywhere in your
+templates and it will be automatically replaced by a message similar to:<br/><br/>
+<b>Google user, I have highlighted the following terms for you:
+<span style="background:yellow">term1</span>&nbsp;
+<span style="background:lightpink">term2</span>&nbsp;
+<span style="background:aquamarine">term3</span>&nbsp;</b>
+<br/><br/>
+If you wish to customize the way this message looks, it is possible to do so using
+CSS. The message is included within a &lt;div class="googlepluginmessage"&gt;...&lt;/div&gt;
+<br/><br/>
+Please reports any bugs to the pLog team! :)
+EOD;
+            $this->author = "The pLog team";
+
+            $this->totalReplacements = 0;
+            $this->highlightedTerms  = "";
+        }
+
+        function start()
+        {
+        	ob_start();
+        }
+
+        function google_hilite($text) {
+
+        	//$ref = urldecode($_SERVER[HTTP_REFERER]);
+
+            $url = new Url($_SERVER["HTTP_REFERER"]);
+
+            # let's see if the referrer is google
+            //if (preg_match('/^http:\/\/w?w?w?\.?google.*/i',$url->getHost())) {
+            if (preg_match('/^w?w?w?\.?google.*/i',$url->getHost())) {
+
+            	# chop the search terms into an array
+                $query_array = $url->getQueryArray();
+
+            	if( $query_array["q"] == "" || empty($query_array["q"]))
+            		return false;
+
+            	// otherwise, we can proceed to highlight the words!
+            	$searchTerms = explode( " ", $query_array["q"] );
+
+                // assign a color to each google search term
+                $i=0;
+                $this->highlightedTerms = "<div class=\"googlepluginmessage\">Google user, I have highlighted the following terms for you: ";
+
+                for($i=0; $i<count($searchTerms); $i++ ) {
+                	$searchTerms[$i] = trim(str_replace( "+", "", $searchTerms[$i]));
+                    $searchTerms[$i] = str_replace( "\"", "", $searchTerms[$i]);
+                	$assignedColors[$searchTerms[$i]] = $this->colors[$i%count($this->colors)];
+
+                    $this->highlightedTerms .= "<span style=\"background:".$assignedColors[$searchTerms[$i]]."\">".$searchTerms[$i]."</span>&nbsp;";
+                }
+
+                //print($highlightedTerms);
+                $this->highlightedTerms .= "</div>";
+
+            	# loop through the search terms
+            	foreach($searchTerms as $b){
+
+                	if( $b != "" || !empty($b)) {
+                    	//$b = trim($b);
+                        // if the string ends up having '+' sings, the regular expression
+                        // parser will surely not like it!
+                        $b = trim(str_replace( "+", "", $b ));
+            			if (!preg_match('/<.+>/',$text)) {
+                			# If there are no tags in the text, we'll just do a simple search and replace
+                    		$text = preg_replace('/(\b'.$b.'\b)/i','<span style="background:'.$assignedColors[$b].'">$1</span>',$text);
+                            $this->totalReplacements++;
+                		}
+                		else {
+                			# If there are tags, we need to stay outside them
+                    		$text = preg_replace('/(?<=>)([^<]+)?(\b'.$b.'\b)/i','$1<span style="background:'.$assignedColors[$b].'">$2</span>',$text);
+                            $this->totalReplacements++;
+                		}
+                    }
+            	}
+        	}
+
+        	return $text;
+        }
+
+        function end()
+        {
+        	$contents = ob_get_contents();
+
+            ob_end_clean();
+
+            $hilite = $this->google_hilite($contents);
+            $hilite = str_replace( "[googleplugin]", $this->highlightedTerms, $hilite );
+
+            print( $hilite );
+        }
+    }
+
+    PluginManager::registerPlugin( "google", "PluginGoogle" );
+?>

Added: plugins/trunk/haiku/pluginhaiku.class.php
===================================================================
--- plugins/trunk/haiku/pluginhaiku.class.php	2005-01-24 14:00:45 UTC (rev 821)
+++ plugins/trunk/haiku/pluginhaiku.class.php	2005-01-24 16:31:02 UTC (rev 822)
@@ -0,0 +1,554 @@
+<?php
+    include_once( PLOG_CLASS_PATH."class/plugin/pluginbase.class.php" );
+    include_once( PLOG_CLASS_PATH."class/plugin/pluginmanager.class.php" );
+
+    define( "DEFAULT_HAIKUS_FILENAME", "./haiku/haiku.sql" );
+
+    /**
+     * Implementation of a very simple haiku plugin
+     */
+    class PluginHaiku extends PluginBase {
+
+        function PluginHaiku()
+        {
+        $this->PluginBase();
+
+            $this->desc = "
+            This plugin will generate a random Haiku<br/>
+        <br/>
+        Usage (Place these somewhere in your favorite template:<br/>
+            &nbsp;&nbsp;To Display The Haiku:
+            &nbsp;&nbsp;{\$haiku->getHaiku()}<br/>
+            &nbsp;&nbsp;To Display The Possible Permutations:
+            &nbsp;&nbsp;{\$haiku->getHaikuPermutations()}<br/>
+            &nbsp;&nbsp;To Display Haiku Status:
+            &nbsp;&nbsp;{\$haiku->getHaikuStats()}<br/>
+        ";
+            $this->author = "Darren Greer";
+
+        // connect to the database
+        $this->connectDb();
+
+        if( $this->checkHaikuDatabase($params) == true ) {
+          $this->setDefaultConfigMessage();
+        } else {
+          $this->setCreateConfigMessage();
+        }
+
+        }
+
+        function getHaiku()
+        {
+      // we need to take into account that plog has definable
+      // prefixes for the database
+      // so it is not sure that the user will have chosen 'plog_'
+      // as the prefix... could be anything else!!
+      $config = new Config();
+      $dbPrefix = $config->getValue( "db_prefix" );
+
+      // get the current blog_id
+          $blogId = $this->blogInfo->getId();
+
+      // First 5 syllable line
+          $query = "SELECT * FROM {$dbPrefix}haiku where haiku_syl=5 and (haiku_blog_id = $blogId or haiku_blog_id = 0 ) order by rand() LIMIT 1";
+      $result = $this->db->Execute( $query );
+      if( !$result ) 
+        return false;
+      if( $result->RecordCount() == 0 ) {
+        $this->setConfigurationErrorMessage( "Could Not Get A 5 Syllable Entry" );
+        return false;
+      }
+      $row=$result->FetchRow();
+          extract($row);
+          $return = "<i> $haiku_text </i><b> <=> </b>";
+
+      // 7 syllable line
+          $query = "SELECT * FROM {$dbPrefix}haiku where haiku_syl=7 and (haiku_blog_id = $blogId or haiku_blog_id = 0 ) order by rand() LIMIT 1";
+      $result = $this->db->Execute( $query );
+      if( !$result )
+        return false;
+      if( $result->RecordCount() == 0 ) {
+        $this->setConfigurationErrorMessage( "Could Not Get A 7 Syllable Entry" );
+        return false;
+      }
+      $row=$result->FetchRow();
+          extract($row);
+          $return = $return . "<i> $haiku_text </i><b> <=> </b>";
+
+      // Second 5 syllable line
+          $query = "SELECT * FROM {$dbPrefix}haiku where haiku_syl=5 and (haiku_blog_id = $blogId or haiku_blog_id = 0 ) order by rand() LIMIT 1";
+      $result = $this->db->Execute( $query );
+      if( !$result )
+        return false;
+      if( $result->RecordCount() == 0 ) {
+        $this->setConfigurationErrorMessage( "Could Not Get A 5 Syllable Entry" );
+        return false;
+      }
+      $row=$result->FetchRow();
+          extract($row);
+          $return = $return . "<i> $haiku_text </i>";
+          return $return;
+        }
+
+        function getHaikuPermutations()
+        {
+      // we need to take into account that plog has definable
+      // prefixes for the database
+      // so it is not sure that the user will have chosen 'plog_'
+      // as the prefix... could be anything else!!
+      $config = new Config();
+      $dbPrefix = $config->getValue( "db_prefix" );
+
+      // get the current blog_id
+          $blogId = $this->blogInfo->getId();
+
+      // Get Possible Combinations
+          $query = "SELECT count(*) as count5 FROM {$dbPrefix}haiku where haiku_syl=5 and (haiku_blog_id = $blogId or haiku_blog_id = 0 )";
+      $result = $this->db->Execute( $query );
+      if( !$result )
+        return false;
+      if( $result->RecordCount() == 0 ) {
+        $this->setConfigurationErrorMessage( "No Records Found" );
+        return false;
+      }
+      $row=$result->FetchRow();
+          extract($row);
+
+          $query = "SELECT count(*) as count7 FROM {$dbPrefix}haiku where haiku_syl=7 and (haiku_blog_id = $blogId or haiku_blog_id = 0 )";
+      $result = $this->db->Execute( $query );
+      if( !$result )
+        return false;
+      if( $result->RecordCount() == 0 ) {
+        $this->setConfigurationErrorMessage( "No Records Found" );
+        return false;
+      }
+      $row=$result->FetchRow();
+          extract($row);
+
+      $total_combs = ($count5 * $count7 * $count5);
+      $return = "<b>$total_combs</b>";
+
+          return $return;
+        }
+
+        function getHaikuStats()
+        {
+      // we need to take into account that plog has definable
+      // prefixes for the database
+      // so it is not sure that the user will have chosen 'plog_'
+      // as the prefix... could be anything else!!
+      $config = new Config();
+      $dbPrefix = $config->getValue( "db_prefix" );
+
+      // get the current blog_id
+      $blogId = $this->blogInfo->getId();
+
+      // Get Possible Combinations
+          $query = "SELECT count(*) as count5 FROM {$dbPrefix}haiku where haiku_syl=5 and (haiku_blog_id = $blogId or haiku_blog_id = 0 )";
+      $result = $this->db->Execute( $query );
+      if( !$result )
+        return false;
+      if( $result->RecordCount() == 0 ) {
+        $this->setConfigurationErrorMessage( "No Records Found" );
+        return false;
+      }
+      $row=$result->FetchRow();
+          extract($row);
+
+          $query = "SELECT count(*) as count7 FROM {$dbPrefix}haiku where haiku_syl=7 and (haiku_blog_id = $blogId or haiku_blog_id = 0 )";
+      $result = $this->db->Execute( $query );
+      if( !$result )
+        return false;
+      if( $result->RecordCount() == 0 ) {
+        $this->setConfigurationErrorMessage( "No Records Found" );
+        return false;
+      }
+      $row=$result->FetchRow();
+          extract($row);
+
+      $return = "5 Syllable: <b>$count5</b><br/>";
+      $return = $return . "7 Syllable: <b>$count7</b>";
+
+          return $return;
+        }
+
+        function configure( $params )
+        {
+             // Get the config values
+      $config = new Config();
+      $dbPrefix = $config->getValue( "db_prefix" );
+
+      $haikuFunction = $params->getValue( "Update" );
+
+      if($haikuFunction == 'Add') {
+
+        // execute the add function
+        if( $this->addHaiku($params) == true ) {
+          return true;
+        } else {
+          return false;
+        }
+
+      } else if( $haikuFunction == "Search" ) {
+
+        // execute the search function
+        if( $this->searchHaiku($params) == true ) {
+          return true;
+        } else {
+          return false;
+        }
+
+      } else if( $haikuFunction == "Update" ) {
+
+        // execute the update function
+        if( $this->updateHaiku($params) == true ) {
+          return true;
+        }    else {
+          return false;
+        }
+
+      } else if( $haikuFunction == "Delete" ) {
+
+        // execute the delete function
+        if( $this->deleteHaiku($params) == true ) {
+          return true;
+        }    else {
+          return false;
+        }
+
+      } else if( $haikuFunction == "Edit" ) {
+
+        // execute the edit function
+        if( $this->editHaiku($params) == true ) {
+          return true;
+        }    else {
+          return false;
+        }
+
+      } else if( $haikuFunction == "Create" ) {
+
+        // execute the create function
+        if( $this->createHaikuDatabase($params) == true ) {
+          return true;
+        }    else {
+          return false;
+        }
+
+      } else {
+        if( $this->checkHaikuDatabase($params) == true ) {
+          $this->setDefaultConfigMessage();
+          return true;
+        } else {
+          $this->setCreateConfigMessage();
+          return true;
+        }
+      }
+
+        }
+
+        function setCreateConfigMessage()
+    {
+      $this->configMessage = '
+      <form name="haikuPluginConfiguration" method="POST" action="admin.php">
+        <strong>No Haiku Table Found ... Shall I Create It?</strong><br>
+        <br/>
+        <input type="hidden" name="pluginId" value="haiku"/>
+        <input type="hidden" name="op" value="updatePluginConfig"/>
+        <input type="submit" name="Update" value="Create"/>
+        <input type="submit" name="Update" value="Cancel"/>
+      </form>
+      ';
+    }
+
+        function setDefaultConfigMessage()
+    {
+      $this->configMessage = '
+      <form name="haikuPluginConfiguration" method="POST" action="admin.php">
+        <strong>Enter Haiku Below</strong><br>
+        Haiku Text: <input type="text" size="50" name="haikuPluginText" value=""/><br/>
+        Haiku Syllable: <select name="haikuPluginSyllable">
+          <option value="5">5</option>
+          <option value="7">7</option>
+        </select>
+        <br/>
+        <input type="hidden" name="pluginId" value="haiku"/>
+        <input type="hidden" name="op" value="updatePluginConfig"/>
+        <input type="submit" name="Update" value="Add"/>
+      </form>
+      <hr>
+      <form name="haikuPluginConfiguration" method="POST" action="admin.php">
+        Search: <input type="text" size="50" name="haikuSearch" value=""/><br/>
+        <input type="hidden" name="pluginId" value="haiku"/>
+        <input type="hidden" name="op" value="updatePluginConfig"/>
+        <input type="submit" name="Update" value="Search"/>
+      </form>
+      ';
+    }
+
+        function setAddConfigMessage()
+    {
+      $this->configMessage = '
+      <form name="haikuPluginConfiguration" method="POST" action="admin.php">
+        <strong>Enter Haiku Below</strong><br>
+        Haiku Text: <input type="text" size="50" name="haikuPluginText" value=""/><br/>
+        Haiku Syllable: <select name="haikuPluginSyllable">
+          <option value="5">5</option>
+          <option value="7">7</option>
+        </select>
+        <br/>
+        <input type="hidden" name="pluginId" value="haiku"/>
+        <input type="hidden" name="op" value="updatePluginConfig"/>
+        <input type="submit" name="Update" value="Add"/>
+      </form>
+      ';
+    }
+
+        function setSearchConfigMessage()
+    {
+      $this->configMessage = $this->configMessage . '
+      <form name="haikuPluginConfiguration" method="POST" action="admin.php">
+        Search: <input type="text" size="50" name="haikuSearch" value=""/><br/>
+        <input type="hidden" name="pluginId" value="haiku"/>
+        <input type="hidden" name="op" value="updatePluginConfig"/>
+        <input type="submit" name="Update" value="Search"/>
+      </form>
+      ';
+    }
+
+        function setEditConfigMessage($row)
+    {
+          extract($row);
+      $this->configMessage = '
+      <form name="haikuPluginConfiguration" method="POST" action="admin.php">
+        <strong>Edit Haiku Below</strong><br>
+        Haiku Text <i>['.$haiku_syl.']</i>: <input type="text" size="50" name="haikuPluginText" value="'.$haiku_text.'"/><br/>
+        <br/>
+        <input type="hidden" name="haikuId" value="'.$haiku_id.'"/>
+        <input type="hidden" name="pluginId" value="haiku"/>
+        <input type="hidden" name="op" value="updatePluginConfig"/>
+        <input type="submit" name="Update" value="Update"/>
+        <input type="submit" name="Update" value="Cancel"/>
+      </form>
+      ';
+    }
+
+    function searchHaiku( $params )
+    {
+             // Get the config values
+      $config = new Config();
+      $dbPrefix = $config->getValue( "db_prefix" );
+
+      // Add the add haiku form
+      $this->setAddConfigMessage();
+      $this->configMessage = $this->configMessage . "<hr>\n";
+
+      // What are we searching for?
+      $haikuSearch = $params->getValue( "haikuSearch" );
+
+      // Execute the query
+      $blogId = $this->blogInfo->getId();
+          $query = "SELECT * FROM {$dbPrefix}haiku where haiku_text like '%$haikuSearch%' and (haiku_blog_id = $blogId or haiku_blog_id = 0)";
+      $result = $this->db->Execute( $query );
+      if( !$result ) {
+        $this->setConfigurationErrorMessage( "No Results" );
+        return false;
+      }
+      if( $result->RecordCount() == 0 )
+        return false;
+      // Loop through the rows and print out the results
+      while( $row = $result->FetchRow($result)) {
+            extract($row);
+        $this->configMessage = $this->configMessage . 
+        '<form name="haikuPluginConfiguration" method="POST" action="admin.php"><i>['.
+        $haiku_syl . ']</i>&nbsp;' . $haiku_text . '
+        <input type="hidden" name="haikuId" value="'.$haiku_id.'"/>
+        <input type="hidden" name="pluginId" value="haiku"/>
+        <input type="hidden" name="op" value="updatePluginConfig"/>
+        <input type="submit" name="Update" value="Edit"/>
+        <input type="submit" name="Update" value="Delete"/>
+        </form>
+        ';
+      }
+
+      $this->configMessage = $this->configMessage . "<br/><hr>\n";
+      $this->setSearchConfigMessage();
+
+      return true;
+    }
+
+    function updateHaiku( $params )
+    {
+             // Get the config values
+      $config = new Config();
+      $dbPrefix = $config->getValue( "db_prefix" );
+
+      $haikuId = $params->getValue( "haikuId" );
+      $haikuPluginText = $params->getValue( "haikuPluginText" );
+
+      // Update the entry    
+          $query = "UPDATE {$dbPrefix}haiku set haiku_text = '{$haikuPluginText}' where haiku_id={$haikuId}";
+      if( $this->db->Execute( $query ) ) {
+        return true;
+      } else {
+        $this->setConfigurationErrorMessage( "Record Not Updated" );
+        return false;
+      }
+
+      return true;
+    }
+
+    function deleteHaiku( $params )
+    {
+             // Get the config values
+      $config = new Config();
+      $dbPrefix = $config->getValue( "db_prefix" );
+
+      $haikuId = $params->getValue( "haikuId" );
+
+      // Delete the entry    
+          $query = "DELETE FROM {$dbPrefix}haiku where haiku_id={$haikuId}";
+      if( $this->db->Execute( $query ) ) {
+        return true;
+      } else {
+        $this->setConfigurationErrorMessage( "Record Not Found" );
+        return false;
+      }
+
+      return true;
+    }
+
+    function editHaiku( $params )
+    {
+             // Get the config values
+      $config = new Config();
+      $dbPrefix = $config->getValue( "db_prefix" );
+
+      $haikuId = $params->getValue( "haikuId" );
+
+      // Grab the Haiku
+          $query = "SELECT * FROM {$dbPrefix}haiku where haiku_id={$haikuId}";
+      $result = $this->db->Execute( $query );
+      if( !$result ) {
+        $this->setConfigurationErrorMessage( "Record Not Found" );
+        return false;
+      }
+      if( $result->RecordCount() == 0 ) {
+        $this->setConfigurationErrorMessage( "Record Not Found" );
+        return false;
+      }
+      $row = $result->FetchRow($result);
+
+      $this->setEditConfigMessage($row);
+
+      return true;
+    }
+
+    function addHaiku( $params )
+    {
+             // Get the config values
+      $config = new Config();
+      $dbPrefix = $config->getValue( "db_prefix" );
+
+          // fetch parameters coming from the user
+      $haikuParameter = $params->getValue( "haikuPluginText" );
+      $syllableParameter = $params->getValue( "haikuPluginSyllable" );
+
+      // check that they are valid
+      if( $haikuParameter == "" || $syllableParameter == "" ) {
+        // If not valid, tell the plugin manager (by returning false, and set error)
+        $this->setConfigurationErrorMessage( "You need to enter the Haiku text, and select a syllable entry" );
+        return false;
+      }
+
+      // get the current locale
+      $locale = $this->blogSettings->getValue( "default_locale" );
+
+      // verify locale was retrieved
+      if( $locale == "" )
+        $locale = "en_UK";
+    
+      // get the current date/time
+      $l = new Locale($locale);
+      $t = new Timestamp($your_sql_date);
+      $dateString = $l->formatDate($t, "%Y-%m-%d %H:%M:%S");
+
+      // get the current blog_id and user_id
+      $blogId = $this->blogInfo->getId();
+          $userId = $this->userInfo->getId();
+      $ownerId = $this->blogInfo->getOwner();
+
+      // if everything is ok, save the Haiku
+          $query = "INSERT INTO {$dbPrefix}haiku (haiku_syl, haiku_text, haiku_date, haiku_owner_id, haiku_blog_id) VALUES ('$syllableParameter','$haikuParameter','$dateString','$userId','$blogId')";
+      $this->db->Execute( $query );
+    
+      return true;
+    }
+
+    function createHaikuDatabase( $params )
+    {
+             // Get the config values
+      $config = new Config();
+      $dbPrefix = $config->getValue( "db_prefix" );
+
+      // Create the Haiku Database
+          $query = "
+        CREATE TABLE {$dbPrefix}haiku (
+        haiku_id int(11) NOT NULL auto_increment,
+        haiku_syl int(11) NOT NULL default '0',
+        haiku_text varchar(255) NOT NULL default '',
+        haiku_date datetime NOT NULL default '0000-00-00 00:00:00',
+        haiku_owner_id int(11) NOT NULL default '0',
+        haiku_blog_id int(11) NOT NULL default '0',
+        UNIQUE KEY haiku_text (haiku_text),
+        UNIQUE KEY haiku_id (haiku_id)
+        )
+      ";
+      if( $this->db->Execute( $query ) ) {
+        $this->insertDefaultHaikus();
+        $this->setDefaultConfigMessage();
+        return true;
+      } else {
+        $this->setConfigurationErrorMessage( "Could Not Create Table" );
+        return false;
+      }
+
+      return true;
+    }
+
+    function insertDefaultHaikus()
+    {
+    	// if the file does not exists or if it's not readable, forget about it
+    	if( !File::isReadable( DEFAULT_HAIKUS_FILENAME ))
+        	return true;
+
+        // otherwise, import it and add the haikus to the db
+        $blogId = $this->blogInfo->getId();
+        include_once( DEFAULT_HAIKUS_FILENAME );
+
+        foreach( $haikus as $haiku ) {
+        	print("adding ".$haiku."<br/>");
+        	$this->db->Execute( $haiku );
+        }
+
+        return true;
+    }
+
+    function checkHaikuDatabase( $params )
+    {
+             // Get the config values
+      $config = new Config();
+      $dbPrefix = $config->getValue( "db_prefix" );
+
+          $query = "SELECT count(*) FROM {$dbPrefix}haiku";
+      if($this->db->Execute( $query )) {
+        return true;
+      } else {
+        $this->setConfigurationErrorMessage( "DB Does Not Exist" );
+        return false;
+      }
+    }
+
+    }
+
+    PluginManager::registerPlugin( "haiku", "PluginHaiku" );
+?>

Added: plugins/trunk/haiku/readme.html
===================================================================
--- plugins/trunk/haiku/readme.html	2005-01-24 14:00:45 UTC (rev 821)
+++ plugins/trunk/haiku/readme.html	2005-01-24 16:31:02 UTC (rev 822)
@@ -0,0 +1,31 @@
+<html>
+ <head>
+  <title>pLog Haiku Plugin</title>
+ </head>
+ <body>
+ <h1>pLog Google Plugin</h1>
+ <p>
+  The Haiku plugin will allow you to show a random Haiku anywhere in your template pages of pLog. The plugin
+  needs an additional table in the database but the plugin itself will take care of creating it upon the first
+  run. The plugin will also add some default haikus to the blog t, so that we do not start with an empty list
+  of haikus. The plugin has been authored by <a href="http://someblog.com">Darren Greer</a>.
+ </p>
+ <p>
+  When clicking the "configure" link, the plugin offers the possibility to search for a haiku or add a new 5 or 7
+  syllable haiku. After looking for haiku, we will also be allowd to either edit or delete it if we don't like it. Different
+  blogs can have its own set of haikus as well as the global ones, meaning that every time a haiku is added, it will also
+  be used when generating a haiku for that blog and for no other blog.
+ </p>
+ </p>
+  In order to enable the haiku plugin in our pages, we need to add the following code to wherever we wish to show a
+  haiku:
+  <pre>
+    {$haiku->getHaiku()}
+  </pre>
+  If we want to show the number of permutations available in the database, then we should add the following:
+  <pre>
+    {$haiku->getPermutations()}
+  </pre>
+ </p>
+ </body>
+</html>

Added: plugins/trunk/jsdictionary/docs/readme.html
===================================================================
--- plugins/trunk/jsdictionary/docs/readme.html	2005-01-24 14:00:45 UTC (rev 821)
+++ plugins/trunk/jsdictionary/docs/readme.html	2005-01-24 16:31:02 UTC (rev 822)
@@ -0,0 +1,53 @@
+<html>
+ <head>
+  <title>pLog JsDictionary Plugin</title>
+ </head>
+ <body>
+ <h1>JsDictionary Plugin</h1>
+ <p>
+  This is a very simple plugin that, with a little bit of Javascript, will allow your users to get information about any
+  word or piece of text that appears in your site. What can that information be? Well, that depends up to the person
+  who configures the plugin. The plugin will feed the word or selected text to a URL (that can be user-defined)
+  which will return the information. In the simplest scenario, the plugin could be made to send the word
+  to an online dictionary that can return the definition for it, or to a translator to find its meaning in another
+  language.
+ </p>
+ <p>
+  In order to use this functionality, your users will need a browser that supports the Javascript 1.2 standard. The
+  feature has been tested to work in IE 5.5 and 6.0 as well as in any Mozilla and Mozilla-based browser (i.e.
+  Firebird)
+ </p>
+ <p>
+  To enable the plugin, you have to include the following in the <b>header.template</b> file of the template
+  set you are currently using:
+  <pre>
+      {$jsdictionary->enable()}
+  </pre>
+  The plugin will output the necessary Javascript code to enable the functionality.
+  </p>
+ </p>
+ <p>
+  The "look up" action is triggered by either double clicking any word in the page or by selecting a piece of
+  text and pressing the "Enter" key. Automatically, a new smaller window will pop up on the screen with the information
+  returned by the site being used at the moment to find information.
+ </p>
+ <p>
+  The plugin comes by default with a few buit-in sites that can be selected with a click of the mouse. Amongst those
+  sites you will find dictionaries, translators, search engines and even movie sites (to for example allow your users
+  to find movies that contain a given set of words in its title... why not!?) Also, it is possible to define a new
+  URL in case none of the ones available is really useful for us.
+ </p>
+ <p>
+  In order to define a new URL, we first need to know what the format of the URL is. For example, if we want to
+  use Google as the look up site, Google uses the following format for its search URL in English:<br/><br/>
+  <i>http://www.google.com/search?q=&lt;your-search-term&gt;&amp;ie=UTF-8&amp;oe=UTF-8&amp;hl=en</i><br/><br/>
+  Knowing this, the only thing we have to do put the string <b>%word%</b> instead of the search term, to let the plugin
+  know where to include the word or selected words:<br/><br/>
+  <i>http://www.google.com/search?q=<b>%word%</b>&amp;ie=UTF-8&amp;oe=UTF-8&amp;hl=en</i><br/>
+ </p>
+ <p>
+  This plugin has been written by the pLog team. Please report any problems using it using the forums at <a href="http://www.plogworld.org/forums">
+  www.plogworld.org/forums</a>
+ </p>
+ </body>
+</html>

Added: plugins/trunk/jsdictionary/pluginjsdictionary.class.php
===================================================================
--- plugins/trunk/jsdictionary/pluginjsdictionary.class.php	2005-01-24 14:00:45 UTC (rev 821)
+++ plugins/trunk/jsdictionary/pluginjsdictionary.class.php	2005-01-24 16:31:02 UTC (rev 822)
@@ -0,0 +1,241 @@
+<?php
+
+	include_once( PLOG_CLASS_PATH."class/plugin/pluginbase.class.php" );
+    include_once( PLOG_CLASS_PATH."class/plugin/pluginmanager.class.php" );
+
+    /**
+     * Implementation of a very simple plugin file.
+     */
+    class PluginJsDictionary extends PluginBase {
+
+    var $_jsCode = "<script language=\"javascript1.2\">
+        var NS = (navigator.appName == \"Netscape\") ? 1 : 0;
+if (NS) document.captureEvents(Event.DBLCLICK);
+
+// register the events we're going to use
+document.ondblclick = dict;
+document.onkeydown = register;
+
+var newwin;
+function dict() {
+if (NS) {
+t = document.getSelection();
+opennewwin(t);
+}
+else {
+t = document.selection.createRange();
+if(document.selection.type == 'Text' && t.text != '') {
+document.selection.empty();
+opennewwin(t.text);
+      }
+   }
+}
+function opennewwin(text) {
+if (text > '') {
+var url = '%s';
+var dict_url = url.replace( /%word%/ig, escape(text));
+//window.alert(dict_url);
+newwin = window.open(dict_url, 'dictionary', 'width=800, height=600, resizable=yes, menubar=yes, toolbar=yes, scrollbars=yes');
+setTimeout('newwin.focus()', 100);
+   }
+}
+
+function register(e)
+{
+	if(!e) e = window.event;
+	if( e.keyCode == 13 ) {
+		selText = getSel();
+		if( selText != '' ) opennewwin(selText);
+	}
+}
+
+function getSel()
+{
+	var str = '';
+	if(document.getSelection) {
+		str = document.getSelection();
+	}
+	else if( document.selection && document.selection.createRange ) {
+		range = document.selection.createRange();
+		if (range) str = range.text;
+	}
+
+	if(!str) return'';
+	// replace unneeded characters
+	str=cleanString( str );
+	return str;
+}
+
+function cleanString( str )
+{
+	return str.replace(/^[^A-Za-z]+|[^A-Za-z]+\$/g,'');
+}
+
+
+</script>
+";
+
+		var $_sites =  Array(
+            Array( "desc" => "Dictionary.com",
+                   "url"  => "http://dictionary.reference.com/search?q=%word%" ),
+        	Array( "desc" => "ILN.net Dictionary",
+                   "url"  => "http://www.iln.net/main/resources/dictionary/default.asp?Word=%word%" ),
+            Array( "desc" => "Cambridge Advanced Learner's Dictionary",
+                   "url"  => "http://dictionary.cambridge.org/results.asp?searchword=%word%&image.x=0&image.y=0" ),
+            Array( "desc" => "Merrian Webster Dictionary",
+                   "url"  => "http://www.m-w.com/cgi-bin/dictionary?book=Dictionary&va=%word%" ),
+            Array( "desc" => "Google",
+                   "url"  => "http://www.google.com/search?q=%word%&ie=UTF-8&oe=UTF-8&hl=en" ),
+            Array( "desc" => "Yahoo! Search",
+                   "url"  => "http://search.yahoo.com/search?fr=fp-pull-web-t&p=%word%" ),
+            Array( "desc" => "Wikipedia",
+                   "url"  => "http://en.wikipedia.org/wiki/%word%" ),
+            Array( "desc" => "IMDB.com Movie Search",
+                   "url"  => "http://www.imdb.com/find?tt=on;nm=on;mx=20;q=%word%" ),
+            Array( "desc" => "Babelfish English to French translator",
+                   "url"  => "http://babelfish.altavista.com/babelfish/tr?doit=done&tt=urltext&intl=l&urltext=%word%&lp=en_fr" ),
+            Array( "desc" => "Babelfish English to German translator",
+                   "url"  => "http://babelfish.altavista.com/babelfish/tr?doit=done&tt=urltext&intl=l&urltext=%word%&lp=en_de" ),
+            Array( "desc" => "Babelfish English to Spanish translator",
+                   "url"  => "http://babelfish.altavista.com/babelfish/tr?doit=done&tt=urltext&intl=l&urltext=%word%&lp=en_es" ),
+            Array( "desc" => "Babelfish English to Italian translator",
+                   "url"  => "http://babelfish.altavista.com/babelfish/tr?doit=done&tt=urltext&intl=l&urltext=%word%&lp=en_it" ),
+            Array( "desc" => "Babelfish English to Portuguese translator",
+                   "url"  => "http://babelfish.altavista.com/babelfish/tr?doit=done&tt=urltext&intl=l&urltext=%word%&lp=en_pt" ),
+            Array( "desc" => "Babelfish English to Japanese translator",
+                   "url"  => "http://babelfish.altavista.com/babelfish/tr?doit=done&tt=urltext&intl=l&urltext=%word%&lp=en_ja" ),
+            Array( "desc" => "Babelfish English to Chinese translator",
+                   "url"  => "http://babelfish.altavista.com/babelfish/tr?doit=done&tt=urltext&intl=l&urltext=%word%&lp=en_zh" ),
+            Array( "desc" => "Babelfish English to Korean translator",
+                   "url"  => "http://babelfish.altavista.com/babelfish/tr?doit=done&tt=urltext&intl=l&urltext=%word%&lp=en_ko" ),
+            Array( "desc" => "Babelfish French to English translator",
+                   "url"  => "http://babelfish.altavista.com/babelfish/tr?doit=done&tt=urltext&intl=l&urltext=%word%&lp=fr_en" ),
+            Array( "desc" => "Babelfish German to English translator",
+                   "url"  => "http://babelfish.altavista.com/babelfish/tr?doit=done&tt=urltext&intl=l&urltext=%word%&lp=de_en" ),
+            Array( "desc" => "Babelfish Spanish to English translator",
+                   "url"  => "http://babelfish.altavista.com/babelfish/tr?doit=done&tt=urltext&intl=l&urltext=%word%&lp=es_en" ),
+            Array( "desc" => "Babelfish Italian to English translator",
+                   "url"  => "http://babelfish.altavista.com/babelfish/tr?doit=done&tt=urltext&intl=l&urltext=%word%&lp=it_en" ),
+            Array( "desc" => "Babelfish Portuguese to English translator",
+                   "url"  => "http://babelfish.altavista.com/babelfish/tr?doit=done&tt=urltext&intl=l&urltext=%word%&lp=pt_en" ),
+            Array( "desc" => "Babelfish Japanese to English translator",
+                   "url"  => "http://babelfish.altavista.com/babelfish/tr?doit=done&tt=urltext&intl=l&urltext=%word%&lp=ja_en" ),
+            Array( "desc" => "Babelfish Chinese to English translator",
+                   "url"  => "http://babelfish.altavista.com/babelfish/tr?doit=done&tt=urltext&intl=l&urltext=%word%&lp=zh_en" ),
+            Array( "desc" => "Babelfish Korean to English translator",
+                   "url"  => "http://babelfish.altavista.com/babelfish/tr?doit=done&tt=urltext&intl=l&urltext=%word%&lp=ko_en" ),
+            Array( "desc" => "Babelfish Russian to English translator",
+                   "url"  => "http://babelfish.altavista.com/babelfish/tr?doit=done&tt=urltext&intl=l&urltext=%word%&lp=ru_en" )
+        );
+
+
+    	function PluginJsDictionary()
+        {
+        	$this->PluginBase();
+
+            $this->desc   = "Allows readers to get a instant definition of any word from the blog by
+                             <b>double clicking</b> any of them. Also, readers can select any arbitrary section
+                             of text and press the <b>Enter</b> key in order to perform a search <br/><br/>
+                             In order to get this plugin working:<br/><br/>
+                             <b>1.</b> First, make sure that the plugin is enabled by clicking the \"configure\"
+                             link on the right. Choose also a dictionary from the ones provided or
+                             use a custom one if you wish.<br/><br/>
+                             <b>2.</b> Add the following to the header.template file of the template set you are
+                             currently using:<br/><br/>
+                             {\$jsdictionary->enable()}
+                             <br/><br/>
+                             Please remember that this plugin needs a Javascript 1.2-compatible browser in order to
+                             work properly.";
+            $this->author = "The pLog team";
+        }
+
+        /**
+         * Enables the dictionary
+         */
+        function enable()
+        {
+        	// do the necessary transformations so that we get the right javascript code
+
+            // if the plugin has been disabled, then quit
+            if( $this->blogSettings->getValue( "plugin_js_dictionary_enabled" ) == false )
+            	return;
+
+            // first of all, fetch the url of the site we're currently using
+            $siteId = $this->blogSettings->getValue( "plugin_js_dictionary_site" );
+            if( $siteId == -1 )
+            	$url = $this->blogSettings->getValue( "plugin_js_dictionary_custom_site" );
+            else
+            	$url = $this->_sites[$siteId]["url"];
+
+            // the mechanism we use to get the right javascript code is a bit clunky
+            // but... it works O:)
+            return str_replace( "%s", $url, $this->_jsCode );
+        }
+
+        /**
+         * generates a valid configuration dialog
+         */
+        function getConfigurationMessage()
+        {
+        	$configMessage = '<h1>JsDictionary Plugin Configuration</h1>
+                              <form name="configureJsDictionaryPlugin" method="post">';
+
+            if( $this->blogSettings->getValue( "plugin_js_dictionary_enabled" ) == true )
+            	$configMessage .= 'Enable the plugin: <input type="checkbox" name="pluginJsDictionaryEnabled" value="1" checked="checked" />';
+            else
+            	$configMessage .= 'Enable the plugin: <input type="checkbox" name="pluginJsDictionaryEnabled" value="1" />';
+
+            $configMessage .= '<br/><br/>Dictionary site: <select name="pluginJsDictionarySite">';
+            foreach( $this->_sites as $id => $site ) {
+            	$configMessage .= '<option value="'.$id.'"';
+                if( $this->blogSettings->getValue( "plugin_js_dictionary_site" ) == $id )
+                	$configMessage .= ' selected="selected" ';
+                $configMessage .= '>'.$site["desc"].'</option>';
+            }
+
+            $configMessage .= '<option value="-1"';
+            if( $this->blogSettings->getValue( "plugin_js_dictionary_site" ) == -1 )
+            	$configMessage .= ' selected="selected" ';
+            $configMessage .= '>Custom (use field below)</option>
+                               </select><br/><br/>
+                               Custom dictionary site: <input size="80" type="text" name="pluginJsDictionaryCustomSite" value="'.$this->blogSettings->getValue( "plugin_js_dictionary_custom_site" ).'" /><br/>
+                               <i>Use \'%word%\' to specify where the selected word should be included in the request</i>
+                               <br/><br/>
+                               <input type="hidden" name="op" value="updatePluginConfig" />
+                               <input type="hidden" name="pluginId" value="jsdictionary" />
+                               <input type="submit" name="Save Settings" value="Save Settings" />
+                               </form>';
+
+            return $configMessage;
+        }
+
+        /**
+         * Configures the plugin.
+         */
+        function configure( $params )
+        {
+        	// check if the user wants to enable or disable the plugin
+        	$pluginEnabled = $params->getValue( "pluginJsDictionaryEnabled" );
+            if( $pluginEnabled == "" )
+            	$pluginEnabled = false;
+
+            $dictionarySite = $params->getValue( "pluginJsDictionarySite" );
+            if( $dictionarySite == "" )
+            	$dictionarySite = 0;
+
+            $customSite = $params->getValue( "pluginJsDictionaryCustomSite" );
+            if( $dictionarySite == "-1" && $customSite == "" )
+            	$dictionarySite = 0;
+
+            $this->blogSettings->setValue( "plugin_js_dictionary_enabled", $pluginEnabled );
+            $this->blogSettings->setValue( "plugin_js_dictionary_site", $dictionarySite );
+            $this->blogSettings->setValue( "plugin_js_dictionary_custom_site", $customSite );
+
+            $this->updateBlogSettings();
+
+            return true;
+        }
+    }
+
+    PluginManager::registerPlugin( "jsdictionary", "PluginJsDictionary" );
+?>

Added: plugins/trunk/whoonline/pluginwhoonline.class.php
===================================================================
--- plugins/trunk/whoonline/pluginwhoonline.class.php	2005-01-24 14:00:45 UTC (rev 821)
+++ plugins/trunk/whoonline/pluginwhoonline.class.php	2005-01-24 16:31:02 UTC (rev 822)
@@ -0,0 +1,222 @@
+<?php
+// This class file is a compact version of the 2 main classes we use.
+include_once( "class/plugin/pluginbase.class.php" );
+include_once( "class/plugin/pluginmanager.class.php" );
+include_once( PLOG_CLASS_PATH."class/dao/model.class.php" );
+include_once( PLOG_CLASS_PATH."class/net/client.class.php" );
+include_once( PLOG_CLASS_PATH."debug.php" );
+
+define ("WHO_ONLINE_TIMEOUT", 360); // 2 minutes
+// Define the main class as a plugin
+
+class PluginWhoOnline extends PluginBase {
+	var $clientip;
+	var $tstamp;
+    	function PluginWhoOnline() { // Declare some about info
+		$this->PluginBase();
+		$this->desc = "
+<p>This plugin will allow your visitors to view how many other visitors are online at the same time. Well it actual does a bit more than that. It can also serve as a simple hit counter and record the most number of online users.<br>
+It is pretty easy to use. For now if you want to configure the capture time just edit the top of the plugin. It is
+set with a default of 120 seconds (2 minutes). For now it will only capture visitors in general but i also want it
+to capture registered (logged in) users, views on specific entries and specific blogs. Have fun and happy hacking.<br>
+<b>Note</b>: This plugin will not record information automatically. It will not count hits on pages that do not include the BlogCount function. Might be a good idea to keep it somewhere global like a side panel or footer.<br>
+Examples:<br>
+<b>{\$whoonline->WhoOnlineSite()}</b> - returns all users recorded over all blogs.<br>
+<b>{\$whoonline->WhoOnlineBlog([id or default current])}</b> - returns all users on a specific blog.<br>
+<b>{\$whoonline->WhoOnlineEntry([article id])}</b> - returns all users on a specific article.<br>
+<b>{\$whoonline->WhoOnlineCustom([unique id])}</b> - returns all users on a custom entry. Like a specific template, etc<br>
+<b>{\$whoonline->WhoOnlineMax([id or default current])}</b> - returns the highest number of users online for specific blog.<br>
+<b>{\$whoonline->BlogCount([id or default current])}</b> - returns a blogs total number of hits.<br>
+</p>";
+		$this->author = "Nick Gerakines";
+	}
+	function register() { // initialize the class
+//		print("[Debug: WhoOnline] Initilizing Class.<br>");
+		$w = new WhoAreUs(); // create the secondary class object
+		$t = new Timestamp(); // create a timestamp object, might be quicker to just invoke time()
+		$w->createWhoTables(); // sift through and see if the tables exist
+//		print("[Debug: WhoOnline] Checking Tables.<br>");
+//		print("[Debug: WhoOnline] Online timeout default set to ".WHO_ONLINE_TIMEOUT." seconds.<br>");
+		$timeout = $t->getUnixDate() - WHO_ONLINE_TIMEOUT; // get the timeout number
+//		print("[Debug: WhoOnline] Setting timeout to $timeout.<br>");
+		$this->tstamp = $t->getUnixDate();
+//		print("[Debug: WhoOnline] Setting tstamp to ".$this->tstamp."<br>");
+		$this->clientip = Client::getIp();
+//		print("[Debug: WhoOnline] Setting clientip to ".$this->clientip.".<br>");
+		$w->cleanwho($timeout);
+	}
+	function BlogCount($blog = -1) {
+		$count = 0;
+		if ($blog < 0) {$blog = $this->blogInfo->getId();}
+		$w = new WhoAreUs(); // create the secondary class object
+		$count = $w->gethits($blog);
+		return $count;
+	}
+	function WhoOnlineMax($blog = -1) {
+//		print("[Debug: WhoOnline->WhoOnlineMax] Running function WhoOnlineMax.<br>");
+		$count = 0;
+		if ($blog < 0) {$blog = $this->blogInfo->getId();}
+//		print("[Debug: WhoOnline->WhoOnlineMax] Using blog $blog.<br>");
+		$w = new WhoAreUs();
+		$count = $w->getcount(" WHERE blog_id = $blog");
+//		print("[Debug: WhoOnline->WhoOnlineMax] Getting current blog count of $count.<br>");
+		$mcount = $w->getmax($blog, $count);
+//		print("[Debug: WhoOnline->WhoOnlineMax] returning $mcount.<br>");
+		return $mcount;
+	}
+	function WhoOnlineSite() { // Poll all distinct visits to the site
+//		print("[Debug: WhoOnline] Running function WhoOnlineSite.<br>");
+		$count = 0;
+		$blog = $this->blogInfo->getId();
+//		print("[Debug: WhoOnline] Setting blog to $blog.<br>");
+		$w = new WhoAreUs(); // create the secondary class object
+		$w->injectSQL("( `blog_id` , `timestamp` , `ip` ) VALUES ('$blog', '".$this->tstamp."', '".$this->clientip."' );");
+		$count = $w->getcount("");
+		return $count;
+	}
+	function WhoOnlineBlog ($blog = -1) { // Poll all distinct visits to specific blog
+//		print("[Debug: WhoOnline] Running function WhoOnlineBlog.<br>");
+		$count = 0;
+//		print("[Debug: WhoOnline] Blog set to $blog.<br>");
+		if ($blog < 0) {$blog = $this->blogInfo->getId();}
+//		print("[Debug: WhoOnline] Blog now set to $blog.<br>");
+		$w = new WhoAreUs(); // create the secondary class object
+		$w->injectSQL("( `blog_id`, `timestamp` , `ip` ) VALUES ( '$blog', '".$this->tstamp."', '".$this->clientip."' );");
+		$count = $w->getcount(" WHERE blog_id = $blog");
+		return $count;
+	}
+	function WhoOnlineEntry($article) { // Poll all distinct visits to specific article in blog
+//		print("[Debug: WhoOnline] Running function WhoOnlineEntry on article $article.<br>");
+		$count = 0;
+		$blog = $this->blogInfo->getId();
+//		print("[Debug: WhoOnline] Setting blog to $blog<br>");
+		$w = new WhoAreUs(); // create the secondary class object
+		$w->injectSQL("( `blog_id` , `article_id` , `timestamp` , `ip` ) VALUES ( '$blog', '$article', '".$this->tstamp."', '".$this->clientip."' );");
+		$count = $w->getcount(" WHERE blog_id = $blog AND article_id = $article");
+		return $count;
+	}
+	function WhoOnlineCustom($custom){
+		$count = 0;
+		$blog = $this->blogInfo->getId();
+		$w = new WhoAreUs(); // create the secondary class object
+		$w->injectSQL("( `blog_id` , `custom_id` , `timestamp` , `ip` ) VALUES ( '$blog', '$custom', '".$this->tstamp."', '".$this->clientip."' );");
+		$count = $w->getcount(" WHERE blog_id = $blog AND custom_id = $custom");
+		return $count;
+	}
+}
+// Define the datacruncher class
+class WhoAreUs extends Model {
+	function WhoAreUs() { // continue class schema defs
+		$this->Model();
+	}
+	function checkTable( $tableName, $tableSchema ) { // hacked from karma plugin
+		//$config = new Config();
+		//$dbPrefix = $config->getValue( "db_prefix" );
+		$dbPrefix = $this->getPrefix();
+		$tableName = $dbPrefix.$tableName;
+		// create the data dictionary and create the table if necessary
+		$dict = NewDataDictionary( $this->_db );
+		$sqlArray = $dict->ChangeTableSQL( $tableName, $tableSchema );
+		$result = $dict->ExecuteSQLArray( $sqlArray );
+		if( $result == 0 )
+			$this->_desc = "There was an error initializing the tables.";
+	}
+	function createWhoTables() { // hacked from karma plugin
+		$table1 = "who_online";
+		$fields1 = "blog_id I(10) NOT NULL default '-1',
+			article_id I(10) NOT NULL default '-1',
+			custom_id I(10) NOT NULL default '-1',
+			timestamp int(15) NOT NULL default '0',
+			ip varchar(40) NOT NULL";
+		$this->checkTable( $table1, $fields1 );
+		$table2 = "who_counts";
+		$fields2 = "blogid INT DEFAULT '0' NOT NULL ,
+			count INT,
+			count_max INT,
+			lastupdate INT(25)";
+		$this->checkTable( $table2, $fields2);
+		return true;		
+	}
+	function injectSql($dbqry) {
+		$query = "INSERT INTO ".$this->getPrefix()."who_online $dbqry";
+//		print("[Debug: WhoOnline] Running injection with query: $query<br>");
+		$result = $this->_db->Execute( $query );
+	}
+	function cleanwho($timeout) {
+		$query = "DELETE FROM ".$this->getPrefix()."who_online WHERE timestamp < $timeout";
+//		print("[Debug: WhoOnline] Running clean with query: $query<br>");
+		$result = $this->_db->Execute( $query );
+		return $result;
+	}
+	function getcount($dbqry) {
+		$query = "SELECT DISTINCT ip FROM ".$this->getPrefix()."who_online$dbqry";
+//		print("[Debug: WhoOnline] Running getcount with query: $query.<br>");
+		$count = 0;
+		$result = $this->_db->Execute($query);
+		if ($result) {
+//			print("[Debug: WhoOnline] getcount success.<br>");
+			$count = $result->RecordCount();
+		}
+//		print("[Debug: WhoOnline] returning count of $count.<br>");
+		return $count;
+	}
+	// gethits function keeps a count of hits on any given blog.
+	// We could do this several ways.
+	// (1) Insert a new record for each hit and just do a record count
+	// (2) Use a single row per blog and just update the count as needed
+	// For time space and effort i'm going with number 1
+	function gethits($blog) {
+		$count = 1;
+		$query = "select * from ".$this->getPrefix()."who_counts where blogid = $blog";
+		$result = $this->_db->Execute($query);
+		$rcount = $result->RecordCount();
+		if ($rcount > 0) {
+			$row = $result->FetchRow();
+			$count = $row["count"] + 1;
+			// 1+ rows existed, do update
+			$query = "UPDATE ".$this->getPrefix()."who_counts SET count = $count WHERE blogid = $blog";
+		} else {
+			// 0 rows existed, do insert.
+			$query = "INSERT INTO ".$this->getPrefix()."who_counts ( blogid, count) VALUES ('$blog', '$count');";
+		}
+		$result = $this->_db->Execute($query);
+		return $count;
+	}
+function getmax($blog, $cur_count){
+		// see if the row is set or not
+		$count = 0;
+		$query = "Select * from ".$this->getPrefix()."who_counts where blogid = $blog";
+//		print("[Debug: WhoOnline->getmax] Running test Query: <b>$query</b>.<br>");
+		$result = $this->_db->Execute($query);
+		$rcount = $result->RecordCount();
+//		print("[Debug: WhoOnline->getmax] Test query yields $rcount rows.<br>");
+		if ($rcount > 0) {
+//			print("[Debug: WhoOnline->getmax] Updating record. <br>");
+			$row = $result->FetchRow();
+			$count = $row["count_max"];
+//			print("[Debug: WhoOnline->getmax] Current max count at $count.<br>");
+			if ($cur_count > $count) {
+				$count = $cur_count;
+				$query = "UPDATE ".$this->getPrefix()."who_counts SET count_max = $count WHERE blogid = $blog";
+//				print("[Debug: WhoOnline->getmax] Updating query with $query.<br>");
+				$result = $this->_db->Execute($query);
+				if ($result) {
+//					print("[Debug: WhoOnline->getmax] Update success with query: $query.<br>");
+				}
+			}
+		} else {
+			$count = $cur_count;
+//			print("[Debug: WhoOnline->getmax] Inserting new record with max count at $cur_count.<br>");
+			$query = "INSERT INTO ".$this->getPrefix()."who_counts ( blogid, count_max) VALUES ('$blog', '$count');";
+//			print("[Debug: WhoOnline->getmax] Inserting new record with query: $query.<br>");
+			$result = $this->_db->Execute($query);
+			if ($result) {
+//					print("[Debug: WhoOnline->getmax] Insert success with query: $query.<br>");
+			}
+
+		}
+		return $count;
+	}
+}
+PluginManager::registerPlugin( "whoonline", "PluginWhoOnline" );
+?>




More information about the pLog-svn mailing list