diff --git a/include/class.osticket.php b/include/class.osticket.php index 512d390e284bdd64b7587f523f71c2ec75712fe4..9dd1df016f1b9727d388ed57f837a4f92c47f72f 100644 --- a/include/class.osticket.php +++ b/include/class.osticket.php @@ -307,7 +307,7 @@ class osTicket { ',log='.db_input($message). ',ip_address='.db_input($_SERVER['REMOTE_ADDR']); - mysql_query($sql); //don't use db_query to avoid possible loop. + db_query($sql, false); return true; } diff --git a/include/class.setup.php b/include/class.setup.php index af44e4d22703f82fe2f9e32dbfb1294a4d3bfac0..dfb348c8919ac8be8fa58df0d5d0bf29cd19db8f 100644 --- a/include/class.setup.php +++ b/include/class.setup.php @@ -21,7 +21,7 @@ Class SetupWizard { 'mysql' => '4.4'); //Version info - same as the latest version. - + var $version =THIS_VERSION; var $version_verbose = THIS_VERSION; @@ -35,7 +35,7 @@ Class SetupWizard { } function load_sql_file($file, $prefix, $abort=true, $debug=false) { - + if(!file_exists($file) || !($schema=file_get_contents($file))) return $this->abort('Error accessing SQL file '.basename($file), $debug); @@ -49,18 +49,17 @@ Class SetupWizard { # Strip comments and remarks $schema=preg_replace('%^\s*(#|--).*$%m', '', $schema); - # Replace table prefis + # Replace table prefix $schema = str_replace('%TABLE_PREFIX%', $prefix, $schema); - # Split by semicolons - and cleanup + # Split by semicolons - and cleanup if(!($statements = array_filter(array_map('trim', @explode(';', $schema))))) return $this->abort('Error parsing SQL schema', $debug); - @mysql_query('SET SESSION SQL_MODE =""'); + db_query('SET SESSION SQL_MODE =""', false); foreach($statements as $k=>$sql) { - //Note that we're not using db_query - because we want to control how errors are reported. - if(mysql_query($sql)) continue; - $error = "[$sql] ".mysql_error(); + if(db_query($sql, false)) continue; + $error = "[$sql] ".db_error(); if($abort) return $this->abort($error, $debug); } @@ -100,7 +99,7 @@ Class SetupWizard { @error is a mixed var. */ function abort($error, $debug=false) { - + if($debug) echo $error; $this->onError($error); @@ -108,7 +107,7 @@ Class SetupWizard { } function setError($error) { - + if($error && is_array($error)) $this->errors = array_merge($this->errors, $error); elseif($error) diff --git a/include/mysql.php b/include/mysql.php index 3a86c7a8c5e5b04e3e0533596109018b992640e1..7375616d9571f009433f0e88086f824621f52820 100644 --- a/include/mysql.php +++ b/include/mysql.php @@ -2,7 +2,7 @@ /********************************************************************* mysql.php - Collection of MySQL helper interface functions. + Collection of MySQL helper interface functions. Mostly wrappers with error/resource checking. @@ -16,8 +16,8 @@ vim: expandtab sw=4 ts=4 sts=4: **********************************************************************/ - function db_connect($host, $user, $passwd, $db = "") { - + function db_connect($host, $user, $passwd, $options = array()) { + //Assert if(!strlen($user) || !strlen($passwd) || !strlen($host)) return NULL; @@ -27,7 +27,7 @@ return NULL; //Select the database, if any. - if($db) db_select_database($db); + if($options['db']) db_select_database($options['db']); //set desired encoding just in case mysql charset is not UTF-8 - Thanks to FreshMedia @mysql_query('SET NAMES "utf8"'); @@ -36,7 +36,7 @@ @db_set_variable('sql_mode', ''); - return $dblink; + return $dblink; } function db_close() { @@ -47,7 +47,7 @@ function db_version() { $version=0; - if(preg_match('/(\d{1,2}\.\d{1,2}\.\d{1,2})/', + if(preg_match('/(\d{1,2}\.\d{1,2}\.\d{1,2})/', mysql_result(db_query('SELECT VERSION()'),0,0), $matches)) # nolint $version=$matches[1]; # nolint @@ -77,18 +77,14 @@ function db_create_database($database, $charset='utf8', $collate='utf8_general_ci') { return @mysql_query(sprintf('CREATE DATABASE %s DEFAULT CHARACTER SET %s COLLATE %s', $database, $charset, $collate)); } - + // execute sql query - function db_query($query, $database="", $conn="") { + function db_query($query, $logError=true) { global $ost; - - if($conn) { /* connection is provided*/ - $res = ($database)?mysql_db_query($database, $query, $conn):mysql_query($query, $conn); - } else { - $res = ($database)?mysql_db_query($database, $query):mysql_query($query); - } - - if(!$res && $ost) { //error reporting + + $res = mysql_query($query); + + if(!$res && $logError && $ost) { //error reporting $msg='['.$query.']'."\n\n".db_error(); $ost->logDBError('DB Error #'.db_errno(), $msg); //echo $msg; #uncomment during debuging or dev. @@ -98,7 +94,7 @@ } function db_squery($query) { //smart db query...utilizing args and sprintf - + $args = func_get_args(); $query = array_shift($args); $query = str_replace("?", "%s", $query); @@ -108,7 +104,7 @@ return db_query($query); } - function db_count($query) { + function db_count($query) { return db_result(db_query($query)); } @@ -126,7 +122,7 @@ function db_fetch_field($res) { return ($res)?mysql_fetch_field($res):NULL; - } + } function db_assoc_array($res, $mode=false) { if($res && db_num_rows($res)) { @@ -159,13 +155,13 @@ function db_free_result($res) { return mysql_free_result($res); } - + function db_output($var) { if(!function_exists('get_magic_quotes_runtime') || !get_magic_quotes_runtime()) //Sucker is NOT on - thanks. return $var; - if (is_array($var)) + if (is_array($var)) return array_map('db_output', $var); return (!is_numeric($var))?stripslashes($var):$var; @@ -192,9 +188,13 @@ } function db_error() { - return mysql_error(); + return mysql_error(); } - + + function db_connect_error() { + return db_error(); + } + function db_errno() { return mysql_errno(); } diff --git a/include/mysqli.php b/include/mysqli.php new file mode 100644 index 0000000000000000000000000000000000000000..327ad52abcda72b264d7cd625cf741a9c70dc3ba --- /dev/null +++ b/include/mysqli.php @@ -0,0 +1,232 @@ +<?php +/********************************************************************* + mysqli.php + + Collection of MySQL helper interface functions. + + Mostly wrappers with error/resource checking. + + Peter Rotich <peter@osticket.com> + Jared Hancock <jared@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: +**********************************************************************/ +$__db = null; + +function db_connect($host, $user, $passwd, $options = array()) { + global $__db; + + //Assert + if(!strlen($user) || !strlen($host)) + return NULL; + + if (!($__db = mysqli_init())) + return NULL; + + // Setup SSL if enabled + if (isset($options['ssl'])) + $__db->ssl_set( + $options['ssl']['key'], + $options['ssl']['cert'], + $options['ssl']['ca'], + null, null); + elseif(!$passwd) + return NULL; + + //Connectr + if(!@$__db->real_connect($host, $user, $passwd)) + return NULL; + + //Select the database, if any. + if(isset($options['db'])) $__db->select_db($options['db']); + + //set desired encoding just in case mysql charset is not UTF-8 - Thanks to FreshMedia + @$__db->query('SET NAMES "utf8"'); + @$__db->query('SET CHARACTER SET "utf8"'); + @$__db->query('SET COLLATION_CONNECTION=utf8_general_ci'); + + @db_set_variable('sql_mode', ''); + + return $__db; +} + +function db_close() { + global $__db; + return @$__db->close(); +} + +function db_version() { + + $version=0; + if(preg_match('/(\d{1,2}\.\d{1,2}\.\d{1,2})/', + db_result(db_query('SELECT VERSION()')), + $matches)) # nolint + $version=$matches[1]; # nolint + + return $version; +} + +function db_timezone() { + return db_get_variable('time_zone'); +} + +function db_get_variable($variable, $type='session') { + $sql =sprintf('SELECT @@%s.%s', $type, $variable); + return db_result(db_query($sql)); +} + +function db_set_variable($variable, $value, $type='session') { + $sql =sprintf('SET %s %s=%s',strtoupper($type), $variable, db_input($value)); + return db_query($sql); +} + + +function db_select_database($database) { + global $__db; + return ($database && @$__db->select_db($database)); +} + +function db_create_database($database, $charset='utf8', + $collate='utf8_general_ci') { + global $__db; + return @$__db->query(sprintf('CREATE DATABASE %s DEFAULT CHARACTER SET %s COLLATE %s', $database, $charset, $collate)); +} + +// execute sql query +function db_query($query, $logError=true) { + global $ost, $__db; + + $res = $__db->query($query); + + if(!$res && $logError && $ost) { //error reporting + $msg='['.$query.']'."\n\n".db_error(); + $ost->logDBError('DB Error #'.db_errno(), $msg); + //echo $msg; #uncomment during debuging or dev. + } + + return $res; +} + +function db_squery($query) { //smart db query...utilizing args and sprintf + + $args = func_get_args(); + $query = array_shift($args); + $query = str_replace("?", "%s", $query); + $args = array_map('db_real_escape', $args); + array_unshift($args, $query); + $query = call_user_func_array('sprintf', $args); + return db_query($query); +} + +function db_count($query) { + return db_result(db_query($query)); +} + +function db_result($res, $row=0) { + if (!$res) + return NULL; + + $res->data_seek($row); + list($value) = db_output($res->fetch_row()); + return $value; +} + +function db_fetch_array($res, $mode=MYSQL_ASSOC) { + return ($res) ? db_output($res->fetch_array($mode)) : NULL; +} + +function db_fetch_row($res) { + return ($res) ? db_output($res->fetch_row()) : NULL; +} + +function db_fetch_field($res) { + return ($res) ? $res->fetch_field() : NULL; +} + +function db_assoc_array($res, $mode=false) { + if($res && db_num_rows($res)) { + while ($row=db_fetch_array($res, $mode)) + $result[]=$row; + } + return $result; +} + +function db_num_rows($res) { + return ($res) ? $res->num_rows : 0; +} + +function db_affected_rows() { + global $__db; + return $__db->affected_rows; +} + +function db_data_seek($res, $row_number) { + return ($res && $res->data_seek($row_number)); +} + +function db_data_reset($res) { + return db_data_seek($res, 0); +} + +function db_insert_id() { + global $__db; + return $__db->insert_id; +} + +function db_free_result($res) { + return ($res && $res->free()); +} + +function db_output($var) { + + if(!function_exists('get_magic_quotes_runtime') || !get_magic_quotes_runtime()) //Sucker is NOT on - thanks. + return $var; + + if (is_array($var)) + return array_map('db_output', $var); + + return (!is_numeric($var))?stripslashes($var):$var; + +} + +//Do not call this function directly...use db_input +function db_real_escape($val, $quote=false) { + global $__db; + + //Magic quotes crap is taken care of in main.inc.php + $val=$__db->real_escape_string($val); + + return ($quote)?"'$val'":$val; +} + +function db_input($var, $quote=true) { + + if(is_array($var)) + return array_map('db_input', $var, array_fill(0, count($var), $quote)); + elseif($var && preg_match("/^\d+(\.\d+)?$/", $var)) + return $var; + + return db_real_escape($var, $quote); +} + +function db_connect_error() { + global $__db; + return $__db->connect_error; +} + +function db_error() { + global $__db; + return $__db->error; +} + +function db_errno() { + global $__db; + return $__db->errno; +} +?> + diff --git a/include/ost-sampleconfig.php b/include/ost-sampleconfig.php index 8a1f3b98eed8b51f6cbd535a8c181bebb5b7f312..d3cbb517a3b2922444a6ccdbd9fcb936439cf5a1 100644 --- a/include/ost-sampleconfig.php +++ b/include/ost-sampleconfig.php @@ -4,7 +4,7 @@ Static osTicket configuration file. Mainly useful for mysql login info. Created during installation process and shouldn't change even on upgrades. - + Peter Rotich <peter@osticket.com> Copyright (c) 2006-2010 osTicket http://www.osticket.com @@ -36,11 +36,31 @@ define('ADMIN_EMAIL','%ADMIN-EMAIL'); #Mysql Login info define('DBTYPE','mysql'); -define('DBHOST','%CONFIG-DBHOST'); +define('DBHOST','%CONFIG-DBHOST'); define('DBNAME','%CONFIG-DBNAME'); define('DBUSER','%CONFIG-DBUSER'); define('DBPASS','%CONFIG-DBPASS'); +# SSL Options +# --------------------------------------------------- +# SSL options for MySQL can be enabled by adding a certificate allowed by +# the database server here. To use SSL, you must have a client certificate +# signed by a CA (certificate authority). You can easily create this +# yourself with the EasyRSA suite. Give the public CA certificate, and both +# the public and private parts of your client certificate below. +# +# Once configured, you can ask MySQL to require the certificate for +# connections: +# +# > create user osticket; +# > grant all on osticket.* to osticket require subject '<subject>'; +# +# More information (to-be) available in doc/security/hardening.md + +# define('DBSSLCA','/path/to/ca.crt'); +# define('DBSSLCERT','/path/to/client.crt'); +# define('DBSSLKEY','/path/to/client.key'); + #Table prefix define('TABLE_PREFIX','%CONFIG-PREFIX'); diff --git a/main.inc.php b/main.inc.php index 284ff321739c42c2e76b2b99ac2d993401a1e370..f45b074d89c226a6521e461558f1ff2fd009cbbc 100644 --- a/main.inc.php +++ b/main.inc.php @@ -122,7 +122,10 @@ require(INCLUDE_DIR.'class.format.php'); //format helpers require(INCLUDE_DIR.'class.validator.php'); //Class to help with basic form input validation...please help improve it. require(INCLUDE_DIR.'class.mailer.php'); - require(INCLUDE_DIR.'mysql.php'); + if (extension_loaded('mysqli')) + require_once INCLUDE_DIR.'mysqli.php'; + else + require(INCLUDE_DIR.'mysql.php'); #CURRENT EXECUTING SCRIPT. define('THISPAGE', Misc::currentURL()); @@ -190,8 +193,18 @@ #Connect to the DB && get configuration from database $ferror=null; - if (!db_connect(DBHOST,DBUSER,DBPASS) || !db_select_database(DBNAME)) { - $ferror='Unable to connect to the database'; + $options = array(); + if (defined('DBSSLCA')) + $options['ssl'] = array( + 'ca' => DBSSLCA, + 'cert' => DBSSLCERT, + 'key' => DBSSLKEY + ); + + if (!db_connect(DBHOST, DBUSER, DBPASS, $options)) { + $ferror='Unable to connect to the database -'.db_connect_error(); + }elseif(!db_select_database(DBNAME)) { + $ferror='Unknown or invalid database '.DBNAME; } elseif(!($ost=osTicket::start(1)) || !($cfg = $ost->getConfig())) { $ferror='Unable to load config info from DB. Get tech support.'; } diff --git a/setup/inc/class.installer.php b/setup/inc/class.installer.php index dfbd12591df7b8f36ded1bddfcd1caef138b90b6..79591febcb28cce57da3ec7f95102ba6c89fe04a 100644 --- a/setup/inc/class.installer.php +++ b/setup/inc/class.installer.php @@ -81,7 +81,7 @@ class Installer extends SetupWizard { //MYSQL: Connect to the DB and check the version & database (create database if it doesn't exist!) if(!$this->errors) { if(!db_connect($vars['dbhost'],$vars['dbuser'],$vars['dbpass'])) - $this->errors['db']='Unable to connect to MySQL server. Possibly invalid login info.'; + $this->errors['db']='Unable to connect to MySQL server. '.db_connect_error(); elseif(db_version()< $this->getMySQLVersion()) $this->errors['db']=sprintf('osTicket requires MySQL %s or better!',$this->getMySQLVersion()); elseif(!db_select_database($vars['dbname']) && !db_create_database($vars['dbname'])) { @@ -92,12 +92,12 @@ class Installer extends SetupWizard { } else { //Abort if we have another installation (or table) with same prefix. $sql = 'SELECT * FROM `'.$vars['prefix'].'config` LIMIT 1'; - if(mysql_query($sql)) { + if(db_query($sql, false)) { $this->errors['err'] = 'We have a problem - another installation with same table prefix exists!'; $this->errors['prefix'] = 'Prefix already in-use'; } else { //Try changing charset and collation of the DB - no bigie if we fail. - mysql_query('ALTER DATABASE '.$vars['dbname'].' DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci'); + db_query('ALTER DATABASE '.$vars['dbname'].' DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci', false); } } } @@ -125,19 +125,19 @@ class Installer extends SetupWizard { $this->errors['err']='Error parsing SQL schema! Get help from developers (#4)'; $sql='SELECT `id` FROM '.PREFIX.'sla ORDER BY `id` LIMIT 1'; - $sla_id_1 = mysql_result(mysql_query($sql), 0); + $sla_id_1 = db_result(db_query($sql, false), 0); $sql='SELECT `dept_id` FROM '.PREFIX.'department ORDER BY `dept_id` LIMIT 1'; - $dept_id_1 = mysql_result(mysql_query($sql), 0); + $dept_id_1 = db_result(db_query($sql, false), 0); $sql='SELECT `tpl_id` FROM '.PREFIX.'email_template ORDER BY `tpl_id` LIMIT 1'; - $template_id_1 = mysql_result(mysql_query($sql), 0); + $template_id_1 = db_result(db_query($sql, false), 0); $sql='SELECT `group_id` FROM '.PREFIX.'groups ORDER BY `group_id` LIMIT 1'; - $group_id_1 = mysql_result(mysql_query($sql), 0); + $group_id_1 = db_result(db_query($sql, false), 0); $sql='SELECT `id` FROM '.PREFIX.'timezone WHERE offset=-5.0 LIMIT 1'; - $eastern_timezone = mysql_result(mysql_query($sql), 0); + $eastern_timezone = db_result(db_query($sql, false), 0); if(!$this->errors) { //Create admin user. @@ -149,7 +149,7 @@ class Installer extends SetupWizard { .', lastname='.db_input($vars['lname']) .', username='.db_input($vars['username']) .', passwd='.db_input(Passwd::hash($vars['passwd'])); - if(!mysql_query($sql) || !($uid=mysql_insert_id())) + if(!db_query($sql, false) || !($uid=db_insert_id())) $this->errors['err']='Unable to create admin user (#6)'; } @@ -161,11 +161,11 @@ class Installer extends SetupWizard { ." ('Support','$email',NOW(),NOW())" .",('osTicket Alerts','alerts@$domain',NOW(),NOW())" .",('','noreply@$domain',NOW(),NOW())"; - @mysql_query($sql); - $support_email_id = mysql_insert_id(); + $support_email_id = db_query($sql, false) ? db_insert_id() : 0; + $sql='SELECT `email_id` FROM '.PREFIX."email WHERE `email`='alerts@$domain' LIMIT 1"; - $alert_email_id = mysql_result(mysql_query($sql), 0); + $alert_email_id = db_result(db_query($sql, false), 0); //Create config settings---default settings! //XXX: rename ostversion helpdesk_* ?? @@ -178,7 +178,7 @@ class Installer extends SetupWizard { .', schema_signature='.db_input($signature) .', helpdesk_url='.db_input(URL) .', helpdesk_title='.db_input($vars['name']); - if(!mysql_query($sql) || !($cid=mysql_insert_id())) + if(!db_query($sql, false) || !($cid=db_insert_id())) $this->errors['err']='Unable to create config settings (#7)'; } @@ -202,12 +202,11 @@ class Installer extends SetupWizard { /************* Make the system happy ***********************/ - $sql='UPDATE '.PREFIX."email SET dept_id=$dept_id_1"; - mysql_query($sql); - $sql='UPDATE '.PREFIX."department SET email_id=$email_id_1" - .", autoresp_email_id=$email_id_1"; - mysql_query($sql); + db_query($sql, false); + $sql='UPDATE '.PREFIX."department SET email_id=$support_email_id" + .", autoresp_email_id=$support_email_id"; + db_query($sql, false); //Create a ticket to make the system warm and happy. $sql='INSERT INTO '.PREFIX.'ticket SET created=NOW(), status="open", source="Web" ' @@ -216,7 +215,7 @@ class Installer extends SetupWizard { .' ,email="support@osticket.com" ' .' ,name="osTicket Support" ' .' ,subject="osTicket Installed!"'; - if(mysql_query($sql) && ($tid=mysql_insert_id())) { + if(db_query($sql, false) && ($tid=db_insert_id())) { if(!($msg=file_get_contents(INC_DIR.'msg/installed.txt'))) $msg='Congratulations and Thank you for choosing osTicket!'; @@ -226,7 +225,7 @@ class Installer extends SetupWizard { .', ticket_id='.db_input($tid) .', title='.db_input('osTicket Installed') .', body='.db_input($msg); - @mysql_query($sql); + db_query($sql, false); } //TODO: create another personalized ticket and assign to admin?? @@ -236,7 +235,7 @@ class Installer extends SetupWizard { .', title="osTicket installed!"' .', log='.db_input($msg) .', ip_address='.db_input($_SERVER['REMOTE_ADDR']); - @mysql_query($sql); + db_query($sql, false); return true; } diff --git a/setup/setup.inc.php b/setup/setup.inc.php index e2f5620f7226af5d8d3c4aa0c55f3576d51eefd9..aa8b67c0495e52377698ee1d18aac4405499d8e9 100644 --- a/setup/setup.inc.php +++ b/setup/setup.inc.php @@ -66,5 +66,10 @@ require_once(INCLUDE_DIR.'class.validator.php'); require_once(INCLUDE_DIR.'class.passwd.php'); require_once(INCLUDE_DIR.'class.format.php'); require_once(INCLUDE_DIR.'class.misc.php'); -require_once(INCLUDE_DIR.'mysql.php'); + +if (extension_loaded('mysqli')) + require_once INCLUDE_DIR.'mysqli.php'; +else + require(INCLUDE_DIR.'mysql.php'); + ?>