Location: PHPKode > projects > Aukyla Document Management System > adms2/apps/ADMS/IndexFile.php
<?php
/*
     IndexFile.php, provides functions to edit index files
     Copyright (C) 2003-2005 Arend van Beelen, Auton Rijnsburg

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

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

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

     For any questions, comments or whatever, you may mail me at: hide@address.com
*/

require_once('Login.php');
require_once('Signal.php');
require_once('URI.php');

// define sections to read for reading XML files
define('ADMS_IndexFileReadingNothing',         0);
define('ADMS_IndexFileReadingRoot',            1);
define('ADMS_IndexFileReadingEntry',           2);
define('ADMS_IndexFileReadingMeta',            3);
define('ADMS_IndexFileReadingIpAccess',        4);
define('ADMS_IndexFileReadingUserAccess',      5);
define('ADMS_IndexFileReadingGroupAccess',     6);
define('ADMS_IndexFileReadingOtherAccess',     7);

class ADMS_IndexFileEntry
{
	public $id = 0;
	public $meta = array();

	public $ipAccess = array();
	public $userAccess = array();
	public $groupAccess = array();
	public $otherAccess = PERMISSION_NONE;
}

// class for handling folders and their entries through index.xml files
class ADMS_IndexFile
{
	// constructor
	function __construct()
	{
		if(isset(self::$permissions) == false)
		{
			self::$permissions = array();
			self::$permissions[PERMISSION_NONE]         = 'none';
			self::$permissions[PERMISSION_READ]         = 'read';
			self::$permissions[PERMISSION_APPEND]       = 'append';
			self::$permissions[PERMISSION_MODIFY]       = 'modify';
			self::$permissions[PERMISSION_DELETE]       = 'delete';
			self::$permissions[PERMISSION_ADMINISTRATE] = 'administrate';
		}

		$this->reset();
	}

	// resets class
	public function reset()
	{
		$this->filename = '';
		$this->entries = array();
		$this->changed = false;
	}

	// handles opening tags in XML files
	private function open_StartElement($parser, $name, $attrs)
	{
		if($this->unknown == true)
		{
			$this->level++;
			return;
		}

		$id = isset($attrs['ID']) ? $attrs['ID'] : '';
		$key = isset($attrs['KEY']) ? $attrs['KEY'] : '';
		$value = isset($attrs['VALUE']) ? $attrs['VALUE'] : '';
		$i18n = isset($attrs['I18N']) ? $attrs['I18N'] : '';
		switch($this->readingmode)
		{
			case ADMS_IndexFileReadingNothing:
				switch($name)
				{
					case 'XML':
						$this->readingmode = ADMS_IndexFileReadingRoot;
						break;

					default:
						if($this->level++ == 0)
						{
							trigger_error("Unknown element \"$name\" outside <xml>");
						}
						$this->unknown = true;
				}
				break;

			case ADMS_IndexFileReadingRoot:
				switch($name)
				{
					case 'ENTRY':
						if($id != '')
						{
							$this->readingmode = ADMS_IndexFileReadingEntry;
							$this->entries[$this->currententry] = new ADMS_IndexFileEntry;
							$this->entries[$this->currententry]->id = $id;
						}
						else
						{
							if($this->level++ == 0)
							{
								trigger_error("Entry without required id tag");
							}
							$this->unknown = true;
						}
						break;

					default:
						if($this->level++ == 0)
						{
							trigger_error("Unknown element \"$name\" inside <xml>");
						}
						$this->unknown = true;
				}
				break;

			case ADMS_IndexFileReadingEntry:
				if($i18n == 'true')
				{
					$value = i18n($value);
				}

				switch($name)
				{
					case 'META':
						$this->readingmode = ADMS_IndexFileReadingMeta;
						$this->entries[$this->currententry]->meta[$key] = $value;
						break;

					case 'IPACCESS':
						$this->readingmode = ADMS_IndexFileReadingIpAccess;
						$this->entries[$this->currententry]->ipAccess[$key] = self::interpretPermissionsString($value);
						break;

					case 'USERACCESS':
						$this->readingmode = ADMS_IndexFileReadingUserAccess;
						$this->entries[$this->currententry]->userAccess[$key] = self::interpretPermissionsString($value);
						break;

					case 'GROUPACCESS':
						$this->readingmode = ADMS_IndexFileReadingGroupAccess;
						$this->entries[$this->currententry]->groupAccess[$key] = self::interpretPermissionsString($value);
						break;

					case 'OTHERACCESS':
						$this->readingmode = ADMS_IndexFileReadingOtherAccess;
						$this->entries[$this->currententry]->otherAccess = self::interpretPermissionsString($value);
						break;

					default:
						if($this->level++ == 0)
						{
							trigger_error("Unknown element \"$name\" inside <entry>");
						}
						$this->unknown = true;
				}
				break;

			default:
				if($this->level++ == 0)
				{
					trigger_error("Element \"$name\" opened in element without children");
				}
				$this->unknown = true;
		}
	}

	// handles closing tags in XML files
	private function open_EndElement($parser, $name)
	{
		if($this->unknown == true)
		{
			if(--$this->level == 0)
			{
				$this->unknown = false;
			}
			return;
		}

		switch($this->readingmode)
		{
			case ADMS_IndexFileReadingRoot:
				if($name == 'XML')
				{
					$this->readingmode = ADMS_IndexFileReadingNothing;
				}
				else
				{
					trigger_error("Unknown element \"$name\" closed in <xml>");
				}
				break;

			case ADMS_IndexFileReadingEntry:
				if($name == 'ENTRY')
				{
					$this->readingmode = ADMS_IndexFileReadingRoot;
					$this->currententry++;
				}
				else
				{
					trigger_error("Unknown element \"$name\" closed in <entry>");
				}
				break;

			case ADMS_IndexFileReadingMeta:
				if($name == 'META')
				{
					$this->readingmode = ADMS_IndexFileReadingEntry;
				}
				else
				{
					trigger_error("Unknown element \"$name\" closed in <meta>");
				}
				break;

			case ADMS_IndexFileReadingIpAccess:
				if($name == 'IPACCESS')
				{
					$this->readingmode = ADMS_IndexFileReadingEntry;
				}
				else
				{
					trigger_error("Unknown element \"$name\" closed in <ipaccess>");
				}
				break;

			case ADMS_IndexFileReadingUserAccess:
				if($name == 'USERACCESS')
				{
					$this->readingmode = ADMS_IndexFileReadingEntry;
				}
				else
				{
					trigger_error("Unknown element \"$name\" closed in <useraccess>");
				}
				break;

			case ADMS_IndexFileReadingGroupAccess:
				if($name == 'GROUPACCESS')
				{
					$this->readingmode = ADMS_IndexFileReadingEntry;
				}
				else
				{
					trigger_error("Unknown element \"$name\" closed in <groupaccess>");
				}
				break;

			case ADMS_IndexFileReadingOtherAccess:
				if($name == 'OTHERACCESS')
				{
					$this->readingmode = ADMS_IndexFileReadingEntry;
				}
				else
				{
					trigger_error("Unknown element \"$name\" closed in <otheracces>");
				}
				break;
		}
	}

	// handles XML data
	private function open_Data($parser, $data)
	{
		return;
	}

	// opens the index.xml file in a directory
	public function open($filename, $mode = 'r')
	{
		$this->reset();
		// open the file
		if($fp = fopen($filename, 'r'))
		{
			// initialize XML parser
			$xml_parser = xml_parser_create();
			xml_set_element_handler($xml_parser, array($this, 'open_StartElement'), array($this, 'open_EndElement'));
			xml_set_character_data_handler($xml_parser, array($this, 'open_Data'));

			$this->readingmode = ADMS_IndexFileReadingNothing;
			$this->unknown = false;
			$this->level = 0;
			$this->currententry = 0;

			while($data = str_replace("\n", "", fread($fp, 4096)))
			{
				if(!xml_parse($xml_parser, $data, feof($fp)))
				{
					trigger_error("Couldn't parse XML index file: ".xml_error_string(xml_get_error_code($xml_parser)));
					$this->reset();
					return false;
				}
			}

			// clean up
			fclose($fp);
			xml_parser_free($xml_parser);

			$this->filename = $filename;

			Signal::emit('ADMS_IndexFileOpened', $this);

			return true;
		}

		trigger_error("Couldn't open XML index file");
		return false;
	}

	// saves the XML document in memory to file
	public function save($filename = false)
	{
		if($filename == false)
		{
			if($this->changed == false)
			{
				return true;
			}

			$filename = $this->filename;
		}

		// open the file
		if($fp = fopen($filename, 'w'))
		{
			// write heading
			fwrite($fp, "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n".
			            "<xml>\n");

			// write entries
			foreach($this->entries as $entry)
			{
				fwrite($fp, "  <entry id=\"{$entry->id}\">\n");
				foreach($entry->meta as $key => $value)
				{
					if($value == '')
					{
						continue;
					}

					if($value == i18n("(top of the system)"))
					{
						$value = "(top of the system)";
						$i18nOption = ' i18n="true"';
					}
					else
					{
						$i18nOption = '';
					}

					fwrite($fp, "    <meta key=\"$key\" value=\"".htmlspecialchars($value)."\"$i18nOption/>\n");
				}
				foreach($entry->ipAccess as $ipRange => $access)
				{
					$access = self::createPermissionsString($access);
					fwrite($fp, "    <ipaccess key=\"".htmlspecialchars($ipRange)."\" value=\"$access\"/>\n");
				}
				foreach($entry->userAccess as $user => $access)
				{
					$access = self::createPermissionsString($access);
					fwrite($fp, "    <useraccess key=\"".htmlspecialchars($user)."\" value=\"$access\"/>\n");
				}
				foreach($entry->groupAccess as $group => $access)
				{
					$access = self::createPermissionsString($access);
					fwrite($fp, "    <groupaccess key=\"".htmlspecialchars($group)."\" value=\"$access\"/>\n");
				}
				if(isset($entry->otherAccess))
				{
					$access = self::createPermissionsString($entry->otherAccess);
					fwrite($fp, "    <otheraccess value=\"$access\"/>\n");
				}

				fwrite($fp, "  </entry>\n");
			}

			// closing tag
			fwrite($fp, "</xml>\n");

			// clean up
			fclose($fp);

			Signal::emit('ADMS_IndexFileSaved', $this, $filename);

			return true;
		}

		trigger_error("Couldn't save XML index file");
		return false;
	}

	// returns the filename of the opened file
	public function filename()
	{
		return $this->filename;
	}

	// sets a new filename, this filename will be used as default when saving the file
	public function setFilename($filename)
	{
		$this->changed = true;
		$this->filename = $filename;
	}

	// returns all entries
	public function entries()
	{
		return $this->entries;
	}

	// returns the first free ID in this directory
	public function freeID()
	{
		for($id = 0; true; $id++)
		{
			if(glob(dirname($this->filename)."/$id*") == false)
			{
				return $id;
			}
		}
	}

	// adds an entry to the file
	public function addEntry($name)
	{
		$this->changed = true;
		$entrynum = sizeof($this->entries);

		$this->entries[$entrynum] = new ADMS_IndexFileEntry;
		$this->entries[$entrynum]->id = $this->freeID();
		$this->entries[$entrynum]->meta['name'] = $name;
		$this->entries[$entrynum]->meta['ctime'] = ''.time();
		$this->entries[$entrynum]->meta['mtime'] = ''.time();
		$this->entries[$entrynum]->meta['owner'] = Login::username();

		return $entrynum;
	}

	// searches for an entry given the id
	public function searchEntry($id)
	{
		foreach($this->entries as $entrynum => $entry)
		{
			if($entry->id == $id)
			{
				return $entrynum;
			}
		}
		return false;
	}

	// removes an entry from a file
	public function removeEntry($entrynum)
	{
		$this->changed = true;
		array_splice($this->entries, $entrynum, 1);
	}

	// returns the value of a meta key
	public function meta($entrynum, $key)
	{
		if(isset($this->entries[$entrynum]))
		{
			return (isset($this->entries[$entrynum]->meta[$key]) ? $this->entries[$entrynum]->meta[$key] : false);
		}
		return false;
	}

	// set a new meta key for an entry
	public function setMeta($entrynum, $key, $value = false)
	{
		if(isset($this->entries[$entrynum]))
		{
			$this->changed = true;
			if($value === false)
			{
				unset($this->entries[$entrynum]->meta[$key]);
			}
			else
			{
				$this->entries[$entrynum]->meta[$key] = $value;
			}
			$this->entries[$entrynum]->meta['mtime'] = ''.time();
		}
	}

	// returns all meta data in an array
	public function metaArray($entrynum)
	{
		if(isset($this->entries[$entrynum]))
		{
			return $this->entries[$entrynum]->meta;
		}
		return array();
	}

	// sets all meta data through an array
	public function setMetaArray($entrynum, $metaArray)
	{
		if(isset($this->entries[$entrynum]))
		{
			$this->entries[$entrynum]->meta = $metaArray;
			$this->entries[$entrynum]->meta['mtime'] = ''.time();
		}
	}

	// returns the access for a given IP range
	public function ipAccess($entrynum, $ipRange)
	{
		if(isset($this->entries[$entrynum]))
		{
			return (isset($this->entries[$entrynum]->ipAccess[$ipRange]) ? $this->entries[$entrynum]->ipAccess[$ipRange] : false);
		}
		return false;
	}

	// sets access rights for an IP range for an entry
	public function setIpAccess($entrynum, $ipRange, $access = false)
	{
		if(isset($this->entries[$entrynum]))
		{
			$this->changed = true;
			if($access === false)
			{
				unset($this->entries[$entrynum]->ipAccess[$ipRange]);
			}
			else
			{
				$this->entries[$entrynum]->ipAccess[$ipRange] = $access;
			}
		}
	}

	// returns the access permissions of all IP ranges in an array
	public function ipAccessArray($entrynum)
	{
		if(isset($this->entries[$entrynum]))
		{
			return $this->entries[$entrynum]->ipAccess;
		}
		return array();
	}

	// sets the access permissions for all IP ranges through an array
	public function setIpAccessArray($entrynum, $accessArray)
	{
		if(isset($this->entries[$entrynum]))
		{
			$this->changed = true;
			$this->entries[$entrynum]->ipAccess = $accessArray;
		}
	}

	// returns the access for a certain user
	public function userAccess($entrynum, $user)
	{
		if(isset($this->entries[$entrynum]))
		{
			return (isset($this->entries[$entrynum]->userAccess[$user]) ? $this->entries[$entrynum]->userAccess[$user] : false);
		}
		return false;
	}

	// sets access rights for a user for an entry
	public function setUserAccess($entrynum, $user, $access = false)
	{
		if(isset($this->entries[$entrynum]))
		{
			$this->changed = true;
			if($access === false)
			{
				unset($this->entries[$entrynum]->userAccess[$user]);
			}
			else
			{
				$this->entries[$entrynum]->userAccess[$user] = $access;
			}
		}
	}

	// returns the access permissions of all users in an array
	public function userAccessArray($entrynum)
	{
		if(isset($this->entries[$entrynum]))
		{
			return $this->entries[$entrynum]->userAccess;
		}
		return array();
	}

	// sets the access permissions for all users through an array
	public function setUserAccessArray($entrynum, $accessArray)
	{
		if(isset($this->entries[$entrynum]))
		{
			$this->changed = true;
			$this->entries[$entrynum]->userAccess = $accessArray;
		}
	}

	// returns the access for a certain group
	public function groupAccess($entrynum, $group)
	{
		if(isset($this->entries[$entrynum]))
		{
			return (isset($this->entries[$entrynum]->groupAccess[$group]) ? $this->entries[$entrynum]->groupAccess[$group] : false);
		}
		return false;
	}

	// sets access rights for a group for an entry
	public function setGroupAccess($entrynum, $group, $access = false)
	{
		if(isset($this->entries[$entrynum]))
		{
			$this->changed = true;
			if($access === false)
			{
				unset($this->entries[$entrynum]->groupAccess[$group]);
			}
			else
			{
				$this->entries[$entrynum]->groupAccess[$group] = $access;
			}
		}
	}

	// returns the access permissions of all groups in an array
	public function groupAccessArray($entrynum)
	{
		if(isset($this->entries[$entrynum]))
		{
			return $this->entries[$entrynum]->groupAccess;
		}
		return array();
	}

	// sets the access permissions for all groups through an array
	public function setGroupAccessArray($entrynum, $accessArray)
	{
		if(isset($this->entries[$entrynum]))
		{
			$this->changed = true;
			$this->entries[$entrynum]->groupAccess = $accessArray;
		}
	}

	// returns the access for others
	public function otherAccess($entrynum)
	{
		if(isset($this->entries[$entrynum]))
		{
			return (isset($this->entries[$entrynum]->otherAccess) ? $this->entries[$entrynum]->otherAccess : false);
		}
		return false;
	}

	// sets access rights for others for an entry
	public function setOtherAccess($entrynum, $access = false)
	{
		if(isset($this->entries[$entrynum]))
		{
			$this->changed = true;
			if($access === false)
			{
				unset($this->entries[$entrynum]->otherAccess);
			}
			else
			{
				$this->entries[$entrynum]->otherAccess = $access;
			}
		}
	}

	// interprets a comma-seperated string containing permissions
	protected static function interpretPermissionsString($permissionsString)
	{
		$permissions = PERMISSION_NONE;
		$permissionStrings = explode(',', $permissionsString);
		for($permission = PERMISSION_READ; $permission <= PERMISSION_ADMINISTRATE; $permission <<= 1)
		{
			if(array_search(self::$permissions[$permission], $permissionStrings) !== false)
			{
				$permissions |= $permission;
			}
		}
		return $permissions;
	}

	// creates a comma-seperated string listed all permissions
	protected static function createPermissionsString($permissions)
	{
		$permissionsString = 'none';
		for($permission = PERMISSION_READ; $permission <= PERMISSION_ADMINISTRATE; $permission <<= 1)
		{
			if($permissions & $permission)
			{
				if($permissionsString == 'none')
				{
					$permissionsString = self::$permissions[$permission];
				}
				else
				{
					$string = self::$permissions[$permission];
					$permissionsString .= ",$string";
				}
			}
		}
		return $permissionsString;
	}

	protected static $permissions;     // strings for specifying permissions
	protected $filename;               // name of the current file
	protected $entries;                // array containing the entries
	protected $changed;                // boolean telling when the indexfile needs to be changed
}

?>
Return current item: Aukyla Document Management System