diff --git a/README.md b/README.md
index 99aa3ffc..e7329f82 100644
--- a/README.md
+++ b/README.md
@@ -54,6 +54,13 @@ It profits from these great projects:
**h5ai** uses [semantic versioning](http://semver.org/).
+### v0.24.1 - *2014-04-09*
+
+* security fixes! (issues #268, #269)
+* language updates (`fi`, `fr`, `hi`, `it`, `zh-tw`)
+* fixes WinOS command detection
+
+
### v0.24.0 - *2013-09-04*
* updates image and text preview
diff --git a/makefile.js b/makefile.js
index bf3e5c25..194107b5 100644
--- a/makefile.js
+++ b/makefile.js
@@ -14,7 +14,7 @@ module.exports = function (make) {
$ = make.fQuery,
mapSrc = $.map.p(src, build).s('.less', '.css').s('.jade', ''),
- mapRoot = $.map.p(root, build);
+ mapRoot = $.map.p(root, path.join(build, '_h5ai'));
make.version('>=0.10.0');
@@ -88,30 +88,30 @@ module.exports = function (make) {
var header = '/* ' + pkg.name + ' ' + pkg.version + ' - ' + pkg.url + ' */';
$(src + ': _h5ai/client/js/*.js')
- .modified(mapSrc, $(src + ': _h5ai/client/js/**'))
+ .newerThan(mapSrc, $(src + ': _h5ai/client/js/**'))
.includify()
.uglifyjs({header: header})
.WRITE(mapSrc);
$(src + ': _h5ai/client/css/*.less')
- .modified(mapSrc, $(src + ': _h5ai/client/css/**'))
+ .newerThan(mapSrc, $(src + ': _h5ai/client/css/**'))
.less()
.cssmin({header: header})
.WRITE(mapSrc);
$(src + ': **/*.jade')
- .modified(mapSrc)
+ .newerThan(mapSrc)
.handlebars(make.env)
.jade()
.WRITE(mapSrc);
$(src + ': **, ! _h5ai/client/js/**, ! _h5ai/client/css/**, ! **/*.jade')
- .modified(mapSrc)
+ .newerThan(mapSrc)
.handlebars(make.env)
.WRITE(mapSrc);
- $(root + ': README*, LICENSE*')
- .modified(mapRoot)
+ $(root + ': *.md')
+ .newerThan(mapRoot)
.WRITE(mapRoot);
});
@@ -119,30 +119,30 @@ module.exports = function (make) {
make.target('build-uncompressed', ['check-version'], 'build all updated files without compression').sync(function () {
$(src + ': _h5ai/client/js/*.js')
- .modified(mapSrc, $(src + ': _h5ai/client/js/**'))
+ .newerThan(mapSrc, $(src + ': _h5ai/client/js/**'))
.includify()
// .uglifyjs()
.WRITE(mapSrc);
$(src + ': _h5ai/client/css/*.less')
- .modified(mapSrc, $(src + ': _h5ai/client/css/**'))
+ .newerThan(mapSrc, $(src + ': _h5ai/client/css/**'))
.less()
// .cssmin()
.WRITE(mapSrc);
$(src + ': **/*.jade')
- .modified(mapSrc)
+ .newerThan(mapSrc)
.handlebars(make.env)
.jade()
.WRITE(mapSrc);
$(src + ': **, ! _h5ai/client/js/**, ! _h5ai/client/css/**, ! **/*.jade')
- .modified(mapSrc)
+ .newerThan(mapSrc)
.handlebars(make.env)
.WRITE(mapSrc);
- $(root + ': README*, LICENSE*')
- .modified(mapRoot)
+ $(root + ': *.md')
+ .newerThan(mapRoot)
.WRITE(mapRoot);
});
diff --git a/package.json b/package.json
index b2c56528..70451e75 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "h5ai",
- "version": "0.24.0",
+ "version": "0.24.1",
"description": "a modern HTTP web server index",
"url": "http://larsjung.de/h5ai/",
"author": "Lars Jung",
diff --git a/src/_h5ai/client/css/inc/fallback.less b/src/_h5ai/client/css/inc/fallback.less
index f73ef3eb..b779222c 100644
--- a/src/_h5ai/client/css/inc/fallback.less
+++ b/src/_h5ai/client/css/inc/fallback.less
@@ -16,31 +16,15 @@
}
th {
padding-bottom: 18px;
-
- a, a:visited {
- color: #555;
- font-weight: normal;
- text-decoration: none;
- cursor: pointer;
- opacity: 0.4;
- .transition(all 0.2s ease-in-out);
-
- &:hover {
- color: #555;
- opacity: 0.9;
- }
- }
- span {
- color: #555;
- font-weight: normal;
- opacity: 0.4;
- }
+ color: #555;
+ font-weight: normal;
+ opacity: 0.4;
}
td {
border-bottom: 1px solid @col-border;
overflow: hidden;
white-space: nowrap;
- font-size: 16px;
+ font-size: 15px;
a, a:active, a:visited {
display: block;
diff --git a/src/_h5ai/client/css/inc/h5ai-info.less b/src/_h5ai/client/css/inc/h5ai-info.less
index d231be17..cafce35e 100644
--- a/src/_h5ai/client/css/inc/h5ai-info.less
+++ b/src/_h5ai/client/css/inc/h5ai-info.less
@@ -68,31 +68,33 @@ body#h5ai-info {
margin: 0;
padding: 0;
- .test-label {
- display: inline-block;
- width: 350px;
- }
- .test-result {
- display: inline-block;
- width: 70px;
- text-align: right;
- font-weight: bold;
- color: #aaa;
+ .test {
+ .label {
+ display: inline-block;
+ width: 350px;
+ }
+ .result {
+ display: inline-block;
+ width: 70px;
+ text-align: right;
+ font-weight: bold;
+ color: #aaa;
- &.test-passed {
- color: #5a5;
+ &.passed {
+ color: #5a5;
+ }
+ &.failed {
+ color: #a55;
+ }
}
- &.test-failed {
- color: #a55;
+ .info {
+ margin: 4px 0 12px 12px;
+ font-size: 0.7em;
+ color: #aaa;
+ width: 350px;
+ line-height: 1.2em;
}
}
- .test-info {
- margin: 4px 0 12px 12px;
- font-size: 0.7em;
- color: #aaa;
- width: 350px;
- line-height: 1.2em;
- }
}
#bottombar {
diff --git a/src/_h5ai/client/js/inc/core/server.js b/src/_h5ai/client/js/inc/core/server.js
index 3ca818f6..528c943c 100644
--- a/src/_h5ai/client/js/inc/core/server.js
+++ b/src/_h5ai/client/js/inc/core/server.js
@@ -23,6 +23,22 @@ modulejs.define('core/server', ['$', '_', 'config', 'core/location'], function (
} else {
callback();
}
+ },
+
+ formRequest: function (data) {
+
+ var $form = $('
')
+ .attr('action', location.getAbsHref());
+
+ _.each(data, function (val, key) {
+
+ $('')
+ .attr('name', key)
+ .attr('value', val)
+ .appendTo($form);
+ });
+
+ $form.appendTo('body').submit().remove();
}
});
diff --git a/src/_h5ai/client/js/inc/ext/download.js b/src/_h5ai/client/js/inc/ext/download.js
index 4b1278d7..8d5b6881 100644
--- a/src/_h5ai/client/js/inc/ext/download.js
+++ b/src/_h5ai/client/js/inc/ext/download.js
@@ -1,5 +1,5 @@
-modulejs.define('ext/download', ['_', '$', 'core/settings', 'core/resource', 'core/event', 'core/server', 'core/location'], function (_, $, allsettings, resource, event, server, location) {
+modulejs.define('ext/download', ['_', '$', 'core/settings', 'core/resource', 'core/event', 'core/location', 'core/server'], function (_, $, allsettings, resource, event, location, server) {
var settings = _.extend({
enabled: false,
@@ -7,8 +7,6 @@ modulejs.define('ext/download', ['_', '$', 'core/settings', 'core/resource', 'co
packageName: 'package'
}, allsettings.download),
- // formats = ['tar', 'zip'],
-
downloadBtnTemplate = '' +
'' +
'
' +
@@ -16,25 +14,14 @@ modulejs.define('ext/download', ['_', '$', 'core/settings', 'core/resource', 'co
'' +
'',
- selectedHrefsStr = '',
- $download, $img,
-
- failed = function () {
-
- $download.addClass('failed');
- setTimeout(function () {
- $download.removeClass('failed');
- }, 1000);
- },
+ selectedItems = [],
onSelection = function (items) {
- selectedHrefsStr = '';
- if (items.length) {
- selectedHrefsStr = _.map(items, function (item) {
+ var $download = $('#download');
- return item.absHref;
- }).join('|:|');
+ selectedItems = items.slice(0);
+ if (selectedItems.length) {
$download.appendTo('#navbar').show();
} else {
$download.hide();
@@ -49,26 +36,21 @@ modulejs.define('ext/download', ['_', '$', 'core/settings', 'core/resource', 'co
action: 'download',
as: (settings.packageName || location.getItem().label) + '.' + extension,
type: type,
- hrefs: selectedHrefsStr
- },
- $form = $('');
+ hrefs: _.pluck(selectedItems, 'absHref').join('|:|')
+ };
- for (var key in query) {
- $form.append('');
- }
- $form.appendTo('body').submit().remove();
+ server.formRequest(query);
},
init = function () {
- if (!settings.enabled || !server.api) {
+ if (!settings.enabled) {
return;
}
- $download = $(downloadBtnTemplate)
+ $(downloadBtnTemplate)
.find('a').on('click', onClick).end()
.appendTo('#navbar');
- $img = $download.find('img');
event.sub('selection', onSelection);
};
diff --git a/src/_h5ai/client/js/inc/info.js b/src/_h5ai/client/js/inc/info.js
index 54bb59cc..8097b7f8 100644
--- a/src/_h5ai/client/js/inc/info.js
+++ b/src/_h5ai/client/js/inc/info.js
@@ -1,14 +1,14 @@
modulejs.define('info', ['$'], function ($) {
- var setCheckResult = function (id, result) {
+ var setCheckResult = function (el, result) {
- var $result = $(id).find('.test-result');
+ var $result = $(el).find('.result');
if (result) {
- $result.addClass('test-passed').text('yes');
+ $result.addClass('passed').text('yes');
} else {
- $result.addClass('test-failed').text('no');
+ $result.addClass('failed').text('no');
}
},
@@ -22,7 +22,7 @@ modulejs.define('info', ['$'], function ($) {
setCheckResult(this, json.checks[$(this).data('id')]);
});
- $('.test.php .test-result').text(json.checks['phpversion']);
+ $('.test.php .result').text(json.checks['phpversion']);
}
});
};
diff --git a/src/_h5ai/conf/l10n/fi.json b/src/_h5ai/conf/l10n/fi.json
new file mode 100644
index 00000000..c6715bf0
--- /dev/null
+++ b/src/_h5ai/conf/l10n/fi.json
@@ -0,0 +1,19 @@
+{
+ "lang": "finnish",
+ "details": "tiedot",
+ "list": "lista",
+ "grid": "ruudukko",
+ "icons": "ikonit",
+ "name": "Nimi",
+ "lastModified": "Viimeksi muokattu",
+ "size": "Koko",
+ "parentDirectory": "Ylähakemisto",
+ "empty": "tyhjä",
+ "folders": "hakemistoa",
+ "files": "tiedostoa",
+ "download": "lataa",
+ "noMatch": "ei osumia",
+ "dateFormat": "DD.MM.YYYY HH:mm",
+ "filter": "suodata",
+ "delete": "poista"
+}
diff --git a/src/_h5ai/conf/l10n/fr.json b/src/_h5ai/conf/l10n/fr.json
index ef29b765..e2431cd1 100644
--- a/src/_h5ai/conf/l10n/fr.json
+++ b/src/_h5ai/conf/l10n/fr.json
@@ -1,6 +1,8 @@
{
"lang": "français",
"details": "détails",
+ "list": "liste",
+ "grid": "grille",
"icons": "icônes",
"name": "Nom",
"lastModified": "Dernière modification",
@@ -14,4 +16,4 @@
"dateFormat": "DD/MM/YYYY HH:mm",
"filter": "filtre",
"delete": "supprimer"
-}
\ No newline at end of file
+}
diff --git a/src/_h5ai/conf/l10n/hi.json b/src/_h5ai/conf/l10n/hi.json
new file mode 100644
index 00000000..a6b4f619
--- /dev/null
+++ b/src/_h5ai/conf/l10n/hi.json
@@ -0,0 +1,19 @@
+{
+ "lang": "हिंदी",
+ "details": "विस्तार",
+ "icons": "आइकॉन",
+ "name": "नाम",
+ "lastModified": "पिछला परिवर्तन",
+ "size": "माप",
+ "parentDirectory": "मूल डायरेक्टरी",
+ "empty": "खाली",
+ "folders": "फोल्डर",
+ "files": "फ़ाइलें",
+ "download": "डाउनलोड",
+ "list": "सूची",
+ "grid": "ग्रिड",
+ "noMatch": "कोई समानता नहीं",
+ "dateFormat": "DD.MM.YYYY HH:mm",
+ "filter": "फ़िल्टर",
+ "delete": "हटाओ"
+}
diff --git a/src/_h5ai/conf/l10n/it.json b/src/_h5ai/conf/l10n/it.json
index 4e733887..6f4cb90f 100644
--- a/src/_h5ai/conf/l10n/it.json
+++ b/src/_h5ai/conf/l10n/it.json
@@ -1,6 +1,8 @@
{
"lang": "italiano",
"details": "dettagli",
+ "list": "lista",
+ "grid": "griglia",
"icons": "icone",
"name": "Nome",
"lastModified": "Ultima modifica",
@@ -8,5 +10,10 @@
"parentDirectory": "Cartella Superiore",
"empty": "vuota",
"folders": "cartelle",
- "files": "file"
+ "files": "file",
+ "download": "download",
+ "noMatch": "nessun risultato",
+ "dateFormat": "DD-MM-YYYY HH:mm",
+ "filter": "filtra",
+ "delete": "elimina"
}
\ No newline at end of file
diff --git a/src/_h5ai/conf/l10n/zh-tw.json b/src/_h5ai/conf/l10n/zh-tw.json
index 2ff1ab01..1170f347 100644
--- a/src/_h5ai/conf/l10n/zh-tw.json
+++ b/src/_h5ai/conf/l10n/zh-tw.json
@@ -1,6 +1,8 @@
{
"lang": "正體中文",
"details": "詳細資料",
+ "list": "清單",
+ "grid": "網格",
"icons": "圖示",
"name": "檔名",
"lastModified": "上次修改",
@@ -9,5 +11,9 @@
"empty": "空資料夾",
"folders": "資料夾",
"files": "檔案",
- "download": "下載"
-}
\ No newline at end of file
+ "download": "下載",
+ "noMatch": "沒有符合的檔案",
+ "dateFormat": "YYYY-MM-DD HH:mm", /* syntax as specified on http://momentjs.com */
+ "filter": "過濾",
+ "delete": "刪除"
+}
diff --git a/src/_h5ai/conf/options.json b/src/_h5ai/conf/options.json
index 12f3f40c..eb8671c6 100644
--- a/src/_h5ai/conf/options.json
+++ b/src/_h5ai/conf/options.json
@@ -159,9 +159,9 @@ Options
},
/*
- Localization, for example "en", "de" etc. - see "langs" below for
- possible values. Adjust it to your needs. If lang is not found in
- "langs" it defaults to "en".
+ Localization, for example "en", "de" etc. - see "_h5ai/conf/l10n" folder for
+ possible values. Adjust it to your needs. If lang is not found
+ it defaults to "en".
- lang: default language
- useBroserLang: boolean, try to use browser language
@@ -188,7 +188,7 @@ Options
2: mode, servername and -version
*/
"mode": {
- "enabled": false,
+ "enabled": true,
"display": 2
},
diff --git a/src/_h5ai/conf/types.json b/src/_h5ai/conf/types.json
index bf0f5f1a..3fa61997 100644
--- a/src/_h5ai/conf/types.json
+++ b/src/_h5ai/conf/types.json
@@ -67,7 +67,7 @@ File types mapped to file extensions
"tiff": [".tiff"],
"unknown": [],
"vcal": [".vcal"],
- "video": [".avi", ".flv", ".mkv", ".mov", ".m4v", ".mp4", ".mpg", ".rm", ".swf", ".vob", ".wmv"],
+ "video": [".avi", ".flv", ".mkv", ".mov", ".m4v", ".mp4", ".mpg", ".rm", ".swf", ".ts", ".vob", ".wmv"],
"xml": [".xml"],
"zip": [".7z", ".bz2", ".jar", ".lzma", ".war", ".z", ".Z", ".zip"]
}
diff --git a/src/_h5ai/index.html.jade b/src/_h5ai/index.html.jade
index eea96a56..e09cbed6 100644
--- a/src/_h5ai/index.html.jade
+++ b/src/_h5ai/index.html.jade
@@ -33,53 +33,53 @@ html.no-js.browser( lang="en" )
h2 Server Details
ul#tests
li.test.php( data-id="php" )
- span.test-label PHP version
- span.test-result ?
- div.test-info PHP version >= 5.2.1
+ span.label PHP version
+ span.result ?
+ div.info PHP version >= 5.2.1
li.test( data-id="cache" )
- span.test-label Cache directory
- span.test-result ?
- div.test-info Web server has write access
+ span.label Cache directory
+ span.result ?
+ div.info Web server has write access
li.test( data-id="thumbs" )
- span.test-label Image thumbs
- span.test-result ?
- div.test-info PHP GD extension with JPEG support available
+ span.label Image thumbs
+ span.result ?
+ div.info PHP GD extension with JPEG support available
li.test( data-id="exif" )
- span.test-label Use EXIF thumbs
- span.test-result ?
- div.test-info PHP EXIF extension available
+ span.label Use EXIF thumbs
+ span.result ?
+ div.info PHP EXIF extension available
li.test( data-id="ffmpeg" )
- span.test-label Movie thumbs
- span.test-result ?
- div.test-info
+ span.label Movie thumbs
+ span.result ?
+ div.info
| Command line program
code ffmpeg
| available
li.test( data-id="convert" )
- span.test-label PDF thumbs
- span.test-result ?
- div.test-info
+ span.label PDF thumbs
+ span.result ?
+ div.info
| Command line program
code convert
| available
li.test( data-id="tar" )
- span.test-label Shell tar
- span.test-result ?
- div.test-info
+ span.label Shell tar
+ span.result ?
+ div.info
| Command line program
code tar
| available
li.test( data-id="zip" )
- span.test-label Shell zip
- span.test-result ?
- div.test-info
+ span.label Shell zip
+ span.result ?
+ div.info
| Command line program
code zip
| available
li.test( data-id="du" )
- span.test-label Folder sizes
- span.test-result ?
- div.test-info
+ span.label Folder sizes
+ span.result ?
+ div.info
| Command line program
code du
| available
diff --git a/src/_h5ai/server/php/inc/App.php b/src/_h5ai/server/php/inc/App.php
index c353f3c9..a292d71d 100644
--- a/src/_h5ai/server/php/inc/App.php
+++ b/src/_h5ai/server/php/inc/App.php
@@ -137,7 +137,7 @@ class App {
$abs_path = $this->get_abs_path($abs_href);
- if (!is_dir($abs_path)) {
+ if (!is_dir($abs_path) || strpos($abs_path, '../') || strpos($abs_path, '/..') || $abs_path == '..') {
return 500;
}
@@ -170,6 +170,11 @@ class App {
public function get_items($abs_href, $what) {
+ $code = $this->get_http_code($abs_href);
+ if ($code != App::$MAGIC_SEQUENCE) {
+ return array();
+ }
+
$cache = array();
$folder = Item::get($this, $this->get_abs_path($abs_href), $cache);
@@ -207,20 +212,34 @@ class App {
uasort($items, array("Item", "cmp"));
$html = "";
- $html .= " | Name | Last modified | Size |
";
+
+ $html .= "";
+ $html .= " | ";
+ $html .= "Name | ";
+ $html .= "Last modified | ";
+ $html .= "Size | ";
+ $html .= "
";
+
if ($folder->get_parent($cache)) {
- $html .= " app_abs_href . "client/icons/96/folder-parent.png\" alt=\"folder-parent\"/> | Parent Directory | | |
";
+ $html .= "";
+ $html .= " | ";
+ $html .= "Parent Directory | ";
+ $html .= " | ";
+ $html .= " | ";
+ $html .= "
";
}
+
foreach ($items as $item) {
$type = $item->is_folder ? "folder" : "default";
$html .= "";
- $html .= " app_abs_href . "client/icons/96/" . $type . ".png\" alt=\"" . $type . "\"/> | ";
- $html .= "abs_href . "\">" . basename($item->abs_path) . " | ";
+ $html .= " | ";
+ $html .= "" . basename($item->abs_path) . " | ";
$html .= "" . date("Y-m-d H:i", $item->date) . " | ";
$html .= "" . ($item->size !== null ? intval($item->size / 1000) . " KB" : "" ) . " | ";
$html .= "
";
}
+
$html .= "
";
return $html;
@@ -282,11 +301,19 @@ class App {
}
$exif = function_exists("exif_thumbnail");
$cache = @is_writable($this->get_cache_abs_path());
- $tar = @preg_match("/tar(.exe)?$/i", `command -v tar`) > 0;
- $zip = @preg_match("/zip(.exe)?$/i", `command -v zip`) > 0;
- $convert = @preg_match("/convert(.exe)?$/i", `command -v convert`) > 0;
- $ffmpeg = @preg_match("/ffmpeg(.exe)?$/i", `command -v ffmpeg`) > 0;
- $du = @preg_match("/du(.exe)?$/i", `command -v du`) > 0;
+ if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') {
+ $tar = @preg_match("/tar(.exe)?$/i", `which tar`) > 0;
+ $zip = @preg_match("/zip(.exe)?$/i", `which zip`) > 0;
+ $convert = @preg_match("/convert(.exe)?$/i", `which convert`) > 0;
+ $ffmpeg = @preg_match("/ffmpeg(.exe)?$/i", `which ffmpeg`) > 0;
+ $du = @preg_match("/du(.exe)?$/i", `which du`) > 0;
+ } else {
+ $tar = @preg_match("/tar(.exe)?$/i", `command -v tar`) > 0;
+ $zip = @preg_match("/zip(.exe)?$/i", `command -v zip`) > 0;
+ $convert = @preg_match("/convert(.exe)?$/i", `command -v convert`) > 0;
+ $ffmpeg = @preg_match("/ffmpeg(.exe)?$/i", `command -v ffmpeg`) > 0;
+ $du = @preg_match("/du(.exe)?$/i", `command -v du`) > 0;
+ }
return array(
"idx" => $this->app_abs_href . "server/php/index.php",
diff --git a/src/_h5ai/server/php/inc/Thumb.php b/src/_h5ai/server/php/inc/Thumb.php
index 5912f376..c4a878f3 100644
--- a/src/_h5ai/server/php/inc/Thumb.php
+++ b/src/_h5ai/server/php/inc/Thumb.php
@@ -2,7 +2,7 @@
class Thumb {
- private static $FFMPEG_CMD = "ffmpeg -i [SOURCE] -an -ss 3 -vframes 1 [TARGET]";
+ private static $FFMPEG_CMD = "ffmpeg -ss 0:01:00 -i [SOURCE] -an -vframes 1 [TARGET]";
private static $CONVERT_CMD = "convert -strip [SOURCE][0] [TARGET]";
private static $THUMB_CACHE = "thumbs";