From: Roland Haeder <roland@mxchange.org>
Date: Wed, 14 May 2014 19:17:21 +0000 (+0200)
Subject: Rewrote both file i/o classes to have a common BaseFileIo class.
X-Git-Url: https://git.mxchange.org/?a=commitdiff_plain;h=6fad95e67a217fe10f5cd024ac13bf4f07416c0b;p=core.git

Rewrote both file i/o classes to have a common BaseFileIo class.

Signed-off-by: Roland Häder <roland@mxchange.org>
---

diff --git a/inc/classes/main/class_Base b/inc/classes/main/class_Base
index cdef34a6..992be1bf 100644
--- a/inc/classes/main/class_Base
+++ b/inc/classes/main/class_Base
@@ -1,6 +1,6 @@
 <?php
 /**
- * A general ???
+ * A general ??? class
  *
  * @author		Roland Haeder <webmaster@ship-simu.org>
  * @version		0.0.0
diff --git a/inc/classes/main/io/class_BaseFileIo.php b/inc/classes/main/io/class_BaseFileIo.php
new file mode 100644
index 00000000..a18a8529
--- /dev/null
+++ b/inc/classes/main/io/class_BaseFileIo.php
@@ -0,0 +1,128 @@
+<?php
+/**
+ * A general FileIo class
+ *
+ * @author		Roland Haeder <webmaster@ship-simu.org>
+ * @version		0.0.0
+ * @copyright	Copyright (c) 2007, 2008 Roland Haeder, 2009 - 2012 Core Developer Team
+ * @license		GNU GPL 3.0 or any newer version
+ * @link		http://www.ship-simu.org
+ *
+ * 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 3 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, see <http://www.gnu.org/licenses/>.
+ */
+class BaseFileIo extends BaseFrameworkSystem {
+	/**
+	 * The current file we are working in
+	 */
+	private $fileName = '';
+
+	/**
+	 * The file pointer
+	 */
+	private $filePointer = NULL;
+
+	/**
+	 * Protected constructor
+	 *
+	 * @param	$className	Name of the class
+	 * @return	void
+	 */
+	protected function __construct ($className) {
+		// Call parent constructor
+		parent::__construct($className);
+	}
+
+	/**
+	 * Destructor for cleaning purposes, etc
+	 *
+	 * @return	void
+	 */
+	public final function __destruct() {
+		// Is there a resource pointer? Then we have to close the file here!
+		if (is_resource($this->getPointer())) {
+			// Try to close a file
+			$this->closeFile();
+		} // END - if
+
+		// Call the parent destructor
+		parent::__destruct();
+	}
+
+	/**
+	 * Close a file source and set it's instance to null and the file name
+	 * to empty
+	 *
+	 * @return	void
+	 * @throws	NullPointerException	If the file pointer instance
+	 *									is not set by setPointer()
+	 * @throws	InvalidResourceException	If there is being set
+	 */
+	public function closeFile () {
+		if (is_null($this->getPointer())) {
+			// Pointer not initialized
+			throw new NullPointerException($this, self::EXCEPTION_IS_NULL_POINTER);
+		} elseif (!is_resource($this->getPointer())) {
+			// Pointer is not a valid resource!
+			throw new InvalidResourceException($this, self::EXCEPTION_INVALID_RESOURCE);
+		}
+
+		// Close the file pointer and reset the instance variable
+		@fclose($this->getPointer());
+		$this->setPointer(NULL);
+		$this->setFileName('');
+	}
+
+	/**
+	 * Setter for the file pointer
+	 *
+	 * @param	$filePointer	File resource
+	 * @return	void
+	 */
+	public final function setPointer ($filePointer) {
+		$this->filePointer = $filePointer;
+	}
+
+	/**
+	 * Getter for the file pointer
+	 *
+	 * @return	$filePointer	The file pointer which shall be a valid
+	 *							file resource
+	 */
+	public final function getPointer () {
+		return $this->filePointer;
+	}
+
+	/**
+	 * Setter for file name
+	 *
+	 * @param	$fileName	The new file name
+	 * @return	void
+	 */
+	public final function setFileName ($fileName) {
+		$fileName = (string) $fileName;
+		$this->fileName = $fileName;
+	}
+
+	/**
+	 * Getter for file name
+	 *
+	 * @return	$fileName	The current file name
+	 */
+	public final function getFileName () {
+		return $this->fileName;
+	}
+}
+
+// [EOF]
+?>
diff --git a/inc/classes/main/io/class_FileIoStream.php b/inc/classes/main/io/class_FileIoStream.php
deleted file mode 100644
index 35d00edd..00000000
--- a/inc/classes/main/io/class_FileIoStream.php
+++ /dev/null
@@ -1,264 +0,0 @@
-<?php
-/**
- * An universal class for file input/output streams.
- *
- * @author		Roland Haeder <webmaster@shipsimu.org>
- * @version		0.0.0
- * @copyright	Copyright (c) 2007, 2008 Roland Haeder, 2009 - 2013 Core Developer Team
- * @license		GNU GPL 3.0 or any newer version
- * @link		http://www.shipsimu.org
- *
- * 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 3 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, see <http://www.gnu.org/licenses/>.
- */
-class FileIoStream extends BaseFrameworkSystem implements FileInputStreamer, FileOutputStreamer {
-	/**
-	 * File header indicator
-	 */
-	const FILE_IO_FILE_HEADER_ID = '@head';
-
-	/**
-	 * Data block indicator
-	 */
-	const FILE_IO_DATA_BLOCK_ID = '@data';
-
-	/**
-	 * Separator #1
-	 */
-	const FILE_IO_CHUNKER = ':';
-
-	/**
-	 * Separator #2
-	 */
-	const FILE_IO_SEPARATOR = '^';
-
-	/**
-	 * Protected constructor
-	 */
-	protected function __construct () {
-		// Call parent constructor
-		parent::__construct(__CLASS__);
-	}
-
-	/**
-	 * Create a file IO stream. This is a class for performing all actions
-	 * on files like creating, deleting and loading them.
-	 *
-	 * @return	$ioInstance	An instance of FileIoStream
-	 */
-	public static final function createFileIoStream () {
-		// Create new instance
-		$ioInstance = new FileIoStream();
-
-		// Return the instance
-		return $ioInstance;
-	}
-
-	/**
-	 * Saves data to a given local file and create missing directory structures
-	 *
-	 * @param	$fileName	The file name for the to be saved file
-	 * @param	$dataArray	The data we shall store to the file
-	 * @return	void
-	 * @see		FileOutputStreamer
-	 * @todo	This method needs heavy rewrite
-	 */
-	public final function saveFile ($fileName, array $dataArray) {
-		// Try it five times
-		$dirName = ''; $fileInstance = NULL;
-		for ($idx = 0; $idx < 5; $idx++) {
-			// Get a file output pointer
-			try {
-				$fileInstance = FrameworkFileOutputPointer::createFrameworkFileOutputPointer($fileName, 'w');
-			} catch (FileIoException $e) {
-				// Create missing directory
-				$dirName = dirname($fileName);
-				for ($idx2 = 0; $idx2 < (2 - $idx); $idx2++) {
-					$dirName = dirname($dirName);
-				} // END - for
-
-				// Try to create it
-				@mkdir($dirName);
-			}
-		} // END - for
-
-		// Write a header information for validation purposes
-		$fileInstance->writeToFile(sprintf("%s%s%s%s%s%s%s%s%s\n",
-			self::FILE_IO_FILE_HEADER_ID,
-			self::FILE_IO_SEPARATOR,
-			$dataArray[0],
-			self::FILE_IO_CHUNKER,
-			time(),
-			self::FILE_IO_CHUNKER,
-			strlen($dataArray[1]),
-			self::FILE_IO_CHUNKER,
-			md5($dataArray[1])
-		));
-
-		// Encode the (maybe) binary stream with Base64
-		$b64Stream = base64_encode($dataArray[1]);
-
-		// write the data line by line
-		$line = str_repeat(' ', 50); $idx = 0;
-		while (strlen($line) == 50) {
-			// Get 50 chars or less
-			$line = substr($b64Stream, $idx, 50);
-
-			// Save it to the stream
-			$fileInstance->writeToFile(sprintf("%s%s%s%s%s\n",
-				self::FILE_IO_DATA_BLOCK_ID,
-				self::FILE_IO_SEPARATOR,
-				$line,
-				self::FILE_IO_CHUNKER,
-				md5($line)
-			));
-
-			// Advance to the next 50-chars block
-			$idx += 50;
-		} // END - while
-
-		// Close the file
-		$fileInstance->closeFile();
-	}
-
-	/**
-	 * Reads from a local file
-	 *
-	 * @param		$fqfn	The full-qualified file-name which we shall load
-	 * @return	$array	An array with the element 'header' and 'data'
-	 * @see		FileInputStreamer
-	 */
-	public final function loadFileContents ($fqfn) {
-		// Initialize some variables and arrays
-		$inputBuffer = '';
-		$lastBuffer = '';
-		$header = array();
-		$data = array();
-		$readData = ''; // This will contain our read data
-
-		// Get a file input handler
-		$fileInstance = FrameworkFileInputPointer::createFrameworkFileInputPointer($fqfn);
-
-		// Read all it's contents (we very and transparently decompress it below)
-		while ($readRawLine = $fileInstance->readFromFile()) {
-			// Add the read line to the buffer
-			$inputBuffer .= $readRawLine;
-
-			// Break infinite loop maybe caused by the input handler
-			if ($lastBuffer == $inputBuffer) break;
-
-			// Remember last read line for avoiding possible infinite loops
-			$lastBuffer = $inputBuffer;
-		} // END - while
-
-		// Close directory handle
-		$fileInstance->closeFile();
-
-		// Convert it into an array
-		$inputBuffer = explode(chr(10), $inputBuffer);
-
-		// Now process the read lines and verify it's content
-		foreach ($inputBuffer as $rawLine) {
-			// Trim it a little but not the leading spaces/tab-stops
-			$rawLine = rtrim($rawLine);
-
-			// Analyze this line
-			if (substr($rawLine, 0, 5) == self::FILE_IO_FILE_HEADER_ID) {
-				// Header found, so let's extract it
-				$header = explode(self::FILE_IO_SEPARATOR, $rawLine);
-				$header = trim($header[1]);
-
-				// Now we must convert it again into an array
-				$header = explode(self::FILE_IO_CHUNKER, $header);
-
-				// Is the header (maybe) valid?
-				if (count($header) != 4) {
-					// Throw an exception
-					throw new InvalidArrayCountException(array($this, 'header', count($header), 4), self::EXCEPTION_ARRAY_HAS_INVALID_COUNT);
-				} // END - if
-			} elseif (substr($rawLine, 0, 5) == self::FILE_IO_DATA_BLOCK_ID) {
-				// Is a data line!
-				$data = explode(self::FILE_IO_SEPARATOR, $rawLine);
-				$data = $data[1];
-
-				// First element is the data, second the MD5 checksum
-				$data = explode(self::FILE_IO_CHUNKER, $data);
-
-				// Validate the read line
-				if (count($data) == 2) {
-					if (md5($data[0]) != $data[1]) {
-						// MD5 hash did not match!
-						throw new InvalidMD5ChecksumException(array($this, md5($data[0]), $data[1]), self::EXCEPTION_MD5_CHECKSUMS_MISMATCH);
-					} // END - if
-				} else {
-					// Invalid count!
-					throw new InvalidArrayCountException(array($this, 'data', count($data), 2), self::EXCEPTION_ARRAY_HAS_INVALID_COUNT);
-				}
-
-				// Add this to the readData string
-				$readData .= $data[0];
-			} else {
-				// Other raw lines than header/data tagged lines and re-add the new-line char
-				$readData .= $rawLine . PHP_EOL;
-			}
-		} // END - foreach
-
-		// Was raw lines read and no header/data?
-		if ((!empty($readData)) && (count($header) == 0) && (count($data) == 0)) {
-			// Return raw lines back
-			return $readData;
-		} // END - if
-
-		// Was a header found?
-		if (count($header) != 4) {
-			// Throw an exception
-			throw new InvalidArrayCountException(array($this, 'header', count($header), 4), self::EXCEPTION_ARRAY_HAS_INVALID_COUNT);
-		} // END - if
-
-		// Decode all from Base64
-		$readData = @base64_decode($readData);
-
-		// Does the size match?
-		if (strlen($readData) != $header[2]) {
-			// Size did not match
-			throw new InvalidDataLengthException(array($this, strlen($readData), $header[2]), self::EXCEPTION_UNEXPECTED_STRING_SIZE);
-		} // END - if
-
-		// Validate the decoded data with the final MD5 hash
-		if (md5($readData) != $header[3]) {
-			// MD5 hash did not match!
-			throw new InvalidMD5ChecksumException(array($this, md5($readData), $header[3]), self::EXCEPTION_MD5_CHECKSUMS_MISMATCH);
-		} // END - if
-
-		// Return all in an array
-		return array(
-			'header' => $header,
-			'data'   => $readData
-		);
-	}
-
-	/**
-	 * Streams the data and maybe does something to it
-	 *
-	 * @param	$data	The data (string mostly) to "stream"
-	 * @return	$data	The data (string mostly) to "stream"
-	 * @throws	UnsupportedOperationException	If this method is called
-	 */
-	public function streamData ($data) {
-		self::createDebugInstance(__CLASS__)->debugOutput('Unhandled ' . strlen($data) . ' bytes in this stream.');
-		throw new UnsupportedOperationException(array($this, __FUNCTION__), self::EXCEPTION_UNSPPORTED_OPERATION);
-	}
-}
-
-// [EOF]
-?>
diff --git a/inc/classes/main/io/class_FrameworkDirectoryPointer.php b/inc/classes/main/io/class_FrameworkDirectoryPointer.php
deleted file mode 100644
index da220403..00000000
--- a/inc/classes/main/io/class_FrameworkDirectoryPointer.php
+++ /dev/null
@@ -1,229 +0,0 @@
-<?php
-/**
- * A class for directory reading and getting its contents, no recursion!
- *
- * @author		Roland Haeder <webmaster@shipsimu.org>
- * @version		0.0.0
- * @copyright	Copyright (c) 2007, 2008 Roland Haeder, 2009 - 2013 Core Developer Team
- * @license		GNU GPL 3.0 or any newer version
- * @link		http://www.shipsimu.org
- *
- * 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 3 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, see <http://www.gnu.org/licenses/>.
- */
-class FrameworkDirectoryPointer extends BaseFrameworkSystem {
-	/**
-	 * The current path we are working in
-	 */
-	private $pathName = '';
-
-	/**
-	 * The directory iterator instance
-	 */
-	private $directoryInstance = NULL;
-
-	/**
-	 * Protected constructor
-	 */
-	protected function __construct () {
-		// Call parent constructor
-		parent::__construct(__CLASS__);
-	}
-
-	/**
-	 * Destructor for cleaning purposes, etc
-	 */
-	public function __destruct() {
-		// Is there a resource pointer? Then we have to close the directory here!
-		if ($this->getDirectoryInstance() instanceof DirectoryIterator) {
-			// Try to close a directory
-			$this->closeDirectory();
-		} // END - if
-
-		// Call the parent destructor
-		parent::__destruct();
-	}
-
-	/**
-	 * Create a directory pointer based on the given path. The path will also
-	 * be verified here.
-	 *
-	 * @param	$pathName		The path name we shall pass to opendir()
-	 * @param	$inConstructor	If we are in de/con-structor or from somewhere else
-	 * @return	$pointerInstance	A prepared instance of FrameworkDirectoryPointer
-	 * @throws	PathIsEmptyException	If the provided path name is empty
-	 * @throws	InvalidPathStringException	If the provided path name is not a string
-	 * @throws	PathIsNoDirectoryException	If the provided path name is not valid
-	 * @throws	PathReadProtectedException	If the provided path name is read-protected
-	 * @todo	Get rid of inConstructor, could be old-lost code.
-	 */
-	public static final function createFrameworkDirectoryPointer ($pathName, $inConstructor = FALSE) {
-		// Some pre-sanity checks...
-		if (is_null($pathName)) {
-			// No pathname given
-			if ($inConstructor) {
-				return NULL;
-			} else {
-				throw new PathIsEmptyException(NULL, self::EXCEPTION_UNEXPECTED_EMPTY_STRING);
-			}
-		} elseif (!is_string($pathName)) {
-			// Is not a string
-			if ($inConstructor) {
-				return NULL;
-			} else {
-				throw new InvalidPathStringException(NULL, self::EXCEPTION_INVALID_STRING);
-			}
-		} elseif (!is_dir($pathName)) {
-			// Not a directory
-			if ($inConstructor) {
-				return NULL;
-			} else {
-				throw new PathIsNoDirectoryException($pathName, self::EXCEPTION_INVALID_PATH_NAME);
-			}
-		} elseif (!is_readable($pathName)) {
-			// Not readable
-			if ($inConstructor) {
-				return NULL;
-			} else {
-				throw new PathReadProtectedException($pathName, self::EXCEPTION_READ_PROTECED_PATH);
-			}
-		}
-
-		// Get an iterator for the directory
-		$directoryInstance = new DirectoryIterator($pathName);
-
-		// Create new instance
-		$pointerInstance = new FrameworkDirectoryPointer();
-
-		// Set directory pointer and path name
-		$pointerInstance->setDirectoryInstance($directoryInstance);
-		$pointerInstance->setPathName($pathName);
-
-		// Return the instance
-		return $pointerInstance;
-	}
-
-	/**
-	 * Read raw lines of data from a directory pointer and return the data
-	 *
-	 * @return	$current	Current entry from encapsulated iterator
-	 */
-	public function readRawDirectory () {
-		// Can the next entry be read?
-		assert($this->getDirectoryInstance()->valid());
-
-		// Default is FALSE
-		$current = FALSE;
-
-		// Is it a dot directory?
-		if (!$this->getDirectoryInstance()->isDot()) {
-			// Read data from the directory pointer and return it
-			$current = $this->getDirectoryInstance()->current();
-		} // END - if
-
-		// Advance to next entry
-		$this->getDirectoryInstance()->next();
-
-		// Return found entry
-		return $current;
-	}
-
-	/**
-	 * Read lines from the current directory pointer except some parts
-	 *
-	 * @param	$except		Some parts of a directory we want to ignore. Valid: directory and file names, other values will be silently ignored
-	 * @return	string		Directory and/or file names read from the current directory pointer
-	 */
-	public function readDirectoryExcept (array $except = array()) {
-		// No exceptions given?
-		if (count($except) == 0) {
-			// No exception given, so read all files and directories, but not recursive
-			self::createDebugInstance(__CLASS__)->debugOutput('DIRECTORY[' . __METHOD__ . ':' . __LINE__ . ']: No exceptions given, please use readRawDirectory() instead!');
-			return $this->readRawDirectory();
-		} // END - if
-
-		// Read a raw line...
-		$rawLine = $this->readRawDirectory();
-		//* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput('DIRECTORY[' . __METHOD__ . ':' . __LINE__ . ']: rawLine[' . gettype($rawLine) . ']=' . $rawLine);
-
-		// Shall we exclude directories?
-		if ((!is_null($rawLine)) && ($rawLine !== FALSE) && (!in_array($rawLine, $except))) {
-			// Return read data
-			//* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput('DIRECTORY[' . __METHOD__ . ':' . __LINE__ . ']: rawLine[' . gettype($rawLine) . ']=' . $rawLine);
-			return $rawLine;
-		} elseif ((!is_null($rawLine)) && ($rawLine !== FALSE)) {
-			// Exclude this part
-			//* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput('DIRECTORY[' . __METHOD__ . ':' . __LINE__ . ']: rawline[' . gettype($rawLine) . ']=' . $rawLine . ' - Recursive call!');
-			return $this->readDirectoryExcept($except);
-		}
-
-		// End pointer reached
-		//* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput('DIRECTORY[' . __METHOD__ . ':' . __LINE__ . ']: Returning NULL!');
-		return NULL;
-	}
-
-	/**
-	 * Close a directory source and set it's instance to null and the path name
-	 * to empty
-	 *
-	 * @return	void
-	 */
-	public function closeDirectory () {
-		// Close the directory by unsetting it
-		$this->setDirectoryInstance(NULL);
-		$this->setPathName('');
-	}
-
-	/**
-	 * Setter for the directory pointer
-	 *
-	 * @param	$directoryInstance	An instanceof a DirectoryIterator class or NULL to unset ("close") it.
-	 * @return	void
-	 */
-	protected final function setDirectoryInstance (DirectoryIterator $directoryInstance = NULL) {
-		// Set instance (or NULL)
-		$this->directoryInstance = $directoryInstance;
-	}
-
-	/**
-	 * Getter for the directory pointer
-	 *
-	 * @return	$directoryInstance	The directory pointer which shall be a valid directory resource
-	 */
-	public final function getDirectoryInstance () {
-		return $this->directoryInstance;
-	}
-
-	/**
-	 * Setter for path name
-	 *
-	 * @param	$pathName	The new path name
-	 * @return	void
-	 */
-	public final function setPathName ($pathName) {
-		$pathName = (string) $pathName;
-		$this->pathName = $pathName;
-	}
-
-	/**
-	 * Getter for path name
-	 *
-	 * @return	$pathName	The current path name
-	 */
-	public final function getPathName () {
-		return $this->pathName;
-	}
-}
-
-// [EOF]
-?>
diff --git a/inc/classes/main/io/class_FrameworkFileInputPointer.php b/inc/classes/main/io/class_FrameworkFileInputPointer.php
deleted file mode 100644
index f46e48ae..00000000
--- a/inc/classes/main/io/class_FrameworkFileInputPointer.php
+++ /dev/null
@@ -1,196 +0,0 @@
-<?php
-/**
- * A class for reading files
- *
- * @author		Roland Haeder <webmaster@shipsimu.org>
- * @version		0.0.0
- * @copyright	Copyright (c) 2007, 2008 Roland Haeder, 2009 - 2013 Core Developer Team
- * @license		GNU GPL 3.0 or any newer version
- * @link		http://www.shipsimu.org
- *
- * 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 3 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, see <http://www.gnu.org/licenses/>.
- */
-class FrameworkFileInputPointer extends BaseFrameworkSystem {
-	/**
-	 * The current file we are working in
-	 */
-	private $fileName = '';
-
-	/**
-	 * The file pointer
-	 */
-	private $filePointer = NULL;
-
-	/**
-	 * Protected constructor
-	 *
-	 * @return	void
-	 */
-	protected function __construct () {
-		// Call parent constructor
-		parent::__construct(__CLASS__);
-	}
-
-	/**
-	 * Destructor for cleaning purposes, etc
-	 *
-	 * @return	void
-	 */
-	public final function __destruct() {
-		// Is there a resource pointer? Then we have to close the file here!
-		if (is_resource($this->getPointer())) {
-			// Try to close a file
-			$this->closeFile();
-		}
-
-		// Call the parent destructor
-		parent::__destruct();
-	}
-
-	/**
-	 * Create a file pointer based on the given file. The file will also
-	 * be verified here.
-	 *
-	 * @param		$fileName	The file name we shall pass to fopen()
-	 * @throws	FileIsEmptyException	If the provided file name is empty.
-	 * @throws	FileIoException		If fopen() returns not a file resource
-	 * @return	void
-	 */
-	public static final function createFrameworkFileInputPointer ($fileName) {
-		// Some pre-sanity checks...
-		if ((is_null($fileName)) || (empty($fileName))) {
-			// No filename given
-			throw new FileIsEmptyException(NULL, self::EXCEPTION_UNEXPECTED_EMPTY_STRING);
-		} elseif (!file_exists($fileName)) {
-			// File does not exist!
-			throw new FileIoException($fileName, self::EXCEPTION_FILE_NOT_FOUND);
-		} elseif (!is_readable($fileName)) {
-			// File does not exist!
-			throw new FileReadProtectedException($fileName, self::EXCEPTION_FILE_CANNOT_BE_READ);
-		}
-
-		// Try to open a handler
-		$filePointer = fopen($fileName, 'rb');
-		if ((is_null($filePointer)) || ($filePointer === FALSE)) {
-			// Something bad happend
-			throw new FileIoException($fileName, self::EXCEPTION_FILE_POINTER_INVALID);
-		} // END - if
-
-		// Create new instance
-		$pointerInstance = new FrameworkFileInputPointer();
-
-		// Set file pointer and file name
-		$pointerInstance->setPointer($filePointer);
-		$pointerInstance->setFileName($fileName);
-
-		// Return the instance
-		return $pointerInstance;
-	}
-
-	/**
-	 * Read data a file pointer
-	 *
-	 * @return	mixed	The result of fread()
-	 * @throws	NullPointerException	If the file pointer instance
-	 *									is not set by setPointer()
-	 * @throws	InvalidResourceException	If there is being set
-	 *									an invalid file resource
-	 */
-	public function readFromFile () {
-		if (is_null($this->getPointer())) {
-			// Pointer not initialized
-			throw new NullPointerException($this, self::EXCEPTION_IS_NULL_POINTER);
-		} elseif (!is_resource($this->getPointer())) {
-			// Pointer is not a valid resource!
-			throw new InvalidResourceException($this, self::EXCEPTION_INVALID_RESOURCE);
-		}
-
-		// Read data from the file pointer and return it
-		return fread($this->getPointer(), 1024);
-	}
-
-	/**
-	 * Close a file source and set it's instance to null and the file name
-	 * to empty
-	 *
-	 * @return	void
-	 * @throws	NullPointerException	If the file pointer instance
-	 *									is not set by setPointer()
-	 * @throws	InvalidResourceException	If there is being set
-	 */
-	public function closeFile () {
-		if (is_null($this->getPointer())) {
-			// Pointer not initialized
-			throw new NullPointerException($this, self::EXCEPTION_IS_NULL_POINTER);
-		} elseif (!is_resource($this->getPointer())) {
-			// Pointer is not a valid resource!
-			throw new InvalidResourceException($this, self::EXCEPTION_INVALID_RESOURCE);
-		}
-
-		// Close the file pointer and reset the instance variable
-		@fclose($this->getPointer());
-		$this->setPointer(NULL);
-		$this->setFileName('');
-	}
-
-	/**
-	 * Setter for the file pointer
-	 *
-	 * @param	$filePointer	File resource
-	 * @return	void
-	 */
-	public final function setPointer ($filePointer) {
-		// Sanity-check if pointer is a valid file resource
-		if (is_resource($filePointer) || is_null($filePointer)) {
-			// Is a valid resource
-			$this->filePointer = $filePointer;
-		} else {
-			// Throw exception
-			throw new InvalidResourceException($this, self::EXCEPTION_INVALID_RESOURCE);
-		}
-	}
-
-	/**
-	 * Getter for the file pointer
-	 *
-	 * @return	$filePointer	The file pointer which shall be a valid
-	 *							file resource
-	 */
-	public final function getPointer () {
-		return $this->filePointer;
-	}
-
-	/**
-	 * Setter for file name
-	 *
-	 * @param	$fileName	The new file name
-	 * @return	void
-	 */
-	public final function setFileName ($fileName) {
-		$fileName = (string) $fileName;
-		$this->fileName = $fileName;
-	}
-
-	/**
-	 * Getter for file name
-	 *
-	 * @return	$fileName	The current file name
-	 */
-	public final function getFileName () {
-		return $this->fileName;
-	}
-}
-
-// [EOF]
-?>
diff --git a/inc/classes/main/io/class_FrameworkFileOutputPointer.php b/inc/classes/main/io/class_FrameworkFileOutputPointer.php
deleted file mode 100644
index 8d80e715..00000000
--- a/inc/classes/main/io/class_FrameworkFileOutputPointer.php
+++ /dev/null
@@ -1,188 +0,0 @@
-<?php
-/**
- * A class for writing files
- *
- * @author		Roland Haeder <webmaster@shipsimu.org>
- * @version		0.0.0
- * @copyright	Copyright (c) 2007, 2008 Roland Haeder, 2009 - 2013 Core Developer Team
- * @license		GNU GPL 3.0 or any newer version
- * @link		http://www.shipsimu.org
- *
- * 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 3 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, see <http://www.gnu.org/licenses/>.
- */
-class FrameworkFileOutputPointer extends BaseFrameworkSystem {
-	/**
-	 * The current file we are working in
-	 */
-	private $fileName = '';
-
-	/**
-	 * The file pointer
-	 */
-	private $filePointer = NULL;
-
-	/**
-	 * Protected constructor
-	 */
-	protected function __construct () {
-		// Call parent constructor
-		parent::__construct(__CLASS__);
-	}
-
-	/**
-	 * Destructor for cleaning purposes, etc
-	 */
-	public final function __destruct() {
-		// Is there a resource pointer? Then we have to close the file here!
-		if (is_resource($this->getPointer())) {
-			// Try to close a file
-			$this->closeFile();
-		}
-
-		// Call the parent destructor
-		parent::__destruct();
-	}
-
-	/**
-	 * Create a file pointer based on the given file. The file will also
-	 * be verified here.
-	 *
-	 * @param	$fileName	The file name we shall pass to fopen()
-	 * @param	$mode		The output mode ('w', 'a' are valid)
-	 * @throws	FileIsEmptyException	If the provided file name is empty.
-	 * @throws	FileIoException		If fopen() returns not a file resource
-	 * @return	void
-	 */
-	public static final function createFrameworkFileOutputPointer ($fileName, $mode) {
-		// Some pre-sanity checks...
-		if (is_null($fileName)) {
-			// No filename given
-			throw new FileIsEmptyException(NULL, self::EXCEPTION_UNEXPECTED_EMPTY_STRING);
-		} // END - if
-
-		// Try to open a handler
-		$filePointer = @fopen($fileName, $mode);
-		if ((is_null($filePointer)) || ($filePointer === FALSE)) {
-			// Something bad happend
-			throw new FileIoException ($fileName, self::EXCEPTION_FILE_POINTER_INVALID);
-		} // END - if
-
-		// Create new instance
-		$pointerInstance = new FrameworkFileOutputPointer();
-
-		// Set file pointer and file name
-		$pointerInstance->setPointer($filePointer);
-		$pointerInstance->setFileName($fileName);
-
-		// Return the instance
-		return $pointerInstance;
-	}
-
-	/**
-	 * Write data to a file pointer
-	 *
-	 * @param	$dataStream		The data stream we shall write to the file
-	 * @return	mixed			Number of writes bytes or FALSE on error
-	 * @throws	NullPointerException	If the file pointer instance
-	 *									is not set by setPointer()
-	 * @throws	InvalidResourceException	If there is being set
-	 *											an invalid file resource
-	 */
-	public function writeToFile ($dataStream) {
-		if (is_null($this->getPointer())) {
-			// Pointer not initialized
-			throw new NullPointerException($this, self::EXCEPTION_IS_NULL_POINTER);
-		} elseif (!is_resource($this->getPointer())) {
-			// Pointer is not a valid resource!
-			throw new InvalidResourceException($this, self::EXCEPTION_INVALID_RESOURCE);
-		}
-
-		// Write data to the file pointer and return written bytes
-		return fwrite($this->getPointer(), $dataStream);
-	}
-
-	/**
-	 * Close a file source and set it's instance to null and the file name
-	 * to empty
-	 *
-	 * @return	void
-	 * @throws	NullPointerException	If the file pointer instance
-	 *									is not set by setPointer()
-	 * @throws	InvalidResourceException	If there is being set
-	 */
-	public function closeFile () {
-		if (is_null($this->getPointer())) {
-			// Pointer not initialized
-			throw new NullPointerException($this, self::EXCEPTION_IS_NULL_POINTER);
-		} elseif (!is_resource($this->getPointer())) {
-			// Pointer is not a valid resource!
-			throw new InvalidResourceException($this, self::EXCEPTION_INVALID_RESOURCE);
-		}
-
-		// Close the file pointer and reset the instance variable
-		@fclose($this->getPointer());
-		$this->setPointer(NULL);
-		$this->setFileName('');
-	}
-
-	/**
-	 * Setter for the file pointer
-	 *
-	 * @param	$filePointer	File resource
-	 * @return	void
-	 */
-	public final function setPointer ($filePointer) {
-		// Sanity-check if pointer is a valid file resource
-		if (is_resource($filePointer) || is_null($filePointer)) {
-			// Is a valid resource
-			$this->filePointer = $filePointer;
-		} else {
-			// Throw exception
-			throw new InvalidResourceException($this, self::EXCEPTION_INVALID_RESOURCE);
-		}
-	}
-
-	/**
-	 * Getter for the file pointer
-	 *
-	 * @return	$filePointer	The file pointer which shall be a valid
-	 *							file resource
-	 */
-	public final function getPointer () {
-		return $this->filePointer;
-	}
-
-	/**
-	 * Setter for file name
-	 *
-	 * @param	$fileName	The new file name
-	 * @return	void
-	 */
-	public final function setFileName ($fileName) {
-		$fileName = (string) $fileName;
-		$this->fileName = $fileName;
-	}
-
-	/**
-	 * Getter for file name
-	 *
-	 * @return	$fileName	The current file name
-	 */
-	public final function getFileName () {
-		return $this->fileName;
-	}
-}
-
-// [EOF]
-?>
diff --git a/inc/classes/main/io/directory/.htaccess b/inc/classes/main/io/directory/.htaccess
new file mode 100644
index 00000000..3a428827
--- /dev/null
+++ b/inc/classes/main/io/directory/.htaccess
@@ -0,0 +1 @@
+Deny from all
diff --git a/inc/classes/main/io/directory/class_FrameworkDirectoryPointer.php b/inc/classes/main/io/directory/class_FrameworkDirectoryPointer.php
new file mode 100644
index 00000000..da220403
--- /dev/null
+++ b/inc/classes/main/io/directory/class_FrameworkDirectoryPointer.php
@@ -0,0 +1,229 @@
+<?php
+/**
+ * A class for directory reading and getting its contents, no recursion!
+ *
+ * @author		Roland Haeder <webmaster@shipsimu.org>
+ * @version		0.0.0
+ * @copyright	Copyright (c) 2007, 2008 Roland Haeder, 2009 - 2013 Core Developer Team
+ * @license		GNU GPL 3.0 or any newer version
+ * @link		http://www.shipsimu.org
+ *
+ * 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 3 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, see <http://www.gnu.org/licenses/>.
+ */
+class FrameworkDirectoryPointer extends BaseFrameworkSystem {
+	/**
+	 * The current path we are working in
+	 */
+	private $pathName = '';
+
+	/**
+	 * The directory iterator instance
+	 */
+	private $directoryInstance = NULL;
+
+	/**
+	 * Protected constructor
+	 */
+	protected function __construct () {
+		// Call parent constructor
+		parent::__construct(__CLASS__);
+	}
+
+	/**
+	 * Destructor for cleaning purposes, etc
+	 */
+	public function __destruct() {
+		// Is there a resource pointer? Then we have to close the directory here!
+		if ($this->getDirectoryInstance() instanceof DirectoryIterator) {
+			// Try to close a directory
+			$this->closeDirectory();
+		} // END - if
+
+		// Call the parent destructor
+		parent::__destruct();
+	}
+
+	/**
+	 * Create a directory pointer based on the given path. The path will also
+	 * be verified here.
+	 *
+	 * @param	$pathName		The path name we shall pass to opendir()
+	 * @param	$inConstructor	If we are in de/con-structor or from somewhere else
+	 * @return	$pointerInstance	A prepared instance of FrameworkDirectoryPointer
+	 * @throws	PathIsEmptyException	If the provided path name is empty
+	 * @throws	InvalidPathStringException	If the provided path name is not a string
+	 * @throws	PathIsNoDirectoryException	If the provided path name is not valid
+	 * @throws	PathReadProtectedException	If the provided path name is read-protected
+	 * @todo	Get rid of inConstructor, could be old-lost code.
+	 */
+	public static final function createFrameworkDirectoryPointer ($pathName, $inConstructor = FALSE) {
+		// Some pre-sanity checks...
+		if (is_null($pathName)) {
+			// No pathname given
+			if ($inConstructor) {
+				return NULL;
+			} else {
+				throw new PathIsEmptyException(NULL, self::EXCEPTION_UNEXPECTED_EMPTY_STRING);
+			}
+		} elseif (!is_string($pathName)) {
+			// Is not a string
+			if ($inConstructor) {
+				return NULL;
+			} else {
+				throw new InvalidPathStringException(NULL, self::EXCEPTION_INVALID_STRING);
+			}
+		} elseif (!is_dir($pathName)) {
+			// Not a directory
+			if ($inConstructor) {
+				return NULL;
+			} else {
+				throw new PathIsNoDirectoryException($pathName, self::EXCEPTION_INVALID_PATH_NAME);
+			}
+		} elseif (!is_readable($pathName)) {
+			// Not readable
+			if ($inConstructor) {
+				return NULL;
+			} else {
+				throw new PathReadProtectedException($pathName, self::EXCEPTION_READ_PROTECED_PATH);
+			}
+		}
+
+		// Get an iterator for the directory
+		$directoryInstance = new DirectoryIterator($pathName);
+
+		// Create new instance
+		$pointerInstance = new FrameworkDirectoryPointer();
+
+		// Set directory pointer and path name
+		$pointerInstance->setDirectoryInstance($directoryInstance);
+		$pointerInstance->setPathName($pathName);
+
+		// Return the instance
+		return $pointerInstance;
+	}
+
+	/**
+	 * Read raw lines of data from a directory pointer and return the data
+	 *
+	 * @return	$current	Current entry from encapsulated iterator
+	 */
+	public function readRawDirectory () {
+		// Can the next entry be read?
+		assert($this->getDirectoryInstance()->valid());
+
+		// Default is FALSE
+		$current = FALSE;
+
+		// Is it a dot directory?
+		if (!$this->getDirectoryInstance()->isDot()) {
+			// Read data from the directory pointer and return it
+			$current = $this->getDirectoryInstance()->current();
+		} // END - if
+
+		// Advance to next entry
+		$this->getDirectoryInstance()->next();
+
+		// Return found entry
+		return $current;
+	}
+
+	/**
+	 * Read lines from the current directory pointer except some parts
+	 *
+	 * @param	$except		Some parts of a directory we want to ignore. Valid: directory and file names, other values will be silently ignored
+	 * @return	string		Directory and/or file names read from the current directory pointer
+	 */
+	public function readDirectoryExcept (array $except = array()) {
+		// No exceptions given?
+		if (count($except) == 0) {
+			// No exception given, so read all files and directories, but not recursive
+			self::createDebugInstance(__CLASS__)->debugOutput('DIRECTORY[' . __METHOD__ . ':' . __LINE__ . ']: No exceptions given, please use readRawDirectory() instead!');
+			return $this->readRawDirectory();
+		} // END - if
+
+		// Read a raw line...
+		$rawLine = $this->readRawDirectory();
+		//* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput('DIRECTORY[' . __METHOD__ . ':' . __LINE__ . ']: rawLine[' . gettype($rawLine) . ']=' . $rawLine);
+
+		// Shall we exclude directories?
+		if ((!is_null($rawLine)) && ($rawLine !== FALSE) && (!in_array($rawLine, $except))) {
+			// Return read data
+			//* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput('DIRECTORY[' . __METHOD__ . ':' . __LINE__ . ']: rawLine[' . gettype($rawLine) . ']=' . $rawLine);
+			return $rawLine;
+		} elseif ((!is_null($rawLine)) && ($rawLine !== FALSE)) {
+			// Exclude this part
+			//* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput('DIRECTORY[' . __METHOD__ . ':' . __LINE__ . ']: rawline[' . gettype($rawLine) . ']=' . $rawLine . ' - Recursive call!');
+			return $this->readDirectoryExcept($except);
+		}
+
+		// End pointer reached
+		//* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput('DIRECTORY[' . __METHOD__ . ':' . __LINE__ . ']: Returning NULL!');
+		return NULL;
+	}
+
+	/**
+	 * Close a directory source and set it's instance to null and the path name
+	 * to empty
+	 *
+	 * @return	void
+	 */
+	public function closeDirectory () {
+		// Close the directory by unsetting it
+		$this->setDirectoryInstance(NULL);
+		$this->setPathName('');
+	}
+
+	/**
+	 * Setter for the directory pointer
+	 *
+	 * @param	$directoryInstance	An instanceof a DirectoryIterator class or NULL to unset ("close") it.
+	 * @return	void
+	 */
+	protected final function setDirectoryInstance (DirectoryIterator $directoryInstance = NULL) {
+		// Set instance (or NULL)
+		$this->directoryInstance = $directoryInstance;
+	}
+
+	/**
+	 * Getter for the directory pointer
+	 *
+	 * @return	$directoryInstance	The directory pointer which shall be a valid directory resource
+	 */
+	public final function getDirectoryInstance () {
+		return $this->directoryInstance;
+	}
+
+	/**
+	 * Setter for path name
+	 *
+	 * @param	$pathName	The new path name
+	 * @return	void
+	 */
+	public final function setPathName ($pathName) {
+		$pathName = (string) $pathName;
+		$this->pathName = $pathName;
+	}
+
+	/**
+	 * Getter for path name
+	 *
+	 * @return	$pathName	The current path name
+	 */
+	public final function getPathName () {
+		return $this->pathName;
+	}
+}
+
+// [EOF]
+?>
diff --git a/inc/classes/main/io/input/.htaccess b/inc/classes/main/io/input/.htaccess
new file mode 100644
index 00000000..3a428827
--- /dev/null
+++ b/inc/classes/main/io/input/.htaccess
@@ -0,0 +1 @@
+Deny from all
diff --git a/inc/classes/main/io/input/class_FrameworkFileInputPointer.php b/inc/classes/main/io/input/class_FrameworkFileInputPointer.php
new file mode 100644
index 00000000..b6b9cb3a
--- /dev/null
+++ b/inc/classes/main/io/input/class_FrameworkFileInputPointer.php
@@ -0,0 +1,94 @@
+<?php
+/**
+ * A class for reading files
+ *
+ * @author		Roland Haeder <webmaster@shipsimu.org>
+ * @version		0.0.0
+ * @copyright	Copyright (c) 2007, 2008 Roland Haeder, 2009 - 2013 Core Developer Team
+ * @license		GNU GPL 3.0 or any newer version
+ * @link		http://www.shipsimu.org
+ *
+ * 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 3 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, see <http://www.gnu.org/licenses/>.
+ */
+class FrameworkFileInputPointer extends BaseFileIo {
+	/**
+	 * Protected constructor
+	 *
+	 * @return	void
+	 */
+	protected function __construct () {
+		// Call parent constructor
+		parent::__construct(__CLASS__);
+	}
+
+	/**
+	 * Create a file pointer based on the given file. The file will also
+	 * be verified here.
+	 *
+	 * @param		$fileName	The file name we shall pass to fopen()
+	 * @throws	FileIsEmptyException	If the provided file name is empty.
+	 * @throws	FileIoException		If fopen() returns not a file resource
+	 * @return	void
+	 */
+	public static final function createFrameworkFileInputPointer ($fileName) {
+		// Some pre-sanity checks...
+		if ((is_null($fileName)) || (empty($fileName))) {
+			// No filename given
+			throw new FileIsEmptyException(NULL, self::EXCEPTION_UNEXPECTED_EMPTY_STRING);
+		} elseif (!file_exists($fileName)) {
+			// File does not exist!
+			throw new FileIoException($fileName, self::EXCEPTION_FILE_NOT_FOUND);
+		} elseif (!is_readable($fileName)) {
+			// File does not exist!
+			throw new FileReadProtectedException($fileName, self::EXCEPTION_FILE_CANNOT_BE_READ);
+		}
+
+		// Try to open a handler
+		$fileInstance = fopen($fileName, 'rb');
+		if ((is_null($fileInstance)) || ($fileInstance === FALSE)) {
+			// Something bad happend
+			throw new FileIoException($fileName, self::EXCEPTION_FILE_POINTER_INVALID);
+		} // END - if
+
+		// Create new instance
+		$pointerInstance = new FrameworkFileInputPointer();
+
+		// Set file pointer and file name
+		$pointerInstance->setInstance($fileInstance);
+		$pointerInstance->setFileName($fileName);
+
+		// Return the instance
+		return $pointerInstance;
+	}
+
+	/**
+	 * Read data a file pointer
+	 *
+	 * @return	mixed	The result of fread()
+	 * @throws	NullPointerException	If the file pointer instance
+	 *									is not set by setPointer()
+	 */
+	public function readFromFile () {
+		if (!$this->getInstance() instanceof SplFileObject) {
+			// Pointer not initialized
+			throw new NullPointerException($this, self::EXCEPTION_IS_NULL_POINTER);
+		}
+
+		// Read data from the file pointer and return it
+		return fread($this->getInstance(), 1024);
+	}
+}
+
+// [EOF]
+?>
diff --git a/inc/classes/main/io/io_handler/.htaccess b/inc/classes/main/io/io_handler/.htaccess
new file mode 100644
index 00000000..3a428827
--- /dev/null
+++ b/inc/classes/main/io/io_handler/.htaccess
@@ -0,0 +1 @@
+Deny from all
diff --git a/inc/classes/main/io/io_handler/class_FileIoStream.php b/inc/classes/main/io/io_handler/class_FileIoStream.php
new file mode 100644
index 00000000..35d00edd
--- /dev/null
+++ b/inc/classes/main/io/io_handler/class_FileIoStream.php
@@ -0,0 +1,264 @@
+<?php
+/**
+ * An universal class for file input/output streams.
+ *
+ * @author		Roland Haeder <webmaster@shipsimu.org>
+ * @version		0.0.0
+ * @copyright	Copyright (c) 2007, 2008 Roland Haeder, 2009 - 2013 Core Developer Team
+ * @license		GNU GPL 3.0 or any newer version
+ * @link		http://www.shipsimu.org
+ *
+ * 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 3 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, see <http://www.gnu.org/licenses/>.
+ */
+class FileIoStream extends BaseFrameworkSystem implements FileInputStreamer, FileOutputStreamer {
+	/**
+	 * File header indicator
+	 */
+	const FILE_IO_FILE_HEADER_ID = '@head';
+
+	/**
+	 * Data block indicator
+	 */
+	const FILE_IO_DATA_BLOCK_ID = '@data';
+
+	/**
+	 * Separator #1
+	 */
+	const FILE_IO_CHUNKER = ':';
+
+	/**
+	 * Separator #2
+	 */
+	const FILE_IO_SEPARATOR = '^';
+
+	/**
+	 * Protected constructor
+	 */
+	protected function __construct () {
+		// Call parent constructor
+		parent::__construct(__CLASS__);
+	}
+
+	/**
+	 * Create a file IO stream. This is a class for performing all actions
+	 * on files like creating, deleting and loading them.
+	 *
+	 * @return	$ioInstance	An instance of FileIoStream
+	 */
+	public static final function createFileIoStream () {
+		// Create new instance
+		$ioInstance = new FileIoStream();
+
+		// Return the instance
+		return $ioInstance;
+	}
+
+	/**
+	 * Saves data to a given local file and create missing directory structures
+	 *
+	 * @param	$fileName	The file name for the to be saved file
+	 * @param	$dataArray	The data we shall store to the file
+	 * @return	void
+	 * @see		FileOutputStreamer
+	 * @todo	This method needs heavy rewrite
+	 */
+	public final function saveFile ($fileName, array $dataArray) {
+		// Try it five times
+		$dirName = ''; $fileInstance = NULL;
+		for ($idx = 0; $idx < 5; $idx++) {
+			// Get a file output pointer
+			try {
+				$fileInstance = FrameworkFileOutputPointer::createFrameworkFileOutputPointer($fileName, 'w');
+			} catch (FileIoException $e) {
+				// Create missing directory
+				$dirName = dirname($fileName);
+				for ($idx2 = 0; $idx2 < (2 - $idx); $idx2++) {
+					$dirName = dirname($dirName);
+				} // END - for
+
+				// Try to create it
+				@mkdir($dirName);
+			}
+		} // END - for
+
+		// Write a header information for validation purposes
+		$fileInstance->writeToFile(sprintf("%s%s%s%s%s%s%s%s%s\n",
+			self::FILE_IO_FILE_HEADER_ID,
+			self::FILE_IO_SEPARATOR,
+			$dataArray[0],
+			self::FILE_IO_CHUNKER,
+			time(),
+			self::FILE_IO_CHUNKER,
+			strlen($dataArray[1]),
+			self::FILE_IO_CHUNKER,
+			md5($dataArray[1])
+		));
+
+		// Encode the (maybe) binary stream with Base64
+		$b64Stream = base64_encode($dataArray[1]);
+
+		// write the data line by line
+		$line = str_repeat(' ', 50); $idx = 0;
+		while (strlen($line) == 50) {
+			// Get 50 chars or less
+			$line = substr($b64Stream, $idx, 50);
+
+			// Save it to the stream
+			$fileInstance->writeToFile(sprintf("%s%s%s%s%s\n",
+				self::FILE_IO_DATA_BLOCK_ID,
+				self::FILE_IO_SEPARATOR,
+				$line,
+				self::FILE_IO_CHUNKER,
+				md5($line)
+			));
+
+			// Advance to the next 50-chars block
+			$idx += 50;
+		} // END - while
+
+		// Close the file
+		$fileInstance->closeFile();
+	}
+
+	/**
+	 * Reads from a local file
+	 *
+	 * @param		$fqfn	The full-qualified file-name which we shall load
+	 * @return	$array	An array with the element 'header' and 'data'
+	 * @see		FileInputStreamer
+	 */
+	public final function loadFileContents ($fqfn) {
+		// Initialize some variables and arrays
+		$inputBuffer = '';
+		$lastBuffer = '';
+		$header = array();
+		$data = array();
+		$readData = ''; // This will contain our read data
+
+		// Get a file input handler
+		$fileInstance = FrameworkFileInputPointer::createFrameworkFileInputPointer($fqfn);
+
+		// Read all it's contents (we very and transparently decompress it below)
+		while ($readRawLine = $fileInstance->readFromFile()) {
+			// Add the read line to the buffer
+			$inputBuffer .= $readRawLine;
+
+			// Break infinite loop maybe caused by the input handler
+			if ($lastBuffer == $inputBuffer) break;
+
+			// Remember last read line for avoiding possible infinite loops
+			$lastBuffer = $inputBuffer;
+		} // END - while
+
+		// Close directory handle
+		$fileInstance->closeFile();
+
+		// Convert it into an array
+		$inputBuffer = explode(chr(10), $inputBuffer);
+
+		// Now process the read lines and verify it's content
+		foreach ($inputBuffer as $rawLine) {
+			// Trim it a little but not the leading spaces/tab-stops
+			$rawLine = rtrim($rawLine);
+
+			// Analyze this line
+			if (substr($rawLine, 0, 5) == self::FILE_IO_FILE_HEADER_ID) {
+				// Header found, so let's extract it
+				$header = explode(self::FILE_IO_SEPARATOR, $rawLine);
+				$header = trim($header[1]);
+
+				// Now we must convert it again into an array
+				$header = explode(self::FILE_IO_CHUNKER, $header);
+
+				// Is the header (maybe) valid?
+				if (count($header) != 4) {
+					// Throw an exception
+					throw new InvalidArrayCountException(array($this, 'header', count($header), 4), self::EXCEPTION_ARRAY_HAS_INVALID_COUNT);
+				} // END - if
+			} elseif (substr($rawLine, 0, 5) == self::FILE_IO_DATA_BLOCK_ID) {
+				// Is a data line!
+				$data = explode(self::FILE_IO_SEPARATOR, $rawLine);
+				$data = $data[1];
+
+				// First element is the data, second the MD5 checksum
+				$data = explode(self::FILE_IO_CHUNKER, $data);
+
+				// Validate the read line
+				if (count($data) == 2) {
+					if (md5($data[0]) != $data[1]) {
+						// MD5 hash did not match!
+						throw new InvalidMD5ChecksumException(array($this, md5($data[0]), $data[1]), self::EXCEPTION_MD5_CHECKSUMS_MISMATCH);
+					} // END - if
+				} else {
+					// Invalid count!
+					throw new InvalidArrayCountException(array($this, 'data', count($data), 2), self::EXCEPTION_ARRAY_HAS_INVALID_COUNT);
+				}
+
+				// Add this to the readData string
+				$readData .= $data[0];
+			} else {
+				// Other raw lines than header/data tagged lines and re-add the new-line char
+				$readData .= $rawLine . PHP_EOL;
+			}
+		} // END - foreach
+
+		// Was raw lines read and no header/data?
+		if ((!empty($readData)) && (count($header) == 0) && (count($data) == 0)) {
+			// Return raw lines back
+			return $readData;
+		} // END - if
+
+		// Was a header found?
+		if (count($header) != 4) {
+			// Throw an exception
+			throw new InvalidArrayCountException(array($this, 'header', count($header), 4), self::EXCEPTION_ARRAY_HAS_INVALID_COUNT);
+		} // END - if
+
+		// Decode all from Base64
+		$readData = @base64_decode($readData);
+
+		// Does the size match?
+		if (strlen($readData) != $header[2]) {
+			// Size did not match
+			throw new InvalidDataLengthException(array($this, strlen($readData), $header[2]), self::EXCEPTION_UNEXPECTED_STRING_SIZE);
+		} // END - if
+
+		// Validate the decoded data with the final MD5 hash
+		if (md5($readData) != $header[3]) {
+			// MD5 hash did not match!
+			throw new InvalidMD5ChecksumException(array($this, md5($readData), $header[3]), self::EXCEPTION_MD5_CHECKSUMS_MISMATCH);
+		} // END - if
+
+		// Return all in an array
+		return array(
+			'header' => $header,
+			'data'   => $readData
+		);
+	}
+
+	/**
+	 * Streams the data and maybe does something to it
+	 *
+	 * @param	$data	The data (string mostly) to "stream"
+	 * @return	$data	The data (string mostly) to "stream"
+	 * @throws	UnsupportedOperationException	If this method is called
+	 */
+	public function streamData ($data) {
+		self::createDebugInstance(__CLASS__)->debugOutput('Unhandled ' . strlen($data) . ' bytes in this stream.');
+		throw new UnsupportedOperationException(array($this, __FUNCTION__), self::EXCEPTION_UNSPPORTED_OPERATION);
+	}
+}
+
+// [EOF]
+?>
diff --git a/inc/classes/main/io/output/.htaccess b/inc/classes/main/io/output/.htaccess
new file mode 100644
index 00000000..3a428827
--- /dev/null
+++ b/inc/classes/main/io/output/.htaccess
@@ -0,0 +1 @@
+Deny from all
diff --git a/inc/classes/main/io/output/class_FrameworkFileOutputPointer.php b/inc/classes/main/io/output/class_FrameworkFileOutputPointer.php
new file mode 100644
index 00000000..1af2697b
--- /dev/null
+++ b/inc/classes/main/io/output/class_FrameworkFileOutputPointer.php
@@ -0,0 +1,95 @@
+<?php
+/**
+ * A class for writing files
+ *
+ * @author		Roland Haeder <webmaster@shipsimu.org>
+ * @version		0.0.0
+ * @copyright	Copyright (c) 2007, 2008 Roland Haeder, 2009 - 2013 Core Developer Team
+ * @license		GNU GPL 3.0 or any newer version
+ * @link		http://www.shipsimu.org
+ *
+ * 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 3 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, see <http://www.gnu.org/licenses/>.
+ */
+class FrameworkFileOutputPointer extends BaseFileIo {
+	/**
+	 * Protected constructor
+	 *
+	 * @return	void
+	 */
+	protected function __construct () {
+		// Call parent constructor
+		parent::__construct(__CLASS__);
+	}
+
+	/**
+	 * Create a file pointer based on the given file. The file will also
+	 * be verified here.
+	 *
+	 * @param	$fileName	The file name we shall pass to fopen()
+	 * @param	$mode		The output mode ('w', 'a' are valid)
+	 * @throws	FileIsEmptyException	If the provided file name is empty.
+	 * @throws	FileIoException		If fopen() returns not a file resource
+	 * @return	void
+	 */
+	public static final function createFrameworkFileOutputPointer ($fileName, $mode) {
+		// Some pre-sanity checks...
+		if (is_null($fileName)) {
+			// No filename given
+			throw new FileIsEmptyException(NULL, self::EXCEPTION_UNEXPECTED_EMPTY_STRING);
+		} // END - if
+
+		// Try to open a handler
+		$filePointer = @fopen($fileName, $mode);
+		if ((is_null($filePointer)) || ($filePointer === FALSE)) {
+			// Something bad happend
+			throw new FileIoException ($fileName, self::EXCEPTION_FILE_POINTER_INVALID);
+		} // END - if
+
+		// Create new instance
+		$pointerInstance = new FrameworkFileOutputPointer();
+
+		// Set file pointer and file name
+		$pointerInstance->setPointer($filePointer);
+		$pointerInstance->setFileName($fileName);
+
+		// Return the instance
+		return $pointerInstance;
+	}
+
+	/**
+	 * Write data to a file pointer
+	 *
+	 * @param	$dataStream		The data stream we shall write to the file
+	 * @return	mixed			Number of writes bytes or FALSE on error
+	 * @throws	NullPointerException	If the file pointer instance
+	 *									is not set by setPointer()
+	 * @throws	InvalidResourceException	If there is being set
+	 *											an invalid file resource
+	 */
+	public function writeToFile ($dataStream) {
+		if (is_null($this->getPointer())) {
+			// Pointer not initialized
+			throw new NullPointerException($this, self::EXCEPTION_IS_NULL_POINTER);
+		} elseif (!is_resource($this->getPointer())) {
+			// Pointer is not a valid resource!
+			throw new InvalidResourceException($this, self::EXCEPTION_INVALID_RESOURCE);
+		}
+
+		// Write data to the file pointer and return written bytes
+		return fwrite($this->getPointer(), $dataStream);
+	}
+}
+
+// [EOF]
+?>