diff --git a/bootstrap.php b/bootstrap.php index 6555f9049273110c43f1d34b76b124566f2660cf..fe2d8a3f182eb752cfe300ad0d01e13a9a192323 100644 --- a/bootstrap.php +++ b/bootstrap.php @@ -1,13 +1,5 @@ <?php -#Set Dir constants -$here = substr(realpath(dirname(__file__)), - strlen($_SERVER['DOCUMENT_ROOT'])); -// Determine the path in the URI used as the base of the osTicket -// installation -if (!defined('ROOT_PATH')) - define('ROOT_PATH', str_replace('\\', '/', $here.'/')); //root path. Damn directories - #Get real path for root dir ---linux and windows define('ROOT_DIR',str_replace('\\', '/', realpath(dirname(__FILE__))).'/'); define('INCLUDE_DIR',ROOT_DIR.'include/'); //Change this if include is moved outside the web path. @@ -17,6 +9,13 @@ define('SETUP_DIR',ROOT_DIR.'setup/'); define('UPGRADE_DIR', INCLUDE_DIR.'upgrader/'); define('I18N_DIR', INCLUDE_DIR.'i18n/'); +require(INCLUDE_DIR.'class.misc.php'); + +// Determine the path in the URI used as the base of the osTicket +// installation +if (!defined('ROOT_PATH')) + define('ROOT_PATH', Misc::siteRootPath(realpath(dirname(__file__))).'/'); //root path. Damn directories + class Bootstrap { function init() { @@ -36,10 +35,6 @@ class Bootstrap { ini_set('session.use_trans_sid', 0); #No cache session_cache_limiter('nocache'); - #Cookies - # TODO: Determine root path - session_set_cookie_params(86400, dirname($_SERVER['PHP_SELF']), - $_SERVER['HTTP_HOST'], self::https()); #Error reporting...Good idea to ENABLE error reporting to a file. i.e display_errors should be set to false $error_reporting = E_ALL & ~E_NOTICE; @@ -221,10 +216,6 @@ else define('THISPAGE', Misc::currentURL()); define('THISURI', $_SERVER['REQUEST_URI']); -#Cookies -session_set_cookie_params(86400, ROOT_PATH, $_SERVER['HTTP_HOST'], - osTicket::is_https()); - define('DEFAULT_MAX_FILE_UPLOADS',ini_get('max_file_uploads')?ini_get('max_file_uploads'):5); define('DEFAULT_PRIORITY_ID',1); diff --git a/client.inc.php b/client.inc.php index 85c9624bb4f419d814af3acf586081be4ac5d1d0..f8f6ddff1e0cab8dd8a8e047138b0b3974eced85 100644 --- a/client.inc.php +++ b/client.inc.php @@ -31,7 +31,7 @@ define('ASSETS_PATH',ROOT_PATH.'assets/default/'); //Check the status of the HelpDesk. if (!in_array(strtolower(basename($_SERVER['SCRIPT_NAME'])), array('logo.php',)) && !(is_object($ost) && $ost->isSystemOnline())) { - include('./offline.php'); + include(ROOT_DIR.'offline.php'); exit; } diff --git a/include/api.tickets.php b/include/api.tickets.php index 59f6c6f5a8b5fbb093fdd59ac97e675dde964639..afad901d50593b06693771ae43f854612fdd3c87 100644 --- a/include/api.tickets.php +++ b/include/api.tickets.php @@ -20,7 +20,8 @@ class TicketApiController extends ApiController { if(!strcasecmp($format, 'email')) $supported = array_merge($supported, array('header', 'mid', - 'emailId', 'ticketId', 'reply-to', 'reply-to-name')); + 'emailId', 'ticketId', 'reply-to', 'reply-to-name', + 'in-reply-to', 'references')); return $supported; } @@ -115,7 +116,7 @@ class TicketApiController extends ApiController { if (($thread = ThreadEntry::lookupByEmailHeaders($data)) && $thread->postEmail($data)) { - return true; + return $thread->getTicket(); } return $this->createTicket($data); } diff --git a/include/class.api.php b/include/class.api.php index 3d61f6031d84ca49f62158bf254233ea86b078b1..28053565f4ac1846538e1546f5457c029b302cd7 100644 --- a/include/class.api.php +++ b/include/class.api.php @@ -317,8 +317,9 @@ class ApiXmlDataParser extends XmlDataParser { if (!is_array($current)) return $current; foreach ($current as $key=>&$value) { - if ($key == "phone") { - $current["phone_ext"] = $value["ext"]; # PHP [like] point + if ($key == "phone" && is_array($value)) { + if (isset($value['ext'])) + $current["phone_ext"] = $value["ext"]; # PHP [like] point $value = $value[":text"]; } else if ($key == "alert") { $value = (bool)$value; @@ -339,6 +340,7 @@ class ApiXmlDataParser extends XmlDataParser { $value = $this->fixup($value); } } + unset($value); return $current; } diff --git a/include/class.captcha.php b/include/class.captcha.php index ca103d920c744e2ea7efd53b75c531c35ba97d90..86f89d9792da363351dee17d151238f03872616e 100644 --- a/include/class.captcha.php +++ b/include/class.captcha.php @@ -3,7 +3,7 @@ class.captcha.php Very basic captcha class. - + Peter Rotich <peter@osticket.com> Copyright (c) 2006-2013 osTicket http://www.osticket.com @@ -44,7 +44,7 @@ class Captcha { $img= imagecreatefrompng($this->bgimg); imagestring($img,$this->font, $x, $y,$this->hash,imagecolorallocate($img,0, 0, 0)); - Header ("(captcha-content-type:) image/png"); + header("Content-Type: image/png"); imagepng($img); imagedestroy($img); $_SESSION['captcha'] = md5($this->hash); diff --git a/include/class.file.php b/include/class.file.php index 9e85630c7bd92f42cce0225e4d2c9c13127073c4..a896d9e9cefd4098be9a7e35080157bbe222d894 100644 --- a/include/class.file.php +++ b/include/class.file.php @@ -136,21 +136,23 @@ class AttachmentFile { return true; } - - function display() { - + function makeCacheable($ttl=3600) { // Thanks, http://stackoverflow.com/a/1583753/1025836 - $last_modified = strtotime($this->lastModified()); - header("Last-Modified: ".gmdate(DATE_RFC822, $last_modified)." GMT", false); + $last_modified = Misc::db2gmtime($this->lastModified()); + header("Last-Modified: ".date('D, d M y H:i:s', $last_modified)." GMT", false); header('ETag: "'.$this->getHash().'"'); - header('Cache-Control: private, max-age=3600'); - header('Expires: ' . date(DATE_RFC822, time() + 3600) . ' GMT'); + header("Cache-Control: private, max-age=$ttl"); + header('Expires: ' . gmdate(DATE_RFC822, time() + $ttl)." GMT"); header('Pragma: private'); if (@strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE']) == $last_modified || @trim($_SERVER['HTTP_IF_NONE_MATCH']) == $this->getHash()) { header("HTTP/1.1 304 Not Modified"); exit(); } + } + + function display() { + $this->makeCacheable(); header('Content-Type: '.($this->getType()?$this->getType():'application/octet-stream')); header('Content-Length: '.$this->getSize()); @@ -159,20 +161,20 @@ class AttachmentFile { } function download() { + $this->makeCacheable(); - header('Pragma: public'); - header('Expires: 0'); - header('Cache-Control: must-revalidate, post-check=0, pre-check=0'); - header('Cache-Control: public'); header('Content-Type: '.($this->getType()?$this->getType():'application/octet-stream')); $filename=basename($this->getName()); $user_agent = strtolower ($_SERVER['HTTP_USER_AGENT']); - if ((is_integer(strpos($user_agent,'msie'))) && (is_integer(strpos($user_agent,'win')))) { - header('Content-Disposition: filename='.$filename.';'); - }else{ - header('Content-Disposition: attachment; filename='.$filename.';' ); - } + if (false !== strpos($user_agent,'msie') && false !== strpos($user_agent,'win')) + header('Content-Disposition: filename='.rawurlencode($filename).';'); + elseif (false !== strpos($user_agent, 'safari') && false === strpos($user_agent, 'chrome')) + // Safari and Safari only can handle the filename as is + header('Content-Disposition: filename='.str_replace(',', '', $filename).';'); + else + // Use RFC5987 + header("Content-Disposition: filename*=UTF-8''".rawurlencode($filename).';' ); header('Content-Transfer-Encoding: binary'); header('Content-Length: '.$this->getSize()); @@ -238,7 +240,7 @@ class AttachmentFile { $sql='INSERT INTO '.FILE_TABLE.' SET created=NOW() ' .',type='.db_input($file['type']) .',size='.db_input($file['size']) - .',name='.db_input(Format::file_name($file['name'])) + .',name='.db_input($file['name']) .',hash='.db_input($file['hash']); # XXX: ft does not exists during the upgrade when attachments are diff --git a/include/class.mailfetch.php b/include/class.mailfetch.php index 57d828274c01594cc6c1e5487c782817add9012a..9f0ae3b1e951069005e2f34ae3b8a00ffb319681 100644 --- a/include/class.mailfetch.php +++ b/include/class.mailfetch.php @@ -423,6 +423,7 @@ class MailFetcher { $newticket=true; $errors=array(); + if (($thread = ThreadEntry::lookupByEmailHeaders($vars)) && ($message = $thread->postEmail($vars))) { if ($message === true) diff --git a/include/class.mailparse.php b/include/class.mailparse.php index d224b9fe739a2f1db30cef8713cbe0ef4737d38b..b9ab3c33ff34fd44496a92affbc38a276fc418b9 100644 --- a/include/class.mailparse.php +++ b/include/class.mailparse.php @@ -264,6 +264,8 @@ class Mail_Parse { } function parseAddressList($address){ + if (!$address) + return false; return Mail_RFC822::parseAddressList($address, null, null,false); } @@ -341,6 +343,9 @@ class EmailDataParser { $data['priorityId'] = $parser->getPriority(); $data['emailId'] = $emailId; + $data['in-reply-to'] = $parser->struct->headers['in-reply-to']; + $data['references'] = $parser->struct->headers['references']; + if ($replyto = $parser->getReplyTo()) { $replyto = $replyto[0]; $data['reply-to'] = $replyto->mailbox.'@'.$replyto->host; diff --git a/include/class.misc.php b/include/class.misc.php index e913a8de0fdd052b0e9a87ec9693b720cc36e03b..d49970e9f9ca8a92d5e16e29c146f329ad7bda60 100644 --- a/include/class.misc.php +++ b/include/class.misc.php @@ -139,21 +139,24 @@ class Misc { return $output; } - function siteBaseUrl() { - # Detects Alias-ing - $paths = explode('/', $_SERVER['REQUEST_URI']); - # Drop the last item -- it will be the php page we're on - array_pop($paths); - $leading = array(); - while (count($paths)) { - if (in_array($paths[0], array('scp','client'))) - break; - $leading[] = array_shift($paths); + /* static */ + function siteRootPath($main_inc_path) { + if (!$_SERVER['DOCUMENT_ROOT']) + // Probably run from the command-line + return './'; + $root = str_replace('\\', '/', $main_inc_path); + $root2 = str_replace('\\','/', $_SERVER['DOCUMENT_ROOT']); + $path = ''; + while (strpos($_SERVER['DOCUMENT_ROOT'], $root) === false) { + $lastslash = strrpos($root, '/'); + if ($lastslash === false) + // Unable to find any commonality between $root and + // DOCUMENT_ROOT + return './'; + $path = substr($root, $lastslash) . $path; + $root = substr($root, 0, $lastslash); } - if (count($leading) > 1) - return implode('/', $leading); - else - return ''; + return $path; } } diff --git a/include/class.ostsession.php b/include/class.ostsession.php index 7541e19ec04aba50072abb7e495e48725316f5c7..b99e5c99135589001de75e1162b5699befa88af8 100644 --- a/include/class.ostsession.php +++ b/include/class.ostsession.php @@ -25,19 +25,32 @@ class osTicketSession { if(!$this->ttl) $this->ttl=SESSION_TTL; - if (!defined('DISABLE_SESSION') && !OsticketConfig::getDBVersion()) { - //Set handlers. - session_set_save_handler( - array(&$this, 'open'), - array(&$this, 'close'), - array(&$this, 'read'), - array(&$this, 'write'), - array(&$this, 'destroy'), - array(&$this, 'gc') - ); - //Forced cleanup. - register_shutdown_function('session_write_close'); - } + if (defined('DISABLE_SESSION') || OsticketConfig::getDBVersion()) + return; + + # Cookies + // Avoid setting a cookie domain without a dot, thanks + // http://stackoverflow.com/a/1188145 + $domain = null; + if (isset($_SERVER['HTTP_HOST']) + && strpos($_SERVER['HTTP_HOST'], '.') !== false + && !Validator::is_ip($_SERVER['HTTP_HOST'])) + $domain = $_SERVER['HTTP_HOST']; + session_set_cookie_params(86400, ROOT_PATH, $domain, + osTicket::is_https()); + + //Set handlers. + session_set_save_handler( + array(&$this, 'open'), + array(&$this, 'close'), + array(&$this, 'read'), + array(&$this, 'write'), + array(&$this, 'destroy'), + array(&$this, 'gc') + ); + //Forced cleanup. + register_shutdown_function('session_write_close'); + //Start the session. session_name('OSTSESSID'); session_start(); diff --git a/include/class.staff.php b/include/class.staff.php index e0220120c0ca497bc12482296d6e08ffe84c257f..c434d3d1ca7548f65fc66160439da988cbfb17b3 100644 --- a/include/class.staff.php +++ b/include/class.staff.php @@ -690,7 +690,7 @@ class Staff { // this user id $sql = 'DELETE FROM '.CONFIG_TABLE.' WHERE `namespace`="pwreset" AND `value`='.db_input($this->getId()); - db_query($sql); + db_query($sql, false); unset($_SESSION['_staff']['reset-token']); } diff --git a/include/ost-sampleconfig.php b/include/ost-sampleconfig.php index d3cbb517a3b2922444a6ccdbd9fcb936439cf5a1..65ff21c0d053e78c6b49a1e0647b881a1bff57f3 100644 --- a/include/ost-sampleconfig.php +++ b/include/ost-sampleconfig.php @@ -22,7 +22,7 @@ if(!strcasecmp(basename($_SERVER['SCRIPT_NAME']),basename(__FILE__)) || !defined #Install flag define('OSTINSTALLED',FALSE); if(OSTINSTALLED!=TRUE){ - if(!file_exists(ROOT_PATH.'setup/install.php')) die('Error: Contact system admin.'); //Something is really wrong! + if(!file_exists(ROOT_DIR.'setup/install.php')) die('Error: Contact system admin.'); //Something is really wrong! //Invoke the installer. header('Location: '.ROOT_PATH.'setup/install.php'); exit; diff --git a/setup/cli/package.php b/setup/cli/package.php index 45fd517704822e7ae3e4c8d471bdb30b14d1e5ea..4bae36081898368857a18838d852bab129429ebe 100755 --- a/setup/cli/package.php +++ b/setup/cli/package.php @@ -110,7 +110,7 @@ package("setup/scripts/*", "scripts/", -1, "*stage"); package("include/{,.}*", "upload/include", -1, array('*ost-config.php', '*.sw[a-z]')); # Include the installer -package("setup/*.{php,txt}", "upload/setup", -1, array("*scripts","*test","*stage")); +package("setup/*.{php,txt,html}", "upload/setup", -1, array("*scripts","*test","*stage")); foreach (array('css','images','js') as $dir) package("setup/$dir/*", "upload/setup/$dir", -1); package("setup/inc/streams/*.sql", "upload/setup/inc/streams", -1);