aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKevin Chabowski <kevin@kch42.de>2011-12-04 12:34:21 +0100
committerKevin Chabowski <kevin@kch42.de>2011-12-04 12:34:21 +0100
commitf5769e7db7d1870b3fb9e3a93b27fb82c1bddf21 (patch)
treef5a4d9302905b24afe1ef7ea40f8421d55b8317d
parent48bed2761f7cc23c30ed2c11ba7f025810594456 (diff)
downloadratatoeskr-cms-f5769e7db7d1870b3fb9e3a93b27fb82c1bddf21.tar.gz
ratatoeskr-cms-f5769e7db7d1870b3fb9e3a93b27fb82c1bddf21.tar.bz2
ratatoeskr-cms-f5769e7db7d1870b3fb9e3a93b27fb82c1bddf21.zip
Added Repository data models and the PluginPackage class.
Not tested yet..
-rw-r--r--ratatoeskr/licenses/wtfpl13
-rw-r--r--ratatoeskr/setup/create_tables.php9
-rw-r--r--ratatoeskr/sys/models.php224
-rw-r--r--ratatoeskr/sys/pluginpackage.php265
4 files changed, 511 insertions, 0 deletions
diff --git a/ratatoeskr/licenses/wtfpl b/ratatoeskr/licenses/wtfpl
new file mode 100644
index 0000000..8b1a9d8
--- /dev/null
+++ b/ratatoeskr/licenses/wtfpl
@@ -0,0 +1,13 @@
+ DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
+ Version 2, December 2004
+
+Copyright (C) 2004 Sam Hocevar <sam@hocevar.net>
+
+Everyone is permitted to copy and distribute verbatim or modified
+copies of this license document, and changing it is allowed as long
+as the name is changed.
+
+ DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. You just DO WHAT THE FUCK YOU WANT TO.
diff --git a/ratatoeskr/setup/create_tables.php b/ratatoeskr/setup/create_tables.php
index 1be8855..8405ade 100644
--- a/ratatoeskr/setup/create_tables.php
+++ b/ratatoeskr/setup/create_tables.php
@@ -125,6 +125,15 @@ CREATE TABLE `PREFIX_users` (
`language` varchar(10) COLLATE utf8_unicode_ci NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
+
+CREATE TABLE `s_db_47`.`PREFIX_repositories` (
+`id` INT NOT NULL AUTO_INCREMENT PRIMARY KEY ,
+`baseurl` TEXT CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL ,
+`name` TEXT CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL ,
+`description` TEXT CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL ,
+`pkgcache` TEXT CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL ,
+`lastrefresh` BIGINT NOT NULL
+) ENGINE = MYISAM CHARACTER SET utf8 COLLATE utf8_unicode_ci;
SQL;
?>
diff --git a/ratatoeskr/sys/models.php b/ratatoeskr/sys/models.php
index c3e112c..2dadb22 100644
--- a/ratatoeskr/sys/models.php
+++ b/ratatoeskr/sys/models.php
@@ -13,6 +13,7 @@ require_once(dirname(__FILE__) . "/db.php");
require_once(dirname(__FILE__) . "/utils.php");
require_once(dirname(__FILE__) . "/../libs/kses.php");
require_once(dirname(__FILE__) . "/textprocessors.php");
+require_once(dirname(__FILE__) . "/pluginpackage.php");
db_connect();
@@ -1795,6 +1796,229 @@ class Image
}
/*
+ * Class RepositoryUnreachableOrInvalid
+ * A Exception that will be thrown, if the repository is aunreachable or seems to be an invalid repository.
+ */
+class RepositoryUnreachableOrInvalid extends Exception { }
+
+/*
+ * Class: Repository
+ * Representation of an plugin repository.
+ */
+class Repository
+{
+ private $id;
+ private $baseurl;
+ private $name;
+ private $description;
+ private $lastrefresh;
+
+ private $stream_ctx;
+
+ /*
+ * Variables: Public class variables
+ * $packages - Array with all packages from this repository. A entry itself is an array: array(name, versioncounter, description)
+ */
+ public $packages;
+
+ private function __construct()
+ {
+ $this->stream_ctx = stream_context_create(array("http" => array("timeout" => 5)));
+ }
+
+ /*
+ * Functions: Getters
+ * get_id - Get internal ID.
+ * get_baseurl - Get the baseurl of the repository.
+ * get_name - Get repository name.
+ * get_description - Get repository description.
+ */
+ public function get_id() { return $this->id; }
+ public function get_baseurl() { return $this->baseurl; }
+ public function get_name() { return $this->name; }
+ public function get_description() { return $this->description; }
+
+ /*
+ * Constructor: create
+ * Create a new repository entry from a base url.
+ *
+ * Parameters:
+ * $baseurl - The baseurl of the repository.
+ *
+ * Throws:
+ * Could throw a <RepositoryUnreachableOrInvalid> exception. In this case, nothing will be written to the database.
+ *
+ * Returns:
+ * A <Repository> object.
+ */
+ public static function create($baseurl)
+ {
+ $obj = new self();
+
+ if(preg_match('/^(http[s]?:\\/\\/.*?)[\\/]?$/', $baseurl, $matches) == 0)
+ throw new RepositoryUnreachableOrInvalid();
+
+ $obj->baseurl = $$matches[1];
+ $obj->refresh(True);
+
+ qdb("INSERT INTO `ratatoeskr_repositories` () VALUES ()");
+ $obj->id = mysql_insert_id();
+ $obj->save();
+ return $obj;
+ }
+
+ /*
+ * Constructor: by_id
+ * Get a repository entry by ID.
+ *
+ * Parameters:
+ * $id - ID.
+ *
+ * Returns:
+ * A <Repository> object.
+ */
+ public static function by_id($id)
+ {
+ $result = qdb("SELECT `name`, `description`, `baseurl`, `pkgcache`, `lastrefresh` WHERE id` = %d", $this->id);
+ $sqlrow = mysql_fetch_assoc($result);
+ if(!$sqlrow)
+ throw new DoesNotExistError();
+
+ $obj = new self();
+ $obj->id = $id;
+ $obj->name = $sqlrow["name"];
+ $obj->description = $sqlrow["description"];
+ $obj->baseurl = $sqlrow["baseurl"];
+ $obj->packages = unserialize(base64_decode($sqlrow["pkgcache"]));
+ $obj->lastrefresh = $sqlrow["lastrefresh"];
+
+ return $obj;
+ }
+
+ private function save()
+ {
+ qdb("UPDATE `PREFIX_repositories` SET `baseurl` => '%s', `name` = '%s', `description` = '%s', `pkgcache` = '%s', `lastrefresh` = %d WHERE `id` = %d",
+ $this->baseurl,
+ $this->name,
+ $this->description,
+ base64_encode(serialize($this->packages)),
+ $this->lastrefresh,
+ $this->id);
+ }
+
+ /*
+ * Function: delete
+ * Delete the repository entry from the database.
+ */
+ public function delete()
+ {
+ qdb("DELETE FROM `PREFIX_repositories` WHERE `id` = %d", $this->id);
+ }
+
+ /*
+ * Function: refresh
+ * Refresh the package cache and the name and description.
+ *
+ * Parameters:
+ * $force - Force a refresh, even if the data was already fetched in the last 6 hours (default: False).
+ *
+ * Throws:
+ * <RepositoryUnreachableOrInvalid>
+ */
+ public function refresh($force = False)
+ {
+ if(($this->lastrefresh > (time() - (60*60*4))) and (!$force))
+ return;
+
+ $repometa = @file_get_contents($this->baseurl . "/repometa", False, $this->stream_ctx);
+ if($repometa === FALSE)
+ throw new RepositoryUnreachableOrInvalid();
+ $repometa = @unserialize($repometa);
+ if((!is_array($repometa)) or (!isset($repometa["name"])) or (!isset($repometa["description"])))
+ throw new RepositoryUnreachableOrInvalid();
+
+ $this->name = $repometa["name"];
+ $this->description = $repometa["description"];
+ $this->packages = @unserialize(@file_get_contents($this->baseurl . "/packagelist", False, $ctx));
+
+ $this->lastrefresh = time();
+
+ $this->save();
+ }
+
+ /*
+ * Function: get_package_meta
+ * Get metadata of a plugin package from this repository.
+ *
+ * Parameters:
+ * $pkgname - The name of the package.
+ *
+ * Throws:
+ * A <DoesNotExistError> Exception, if the package was not found.
+ *
+ * Returns:
+ * A <PluginPackageMeta> object
+ */
+ public function get_package_meta($pkgname)
+ {
+ $found = False;
+ foreach($this->packages as $p)
+ {
+ if($p[0] == $pkgname)
+ {
+ $found = True;
+ break;
+ }
+ }
+ if(!$found)
+ throw new DoesNotExistError("Package not in package cache.");
+
+ $pkgmeta = @unserialize(@file_get_contents($this->baseurl . "/packages/" . urlencode($pkgname) . "/meta", False, $this->stream_ctx));
+
+ if(!($pkgmeta instanceof PluginPackageMeta))
+ throw new DoesNotExistError();
+
+ return $pkgmeta;
+ }
+
+ /*
+ * Function: download_package
+ * Download a package from the repository
+ *
+ * Parameters:
+ * $pkgname - Name of the package.
+ * $version - The version to download (defaults to "current").
+ *
+ * Throws:
+ * * A <DoesNotExistError> Exception, if the package was not found.
+ * * A <InvalidPackage> Exception, if the package was malformed.
+ *
+ * Returns:
+ * A <PluginPackage> object.
+ */
+ public function download_package($pkgname, $version = "current")
+ {
+ $found = False;
+ foreach($this->packages as $p)
+ {
+ if($p[0] == $pkgname)
+ {
+ $found = True;
+ break;
+ }
+ }
+ if(!$found)
+ throw new DoesNotExistError("Package not in package cache.");
+
+ $raw = @file_get_contents($this->baseurl . "/packages/" . urlencode($pkgname) . "/versions/" . urlencode($version), False, $this->stream_ctx);
+ if($raw === False)
+ throw new DoesNotExistError();
+
+ return PluginPackage::load($raw);
+ }
+}
+
+/*
* Class: Article
* Representation of an article
*/
diff --git a/ratatoeskr/sys/pluginpackage.php b/ratatoeskr/sys/pluginpackage.php
new file mode 100644
index 0000000..0200c79
--- /dev/null
+++ b/ratatoeskr/sys/pluginpackage.php
@@ -0,0 +1,265 @@
+<?php
+
+/*
+ * File: ratatoeskr/sys/pluginpackage.php
+ * Handle plugin packages easily.
+ *
+ * License:
+ * This file is part of Ratatöskr.
+ * Unlike the other parts of Ratatöskr, *this* file ist *not* licensed under the
+ * MIT / X11 License, but under the WTFPL, to make it even easier to use this
+ * file in other projects.
+ * See "ratatoeskr/licenses/wtfpl" for more information.
+ */
+
+/*
+ * Function: dir2array
+ * Pack a directory into an array.
+ *
+ * Parameters:
+ * $dir - The directory to pack.
+ *
+ * Returns:
+ * Associative array. Keys are filenames, values are either the file's content as a string or another array, if it's a directory.
+ */
+function dir2array($dir)
+{
+ $rv = array();
+ foreach(scandir($dir) as $fn)
+ {
+ if(($fn == ".") or ($fn == ".."))
+ continue;
+ $fn_new = $dir . "/" . $fn;
+ if(is_dir($fn_new))
+ $rv[$fn] = dir2array($fn_new);
+ elseif(is_file($fn_new))
+ $rv[$fn] = file_get_contents($fn_new);
+ }
+ return $rv;
+}
+
+/*
+ * Class: InvalidPackage
+ * An Exception that <PluginPackage>'s function can throw, if the package is invalid.
+ */
+class InvalidPackage extends Exception {}
+
+/*
+ * Class: PluginPackage
+ * A plugin package representation.
+ */
+class PluginPackage
+{
+ public static $magic = "R7RPLGPACKV001";
+
+ /*
+ * Variables: Mandatory values
+ *
+ * $code - The plugin code
+ * $classname - The name of the plugins main class
+ * $name - Name of the plugin (must be at least one character, allowed chars: a-z A-Z 0-9 - _)
+ * $author - The author of the plugin (preferably in the format: Name<mail@address>)
+ * $versiontext - A text to describe the current version, something like "1.1 Beta"
+ * $versioncount - A number for this version, should be increased with every release
+ * $api - The used API version
+ * $short_description - A short description.
+ */
+ public $code = NULL;
+ public $classname = NULL;
+ public $name = NULL;
+ public $author = NULL;
+ public $versiontext = NULL;
+ public $versioncount = NULL;
+ public $api = NULL;
+ public $short_description = NULL;
+
+ /*
+ * Variables: Optional values
+ *
+ * $updatepath - A URL that points to a update information resource (serialize'd array("current-version" => VERSIONCOUNT, "dl-path" => DOWNLOAD PATH); will get overwritten/set by the default repository software.
+ * $web - A URL to the webpage for the plugin. If left empty, the default repository software will set this to the description page of your plugin.
+ * $license - The license text of your plugin.
+ * $help - A help / manual (formatted in HTML) for your plugin.
+ * $custompub - <dir2array> 'd directory that contains custom public(i.e. can later be accessed from the web) data.
+ * $custompriv - <dir2array> 'd directory that contains custom private data.
+ * $tpls - <dir2array> 'd directory containing custom STE templates.
+ */
+ public $updatepath = NULL;
+ public $web = NULL;
+ public $license = NULL;
+ public $help = NULL;
+ public $custompub = NULL;
+ public $custompriv = NULL;
+ public $tpls = NULL;
+
+ /*
+ * Function: validate
+ * Validate, if the variables are set correctly.
+ * Will throw an <InvalidPackage> exception if invalid.
+ */
+ public function validate()
+ {
+ function validate_url ($u) { return preg_match("/^http[s]{0,1}://.*$/", $u) != 0; }
+ function validate_arraydir($a)
+ {
+ if(!is_array($a))
+ return False;
+ foreach($a as $k=>$v)
+ {
+ if(!is_string($k))
+ return False;
+ if(is_array($v) and (!validate_arraydir($v)))
+ return False;
+ elseif(!is_string($v))
+ return False;
+ }
+ return True;
+ }
+
+ if(!is_string($this->code))
+ throw new InvalidPackage("Invalid code value.");
+ if(!is_string($this->classname))
+ throw new InvalidPackage("Invalid classname value.");
+ if(preg_match("/^[a-zA-Z0-9_\\-]+$/", $this->name) == 0)
+ throw new InvalidPackage("Invalid name value (must be at least 1 character, accepted chars: a-z A-Z 0-9 - _).");
+ if(!is_string($this->author))
+ throw new InvalidPackage("Invalid author value.");
+ if(!is_string($this->versiontext))
+ throw new InvalidPackage("Invalid versiontext value.");
+ if(!is_numeric($this->versioncount))
+ throw new InvalidPackage("Invalid versioncount value. Must be a number.");
+ if(!is_numeric($this->api))
+ throw new InvalidPackage("Invalid api value. Must be a number.");
+ if(!is_string($this->short_description))
+ throw new InvalidPackage("Invalid short_description value.");
+
+ if(($this->updatepath !== NULL) and (!validate_url($this->updatepath)))
+ throw new InvalidPackage("Invalid updatepath value. Must be an URL.");
+ if(($this->web !== NULL) and (!validate_url($this->web)))
+ throw new InvalidPackage("Invalid web value. Must be an URL.");
+ if(($this->license !== NULL) and (!is_string($this->license)))
+ throw new InvalidPackage("Invalid license value.");
+ if(($this->help !== NULL) and (!is_string($this->help)))
+ throw new InvalidPackage("Invalid help value.");
+ if(($this->custompub !== NULL) and (!validate_arraydir($this->custompub)))
+ throw new InvalidPackage("Invalid custompub value.");
+ if(($this->custompriv !== NULL) and (!validate_arraydir($this->custompriv)))
+ throw new InvalidPackage("Invalid custompriv value.");
+ if(($this->tpls !== NULL) and (!validate_arraydir($this->tpls)))
+ throw new InvalidPackage("Invalid tpls value.");
+ return True;
+ }
+
+ /*
+ * Function: load
+ * Load a plugin package from binary data.
+ *
+ * Parameters:
+ * $plugin_raw - The raw package to load.
+ *
+ * Returns:
+ * The <PluginPackage> object.
+ *
+ * Throws:
+ * <InvalidPackage> if package is invalid.
+ */
+ public static function load($plugin_raw)
+ {
+ /* Read and compare magic number */
+ $magic = substr($plugin_raw, 0, strlen(self::$magic));
+ if($magic != self::$magic)
+ throw new InvalidPackage("Wrong magic number");
+
+ /* Read sha1sum and uncompress serialized plugin, then compare the hash */
+ $sha1sum = substr($plugin_raw, strlen(self::$magic), 20);
+ $pluginser = gzuncompress(substr($plugin_raw, strlen(self::$magic) + 20));
+ if(sha1($pluginser, True) != $sha1sum)
+ throw new InvalidPackage("Wrong SHA1 hash");
+
+ $plugin = @unserialize($pluginser);
+ if(!($plugin instanceof this))
+ throw new InvalidPackage("Not the correct class or not unserializeable.");
+
+ $plugin->validate();
+
+ return $plugin;
+ }
+
+ /*
+ * Function: save
+ * Save the plugin.
+ *
+ * Returns:
+ * A binary plugin package.
+ *
+ * Throws:
+ * <InvalidPackage> if package is invalid.
+ */
+ public function save()
+ {
+ $this->validate();
+ $ser = serialize($self);
+ return this::$magic . sha1($ser, True) . gzcompress($ser, 9);
+ }
+
+ /*
+ * Function: extract_meta
+ * Get just the metadata of this package.
+ *
+ * Returns:
+ * A <PluginPackageMeta> object.
+ */
+ public function extract_meta()
+ {
+ $meta = new PluginPackageMeta();
+
+ $meta->name = $this>name;
+ $meta->author = $this>author;
+ $meta->versiontext = $this>versiontext;
+ $meta->versioncount = $this>versioncount;
+ $meta->api = $this>api;
+ $meta->short_description = $this>short_description;
+ $meta->updatepath = $this>updatepath;
+ $meta->web = $this>web;
+ $meta->license = $this>license;
+
+ return $meta;
+ }
+}
+
+/*
+ * Class: PluginPackageMeta
+ * Only the metadata of a <PluginPackage>.
+ */
+class PluginPackageMeta
+{
+ /*
+ * Variables: Mandatory values
+ *
+ * $name - Name of the plugin (must be at least one character, allowed chars: a-z A-Z 0-9 - _)
+ * $author - The author of the plugin (preferably in the format: Name<mail@address>)
+ * $versiontext - A text to describe the current version, something like "1.1 Beta"
+ * $versioncount - A number for this version, should be increased with every release
+ * $api - The used API version
+ * $short_description - A short description.
+ */
+ public $name = NULL;
+ public $author = NULL;
+ public $versiontext = NULL;
+ public $versioncount = NULL;
+ public $api = NULL;
+ public $short_description = NULL;
+
+ /*
+ * Variables: Optional values
+ *
+ * $updatepath - A URL that points to a update information resource (serialize'd array("current-version" => VERSIONCOUNT, "dl-path" => DOWNLOAD PATH); will get overwritten/set by the default repository software.
+ * $web - A URL to the webpage for the plugin. If left empty, the default repository software will set this to the description page of your plugin.
+ * $license - The license text of your plugin.
+ */
+ public $updatepath = NULL;
+ public $web = NULL;
+ public $license = NULL;
+}
+
+?>