diff --git a/README.md b/README.md index 43b787b2..09df5d8f 100644 --- a/README.md +++ b/README.md @@ -10,6 +10,12 @@ It uses the [Faenza icon set](http://tiheum.deviantart.com/art/Faenza-Icons-1733 ## Changelog +### v0.15.1 · *2011-09-06* + +* fixed security issues with the zipped download feature +* made zipped download optional (but enabled by default) + + ### v0.15 · *2011-09-04* * added zipped download for selected files diff --git a/build.properties b/build.properties index c5e25966..957db0e6 100644 --- a/build.properties +++ b/build.properties @@ -3,7 +3,7 @@ custom = true # project project.name = h5ai -project.version = 0.15 +project.version = 0.15.1 # src diff --git a/release/h5ai-0.15.1.tar.gz b/release/h5ai-0.15.1.tar.gz new file mode 100644 index 00000000..1136352f Binary files /dev/null and b/release/h5ai-0.15.1.tar.gz differ diff --git a/release/h5ai-0.15.zip b/release/h5ai-0.15.1.zip similarity index 85% rename from release/h5ai-0.15.zip rename to release/h5ai-0.15.1.zip index 1bf69059..17889bc8 100644 Binary files a/release/h5ai-0.15.zip and b/release/h5ai-0.15.1.zip differ diff --git a/release/h5ai-0.15.tar.gz b/release/h5ai-0.15.tar.gz deleted file mode 100644 index 45506ad8..00000000 Binary files a/release/h5ai-0.15.tar.gz and /dev/null differ diff --git a/src/h5ai/js/inc/h5ai.js b/src/h5ai/js/inc/h5ai.js index 45006e29..79818ad4 100644 --- a/src/h5ai/js/inc/h5ai.js +++ b/src/h5ai/js/inc/h5ai.js @@ -28,7 +28,9 @@ var H5ai = function (options, langs) { dateFormat: "Y-m-d H:i", ignore: ["h5ai", "h5ai.header.html", "h5ai.footer.html"], ignoreRE: ["/^\\./"], - showThumbs: true + showThumbs: true, + + zippedDownload: true }, settings = $.extend({}, defaults, options), pathClick = function (fn) { @@ -292,7 +294,7 @@ var H5ai = function (options, langs) { }); }); }, - initSelect = function () { + initZippedDownload = function () { var x = 0, y = 0, @@ -362,9 +364,11 @@ var H5ai = function (options, langs) { return false; }; - $("body>nav,body>footer,#tree,#extended a").bind("mousedown", noSelection); - $("#extended a").live("mousedown", noSelection); - $window.bind("mousedown", selectionStart); + if (settings.zippedDownload) { + $("body>nav,body>footer,#tree,#extended a").bind("mousedown", noSelection); + $("#extended a").live("mousedown", noSelection); + $window.bind("mousedown", selectionStart); + } }, init = function () { @@ -376,7 +380,7 @@ var H5ai = function (options, langs) { initLangSelector(langs); localize(langs, settings.lang, settings.useBrowserLang); initIndicators(); - initSelect(); + initZippedDownload(); }, h5ai = { settings: settings, diff --git a/src/h5ai/options.js b/src/h5ai/options.js index 85189425..b461558a 100644 --- a/src/h5ai/options.js +++ b/src/h5ai/options.js @@ -97,7 +97,13 @@ h5aiOptions = { * Only used in PHP implementation. * Show thumbnails in Icons view. */ - "showThumbs": true + "showThumbs": true, + + /* + * Enable zipped download of selected entries. Requieres + * PHP on the server. + */ + "zippedDownload": true }; @@ -117,7 +123,8 @@ h5aiLangs = { "parentDirectory": "Parent Directory", "empty": "empty", "folders": "folders", - "files": "files" + "files": "files", + "download": "download" }, "de": { @@ -130,7 +137,8 @@ h5aiLangs = { "parentDirectory": "Übergeordnetes Verzeichnis", "empty": "leer", "folders": "Ordner", - "files": "Dateien" + "files": "Dateien", + "download": "Download" }, "fr": { @@ -143,7 +151,8 @@ h5aiLangs = { "parentDirectory": "Dossier parent", "empty": "vide", "folders": "Répertoires", - "files": "Fichiers" + "files": "Fichiers", + "download": "download" }, "nl": { @@ -155,8 +164,9 @@ h5aiLangs = { "size": "Grootte", "parentDirectory": "Bovenliggende map", "empty": "lege", - "folders": "[?folders?]", - "files": "[?files?]" + "folders": "folders", + "files": "files", + "download": "download" }, "sv": { @@ -168,8 +178,9 @@ h5aiLangs = { "size": "Filstorlek", "parentDirectory": "Till överordnad mapp", "empty": "tom", - "folders": "[?folders?]", - "files": "[?files?]" + "folders": "folders", + "files": "files", + "download": "download" }, "cs": { @@ -182,7 +193,8 @@ h5aiLangs = { "parentDirectory": "Nadřazený adresář", "empty": "prázdný", "folders": "složek", - "files": "souborů" + "files": "souborů", + "download": "download" }, "sk": { @@ -195,7 +207,8 @@ h5aiLangs = { "parentDirectory": "Nadriadený priečinok", "empty": "prázdny", "folders": "priečinkov", - "files": "súborov" + "files": "súborov", + "download": "download" }, "es": { @@ -207,8 +220,9 @@ h5aiLangs = { "size": "Tamaño", "parentDirectory": "Directorio superior", "empty": "vacío", - "folders": "[?folders?]", - "files": "[?files?]" + "folders": "folders", + "files": "files", + "download": "download" }, "tr": { @@ -220,8 +234,9 @@ h5aiLangs = { "size": "Boyut", "parentDirectory": "Üst Dizin", "empty": "boş", - "folders": "[?folders?]", - "files": "[?files?]" + "folders": "folders", + "files": "files", + "download": "download" }, "pt": { @@ -234,7 +249,8 @@ h5aiLangs = { "parentDirectory": "Diretório superior", "empty": "vazio", "folders": "pastas", - "files": "arquivos" + "files": "arquivos", + "download": "download" }, "bg": { @@ -247,7 +263,8 @@ h5aiLangs = { "parentDirectory": "Предходна директория", "empty": "празно", "folders": "папки", - "files": "файлове" + "files": "файлове", + "download": "download" }, "lv": { @@ -260,7 +277,8 @@ h5aiLangs = { "parentDirectory": "Vecākdirektorijs", "empty": "tukšs", "folders": "mapes", - "files": "faili" + "files": "faili", + "download": "download" }, "zh-cn": { @@ -273,7 +291,8 @@ h5aiLangs = { "parentDirectory": "上层文件夹", "empty": "空文件夹", "folders": "文件夹", - "files": "文件" + "files": "文件", + "download": "download" }, "pl": { @@ -286,7 +305,8 @@ h5aiLangs = { "parentDirectory": "Katalog nadrzędny", "empty": "pusty", "folders": "foldery", - "files": "pliki" + "files": "pliki", + "download": "download" }, "ru": { @@ -299,6 +319,7 @@ h5aiLangs = { "parentDirectory": "Главная директория", "empty": "пусто", "folders": "папки", - "files": "файлы" + "files": "файлы", + "download": "download" } }; diff --git a/src/h5ai/php/h5ai.php b/src/h5ai/php/h5ai.php index be8ac865..b50ebfbb 100644 --- a/src/h5ai/php/h5ai.php +++ b/src/h5ai/php/h5ai.php @@ -27,7 +27,7 @@ class H5ai { $this->sortOrder = array( "column" => array_key_exists("col", $_REQUEST) ? $_REQUEST["col"] : $defaultSortOrder["column"], "ascending" => array_key_exists("asc", $_REQUEST) ? $_REQUEST["asc"] !== "false" : $defaultSortOrder["ascending"] - ); + ); $this->dateFormat = $this->options["options"]["dateFormat"]; $this->view = array_key_exists("view", $_REQUEST) ? $_REQUEST["view"] : $this->options["options"]["viewmodes"][0]; if (!in_array($this->view, H5ai::$VIEWMODES)) { @@ -96,7 +96,14 @@ class H5ai { if ($absPath === null) { return $this->absHref; } - return $this->normalizePath(rawurlencode(preg_replace("!^" . $this->docRoot . "!", "", $absPath)), $endWithSlash); + $absHref = preg_replace("!^" . $this->docRoot . "!", "", $absPath); + $parts = explode("/", $absHref); + $encodedParts = array(); + foreach ($parts as $part) { + $encodedParts[] = rawurlencode($part); + } + $endodedAbsHref = implode("/", $encodedParts); + return $this->normalizePath($endodedAbsHref, $endWithSlash); } public function getAbsPath($absHref = null) { diff --git a/src/h5ai/php/zipcontent.php b/src/h5ai/php/zipcontent.php index 9833e103..76ad5ba4 100644 --- a/src/h5ai/php/zipcontent.php +++ b/src/h5ai/php/zipcontent.php @@ -11,14 +11,18 @@ require_once "zipit.php"; $h5ai = new H5ai(); $zipit = new ZipIt($h5ai); -$files = explode(":", trim($_REQUEST["hrefs"])); +$hrefs = explode(":", trim($_REQUEST["hrefs"])); -$zipFile = $zipit->zip($files); +$zipFile = $zipit->zip($hrefs); -header("Content-Disposition: attachment; filename=\"h5ai-selection.zip\""); -header("Content-Type: application/force-download"); -header("Content-Length: " . filesize($zipFile)); -header("Connection: close"); -readfile($zipFile); +if ($zipFile !== false) { + header("Content-Disposition: attachment; filename=\"h5ai-selection.zip\""); + header("Content-Type: application/force-download"); + header("Content-Length: " . filesize($zipFile)); + header("Connection: close"); + readfile($zipFile); +} else { + echo "sorry, something went wrong while building the zip."; +} ?> \ No newline at end of file diff --git a/src/h5ai/php/zipit.php b/src/h5ai/php/zipit.php index 795aa370..54cfec38 100644 --- a/src/h5ai/php/zipit.php +++ b/src/h5ai/php/zipit.php @@ -18,12 +18,16 @@ class ZipIt { } foreach ($hrefs as $href) { - $localFile = $this->h5ai->getAbsPath($href); - $file = preg_replace("!^" . $this->h5ai->getDocRoot() . "!", "", $localFile); - if (is_dir($localFile)) { - $this->zipDir($zip, $localFile, $file); - } else { - $this->zipFile($zip, $localFile, $file); + $d = dirname($href); + $n = basename($href); + if ($this->h5ai->getHttpCode($this->h5ai->getAbsHref($d)) === "h5ai" && !$this->h5ai->ignoreThisFile($n)) { + $localFile = $this->h5ai->getAbsPath($href); + $file = preg_replace("!^" . $this->h5ai->getDocRoot() . "!", "", $localFile); + if (is_dir($localFile)) { + $this->zipDir($zip, $localFile, $file); + } else { + $this->zipFile($zip, $localFile, $file); + } } } @@ -39,16 +43,18 @@ class ZipIt { } private function zipDir($zip, $localDir, $dir) { - - $zip->addEmptyDir($dir); - $files = $this->h5ai->readDir($localDir); - foreach ($files as $file) { - $localFile = $localDir . "/" . $file; - $file = $dir . "/" . $file; - if (is_dir($localFile)) { - $this->zipDir($zip, $localFile, $file); - } else { - $this->zipFile($zip, $localFile, $file); + + if ($this->h5ai->getHttpCode($this->h5ai->getAbsHref($localDir)) === "h5ai") { + $zip->addEmptyDir($dir); + $files = $this->h5ai->readDir($localDir); + foreach ($files as $file) { + $localFile = $localDir . "/" . $file; + $file = $dir . "/" . $file; + if (is_dir($localFile)) { + $this->zipDir($zip, $localFile, $file); + } else { + $this->zipFile($zip, $localFile, $file); + } } } }