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);