diff --git a/include/UniversalClassLoader.php b/include/UniversalClassLoader.php new file mode 100644 index 0000000000000000000000000000000000000000..9b9bf801b95524ffe255ec0abbdc6ca127ca89ed --- /dev/null +++ b/include/UniversalClassLoader.php @@ -0,0 +1,319 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\ClassLoader; + +/** + * UniversalClassLoader implements a "universal" autoloader for PHP 5.3. + * + * It is able to load classes that use either: + * + * * The technical interoperability standards for PHP 5.3 namespaces and + * class names (https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-0.md); + * + * * The PEAR naming convention for classes (http://pear.php.net/). + * + * Classes from a sub-namespace or a sub-hierarchy of PEAR classes can be + * looked for in a list of locations to ease the vendoring of a sub-set of + * classes for large projects. + * + * Example usage: + * + * $loader = new UniversalClassLoader(); + * + * // register classes with namespaces + * $loader->registerNamespaces(array( + * 'Symfony\Component' => __DIR__.'/component', + * 'Symfony' => __DIR__.'/framework', + * 'Sensio' => array(__DIR__.'/src', __DIR__.'/vendor'), + * )); + * + * // register a library using the PEAR naming convention + * $loader->registerPrefixes(array( + * 'Swift_' => __DIR__.'/Swift', + * )); + * + * + * // to enable searching the include path (e.g. for PEAR packages) + * $loader->useIncludePath(true); + * + * // activate the autoloader + * $loader->register(); + * + * In this example, if you try to use a class in the Symfony\Component + * namespace or one of its children (Symfony\Component\Console for instance), + * the autoloader will first look for the class under the component/ + * directory, and it will then fallback to the framework/ directory if not + * found before giving up. + * + * @author Fabien Potencier <fabien@symfony.com> + * + * @api + */ +class UniversalClassLoader_osTicket +{ + private $namespaces = array(); + private $prefixes = array(); + private $namespaceFallbacks = array(); + private $prefixFallbacks = array(); + private $useIncludePath = false; + + /** + * Turns on searching the include for class files. Allows easy loading + * of installed PEAR packages + * + * @param Boolean $useIncludePath + */ + public function useIncludePath($useIncludePath) + { + $this->useIncludePath = $useIncludePath; + } + + /** + * Can be used to check if the autoloader uses the include path to check + * for classes. + * + * @return Boolean + */ + public function getUseIncludePath() + { + return $this->useIncludePath; + } + + /** + * Gets the configured namespaces. + * + * @return array A hash with namespaces as keys and directories as values + */ + public function getNamespaces() + { + return $this->namespaces; + } + + /** + * Gets the configured class prefixes. + * + * @return array A hash with class prefixes as keys and directories as values + */ + public function getPrefixes() + { + return $this->prefixes; + } + + /** + * Gets the directory(ies) to use as a fallback for namespaces. + * + * @return array An array of directories + */ + public function getNamespaceFallbacks() + { + return $this->namespaceFallbacks; + } + + /** + * Gets the directory(ies) to use as a fallback for class prefixes. + * + * @return array An array of directories + */ + public function getPrefixFallbacks() + { + return $this->prefixFallbacks; + } + + /** + * Registers the directory to use as a fallback for namespaces. + * + * @param array $dirs An array of directories + * + * @api + */ + public function registerNamespaceFallbacks(array $dirs) + { + $this->namespaceFallbacks = $dirs; + } + + /** + * Registers a directory to use as a fallback for namespaces. + * + * @param string $dir A directory + */ + public function registerNamespaceFallback($dir) + { + $this->namespaceFallbacks[] = $dir; + } + + /** + * Registers directories to use as a fallback for class prefixes. + * + * @param array $dirs An array of directories + * + * @api + */ + public function registerPrefixFallbacks(array $dirs) + { + $this->prefixFallbacks = $dirs; + } + + /** + * Registers a directory to use as a fallback for class prefixes. + * + * @param string $dir A directory + */ + public function registerPrefixFallback($dir) + { + $this->prefixFallbacks[] = $dir; + } + + /** + * Registers an array of namespaces + * + * @param array $namespaces An array of namespaces (namespaces as keys and locations as values) + * + * @api + */ + public function registerNamespaces(array $namespaces) + { + foreach ($namespaces as $namespace => $locations) { + $this->namespaces[$namespace] = (array) $locations; + } + } + + /** + * Registers a namespace. + * + * @param string $namespace The namespace + * @param array|string $paths The location(s) of the namespace + * + * @api + */ + public function registerNamespace($namespace, $paths) + { + $this->namespaces[$namespace] = (array) $paths; + } + + /** + * Registers an array of classes using the PEAR naming convention. + * + * @param array $classes An array of classes (prefixes as keys and locations as values) + * + * @api + */ + public function registerPrefixes(array $classes) + { + foreach ($classes as $prefix => $locations) { + $this->prefixes[$prefix] = (array) $locations; + } + } + + /** + * Registers a set of classes using the PEAR naming convention. + * + * @param string $prefix The classes prefix + * @param array|string $paths The location(s) of the classes + * + * @api + */ + public function registerPrefix($prefix, $paths) + { + $this->prefixes[$prefix] = (array) $paths; + } + + /** + * Registers this instance as an autoloader. + * + * @param Boolean $prepend Whether to prepend the autoloader or not + * + * @api + */ + public function register($prepend = false) + { + spl_autoload_register(array($this, 'loadClass'), true, $prepend); + } + + /** + * Loads the given class or interface. + * + * @param string $class The name of the class + * + * @return Boolean|null True, if loaded + */ + public function loadClass($class) + { + if ($file = $this->findFile($class)) { + require $file; + + return true; + } + } + + /** + * Finds the path to the file where the class is defined. + * + * @param string $class The name of the class + * + * @return string|null The path, if found + */ + public function findFile($class) + { + if (false !== $pos = strrpos($class, '\\')) { + // namespaced class name + $namespace = substr($class, 0, $pos); + $className = substr($class, $pos + 1); + $normalizedClass = str_replace('\\', DIRECTORY_SEPARATOR, $namespace).DIRECTORY_SEPARATOR.str_replace('_', DIRECTORY_SEPARATOR, $className).'.php'; + foreach ($this->namespaces as $ns => $dirs) { + if (0 !== strpos($namespace, $ns)) { + continue; + } + + foreach ($dirs as $dir) { + $file = $dir.DIRECTORY_SEPARATOR.$normalizedClass; + if (is_file($file)) { + return $file; + } + } + } + + foreach ($this->namespaceFallbacks as $dir) { + $file = $dir.DIRECTORY_SEPARATOR.$normalizedClass; + if (is_file($file)) { + return $file; + } + } + + } else { + // PEAR-like class name + $normalizedClass = str_replace('_', DIRECTORY_SEPARATOR, $class).'.php'; + foreach ($this->prefixes as $prefix => $dirs) { + if (0 !== strpos($class, $prefix)) { + continue; + } + + foreach ($dirs as $dir) { + $file = $dir.DIRECTORY_SEPARATOR.$normalizedClass; + if (is_file($file)) { + return $file; + } + } + } + + foreach ($this->prefixFallbacks as $dir) { + $file = $dir.DIRECTORY_SEPARATOR.$normalizedClass; + if (is_file($file)) { + return $file; + } + } + } + + if ($this->useIncludePath && $file = stream_resolve_include_path($normalizedClass)) { + return $file; + } + } +} diff --git a/include/ajax.tickets.php b/include/ajax.tickets.php index 016882de13a4599bbf5976ed940c7b28d2fd73cc..445733dc6f80fc0283e72740e742f79aabd19b24 100644 --- a/include/ajax.tickets.php +++ b/include/ajax.tickets.php @@ -73,11 +73,8 @@ class TicketsAjaxAPI extends AjaxController { .' FROM '.TICKET_TABLE.' ticket' .' JOIN '.USER_TABLE.' user ON user.id = ticket.user_id' .' JOIN '.USER_EMAIL_TABLE.' email ON user.id = email.user_id' - .' LEFT JOIN '.FORM_ENTRY_TABLE.' entry ON (entry.object_id = user.id - AND entry.object_type=\'U\') - LEFT JOIN '.FORM_ANSWER_TABLE.' data ON (data.entry_id = entry.id)' .' WHERE (email.address LIKE \'%'.db_input(strtolower($_REQUEST['q']), false).'%\' - OR data.value LIKE \'%'.db_input($_REQUEST['q'], false).'%\')'; + OR user.name LIKE \'%'.db_input($_REQUEST['q'], false).'%\')'; $sql.=' AND ( staff_id='.db_input($thisstaff->getId()); diff --git a/include/class.file.php b/include/class.file.php index 84689f02011afd73cb2871582adb43aa5f3c07cb..a2ce70bfa1a56b33641eda172b40651619e067fb 100644 --- a/include/class.file.php +++ b/include/class.file.php @@ -307,21 +307,24 @@ class AttachmentFile { = self::_getKeyAndHash($file['data']); if (!$file['key']) $file['key'] = $key; - - if (!isset($file['size'])) - $file['size'] = strlen($file['data']); } - // Check and see if the file is already on record - $sql = 'SELECT id, `key` FROM '.FILE_TABLE - .' WHERE signature='.db_input($file['signature']) - .' AND size='.db_input($file['size']); + if (isset($file['size'])) { + // Check and see if the file is already on record + $sql = 'SELECT id, `key` FROM '.FILE_TABLE + .' WHERE signature='.db_input($file['signature']) + .' AND size='.db_input($file['size']); - // If the record exists in the database already, a file with the - // same hash and size is already on file -- just return its ID - if (list($id, $key) = db_fetch_row(db_query($sql))) { - $file['key'] = $key; - return $id; + // If the record exists in the database already, a file with the + // same hash and size is already on file -- just return its ID + if (list($id, $key) = db_fetch_row(db_query($sql))) { + $file['key'] = $key; + return $id; + } + } + elseif (!isset($file['data'])) { + // Unable to determine the file's size + return false; } if (!$file['type']) { @@ -337,15 +340,16 @@ class AttachmentFile { $file['type'] = 'application/octet-stream'; } - $sql='INSERT INTO '.FILE_TABLE.' SET created=NOW() ' .',type='.db_input(strtolower($file['type'])) - .',size='.db_input($file['size']) .',name='.db_input($file['name']) .',`key`='.db_input($file['key']) .',ft='.db_input($ft ?: 'T') .',signature='.db_input($file['signature']); + if (isset($file['size'])) + $sql .= ',size='.db_input($file['size']); + if (!(db_query($sql) && ($id = db_insert_id()))) return false; @@ -383,8 +387,23 @@ class AttachmentFile { return false; } - $sql = 'UPDATE '.FILE_TABLE.' SET bk='.db_input($bk->getBkChar()) - .' WHERE id='.db_input($f->getId()); + $sql = 'UPDATE '.FILE_TABLE.' SET bk='.db_input($bk->getBkChar()); + + if (!isset($file['size'])) { + if ($size = $bk->getSize()) + $file['size'] = $size; + // Prefer mb_strlen, because mbstring.func_overload will + // automatically prefer it if configured. + elseif (extension_loaded('mbstring')) + $file['size'] = mb_strlen($file['data'], '8bit'); + // bootstrap.php include a compat version of mb_strlen + else + $file['size'] = strlen($file['data']); + + $sql .= ', `size`='.db_input($file['size']); + } + + $sql .= ' WHERE id='.db_input($f->getId()); db_query($sql); return $f->getId(); @@ -745,6 +764,18 @@ class FileStorageBackend { function getHashDigest($algo) { return false; } + + /** + * getSize + * + * Retrieves the size of the contents written or available to be read. + * The backend should optimize this process if possible by keeping track + * of the bytes written in a way apart from `strlen`. This value will be + * used instead of inspecting the contents using `strlen`. + */ + function getSize() { + return false; + } } @@ -764,7 +795,7 @@ class AttachmentChunkedData extends FileStorageBackend { $this->_buffer = false; } - function length() { + function getSize() { list($length) = db_fetch_row(db_query( 'SELECT SUM(LENGTH(filedata)) FROM '.FILE_CHUNK_TABLE .' WHERE file_id='.db_input($this->file->getId()))); @@ -788,11 +819,12 @@ class AttachmentChunkedData extends FileStorageBackend { function write($what, $chunk_size=CHUNK_SIZE) { $offset=0; + $what = bin2hex($what); for (;;) { - $block = substr($what, $offset, $chunk_size); + $block = substr($what, $offset, $chunk_size*2); if (!$block) break; if (!db_query('REPLACE INTO '.FILE_CHUNK_TABLE - .' SET filedata=0x'.bin2hex($block).', file_id=' + .' SET filedata=0x'.$block.', file_id=' .db_input($this->file->getId()).', chunk_id='.db_input($this->_chunk++))) return false; $offset += strlen($block); diff --git a/include/class.mailfetch.php b/include/class.mailfetch.php index 644d866637383fb9faadfce643616a280e8e2d52..0b739e7c82eeb4a9a1668a096effcbc8ade8616e 100644 --- a/include/class.mailfetch.php +++ b/include/class.mailfetch.php @@ -462,6 +462,7 @@ class MailFetcher { array( 'name' => $this->mime_decode($filename), 'type' => $this->getMimeType($part), + 'size' => $part->bytes ?: null, 'encoding' => $part->encoding, 'index' => ($index?$index:1), 'cid' => $content_id, diff --git a/include/class.mailparse.php b/include/class.mailparse.php index f3feaf25d5e2678a4be426ab36e898dcd48782a2..378c68c1959e2a5c6ff4d442a9b8282c43c7aee3 100644 --- a/include/class.mailparse.php +++ b/include/class.mailparse.php @@ -396,6 +396,13 @@ class Mail_Parse { else $file['data'] = $part->body; + // Capture filesize in order to support de-duplication + if (extension_loaded('mbstring')) + $file['size'] = mb_strlen($file['data'], '8bit'); + // bootstrap.php include a compat version of mb_strlen + else + $file['size'] = strlen($file['data']); + if(!$this->decode_bodies && $part->headers['content-transfer-encoding']) $file['encoding'] = $part->headers['content-transfer-encoding']; diff --git a/include/staff/faq.inc.php b/include/staff/faq.inc.php index 56fa42dd62a6fadbbf8cf4169a005dd24d48a4c6..9bb484f403ee27ba8682acafce7cdba3895cbfd0 100644 --- a/include/staff/faq.inc.php +++ b/include/staff/faq.inc.php @@ -89,7 +89,7 @@ $info=Format::htmlchars(($errors && $_POST)?$_POST:$info); <textarea name="answer" cols="21" rows="12" style="width:98%;" class="richtext draft" data-draft-namespace="faq" - data-draft-object-id="<?php if (isset($faq)) echo $faq->getId(); ?>" + data-draft-object-id="<?php if (is_object($faq)) echo $faq->getId(); ?>" ><?php echo $info['answer']; ?></textarea> </td> </tr> diff --git a/setup/inc/file-missing.inc.php b/setup/inc/file-missing.inc.php index 2c84883c4b676011f868ffe2dd9adaf91ebd280e..c0e1994e83a20c2d7c98b0e09c4ec005fabf5cb9 100644 --- a/setup/inc/file-missing.inc.php +++ b/setup/inc/file-missing.inc.php @@ -25,6 +25,6 @@ if(!defined('SETUPINC')) die('Kwaheri!'); <div id="sidebar"> <h3>Need Help?</h3> <p> - If you are looking for a greater level of support, we provide <u>professional installation services</u> and commercial support with guaranteed response times, and access to the core development team. We can also help customize osTicket or even add new features to the system to meet your unique needs. <a target="_blank" href="http://osticket.com/support/professional_services.php">Learn More!</a> + If you are looking for a greater level of support, we provide <u>professional installation services</u> and commercial support with guaranteed response times, and access to the core development team. We can also help customize osTicket or even add new features to the system to meet your unique needs. <a target="_blank" href="http://osticket.com/support">Learn More!</a> </p> </div> diff --git a/setup/inc/file-perm.inc.php b/setup/inc/file-perm.inc.php index 6a158082ddecadbb7552f52f43503cf29f7ac3bb..7c2378a77c46be6ca1f3173a9697464dabb480a9 100644 --- a/setup/inc/file-perm.inc.php +++ b/setup/inc/file-perm.inc.php @@ -27,6 +27,6 @@ if(!defined('SETUPINC')) die('Kwaheri!'); <div id="sidebar"> <h3>Need Help?</h3> <p> - If you are looking for a greater level of support, we provide <u>professional installation services</u> and commercial support with guaranteed response times, and access to the core development team. We can also help customize osTicket or even add new features to the system to meet your unique needs. <a target="_blank" href="http://osticket.com/support/professional_services.php">Learn More!</a> + If you are looking for a greater level of support, we provide <u>professional installation services</u> and commercial support with guaranteed response times, and access to the core development team. We can also help customize osTicket or even add new features to the system to meet your unique needs. <a target="_blank" href="http://osticket.com/support">Learn More!</a> </p> </div> diff --git a/setup/inc/file-unclean.inc.php b/setup/inc/file-unclean.inc.php index 3c194b60ac2f078ecaef85cb3811ac9ed0741a6d..8847ead592cc50ebbb4db937a33cac2334b72278 100644 --- a/setup/inc/file-unclean.inc.php +++ b/setup/inc/file-unclean.inc.php @@ -13,6 +13,6 @@ if(!defined('SETUPINC')) die('Kwaheri!'); <div id="sidebar"> <h3>Need Help?</h3> <p> - We provide <u>professional installation services</u> and commercial support with guaranteed response times, and access to the core development team. <a target="_blank" href="http://osticket.com/support/professional_services.php">Learn More!</a> + We provide <u>professional installation services</u> and commercial support with guaranteed response times, and access to the core development team. <a target="_blank" href="http://osticket.com/support">Learn More!</a> </p> </div> diff --git a/setup/inc/header.inc.php b/setup/inc/header.inc.php index a1ee36a1dd0833f6bab52b2be732610bdf67afe3..ef8aed7e3da82dd02a3e8c4cd41d53b44380b44b 100644 --- a/setup/inc/header.inc.php +++ b/setup/inc/header.inc.php @@ -20,7 +20,7 @@ foreach($wizard['menu'] as $k=>$v) echo sprintf('<a target="_blank" href="%s">%s</a> — ',$v,$k); ?> - <a target="_blank" href="http://osticket.com/support/contact.php">Contact Us</a> + <a target="_blank" href="http://osticket.com/contact-us">Contact Us</a> </li> </ul> </div> diff --git a/setup/inc/install-done.inc.php b/setup/inc/install-done.inc.php index 3aaf5caf33712eb6f2157966f609038a2fe99dd3..466c67bd10ef42c697916ab9bbb8e9be2c548e4b 100644 --- a/setup/inc/install-done.inc.php +++ b/setup/inc/install-done.inc.php @@ -30,7 +30,7 @@ $url=URL; <tr> <td width="50%"> <strong>osTicket Forums:</strong><Br> - <a href="#">http://osticket.com/forums/</a> + <a href="#">http://osticket.com/forum/</a> </td> <td width="50%"> <strong>osTicket Community Wiki:</strong><Br> @@ -44,5 +44,5 @@ $url=URL; <h3>What's Next?</h3> <p><b>Post-Install Setup</b>: You can now log in to <a href="../scp/admin.php" target="_blank">Admin Panel</a> with the username and password you created during the install process. After a successful log in, you can proceed with post-install setup. For complete and upto date guide see <a href="http://osticket.com/wiki/Post-Install_Setup_Guide" target="_blank">osTicket wiki</a></p> - <p><b>Commercial Support Available</b>: Don't let technical problems impact your osTicket implementation. Get guidance and hands-on expertise to address unique challenges and make sure your osTicket runs smoothly, efficiently, and securely. <a target="_blank" href="http://osticket.com/support/commercial_support.php.php">Learn More!</a></p> + <p><b>Commercial Support Available</b>: Don't let technical problems impact your osTicket implementation. Get guidance and hands-on expertise to address unique challenges and make sure your osTicket runs smoothly, efficiently, and securely. <a target="_blank" href="http://osticket.com/commercial-support">Learn More!</a></p> </div> diff --git a/setup/inc/install-prereq.inc.php b/setup/inc/install-prereq.inc.php index a6c3340b5902ed979991404731a6ef33e0bc6009..f004ba6883fbd858e51f09fc2db92edadddc6cc0 100644 --- a/setup/inc/install-prereq.inc.php +++ b/setup/inc/install-prereq.inc.php @@ -40,6 +40,6 @@ if(!defined('SETUPINC')) die('Kwaheri!'); <div id="sidebar"> <h3>Need Help?</h3> <p> - If you are looking for a greater level of support, we provide <u>professional installation services</u> and commercial support with guaranteed response times, and access to the core development team. We can also help customize osTicket or even add new features to the system to meet your unique needs. <a target="_blank" href="http://osticket.com/support/professional_services.php">Learn More!</a> + If you are looking for a greater level of support, we provide <u>professional installation services</u> and commercial support with guaranteed response times, and access to the core development team. We can also help customize osTicket or even add new features to the system to meet your unique needs. <a target="_blank" href="http://osticket.com/support">Learn More!</a> </p> </div> diff --git a/setup/inc/install.inc.php b/setup/inc/install.inc.php index f58943a2fc450022077fd2d1ba59f752b636c66f..a14ea07bc9b593110e0b2d0f6f47f68894d24459 100644 --- a/setup/inc/install.inc.php +++ b/setup/inc/install.inc.php @@ -118,7 +118,7 @@ $info=($_POST && $errors)?Format::htmlchars($_POST):array('prefix'=>'ost_','dbho </form> </div> <div> - <p><strong>Need Help?</strong> We provide <u>professional installation services</u> and commercial support. <a target="_blank" href="http://osticket.com/support/professional_services.php">Learn More!</a></p> + <p><strong>Need Help?</strong> We provide <u>professional installation services</u> and commercial support. <a target="_blank" href="http://osticket.com/support">Learn More!</a></p> </div> <div id="overlay"></div> <div id="loading">