Merge branch 'develop'

This commit is contained in:
Lars Jung
2012-02-24 17:02:46 +01:00
61 changed files with 6066 additions and 3659 deletions

32
.gitignore vendored
View File

@@ -4,10 +4,8 @@ build
build.local.*
release
# Eclipse
.classpath
.ant-targets-*
# Sublime
*.sublime-*
# Numerous always-ignore extensions
*.diff
@@ -20,29 +18,3 @@ release
*.vi
*~
*.sass-cache
# OS or Editor folders
.DS_Store
.cache
.project
.settings
.tmproj
nbproject
Thumbs.db
# Dreamweaver added files
_notes
dwsync.xml
# Komodo
*.komodoproject
.komodotools
# Folders to ignore
.hg
.svn
.CVS
intermediate
publish
.idea

View File

@@ -1,4 +1,4 @@
Copyright (c) 2011 Lars Jung, http://larsjung.de
Copyright (c) 2012 Lars Jung, http://larsjung.de
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in

View File

@@ -23,11 +23,34 @@ h5ai is provided under the terms of the [MIT License](http://github.com/lrsjng/h
* [jQuery](http://jquery.com) (MIT/GPL)
* [jQuery.mousewheel](http://github.com/brandonaaron/jquery-mousewheel) (MIT)
* [modernizr](http://www.modernizr.com) (MIT/BSD)
* [qrcode](http://www.d-project.com/qrcode/index.html) (MIT)
## Changelog
### v0.17 · *2011-11-28*
### v0.18 - *2012-02-24*
* adds optional QRCode display
* adds optional filtering for displayed files and folders
* updates design
* improves zipped download
* adds support for zipped download of htaccess restricted files
* changes h5ai.htaccess
* custom headers/footers are now optional and disabled by default
* fixes problems with folder recognition in the JS version
* fixes include problems in PHP version
* fixes path problems on servers running on Windows in PHP version
* fixes broken links in custom headers/footers while zipped download enabled
* fixes problems with thumbnails for files with single or double quotes in filename
* improves url hashes
* updates year in `LICENSE.TXT`
* updates es translation
* adds zh-tw translation by [Yao Wei](http://github.com/medicalwei)
* updates zh-cn translation
### v0.17 - *2011-11-28*
* h5ai is now located in `_h5ai` to reduce collisions
* switches from HTML5 Boilerplate reset to normalization
@@ -43,7 +66,7 @@ h5ai is provided under the terms of the [MIT License](http://github.com/lrsjng/h
* adds support for use with userdir (requires some manual changes)
### v0.16 · *2011-11-02*
### v0.16 - *2011-11-02*
* sorts translations in `options.js`
* improves HTML head sections
@@ -57,25 +80,25 @@ h5ai is provided under the terms of the [MIT License](http://github.com/lrsjng/h
* image thumbs and zipped download is disabled by default now, but works fine if PHP is configured
### v0.15.2 · *2011-09-18*
### v0.15.2 - *2011-09-18*
* added it translation by [Salvo Gentile](http://github.com/SalvoGentile) and [Marco Patriarca](http://github.com/Fexys)
* switched build process from scripp to wepp
### v0.15.1 · *2011-09-06*
### 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*
### v0.15 - *2011-09-04*
* added zipped download for selected files
* cleaned and refactored
### v0.14.1 · *2011-09-01*
### v0.14.1 - *2011-09-01*
* display meta information in bottom bar (icon view)
* added zh-cn translation by [Dongsheng Cai](http://github.com/dongsheng)
@@ -83,18 +106,18 @@ h5ai is provided under the terms of the [MIT License](http://github.com/lrsjng/h
* added ru translation by Богдан Илюхин
### v0.14 · *2011-08-16*
### v0.14 - *2011-08-16*
* added image thumbnails for PHP version
* new option `slideTree` to turn off auto slide in
### v0.13.2 · *2011-08-12*
### v0.13.2 - *2011-08-12*
* changes in `/h5ai/.htaccess` ... PHP configuration ...
### v0.13.1 · *2011-08-12*
### v0.13.1 - *2011-08-12*
* ~~hopefully fixed that PHP doesn't get interpreted~~ :/
* fixed initial tree display
@@ -103,7 +126,7 @@ h5ai is provided under the terms of the [MIT License](http://github.com/lrsjng/h
* added lv translation by Sandis Veinbergs
### v0.13 · *2011-08-06*
### v0.13 - *2011-08-06*
* added PHP implementation! (should work with PHP 5.2+)
* added new options
@@ -117,42 +140,42 @@ h5ai is provided under the terms of the [MIT License](http://github.com/lrsjng/h
* added bg translation by George Andonov
### v0.12.3 · *2011-07-30*
### v0.12.3 - *2011-07-30*
* added tr translation by [Batuhan Icoz](http://github.com/batuhanicoz)
### v0.12.2 · *2011-07-30*
### v0.12.2 - *2011-07-30*
* added es translation by Jose David Calderon Serrano
### v0.12.1 · *2011-07-29*
### v0.12.1 - *2011-07-29*
* fixed unchecked use of console.log
### v0.12 · *2011-07-28*
### v0.12 - *2011-07-28*
* improved performance
### v0.11 · *2011-07-27*
### v0.11 - *2011-07-27*
* changed license to MIT license, see `LICENSE.txt`
### v0.10.2 · *2011-07-26*
### v0.10.2 - *2011-07-26*
* improved tree scrollbar
### v0.10.1 · *2011-07-24*
### v0.10.1 - *2011-07-24*
* fixed problems with ' in links
### v0.10 · *2011-07-24*
### v0.10 - *2011-07-24*
* fixed problems with XAMPP on Windows (see `dot.htaccess` comments for instructions)
* fixed tree fade-in-fade-out effect for small displays ([issue #6](http://github.com/lrsjng/h5ai/issues/6))
@@ -161,7 +184,7 @@ h5ai is provided under the terms of the [MIT License](http://github.com/lrsjng/h
* added "empty" to localization (hope Google Translate did a good job here)
### v0.9 · *2011-07-18*
### v0.9 - *2011-07-18*
* linked hover states between crumb, extended view and tree
* fixed size of tree view (now there's a ugly scrollbar, hopefully will be fixed)
@@ -172,7 +195,7 @@ h5ai is provided under the terms of the [MIT License](http://github.com/lrsjng/h
* added sv translation by Oscar Carlsson
### v0.8 · *2011-07-08*
### v0.8 - *2011-07-08*
* removed slashes from folder labels
* optionally rename parent folder entries to real folder names, see `options.js`
@@ -181,19 +204,19 @@ h5ai is provided under the terms of the [MIT License](http://github.com/lrsjng/h
* refactored js a lot (again...)
### v0.7 · *2011-07-07*
### v0.7 - *2011-07-07*
* removed shadows
* smarter tree side bar
### v0.6 · *2011-07-05*
### v0.6 - *2011-07-05*
* refactored js
* added localization, see `options.js`
### v0.5.3 · *2011-07-04*
### v0.5.3 - *2011-07-04*
* refactored js
* added basic options support via `options.js`
@@ -201,24 +224,24 @@ h5ai is provided under the terms of the [MIT License](http://github.com/lrsjng/h
* optional tree sidebar
### v0.5.2 · *2011-07-02*
### v0.5.2 - *2011-07-02*
* details view adjusts to window width
* linked icon for *.gz and *.bz2
### v0.5.1 · *2011-07-01*
### v0.5.1 - *2011-07-01*
* disabled tree sidebar for now, since it had unwanted side effects
### v0.5 · *2011-07-01*
### v0.5 - *2011-07-01*
* added tree sidebar
* some refactorings
### v0.4 · *2011-06-27*
### v0.4 - *2011-06-27*
* added better fallback, in case JavaScript is disabled
* rewrote js, fixed middle-button click etc. problems
@@ -227,20 +250,20 @@ h5ai is provided under the terms of the [MIT License](http://github.com/lrsjng/h
* updated dot.access
### v0.3.2 · *2011-06-24*
### v0.3.2 - *2011-06-24*
* removed lib versions from file names
* added 'empty' indicator for icons view
### v0.3.1 · *2011-06-24*
### v0.3.1 - *2011-06-24*
* refactored js
* added `folderClick` and `fileClick` callback hooks
* fixed .emtpy style
### v0.3 · *2011-06-23*
### v0.3 - *2011-06-23*
* included build stuff, files previously found in the base directory are now located in folder `target`
* styles and scripts are now minified
@@ -248,20 +271,20 @@ h5ai is provided under the terms of the [MIT License](http://github.com/lrsjng/h
* updated jQuery to version 1.6.1
### v0.2.3 · *2011-06-17*
### v0.2.3 - *2011-06-17*
* more refactoring in main.js
* ~~added custom js support, and global includes~~ *removed, only custom top and bottom sections supported*
### v0.2.2 · *2011-06-16*
### v0.2.2 - *2011-06-16*
* refactored a lot, added some comments
* included fixes from [NumEricR](http://github.com/NumEricR)
* added top/bottom message support, only basicly styled
### v0.2.1 · *2011-06-16*
### v0.2.1 - *2011-06-16*
* fixed croped filenames
* fixed missing .png extension in header
@@ -269,7 +292,7 @@ h5ai is provided under the terms of the [MIT License](http://github.com/lrsjng/h
* added changelog
### v0.2 · *2011-06-15*
### v0.2 - *2011-06-15*
* added icon view

View File

@@ -3,7 +3,7 @@ custom = true
# project
project.name = h5ai
project.version = 0.17
project.version = 0.18
# src
@@ -16,8 +16,6 @@ release.dir = release
# tools
tool.wepp = tools/wepp
tool.wepp = wepp
tool.jslint = jslint
tool.jshint = jshint
tool.jsxint.file = ${build.dir}/_h5ai/js/main-js.js

View File

@@ -5,8 +5,6 @@
default="release"
>
<import file="tools/wepp.ant.xml" />
<target name="init">
<property file="build.properties" />
<tstamp>
@@ -37,42 +35,82 @@
</target>
<target name="build" depends="build-prepare">
<wepp.dir dir="${build.dir}/_h5ai/css" />
<wepp.dir dir="${build.dir}/_h5ai/js" />
<wepp-dir-min dir="${build.dir}/_h5ai/css" todir="${build.dir}/_h5ai/css" />
<wepp-dir-min dir="${build.dir}/_h5ai/js" todir="${build.dir}/_h5ai/js" />
</target>
<target name="build-uncompressed" depends="build-prepare">
<wepp.dir dir="${build.dir}/_h5ai/css" args="--nc" />
<wepp.dir dir="${build.dir}/_h5ai/js" args="--nc" />
<wepp-dir dir="${build.dir}/_h5ai/css" todir="${build.dir}/_h5ai/css" />
<wepp-dir dir="${build.dir}/_h5ai/js" todir="${build.dir}/_h5ai/js" />
</target>
<target name="release" depends="build">
<mkdir dir="${release.dir}" />
<zip destfile="${release.dir}/${project.name}-${project.version}.zip" basedir="${build.dir}" />
<tar destfile="${release.dir}/${project.name}-${project.version}.tar" basedir="${build.dir}"/>
<gzip destfile="${release.dir}/${project.name}-${project.version}.tar.gz" src="${release.dir}/${project.name}-${project.version}.tar"/>
<delete file="${release.dir}/${project.name}-${project.version}.tar" />
</target>
<target name="pre-xint" depends="build-prepare">
<wepp file="${tool.jsxint.file}" tofile="${tool.jsxint.file}" args="--nc" />
<target name="lint" depends="build-prepare">
<wepp file="${build.dir}/_h5ai/js/inc/main.js" tofile="${build.dir}/_h5ai/js/inc/main.js" />
<jslint files="${build.dir}/_h5ai/js/inc/main.js" />
</target>
<target name="lint" depends="pre-xint">
<echo>JSLint "${tool.jsxint.file}"</echo>
<exec executable="${tool.jslint}" failonerror="true">
<arg value="${tool.jsxint.file}" />
<macrodef name="wepp-args">
<attribute name="args" default="" />
<sequential>
<exec executable="${tool.wepp}" failonerror="true">
<arg line="@{args}" />
</exec>
</target>
</sequential>
</macrodef>
<target name="hint" depends="pre-xint">
<echo>JSHint "${tool.jsxint.file}"</echo>
<exec executable="${tool.jshint}" failonerror="true">
<arg value="${tool.jsxint.file}" />
<macrodef name="wepp">
<attribute name="file" />
<attribute name="tofile" />
<sequential>
<wepp-args args="--nc --inFile '@{file}' --outFile '@{toFile}'" />
</sequential>
</macrodef>
<macrodef name="wepp-min">
<attribute name="file" />
<attribute name="tofile" />
<sequential>
<wepp-args args="--inFile '@{file}' --outFile '@{toFile}'" />
<bytes file="@{file}" toFile="@{toFile}" />
</sequential>
</macrodef>
<macrodef name="wepp-dir">
<attribute name="dir" />
<attribute name="todir" />
<sequential>
<wepp-args args="--nc --inDir '@{dir}' --outDir '@{todir}'" />
<delete dir="@{todir}/inc" >
<fileset dir="." includes="@{todir}/**/*.less" />
</delete>
</sequential>
</macrodef>
<macrodef name="wepp-dir-min">
<attribute name="dir" />
<attribute name="todir" />
<sequential>
<wepp-args args="--inDir '@{dir}' --outDir '@{todir}'" />
<delete dir="@{todir}/inc" >
<fileset dir="." includes="@{todir}/**/*.less" />
</delete>
</sequential>
</macrodef>
<macrodef name="jslint">
<attribute name="files" />
<sequential>
<echo>JSLint @{files}</echo>
<exec executable="${tool.jslint}" failonerror="false">
<arg line="@{files}" />
</exec>
</target>
<target name="xint" depends="lint,hint">
</target>
</sequential>
</macrodef>
</project>

View File

@@ -1,5 +1,7 @@
Options -Indexes
AddType text/html .php

View File

@@ -18,10 +18,15 @@ var H5AI_CONFIG = {
/*
* Filenames of customized header and footer files to look for
* in each folder.
* in each folder. For Example:
*
* "customHeader": "_h5ai.header.html",
* "customFooter": "_h5ai.footer.html",
*
* This is disabled by default.
*/
"customHeader": "_h5ai.header.html",
"customFooter": "_h5ai.footer.html",
"customHeader": null,
"customFooter": null,
/*
* An array of view modes the user may choose from. Currently there
@@ -100,13 +105,27 @@ var H5AI_CONFIG = {
* Requires PHP on the server.
* Show thumbnails for image files.
*/
"showThumbs": false,
"showThumbs": true,
"thumbTypes": ["bmp", "gif", "ico", "image", "jpg", "png", "tiff"],
/*
* Requires PHP on the server.
* Enable zipped download of selected entries.
*/
"zippedDownload": false
"zippedDownload": false,
/*
* Show QRCodes on hovering files.
* Set this to the desired size in pixel or null to not display QRCodes.
* A good size to start with might be 150.
*/
"qrCodesSize": null,
/*
* Allow filtering the displayed files and folders.
* Filters are ment to be JavaScript regular expressions.
*/
"showFilter": false
},
@@ -195,7 +214,8 @@ var H5AI_CONFIG = {
"empty": "empty",
"folders": "folders",
"files": "files",
"download": "download"
"download": "download",
"noMatch": "no match"
},
"bg": {
@@ -209,7 +229,8 @@ var H5AI_CONFIG = {
"empty": "празно",
"folders": "папки",
"files": "файлове",
"download": "download"
"download": "download",
"noMatch": "no match"
},
"cs": {
@@ -223,7 +244,8 @@ var H5AI_CONFIG = {
"empty": "prázdný",
"folders": "složek",
"files": "souborů",
"download": "download"
"download": "download",
"noMatch": "no match"
},
"de": {
@@ -237,7 +259,8 @@ var H5AI_CONFIG = {
"empty": "leer",
"folders": "Ordner",
"files": "Dateien",
"download": "Download"
"download": "Download",
"noMatch": "keine Treffer"
},
"es": {
@@ -249,9 +272,10 @@ var H5AI_CONFIG = {
"size": "Tamaño",
"parentDirectory": "Directorio superior",
"empty": "vacío",
"folders": "folders",
"files": "files",
"download": "download"
"folders": "Directorios",
"files": "Archivos",
"download": "Descargar",
"noMatch": "no match"
},
"fr": {
@@ -265,7 +289,8 @@ var H5AI_CONFIG = {
"empty": "vide",
"folders": "Répertoires",
"files": "Fichiers",
"download": "télécharger"
"download": "télécharger",
"noMatch": "no match"
},
"it": {
@@ -279,7 +304,8 @@ var H5AI_CONFIG = {
"empty": "vuota",
"folders": "cartelle",
"files": "file",
"download": "download"
"download": "download",
"noMatch": "no match"
},
"lv": {
@@ -293,7 +319,8 @@ var H5AI_CONFIG = {
"empty": "tukšs",
"folders": "mapes",
"files": "faili",
"download": "lejupielādēt"
"download": "lejupielādēt",
"noMatch": "no match"
},
"nl": {
@@ -307,7 +334,8 @@ var H5AI_CONFIG = {
"empty": "lege",
"folders": "folders",
"files": "files",
"download": "download"
"download": "download",
"noMatch": "no match"
},
"pl": {
@@ -321,7 +349,8 @@ var H5AI_CONFIG = {
"empty": "pusty",
"folders": "foldery",
"files": "pliki",
"download": "download"
"download": "download",
"noMatch": "no match"
},
"pt": {
@@ -335,7 +364,8 @@ var H5AI_CONFIG = {
"empty": "vazio",
"folders": "pastas",
"files": "arquivos",
"download": "download"
"download": "download",
"noMatch": "no match"
},
"ru": {
@@ -349,7 +379,8 @@ var H5AI_CONFIG = {
"empty": "пусто",
"folders": "папки",
"files": "файлы",
"download": "download"
"download": "download",
"noMatch": "no match"
},
"sk": {
@@ -363,7 +394,8 @@ var H5AI_CONFIG = {
"empty": "prázdny",
"folders": "priečinkov",
"files": "súborov",
"download": "download"
"download": "download",
"noMatch": "no match"
},
"sv": {
@@ -377,7 +409,8 @@ var H5AI_CONFIG = {
"empty": "tom",
"folders": "folders",
"files": "files",
"download": "download"
"download": "download",
"noMatch": "no match"
},
"tr": {
@@ -391,7 +424,8 @@ var H5AI_CONFIG = {
"empty": "boş",
"folders": "klasörler",
"files": "dosyalar",
"download": "indir"
"download": "indir",
"noMatch": "no match"
},
"zh-cn": {
@@ -405,7 +439,23 @@ var H5AI_CONFIG = {
"empty": "空文件夹",
"folders": "文件夹",
"files": "文件",
"download": "download"
"download": "下载",
"noMatch": "no match"
},
"zh-tw": {
"lang": "正體中文",
"details": "詳細資料",
"icons": "圖示",
"name": "檔名",
"lastModified": "上次修改",
"size": "大小",
"parentDirectory": "上層目錄",
"empty": "空資料夾",
"folders": "資料夾",
"files": "檔案",
"download": "下載",
"noMatch": "no match"
}
}
};

29
src/_h5ai/config.php Normal file
View File

@@ -0,0 +1,29 @@
<?php
/*
* h5ai %BUILD_VERSION%
*
* PHP Configuration
* filesystem paths and file ignore rules
*/
global $H5AI_CONFIG;
$H5AI_CONFIG = array(
/*
* This configuration assumes that h5ai is installed
* in the webroot directory of the Apache server.
*/
"ROOT_ABS_PATH" => safe_dirname(safe_dirname(__FILE__)),
/*
* Files/folders that should not be listed. Specified
* by the complete filename or by a regular expression.
* http://www.php.net/manual/en/function.preg-match.php
*/
"IGNORE" => array(),
"IGNORE_PATTERNS" => array("/^\\./", "/^_h5ai/")
);
?>

View File

@@ -0,0 +1,18 @@
#content {
max-width: 960px;
margin: 0 auto;
> header {
display: none;
padding-bottom: 10px;
margin-bottom: 80px;
border-bottom: 2px dashed #ddd;
}
> footer {
display: none;
padding-top: 10px;
margin-top: 80px;
border-top: 2px dashed #ddd;
}
}

View File

@@ -0,0 +1,22 @@
#context {
position: fixed;
z-index: 1;
display: none;
right: 16px;
bottom: 50px;
background-color: #fff;
border: 2px solid #ddd;
padding: 8px;
span {
display: block;
}
.qrcode {
canvas {
display: block;
}
}
}

View File

@@ -146,13 +146,16 @@
}
}
}
.empty {
.empty, .no-match {
text-align: center;
margin: 50px 0;
color: #ddd;
font-size: 5em;
font-weight: bold;
}
.no-match {
display: none;
}
}
@@ -170,8 +173,6 @@
#extended.icons-view {
display: none;
padding: 3px;
border: 1px solid #eee;
border-radius: 15px;
ul {
margin: 0;
@@ -269,7 +270,8 @@
}
}
}
.empty {
.empty, .no-match {
margin: 0 120px;
padding: 16px;
height: 120px;
text-align: center;
@@ -277,4 +279,7 @@
font-size: 5em;
font-weight: bold;
}
.no-match {
display: none;
}
}

View File

@@ -0,0 +1,108 @@
body > footer {
position: fixed;
z-index: 5;
width: 100%;
left: 0;
bottom: 0;
padding: 6px 0 8px 0;
.vert-gradient(rgb(241,241,241), rgb(228,228,228));
border-top: 1px solid rgb(210,210,210);
color: #999;
font-size: 0.85em;
text-align: center;
a, a:active, a:visited {
color: #555;
text-decoration: none;
.transition(all 0.2s ease-in-out);
opacity: 0.7;
&:hover {
color: #e80;
opacity: 1;
}
}
.left {
display: block;
padding: 0 8px;
float: left
}
.center {
display: block;
margin: 0 100px;
}
.right {
display: block;
padding: 0 8px;
float: right
}
.noJsMsg {
color: #c33;
margin-left: 16px;
}
.status {
.sep {
display: inline-block;
padding: 0 6px;
}
&.default {
}
&.dynamic {
display: none;
}
}
#langSelector {
position: relative;
cursor: pointer;
.langOptions {
position: absolute;
z-index: 2;
overflow: auto;
display: none;
right: 0;
top: 0;
max-height: 200px;
background-color: rgb(241,241,241);
border: 1px solid rgb(210,210,210);
> .scrollbar {
margin: 0;
width: 6px;
background-color: rgb(210,210,210);
.drag {
background-color: rgb(180,180,180);
}
&.dragOn .drag {
background-color: rgb(150,150,150);
}
}
ul {
margin: 0;
padding: 0;
list-style: none;
text-align: left;
li {
padding: 8px 24px 10px 24px;
white-space: nowrap;
border-top: 1px solid rgb(231,231,231);
.transition(all 0.2s ease-in-out);
&.current {
color: #333;
background-color: rgba(255,255,255,0.8);
}
&:hover {
color: #e80;
background-color: rgba(255,255,255,0.8);
}
}
}
}
}
}

View File

@@ -1,237 +0,0 @@
@import "h5bp-norm";
@import "mixins";
html.js {
.hideOnJs {
display: none;
}
}
html.no-js {
.hideOnNoJs {
display: none;
}
}
body {
font-family: Ubuntu, sans-serif;
font-size: 16px;
color: #555;
background-color: #fff;
margin: 80px 30px;
}
body > nav {
position: fixed;
z-index: 1;
width: 100%;
left: 0;
top: 0;
font-size: 0.85em;
background-color: rgb(241,241,241);
border-bottom: 2px solid rgb(210,210,210);
span.jsDisabledFallback {
display: block;
height: 30px;
line-height: 30px;
padding: 0 10px;
color: #999;
}
a, a:active, a:visited {
color: #555;
cursor: pointer;
text-decoration: none;
opacity: 0.7;
.transition(all 0.2s ease-in-out);
display: block;
height: 30px;
line-height: 30px;
padding: 0 10px;
&:hover, &.hover {
color: #e80;
background-color: rgba(255,255,255,0.5);
opacity: 1.0;
}
}
.current a {
background-color: rgba(255,255,255,0.5);
opacity: 1.0;
}
img {
position: relative;
top: -2px;
width: 16px;
height: 16px;
}
img + span {
margin-left: 6px;
}
.crumb {
float: left;
border-right: 1px solid rgb(231,231,231);
.hint {
margin-left: 8px;
font-style: italic;
color: #999;
}
img.hint {
width: 10px;
height: 10px;
}
}
.view {
float: right;
border-left: 1px solid rgb(231,231,231);
}
#download {
display: none;
float: right;
border-left: 1px solid rgb(231,231,231);
}
}
#content {
max-width: 960px;
margin: 0 auto;
> header {
display: none;
padding-bottom: 10px;
margin-bottom: 80px;
border-bottom: 2px dashed #ddd;
}
> footer {
display: none;
padding-top: 10px;
margin-top: 80px;
border-top: 2px dashed #ddd;
}
}
@import "table";
@import "extended";
@import "tree";
body > footer {
position: fixed;
z-index: 1;
width: 100%;
left: 0;
bottom: 0;
padding: 6px 0 8px 0;
background-color: rgb(241,241,241);
border-top: 2px solid rgb(210,210,210);
color: #999;
font-size: 0.85em;
text-align: center;
a, a:active, a:visited {
color: #555;
text-decoration: none;
.transition(all 0.2s ease-in-out);
opacity: 0.7;
&:hover {
color: #e80;
opacity: 1;
}
}
.left {
display: block;
padding: 0 8px;
float: left
}
.center {
display: block;
margin: 0 100px;
}
.right {
display: block;
padding: 0 8px;
float: right
}
.noJsMsg {
color: #c33;
margin-left: 16px;
}
.status {
.sep {
display: inline-block;
padding: 0 6px;
}
&.default {
}
&.dynamic {
display: none;
}
}
#langSelector {
position: relative;
cursor: pointer;
.langOptions {
position: absolute;
z-index: 2;
overflow: auto;
display: none;
right: 0;
top: 0;
max-height: 200px;
background-color: rgb(241,241,241);
border: 1px solid rgb(210,210,210);
> .scrollbar {
margin: 0;
width: 6px;
background-color: rgb(210,210,210);
.drag {
background-color: rgb(180,180,180);
}
&.dragOn .drag {
background-color: rgb(150,150,150);
}
}
ul {
margin: 0;
padding: 0;
list-style: none;
text-align: left;
li {
padding: 8px 24px 10px 24px;
white-space: nowrap;
border-top: 1px solid rgb(231,231,231);
.transition(all 0.2s ease-in-out);
&.current {
color: #333;
background-color: rgba(255,255,255,0.8);
}
&:hover {
color: #e80;
background-color: rgba(255,255,255,0.8);
}
}
li:nth-child(3n+1) {
}
}
}
}
}
@import "responsive";

View File

@@ -1,38 +1,59 @@
.border-radius (@radius) {
-moz-border-radius: @radius;
-webkit-border-radius: @radius;
border-radius: @radius;
-webkit-border-radius: @radius; /* Saf3-4, iOS 1-3.2, Android <1.6 */
-moz-border-radius: @radius; /* FF1-3.6 */
border-radius: @radius; /* Opera 10.5, IE9, Saf5, Chrome, FF4, iOS 4, Android 2.1+ */
}
.background-clip () {
-webkit-background-clip: padding-box;
-moz-background-clip: padding;
background-clip: padding-box;
}
.box-shadow (@shadow) {
-moz-box-shadow: @shadow;
-webkit-box-shadow: @shadow;
box-shadow: @shadow;
-webkit-box-shadow: @shadow; /* Saf3-4 */
-moz-box-shadow: @shadow; /* FF3.5 - 3.6 */
box-shadow: @shadow; /* Opera 10.5, IE9, FF4+, Chrome 10+ */
}
.transition (@transition) {
-moz-transition: @transition;
-ms-transition: @transition;
-o-transition: @transition;
-webkit-transition: @transition;
-webkit-transition: @transition; /* Saf3.2+, Chrome */
-moz-transition: @transition; /* FF4+ */
-ms-transition: @transition; /* IE10? */
-o-transition: @transition; /* Opera 10.5+ */
transition: @transition;
}
.transform (@transform) {
-moz-transform: @transform;
-o-transform: @transform;
-webkit-transform: @transform;
-webkit-transform: @transform; /* Saf3.1+, Chrome */
-moz-transform: @transform; /* FF3.5+ */
-ms-transform: @transform; /* IE9 */
-o-transform: @transform; /* Opera 10.5 */
transform: @transform;
zoom: 1;
}
.vert-gradient (@top, @bottom) {
background-color: @top;
background-image: -webkit-gradient(linear, left top, left bottom, from(@top), to(@bottom)); /* Saf4+, Chrome */
background-image: -webkit-linear-gradient(top, @top, @bottom); /* Chrome 10+, Saf5.1+, iOS 5+ */
background-image: -moz-linear-gradient(top, @top, @bottom); /* FF3.6 */
background-image: -ms-linear-gradient(top, @top, @bottom); /* IE10 */
background-image: -o-linear-gradient(top, @top, @bottom); /* Opera 11.10+ */
background-image: linear-gradient(top, @top, @bottom);
}
.background-size (@size) {
-moz-background-size: @size;
-webkit-background-size: @size;
background-size: @size;
-webkit-background-size: @size; /* Saf3-4 */
-moz-background-size: @size; /* FF3.6 */
background-size: @size; /* Opera, IE9, Saf5, Chrome, FF4 */
}

135
src/_h5ai/css/inc/nav.less Normal file
View File

@@ -0,0 +1,135 @@
.nav-highlight {
background-color: rgba(255,255,255,0.5);
opacity: 1.0;
}
.nav-hover {
.nav-highlight;
color: #e80;
}
@nav-sep-border: 1px solid rgba(0,0,0,0.05);
.nav-left {
float: left;
border-right: @nav-sep-border;
}
.nav-right {
float: right;
border-left: @nav-sep-border;
}
body > nav {
position: fixed;
z-index: 5;
width: 100%;
left: 0;
top: 0;
font-size: 0.85em;
.vert-gradient(rgb(241,241,241), rgb(228,228,228));
border-bottom: 1px solid rgb(210,210,210);
span.jsDisabledFallback {
display: block;
height: 30px;
line-height: 30px;
padding: 0 10px;
color: #999;
}
a, a:active, a:visited, span.element {
color: #555;
cursor: pointer;
text-decoration: none;
opacity: 0.7;
.transition(all 0.2s ease-in-out);
display: block;
height: 30px;
line-height: 30px;
padding: 0 10px;
&:hover, &.hover {
.nav-hover;
}
}
.current {
a, span.element {
.nav-highlight;
}
}
img {
position: relative;
top: -2px;
width: 16px;
height: 16px;
}
img + span, img + input {
margin-left: 6px;
}
.crumb {
.nav-left;
.hint {
margin-left: 8px;
font-style: italic;
color: #999;
}
img.hint {
width: 10px;
height: 10px;
}
}
.view {
.nav-right;
}
#download {
display: none;
.nav-right;
.transition(all 0.2s ease-in-out);
&.failed {
background-color: rgba(255,0,0,0.5);
}
}
#filter {
.nav-right;
input {
display: none;
border: none;
font-family: Ubuntu, sans-serif;
color: #555;
background-color: rgba(0,0,0,0);
width: 100px;
}
&.current {
input {
display: inline;
}
}
}
}
#download-auth {
display: none;
position: fixed;
z-index: 5;
left: 0;
top: 0;
font-size: 0.85em;
.vert-gradient(rgb(241,241,241), rgb(228,228,228));
border: 1px solid rgb(210,210,210);
input {
display: block;
margin: 4px 6px;
border: 1px solid rgb(210,210,210);
font-family: Ubuntu, sans-serif;
color: #555;
background-color: rgba(255,255,255,1);
width: 100px;
}
}

View File

@@ -3,15 +3,14 @@
display: none;
position: fixed;
left: 0;
top: 82px;
z-index: 1;
top: 31px;
height: 100%;
z-index: 3;
overflow: auto;
font-size: 0.85em;
padding: 8px;
background-color: rgb(241,241,241);
border: 1px solid rgb(210,210,210);
border-left: none;
.border-radius(0 10px 10px 0);
border-right: 2px solid rgb(221,221,221);
> .scrollbar {
margin: 8px 8px 8px 0;

View File

@@ -1,3 +0,0 @@
@import "inc/main";

View File

@@ -1,17 +0,0 @@
@import "inc/main";
#table {
display: none;
}
#tree, #content > header, #content > footer {
display: block;
}
html.no-js {
#extended.details-view, #extended.icons-view {
display: block;
}
}

58
src/_h5ai/css/main.less Normal file
View File

@@ -0,0 +1,58 @@
@import "inc/h5bp-norm";
@import "inc/mixins";
body {
font-family: Ubuntu, sans-serif;
font-size: 16px;
color: #555;
background-color: #fff;
margin: 80px 30px;
}
@import "inc/nav";
@import "inc/content";
@import "inc/table";
@import "inc/extended";
@import "inc/tree";
@import "inc/context";
@import "inc/footer";
@import "inc/responsive";
html.js {
.hideOnJs {
display: none;
}
}
html.no-js {
.hideOnNoJs {
display: none;
}
}
html.h5ai-js {
#h5ai-reference:after {
content: " (js)";
}
}
html.h5ai-php {
#h5ai-reference:after {
content: " (php)";
}
#table {
display: none;
}
#tree, #content > header, #content > footer {
display: block;
}
html.no-js {
#extended.details-view, #extended.icons-view {
display: block;
}
}
}

View File

@@ -1,12 +1,10 @@
<!-- generated code ends here -->
</section>
<section id="extended" class="clearfix"></section>
<footer></footer>
</section>
<section id="tree"></section>
<div id="selection-rect"></div>
<footer class="clearfix">
<span class="left">
<a href="http://larsjung.de/h5ai" target="_blank" title="h5ai project page">h5ai %BUILD_VERSION% (js)</a>
<a id="h5ai-reference" href="http://larsjung.de/h5ai" target="_blank" title="h5ai project page">h5ai %BUILD_VERSION%</a>
<span class="hideOnJs noJsMsg"> ⚡ JavaScript is disabled! ⚡ </span>
</span>
<span class="right">
@@ -27,8 +25,7 @@
</span>
</span>
</footer>
<script src="/_h5ai/js/libs.js"></script>
<script src="/_h5ai/config.js"></script>
<script src="/_h5ai/js/main-js.js"></script>
<script src="/_h5ai/js/libs.js"></script>
</body>
</html>

View File

@@ -1,4 +0,0 @@
<!-- generated code ends here -->
</section>
</body>
</html>

View File

@@ -2,7 +2,7 @@
<!--[if lt IE 7]> <html class="no-js ie6 oldie" lang="en"> <![endif]-->
<!--[if IE 7]> <html class="no-js ie7 oldie" lang="en"> <![endif]-->
<!--[if IE 8]> <html class="no-js ie8 oldie" lang="en"> <![endif]-->
<!--[if gt IE 8]><!--> <html class="no-js" lang="en"> <!--<![endif]-->
<!--[if gt IE 8]><!--> <html class="h5ai-js no-js" lang="en"> <!--<![endif]-->
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
@@ -13,16 +13,18 @@
<link rel="shortcut icon" type="image/png" href="/_h5ai/images/h5ai-16x16.png">
<link rel="apple-touch-icon" type="image/png" href="/_h5ai/images/h5ai-48x48.png">
<link rel="stylesheet" href="http://fonts.googleapis.com/css?family=Ubuntu:regular,italic,bold">
<link rel="stylesheet" href="/_h5ai/css/main-js.css">
<link rel="stylesheet" href="/_h5ai/css/main.css">
<script src="/_h5ai/js/modernizr.min.js"></script>
</head>
<body>
<div id="selection-rect"></div>
<nav class="clearfix hideOnNoJs">
<ul id="navbar"></ul>
</nav>
<section id="tree"></section>
<section id="content">
<header></header>
<section id="extended" class="clearfix"></section>
<footer></footer>
<section id="table" class="hideOnJs">
<!--
The following code was generated by Apache's autoindex module. It is not valid HTML5, but this

View File

@@ -2,7 +2,7 @@
<!--[if lt IE 7]> <html class="no-js ie6 oldie" lang="en"> <![endif]-->
<!--[if IE 7]> <html class="no-js ie7 oldie" lang="en"> <![endif]-->
<!--[if IE 8]> <html class="no-js ie8 oldie" lang="en"> <![endif]-->
<!--[if gt IE 8]><!--> <html class="no-js" lang="en"> <!--<![endif]-->
<!--[if gt IE 8]><!--> <html class="h5ai-php no-js" lang="en"> <!--<![endif]-->
<?php include "php/main.php"; ?>
<head>
<meta charset="utf-8">
@@ -14,11 +14,10 @@
<link rel="shortcut icon" type="image/png" href="/_h5ai/images/h5ai-16x16.png">
<link rel="apple-touch-icon" type="image/png" href="/_h5ai/images/h5ai-48x48.png">
<link rel="stylesheet" href="http://fonts.googleapis.com/css?family=Ubuntu:regular,italic,bold">
<link rel="stylesheet" href="/_h5ai/css/main-php.css">
<link rel="stylesheet" href="/_h5ai/css/main.css">
<script src="/_h5ai/js/modernizr.min.js"></script>
</head>
<body>
<div id="selection-rect"></div>
<nav class="clearfix">
<ul id="navbar">
<?php echo $crumb->toHtml(); ?>
@@ -29,32 +28,5 @@
<?php echo $customize->getHeader(); ?>
<?php echo $extended->toHtml(); ?>
<?php echo $customize->getFooter(); ?>
</section>
<footer class="clearfix">
<span class="left">
<a href="http://larsjung.de/h5ai" target="_blank" title="h5ai project page">h5ai %BUILD_VERSION% (php)</a>
<span class="hideOnJs noJsMsg"> ⚡ JavaScript is disabled! ⚡ </span>
</span>
<span class="right">
<span id="langSelector">
<span class="lang">en</span> - <span class="l10n-lang">english</span>
<span class="langOptions"></span>
</span>
</span>
<span class="center">
<span class="hideOnNoJs">
<span class="status default">
<span class="folderTotal"></span> <span class="l10n-folders">folders</span>
<span class='sep'>·</span>
<span class="fileTotal"></span> <span class="l10n-files">files</span>
</span>
<span class="status dynamic">
</span>
</span>
</span>
</footer>
<script src="/_h5ai/js/libs.js"></script>
<script src="/_h5ai/config.js"></script>
<script src="/_h5ai/js/main-php.js"></script>
<section id="table">
<section id="table" class="hideOnJs">
<!-- The following code was generated by Apache's autoindex module and gets ignored and removed from the DOM tree. -->

BIN
src/_h5ai/images/filter.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 706 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 847 B

View File

@@ -0,0 +1,55 @@
(function ($, H5AI) {
H5AI.context = (function () {
var $context,
qrCodesSize,
showQrCode = function ($a) {
var absHref = $a.attr('href'),
url = 'http://' + document.domain + absHref;
$context.find('.qrcode').empty().qrcode({
render: Modernizr.canvas ? 'canvas' : 'div',
width: qrCodesSize,
height: qrCodesSize,
color: '#333',
text: url
});
},
init = function () {
qrCodesSize = H5AI.core.settings.qrCodesSize;
if (!qrCodesSize) {
return;
}
var hideTimeoutId = null;
$context = $('<div id="context"><div class="qrcode"/></div>');
$context.appendTo('body');
$('#extended')
.on('mouseenter', '.entry.file a', function () {
showQrCode($(this));
clearTimeout(hideTimeoutId);
$context.stop(true, true).fadeIn(400);
})
.on('mouseleave', '.entry.file a', function () {
hideTimeoutId = setTimeout(function () {
$context.stop(true, true).fadeOut(400);
}, 200);
});
};
return {
init: init
};
}());
}(jQuery, H5AI));

View File

@@ -15,21 +15,23 @@
rootAbsHref: "/",
h5aiAbsHref: "/_h5ai/",
customHeader: "_h5ai.header.html",
customFooter: "_h5ai.footer.html",
customHeader: null,
customFooter: null,
viewmodes: ["details", "icons"],
sortorder: "na",
showTree: true,
slideTree: true,
folderStatus: {},
lang: null,
lang: "en",
useBrowserLang: true,
setParentFolderLabels: true,
linkHoverStates: true,
dateFormat: "yyyy-MM-dd HH:mm",
showThumbs: false,
zippedDownload: false
thumbTypes: ["bmp", "gif", "ico", "image", "jpg", "png", "tiff"],
zippedDownload: false,
qrCodesSize: null,
showFilter: false
},
settings = $.extend({}, defaults, config.options),
currentDateFormat = settings.dateFormat,
@@ -42,13 +44,42 @@
});
return map;
}(config.types)),
hash = function (obj) {
if ($.isPlainObject(obj)) {
var hashStr = '';
$.each($.extend({}, hash(), obj), function (key, value) {
if (value) {
hashStr += '/' + encodeURIComponent(key) + '=' + encodeURIComponent(value);
}
});
hashStr = '#!' + hashStr;
window.location.hash = hashStr;
return hashStr;
} else {
var result = {},
parts = document.location.hash.split('/');
if (parts.length >= 2 || parts[0] === '#!') {
parts.shift();
$.each(parts, function (idx, part) {
var match = /^([^=]*)=(.*?)$/.exec(part);
if (match) {
result[decodeURIComponent(match[1])] = decodeURIComponent(match[2]);
}
});
}
return typeof obj === 'string' ? result[obj] : result;
}
},
api = function () {
return settings.h5aiAbsHref + "php/api.php";
},
image = function (id) {
image = function (id, noPngExt) {
return settings.h5aiAbsHref + "images/" + id + ".png";
return settings.h5aiAbsHref + "images/" + id + (noPngExt ? "" : ".png");
},
icon = function (id, big) {
@@ -66,6 +97,7 @@
viewmode = amplify.store(settings.store.viewmode);
}
viewmode = $.inArray(viewmode, settings.viewmodes) >= 0 ? viewmode : settings.viewmodes[0];
H5AI.core.hash({view: viewmode});
$viewDetails.add($viewIcons).removeClass("current");
if (viewmode === "details") {
@@ -88,7 +120,7 @@
navHeight = $("body > nav").outerHeight(),
footerHeight = $("body > footer").outerHeight(),
contentSpacing = 50,
treeSpacing = 30;
treeSpacing = 0;
$body.css({
"margin-top": navHeight + contentSpacing,
@@ -97,7 +129,7 @@
$tree.css({
top: navHeight + treeSpacing,
height: winHeight - navHeight - footerHeight - 18 - 2 * treeSpacing
height: winHeight - navHeight - footerHeight - 16 - 2 * treeSpacing
});
try {
@@ -121,13 +153,19 @@
if ($.inArray("icons", settings.viewmodes) >= 0) {
$("<li id='viewicons' class='view'><a href='#'><img alt='view-icons' /><span class='l10n-icons'>icons</span></a></li>")
.find("img").attr("src", image("view-icons")).end()
.click(function () { viewmode("icons"); })
.find("a").click(function (event) {
viewmode("icons");
event.preventDefault();
}).end()
.appendTo($navbar);
}
if ($.inArray("details", settings.viewmodes) >= 0) {
$("<li id='viewdetails' class='view'><a href='#'><img alt='view-details' /><span class='l10n-details'>details</span></a></li>")
.find("img").attr("src", image("view-details")).end()
.click(function () { viewmode("details"); })
.find("a").click(function (event) {
viewmode("details");
event.preventDefault();
}).end()
.appendTo($navbar);
}
}
@@ -255,6 +293,7 @@
$(".lang").text(lang);
$(".langOption").removeClass("current");
$(".langOption." + lang).addClass("current");
H5AI.core.hash({lang: lang});
}
formatDates(selected.dateFormat || settings.dateFormat);
@@ -384,6 +423,7 @@
return {
settings: settings,
hash: hash,
api: api,
image: image,
icon: icon,

View File

@@ -49,9 +49,11 @@
if ($ul.children(".entry:not(.folder-parent)").size() === 0) {
$("#extended").append($("<div class='empty l10n-empty'>empty</div>"));
}
$("#extended").append($("<div class='no-match l10n-noMatch'>no match</div>"));
},
customize = function () {
if (H5AI.core.settings.customHeader) {
$.ajax({
url: H5AI.core.settings.customHeader,
dataType: "html",
@@ -59,7 +61,9 @@
$("#content > header").append($(data)).show();
}
});
}
if (H5AI.core.settings.customFooter) {
$.ajax({
url: H5AI.core.settings.customFooter,
dataType: "html",
@@ -67,6 +71,7 @@
$("#content > footer").prepend($(data)).show();
}
});
}
},
fetchPath = function (pathname, callback) {

111
src/_h5ai/js/inc/Finder.js Normal file
View File

@@ -0,0 +1,111 @@
(function ($, H5AI) {
H5AI.finder = (function () {
var filter = function (re) {
var match = [],
noMatch = [];
if (re) {
$('#extended .entry').each(function () {
var label = $(this).find('.label').text();
if (label.match(re)) {
match.push(this);
} else {
noMatch.push(this);
}
});
} else {
match = $('#extended .entry');
}
if ($(match).length) {
$('#extended .no-match').hide();
} else {
setTimeout(function () {
$('#extended .no-match').show();
}, 200);
}
$(match).fadeIn(200);
$(noMatch).fadeOut(200);
},
checkState = function (focus) {
var $filter = $('#filter'),
$input = $filter.find('input'),
val = $input.val();
if (val || focus) {
$filter.addClass('current');
} else {
$filter.removeClass('current');
}
H5AI.core.hash({filter: val});
},
parseFilterSequence = function (sequence) {
if (sequence.substr(0,3) === 're:') {
return new RegExp(sequence.substr(3));
}
sequence = $.map($.trim(sequence).split(/\s+/), function (part) {
return H5AI.util.reEscape(part);
}).join('|');
return new RegExp(sequence);
},
init = function () {
if (H5AI.core.settings.showFilter) {
$("<li id='filter'><span class='element'><img alt='filter' /><input type='text' value='' placeholder='filter' /></span></li>")
.on('click', function () {
var $input = $(this).find('input');
$input.focus();
})
.find("img").attr("src", H5AI.core.image("filter")).end()
.find("input")
.on('focus', function () {
checkState(true);
})
.on('blur', function () {
checkState(false);
})
.on('keyup', function () {
var $input = $(this),
val = $input.val();
if (val) {
filter(parseFilterSequence(val));
} else {
filter();
}
checkState($input.is(':focus'));
})
.end()
.appendTo($("#navbar"));
var initialFilter = H5AI.core.hash('filter');
if (initialFilter) {
$('#filter input').val(initialFilter);
checkState(false);
}
}
};
return {
init: init,
filter: filter
};
}());
}(jQuery, H5AI));

View File

@@ -3,8 +3,7 @@
H5AI.html = (function () {
var thumbTypes = ["bmp", "gif", "ico", "image", "jpg", "png", "tiff"],
onClick = function (path, context) {
var onClick = function (path, context) {
},
updateCrumbHtml = function (path) {
@@ -72,10 +71,11 @@
$html.data("status", path.status);
}
if (H5AI.core.settings.showThumbs === true && $.inArray(path.type, thumbTypes) >= 0) {
if (H5AI.core.settings.showThumbs === true && $.inArray(path.type, H5AI.core.settings.thumbTypes) >= 0) {
imgClass = "class='thumb'";
icon16 = H5AI.core.api() + "?action=thumb&href=" + path.absHref + "&width=16&height=16&mode=square";
icon48 = H5AI.core.api() + "?action=thumb&href=" + path.absHref + "&width=96&height=46&mode=rational";
var escapedHref = path.absHref.replace(/'/g, "%27").replace(/"/g, "%22");
icon16 = H5AI.core.api() + "?action=thumb&href=" + escapedHref + "&width=16&height=16&mode=square";
icon48 = H5AI.core.api() + "?action=thumb&href=" + escapedHref + "&width=96&height=46&mode=rational";
}
$label = $("<span class='label'>" + path.label + "</span>");

View File

@@ -39,7 +39,7 @@
path.parentFolder = folder;
path.label = $a.text();
path.type = $tds.eq(0).find("img").attr("alt") === "[DIR]" ? "folder" : H5AI.core.getFileType(path.label);
path.type = H5AI.util.pathEndsWithSlash(path.label) ? "folder" : H5AI.core.getFileType(path.label);
path.href = $a.attr("href");
path.time = date ? date.getTime() : 0;
path.size = size;

View File

@@ -78,14 +78,15 @@
var order = orders[id];
$all.removeClass("ascending").removeClass("descending");
order.head.addClass(order.clas).attr("href", "#!/sort=" + id);
order.head.addClass(order.clas);
sort(order.fn);
H5AI.core.hash({sort: id});
},
init = function () {
var $ascending = $("<img src='" + H5AI.core.image("ascending") + "' class='sort ascending' alt='ascending' />"),
$descending = $("<img src='" + H5AI.core.image("descending") + "' class='sort descending' alt='descending' />"),
initialOrder = /^.*#!.*\/sort=(.*?)(?:\/.*)?$/.exec(document.location),
initialOrder = H5AI.core.hash('sort'),
$header = $("#extended li.header"),
$label = $header.find("a.label"),
$date = $header.find("a.date"),
@@ -125,27 +126,27 @@
}
};
sortBy(initialOrder ? initialOrder[1] : H5AI.core.settings.sortorder);
sortBy(initialOrder ? initialOrder : H5AI.core.settings.sortorder);
$label
.attr("href", "#!/sort=na")
.append($ascending.clone()).append($descending.clone())
.click(function () {
.click(function (event) {
sortBy("n" + ($label.hasClass("ascending") ? "d" : "a"));
event.preventDefault();
});
$date
.attr("href", "#!/sort=da")
.prepend($ascending.clone()).prepend($descending.clone())
.click(function () {
.click(function (event) {
sortBy("d" + ($date.hasClass("ascending") ? "d" : "a"));
event.preventDefault();
});
$size
.attr("href", "#!/sort=sa")
.prepend($ascending.clone()).prepend($descending.clone())
.click(function () {
.click(function (event) {
sortBy("s" + ($size.hasClass("ascending") ? "d" : "a"));
event.preventDefault();
});
};

View File

@@ -100,6 +100,10 @@
return decodeURI(uri);
} catch (err) {}
return uri;
},
reEscape = function (sequence) {
return sequence.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&');
};
return {
@@ -108,7 +112,8 @@
getAbsHref: getAbsHref,
parseSize: parseSize,
formatSize: formatSize,
checkedDecodeUri: checkedDecodeUri
checkedDecodeUri: checkedDecodeUri,
reEscape: reEscape
};
}());

View File

@@ -7,21 +7,25 @@
y = 0,
$document = $(document),
$selectionRect = $("#selection-rect"),
selectedHrefsStr = "",
$download, $img, $downloadAuth, $downloadUser, $downloadPassword,
updateDownloadBtn = function () {
var $selected = $("#extended a.selected"),
$downloadBtn = $("#download"),
query, href;
$downloadBtn = $("#download");
if ($selected.size() > 0) {
selectedHrefsStr = "";
if ($selected.length) {
$selected.each(function () {
href = $(this).attr("href");
query = query ? query + ":" + href : href;
var href = $(this).attr("href");
selectedHrefsStr = selectedHrefsStr ? selectedHrefsStr + ":" + href : href;
});
query = H5AI.core.api() + "?action=zip&hrefs=" + query;
$downloadBtn.show().find("a").attr("href", query);
$downloadBtn.show();
} else {
$downloadBtn.hide().find("a").attr("href", "#");
$downloadBtn.hide();
$downloadAuth.hide();
}
},
selectionUpdate = function (event) {
@@ -67,12 +71,12 @@
}
event.preventDefault();
$(':focus').blur();
if (!event.ctrlKey) {
$("#extended a").removeClass("selected");
updateDownloadBtn();
}
$selectionRect.show().css({left: x, top: y, width: 0, height: 0});
selectionUpdate(event);
$document
.on("mousemove", selectionUpdate)
@@ -80,7 +84,7 @@
},
noSelection = function (event) {
event.stopPropagation();
event.stopImmediatePropagation();
return false;
},
noSelectionUnlessCtrl = function (event) {
@@ -89,15 +93,92 @@
noSelection(event);
}
},
failed = function () {
$download.addClass('failed');
setTimeout(function () {
$download.removeClass('failed');
}, 1000);
},
handleResponse = function (response) {
$download.removeClass('current');
$img.attr('src', H5AI.core.image("download"));
if (response) {
if (response.status === 'ok') {
window.location = H5AI.core.api() + '?action=getzip&id=' + response.id;
} else {
if (response.code === 401) {
$downloadAuth
.css({
left: $download.offset().left,
top: $download.offset().top + $download.outerHeight()
})
.show();
$downloadUser.focus();
}
failed();
}
} else {
failed();
}
},
requestZipping = function (hrefsStr) {
$download.addClass('current');
$img.attr('src', H5AI.core.image("loading.gif", true));
$.ajax({
url: H5AI.core.api(),
data: {
action: 'zip',
hrefs: selectedHrefsStr
},
type: 'POST',
dataType: 'json',
beforeSend: function (xhr) {
var user = $downloadUser.val(),
password = $downloadPassword.val();
if (user) {
xhr.setRequestHeader ('Authorization', 'Basic ' + Base64.encode(user + ':' + password));
}
},
success: function (response) {
handleResponse(response);
},
failed: function () {
handleResponse();
}
});
},
init = function () {
if (H5AI.core.settings.zippedDownload) {
$("<li id='download'><a href='#'><img alt='download' /><span class='l10n-download'>download</span></a></li>")
.find("img").attr("src", H5AI.core.image("download")).end()
.appendTo($("#navbar"));
.find("a").click(function (event) {
$("body>nav,body>footer,#tree").on("mousedown", noSelection);
$("#extended").on("mousedown", "a", noSelectionUnlessCtrl);
event.preventDefault();
$downloadAuth.hide();
requestZipping(selectedHrefsStr);
}).end()
.appendTo($("#navbar"));
$("<div id='download-auth'><input id='download-auth-user' type='text' value='' placeholder='user' /><input id='download-auth-password' type='text' value='' placeholder='password' /></div>")
.appendTo($("body"));
$download = $('#download');
$downloadAuth = $('#download-auth');
$downloadUser = $('#download-auth-user');
$downloadPassword = $('#download-auth-password');
$img = $download.find('img');
$("body>nav,body>footer,#tree,input").on("mousedown", noSelection);
$("#content").on("mousedown", "a", noSelectionUnlessCtrl);
$document.on("mousedown", selectionStart);
}
};

View File

@@ -0,0 +1,137 @@
/*
* taken from here:
* http://www.webtoolkit.info/javascript-base64.html
* with minor modifications
*/
var Base64 = {
// private property
_keyStr : "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",
// public method for encoding
encode : function (input) {
var output = "";
var chr1, chr2, chr3, enc1, enc2, enc3, enc4;
var i = 0;
input = Base64._utf8_encode(input);
while (i < input.length) {
chr1 = input.charCodeAt(i++);
chr2 = input.charCodeAt(i++);
chr3 = input.charCodeAt(i++);
enc1 = chr1 >> 2;
enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
enc4 = chr3 & 63;
if (isNaN(chr2)) {
enc3 = enc4 = 64;
} else if (isNaN(chr3)) {
enc4 = 64;
}
output = output +
this._keyStr.charAt(enc1) + this._keyStr.charAt(enc2) +
this._keyStr.charAt(enc3) + this._keyStr.charAt(enc4);
}
return output;
},
// public method for decoding
decode : function (input) {
var output = "";
var chr1, chr2, chr3;
var enc1, enc2, enc3, enc4;
var i = 0;
input = input.replace(/[^A-Za-z0-9\+\/\=]/g, "");
while (i < input.length) {
enc1 = this._keyStr.indexOf(input.charAt(i++));
enc2 = this._keyStr.indexOf(input.charAt(i++));
enc3 = this._keyStr.indexOf(input.charAt(i++));
enc4 = this._keyStr.indexOf(input.charAt(i++));
chr1 = (enc1 << 2) | (enc2 >> 4);
chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
chr3 = ((enc3 & 3) << 6) | enc4;
output = output + String.fromCharCode(chr1);
if (enc3 != 64) {
output = output + String.fromCharCode(chr2);
}
if (enc4 != 64) {
output = output + String.fromCharCode(chr3);
}
}
return Base64._utf8_decode(output);
},
// private method for UTF-8 encoding
_utf8_encode : function (string) {
string = string.replace(/\r\n/g,"\n");
var utftext = "";
for (var n = 0; n < string.length; n++) {
var c = string.charCodeAt(n);
if (c < 128) {
utftext += String.fromCharCode(c);
}
else if((c > 127) && (c < 2048)) {
utftext += String.fromCharCode((c >> 6) | 192);
utftext += String.fromCharCode((c & 63) | 128);
}
else {
utftext += String.fromCharCode((c >> 12) | 224);
utftext += String.fromCharCode(((c >> 6) & 63) | 128);
utftext += String.fromCharCode((c & 63) | 128);
}
}
return utftext;
},
// private method for UTF-8 decoding
_utf8_decode : function (utftext) {
var string = "";
var i = 0;
var c = c1 = c2 = 0;
while ( i < utftext.length ) {
c = utftext.charCodeAt(i);
if (c < 128) {
string += String.fromCharCode(c);
i++;
}
else if((c > 191) && (c < 224)) {
c2 = utftext.charCodeAt(i+1);
string += String.fromCharCode(((c & 31) << 6) | (c2 & 63));
i += 2;
}
else {
c2 = utftext.charCodeAt(i+1);
c3 = utftext.charCodeAt(i+2);
string += String.fromCharCode(((c & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63));
i += 3;
}
}
return string;
}
}

View File

@@ -82,6 +82,3 @@ function handler(event) {
}
})(jQuery);

View File

@@ -0,0 +1,130 @@
/*!
* jQuery.qrcode
* author: Lars Jung
* license: MIT
*
* kudos to http://github.com/jeromeetienne/jquery-qrcode
*/
(function ($) {
'use strict';
// @include "qrcode.js"
var createQr = function (typeNumber, correctLevel, text) {
var qr = new qrcode(typeNumber, correctLevel);
qr.addData(text);
qr.make();
return qr;
},
createBestQr = function (text) {
for (var type = 2; type <= 10; type += 1) {
try {
return createQr(type, 'L', text);
} catch (err) {}
}
return null;
},
createCanvas = function (settings) {
var qr = createBestQr(settings.text),
$canvas = $('<canvas/>').attr('width', settings.width).attr('height', settings.height),
ctx = $canvas[0].getContext('2d');
if (settings.bgColor) {
ctx.fillStyle = settings.bgColor;
ctx.fillRect(0, 0, settings.width, settings.height);
}
if (qr) {
var moduleCount = qr.getModuleCount(),
moduleWidth = settings.width / moduleCount,
moduleHeight = settings.height / moduleCount,
row, col;
ctx.beginPath();
for (row = 0; row < moduleCount; row += 1) {
for (col = 0; col < moduleCount; col += 1) {
if (qr.isDark(row, col)) {
ctx.rect(col * moduleWidth, row * moduleHeight, moduleWidth, moduleHeight);
}
}
}
ctx.fillStyle = settings.color;
ctx.fill();
}
return $canvas;
},
createDiv = function (settings) {
var qr = createBestQr(settings.text),
$div = $('<div/>').css({
position: 'relative',
left: 0,
top: 0,
padding: 0,
margin: 0,
width: settings.width,
height: settings.height
});
if (settings.bgColor) {
$div.css('background-color', settings.bgColor);
}
if (qr) {
var moduleCount = qr.getModuleCount(),
moduleWidth = Math.floor(settings.width / moduleCount),
moduleHeight = Math.floor(settings.height / moduleCount),
offsetLeft = Math.floor(0.5 * (settings.width - moduleWidth * moduleCount)),
offsetTop = Math.floor(0.5 * (settings.height - moduleHeight * moduleCount)),
row, col;
for (row = 0; row < moduleCount; row++) {
for (col = 0; col < moduleCount; col++) {
if (qr.isDark(row, col)) {
$('<div/>')
.css({
left: offsetLeft + col * moduleWidth,
top: offsetTop + row * moduleHeight
})
.appendTo($div);
}
}
}
$div.children()
.css({
position: 'absolute',
padding: 0,
margin: 0,
width: moduleWidth,
height: moduleHeight,
'background-color': settings.color
});
}
return $div;
},
defaults = {
render: 'canvas',
width: 256,
height: 256,
color: '#000',
bgColor: null,
text: 'no text'
};
$.fn.qrcode = function(options) {
var settings = $.extend({}, defaults, options);
$(this).append(settings.render === 'canvas' ? createCanvas(settings) : createDiv(settings));
};
}(jQuery));

View File

@@ -3,9 +3,8 @@
* author: Lars Jung
* license: MIT
*
* bad and ugly coded!
* still quick and dirty!
*/
(function (window, $) {
"use strict";

File diff suppressed because it is too large Load Diff

42
src/_h5ai/js/inc/main.js Normal file
View File

@@ -0,0 +1,42 @@
(function ($) {
'use strict';
/*jslint browser: true, confusion: true, regexp: true, vars: true, white: true */
/*global Modernizr, jQuery, amplify, H5AI_CONFIG */
var H5AI = {};
// @include "Util.js"
// @include "Core.js"
// @include "Sort.js"
// @include "ZippedDownload.js"
// @include "Finder.js"
// @include "Context.js"
// @include "Path.js"
// @include "Connector.js"
// @include "Html.js"
// @include "Extended.js"
$(function () {
var isPhp = $('html.h5ai-php').length > 0;
if (!isPhp) {
H5AI.extended.init();
}
H5AI.core.init();
H5AI.sort.init();
H5AI.finder.init();
H5AI.zippedDownload.init();
H5AI.context.init();
if (isPhp) {
$('#tree').scrollpanel();
H5AI.core.shiftTree(false, true);
}
});
}(jQuery));

View File

@@ -3,6 +3,10 @@
// @include "inc/lib/jquery.mousewheel.js"
// @include "inc/lib/jquery.fracs-core.min.js"
// @include "inc/lib/jquery.scrollpanel.js"
// @include "inc/lib/jquery.qrcode.js"
// @include "inc/lib/amplify.min.js"
// @include "inc/lib/base64.js"
// @include "inc/lib/date.js"
// @include "inc/main.js"

View File

@@ -1,29 +0,0 @@
/*jslint browser: true, confusion: true, regexp: true, white: true */
/*jshint browser: true, confusion: true, regexp: false, white: false */
/*global jQuery, amplify, H5AI_CONFIG */
(function ($) {
"use strict";
var H5AI = {};
// @include "inc/Util.js"
// @include "inc/Core.js"
// @include "inc/Sort.js"
// @include "inc/ZippedDownload.js"
// @include "inc/Path.js"
// @include "inc/Connector.js"
// @include "inc/Html.js"
// @include "inc/Extended.js"
$(function () {
H5AI.extended.init();
H5AI.core.init();
H5AI.sort.init();
H5AI.zippedDownload.init();
});
}(jQuery));

View File

@@ -1,25 +0,0 @@
/*jslint browser: true, confusion: true, regexp: true, white: true */
/*jshint browser: true, confusion: true, regexp: false, white: false */
/*global jQuery, amplify, H5AI_CONFIG */
(function ($) {
"use strict";
var H5AI = {};
// @include "inc/Util.js"
// @include "inc/Core.js"
// @include "inc/Sort.js"
// @include "inc/ZippedDownload.js"
$(function () {
H5AI.core.init();
H5AI.sort.init();
H5AI.zippedDownload.init();
$("#tree").scrollpanel();
H5AI.core.shiftTree(false, true);
});
}(jQuery));

View File

@@ -1,5 +1,18 @@
<?php
function safe_dirname($path, $endWithSlash = false) {
$path = str_replace("\\", "/", dirname($path));
return preg_match("#^(\w:)?/$#", $path) ? $path : (preg_replace('#/$#', '', $path) . ($endWithSlash ? "/" : ""));
}
define("H5AI_ABS_PATH", safe_dirname(safe_dirname(__FILE__)));
function require_h5ai($lib) {
require_once(H5AI_ABS_PATH . $lib);
}
function fail($code, $msg, $cond = true) {
if ($cond) {
@@ -18,15 +31,14 @@ function checkKeys($keys) {
}
list($action) = checkKeys(array("action"));
require_once "config.php";
require_once "inc/H5ai.php";
require_h5ai("/php/inc/H5ai.php");
$h5ai = new H5ai();
$options = $h5ai->getOptions();
list($action) = checkKeys(array("action"));
if ($action === "httpcodes") {
list($hrefs) = checkKeys(array("hrefs"));
@@ -55,10 +67,10 @@ else if ($action === "thumb") {
fail(0, "thumbs are disabled", !$options["showThumbs"]);
list($srcAbsHref, $width, $height, $mode) = checkKeys(array("href", "width", "height", "mode"));
require_once "inc/Thumbnail.php";
require_once "inc/Image.php";
require_h5ai("/php/inc/Thumbnail.php");
require_h5ai("/php/inc/Image.php");
$srcAbsPath = $h5ai->getDocRoot() . rawurldecode($srcAbsHref);
$srcAbsPath = $h5ai->getRootAbsPath() . rawurldecode($srcAbsHref);
if (!Thumbnail::isUsable()) {
Image::showImage($srcAbsPath);
@@ -82,7 +94,7 @@ else if ($action === "tree") {
list($href) = checkKeys(array("href"));
require_once "inc/Tree.php";
require_h5ai("/php/inc/Tree.php");
$absHref = trim($href);
$absPath = $h5ai->getAbsPath($absHref);
@@ -99,19 +111,32 @@ else if ($action === "zip") {
fail(0, "zipped download is disabled", !$options["zippedDownload"]);
list($hrefs) = checkKeys(array("hrefs"));
require_once "inc/ZipIt.php";
require_h5ai("/php/inc/ZipIt.php");
$zipit = new ZipIt($h5ai);
$hrefs = explode(":", trim($hrefs));
$zipFile = $zipit->zip($hrefs);
if ($zipFile === false) {
fail(2, "something went wrong while building the zip");
if (is_string($zipFile)) {
$response = array('status' => 'ok', 'id' => basename($zipFile), 'size' => filesize($zipFile));
} else {
$response = array('status' => 'failed', 'code' => $zipFile);
}
echo json_encode($response);
}
else if ($action === "getzip") {
list($id) = checkKeys(array("id"));
fail(1, "zipped file not found: " . $id, !preg_match("/^h5ai-zip-/", $id));
$zipFile = str_replace("\\", "/", sys_get_temp_dir()) . "/" . $id;
fail(2, "zipped file not found: " . $id, !file_exists($zipFile));
header("Content-Disposition: attachment; filename=\"h5ai-selection.zip\"");
header("Content-Type: application/force-download");
header("Content-Type: application/octet-stream");
header("Content-Length: " . filesize($zipFile));
header("Connection: close");
readfile($zipFile);

View File

@@ -1,27 +0,0 @@
<?php
/*
* h5ai %BUILD_VERSION%
*
* PHP Configuration
* filesystem paths and file ignore rules
*/
global $H5AI_CONFIG;
$H5AI_CONFIG = array();
/*
* This configuration assumes that h5ai is installed
* in the webroot directory of the Apache server.
*/
$H5AI_CONFIG["H5AI_ROOT"] = dirname(dirname(__FILE__));
$H5AI_CONFIG["DOCUMENT_ROOT"] = dirname($H5AI_CONFIG["H5AI_ROOT"]);
/*
* Files/folders that should not be listed. Specified
* by the complete filename or by a regular expression.
* http://www.php.net/manual/en/function.preg-match.php
*/
$H5AI_CONFIG["IGNORE"] = array();
$H5AI_CONFIG["IGNORE_PATTERNS"] = array("/^\\./", "/^_h5ai/");
?>

View File

@@ -7,18 +7,22 @@
##############################################
class Cache {
private $dir;
function __construct($dir) {
$this->dir = $dir;
}
private function _name($key) {
return $this->dir . "/" . sha1($key);
}
public function get($key, $expiration = 3600) {
if (!is_dir($this->dir) || !is_writable($this->dir)) {
@@ -55,6 +59,7 @@ class Cache {
return $cache;
}
public function set($key, $data) {
if (!is_dir($this->dir) || !is_writable($this->dir)) {
@@ -78,6 +83,7 @@ class Cache {
return true;
}
public function clear($key) {
$cache_path = $this->_name($key);

View File

@@ -1,23 +1,26 @@
<?php
class Crumb {
private $h5ai, $parts;
public function __construct($h5ai) {
$this->h5ai = $h5ai;
$this->parts = array();
$href = $h5ai->getAbsHref();
while ($href !== "/" && $href !== "//") {
while ($href !== "/") {
$this->parts[] = $href;
$href = dirname($href) . "/";
$href = safe_dirname($href, true);
}
$this->parts[] = "/";
$this->parts = array_reverse($this->parts);
}
public function toHtml() {
$html = "";

View File

@@ -1,29 +1,34 @@
<?php
class Customize {
private $customHeader, $customFooter;
public function __construct($h5ai) {
$absPath = $h5ai->getAbsPath();
$options = $h5ai->getOptions();
$this->customHeader = $absPath . "/" . $options["customHeader"];
$this->customFooter = $absPath . "/" . $options["customFooter"];
$this->customHeader = $options["customHeader"] ? $absPath . "/" . $options["customHeader"] : false;
$this->customFooter = $options["customFooter"] ? $absPath . "/" . $options["customFooter"] : false;
}
public function getHeader() {
return $this->getContent($this->customHeader, "header");
}
public function getFooter() {
return $this->getContent($this->customFooter, "footer");
}
private function getContent($file, $tag) {
return file_exists($file) ? ("<" . $tag . ">" . file_get_contents($file) . "</" . $tag . ">") : "";
return (is_string($file) && file_exists($file)) ? ("<$tag>" . file_get_contents($file) . "</$tag>") : "";
}
}

View File

@@ -1,10 +1,12 @@
<?php
require_once "Thumbnail.php";
require_h5ai("/php/inc/Thumbnail.php");
class Entry {
private $h5ai, $label, $absPath, $absHref, $date, $isFolder, $type, $size, $thumbTypes;
private $h5ai, $label, $absPath, $absHref, $date, $isFolder, $type, $size;
public function __construct($h5ai, $absPath, $absHref, $type = null, $label = null) {
@@ -23,15 +25,15 @@ class Entry {
$this->type = $type !== null ? $type : $this->h5ai->getType($this->absPath);
$this->size = filesize($this->absPath);
}
$this->thumbTypes = array("bmp", "gif", "ico", "image", "jpg", "png", "tiff");
}
public function isFolder() {
return $this->isFolder;
}
public function toHtml() {
$classes = "entry " . ($this->isFolder ? "folder " : "file ") . $this->type;
@@ -55,7 +57,7 @@ class Entry {
}
}
}
if ($this->h5ai->showThumbs() && in_array($this->type, $this->thumbTypes)) {
if ($this->h5ai->showThumbs() && in_array($this->type, $this->h5ai->getThumbTypes())) {
$imgClass = " class='thumb' ";
$thumbnail = new Thumbnail($this->h5ai, $this->absHref, "square", 16, 16);
$thumbnail->create();
@@ -80,8 +82,10 @@ class Entry {
class Extended {
private $h5ai, $parent, $content;
public function __construct($h5ai) {
$this->h5ai = $h5ai;
@@ -90,12 +94,13 @@ class Extended {
$this->loadContent();
}
private function loadContent() {
if ($this->h5ai->getAbsHref() !== "/") {
$options = $this->h5ai->getOptions();
$parentPath = dirname($this->h5ai->getAbsPath());
$parentHref = dirname($this->h5ai->getAbsHref());
$parentPath = safe_dirname($this->h5ai->getAbsPath());
$parentHref = safe_dirname($this->h5ai->getAbsHref(), true);
$label = $options["setParentFolderLabels"] === true ? $this->h5ai->getLabel($parentHref) : "<span class='l10n-parentDirectory'>Parent Directory</span>";
$this->parent = new Entry($this->h5ai, $parentPath, $parentHref, "folder-parent", $label);
}
@@ -110,6 +115,7 @@ class Extended {
}
}
public function toHtml() {
$html = "<section id='extended' class='" . $this->h5ai->getView() . "-view clearfix'>\n";
@@ -125,11 +131,13 @@ class Extended {
if (count($this->content) === 0) {
$html .= "<div class='empty l10n-empty'>empty</div>";
}
$html .= "<div class='no-match l10n-noMatch'>no match</div>";
$html .="</section>";
return $html;
}
public function generateHeaders() {
private function generateHeaders() {
$html = "\t<li class='header'>\n";
$html .= "\t\t<a class='icon'></a>\n";

View File

@@ -1,34 +1,38 @@
<?php
require_once "Cache.php";
require_h5ai("/config.php");
require_h5ai("/php/inc/Cache.php");
class H5ai {
private static $VIEWMODES = array("details", "icons");
private $docRoot, $h5aiRoot, $h5aiAbsHref, $domain,
private $h5aiAbsPath,
$rootAbsPath, $ignore, $ignoreRE,
$config, $options, $types, $langs,
$cache,
$rootAbsHref, $h5aiAbsHref, $domain,
$absHref, $absPath,
$ignore, $ignoreRE,
$view;
public function __construct() {
global $H5AI_CONFIG;
$this->h5aiAbsPath = H5AI_ABS_PATH;
$this->docRoot = $H5AI_CONFIG["DOCUMENT_ROOT"];
$this->h5aiRoot = $H5AI_CONFIG["H5AI_ROOT"];
global $H5AI_CONFIG;
$this->rootAbsPath = $H5AI_CONFIG["ROOT_ABS_PATH"];
$this->ignore = $H5AI_CONFIG["IGNORE"];
$this->ignoreRE = $H5AI_CONFIG["IGNORE_PATTERNS"];
$this->config = $this->loadConfig($this->h5aiRoot . "/config.js");
$this->config = $this->loadConfig($this->h5aiAbsPath . "/config.js");
$this->options = $this->config["options"];
$this->types = $this->config["types"];
$this->langs = $this->config["langs"];
$this->cache = new Cache($this->h5aiRoot . "/cache");
$this->cache = new Cache($this->h5aiAbsPath . "/cache");
$this->hrefRoot = $this->options["rootAbsHref"];
$this->rootAbsHref = $this->options["rootAbsHref"];
$this->h5aiAbsHref = $this->options["h5aiAbsHref"];
$this->domain = getenv("HTTP_HOST");
@@ -56,101 +60,120 @@ class H5ai {
}
public function getDocRoot() {
public function getH5aiAbsPath() {
return $this->docRoot;
return $this->h5aiAbsPath;
}
public function getH5aiRoot() {
return $this->h5aiRoot;
public function getRootAbsPath() {
return $this->rootAbsPath;
}
public function getHrefRoot() {
return $this->hrefRoot;
public function getRootAbsHref() {
return $this->rootAbsHref;
}
public function getH5aiAbsHref() {
return $this->h5aiAbsHref;
}
public function getDomain() {
return $this->domain;
}
public function getView() {
return $this->view;
}
public function api() {
return $this->h5aiAbsHref . "php/api.php";
}
public function image($id) {
return $this->h5aiAbsHref . "images/" . $id . ".png";
}
public function icon($id, $big = false) {
return $this->h5aiAbsHref . "icons/" . ($big ? "48x48" : "16x16") . "/" . $id . ".png";
}
public function getOptions() {
return $this->options;
}
public function getLangs() {
return $this->langs;
}
public function normalizePath($path, $endWithSlash) {
return preg_match("#^(\w:)?/$#", $path) ? $path : (preg_replace('#/$#', '', $path) . ($endWithSlash ? "/" : ""));
}
public function getAbsHref($absPath = null, $endWithSlash = true) {
if ($absPath === null) {
return $this->absHref;
}
//
$absPath=substr($absPath, strlen($this->docRoot));
$absPath = substr($absPath, strlen($this->rootAbsPath));
$absHref = preg_replace("!^" . $this->docRoot . "!", "", $absPath);
$parts = explode("/", $absHref);
$parts = explode("/", $absPath);
$encodedParts = array();
foreach ($parts as $part) {
$encodedParts[] = rawurlencode($part);
}
$endodedAbsHref = implode("/", $encodedParts);
//
$endodedAbsHref = $this->hrefRoot . $endodedAbsHref;
return $this->normalizePath($endodedAbsHref, $endWithSlash);
return $this->normalizePath($this->rootAbsHref . implode("/", $encodedParts), $endWithSlash);
}
public function getAbsPath($absHref = null) {
if ($absHref === null) {
return $this->absPath;
}
//
$absHref=substr($absHref, strlen($this->hrefRoot));
$absHref = substr($absHref, strlen($this->rootAbsHref));
return $this->normalizePath($this->docRoot . "/" . rawurldecode($absHref), false);
return $this->normalizePath($this->rootAbsPath . "/" . rawurldecode($absHref), false);
}
public function showThumbs() {
return $this->options["showThumbs"] === true;
}
public function getThumbTypes() {
return $this->options["thumbTypes"];
}
public function getTitle() {
$title = $this->domain . rawurldecode($this->absHref);
@@ -162,6 +185,7 @@ class H5ai {
return $title;
}
public function getType($absPath) {
foreach($this->types as $type => $exts) {
@@ -174,9 +198,10 @@ class H5ai {
return "unknown";
}
public function ignoreThisFile($file) {
# always ignore
// always ignore
if ($file === "." || $file === ".." || $this->startsWith($file, '.ht')) {
return true;
}
@@ -193,6 +218,7 @@ class H5ai {
return false;
}
public function readDir($path) {
$content = array();
@@ -209,33 +235,32 @@ class H5ai {
return $content;
}
public function getLabel($absHref) {
return $absHref === "/" ? $this->domain : rawurldecode(basename($absHref));
}
public function normalizePath($path, $endWithSlash) {
return ($path === "/") ? "/" : (preg_replace('#/$#', '', $path) . ($endWithSlash ? "/" : ""));
}
public function startsWith($sequence, $start) {
return strcasecmp(substr($sequence, 0, strlen($start)), $start) === 0;
}
public function endsWith($sequence, $end) {
return strcasecmp(substr($sequence, -strlen($end)), $end) === 0;
}
public function getHttpCode($absHref) {
return $this->cachedHttpCode($absHref);
#return $this->fetchHttpCode($absHref);
#return $this->guessHttpCode($absHref);
//return $this->cachedHttpCode($absHref);
return $this->fetchHttpCode($absHref);
}
public function cachedHttpCode($absHref) {
$cached = $this->cache->get($absHref);
@@ -252,6 +277,7 @@ class H5ai {
return $cached["code"];
}
public function fetchHttpCode($absHref) {
$contentType = "Content-Type:";
@@ -285,19 +311,6 @@ class H5ai {
fclose($socket);
return $code;
}
public function guessHttpCode($absHref) {
$indexFiles = array("index.html", "index.cgi", "index.pl", "index.php", "index.xhtml", "index.htm");
$absPath = $this->getAbsPath($absHref);
$files = $this->readDir($absPath);
foreach ($files as $file) {
if (in_array($file, $indexFiles)) {
return 200;
}
}
return "h5ai";
}
}
?>

View File

@@ -2,13 +2,7 @@
class Image {
private $sourceFile;
private $source;
private $width;
private $height;
private $type;
private $dest;
private $sourceFile, $source, $width, $height, $type, $dest;
public static function isUsable() {
@@ -84,7 +78,7 @@ class Image {
public function releaseDest() {
if (!is_null($this->dest)) {
imagedestroy($this->dest);
@imagedestroy($this->dest);
$this->dest = null;
}
}
@@ -93,7 +87,7 @@ class Image {
public function releaseSource() {
if (!is_null($this->source)) {
imagedestroy($this->source);
@imagedestroy($this->source);
$this->sourceFile = null;
$this->source = null;
$this->width = null;

View File

@@ -1,31 +1,34 @@
<?php
require_once "Image.php";
require_h5ai("/php/inc/Image.php");
class Thumbnail {
private $srcAbsHref, $srcAbsPath, $width, $height, $name, $href, $path;
public static function isUsable() {
return Image::isUsable();
}
public function __construct($h5ai, $absHref, $mode, $width, $height) {
$this->h5ai = $h5ai;
$this->srcAbsHref = $absHref;
$this->srcAbsPath = $this->h5ai->getDocRoot() . urldecode($absHref);
$this->srcAbsPath = $this->h5ai->getRootAbsPath() . urldecode($absHref);
$this->width = $width;
$this->height = $height;
$this->mode = $mode;
$this->name = sha1("$this->srcAbsPath-$this->width-$this->height-$this->mode");
$this->href = $this->h5ai->getH5aiAbsHref() . "/cache/thumb-" . $this->name . ".jpg";
$this->path = $this->h5ai->getDocRoot() . $this->href;
$this->href = $this->h5ai->getH5aiAbsHref() . "cache/thumb-" . $this->name . ".jpg";
$this->path = $this->h5ai->getRootAbsPath() . $this->href;
$this->liveHref = $this->h5ai->api() . "?action=thumb&href=" . $this->srcAbsHref . "&width=" . $this->width . "&height=" . $this->height . "&mode=" . $this->mode;
}
public function create($force = 0) {
if (
@@ -40,16 +43,19 @@ class Thumbnail {
}
}
public function getHref() {
return $this->href;
}
public function getPath() {
return $this->path;
}
public function getLiveHref() {
return $this->liveHref;

View File

@@ -1,8 +1,10 @@
<?php
class TreeEntry {
private $h5ai, $label, $absPath, $absHref, $isFolder, $type, $content;
public function __construct($h5ai, $absPath, $absHref, $type = null) {
$this->h5ai = $h5ai;
@@ -16,6 +18,7 @@ class TreeEntry {
$this->content = null;
}
public function loadContent() {
$this->content = array();
@@ -36,6 +39,7 @@ class TreeEntry {
$this->sort();
}
public function cmpTrees($t1, $t2) {
if ($t1->isFolder && !$t2->isFolder) {
@@ -47,6 +51,7 @@ class TreeEntry {
return strcasecmp($t1->absPath, $t2->absPath);
}
public function sort() {
if ($this->content !== null) {
@@ -54,6 +59,7 @@ class TreeEntry {
}
}
public function toHtml() {
$classes = "entry " . $this->type . ($this->absHref === $this->h5ai->getAbsHref() ? " current" : "");
@@ -86,7 +92,7 @@ class TreeEntry {
$html .= "<span class='indicator" . $indicatorState . "'><img src='" . $this->h5ai->image("tree") . "' alt='>' /></span>\n";
}
$html .= "<a href='" . $this->absHref . "'>\n";
$html .= "<span class='icon'><img src='" . $this->h5ai->icon($icon) . "' alt='" . $icon . "' /></span>\n";
$html .= "<span class='icon'><img src='" . $this->h5ai->icon($icon) . "' alt='" . $icon . "' /></span>";
$html .= "<span class='label'>" . $this->label . "</span>" . $hint . "\n";
$html .= "</a>\n";
$html .= $this->contentToHtml();
@@ -94,6 +100,7 @@ class TreeEntry {
return $html;
}
public function contentToHtml() {
$html = "<ul class='content'>\n";
@@ -106,13 +113,14 @@ class TreeEntry {
return $html;
}
public function getRoot() {
if ($this->absHref === "/") {
return $this;
};
$tree = new TreeEntry($this->h5ai, dirname($this->absPath), dirname($this->absHref));
$tree = new TreeEntry($this->h5ai, safe_dirname($this->absPath), safe_dirname($this->absHref, true));
$tree->loadContent();
$tree->content[$this->absPath] = $this;
@@ -122,13 +130,16 @@ class TreeEntry {
class Tree {
private $h5ai;
public function __construct($h5ai) {
$this->h5ai = $h5ai;
}
public function toHtml() {
$options = $this->h5ai->getOptions();

View File

@@ -1,30 +1,42 @@
<?php
class ZipIt {
private $h5ai;
public function __construct($h5ai) {
$this->h5ai = $h5ai;
}
public function zip($hrefs) {
$zipFile = tempnam("/tmp", "h5ai-download");
$zipFile = tempnam(sys_get_temp_dir(), "h5ai-zip-");
$zip = new ZipArchive();
if (!$zip->open($zipFile, ZIPARCHIVE::CREATE)) {
return false;
return null;
}
$zip->addEmptyDir("/");
foreach ($hrefs as $href) {
$d = dirname($href);
$d = safe_dirname($href, true);
$n = basename($href);
if ($this->h5ai->getHttpCode($this->h5ai->getAbsHref($d)) === "h5ai" && !$this->h5ai->ignoreThisFile($n)) {
$code = $this->h5ai->getHttpCode($d);
if ($code == 401) {
return $code;
}
if ($code == "h5ai" && !$this->h5ai->ignoreThisFile($n)) {
$localFile = $this->h5ai->getAbsPath($href);
$file = preg_replace("!^" . $this->h5ai->getDocRoot() . "!", "", $localFile);
$file = preg_replace("!^" . $this->h5ai->getRootAbsPath() . "!", "", $localFile);
if (is_dir($localFile)) {
$this->zipDir($zip, $localFile, $file);
$rcode = $this->zipDir($zip, $localFile, $file);
if ($rcode == 401) {
return $rcode;
}
} else {
$this->zipFile($zip, $localFile, $file);
}
@@ -32,9 +44,10 @@ class ZipIt {
}
$zip->close();
return $zipFile;
return filesize($zipFile) ? $zipFile : null;
}
private function zipFile($zip, $localFile, $file) {
if (is_readable($localFile)) {
@@ -42,21 +55,28 @@ class ZipIt {
}
}
private function zipDir($zip, $localDir, $dir) {
if ($this->h5ai->getHttpCode($this->h5ai->getAbsHref($localDir)) === "h5ai") {
$code = $this->h5ai->getHttpCode($this->h5ai->getAbsHref($localDir));
if ($code == '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);
$rcode = $this->zipDir($zip, $localFile, $file);
if ($rcode == 401) {
return $rcode;
}
} else {
$this->zipFile($zip, $localFile, $file);
}
}
}
return code;
}
}

View File

@@ -1,11 +1,23 @@
<?php
require_once "config.php";
require_once "inc/H5ai.php";
require_once "inc/Crumb.php";
require_once "inc/Customize.php";
require_once "inc/Extended.php";
require_once "inc/Tree.php";
function safe_dirname($path, $endWithSlash = false) {
$path = str_replace("\\", "/", dirname($path));
return preg_match("#^(\w:)?/$#", $path) ? $path : (preg_replace('#/$#', '', $path) . ($endWithSlash ? "/" : ""));
}
define("H5AI_ABS_PATH", safe_dirname(safe_dirname(__FILE__)));
function require_h5ai($lib) {
require_once(H5AI_ABS_PATH . $lib);
}
require_h5ai("/php/inc/H5ai.php");
require_h5ai("/php/inc/Crumb.php");
require_h5ai("/php/inc/Customize.php");
require_h5ai("/php/inc/Extended.php");
require_h5ai("/php/inc/Tree.php");
$h5ai = new H5ai();
$crumb = new Crumb($h5ai);

View File

@@ -8,11 +8,11 @@
# pure JavaScript version
HeaderName /_h5ai/header.html
ReadmeName /_h5ai/footer.html
# PHP version
# HeaderName /_h5ai/header.php
# ReadmeName /_h5ai/footer.php
ReadmeName /_h5ai/footer.html
IndexIgnore _h5ai*

View File

@@ -1,4 +0,0 @@
#! /usr/bin/env node
// -*- js -*-
require("wepp").processArgs(process.argv);

View File

@@ -1,40 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<project name="wepp.macros" basedir=".">
<macrodef name="wepp">
<attribute name="file" />
<attribute name="toFile" />
<attribute name="args" default="" />
<sequential>
<exec executable="${tool.wepp}">
<arg line="@{args}" />
<arg value="--in" />
<arg value="@{file}" />
<arg value="--out" />
<arg value="@{toFile}" />
</exec>
</sequential>
</macrodef>
<macrodef name="wepp.dir">
<attribute name="dir" />
<attribute name="args" default="" />
<sequential>
<exec executable="${tool.wepp}">
<arg line="@{args}" />
<arg value="--inDir" />
<arg value="@{dir}" />
<arg value="--outDir" />
<arg value="@{dir}" />
</exec>
<delete dir="@{dir}/inc">
<fileset
dir="."
includes="@{dir}/**/*.less"
excludes="@{dir}/inc/**,@{dir}/lib/**"
/>
</delete>
</sequential>
</macrodef>
</project>