<?php
/*
 * This file is part of the easy-CMS project.
 * easy-CMS 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.
 * 
 * easy-CMS 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 easy-CMS; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

include_once('classes/system/Node.class.php');

/**
 * File Class
 *
 * @author  cedseven
 * @package System
 */
class File extends Node {
	/**
	 * Constructor
	 *
	 * @param string $name
	 * @param string $path
	 * @param boolean $create
	 * @param string $content
	 */
	function File($name, $path='', $create=false, $content='') {
		parent::Node($name, $path);
		$fileName = $this->getNodeFullName();
		if($create){
			$this->write($content);
		}
	}

	/**
	 * Gets node type
	 *
	 * @return string
	 */
	function getNodeType() {
		return FILE_NODE;
	}

	/**
	 * Gets file extension
	 *
	 * @return string
	 */
	function getExtension() {
		// name may have several '.' chars
		$parts = explode('.', $this->getName());
		if(!count($parts)) {
		  return '';
		}
		return strtolower($parts[count($parts)-1]);
	}

	/**
	 * Gets filename without its extension
	 *
	 * @return string
	 */
	function getPrefix() {
    $prefix = '';
		// name may have several '.' chars
		$parts = explode('.', $this->getName());
		if(!count($parts)) {
		  return '';
		}
		for($i = 0; $i < count($parts)-1; ++$i) {
      if(strlen($prefix) > 0) {
        $prefix .= '.';
      }
      $prefix .= $parts[$i];
		}
		return $prefix;
	}


	function isHiddenFile() {
		return parent::isHiddenFile($this->getName());
	}

	/**
	 * checks if a filename is valid
	 *
	 * @static
	 * @return boolean
	 */
	function isValidFileName() {
		return parent::isValidFileName($this->getName());
	}

	/**
	 * Reads content from file 
	 *
	 * @return string
	 */
	function read() {
		return file_get_contents($this->getNodeFullName());
	}

	/**
	 * Removes the file
	 *
	 * @return integer
	 */
	function remove() {
		$fileName = $this->getNodeFullName();
  	if(!unlink($fileName)) {
			return -1;
		}
		return 1;
	}

	function is_ascii($string) {
		for($i = 0; $i < strlen($string); ++$i) {
			$asciiPos = ord(substr($string, $i, 1));
			if($asciiPos >= 192) {
		  	 return false;
			}
		}
		return true;
	}


	/**
	 * Writes content into file
	 *
	 * @param  string $content
	 * @return integer <0 if error
	 */
	function write($content, $doCheck=true) {
		$fileName = $this->getNodeFullName();

		$extension = $this->getExtension();
    $forbidden_extensions = array('php', 'php3', 'php4', 'php5', 'php6', 'cgi', 'pl', 'sh', 'bash', 'csh', 'tcsh', 'ksh', 'zsh');

    if($doCheck) {
  		if($this->isHiddenFile()) {
				// hidden files forbidden
        trigger_error("File::write, error : creation denied for file '$fileName' (hidden files are not authorized).", E_USER_ERROR);
				return -1;
  		}
  		if(in_array($extension, $forbidden_extensions)) {
				// executable files forbidden
        trigger_error("File::write, error : creation denied for file '$fileName' (unauthorized file extension).", E_USER_ERROR);
				return -1;
  		}
  		if(!$this->isValidFileName()) {
				// invalid chars in file name
        trigger_error("File::write, error : '$fileName' has invalid filename.", E_USER_ERROR);
				// make it valid
				$inputName = $this->getName();

				$baseName = substr($inputName, 0, strlen($inputName)-strlen($extension)-1);
				if(strlen($extension) > 4) {
					$extension = substr($extension, 0, 4);
				}

				if(strlen($inputName) < 3) {
					$baseName .= "___";
				}
				if(strlen($inputName) > 124) {
					$baseName = substr($baseName, 0, 124);
				}

				$outputName = Node::toValidName("$baseName.$extension");

        trigger_error("File::write, warning : invalid filename, renaming to  '$outputName'.", E_USER_ERROR);
        
				$this->setName($outputName);
				$fileName = $this->getNodeFullName();
  		}
  		if(is_file($fileName)) {
				// prevent from overwriting existing files
				$baseName = substr($fileName, 0, strlen($fileName)-strlen($extension)-1);
				$i = 1;
				while(is_file($baseName."($i).$extension")) {
					++$i;
				}
        trigger_error("File::write, error : file '$fileName' already exists, renaming to $baseName($i).$extension.", E_USER_ERROR);
				$fileName = $baseName."($i).$extension";
  		}
    }

		if(($file = @fopen($fileName, 'w')) === false) {
      trigger_error("File::write, error : unable to open file '$fileName'.", E_USER_ERROR);
      return -1;
    }
    if($file) {
    	if((@fwrite($file, $content)) === false) {
        trigger_error("File::write, error : unable to write to file '$fileName'.", E_USER_ERROR);
				return -1;
			}
			fclose($file);
		}
		if(!chmod($fileName, 0644)){
      trigger_error("File::write, error : unable to perform chmod on the file '$fileName'.", E_USER_ERROR);
			return -1;
		}
  	return 1;
	}
}
?>