/** * Handler for uncaught exceptions. * @param \Exception $exception The exception. * @param bool Whether the exception was generated by a fatal PHP error. */ public function handleError($exception, $fatal = false) { $this->logger->critical(tr('Uncaught exception: %1', $exception->getMessage()), array('exception' => $exception)); $this->fatalError = $fatal; if ($this->isCli()) { if (isset($this->m->shell)) { $this->m->shell->handleException($exception); } else { Shell::dumpException($exception); } $this->stop(1); } if ($this->config['system']['createCrashReports']) { $file = $exception->getFile(); $line = $exception->getLine(); $message = $exception->getMessage(); $hash = substr(md5($file . $line . $message), 0, 10); $name = date('Y-m-d') . '_crash_' . $hash . '.html'; if (!isset($this->errorPaths['log'])) { $this->logger->alert(tr('Could not create crash report: Log directory is missing')); } else { if (!file_exists($this->errorPaths['log'] . '/' . $name)) { $file = fopen($this->errorPaths['log'] . '/' . $name, 'w'); if ($file !== false) { ob_start(); $this->crashReport($exception); fwrite($file, ob_get_clean()); fclose($file); $this->logger->critical(tr('A crash report has been generated: "%1"', $name)); } else { $hash = null; $this->logger->alert(tr('Failed to create crash report "%1"', $name)); } } } if (!$this->config['system']['showReference']) { $hash = null; } } // Clean the view while (ob_get_level() > 0) { ob_end_clean(); } Http::setContentType('text/html'); Http::setStatus(Http::INTERNAL_SERVER_ERROR); if ($this->config['system']['showExceptions']) { ob_start(); $this->crashReport($exception); $body = ob_get_clean(); $event = new ShowExceptionEvent($this, $exception, $body); $this->safeTriggerEvent('showException', $event); echo $event->body; $this->stop(1); } else { $custom = null; try { if (isset($this->errorPaths['errorTemplate'])) { include $this->errorPaths['errorTemplate']; $custom = true; } } catch (\Exception $e) { $this->logger->alert(tr('Error template (%1) failed: %2', '{template}', $e->getMessage()), array('template' => $this->errorPaths['errorTemplate'], 'exception' => $e)); } if (!isset($custom)) { include \Jivoo\PATH . '/Core/templates/error/error.php'; } $this->stop(1); } }
/** * Sends a response to the client and stops execution of the applicaton. * @param Response $response Response object. * @param int $status HTTP status code override. */ public function respond(Response $response, $status = null) { if (headers_sent($file, $line)) { throw new HeadersSentException(tr('Headers already sent in %1 on line %2', $file, $line)); } $event = new RenderEvent($this, $this->selection, $response); $this->triggerEvent('beforeRender', $event); $this->logger->debug(tr('Rendering response %1 (%2 %3)', get_class($response), $response->status, $response->type)); if (isset($status)) { Http::setStatus($status); } else { Http::setStatus($response->status); } // TODO: to remove or not to remove PHP version from response? header_remove('X-Powered-By'); Http::setContentType($response->type); if (isset($response->modified)) { header('Modified: ' . Http::date($response->modified)); } if (isset($response->cache)) { $cache = $response->cache; if (isset($response->maxAge)) { $cache .= ', max-age=' . $response->maxAge; header('Expires: ' . Http::date(time() + $response->maxAge)); } header('Pragma: ' . $response->cache); header('Cache-Control: ' . $cache); } else { if ($this->etags) { $tag = md5($response->body); header('ETag: ' . $tag); header('Cache-Control: must-revalidate'); header('Pragma: must-revalidate'); if (isset($_SERVER['HTTP_IF_NONE_MATCH'])) { $tags = explode(',', $_SERVER['HTTP_IF_NONE_MATCH']); foreach ($tags as $match) { if (trim($match) == $tag) { Http::setStatus(Http::NOT_MODIFIED); $this->app->stop(); } } } } } $body = $response->body; $event->body = $body; $this->triggerEvent('afterRender', $event); if ($event->overrideBody) { $body = $event->body; } if (function_exists('bzcompress') and $this->request->acceptsEncoding('bzip2')) { header('Content-Encoding: bzip2'); echo bzcompress($body); } else { if (function_exists('gzencode') and $this->request->acceptsEncoding('gzip')) { header('Content-Encoding: gzip'); echo gzencode($body); } else { echo $body; } } $this->app->stop(); }
/** * {@inheritdoc} */ public function toRoute($routeString) { if (preg_match('/^snippet:([a-z0-9_\\\\]+)(?:\\?(.*))?$/i', $routeString, $matches) !== 1) { throw new InvalidRouteException(tr('Invalid route string for snippet dispatcher')); } $route = array('parameters' => array()); if (isset($matches[2])) { $route['parameters'] = Http::decodeQuery($matches[2], false); if (!is_array($route['parameters'])) { throw new InvalidRouteException(tr('Invalid JSON parameters in route string')); } } $route['snippet'] = $matches[1]; return $route; }
/** * {@inheritdoc} */ public function toRoute($routeString) { if (preg_match('/^action:(?:([a-z0-9_\\\\]+)::)?([a-z0-9_\\\\]+)(?:\\?(.*))?$/i', $routeString, $matches) !== 1) { throw new InvalidRouteException(tr('Invalid route string for action dispatcher')); } $route = array('parameters' => array()); if (isset($matches[3])) { $route['parameters'] = Http::decodeQuery($matches[3], false); if (!is_array($route['parameters'])) { throw new InvalidRouteException(tr('Invalid JSON parameters in route string')); } } if ($matches[1] != '') { $route['controller'] = $matches[1]; $route['action'] = $matches[2]; } else { if (ucfirst($matches[2]) === $matches[2]) { $route['controller'] = $matches[2]; } else { if (isset($this->m->Routing->route['controller'])) { $route['controller'] = $this->m->Routing->route['controller']; } $route['action'] = $matches[2]; } } return $route; }