public static function processRequest(array $params)
 {
     // set timezone if unset to avoid warnings
     date_default_timezone_set(@date_default_timezone_get());
     // set memory limit if required
     if ($params['memoryLimit']) {
         $inibytes = self::returnBytes(ini_get('memory_limit'));
         $ourbytes = self::returnBytes($params['memoryLimit']);
         if ($inibytes < $ourbytes) {
             @ini_set('memory_limit', $params['memoryLimit']);
         }
     }
     // load up the configured rate limiter class, if any
     if (!empty($params['rateLimiter'])) {
         $limiter = $params['rateLimiter'];
         // if the configured class does not exist, this is a hack attempt and someone is hitting the imthumb.php script directly to bypass rate limiting
         if (!class_exists($limiter)) {
             $remoteIPString = isset($_SERVER['HTTP_CLIENT_IP']) ? $_SERVER['HTTP_CLIENT_IP'] : (isset($_SERVER['HTTP_X_FORWARDED_FOR']) ? $_SERVER['HTTP_X_FORWARDED_FOR'] : (isset($_SERVER['REMOTE_ADDR']) ? $_SERVER['REMOTE_ADDR'] : ''));
             throw new ImThumbCriticalException("Rate limiter class not found, hack attempt! Source {$remoteIPString}", ImThumb::ERR_HACK_ATTEMPT);
         }
         $params['rateLimiter'] = new $limiter();
     }
     $handler = new ImThumb($params);
     $http = new ImThumbHTTP($handler, $params);
     try {
         // check for referrer
         if (!$params['externalReferrerAllowed'] && !self::isReferrerOk()) {
             self::quickImageResponse('leeching');
         }
         // check for rate limiting
         if (!$handler->checkRateLimits()) {
             self::quickImageResponse('ratelimited');
         }
         // load up the image
         $handler->loadImage($params['src']);
         // check for browser cache
         if ($handler->hasBrowserCache()) {
             $http->sendHeaders();
             exit(0);
         }
         // check and write to caches
         if (!$handler->writeCache()) {
             // check cache directory for expired content if we processed an already cached image
             if ($handler->cache) {
                 $handler->cache->checkExpiredCaches();
             }
         }
         // output the image and all headers
         if (!$http->display()) {
             // nothing to display, we aren't configured to show any fallback 404 image
             throw new ImThumbCriticalException("Source image not found. Source querystring: {$_SERVER['QUERY_STRING']}", ImThumb::ERR_SERVER_CONFIG);
         }
     } catch (Exception $e) {
         if ($e instanceof ImThumbCriticalException) {
             throw $e;
         }
         // attempt to load any configured error image. If this errors out it will just throw the exception naturally.
         $handler->loadErrorImage();
         $handler->configureUnalteredFitImage();
         $handler->doResize();
         if ($e instanceof ImThumbException) {
             if ($e->getCode() == ImThumb::ERR_SRC_IMAGE) {
                 // log the querystring passed in addition to regular message
                 $msg = $e->getMessage() . ' Source querystring: ' . $_SERVER['QUERY_STRING'];
             } else {
                 $msg = $e->getMessage();
             }
         } else {
             $msg = 'Unknown error ' . $e->getCode() . ': ' . $e->getMessage();
         }
         $theImage = $handler->getImage();
         if (!$theImage) {
             throw $e;
         }
         $http->sendHeaders($msg);
         echo $theImage;
         exit(0);
     }
 }