Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/matomo-org/matomo.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/core
diff options
context:
space:
mode:
authormattab <matthieu.aubry@gmail.com>2013-09-14 04:14:23 +0400
committermattab <matthieu.aubry@gmail.com>2013-09-14 04:14:23 +0400
commitcf279bc8aa095c849932182bd3eb1c60ed9f67a3 (patch)
treeab8230b7e4e7b46065c079d3bfdaf3d28c443978 /core
parentdf470ed7170e4b323b4623fd55453abc2d7810ad (diff)
ProxyHttp class until I find a better name
Diffstat (limited to 'core')
-rw-r--r--core/AssetManager.php2
-rw-r--r--core/DataTable/Renderer/Csv.php12
-rw-r--r--core/DataTable/Renderer/Json.php7
-rw-r--r--core/FrontController.php3
-rw-r--r--core/Piwik.php36
-rw-r--r--core/ProxyHttp.php233
-rw-r--r--core/ReportRenderer.php8
-rw-r--r--core/Session.php5
-rw-r--r--core/View.php2
9 files changed, 249 insertions, 59 deletions
diff --git a/core/AssetManager.php b/core/AssetManager.php
index e65639b12f..af8e8a4bd4 100644
--- a/core/AssetManager.php
+++ b/core/AssetManager.php
@@ -500,7 +500,7 @@ class AssetManager
}
// Tries to remove compressed version of the merged file.
- // See Piwik::serveFile() for more info on static file compression
+ // See Piwik::serverStaticFile() for more info on static file compression
$compressedFileLocation = PIWIK_USER_PATH . Piwik::COMPRESSED_FILE_LOCATION . $filename;
@unlink($compressedFileLocation . ".deflate");
diff --git a/core/DataTable/Renderer/Csv.php b/core/DataTable/Renderer/Csv.php
index 64a62e3c2a..e1f4556025 100644
--- a/core/DataTable/Renderer/Csv.php
+++ b/core/DataTable/Renderer/Csv.php
@@ -10,14 +10,14 @@
*/
namespace Piwik\DataTable\Renderer;
-use Piwik\DataTable\Simple;
+use Piwik\Common;
use Piwik\DataTable\Renderer;
+use Piwik\DataTable\Simple;
+use Piwik\DataTable;
+use Piwik\Date;
use Piwik\Period;
use Piwik\Period\Range;
-use Piwik\Piwik;
-use Piwik\Common;
-use Piwik\Date;
-use Piwik\DataTable;
+use Piwik\ProxyHttp;
/**
* CSV export
@@ -353,7 +353,7 @@ class Csv extends Renderer
// silent fail otherwise unit tests fail
@header('Content-Type: application/vnd.ms-excel');
@header('Content-Disposition: attachment; filename="' . $fileName . '"');
- Piwik::overrideCacheControlHeaders();
+ ProxyHttp::overrideCacheControlHeaders();
}
/**
diff --git a/core/DataTable/Renderer/Json.php b/core/DataTable/Renderer/Json.php
index 89dd73ab37..ad22cab3ad 100644
--- a/core/DataTable/Renderer/Json.php
+++ b/core/DataTable/Renderer/Json.php
@@ -10,11 +10,10 @@
*/
namespace Piwik\DataTable\Renderer;
-use Piwik\DataTable\Renderer;
-use Piwik\Piwik;
use Piwik\Common;
+use Piwik\DataTable\Renderer;
use Piwik\DataTable;
-use Piwik\DataTable\Renderer\Php;
+use Piwik\ProxyHttp;
/**
* JSON export.
@@ -114,7 +113,7 @@ class Json extends Renderer
protected function renderHeader()
{
self::sendHeaderJSON();
- Piwik::overrideCacheControlHeaders();
+ ProxyHttp::overrideCacheControlHeaders();
}
public static function sendHeaderJSON()
diff --git a/core/FrontController.php b/core/FrontController.php
index 79a57b5e93..b26a754808 100644
--- a/core/FrontController.php
+++ b/core/FrontController.php
@@ -15,7 +15,6 @@ use Piwik\API\Request;
use Piwik\API\ResponseBuilder;
use Piwik\Log;
use Piwik\Session;
-use Piwik\Profiler;
use Zend_Registry;
/**
@@ -344,7 +343,7 @@ class FrontController
{
if (!Common::isPhpCliMode()
&& Config::getInstance()->General['force_ssl'] == 1
- && !Piwik::isHttps()
+ && !ProxyHttp::isHttps()
// Specifically disable for the opt out iframe
&& !(Common::getRequestVar('module', '') == 'CoreAdminHome'
&& Common::getRequestVar('action', '') == 'optOut')
diff --git a/core/Piwik.php b/core/Piwik.php
index 6d178f45eb..469b1f80e6 100644
--- a/core/Piwik.php
+++ b/core/Piwik.php
@@ -178,42 +178,6 @@ class Piwik
return $url;
}
- /**
- * Returns true if this appears to be a secure HTTPS connection
- *
- * @return bool
- */
- static public function isHttps()
- {
- return Url::getCurrentScheme() === 'https';
- }
-
- /**
- * Workaround IE bug when downloading certain document types over SSL and
- * cache control headers are present, e.g.,
- *
- * Cache-Control: no-cache
- * Cache-Control: no-store,max-age=0,must-revalidate
- * Pragma: no-cache
- *
- * @see http://support.microsoft.com/kb/316431/
- * @see RFC2616
- *
- * @param string $override One of "public", "private", "no-cache", or "no-store". (optional)
- */
- static public function overrideCacheControlHeaders($override = null)
- {
- if ($override || self::isHttps()) {
- @header('Pragma: ');
- @header('Expires: ');
- if (in_array($override, array('public', 'private', 'no-cache', 'no-store'))) {
- @header("Cache-Control: $override, must-revalidate");
- } else {
- @header('Cache-Control: must-revalidate');
- }
- }
- }
-
/*
* File and directory operations
*/
diff --git a/core/ProxyHttp.php b/core/ProxyHttp.php
new file mode 100644
index 0000000000..5bcde43de1
--- /dev/null
+++ b/core/ProxyHttp.php
@@ -0,0 +1,233 @@
+<?php
+/**
+ * Piwik - Open source web analytics
+ *
+ * @link http://piwik.org
+ * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
+ *
+ * @category Piwik
+ * @package Piwik
+ */
+namespace Piwik;
+
+/**
+ * Http helper: static file server proxy, with compression, caching, isHttps() helper...
+ *
+ * Used to server piwik.js and the merged+minified CSS and JS files
+ *
+ * @package Piwik
+ */
+class ProxyHttp
+{
+ /**
+ * Returns true if the current request appears to be a secure HTTPS connection
+ *
+ * @return bool
+ */
+ public static function isHttps()
+ {
+ return Url::getCurrentScheme() === 'https';
+ }
+
+ /**
+ * Serve static files through php proxy.
+ *
+ * It performs the following actions:
+ * - Checks the file is readable or returns "HTTP/1.0 404 Not Found"
+ * - Returns "HTTP/1.1 304 Not Modified" after comparing the HTTP_IF_MODIFIED_SINCE
+ * with the modification date of the static file
+ * - Will try to compress the static file according to HTTP_ACCEPT_ENCODING. Compressed files are store in
+ * the /tmp directory. If compressing extensions are not available, a manually gzip compressed file
+ * can be provided in the /tmp directory. It has to bear the same name with an added .gz extension.
+ * Using manually compressed static files requires you to manually update the compressed file when
+ * the static file is updated.
+ * - Overrides server cache control config to allow caching
+ * - Sends Very Accept-Encoding to tell proxies to store different version of the static file according
+ * to users encoding capacities.
+ *
+ * Warning:
+ * Compressed filed are stored in the /tmp directory.
+ * If this method is used with two files bearing the same name but located in different locations,
+ * there is a risk of conflict. One file could be served with the content of the other.
+ * A future upgrade of this method would be to recreate the directory structure of the static file
+ * within a /tmp/compressed-static-files directory.
+ *
+ * @param string $file The location of the static file to serve
+ * @param string $contentType The content type of the static file.
+ * @param bool $expireFarFuture If set to true, will set Expires: header in far future.
+ * Should be set to false for files that don't have a cache buster (eg. piwik.js)
+ */
+ public static function serverStaticFile($file, $contentType, $expireFarFuture = true)
+ {
+ if (file_exists($file)) {
+ // conditional GET
+ $modifiedSince = '';
+ if (isset($_SERVER['HTTP_IF_MODIFIED_SINCE'])) {
+ $modifiedSince = $_SERVER['HTTP_IF_MODIFIED_SINCE'];
+
+ // strip any trailing data appended to header
+ if (false !== ($semicolon = strpos($modifiedSince, ';'))) {
+ $modifiedSince = substr($modifiedSince, 0, $semicolon);
+ }
+ }
+
+ $fileModifiedTime = @filemtime($file);
+ $lastModified = gmdate('D, d M Y H:i:s', $fileModifiedTime) . ' GMT';
+
+ // set HTTP response headers
+ self::overrideCacheControlHeaders('public');
+ @header('Vary: Accept-Encoding');
+ @header('Content-Disposition: inline; filename=' . basename($file));
+
+ if ($expireFarFuture) {
+ // Required by proxy caches potentially in between the browser and server to cache the request indeed
+ @header("Expires: " . gmdate('D, d M Y H:i:s', time() + 86400 * 100) . ' GMT');
+ }
+
+ // Returns 304 if not modified since
+ if ($modifiedSince === $lastModified) {
+ self::setHttpStatus('304 Not Modified');
+ } else {
+ // optional compression
+ $compressed = false;
+ $encoding = '';
+ $compressedFileLocation = PIWIK_USER_PATH . Piwik::COMPRESSED_FILE_LOCATION . basename($file);
+
+ $phpOutputCompressionEnabled = ProxyHttp::isPhpOutputCompressed();
+ if (isset($_SERVER['HTTP_ACCEPT_ENCODING']) && !$phpOutputCompressionEnabled) {
+ $acceptEncoding = $_SERVER['HTTP_ACCEPT_ENCODING'];
+
+ if (extension_loaded('zlib') && function_exists('file_get_contents') && function_exists('file_put_contents')) {
+ if (preg_match('/(?:^|, ?)(deflate)(?:,|$)/', $acceptEncoding, $matches)) {
+ $encoding = 'deflate';
+ $filegz = $compressedFileLocation . '.deflate';
+ } else if (preg_match('/(?:^|, ?)((x-)?gzip)(?:,|$)/', $acceptEncoding, $matches)) {
+ $encoding = $matches[1];
+ $filegz = $compressedFileLocation . '.gz';
+ }
+
+ if (!empty($encoding)) {
+ // compress-on-demand and use cache
+ if (!file_exists($filegz) || ($fileModifiedTime > @filemtime($filegz))) {
+ $data = file_get_contents($file);
+
+ if ($encoding == 'deflate') {
+ $data = gzdeflate($data, 9);
+ } else if ($encoding == 'gzip' || $encoding == 'x-gzip') {
+ $data = gzencode($data, 9);
+ }
+
+ file_put_contents($filegz, $data);
+ }
+
+ $compressed = true;
+ $file = $filegz;
+ }
+ } else {
+ // manually compressed
+ $filegz = $compressedFileLocation . '.gz';
+ if (preg_match('/(?:^|, ?)((x-)?gzip)(?:,|$)/', $acceptEncoding, $matches) && file_exists($filegz) && ($fileModifiedTime < @filemtime($filegz))) {
+ $encoding = $matches[1];
+ $compressed = true;
+ $file = $filegz;
+ }
+ }
+ }
+
+ @header('Last-Modified: ' . $lastModified);
+
+ if (!$phpOutputCompressionEnabled) {
+ @header('Content-Length: ' . filesize($file));
+ }
+
+ if (!empty($contentType)) {
+ @header('Content-Type: ' . $contentType);
+ }
+
+ if ($compressed) {
+ @header('Content-Encoding: ' . $encoding);
+ }
+
+ if (!_readfile($file)) {
+ self::setHttpStatus('505 Internal server error');
+ }
+ }
+ } else {
+ self::setHttpStatus('404 Not Found');
+ }
+ }
+
+ /**
+ * Test if php output is compressed
+ *
+ * @return bool True if php output is (or suspected/likely) to be compressed
+ */
+ public static function isPhpOutputCompressed()
+ {
+ // Off = ''; On = '1'; otherwise, it's a buffer size
+ $zlibOutputCompression = ini_get('zlib.output_compression');
+
+ // could be ob_gzhandler, ob_deflatehandler, etc
+ $outputHandler = ini_get('output_handler');
+
+ // output handlers can be stacked
+ $obHandlers = array_filter(ob_list_handlers(), function ($var) {
+ return $var !== "default output handler";
+ });
+
+ // user defined handler via wrapper
+ $autoPrependFile = ini_get('auto_prepend_file');
+ $autoAppendFile = ini_get('auto_append_file');
+
+ return !empty($zlibOutputCompression) ||
+ !empty($outputHandler) ||
+ !empty($obHandlers) ||
+ !empty($autoPrependFile) ||
+ !empty($autoAppendFile);
+ }
+
+
+ /**
+ * Workaround IE bug when downloading certain document types over SSL and
+ * cache control headers are present, e.g.,
+ *
+ * Cache-Control: no-cache
+ * Cache-Control: no-store,max-age=0,must-revalidate
+ * Pragma: no-cache
+ *
+ * @see http://support.microsoft.com/kb/316431/
+ * @see RFC2616
+ *
+ * @param string $override One of "public", "private", "no-cache", or "no-store". (optional)
+ */
+ public static function overrideCacheControlHeaders($override = null)
+ {
+ if ($override || self::isHttps()) {
+ @header('Pragma: ');
+ @header('Expires: ');
+ if (in_array($override, array('public', 'private', 'no-cache', 'no-store'))) {
+ @header("Cache-Control: $override, must-revalidate");
+ } else {
+ @header('Cache-Control: must-revalidate');
+ }
+ }
+ }
+
+
+ /**
+ * Set response header, e.g., HTTP/1.0 200 Ok
+ *
+ * @param string $status Status
+ * @return bool
+ */
+ protected static function setHttpStatus($status)
+ {
+ if (substr_compare(PHP_SAPI, '-fcgi', -5)) {
+ @header($_SERVER['SERVER_PROTOCOL'] . ' ' . $status);
+ } else {
+ // FastCGI
+ @header('Status: ' . $status);
+ }
+ }
+
+} \ No newline at end of file
diff --git a/core/ReportRenderer.php b/core/ReportRenderer.php
index f724935209..3287a6e97e 100644
--- a/core/ReportRenderer.php
+++ b/core/ReportRenderer.php
@@ -11,12 +11,10 @@
namespace Piwik;
use Exception;
-use Piwik\DataTable\Simple;
+use Piwik\API\Request;
use Piwik\DataTable\Row;
-use Piwik\Piwik;
+use Piwik\DataTable\Simple;
use Piwik\DataTable;
-use Piwik\Loader;
-use Piwik\API\Request;
use Piwik\Plugins\ImageGraph\API;
/**
@@ -175,7 +173,7 @@ abstract class ReportRenderer
{
$filename = ReportRenderer::appendExtension($filename, $extension);
- Piwik::overrideCacheControlHeaders();
+ ProxyHttp::overrideCacheControlHeaders();
header('Content-Description: File Transfer');
header('Content-Type: ' . $contentType);
header('Content-Disposition: attachment; filename="' . str_replace('"', '\'', basename($filename)) . '";');
diff --git a/core/Session.php b/core/Session.php
index 16378607ed..59e02a89a2 100644
--- a/core/Session.php
+++ b/core/Session.php
@@ -11,9 +11,6 @@
namespace Piwik;
use Exception;
-use Piwik\Config;
-use Piwik\Piwik;
-use Piwik\Common;
use Piwik\Session\SaveHandler\DbTable;
use Zend_Registry;
use Zend_Session;
@@ -63,7 +60,7 @@ class Session extends Zend_Session
@ini_set('session.use_only_cookies', '1');
// advise browser that session cookie should only be sent over secure connection
- if (Piwik::isHttps()) {
+ if (ProxyHttp::isHttps()) {
@ini_set('session.cookie_secure', '1');
}
diff --git a/core/View.php b/core/View.php
index fea23de6ac..910e5b1397 100644
--- a/core/View.php
+++ b/core/View.php
@@ -134,7 +134,7 @@ class View implements ViewInterface
$this->totalNumberOfQueries = 0;
}
- Piwik::overrideCacheControlHeaders('no-store');
+ ProxyHttp::overrideCacheControlHeaders('no-store');
@header('Content-Type: ' . $this->contentType);
// always sending this header, sometimes empty, to ensure that Dashboard embed loads (which could call this header() multiple times, the last one will prevail)