/**
  * This should be the first call to initialize all the static variables
  * The application object also has static methods that are miscellaneous web
  * development utilities, etc.
  *
  * @throws Exception
  * @return void
  */
 public static function Initialize()
 {
     self::$EncodingType = defined('__QAPPLICATION_ENCODING_TYPE__') ? __QAPPLICATION_ENCODING_TYPE__ : self::$EncodingType;
     // Are we running as CLI?
     if (PHP_SAPI == 'cli') {
         QApplication::$CliMode = true;
     } else {
         QApplication::$CliMode = false;
     }
     // Setup Server Address
     if (array_key_exists('LOCAL_ADDR', $_SERVER)) {
         QApplication::$ServerAddress = $_SERVER['LOCAL_ADDR'];
     } else {
         if (array_key_exists('HTTP_X_FORWARDED_FOR', $_SERVER)) {
             QApplication::$ServerAddress = $_SERVER['HTTP_X_FORWARDED_FOR'];
         } else {
             if (array_key_exists('SERVER_ADDR', $_SERVER)) {
                 QApplication::$ServerAddress = $_SERVER['SERVER_ADDR'];
             }
         }
     }
     // Setup ScriptFilename and ScriptName
     QApplication::$ScriptFilename = $_SERVER['SCRIPT_FILENAME'];
     QApplication::$ScriptName = $_SERVER['SCRIPT_NAME'];
     // Ensure both are set, or we'll have to abort
     if (!QApplication::$ScriptFilename || !QApplication::$ScriptName) {
         throw new Exception('Error on QApplication::Initialize() - ScriptFilename or ScriptName was not set');
     }
     // Setup PathInfo and QueryString (if applicable)
     QApplication::$PathInfo = null;
     if (array_key_exists('PATH_INFO', $_SERVER)) {
         QApplication::$PathInfo = urlencode(trim($_SERVER['PATH_INFO']));
         QApplication::$PathInfo = str_ireplace('%2f', '/', QApplication::$PathInfo);
     }
     QApplication::$QueryString = array_key_exists('QUERY_STRING', $_SERVER) ? $_SERVER['QUERY_STRING'] : null;
     // Setup RequestUri
     if (defined('__URL_REWRITE__')) {
         switch (strtolower(__URL_REWRITE__)) {
             case 'apache':
                 QApplication::$RequestUri = $_SERVER['REQUEST_URI'];
                 break;
             case 'none':
                 QApplication::$RequestUri = sprintf('%s%s%s', QApplication::$ScriptName, QApplication::$PathInfo, QApplication::$QueryString ? sprintf('?%s', QApplication::$QueryString) : null);
                 break;
             default:
                 throw new Exception('Invalid URL Rewrite type: ' . __URL_REWRITE__);
         }
     } else {
         QApplication::$RequestUri = sprintf('%s%s%s', QApplication::$ScriptName, QApplication::$PathInfo, QApplication::$QueryString ? sprintf('?%s', QApplication::$QueryString) : null);
     }
     // Setup DocumentRoot
     QApplication::$DocumentRoot = trim(__DOCROOT__);
     // Setup Browser Type
     if (array_key_exists('HTTP_USER_AGENT', $_SERVER)) {
         $strUserAgent = trim(strtolower($_SERVER['HTTP_USER_AGENT']));
         QApplication::$BrowserType = 0;
         // INTERNET EXPLORER (versions 6 through 10)
         if (strpos($strUserAgent, 'msie') !== false) {
             QApplication::$BrowserType = QApplication::$BrowserType | QBrowserType::InternetExplorer;
             // just major version number. Will not see IE 10.6.
             $matches = array();
             preg_match('#msie\\s(.\\d)#', $strUserAgent, $matches);
             if ($matches) {
                 QApplication::$BrowserVersion = (int) $matches[1];
             }
         } else {
             if (strpos($strUserAgent, 'trident') !== false) {
                 // IE 11 significantly changes the user agent, and no longer includes 'MSIE'
                 QApplication::$BrowserType = QApplication::$BrowserType | QBrowserType::InternetExplorer;
                 $matches = array();
                 preg_match('/rv:(.+)\\)/', $strUserAgent, $matches);
                 if ($matches) {
                     QApplication::$BrowserVersion = (double) $matches[1];
                 }
                 // FIREFOX
             } else {
                 if (strpos($strUserAgent, 'firefox') !== false || strpos($strUserAgent, 'iceweasel') !== false) {
                     QApplication::$BrowserType = QApplication::$BrowserType | QBrowserType::Firefox;
                     $strUserAgent = str_replace('iceweasel/', 'firefox/', $strUserAgent);
                     $matches = array();
                     preg_match('#firefox/(.+)#', $strUserAgent, $matches);
                     if ($matches) {
                         QApplication::$BrowserVersion = (double) $matches[1];
                     }
                 } elseif (strpos($strUserAgent, 'chrome') !== false) {
                     QApplication::$BrowserType = QApplication::$BrowserType | QBrowserType::Chrome;
                     // find major version number only
                     $matches = array();
                     preg_match('#chrome/(\\d+)#', $strUserAgent, $matches);
                     if ($matches) {
                         QApplication::$BrowserVersion = (int) $matches[1];
                     }
                 } elseif (strpos($strUserAgent, 'safari') !== false) {
                     QApplication::$BrowserType = QApplication::$BrowserType | QBrowserType::Safari;
                     $matches = array();
                     preg_match('#version/(.+)\\s#', $strUserAgent, $matches);
                     if ($matches) {
                         QApplication::$BrowserVersion = (double) $matches[1];
                     }
                 } elseif (strpos($strUserAgent, 'konqueror') !== false) {
                     QApplication::$BrowserType = QApplication::$BrowserType | QBrowserType::Konqueror;
                     // only looking at major version number on this one
                     $matches = array();
                     preg_match('#konqueror/(\\d+)#', $strUserAgent, $matches);
                     if ($matches) {
                         QApplication::$BrowserVersion = (int) $matches[1];
                     }
                 } elseif (strpos($strUserAgent, 'opera') !== false) {
                     QApplication::$BrowserType = QApplication::$BrowserType | QBrowserType::Opera;
                     // two different patterns;
                     $matches = array();
                     preg_match('#version/(\\d+)#', $strUserAgent, $matches);
                     if ($matches) {
                         QApplication::$BrowserVersion = (int) $matches[1];
                     } else {
                         preg_match('#opera\\s(.+)#', $strUserAgent, $matches);
                         if ($matches) {
                             QApplication::$BrowserVersion = (double) $matches[1];
                         }
                     }
                 }
             }
         }
         // Unknown
         if (QApplication::$BrowserType == 0) {
             QApplication::$BrowserType = QApplication::$BrowserType | QBrowserType::Unsupported;
         }
         // OS (supporting Windows, Linux and Mac)
         if (strpos($strUserAgent, 'windows') !== false) {
             QApplication::$BrowserType = QApplication::$BrowserType | QBrowserType::Windows;
         } elseif (strpos($strUserAgent, 'linux') !== false) {
             QApplication::$BrowserType = QApplication::$BrowserType | QBrowserType::Linux;
         } elseif (strpos($strUserAgent, 'macintosh') !== false) {
             QApplication::$BrowserType = QApplication::$BrowserType | QBrowserType::Macintosh;
         }
         // Mobile version of one of the above browsers, or some other unknown browser
         if (strpos($strUserAgent, 'mobi') !== false) {
             // opera is just 'mobi', everyone else uses 'mobile'
             QApplication::$BrowserType = QApplication::$BrowserType | QBrowserType::Mobile;
         }
     }
     // Preload Class Files
     foreach (QApplication::$PreloadedClassFile as $strClassFile) {
         require $strClassFile;
     }
     // Initialize any classes that might call into the autoloader
     $strCacheProviderClass = 'QCacheProviderNoCache';
     if (defined('CACHE_PROVIDER_CLASS')) {
         $strCacheProviderClass = CACHE_PROVIDER_CLASS;
     }
     if ($strCacheProviderClass) {
         if (defined('CACHE_PROVIDER_OPTIONS')) {
             QApplicationBase::$objCacheProvider = new $strCacheProviderClass(unserialize(CACHE_PROVIDER_OPTIONS));
         } else {
             QApplicationBase::$objCacheProvider = new $strCacheProviderClass();
         }
     }
     if (defined('__MINIMIZE__') && __MINIMIZE__) {
         QApplicationBase::$Minimize = true;
     }
 }