<?php

require_once('globals.php');
require_once('sql.php');
require_once('sxe.php');
require_once('res.php');

res_Resource::setDefaultLanguage(PB_LANGUAGE);

class util_RightHandler extends sxe_OperationHandler {
    public function handle($server, $operation, $exchange) {
        $requiredRight = $operation->getAttribute('requiredRight');
        if ($requiredRight == NULL) {
            return;
        }
        $user = util_RightHandler::getContextUser($server);
        if (($requiredRight != 'connect') && (! $user->hasRight($requiredRight))) {
            throw new Exception('Required right not found');
        }
        // check repository rigths
        $requiredRepositoryRight = $operation->getAttribute('requiredRepositoryRight');
        if ($requiredRepositoryRight != NULL) {
            $repositoryId = NULL;
            $repositoryIdAttName = $operation->getAttribute('repositoryIdAttName');
            $mediaIdAttName = $operation->getAttribute('mediaIdAttName', 'mediaId');
            $request = $exchange->getRequest();
            if ($repositoryIdAttName != NULL) {
                $repositoryId = $request->getAttribute($repositoryIdAttName);
            } else {
                $mediaId = $request->getAttribute($mediaIdAttName);
                $media = pb_Media::fetchFromId($mediaId);
                if ($media == NULL) {
                    throw new Exception("Media id " . $mediaId . " not found");
                }
                $repositoryId = $media->getRepositoryId();
            }
            $repositoryUserRigths = pb_Repository::getUserRights($repositoryId, $user->getId());
            if ($repositoryUserRigths == NULL) {
                throw new Exception('User id ' . $user->getId() . ' has no access for repository id ' . $repositoryId);
            }
            if (($requiredRepositoryRight != 'connect') && (! util_RightHandler::hasRight($requiredRepositoryRight, $repositoryUserRigths))) {
                throw new Exception('Required repository right not found');
            }
        }
    }
    public static function getContextUser($server) {
        $user = $server->getContextKey('user');
        if ($user == NULL) {
            $header = $server->getRequestHeader();
            $authentication = sxe_Server::getFirstChildNode($header, 'authentication');
            $login = sxe_Server::getFirstChildValue($authentication, 'login');
            $password = sxe_Server::getFirstChildValue($authentication, 'password');
            if (($authentication == NULL) || ($login == NULL) || ($password == NULL) || (! Helper::loginIsValid($login))) {
                throw new Exception('Authentication required');
            }
            $user = pb_User::fetchFromLogin($login);
            if (($user == NULL) || ($user->getPassword() != $password)) {
                throw new Exception('No match found for login/password');
            }
            $server->setContextKey('user', $user);
        }
        return $user;
    }
    public static function hasRight($right, $csRights) {
        return strpos($csRights, $right) !== false;
    }
}

class util_UploadedFile {
    protected $file = NULL;
    protected $name = NULL;
    protected $uploaded = true;

    public function __construct($name, $tmpName, $uploaded = true) {
        //echo 'util_UploadedFile(' . $name . ', ' . $tmpName . ')';
        $this->name = $name;
        $this->tmpName = $tmpName;
        $this->uploaded = $uploaded;
    }
	public function getName() {
        return $this->name;
	}
	public function getTmpName() {
        return $this->tmpName;
    }
    public function _moveTo($path) {
        if ($this->uploaded) {
            return move_uploaded_file($this->getTmpName(), $path);
        } else {
            return rename($this->getTmpName(), $path);
        }
    }
    public function moveTo($path) {
        //echo 'util_UploadedFile.moveTo(' . $path . ')';
        if (is_file($path)) {
            throw new Exception('The destination already exists');
        }
        if (! $this->_moveTo($path)) {
            //echo 'The move has failed (' . $this->getTmpName() . ')';
            throw new Exception('The move has failed');
        }
    }
    public static function createFromDistant($fileKey, $name = NULL) {
        if (! array_key_exists($fileKey, $_FILES)) {
            throw new Exception("The key $fileKey does not exists");
        }
        $file = $_FILES[$fileKey];
        // name, type, tmp_name, error, size
        if ($file['error'] != UPLOAD_ERR_OK) {
            $UPLOAD_ERR_MSGS = array(
                UPLOAD_ERR_INI_SIZE => "The uploaded file exceeds the upload_max_filesize directive in php.ini.",
                UPLOAD_ERR_FORM_SIZE => "The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form.",
                UPLOAD_ERR_PARTIAL => "The uploaded file was only partially uploaded.",
                UPLOAD_ERR_NO_FILE => "No file was uploaded.",
                UPLOAD_ERR_NO_TMP_DIR => "Missing a temporary folder.",
                UPLOAD_ERR_CANT_WRITE => "Failed to write file to disk.",
                UPLOAD_ERR_EXTENSION => "A PHP extension stopped the file upload."
            );
            throw new Exception('The upload for key "' . $fileKey . '" has failed due to "' .
                $UPLOAD_ERR_MSGS[$file['error']] . '" (' . $file['error'] . ')');
        }
        if ($name == NULL) {
            $name = strtr($file['name'], '?*', '__');
        }
        return new util_UploadedFile($name, $file['tmp_name']);
    }
    public static function createFromLocal($filename, $name = NULL) {
        if ($name == NULL) {
            $name = $filename;
        }
        $path = PB_INCOMING_PATH . '/' . $filename;
        if (! is_file($path)) {
            throw new Exception('File not found (' . $filename . ')');
        }
        return new util_UploadedFile($name, $path, false);
	}
}

class Helper {
    private static $instance;
    private $sql = NULL;
    private $sxe = NULL;
    private $res = NULL;

    private function __construct() {
    }
    public function getRes() {
        if ($this->res == NULL) {
            $this->res = new res_Resource('server', PB_LANGUAGE);
        }
        return $this->res;
    }
	public function getSQL() {
        if ($this->sql == NULL) {
            $this->sql = new sql_Connection(DB_HOST, DB_USER, DB_PASSWORD, DB_NAME);
        }
        return $this->sql;
	}
	public function openSQL() {
        if ($this->sql == NULL) {
            $this->sql = new sql_Connection(DB_HOST, DB_USER, DB_PASSWORD, DB_NAME);
            $this->sql->begin();
        }
        return $this->sql;
	}
	public function closeSQL($commit = true) {
        if ($this->sql != NULL) {
            if ($commit) {
                $this->sql->commit();
            } else {
                $this->sql->rollback();
            }
        }
	}
	public function getServer() {
        if ($this->sxe == NULL) {
            $this->sxe = new sxe_Server();
            $this->sxe->registerHandler(new util_RightHandler());
        }
        return $this->sxe;
	}
	public function getAdminEMail() {
        return ADMIN_EMAIL;
	}
	public function getSiteAddress() {
        return SITE_FULL_ADDRESS;
	}
	public function getSiteName() {
        return SITE_NAME;
	}
	public function createMail($to = '', $subject = '', $message = '', $headers = NULL) {
        $mail = new net_Mail($to, $subject, $message, $headers);
        if (strpos(SITE_FULL_ADDRESS, 'localhost') !== false) {
        	$mail->setDebug(true);
        }
        return $mail;
	}
    public static function getInstance() {
        if (! isset(self::$instance)) {
            $c = __CLASS__;
            self::$instance = new $c;
        }
        return self::$instance;
    }
    public static function toASCII($text, $subst = '') {
        // &#1200;
        return preg_replace('/&#[0-9a-fA-F]+;/', $subst, preg_replace('/[^(\x20-\x7F)]/', $subst, $text));
    }
    public static function disableMagicQuotesGPC($value) {
        if (TRUE == function_exists('get_magic_quotes_gpc') && 1 == get_magic_quotes_gpc()) {
            $mqs = strtolower(ini_get('magic_quotes_sybase'));
            if (TRUE == empty($mqs) || 'off' == $mqs) {
                return stripslashes($value);
            } else {
                return str_replace("''", "'", $value);
            }
        }
        return $value;
    }
    
    public static function startsWith($haystack, $needle, $case = TRUE) {
        if ($case) {
            return strpos($haystack, $needle, 0) === 0;
        }
        return stripos($haystack, $needle, 0) === 0;
    }
    public static function endsWith($haystack, $needle, $case = TRUE) {
        $expectedPosition = strlen($haystack) - strlen($needle);
        if ($case) {
            return strrpos($haystack, $needle, 0) === $expectedPosition;
        }
        return strripos($haystack, $needle, 0) === $expectedPosition;
    }
    public static function toFilename($filename, $subst = '_') {
        // \/:*?"<>|
        $trans = array(
          "\xE9" => 'e',
          "\xE8" => 'e',
          "\xEA" => 'e',
          "\xEB" => 'e',
          "\xE0" => 'a',
          "\xE2" => 'a',
          "\xE4" => 'a',
          "\xE3" => 'a',
          "\xF2" => 'o',
          "\xF4" => 'o',
          "\xF6" => 'o',
          "\xF5" => 'o',
          "\xEF" => 'i',
          "\xEE" => 'i',
          "\xEC" => 'i',
          "\xF9" => 'u',
          "\xFB" => 'u',
          "\xFC" => 'u',
          "\xF1" => 'n');
        return preg_replace('/[\/\\:*?\"<>|]/', $subst, Helper::toASCII(strtr($filename, $trans), $subst));
    }
    public static function loginIsValid($login) {
        //return preg_match('/^[-a-zA-Z0-9_~\\.@ \']{3,60}$/i', $login);
        $len = strlen($login);
       return ($len >= 3) && ($len <= 60) && (strpos($login, ';') === false);
    }
    public static function mkdir($path) {
        //echo "mkdir($path)\n";
        if (is_dir($path)) {
            return true;
        }
        return mkdir($path, 0777, true);
    }
    public static function rmdir($path) {
        //echo "rmdir($path);<br>\n";
        $dir = opendir($path);
        while($entryName = readdir($dir)) {
            if (($entryName == '.') || ($entryName == '..')) {
                continue;
            }
            $entryPath = $path . '/' . $entryName;
            if (is_dir($entryPath)) {
                if (! Helper::rmdir($entryPath)) {
                    return false;
                }
            } else {
                //echo "unlink($entryPath);<br>\n";
                if (! unlink($entryPath)) {
                    return false;
                }
            }
        }
        closedir($dir);
        //return true;
        return rmdir($path);
    }
    public static function cleandir($path) {
        //echo "cleandir($path);<br>\n";
        if (! is_dir($path)) {
            throw new Exception('Invalid directory (' . $path . ')');
        }
        $dir = opendir($path);
        if (! $dir) {
            throw new Exception('Cannot open directory (' . $path . ')');
        }
        while($entryName = readdir($dir)) {
	        //echo " cleaning $entryName<br>\n";
            if (($entryName == '.') || ($entryName == '..')) {
                continue;
            }
            $entryPath = $path . '/' . $entryName;
            if (is_dir($entryPath)) {
                if (! Helper::rmdir($entryPath)) {
                    return false;
                }
            }
        }
        closedir($dir);
    }
}

?>