Skip to content
Snippets Groups Projects
class.osticket.php 12.2 KiB
Newer Older
  • Learn to ignore specific revisions
  • /*******************************************************************
    
        Core osTicket object: loads congfig and provides loggging facility.
    
    
        Use osTicket::start(configId)
    
        Peter Rotich <peter@osticket.com>
    
        Copyright (c)  2006-2013 osTicket
    
        http://www.osticket.com
    
        Released under the GNU General Public License WITHOUT ANY WARRANTY.
        See LICENSE.TXT for details.
    
        vim: expandtab sw=4 ts=4 sts=4:
    **********************************************************************/
    
    
    require_once(INCLUDE_DIR.'class.csrf.php'); //CSRF token class.
    
    require_once(INCLUDE_DIR.'class.migrater.php');
    
    
        var $loglevel=array(1=>'Error','Warning','Debug');
    
        var $title; //Custom title. html > head > title.
    
        function osTicket() {
    
            require_once(INCLUDE_DIR.'class.config.php'); //Config helper
    
    
            $this->session = osTicketSession::start(SESSION_TTL); // start DB based session
    
            $this->config = new OsticketConfig();
    
            $this->csrf = new CSRF('__CSRFToken__');
    
            return ($this->getConfig() && $this->getConfig()->isHelpDeskOnline() && !$this->isUpgradePending());
    
    		foreach (DatabaseMigrater::getUpgradeStreams(UPGRADE_DIR.'streams/') as $stream=>$hash)
    			if (strcasecmp($hash,
    					$this->getConfig()->getSchemaSignature($stream)))
    				return true;
    		return false;
    
        function getConfig() {
            return $this->config;
        }
    
    
        function getDBSignature($namespace='core') {
            return $this->getConfig()->getSchemaSignature($namespace);
    
    Peter Rotich's avatar
    Peter Rotich committed
        }
    
        function getVersion() {
            return THIS_VERSION;
        }
    
    
        function getCSRF(){
            return $this->csrf;
        }
    
        function getCSRFToken() {
            return $this->getCSRF()->getToken();
        }
    
        function getCSRFFormInput() {
            return $this->getCSRF()->getFormInput();
        }
    
        function validateCSRFToken($token) {
            return ($token && $this->getCSRF()->validateToken($token));
        }
    
        function checkCSRFToken($name='') {
    
            $name = $name?$name:$this->getCSRF()->getTokenName();
            if(isset($_POST[$name]) && $this->validateCSRFToken($_POST[$name]))
                return true;
    
            if(isset($_SERVER['HTTP_X_CSRFTOKEN']) && $this->validateCSRFToken($_SERVER['HTTP_X_CSRFTOKEN']))
                return true;
    
            $msg=sprintf('Invalid CSRF token [%s] on %s',
                    ($_POST[$name].''.$_SERVER['HTTP_X_CSRFTOKEN']), THISPAGE);
    
            $this->logWarning('Invalid CSRF Token '.$name, $msg, false);
    
    
        function getLinkToken() {
            return md5($this->getCSRFToken().SECRET_SALT.session_id());
        }
    
        function validateLinkToken($token) {
                return ($token && !strcasecmp($token, $this->getLinkToken()));
        }
    
    
        function isFileTypeAllowed($file, $mimeType='') {
    
            if(!$file || !($allowedFileTypes=$this->getConfig()->getAllowedFileTypes()))
                return false;
    
            //Return true if all file types are allowed (.*)
            if(trim($allowedFileTypes)=='.*') return true;
    
            $allowed = array_map('trim', explode(',', strtolower($allowedFileTypes)));
            $filename = is_array($file)?$file['name']:$file;
    
            $ext = strtolower(preg_replace("/.*\.(.{3,4})$/", "$1", $filename));
    
            //TODO: Check MIME type - file ext. shouldn't be solely trusted.
    
            return ($ext && is_array($allowed) && in_array(".$ext", $allowed));
        }
    
    
        /* Replace Template Variables */
        function replaceTemplateVariables($input, $vars=array()) {
    
            $replacer = new VariableReplacer();
    
            $replacer->assign(array_merge($vars,
    
                        array('url' => $this->getConfig()->getBaseUrl())
                        ));
    
            return $replacer->replaceVars($input);
        }
    
    
        function addExtraHeader($header) {
            $this->headers[md5($header)] = $header;
        }
    
        function getExtraHeaders() {
            return $this->headers;
        }
    
    
        function setPageTitle($title) {
            $this->title = $title;
        }
    
        function getPageTitle() {
            return $this->title;
        }
    
    
        function getErrors() {
            return $this->errors;
        }
    
        function setErrors($errors) {
            $this->errors = $errors;
        }
    
        function getError() {
    
            return $this->system['err'];
    
            $this->system['error'] = $error;
    
        }
    
        function clearError() {
            $this->setError('');
        }
    
        function getWarning() {
    
            return $this->system['warning'];
    
        function setWarning($warning) {
            $this->system['warning'] = $warning;
    
        function getNotice() {
            return $this->system['notice'];
    
        function setNotice($notice) {
            $this->system['notice'] = $notice;
    
        function clearNotice() {
            $this->setNotice('');
    
            if(!($to=$this->getConfig()->getAdminEmail()))
    
    
            //append URL to the message
            $message.="\n\n".THISPAGE;
    
    
            if(!($email=$this->getConfig()->getAlertEmail()))
    
                $email=$this->getConfig()->getDefaultEmail(); //will take the default email.
    
                $email->sendAlert($to, $subject, $message, null, array('text'=>true));
    
                Mailer::sendmail($to, $subject, $message, sprintf('"osTicket Alerts"<%s>',$to));
    
            }
    
            //log the alert? Watch out for loops here.
            if($log)
                $this->log(LOG_CRIT, $subject, $message, false); //Log the entry...and make sure no alerts are resent.
    
        }
    
    
        function logDebug($title, $message, $force=false) {
            return $this->log(LOG_DEBUG, $title, $message, false, $force);
    
        }
    
        function logInfo($title, $message, $alert=false) {
            return $this->log(LOG_INFO, $title, $message, $alert);
        }
    
        function logWarning($title, $message, $alert=true) {
            return $this->log(LOG_WARN, $title, $message, $alert);
        }
    
        function logError($title, $error, $alert=true) {
            return $this->log(LOG_ERR, $title, $error, $alert);
        }
    
    
        function logDBError($title, $error, $alert=true) {
    
            if($alert && !$this->getConfig()->alertONSQLError())
                $alert =false;
    
    
            $e = new Exception();
            $bt = str_replace(ROOT_DIR, '(root)/', $e->getTraceAsString());
            $error .= "\n\n---- Backtrace ----\n".$bt;
    
    
        function log($priority, $title, $message, $alert=false, $force=false) {
    
    
            //We are providing only 3 levels of logs. Windows style.
            switch($priority) {
                case LOG_EMERG:
    
                case LOG_ERR:
                    $level=1; //Error
                    break;
                case LOG_WARN:
                case LOG_WARNING:
                    $level=2; //Warning
                    break;
                case LOG_NOTICE:
                case LOG_INFO:
                case LOG_DEBUG:
                default:
                    $level=3; //Debug
            }
    
    
            if($this->getConfig()->getLogLevel()<$level && !$force)
    
            //Alert admin if enabled...
            if($alert && $this->getConfig()->getLogLevel() >= $level)
                $this->alertAdmin($title, $message);
    
    
            //Save log based on system log level settings.
            $loglevel=array(1=>'Error','Warning','Debug');
    
    Peter Rotich's avatar
    Peter Rotich committed
            $sql='INSERT INTO '.SYSLOG_TABLE.' SET created=NOW(), updated=NOW() '
                .',title='.db_input(Format::sanitize($title, true))
                .',log_type='.db_input($loglevel[$level])
                .',log='.db_input(Format::sanitize($message, false))
                .',ip_address='.db_input($_SERVER['REMOTE_ADDR']);
    
            if(!($gp=$this->getConfig()->getLogGracePeriod()) || !is_numeric($gp))
    
                return false;
    
            //System logs
            $sql='DELETE  FROM '.SYSLOG_TABLE.' WHERE DATE_ADD(created, INTERVAL '.$gp.' MONTH)<=NOW()';
            db_query($sql);
    
    Peter Rotich's avatar
    Peter Rotich committed
        /*
         * Util functions
         *
         */
    
        function get_var($index, $vars, $default='', $type=null) {
    
            if(is_array($vars)
                    && array_key_exists($index, $vars)
                    && (!$type || gettype($vars[$index])==$type))
                return $vars[$index];
    
            return $default;
        }
    
        function get_db_input($index, $vars, $quote=true) {
            return db_input($this->get_var($index, $vars), $quote);
        }
    
        function get_path_info() {
            if(isset($_SERVER['PATH_INFO']))
                return $_SERVER['PATH_INFO'];
    
            if(isset($_SERVER['ORIG_PATH_INFO']))
                return $_SERVER['ORIG_PATH_INFO'];
    
            //TODO: conruct possible path info.
    
            return null;
        }
    
    
        /* static */
        function get_root_path($dir) {
    
    
            /* If run from the commandline, DOCUMENT_ROOT will not be set. It is
             * also likely that the ROOT_PATH will not be necessary, so don't
             * bother attempting to figure it out.
             *
             * Secondly, if the directory of main.inc.php is the same as the
             * document root, the the ROOT path truly is '/'
             */
    
            if(!$_SERVER['DOCUMENT_ROOT']
                    || !strcasecmp($_SERVER['DOCUMENT_ROOT'], $dir))
                return '/';
    
    
            /* The main idea is to try and use full-path filename of PHP_SELF and
             * SCRIPT_NAME. The SCRIPT_NAME should be the path of that script
             * inside the DOCUMENT_ROOT. This is most likely useful if osTicket
             * is run using something like Apache UserDir setting where the
             * DOCUMENT_ROOT of Apache and the installation path of osTicket
             * have nothing in comon.
    
             *
             * +---------------------------+-------------------+----------------+
    
             * | PHP Script                | SCRIPT_NAME       | ROOT_PATH      |
    
             * +---------------------------+-------------------+----------------+
             * | /home/u1/www/osticket/... | /~u1/osticket/... | /~u1/osticket/ |
             * +---------------------------+-------------------+----------------+
             *
             * The algorithm will remove the directory of main.inc.php from
    
             * as seen. What's left should be the script executed inside
    
             * the osTicket installation. That is removed from SCRIPT_NAME.
             * What's left is the ROOT_PATH.
             */
    
            $frame = array_pop(debug_backtrace(false));
    
            $file = str_replace('\\','/', $frame['file']);
            $path = substr($file, strlen(ROOT_DIR));
    
            if($path && ($pos=strpos($_SERVER['SCRIPT_NAME'], $path))!==false)
    
                return substr($_SERVER['SCRIPT_NAME'], 0, $pos);
    
            return null;
        }
    
    
        /**
         * Returns TRUE if the request was made via HTTPS and false otherwise
         */
        function is_https() {
            return (isset($_SERVER['HTTPS'])
                    && strtolower($_SERVER['HTTPS']) == 'on')
                || (isset($_SERVER['HTTP_X_FORWARDED_PROTO'])
                    && strtolower($_SERVER['HTTP_X_FORWARDED_PROTO']) == 'https');
        }
    
    
    Peter Rotich's avatar
    Peter Rotich committed
        /* returns true if script is being executed via commandline */
        function is_cli() {
            return (!strcasecmp(substr(php_sapi_name(), 0, 3), 'cli')
                    || (!$_SERVER['REQUEST_METHOD'] && !$_SERVER['HTTP_HOST']) //Fallback when php-cgi binary is used via cli
                    );
        }
    
        function start() {
    
            if(!($ost = new osTicket()))
    
            //Set default time zone... user/staff settting will override it (on login).
    
            $_SESSION['TZ_OFFSET'] = $ost->getConfig()->getTZoffset();
            $_SESSION['TZ_DST'] = $ost->getConfig()->observeDaylightSaving();