lbry.com/view/Response.class.php
2018-05-21 11:49:15 -04:00

382 lines
11 KiB
PHP

<?php
class Response
{
const HEADER_STATUS = 'Status';
const HEADER_LOCATION = 'Location';
const HEADER_CACHE_CONTROL = 'Cache-Control';
const HEADER_LAST_MODIFIED = 'Last-Modified';
const HEADER_ETAG = 'Etag';
const HEADER_CONTENT_TYPE = 'Content-Type';
const HEADER_CONTENT_LENGTH = 'Content-Length';
const HEADER_CONTENT_DISPOSITION = 'Content-Disposition';
const HEADER_CONTENT_TYPE_OPTIONS = 'X-Content-Type-Options';
const HEADER_CONTENT_ENCODING = 'Content-Encoding';
const HEADER_CROSS_ORIGIN = 'Access-Control-Allow-Origin';
protected static $metaDescription = '';
protected static $metaTitle = '';
protected static $jsCalls = [];
protected static $assets = [
'js' => [
'/js/jquery-3.3.1.min.js',
'/js/global.js'
],
'css' => ['/css/all.css']
];
protected static $headers = [];
protected static $headersSent = false;
protected static $content = '';
protected static $contentSent = false;
protected static $isHeadersOnly = false;
protected static $gzipResponseContent = true;
protected static $metaImages = [];
protected static $facebookAnalyticsType = "PageView";
public static function setMetaDescription($description)
{
static::$metaDescription = $description;
}
public static function addMetaImage($url)
{
static::$metaImages[] = $url;
}
public static function addMetaImages(array $urls)
{
foreach ($urls as $url) {
static::addMetaImage($url);
}
}
public static function getMetaDescription()
{
return static::$metaDescription ?: 'A Content Revolution';
}
public static function getMetaImages()
{
return static::$metaImages ?: [Request::getHostAndProto() . '/img/lbry-green-meta-1200x900.png'];
}
public static function setMetaTitle($title)
{
static::$metaTitle = $title;
}
public static function getMetaTitle()
{
return static::$metaTitle;
}
public static function guessMetaTitle($content)
{
$title = '';
preg_match_all('/<h(1|2)[^>]*>([^<]+)</', $content, $titleMatches);
foreach ($titleMatches[1] as $matchIndex => $headerValue) {
if ($headerValue == '1' || !$title) {
$title = $titleMatches[2][$matchIndex];
if ($headerValue == '1') {
return $title;
}
}
}
return $title;
}
public static function getJsCalls()
{
return static::$jsCalls;
}
public static function jsOutputCallback($js)
{
static::$jsCalls[] = $js;
return '';
}
public static function addJsAsset($src)
{
static::$assets['js'][$src] = $src;
}
public static function addCssAsset($src)
{
static::$assets['css'][$src] = $src;
}
public static function getJsAssets()
{
return static::$assets['js'];
}
public static function getCssAssets()
{
return static::$assets['css'];
}
public static function setCssAssets(array $assets = [])
{
static::$assets['css'] = $assets;
}
public static function setGzipResponseContent($gzip = true)
{
static::$gzipResponseContent = $gzip;
}
public static function gzipContentIfNotDisabled()
{
if (static::$gzipResponseContent) {
$content = static::getContent();
if (strlen($content) > 256) { // not worth it for really short content
$compressed = gzencode($content, 1);
static::setContent($compressed);
static::setHeader(static::HEADER_CONTENT_LENGTH, strlen($compressed));
static::setHeader(static::HEADER_CONTENT_ENCODING, 'gzip');
}
}
}
public static function send()
{
static::sendHeaders();
static::sendContent();
}
public static function setContent(string $content)
{
static::$content = $content;
}
public static function getContent(): string
{
return static::$content;
}
public static function sendContent()
{
if (static::$contentSent) {
throw new LogicException('Content has already been sent. It cannot be sent twice');
}
if (!static::$isHeadersOnly) {
echo static::$content;
}
static::$contentSent = true;
}
public static function setIsHeadersOnly(bool $isHeadersOnly = true)
{
static::$isHeadersOnly = $isHeadersOnly;
}
public static function setDownloadHttpHeaders($name, $type = null, $size = null, $noSniff = true)
{
static::setBinaryHttpHeaders($type, $size, $noSniff);
static::setHeader('Content-Disposition', 'attachment;filename=' . $name);
}
public static function setBinaryHttpHeaders($type, $size = null, $noSniff = true)
{
static::setGzipResponseContent(false); // in case its already compressed
static::setHeaders(array_filter([
static::HEADER_CONTENT_TYPE => $type,
static::HEADER_CONTENT_LENGTH => $size ?: null,
static::HEADER_CONTENT_TYPE_OPTIONS => $noSniff ? 'nosniff' : null,
]));
}
public static function setContentEtag()
{
static::setHeader(static::HEADER_ETAG, md5(static::getContent()));
}
public static function enableHttpCache(int $seconds = 300)
{
static::addCacheControlHeader('max-age', $seconds);
static::setHeader('Pragma', 'public');
}
public static function addCacheControlHeader(string $name, $value = null)
{
$cacheControl = static::getHeader(static::HEADER_CACHE_CONTROL);
$currentHeaders = [];
if ($cacheControl) {
foreach (preg_split('/\s*,\s*/', $cacheControl) as $tmp) {
$tmp = explode('=', $tmp);
$currentHeaders[$tmp[0]] = $tmp[1] ?? null;
}
}
$currentHeaders[strtr(strtolower($name), '_', '-')] = $value;
$headers = [];
foreach ($currentHeaders as $key => $currentVal) {
$headers[] = $key . ($currentVal !== null ? '=' . $currentVal : '');
}
static::setHeader(static::HEADER_CACHE_CONTROL, implode(', ', $headers));
}
public static function setHeader($name, $value)
{
static::$headers[$name] = $value;
}
public static function setHeaders($headers, $overwrite = true)
{
foreach ($headers as $name => $value) {
if ($overwrite || !static::getHeader($name)) {
static::setHeader($name, $value);
}
}
}
public static function getHeader($name, $default = null)
{
return static::$headers[$name] ?? $default;
}
public static function getHeaders(): array
{
return static::$headers;
}
public static function setStatus($status)
{
static::setHeader(static::HEADER_STATUS, $status);
}
public static function setDefaultSecurityHeaders()
{
$defaultHeaders = [
'Content-Security-Policy' => "frame-ancestors 'none'",
'X-Frame-Options' => 'DENY',
'X-XSS-Protection' => '1',
];
if (IS_PRODUCTION) {
$defaultHeaders['Strict-Transport-Security'] = 'max-age=31536000';
}
static::setHeaders($defaultHeaders, false);
}
public static function sendHeaders()
{
if (static::$headersSent) {
throw new LogicException('Headers have already been sent. They cannot be sent twice');
}
if (!static::getHeader(static::HEADER_CONTENT_TYPE)) {
static::setHeader(static::HEADER_CONTENT_TYPE, 'text/html');
}
$headers = static::getHeaders();
if (isset($headers[static::HEADER_STATUS])) {
$status = 'HTTP/1.0 ' . $headers[static::HEADER_STATUS] . ' ' . static::getStatusTextForCode($headers[static::HEADER_STATUS]);
header($status);
if (substr(php_sapi_name(), 0, 3) == 'cgi') {
// fastcgi servers cannot send this status information because it was sent by them already due to the HTT/1.0 line
// so we can safely unset them. see ticket #3191
unset($headers[static::HEADER_STATUS]);
}
}
foreach ($headers as $name => $value) {
header($name . ': ' . $value);
}
static::$headersSent = true;
}
public static function getStatusTextForCode($code)
{
$statusTexts = [
'100' => 'Continue',
'101' => 'Switching Protocols',
'200' => 'OK',
'201' => 'Created',
'202' => 'Accepted',
'203' => 'Non-Authoritative Information',
'204' => 'No Content',
'205' => 'Reset Content',
'206' => 'Partial Content',
'300' => 'Multiple Choices',
'301' => 'Moved Permanently',
'302' => 'Found',
'303' => 'See Other',
'304' => 'Not Modified',
'305' => 'Use Proxy',
'306' => '(Unused)',
'307' => 'Temporary Redirect',
'400' => 'Bad Request',
'401' => 'Unauthorized',
'402' => 'Payment Required',
'403' => 'Forbidden',
'404' => 'Not Found',
'405' => 'Method Not Allowed',
'406' => 'Not Acceptable',
'407' => 'Proxy Authentication Required',
'408' => 'Request Timeout',
'409' => 'Conflict',
'410' => 'Gone',
'411' => 'Length Required',
'412' => 'Precondition Failed',
'413' => 'Request Entity Too Large',
'414' => 'Request-URI Too Long',
'415' => 'Unsupported Media Type',
'416' => 'Requested Range Not Satisfiable',
'417' => 'Expectation Failed',
'419' => 'Authentication Timeout',
'422' => 'Unprocessable Entity',
'426' => 'Upgrade Required',
'429' => 'Too Many Requests',
'500' => 'Internal Server Error',
'501' => 'Not Implemented',
'502' => 'Bad Gateway',
'503' => 'Service Unavailable',
'504' => 'Gateway Timeout',
'505' => 'HTTP Version Not Supported',
];
return $statusTexts[$code] ?? null;
}
public static function setFacebookPixelAnalyticsType($type)
{
static::$facebookAnalyticsType = $type;
}
public static function getFacebookPixelAnalyticsType()
{
return static::$facebookAnalyticsType;
}
protected static function normalizeHeaderName($name): string
{
return preg_replace_callback(
'/\-(.)/',
function ($matches) {
return '-' . strtoupper($matches[1]);
},
strtr(ucfirst(strtolower($name)), '_', '-')
);
}
// public static function addBodyCssClass($classOrClasses)
// {
// static::$bodyCssClasses = array_unique(array_merge(static::$bodyCssClasses, (array)$classOrClasses));
// }
//
// public static function getBodyCssClasses()
// {
// return static::$bodyCssClasses;
// }
}