1
0
mirror of https://github.com/lrsjng/h5ai.git synced 2025-08-30 09:10:28 +02:00

Compare commits

..

21 Commits

Author SHA1 Message Date
Lars Jung
74d967a27a Merge branch 'develop' 2011-11-02 00:57:18 +01:00
Lars Jung
6a5c35ad9a Last changes before release. 2011-11-02 00:56:55 +01:00
Lars Jung
4901034721 A lot of small fixes. 2011-11-01 22:33:00 +01:00
Lars Jung
8b1d6b9ef7 Updates readme. 2011-10-30 22:05:25 +01:00
Lars Jung
0fcd4e9709 Merge branch 'redesign-js' into develop 2011-10-30 21:55:05 +01:00
Lars Jung
4a65ce61df Improves file selection for zipped download. Zipped download is now disabled by default. 2011-10-30 21:50:25 +01:00
Lars Jung
3c23c7e956 Changes default language from to . 2011-10-07 16:38:30 +02:00
Lars Jung
caced60eaa More refactorings. 2011-10-06 05:12:29 +02:00
Lars Jung
4c1ed3d1e8 Redesigned js. 2011-09-29 13:43:22 +02:00
Lars Jung
8670b248a9 Refactorings. 2011-09-27 17:45:09 +02:00
Lars Jung
7f46dceba0 Minor refactorings. 2011-09-24 03:26:03 +02:00
Lars Jung
a95aef17be Removed release folder. 2011-09-23 17:09:05 +02:00
Lars Jung
e8dcb83d92 Improved HTML head sections. 2011-09-23 17:05:40 +02:00
Lars Jung
03de1d9472 Sorted translations in options.js. 2011-09-18 22:45:30 +02:00
Lars Jung
5e486e0aa2 Moved to version 0.16. 2011-09-18 19:54:18 +02:00
Lars Jung
a8f62f187c Added it translation. Switched to wepp. 2011-09-18 19:49:26 +02:00
Lars Jung
8e21a3c038 Fixed security issues. 2011-09-06 20:57:49 +02:00
Lars Jung
df30c67ade Added selection and zipped download. 2011-09-04 21:18:55 +02:00
Lars Jung
2d3b0eed4f Added selection and zipped download. 2011-09-04 21:18:19 +02:00
Lars Jung
a371ee2afd Minor additions. 2011-09-01 14:27:58 +02:00
Lars Jung
480c4aab79 Added thumbs and slide option. 2011-08-16 21:03:09 +02:00
67 changed files with 4037 additions and 3223 deletions

4
.gitignore vendored
View File

@@ -1,10 +1,8 @@
# Build folders to ignore
bin
build
target
build.local.*
release
# Eclipse

View File

@@ -2,13 +2,69 @@
* Website with download, docs and demo: <http://larsjung.de/h5ai>
* Sources: <http://github.com/lrsjng/h5ai>
* Q&A group: <http://groups.google.com/group/h5ai>
h5ai is provided under the terms of the [MIT License](http://github.com/lrsjng/h5ai/blob/master/LICENSE.txt).
It uses the [Faenza icon set](http://tiheum.deviantart.com/art/Faenza-Icons-173323228) (GPL license).
## h5ai profits from these great projects
* [AmplifyJS](http://amplifyjs.com) (MIT/GPL)
* [Datejs](http://www.datejs.com) (MIT)
* [Faenza icon set](http://tiheum.deviantart.com/art/Faenza-Icons-173323228) (GPL)
* [HTML5 ★ Boilerplate](http://html5boilerplate.com)
* [jQuery](http://jquery.com) (MIT/GPL)
* [jQuery.mousewheel](http://github.com/brandonaaron/jquery-mousewheel) (MIT)
* [modernizr](http://www.modernizr.com) (MIT/BSD)
## Changelog
### v0.16 · *2011-11-02*
* sorts translations in `options.js`
* improves HTML head sections
* refactors JavaScript and PHP a lot
* improves/fixes file selection for zipped download
* fixes scrollbar and header/footer link issues (didn't work when zipped download enabled)
* adds support for ctrl-select
* `dateFormat` in `options.js` changed, now affecting JS and PHP version
* `dateFormat` is localizable by adding it to a translation in `options.js`
* PHP version is now configurable via `php/config.php` (set custom doc root and other PHP related things)
* image thumbs and zipped download is disabled by default now, but works fine if PHP is configured
### 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*
* fixed security issues with the zipped download feature
* made zipped download optional (but enabled by default)
### v0.15 · *2011-09-04*
* added zipped download for selected files
* cleaned and refactored
### 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)
* added pl translation by Radosław Zając
* added ru translation by Богдан Илюхин
### 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*

View File

@@ -1,20 +1,20 @@
custom = true
custom = true
# project
project.name = h5ai
project.version = 0.13.2
project.name = h5ai
project.version = 0.16
# src
src.dir = src
src.dir = src
# build
build.dir = build
release.dir = release
build.dir = build
release.dir = release
# libs
lib.scripp.jar = tools/scripp.jar
# tools
tool.wepp = tools/wepp

114
build.xml
View File

@@ -1,81 +1,57 @@
<?xml version="1.0" encoding="utf-8"?>
<project
name="h5ai"
basedir="."
default="release"
xmlns:scripp="antlib:de.larsjung.scripp.ant"
name="h5ai"
basedir="."
default="release"
>
<target name="init">
<property file="build.properties" />
<tstamp>
<format property="build.stamp" pattern="yyyy-MM-dd-HHmmss" />
</tstamp>
<property name="build.label" value="${project.name} ${project.version} b${build.stamp}" />
<echo>Build: ${build.label}</echo>
<taskdef
resource="de/larsjung/scripp/ant/antlib.xml"
uri="antlib:de.larsjung.scripp.ant"
classpath="${lib.scripp.jar}"
/>
</target>
<import file="tools/wepp.ant.xml" />
<target name="clean" depends="init">
<delete dir="${build.dir}" />
<delete dir="${release.dir}" />
</target>
<target name="init">
<property file="build.properties" />
<tstamp>
<format property="build.stamp" pattern="yyyy-MM-dd-HHmmss" />
</tstamp>
<property name="build.label" value="${project.name} ${project.version} b${build.stamp}" />
<echo>Build: ${build.label}</echo>
</target>
<target name="clean" depends="init">
<delete dir="${build.dir}" />
<delete dir="${release.dir}" />
</target>
<target name="build-prepare" depends="clean">
<mkdir dir="${build.dir}" />
<copy todir="${build.dir}">
<fileset dir="${src.dir}" />
<fileset file="LICENSE.txt" />
<fileset file="README.md" />
</copy>
<replace dir="${build.dir}">
<replacefilter token="%BUILD%" value="${build.label}" />
<replacefilter token="%BUILD_NAME%" value="${project.name}" />
<replacefilter token="%BUILD_VERSION%" value="${project.version}" />
<replacefilter token="%BUILD_STAMP%" value="${build.stamp}" />
</replace>
</target>
<target name="build-prepare" depends="clean">
<mkdir dir="${build.dir}" />
<copy todir="${build.dir}">
<fileset dir="${src.dir}" />
<fileset file="LICENSE.txt" />
<fileset file="README.md" />
</copy>
<replace dir="${build.dir}">
<replacefilter token="%BUILD%" value="${build.label}" />
<replacefilter token="%BUILD_NAME%" value="${project.name}" />
<replacefilter token="%BUILD_VERSION%" value="${project.version}" />
<replacefilter token="%BUILD_STAMP%" value="${build.stamp}" />
</replace>
</target>
<target name="build" depends="build-prepare">
<scripp.dir dir="${build.dir}/h5ai/css" />
<scripp.dir dir="${build.dir}/h5ai/js" />
</target>
<target name="build" depends="build-prepare">
<wepp.dir dir="${build.dir}/h5ai/css" />
<wepp.dir dir="${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" />
</target>
<target name="build-uncompressed" depends="build-prepare">
<scripp.dir dir="${build.dir}/h5ai/css" compress="false" />
<scripp.dir dir="${build.dir}/h5ai/js" compress="false" />
</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="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>
<macrodef name="scripp.dir">
<attribute name="dir" />
<attribute name="compress" default="true" />
<sequential>
<scripp:process compress="@{compress}">
<fileset dir="@{dir}" includes="**/*.less,**/*.css,**/*.js" excludes="inc/**/*,**/*.min.css,**/*.min.js" />
<globmapper from="*.less" to="*.css" />
<globmapper from="*.css" to="*.css" />
<globmapper from="*.js" to="*.js" />
</scripp:process>
<delete dir="@{dir}/inc">
<fileset dir="@{dir}" includes="**/*.less" />
</delete>
</sequential>
</macrodef>
</project>

View File

@@ -19,14 +19,17 @@ AddType text/html .php
# cache images, css and js for 52 weeks
<IfModule headers_module>
<FilesMatch "\.png$">
Header set Cache-Control "max-age=31449600, public"
</FilesMatch>
<FilesMatch "\.css$">
Header set Cache-Control "max-age=31449600, public"
</FilesMatch>
<FilesMatch "\.js$">
Header set Cache-Control "max-age=31449600, public"
</FilesMatch>
<FilesMatch "\.png$">
Header set Cache-Control "max-age=31449600, public"
</FilesMatch>
<FilesMatch "\.css$">
Header set Cache-Control "max-age=31449600, public"
</FilesMatch>
<FilesMatch "\.js$">
Header set Cache-Control "max-age=31449600, public"
</FilesMatch>
<FilesMatch "thumb-.*\.jpg$">
Header set Cache-Control "max-age=31449600, public"
</FilesMatch>
</IfModule>

View File

@@ -1,219 +1,265 @@
#extended.details-view {
display: none;
display: none;
ul {
margin: 0;
padding: 0;
list-style: none;
ul {
margin: 0;
padding: 0;
list-style: none;
li {
position: relative;
white-space: nowrap;
clear: both;
li {
position: relative;
white-space: nowrap;
clear: both;
&.header {
a, a:active, a:visited {
padding-bottom: 18px;
color: #555;
text-decoration: none;
opacity: 0.4;
cursor: pointer;
.transition( all 0.2s ease-in-out );
&:hover {
color: #555;
opacity: 0.9;
}
img {
width: 12px;
height: 12px;
padding: 0 8px;
}
}
}
&.entry {
border-bottom: 1px solid #ddd;
&.header {
a, a:active, a:visited {
padding-bottom: 18px;
color: #555;
text-decoration: none;
opacity: 0.4;
cursor: pointer;
.transition(all 0.2s ease-in-out);
a, a:active, a:visited {
display: block;
color: #555;
text-decoration: none;
cursor: pointer;
&:hover, &.hover {
background-color: #f6f6f6;
color: #e80;
}
}
&.error {
a, a:active, a:visited {
color: #aaa;
.label {
.hint {
margin-left: 12px;
font-size: 0.9em;
color: #c55;
}
}
&:hover, &.hover {
opacity: 1;
background-color: #f6f6f6;
color: #e80;
}
}
}
&.folder-parent {
.date, .size {
display: none;
}
}
&.folder {
.size {
display: none;
}
}
}
.icon, .label, .date, .size {
padding: 6px;
}
.icon {
display: inline-block;
position: absolute;
left: 0;
top: 2px;
width: 16px;
&:hover {
color: #555;
opacity: 0.9;
}
img {
width: 12px;
height: 12px;
padding: 0 8px;
}
}
}
&.entry {
img {
width: 16px;
height: 16px;
}
}
.icon.big {
display: none;
}
.label {
display: block;
margin: 0 270px 0 24px;
overflow: hidden;
white-space: nowrap;
text-align: left;
}
.date {
position: absolute;
right: 100px;
top: 0;
text-align: right;
width: 160px;
white-space: nowrap;
}
.size {
position: absolute;
right: 0;
top: 0;
text-align: right;
width: 80px;
white-space: nowrap;
}
}
}
.empty {
text-align: center;
margin: 50px 0;
color: #ddd;
font-size: 5em;
font-weight: bold;
}
a, a:active, a:visited {
display: block;
color: #555;
text-decoration: none;
cursor: pointer;
border-bottom: 1px solid #ddd;
&:hover, &.hover {
background-color: #f6f6f6;
color: #e80;
}
&.selected:not(.selecting), &.selecting:not(.selected) {
border-color: rgba(240,100,0,0.2);
background-color: rgba(240,100,0,0.2);
}
}
&.error {
a, a:active, a:visited {
color: #aaa;
.label {
.hint {
margin-left: 12px;
font-size: 0.9em;
color: #c55;
}
}
&:hover, &.hover {
opacity: 1;
background-color: #f6f6f6;
color: #e80;
}
}
}
&.folder-parent {
.date, .size {
display: none;
}
}
&.folder {
.size {
display: none;
}
}
}
.icon, .label, .date, .size {
padding: 6px;
}
.icon {
display: inline-block;
position: absolute;
left: 0;
top: 2px;
width: 16px;
img {
width: 16px;
height: 16px;
}
}
.icon.big {
display: none;
}
.label {
display: block;
margin: 0 270px 0 24px;
overflow: hidden;
white-space: nowrap;
text-align: left;
}
.date {
position: absolute;
right: 100px;
top: 0;
text-align: right;
width: 160px;
white-space: nowrap;
}
.size {
position: absolute;
right: 0;
top: 0;
text-align: right;
width: 80px;
white-space: nowrap;
}
&.entry.thumb .icon.small {
overflow: hidden;
padding: 5px;
img {
background-color: #eee;
width: 16px;
height: 16px;
border: 1px solid #ddd;
overflow: hidden;
}
}
}
}
.empty {
text-align: center;
margin: 50px 0;
color: #ddd;
font-size: 5em;
font-weight: bold;
}
}
#selection-rect {
display: none;
position: absolute;
left: 0;
top: 0;
z-index: 2;
border: 1px dashed rgba(240,100,0,0.5);
background-color: rgba(240,100,0,0.2);
}
#extended.icons-view {
display: none;
padding: 3px;
border: 1px solid #eee;
border-radius: 15px;
display: none;
padding: 3px;
border: 1px solid #eee;
border-radius: 15px;
ul {
margin: 0;
padding: 0;
list-style: none;
ul {
margin: 0;
padding: 0;
list-style: none;
li {
&.header {
display: none;
}
&.entry {
float: left;
li {
&.header {
display: none;
}
&.entry {
float: left;
a, a:active, a:visited {
display: block;
margin: 8px;
padding: 8px;
width: 100px;
height: 120px;
float: left;
text-align: center;
text-decoration: none;
overflow: hidden;
border-radius: 5px;
color: #555;
cursor: pointer;
border: 2px solid rgba(0,0,0,0);
&:hover, &.hover {
color: #e80;
border-color: #eee;
background-color: #f6f6f6;
}
.icon {
display: block;
a, a:active, a:visited {
display: block;
margin: 8px;
padding: 8px;
width: 100px;
height: 120px;
float: left;
text-align: center;
text-decoration: none;
overflow: hidden;
border-radius: 5px;
color: #555;
cursor: pointer;
border: 2px solid rgba(0,0,0,0);
img {
width: 48px;
height: 48px;
margin-bottom: 8px;
}
}
.icon.small {
display: none;
}
.label {
display: block;
word-wrap: break-word;
}
.date, .size {
display: none;
}
}
&.error {
a, a:active, a:visited {
color: #aaa;
text-decoration: none;
.label {
.hint {
padding: 0 6px;
font-size: 0.9em;
color: #c55;
}
}
&:hover, &.hover {
color: #e80;
border-color: #eee;
background-color: #f6f6f6;
}
}
}
}
}
}
.empty {
padding: 16px;
height: 120px;
text-align: center;
color: #ddd;
font-size: 5em;
font-weight: bold;
}
&:hover, &.hover {
color: #e80;
border-color: #eee;
background-color: #f6f6f6;
}
&.selected:not(.selecting), &.selecting:not(.selected) {
border-color: rgba(240,100,0,0.2);
background-color: rgba(240,100,0,0.2);
}
.icon {
display: block;
img {
min-width: 48px;
min-height: 48px;
margin-bottom: 8px;
}
}
.icon.small {
display: none;
}
.label {
display: block;
word-wrap: break-word;
}
.date, .size {
display: none;
}
}
&.error {
a, a:active, a:visited {
color: #aaa;
text-decoration: none;
.label {
.hint {
padding: 0 6px;
font-size: 0.9em;
color: #c55;
}
}
&:hover, &.hover {
color: #e80;
border-color: #eee;
background-color: #f6f6f6;
}
}
}
}
&.entry.thumb .icon.big {
width: 100px;
height: 58px;
overflow: hidden;
img {
background-color: #eee;
min-width: 46px;
min-height: 46px;
min-width: 12px;
min-height: 12px;
border: 1px solid #ddd;
overflow: hidden;
}
}
}
}
.empty {
padding: 16px;
height: 120px;
text-align: center;
color: #ddd;
font-size: 5em;
font-weight: bold;
}
}

View File

@@ -53,8 +53,8 @@ sup { top: -0.5em; }
sub { bottom: -0.25em; }
pre { white-space: pre; white-space: pre-wrap; word-wrap: break-word; padding: 15px; }
textarea { overflow: auto; }
.ie6 legend, .ie7 legend { margin-left: -7px; }
textarea { overflow: auto; }
.ie6 legend, .ie7 legend { margin-left: -7px; }
input[type="radio"] { vertical-align: text-bottom; }
input[type="checkbox"] { vertical-align: bottom; }
.ie7 input[type="checkbox"] { vertical-align: baseline; }
@@ -81,7 +81,7 @@ a:hover { color: #036; }
/**
* Primary styles
*
* Author:
* Author:
*/
@@ -117,20 +117,20 @@ a:hover { color: #036; }
}
@media screen and (max-device-width: 480px) {
/* html { -webkit-text-size-adjust:none; -ms-text-size-adjust:none; } */
}
@media print {
* { background: transparent !important; color: black !important; text-shadow: none !important; filter:none !important;
-ms-filter: none !important; }
-ms-filter: none !important; }
a, a:visited { color: #444 !important; text-decoration: underline; }
a[href]:after { content: " (" attr(href) ")"; }
abbr[title]:after { content: " (" attr(title) ")"; }
.ir a:after, a[href^="javascript:"]:after, a[href^="#"]:after { content: ""; }
.ir a:after, a[href^="javascript:"]:after, a[href^="#"]:after { content: ""; }
pre, blockquote { border: 1px solid #999; page-break-inside: avoid; }
thead { display: table-header-group; }
thead { display: table-header-group; }
tr, img { page-break-inside: avoid; }
@page { margin: 0.5cm; }
p, h2, h3 { orphans: 3; widows: 3; }

View File

@@ -4,108 +4,113 @@
html.js {
.hideOnJs {
display: none;
}
.hideOnJs {
display: none;
}
}
html.no-js {
.hideOnNoJs {
display: none;
}
.hideOnNoJs {
display: none;
}
}
body {
font-family: Ubuntu, sans-serif;
font-size: 16px;
color: #555;
margin: 80px 30px;
font-family: Ubuntu, sans-serif;
font-size: 16px;
color: #555;
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);
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;
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);
&: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 {
width: 16px;
height: 16px;
vertical-align: bottom;
padding: 0 6px 6px 0;
}
.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;
vertical-align: baseline;
padding: 0px;
}
}
.view {
float: right;
border-left: 1px solid rgb(231,231,231);
}
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 {
width: 16px;
height: 16px;
vertical-align: bottom;
padding: 0 6px 6px 0;
}
.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;
vertical-align: baseline;
padding: 0px;
}
}
.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;
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;
}
> 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;
}
}
@@ -115,80 +120,91 @@ body > nav {
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;
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);
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 300px;
}
.right {
display: block;
padding: 0 8px;
float: right
}
#langSelector {
position: relative;
cursor: pointer;
.langOptions {
position: absolute;
z-index: 2;
display: none;
right: 0;
top: 0;
background-color: rgb(241,241,241);
border: 1px solid rgb(210,210,210);
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);
}
}
}
}
}
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 300px;
}
.right {
display: block;
padding: 0 8px;
float: right
}
.status {
.sep {
display: inline-block;
padding: 0 6px;
}
&.default {
}
&.dynamic {
display: none;
}
}
#langSelector {
position: relative;
cursor: pointer;
.langOptions {
position: absolute;
z-index: 2;
display: none;
right: 0;
top: 0;
background-color: rgb(241,241,241);
border: 1px solid rgb(210,210,210);
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,38 +1,38 @@
.border-radius ( @radius ) {
-moz-border-radius: @radius;
-webkit-border-radius: @radius;
border-radius: @radius;
.border-radius (@radius) {
-moz-border-radius: @radius;
-webkit-border-radius: @radius;
border-radius: @radius;
}
.box-shadow ( @shadow ) {
-moz-box-shadow: @shadow;
-webkit-box-shadow: @shadow;
box-shadow: @shadow;
.box-shadow (@shadow) {
-moz-box-shadow: @shadow;
-webkit-box-shadow: @shadow;
box-shadow: @shadow;
}
.transition ( @transition ) {
-moz-transition: @transition;
-ms-transition: @transition;
-o-transition: @transition;
-webkit-transition: @transition;
transition: @transition;
.transition (@transition) {
-moz-transition: @transition;
-ms-transition: @transition;
-o-transition: @transition;
-webkit-transition: @transition;
transition: @transition;
}
.transform ( @transform ) {
-moz-transform: @transform;
-o-transform: @transform;
-webkit-transform: @transform;
transform: @transform;
.transform (@transform) {
-moz-transform: @transform;
-o-transform: @transform;
-webkit-transform: @transform;
transform: @transform;
}
.background-size ( @size ) {
-moz-background-size: @size;
-webkit-background-size: @size;
background-size: @size;
.background-size (@size) {
-moz-background-size: @size;
-webkit-background-size: @size;
background-size: @size;
}

View File

@@ -1,68 +1,68 @@
#table {
table {
display: block;
width: 100%;
border-collapse: collapse;
table {
display: block;
width: 100%;
border-collapse: collapse;
th, td {
padding: 3px 6px;
text-align: left;
border: none;
}
th {
padding-bottom: 18px;
opacity: 0.4;
.transition( all 0.2s ease-in-out );
th, td {
padding: 3px 6px;
text-align: left;
border: none;
}
th {
padding-bottom: 18px;
opacity: 0.4;
.transition(all 0.2s ease-in-out);
&:hover, &:hover a {
color: #555;
cursor: pointer;
opacity: 0.9;
}
a, a:visited {
color: #555;
font-weight: normal;
&:hover, &:hover a {
color: #555;
cursor: pointer;
opacity: 0.9;
}
a, a:visited {
color: #555;
font-weight: normal;
img {
width: 12px;
height: 12px;
padding: 0 8px;
}
}
}
td {
border: 1px solid #ddd;
border-left: none;
border-right: none;
}
td:nth-child(1), th:nth-child(1) {
text-align: center;
width: 16px;
img {
width: 12px;
height: 12px;
padding: 0 8px;
}
}
}
td {
border: 1px solid #ddd;
border-left: none;
border-right: none;
}
td:nth-child(1), th:nth-child(1) {
text-align: center;
width: 16px;
img {
width: 16px;
height: 16px;
padding-top: 2px;
}
}
td:nth-child(2), th:nth-child(2) {
width: 682px;
max-width: 682px;
overflow: hidden;
white-space: nowrap;
}
td:nth-child(3), th:nth-child(3) {
text-align: right;
width: 160px;
min-width: 160px;
white-space: nowrap;
}
td:nth-child(4), th:nth-child(4) {
text-align: right;
width: 70px;
min-width: 70px;
white-space: nowrap;
}
}
img {
width: 16px;
height: 16px;
padding-top: 2px;
}
}
td:nth-child(2), th:nth-child(2) {
width: 682px;
max-width: 682px;
overflow: hidden;
white-space: nowrap;
}
td:nth-child(3), th:nth-child(3) {
text-align: right;
width: 160px;
min-width: 160px;
white-space: nowrap;
}
td:nth-child(4), th:nth-child(4) {
text-align: right;
width: 70px;
min-width: 70px;
white-space: nowrap;
}
}
}

View File

@@ -1,129 +1,129 @@
#tree {
display: none;
position: fixed;
left: 0;
top: 82px;
z-index: 1;
overflow: auto;
font-size: 0.85em;
padding: 16px 16px 16px 16px;
background-color: rgb(241,241,241);
border: 2px solid rgb(210,210,210);
border-left: none;
.border-radius ( 0 15px 15px 0 );
display: none;
position: fixed;
left: 0;
top: 82px;
z-index: 1;
overflow: auto;
font-size: 0.85em;
padding: 16px 16px 16px 16px;
background-color: rgb(241,241,241);
border: 2px solid rgb(210,210,210);
border-left: none;
.border-radius (0 15px 15px 0);
> .scrollbar {
margin: 12px 12px 12px 0;
width: 6px;
background-color: rgb(210,210,210);
.border-radius( 3px );
.drag {
background-color: rgb(180,180,180);
.border-radius( 3px );
}
&.dragOn .drag {
background-color: rgb(150,150,150);
}
}
.entry {
.blank, .indicator {
display: inline-block;
width: 16px;
height: 25px;
float: left;
}
.indicator {
opacity: 0.7;
.transition( all 0.2s ease-in-out );
cursor: pointer;
&:hover {
opacity: 1;
}
img {
position: relative;
left: 0;
top: 3px;
width: 12px;
height: 12px;
vertical-align: bottom;
.transition( all 0.2s ease-in-out );
}
&.open {
img {
.transform( rotate(90deg) );
}
}
&.unknown {
opacity: 0.3;
}
}
> a, > a:active, > a.visited {
margin-left: 16px;
padding: 4px 6px;
border: 1px solid rgba(0,0,0,0);
.border-radius( 5px );
display: block;
color: #555;
text-decoration: none;
opacity: 0.7;
> .scrollbar {
margin: 12px 12px 12px 0;
width: 6px;
background-color: rgb(210,210,210);
.border-radius(3px);
&:hover, &.hover {
color: #e80;
background-color: rgba(255,255,255,0.5);
opacity: 1;
}
.label {
display: inline-block;
}
.icon {
display: inline-block;
width: 20px;
img {
width: 16px;
height: 16px;
vertical-align: bottom;
}
}
.hint {
display: inline-block;
margin-left: 12px;
font-size: 0.9em;
color: #ccc;
img {
width: 10px;
height: 10px;
vertical-align: baseline;
}
}
}
&.file {
display: none;
}
&.current {
> a, > a:active, > a:visited {
border: 1px solid rgb(221,221,221);
background-color: rgba(255,255,255,0.5);
opacity: 1;
}
}
&.error {
> a, > a:active, > a:visited {
color: #999;
&:hover, &.hover {
color: #e80;
}
}
.hint {
color: #c55;
}
}
.content {
list-style: none;
margin-left: 20px;
}
}
.drag {
background-color: rgb(180,180,180);
.border-radius(3px);
}
&.dragOn .drag {
background-color: rgb(150,150,150);
}
}
.entry {
.blank, .indicator {
display: inline-block;
width: 16px;
height: 25px;
float: left;
}
.indicator {
opacity: 0.7;
.transition(all 0.2s ease-in-out);
cursor: pointer;
&:hover {
opacity: 1;
}
img {
position: relative;
left: 0;
top: 3px;
width: 12px;
height: 12px;
vertical-align: bottom;
.transition(all 0.2s ease-in-out);
}
&.open {
img {
.transform(rotate(90deg));
}
}
&.unknown {
opacity: 0.3;
}
}
> a, > a:active, > a.visited {
margin-left: 16px;
padding: 4px 6px;
border: 1px solid rgba(0,0,0,0);
.border-radius(5px);
display: block;
color: #555;
text-decoration: none;
opacity: 0.7;
&:hover, &.hover {
color: #e80;
background-color: rgba(255,255,255,0.5);
opacity: 1;
}
.label {
display: inline-block;
}
.icon {
display: inline-block;
width: 20px;
img {
width: 16px;
height: 16px;
vertical-align: bottom;
}
}
.hint {
display: inline-block;
margin-left: 12px;
font-size: 0.9em;
color: #ccc;
img {
width: 10px;
height: 10px;
vertical-align: baseline;
}
}
}
&.file {
display: none;
}
&.current {
> a, > a:active, > a:visited {
border: 1px solid rgb(221,221,221);
background-color: rgba(255,255,255,0.5);
opacity: 1;
}
}
&.error {
> a, > a:active, > a:visited {
color: #999;
&:hover, &.hover {
color: #e80;
}
}
.hint {
color: #c55;
}
}
.content {
list-style: none;
margin-left: 20px;
}
}
}

View File

@@ -3,13 +3,15 @@
#table {
display: none;
display: none;
}
#tree, #content > header, #content > footer {
display: block;
display: block;
}
html.no-js {
#extended.details-view, #extended.icons-view {
display: block;
}
#extended.details-view, #extended.icons-view {
display: block;
}
}

View File

@@ -1,30 +1,34 @@
<!-- generated code ends here -->
</section>
<section id="extended"></section>
<footer></footer>
</section>
<section id="tree"></section>
<footer class="clearfix">
<span class="left">
<a href="http://larsjung.de/h5ai" target="_blank" title="h5ai project page">h5ai %BUILD_VERSION% (js)</a>
</span>
<span class="right">
<span class="hideOnJs">JavaScript is disabled!</span>
<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="folderCount"></span> <span class="l10n-folders">folders</span>
·
<span class="fileCount"></span> <span class="l10n-files">files</span>
</span>
</span>
</footer>
<script src="/h5ai/js/lib/jquery.min.js"></script>
<script src="/h5ai/options.js"></script>
<script src="/h5ai/js/main-js.js"></script>
<!-- generated code ends here -->
</section>
<section id="extended" class="clearfix"></section>
<footer></footer>
</section>
<section id="tree"></section>
<footer class="clearfix">
<span class="left">
<a href="http://larsjung.de/h5ai" target="_blank" title="h5ai project page">h5ai %BUILD_VERSION% (js)</a>
</span>
<span class="right">
<span class="hideOnJs">JavaScript is disabled!</span>
<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="folderCount"></span> <span class="l10n-folders">folders</span>
<span class='sep'>·</span>
<span class="fileCount"></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/options.js"></script>
<script src="/h5ai/js/main-js.js"></script>
</body>
</html>

View File

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

View File

@@ -1,34 +1,42 @@
<!DOCTYPE html>
<html class="no-js">
<!--[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]-->
<head>
<meta charset="utf-8">
<title>Directory index · styled with h5ai</title>
<meta name="h5ai-version" content="h5ai %BUILD_VERSION% (js)">
<meta name="description" content="Directory index styled with h5ai (http://larsjung.de/h5ai)">
<meta name="keywords" content="directory, index, autoindex, h5ai">
<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" type="text/css" href="http://fonts.googleapis.com/css?family=Ubuntu:regular,italic,bold">
<link rel="stylesheet" type="text/css" href="/h5ai/css/main-js.css">
<script src="/h5ai/js/lib/modernizr.min.js"></script>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<title>Directory index · styled with h5ai</title>
<meta name="h5ai-version" content="h5ai %BUILD_VERSION% (js)">
<meta name="description" content="Directory index styled with h5ai (http://larsjung.de/h5ai)">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<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">
<script src="/h5ai/js/modernizr.min.js"></script>
</head>
<body>
<nav class="clearfix">
<ul>
<li id="viewicons" class="view hideOnNoJs">
<a href="#"><img src="/h5ai/images/view-icons.png" alt="view-icons" /><span class="l10n-icons">icons</span></a>
</li>
<li id="viewdetails" class="view hideOnNoJs" >
<a href="#"><img src="/h5ai/images/view-details.png" alt="view-details" /><span class="l10n-details">details</span></a>
</li>
</ul>
</nav>
<section id="content">
<header></header>
<section id="table" class="hideOnJs">
<!--
The following code was generated by apache's autoindex module. It is not valid HTML 5 for the
reason, that 'align' and 'valign' attributes on the td element are obsolete. Both of them are
removed via javascript. The actual page should render as perfect HTML 5, even if the produced
source is not valid HTML 5.
-->
<div id="selection-rect"></div>
<nav class="clearfix">
<ul>
<li id="viewicons" class="view hideOnNoJs">
<a href="#"><img src="/h5ai/images/view-icons.png" alt="view-icons" /><span class="l10n-icons">icons</span></a>
</li>
<li id="viewdetails" class="view hideOnNoJs" >
<a href="#"><img src="/h5ai/images/view-details.png" alt="view-details" /><span class="l10n-details">details</span></a>
</li>
<li id="download" class="hideOnNoJs">
<a href="#"><img src="/h5ai/images/download.png" alt="download" /><span class="l10n-download">download</span></a>
</li>
</ul>
</nav>
<section id="content">
<header></header>
<section id="table" class="hideOnJs">
<!--
The following code was generated by apache's autoindex module. It is not valid HTML 5 for the
reason, that 'align' and 'valign' attributes on the td element are obsolete. Both of them are
removed via javascript. The actual page should render as perfect HTML 5, even if the produced
source is not valid HTML 5.
-->

View File

@@ -1,55 +1,67 @@
<!DOCTYPE html>
<html class="no-js">
<!--[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]-->
<?php include "php/main.php"; ?>
<head>
<meta charset="utf-8">
<title><?php echo $h5ai->getTitle(); ?></title>
<meta name="h5ai-version" content="h5ai %BUILD_VERSION% (php)">
<meta name="description" content="Directory index styled with h5ai (http://larsjung.de/h5ai)">
<meta name="keywords" content="directory, index, autoindex, h5ai">
<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" type="text/css" href="http://fonts.googleapis.com/css?family=Ubuntu:regular,italic,bold">
<link rel="stylesheet" type="text/css" href="/h5ai/css/main-php.css">
<script src="/h5ai/js/lib/modernizr.min.js"></script>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<title><?php echo $h5ai->getTitle(); ?></title>
<meta name="h5ai-version" content="h5ai %BUILD_VERSION% (php)">
<meta name="description" content="Directory index styled with h5ai (http://larsjung.de/h5ai)">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<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">
<script src="/h5ai/js/modernizr.min.js"></script>
</head>
<body>
<nav class="clearfix">
<ul>
<?php echo $crumb->toHtml(); ?>
<li id="viewicons" class="view hideOnNoJs">
<a href="#"><img src="/h5ai/images/view-icons.png" alt="view-icons" /><span class="l10n-icons">icons</span></a>
</li>
<li id="viewdetails" class="view hideOnNoJs" >
<a href="#"><img src="/h5ai/images/view-details.png" alt="view-details" /><span class="l10n-details">details</span></a>
</li>
</ul>
</nav>
<?php echo $tree->toHtml(); ?>
<section id="content">
<?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>
<span class="right">
<span class="hideOnJs">JavaScript is disabled!</span>
<span id="langSelector">
<span class="lang">en</span> - <span class="l10n-lang">english</span>
<span class="langOptions"></span>
</span>
</span>
<span class="center">
<?php echo $extended->getFolderCount(); ?> <span class="l10n-folders">folders</span>
·
<?php echo $extended->getFileCount(); ?> <span class="l10n-files">files</span>
</span>
</footer>
<script src="/h5ai/js/lib/jquery.min.js"></script>
<script src="/h5ai/options.js"></script>
<script src="/h5ai/js/main-php.js"></script>
<section id="table">
<!-- the following code was generated by apache's autoindex module and gets ignored -->
<div id="selection-rect"></div>
<nav class="clearfix">
<ul>
<?php echo $crumb->toHtml(); ?>
<li id="viewicons" class="view hideOnNoJs">
<a href="#"><img src="/h5ai/images/view-icons.png" alt="view-icons" /><span class="l10n-icons">icons</span></a>
</li>
<li id="viewdetails" class="view hideOnNoJs" >
<a href="#"><img src="/h5ai/images/view-details.png" alt="view-details" /><span class="l10n-details">details</span></a>
</li>
<li id="download" class="hideOnNoJs">
<a href="#"><img src="/h5ai/images/download.png" alt="download" /><span class="l10n-download">download</span></a>
</li>
</ul>
</nav>
<?php echo $tree->toHtml(); ?>
<section id="content">
<?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>
<span class="right">
<span class="hideOnJs">JavaScript is disabled!</span>
<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="status default">
<?php echo $extended->getFolderCount(); ?> <span class="l10n-folders">folders</span>
<span class='sep'>·</span>
<?php echo $extended->getFileCount(); ?> <span class="l10n-files">files</span>
</span>
<span class="status dynamic">
</span>
</span>
</footer>
<script src="/h5ai/js/libs.js"></script>
<script src="/h5ai/options.js"></script>
<script src="/h5ai/js/main-php.js"></script>
<section id="table">
<!-- the following code was generated by apache's autoindex module and gets ignored -->

Binary file not shown.

After

Width:  |  Height:  |  Size: 528 B

View File

@@ -0,0 +1,143 @@
/*global $, H5aiJs */
H5aiJs.factory.Connector = function () {
var contentTypeRegEx = /^text\/html;h5ai=/,
pathnameStatusCache = {},
fetchStatus = function (pathname, callback) {
if (H5aiJs.h5ai.settings.folderStatus[pathname]) {
callback(H5aiJs.h5ai.settings.folderStatus[pathname]);
return;
} else if (pathnameStatusCache[pathname]) {
callback(pathnameStatusCache[pathname]);
return;
}
$.ajax({
url: pathname,
type: "HEAD",
complete: function (xhr) {
var status = xhr.status;
if (status === 200 && contentTypeRegEx.test(xhr.getResponseHeader("Content-Type"))) {
status = "h5ai";
}
pathnameStatusCache[pathname] = status;
callback(status);
}
});
},
updatePath = function (path) {
if (path.isFolder && !path.isParentFolder && path.status === undefined) {
fetchStatus(path.absHref, function (status) {
if (status !== "h5ai") {
path.status = status;
}
H5aiJs.html.updateHtml(path);
H5aiJs.h5ai.linkHoverStates();
});
}
},
updatePaths = function () {
$.each(H5aiJs.pathCache.cache, function (ref, cached) {
updatePath(cached);
});
},
fetchStatusAndContent = function (pathname, includeParent, callback) {
fetchStatus(pathname, function (status) {
if (status !== "h5ai") {
callback(status, {});
return;
}
$.ajax({
url: pathname,
type: "GET",
dataType: "html",
error: function (xhr) {
callback(xhr.status, {}); // since it was checked before this should never happen
},
success: function (html, status, xhr) {
var content = {};
if (!contentTypeRegEx.test(xhr.getResponseHeader("Content-Type"))) {
callback(xhr.status, {}); // since it was checked before this should never happen
return;
}
$(html).find("#table td").closest("tr").each(function () {
var path = H5aiJs.pathCache.getPath(pathname, this);
if (path.isFolder && (!path.isParentFolder || includeParent)) {
content[path.absHref] = path;
updatePath(path);
}
});
callback("h5ai", content);
}
});
});
},
fetchPath = function (pathname, callback) {
fetchStatusAndContent(pathname, false, function (status, content) {
var path = H5aiJs.pathCache.getPath(pathname);
path.status = status;
path.content = content;
callback(path);
});
},
fetchTree = function (pathname, callback, childPath) {
fetchPath(pathname, function (path) {
var parent = H5aiJs.pathCache.splitPathname(pathname)[0];
path.treeOpen = true;
if (childPath) {
path.content[childPath.absHref] = childPath;
}
if (parent === "") {
callback(path);
} else {
fetchTree(parent, callback, path);
}
});
},
populateTree = function () {
fetchTree(document.location.pathname, function (path) {
$("#tree")
.append(H5aiJs.html.updateTreeHtml(path))
.scrollpanel()
.show();
H5aiJs.h5ai.shiftTree(false, true);
H5aiJs.h5ai.linkHoverStates();
setTimeout(function () { $("#tree").get(0).updateScrollbar(); }, 1);
});
},
init = function () {
if (H5aiJs.h5ai.settings.showTree) {
updatePaths();
populateTree();
}
};
return {
fetchStatusAndContent: fetchStatusAndContent,
init: init
};
};

112
src/h5ai/js/inc/Extended.js Normal file
View File

@@ -0,0 +1,112 @@
/*global $, H5aiJs */
H5aiJs.factory.Extended = function () {
var settings = {
customHeader: "h5ai.header.html",
customFooter: "h5ai.footer.html"
},
initTitle = function () {
document.title = document.domain + document.location.pathname;
try {
document.title = decodeURI(document.title);
} catch (err) {}
},
initBreadcrumb = function () {
var $ul = $("body > nav ul"),
pathname = "/",
path = H5aiJs.pathCache.getPath(pathname),
pathnameParts = document.location.pathname.split("/");
$ul.append(H5aiJs.html.updateCrumbHtml(path));
$.each(pathnameParts, function (idx, part) {
if (part !== "") {
pathname += part + "/";
$ul.append(H5aiJs.html.updateCrumbHtml(H5aiJs.pathCache.getPath(pathname)));
}
});
},
initExtendedView = function () {
var $ths = $("#table th"),
$label = $ths.eq(1).find("a"),
$date = $ths.eq(2).find("a"),
$size = $ths.eq(3).find("a"),
sortquery = document.location.search,
order = {
column: (sortquery.indexOf("C=N") >= 0) ? "name" : (sortquery.indexOf("C=M") >= 0) ? "date" : (sortquery.indexOf("C=S") >= 0) ? "size" : H5aiJs.h5ai.settings.sortorder.column,
ascending: (sortquery.indexOf("O=A") >= 0) ? true : (sortquery.indexOf("O=D") >= 0) ? false : H5aiJs.h5ai.settings.sortorder.ascending
},
$icon, $ul, $li;
$ul = $("<ul/>");
$li = $("<li class='header' />")
.appendTo($ul)
.append($("<a class='icon'></a>"))
.append($("<a class='label' href='" + $label.attr("href") + "'><span class='l10n-name'>" + $label.text() + "</span></a>"))
.append($("<a class='date' href='" + $date.attr("href") + "'><span class='l10n-lastModified'>" + $date.text() + "</span></a>"))
.append($("<a class='size' href='" + $size.attr("href") + "'><span class='l10n-size'>" + $size.text() + "</span></a>"));
// header sort icons
if (order.ascending) {
$icon = $("<img src='" + H5aiJs.h5ai.image("ascending") + "' class='sort' alt='ascending' />");
} else {
$icon = $("<img src='" + H5aiJs.h5ai.image("descending") + "' class='sort' alt='descending' />");
}
if (order.column === "date") {
$li.find("a.date").prepend($icon);
} else if (order.column === "size") {
$li.find("a.size").prepend($icon);
} else {
$li.find("a.label").append($icon);
}
// entries
$("#table td").closest("tr").each(function () {
var path = H5aiJs.pathCache.getPath(document.location.pathname, this);
$ul.append(H5aiJs.html.updateExtendedHtml(path));
});
$("#extended").append($ul);
// empty
if ($ul.children(".entry:not(.parentfolder)").size() === 0) {
$("#extended").append($("<div class='empty l10n-empty'>empty</div>"));
}
},
customize = function () {
$.ajax({
url: settings.customHeader,
dataType: "html",
success: function (data) {
$("#content > header").append($(data)).show();
}
});
$.ajax({
url: settings.customFooter,
dataType: "html",
success: function (data) {
$("#content > footer").prepend($(data)).show();
}
});
},
initTotals = function () {
$(".folderCount").text($("#extended .entry.folder:not(.parentfolder)").size());
$(".fileCount").text($("#extended .entry.file").size());
};
this.init = function () {
initTitle();
initBreadcrumb();
initExtendedView();
customize();
initTotals();
};
};

461
src/h5ai/js/inc/H5ai.js Normal file
View File

@@ -0,0 +1,461 @@
H5aiJs.factory.H5ai = function (options, langs) {
/*global window, $, amplify*/
var $window = $(window),
$document = $(document),
defaults = {
store: {
viewmode: "h5ai.pref.viewmode",
lang: "h5ai.pref.lang"
},
callbacks: {
pathClick: []
},
h5aiAbsHref: "/h5ai",
viewmodes: ["details", "icons"],
sortorder: {
column: "name",
ascending: true
},
showTree: true,
slideTree: true,
folderStatus: {},
lang: null,
useBrowserLang: true,
setParentFolderLabels: true,
linkHoverStates: true,
dateFormat: "yyyy-MM-dd HH:mm",
showThumbs: true,
zippedDownload: true
},
settings = $.extend({}, defaults, options),
api = function () {
return settings.h5aiAbsHref + "/php/api.php";
},
image = function (id) {
return settings.h5aiAbsHref + "/images/" + id + ".png";
},
icon = function (id, big) {
return settings.h5aiAbsHref + "/icons/" + (big ? "48x48" : "16x16") + "/" + id + ".png";
},
pathClick = function (fn) {
if ($.isFunction(fn)) {
settings.callbacks.pathClick.push(fn);
}
},
triggerPathClick = function (path, context) {
$.each(settings.callbacks.pathClick, function (idx, callback) {
callback(path, context);
});
},
getViewmode = function () {
var viewmode = amplify.store(settings.store.viewmode);
return $.inArray(viewmode, settings.viewmodes) >= 0 ? viewmode : settings.viewmodes[0];
},
applyViewmode = function (viewmode) {
if (viewmode) {
amplify.store(settings.store.viewmode, viewmode);
}
viewmode = getViewmode();
$("#viewdetails,#viewicons").hide().removeClass("current");
if (settings.viewmodes.length > 1) {
if ($.inArray("details", settings.viewmodes) >= 0) {
$("#viewdetails").show();
}
if ($.inArray("icons", settings.viewmodes) >= 0) {
$("#viewicons").show();
}
}
if (viewmode === "details") {
$("#viewdetails").closest("li").addClass("current");
$("#extended").addClass("details-view").removeClass("icons-view").show();
} else if (viewmode === "icons") {
$("#viewicons").closest("li").addClass("current");
$("#extended").removeClass("details-view").addClass("icons-view").show();
} else {
$("#extended").hide();
}
},
initTopSpace = function () {
var adjustTopSpace = function () {
var winHeight = $window.height(),
navHeight = $("body > nav").outerHeight(),
footerHeight = $("body > footer").outerHeight(),
contentSpacing = 50,
treeSpacing = 50;
$("body").css({
"margin-top": navHeight + contentSpacing,
"margin-bottom": footerHeight + contentSpacing
});
$("#tree").css({
top: navHeight + treeSpacing,
height: winHeight - navHeight - footerHeight - 36 - 2 * treeSpacing
});
try {
$("#tree").get(0).updateScrollbar();
} catch (err) {}
};
$window.resize(function () {
adjustTopSpace();
});
adjustTopSpace();
},
initViews = function () {
$("#table").remove();
$("#viewdetails").closest("li")
.click(function () { applyViewmode("details"); });
$("#viewicons").closest("li")
.click(function () { applyViewmode("icons"); });
// status update
$("#extended .entry a").hover(
function () {
if ($("#extended").hasClass("icons-view")) {
var $this = $(this);
$(".status.default").hide();
$(".status.dynamic")
.empty()
.append($this.find(".label").clone())
.append($("<span class='sep'>·</span>"))
.append($this.find(".date").clone())
.show();
if (!$this.closest(".entry").hasClass("folder")) {
$(".status.dynamic")
.append($("<span class='sep'>·</span>"))
.append($this.find(".size").clone());
}
}
},
function () {
$(".status.default").show();
$(".status.dynamic").empty().hide();
}
);
},
shiftTree = function (forceVisible, dontAnimate) {
var $tree = $("#tree"),
$extended = $("#extended");
if ((settings.slideTree && $tree.outerWidth() < $extended.offset().left) || forceVisible) {
if (dontAnimate) {
$tree.stop().css({ left: 0 });
} else {
$tree.stop().animate({ left: 0 });
}
} else {
if (dontAnimate) {
$tree.stop().css({ left: 18 - $tree.outerWidth() });
} else {
$tree.stop().animate({ left: 18 - $tree.outerWidth() });
}
}
},
initTree = function () {
$("#tree").hover(
function () { shiftTree(true); },
function () { shiftTree(); }
);
$window.resize(function () { shiftTree(); });
shiftTree(false, true);
},
selectLinks = function (href) {
var elements = [];
$("a[href^='/']").each(function () {
if ($(this).attr("href") === href) {
elements.push(this);
}
});
return $(elements);
},
linkHoverStates = function () {
if (settings.linkHoverStates) {
$("a[href^='/']:not(.linkedHoverStates)").each(function () {
var $a = $(this).addClass("linkedHoverStates"),
href = $a.attr("href");
$a.hover(
function () { selectLinks(href).addClass("hover"); },
function () { selectLinks(href).removeClass("hover"); }
);
});
}
},
localize = function (langs, lang, useBrowserLang) {
var storedLang = amplify.store(settings.store.lang),
dateFormat = settings.dateFormat,
browserLang, selected, key;
if (langs[storedLang]) {
lang = storedLang;
} else if (useBrowserLang) {
browserLang = navigator.language;
if (langs[browserLang]) {
lang = browserLang;
} else if (browserLang.length > 2 && langs[browserLang.substr(0, 2)]) {
lang = browserLang.substr(0, 2);
}
}
if (!langs[lang]) {
lang = "en";
}
selected = langs[lang];
if (selected) {
$.each(selected, function (key, value) {
$(".l10n-" + key).text(value);
});
$(".lang").text(lang);
$(".langOption").removeClass("current");
$(".langOption." + lang).addClass("current");
}
dateFormat = selected.dateFormat || dateFormat;
$("#extended .entry .date").each(function () {
var $this = $(this),
time = $this.data("time"),
formattedDate = time ? new Date(time).toString(dateFormat) : "";
$this.text(formattedDate);
});
},
initLangSelector = function (langs) {
var $langOptions = $(".langOptions"),
sortedLangsKeys = [],
$ul;
$.each(langs, function (lang) {
sortedLangsKeys.push(lang);
});
sortedLangsKeys.sort();
$ul = $("<ul />");
$.each(sortedLangsKeys, function (idx, lang) {
$("<li class='langOption' />")
.addClass(lang)
.text(lang + " - " + langs[lang].lang)
.appendTo($ul)
.click(function () {
amplify.store(settings.store.lang, lang);
localize(langs, lang, false);
});
});
$("#langSelector .langOptions").append($ul);
$("#langSelector").hover(
function () {
$langOptions
.css("top", "-" + $langOptions.outerHeight() + "px")
.stop(true, true)
.fadeIn();
},
function () {
$langOptions
.stop(true, true)
.fadeOut();
}
);
},
onIndicatorClick = function (event) {
var $indicator = $(this),
$entry = $indicator.closest(".entry");
if ($indicator.hasClass("unknown")) {
$.get(api(), { "action": "tree", "href": $entry.find("> a").attr("href") }, function (html) {
var $content = $(html);
$indicator.removeClass("unknown");
if ($content.find("> li").size() === 0) {
$indicator.replaceWith($("<span class='blank' />"));
} else {
$indicator.addClass("open");
$entry.find("> .content").replaceWith($content);
$("#tree").get(0).updateScrollbar();
$content.find(".indicator:not(.initiated)")
.click(onIndicatorClick)
.addClass("initiated");
}
});
} else if ($indicator.hasClass("open")) {
$indicator.removeClass("open");
$("#tree").get(0).updateScrollbar(true);
$entry.find("> .content").slideUp(function () {
$("#tree").get(0).updateScrollbar();
});
} else {
$indicator.addClass("open");
$("#tree").get(0).updateScrollbar(true);
$entry.find("> .content").slideDown(function () {
$("#tree").get(0).updateScrollbar();
});
}
},
initIndicators = function () {
$("#tree .entry.folder .indicator:not(.initiated)")
.click(onIndicatorClick)
.addClass("initiated");
},
initZippedDownload = function () {
var x = 0,
y = 0,
ctrl = false,
updateDownloadBtn = function () {
var query,
href,
$selected = $("#extended a.selected");
if ($selected.size() > 0) {
$selected.each(function () {
href = $(this).attr("href");
query = query ? query + ":" + href : href;
});
query = api() + "?action=zip&hrefs=" + query;
$("#download").show().find("a").attr("href", query);
} else {
$("#download").hide().find("a").attr("href", "#");
}
},
selectionUpdate = function (event) {
var l = Math.min(x, event.pageX),
t = Math.min(y, event.pageY),
w = Math.abs(x - event.pageX),
h = Math.abs(y - event.pageY),
sel;
event.preventDefault();
$("#selection-rect").css({left: l, top: t, width: w, height: h});
sel = $("#selection-rect").fracs("rect");
$("#extended a").removeClass("selecting").each(function () {
var $a = $(this),
rect = $a.fracs("rect"),
inter = sel.intersection(rect);
if (inter && !$a.closest(".entry").hasClass("folder-parent")) {
$a.addClass("selecting");
}
});
},
selectionEnd = function (event) {
event.preventDefault();
$document.unbind("mousemove", selectionUpdate);
$("#selection-rect").hide().css({left: 0, top: 0, width: 0, height: 0});
$("#extended a.selecting.selected").removeClass("selecting").removeClass("selected");
$("#extended a.selecting").removeClass("selecting").addClass("selected");
updateDownloadBtn();
},
selectionStart = function (event) {
var view = $.fracs.viewport();
x = event.pageX;
y = event.pageY;
// only on left button and don't block the scrollbars
if (event.button !== 0 || x >= view.right || y >= view.bottom) {
return;
}
event.preventDefault();
if (!ctrl) {
$("#extended a").removeClass("selected");
updateDownloadBtn();
}
$("#selection-rect").show().css({left: x, top: y, width: 0, height: 0});
selectionUpdate(event);
$document
.bind("mousemove", selectionUpdate)
.one("mouseup", selectionEnd);
},
noSelection = function (event) {
event.stopPropagation();
return false;
},
noSelectionUnlessCtrl = function (event) {
if (!ctrl) {
noSelection(event);
}
};
if (settings.zippedDownload) {
$("body>nav,body>footer,#tree").bind("mousedown", noSelection);
$("#extended .entry a").bind("mousedown", noSelectionUnlessCtrl).live("mousedown", noSelectionUnlessCtrl);
$document
.bind("mousedown", selectionStart)
.keydown(function (event) {
if (event.keyCode === 17) {
ctrl = true;
}
})
.keyup(function (event) {
if (event.keyCode === 17) {
ctrl = false;
}
});
}
},
init = function () {
applyViewmode();
initTopSpace();
initViews();
initTree();
linkHoverStates();
initLangSelector(langs);
localize(langs, settings.lang, settings.useBrowserLang);
initIndicators();
initZippedDownload();
};
return {
settings: settings,
api: api,
image: image,
icon: icon,
shiftTree: shiftTree,
linkHoverStates: linkHoverStates,
pathClick: pathClick,
triggerPathClick: triggerPathClick,
initIndicators: initIndicators,
init: init
};
};

260
src/h5ai/js/inc/Html.js Normal file
View File

@@ -0,0 +1,260 @@
/*global $, H5aiJs */
H5aiJs.factory.Html = function () {
var thumbExts = ["bmp", "gif", "ico", "image", "jpg", "jpeg", "png", "tiff"],
onClick = function (path, context) {
H5aiJs.h5ai.triggerPathClick(path, context);
},
updateCrumbHtml = function (path) {
var $html, $a;
if (path.html.$crumb && path.html.$crumb.data("status") === path.status) {
return path.html.$crumb;
}
$html = $("<li class='crumb' />")
.data("path", path)
.addClass(path.isFolder ? "folder" : "file");
if (path.status) {
$html.data("status", path.status);
}
$a = $("<a><img src='" + H5aiJs.h5ai.image("crumb") + "' alt='>' />" + path.label + "</a>")
.appendTo($html)
.attr("href", path.absHref)
.click(function() { onClick(path, "crumb"); });
if (path.isDomain) {
$html.addClass("domain");
$a.find("img").attr("src", H5aiJs.h5ai.image("home"));
}
if (path.isCurrentFolder) {
$html.addClass("current");
}
if (!isNaN(path.status)) {
if (path.status === 200) {
$("<img class='hint' src='" + H5aiJs.h5ai.image("page") + "' alt='not listable' />").appendTo($a);
} else {
$("<span class='hint'>(" + path.status + ")</span>").appendTo($a);
}
}
if (path.html.$crumb) {
path.html.$crumb.replaceWith($html);
}
path.html.$crumb = $html;
return $html;
},
updateExtendedHtml = function (path) {
var $html, $a, $label,
formattedDate = path.date ? path.date.toString(H5aiJs.h5ai.settings.dateFormat) : "",
ext = path.absHref.substr((path.absHref.lastIndexOf('.') + 1)),
icon16 = path.icon16,
icon48 = path.icon48;
if (path.html.$extended && path.html.$extended.data("status") === path.status) {
return path.html.$extended;
}
$html = $("<li class='entry' />")
.data("path", path)
.addClass(path.isFolder ? "folder" : "file");
if (path.status) {
$html.data("status", path.status);
}
if (H5aiJs.h5ai.settings.showThumbs && $.inArray(ext.toLowerCase(), thumbExts) >= 0) {
icon16 = H5aiJs.h5ai.api() + "?action=thumb&href=" + path.absHref + "&width=16&height=16&mode=square";
icon48 = H5aiJs.h5ai.api() + "?action=thumb&href=" + path.absHref + "&width=96&height=46&mode=rational";
}
$label = $("<span class='label'>" + path.label + "</span>");
$a = $("<a />")
.attr("href", path.absHref)
.click(function() { onClick(path, "extended"); })
.appendTo($html)
.append($("<span class='icon small'><img src='" + icon16 + "' alt='" + path.alt + "' /></span>"))
.append($("<span class='icon big'><img src='" + icon48 + "' alt='" + path.alt + "' /></span>"))
.append($label)
.append($("<span class='date' data-time='" + path.time + "'></span>"))
.append($("<span class='size'>" + path.size + "</span>"));
$a.hover(
function () {
if ($("#extended").hasClass("icons-view")) {
var $this = $(this);
$(".status.default").hide();
$(".status.dynamic")
.empty()
.append($this.find(".label").clone())
.append($("<span class='sep'>·</span>"))
.append($this.find(".date").clone())
.show();
if (!$this.closest(".entry").hasClass("folder")) {
$(".status.dynamic")
.append($("<span class='sep'>·</span>"))
.append($this.find(".size").clone());
}
}
},
function () {
$(".status.default").show();
$(".status.dynamic").empty().hide();
}
);
if (path.isParentFolder) {
if (!H5aiJs.h5ai.settings.setParentFolderLabels) {
$label.addClass("l10n-parentDirectory");
}
$html.addClass("folder-parent");
}
if (!isNaN(path.status)) {
if (path.status === 200) {
$html.addClass("page");
$a.find(".icon.small img").attr("src", H5aiJs.h5ai.icon("folder-page"));
$a.find(".icon.big img").attr("src", H5aiJs.h5ai.icon("folder-page", true));
} else {
$html.addClass("error");
$label.append($("<span class='hint'> " + path.status + " </span>"));
}
}
if (path.html.$extended) {
path.html.$extended.replaceWith($html);
}
path.html.$extended = $html;
return $html;
},
updateTreeHtml = function (path) {
var $html, $blank, $a, $indicator, $ul, idx;
$html = $("<div class='entry' />")
.data("path", path)
.addClass(path.isFolder ? "folder" : "file");
$blank = $("<span class='blank' />").appendTo($html);
$a = $("<a />")
.attr("href", path.absHref)
.click(function() { path.onClick(path, "tree"); })
.appendTo($html)
.append($("<span class='icon'><img src='" + path.icon16 + "' /></span>"))
.append($("<span class='label'>" + path.label + "</span>"));
if (path.isFolder) {
// indicator
if (path.status === undefined || !path.isEmpty()) {
$indicator = $("<span class='indicator initiated'><img src='" + H5aiJs.h5ai.image("tree") + "' /></span>")
.click(function (event) {
var $entry = $indicator.closest(".entry"); // $html
if ($indicator.hasClass("unknown")) {
H5aiJs.connector.fetchStatusAndContent(path.absHref, false, function (status, content) {
path.status = status;
path.content = content;
path.treeOpen = true;
$("#tree").get(0).updateScrollbar(true);
updateTreeHtml(path);
$("#tree").get(0).updateScrollbar();
});
} else if ($indicator.hasClass("open")) {
path.treeOpen = false;
$indicator.removeClass("open");
$("#tree").get(0).updateScrollbar(true);
$entry.find("> ul.content").slideUp(function() {
$("#tree").get(0).updateScrollbar();
});
} else {
path.treeOpen = true;
$indicator.addClass("open");
$("#tree").get(0).updateScrollbar(true);
$entry.find("> ul.content").slideDown(function() {
$("#tree").get(0).updateScrollbar();
});
}
});
if (path.status === undefined) {
$indicator.addClass("unknown");
} else if (path.treeOpen) {
$indicator.addClass("open");
}
$blank.replaceWith($indicator);
}
// is path the domain?
if (path.isDomain) {
$html.addClass("domain");
$a.find(".icon img").attr("src", H5aiJs.h5ai.icon("folder-home"));
}
// is path the current folder?
if (path.isCurrentFolder) {
$html.addClass("current");
$a.find(".icon img").attr("src", H5aiJs.h5ai.icon("folder-open"));
}
// does it have subfolders?
if (!path.isEmpty()) {
$ul = $("<ul class='content' />").appendTo($html);
$.each(path.content, function (idx, entry) {
$("<li />").append(updateTreeHtml(entry)).appendTo($ul);
});
if (path.status === undefined || !path.treeOpen) {
$ul.hide();
}
}
// reflect folder status
if (!isNaN(path.status)) {
if (path.status === 200) {
$a.find(".icon img").attr("src", H5aiJs.h5ai.icon("folder-page"));
$a.append($("<span class='hint'><img src='" + H5aiJs.h5ai.image("page") + "' /></span>"));
} else {
$html.addClass("error");
$a.append($("<span class='hint'>" + path.status + "</span>"));
}
}
}
if (path.html.$tree) {
path.html.$tree.replaceWith($html);
}
path.html.$tree = $html;
return $html;
},
updateHtml = function (path) {
updateCrumbHtml(path);
updateExtendedHtml(path);
updateTreeHtml(path);
};
return {
updateCrumbHtml: updateCrumbHtml,
updateExtendedHtml: updateExtendedHtml,
updateTreeHtml: updateTreeHtml,
updateHtml: updateHtml
};
};

102
src/h5ai/js/inc/Path.js Normal file
View File

@@ -0,0 +1,102 @@
/*global $, H5aiJs */
H5aiJs.factory.Path = function (folder, tableRow) {
var checkedDecodeUri = function (uri) {
try { return decodeURI(uri); } catch (err) {}
return uri;
},
$tds, $img, $a, splits;
// parentFolder: undefined,
// label: undefined,
// dateOrgStr: undefined,
// date: undefined,
// time: undefined,
// size: undefined,
// href: undefined,
// absHref: undefined,
// alt: undefined,
// icon16: undefined,
// icon48: undefined,
// isFolder: undefined,
// isParentFolder: undefined,
// isCurrentFolder: undefined,
// isDomain: undefined,
this.status = undefined; // undefined, "h5ai" or HTTP response code
this.content = undefined; // associative array path.absHref -> path
this.html = {
$crumb: undefined,
$extended: undefined,
$tree: undefined
};
this.treeOpen = false;
if (!H5aiJs.pathCache.pathEndsWithSlash(folder)) {
folder += "/";
}
if (tableRow) {
$tds = $(tableRow).find("td");
$img = $tds.eq(0).find("img");
$a = $tds.eq(1).find("a");
this.parentFolder = folder;
this.label = $a.text();
this.dateOrgStr = $tds.eq(2).text();
this.date = Date.parse(this.dateOrgStr);
this.time = this.date ? this.date.getTime() : 0;
this.size = $tds.eq(3).text();
this.href = $a.attr("href");
this.alt = $img.attr("alt");
this.icon16 = $img.attr("src");
} else {
splits = H5aiJs.pathCache.splitPathname(folder);
this.parentFolder = splits[0];
this.label = checkedDecodeUri(splits[1]);
if (this.label === "/") {
this.label = checkedDecodeUri(document.domain) + "/";
}
this.dateOrgStr = "";
this.date = null;
this.time = 0;
this.size = "";
this.href = splits[1];
this.alt = "[DIR]";
this.icon16 = H5aiJs.h5ai.icon("folder");
}
if (H5aiJs.pathCache.pathEndsWithSlash(this.label)) {
this.label = this.label.slice(0, -1);
}
this.icon48 = this.icon16.replace("16x16", "48x48");
this.isFolder = (this.alt === "[DIR]");
this.isParentFolder = (this.isFolder && this.label === "Parent Directory");
this.absHref = this.isParentFolder ? this.href : this.parentFolder + this.href;
this.isCurrentFolder = (this.absHref === document.location.pathname);
this.isDomain = (this.absHref === "/");
if (this.isParentFolder && H5aiJs.h5ai.settings.setParentFolderLabels) {
if (this.isDomain) {
this.label = checkedDecodeUri(document.domain);
} else {
this.label = checkedDecodeUri(H5aiJs.pathCache.splitPathname(H5aiJs.pathCache.splitPathname(this.parentFolder)[0])[1].slice(0, -1));
}
}
};
H5aiJs.factory.Path.prototype = {
isEmpty: function () {
return !this.content || $.isEmptyObject(this.content);
},
onClick: function (context) {
H5aiJs.h5ai.triggerPathClick(this, context);
}
};

View File

@@ -0,0 +1,56 @@
/*global $, H5aiJs */
H5aiJs.factory.PathCache = function () {
var cache = {},
rePathnameSplit = /^(\/(.*\/)*)([^\/]+\/?)$/,
rePathEndsWithSlash = /\/$/,
splitPathname = function (pathname) {
var match;
if (pathname === "/") {
return ["", "/"];
}
match = rePathnameSplit.exec(pathname);
return [match[1], match[3]];
},
pathEndsWithSlash = function (pathname) {
return rePathEndsWithSlash.test(pathname);
},
getAbsHref = function (folder, tableRow) {
var $a, isParentFolder, href;
if (!pathEndsWithSlash(folder)) {
folder += "/";
}
if (!tableRow) {
return folder;
}
$a = $(tableRow).find("td").eq(1).find("a");
isParentFolder = ($a.text() === "Parent Directory");
href = $a.attr("href");
return isParentFolder ? undefined : folder + href;
},
getPath = function (folder, tableRow) {
var absHref = getAbsHref(folder, tableRow),
path = cache[absHref];
if (!path) {
path = new H5aiJs.factory.Path(folder, tableRow);
if (!path.isParentFolder) {
cache[path.absHref] = path;
}
}
return path;
};
this.splitPathname = splitPathname;
this.pathEndsWithSlash = pathEndsWithSlash;
this.getPath = getPath;
this.cache = cache;
};

View File

@@ -1,153 +0,0 @@
var Extended = function ( pathCache, h5ai ) {
/*******************************
* config
*******************************/
this.config = {
customHeader: "h5ai.header.html",
customFooter: "h5ai.footer.html"
};
/*******************************
* init
*******************************/
this.init = function () {
try {
document.title = decodeURI( document.domain + document.location.pathname );
} catch ( err ) {
document.title = document.domain + document.location.pathname;
};
this.initBreadcrumb();
this.initExtendedView();
this.customize();
this.initCounts();
};
/*******************************
* breadcrumb
*******************************/
this.initBreadcrumb = function () {
var $ul = $( "body > nav ul" );
var pathname = "/";
var path = pathCache.getPathForFolder( pathname );
$ul.append( path.updateCrumbHtml() );
var pathnameParts = document.location.pathname.split( "/" );
for ( idx in pathnameParts ) {
var part = pathnameParts[idx];
if ( part !== "" ) {
pathname += part + "/";
var path = pathCache.getPathForFolder( pathname );
$ul.append( path.updateCrumbHtml() );
};
};
};
/*******************************
* extended view
*******************************/
this.initExtendedView = function () {
var $ul = $( "<ul/>" );
// headers
var $ths = $( "#table th" );
var $label = $ths.eq( 1 ).find( "a" );
var $date = $ths.eq( 2 ).find( "a" );
var $size = $ths.eq( 3 ).find( "a" );
var $li = $( "<li class='header' />" ).appendTo( $ul );
$( "<a class='icon'></a>" ).appendTo( $li );
$( "<a class='label' href='" + $label.attr( "href" ) + "'><span class='l10n-name'>" + $label.text() + "</span></a>" ).appendTo( $li );
$( "<a class='date' href='" + $date.attr( "href" ) + "'><span class='l10n-lastModified'>" + $date.text() + "</span></a>" ).appendTo( $li );
$( "<a class='size' href='" + $size.attr( "href" ) + "'><span class='l10n-size'>" + $size.text() + "</span></a>" ).appendTo( $li );
// header sort icons
var sortquery = document.location.search;
var order = {
column: ( sortquery.indexOf( "C=N" ) >= 0 ) ? "name" : ( sortquery.indexOf( "C=M" ) >= 0 ) ? "date" : ( sortquery.indexOf( "C=S" ) >= 0 ) ? "size" : h5ai.config.sortorder.column,
ascending: ( sortquery.indexOf( "O=A" ) >= 0 ) ? true : ( sortquery.indexOf( "O=D" ) >= 0 ) ? false : h5ai.config.sortorder.ascending
};
var $icon;
if ( order.ascending ) {
$icon = $( "<img src='/h5ai/images/ascending.png' class='sort' alt='ascending' />" );
} else {
$icon = $( "<img src='/h5ai/images/descending.png' class='sort' alt='descending' />" );
};
if ( order.column === "date" ) {
$li.find( "a.date" ).prepend( $icon );
} else if ( order.column === "size" ) {
$li.find( "a.size" ).prepend( $icon );
} else {
$li.find( "a.label" ).append( $icon );
};
// entries
$( "#table td" ).closest( "tr" ).each( function () {
var path = pathCache.getPathForTableRow( document.location.pathname, this );
$ul.append( path.updateExtendedHtml() );
} );
$( "#extended" ).append( $ul );
$.log( document.location.pathname, "folders:", $( "#extended .folder" ).size() , "files:", $( "#extended .file" ).size() );
// empty
if ( $ul.children( ".entry:not(.parentfolder)" ).size() === 0 ) {
$( "#extended" ).append( $( "<div class='empty l10n-empty'>empty</div>" ) );
};
// in case of floats
$( "#extended" ).addClass( "clearfix" );
};
/*******************************
* customize
*******************************/
this.customize = function () {
$.ajax( {
url: this.config.customHeader,
dataType: "html",
success: function ( data ) {
$( "#content > header" ).append( $( data ) ).show();
}
} );
$.ajax( {
url: this.config.customFooter,
dataType: "html",
success: function ( data ) {
$( "#content > footer" ).prepend( $( data ) ).show();
}
} );
};
/*******************************
* init counts
*******************************/
this.initCounts = function () {
$( ".folderCount" ).text( $( "#extended .entry.folder:not(.parentfolder)" ).size() );
$( ".fileCount" ).text( $( "#extended .entry.file" ).size() );
};
};

View File

@@ -1,351 +0,0 @@
var H5ai = function ( options, langs ) {
/*******************************
* config
*******************************/
var defaults = {
store: {
viewmode: "h5ai.viewmode",
lang: "h5ai.lang"
},
callbacks: {
pathClick: []
},
viewmodes: [ "details", "icons" ],
sortorder: {
column: "name",
ascending: true
},
showTree: true,
folderStatus: {
},
lang: null,
useBrowserLang: true,
setParentFolderLabels: true,
linkHoverStates: true
};
this.config = $.extend( {}, defaults, options );
/*******************************
* public api
*******************************/
this.pathClick = function ( fn ) {
if ( $.isFunction( fn ) ) {
this.config.callbacks.pathClick.push( fn );
};
return this;
};
/*******************************
* init
*******************************/
this.init = function () {
this.applyViewmode();
this.initTopSpace();
this.initViews();
this.initTree();
this.linkHoverStates();
this.initLangSelector( langs );
this.localize( langs, this.config.lang, this.config.useBrowserLang );
this.initIndicators();
};
/*******************************
* callback triggers
*******************************/
this.triggerPathClick = function ( path, context ) {
for ( idx in this.config.callbacks.pathClick ) {
this.config.callbacks.pathClick[idx].call( window, path, context );
};
};
/*******************************
* local stored viewmode
*******************************/
this.getViewmode = function () {
var viewmode = localStorage.getItem( this.config.store.viewmode );
return $.inArray( viewmode, this.config.viewmodes ) >= 0 ? viewmode : this.config.viewmodes[0];
};
this.applyViewmode = function ( viewmode ) {
if ( viewmode !== undefined ) {
localStorage.setItem( this.config.store.viewmode, viewmode );
};
viewmode = this.getViewmode();
$( "#viewdetails,#viewicons" ).hide().removeClass( "current" );
if ( this.config.viewmodes.length > 1 ) {
if ( $.inArray( "details", this.config.viewmodes ) >= 0 ) {
$( "#viewdetails" ).show();
};
if ( $.inArray( "icons", this.config.viewmodes ) >= 0 ) {
$( "#viewicons" ).show();
};
};
if ( viewmode === "details" ) {
$( "#viewdetails" ).closest( "li" ).addClass( "current" );
$( "#extended" ).addClass( "details-view" ).removeClass( "icons-view" ).show();
} else if ( viewmode === "icons" ) {
$( "#viewicons" ).closest( "li" ).addClass( "current" );
$( "#extended" ).removeClass( "details-view" ).addClass( "icons-view" ).show();
} else {
$( "#extended" ).hide();
};
};
/*******************************
* top space, depending on nav height
*******************************/
this.initTopSpace = function () {
function adjustTopSpace() {
var winHeight = $( window ).height();
var navHeight = $( "body > nav" ).outerHeight();
var footerHeight = $( "body > footer" ).outerHeight();
var contentSpacing = 50;
var treeSpacing = 50;
$( "body" )
.css( "margin-top", "" + ( navHeight + contentSpacing ) + "px" )
.css( "margin-bottom", "" + ( footerHeight + contentSpacing ) + "px" );
$( "#tree" )
.css( "top", "" + ( navHeight + treeSpacing ) + "px" )
.css( "height", "" + ( winHeight - navHeight - footerHeight - 36 - 2 * treeSpacing ) + "px" );
try {
$( "#tree" ).get( 0 ).updateScrollbar();
} catch ( err ) {};
};
$( window ).resize( function () {
adjustTopSpace();
} );
adjustTopSpace();
};
/*******************************
* init views
*******************************/
this.initViews = function () {
$( "#table" ).remove();
$( "#viewdetails" ).closest( "li" )
.click( $.proxy( function () {
this.applyViewmode( "details" );
}, this ) );
$( "#viewicons" ).closest( "li" )
.click( $.proxy( function () {
this.applyViewmode( "icons" );
}, this ) );
};
/*******************************
* init tree
*******************************/
this.shiftTree = function ( forceVisible, dontAnimate ) {
var $tree = $( "#tree" );
var $extended = $( "#extended" );
if ( $tree.outerWidth() < $extended.offset().left || forceVisible === true ) {
if ( dontAnimate === true ) {
$tree.stop().css( { left: 0 } );
} else {
$tree.stop().animate( { left: 0 } );
};
} else {
if ( dontAnimate === true ) {
$tree.stop().css( { left: 18 - $tree.outerWidth() } );
} else {
$tree.stop().animate( { left: 18 - $tree.outerWidth() } );
};
};
};
this.initTree = function () {
$( "#tree" ).hover(
$.proxy( function () { this.shiftTree( true ); }, this ),
$.proxy( function () { this.shiftTree(); }, this )
);
$( window ).resize( $.proxy( function () { this.shiftTree(); }, this ) );
this.shiftTree( false, true );
};
/*******************************
* link hover states
*******************************/
this.linkHoverStates = function () {
if ( !this.config.linkHoverStates ) {
return;
};
$( "a[href^='/']:not(.linkedHoverStates)" ).each( function () {
var $a = $( this ).addClass( "linkedHoverStates" );
var href = $a.attr( "href" );
$a.hover(
function () {
$( "a[href='" + href + "']" ).addClass( "hover" );
},
function () {
$( "a[href='" + href + "']" ).removeClass( "hover" );
}
);
} );
};
/*******************************
* localization
*******************************/
this.initLangSelector = function ( langs ) {
var sortedLangsKeys = [];
for ( lang in langs ) {
sortedLangsKeys.push( lang );
};
sortedLangsKeys.sort();
var THIS = this;
var $ul = $( "<ul />" );
for ( idx in sortedLangsKeys ) {
( function ( lang ) {
$( "<li class='langOption' />" )
.addClass( lang )
.text( lang + " - " + langs[lang]["lang"] )
.appendTo( $ul )
.click( function () {
localStorage.setItem( THIS.config.store.lang, lang );
THIS.localize( langs, lang, false );
} );
} )( sortedLangsKeys[idx] );
};
$( "#langSelector .langOptions" )
.append( $ul );
$( "#langSelector" ).hover(
function () {
var $ele = $( ".langOptions" );
$ele.css( "top", "-" + $ele.outerHeight() + "px" ).stop( true, true ).fadeIn();
},
function () {
$( ".langOptions" ).stop( true, true ).fadeOut();
}
);
};
this.localize = function ( langs, lang, useBrowserLang ) {
if ( useBrowserLang === true ) {
var browserLang = navigator.language;
if ( langs[ browserLang ] !== undefined ) {
lang = browserLang;
} else if ( browserLang.length > 2 && langs[ browserLang.substr( 0, 2 ) ] !== undefined ) {
lang = browserLang.substr( 0, 2 );
};
};
if ( langs[ lang ] === undefined ) {
lang = "en";
};
var storedLang = localStorage.getItem( this.config.store.lang );
if ( langs[ storedLang ] !== undefined ) {
lang = storedLang;
};
var selected = langs[ lang ];
for ( key in selected ) {
$( ".l10n-" + key ).text( selected[key] );
};
$( ".lang" ).text( lang );
$( ".langOption" ).removeClass( "current" );
$( ".langOption." + lang ).addClass( "current" );
};
/*******************************
* initiate tree indicators
*******************************/
this.initIndicators = function () {
var THIS = this;
$( "#tree .entry.folder:not(.initiatedIndicator)" ).each( function () {
var $entry = $( this ).addClass( "initiatedIndicator" );
var $indicator = $entry.find( "> .indicator" );
$indicator.click( function( event ) {
if ( $indicator.hasClass( "unknown" ) ) {
$.get( "/h5ai/php/treecontent.php", { "href": $entry.find( "> a" ).attr( "href" ) }, function ( html ) {
$content = $( html );
$indicator.removeClass( "unknown" );
if ( $content.find( "> li" ).size() === 0 ) {
$indicator.replaceWith( $( "<span class='blank' />" ) );
} else {
$indicator.addClass( "open" );
$entry.find( "> .content" ).replaceWith( $content );
$( "#tree" ).get( 0 ).updateScrollbar();
THIS.initIndicators();
};
} );
} else if ( $indicator.hasClass( "open" ) ) {
$indicator.removeClass( "open" );
$( "#tree" ).get( 0 ).updateScrollbar( true );
$entry.find( "> .content" ).slideUp( function() {
$( "#tree" ).get( 0 ).updateScrollbar();
} );
} else {
$indicator.addClass( "open" );
$( "#tree" ).get( 0 ).updateScrollbar( true );
$entry.find( "> .content" ).slideDown( function() {
$( "#tree" ).get( 0 ).updateScrollbar();
} );
};
} );
} );
};
};

View File

@@ -1,31 +0,0 @@
// v2.2
(function($){$.toJSON=function(o)
{if(typeof(JSON)=='object'&&JSON.stringify)
return JSON.stringify(o);var type=typeof(o);if(o===null)
return"null";if(type=="undefined")
return undefined;if(type=="number"||type=="boolean")
return o+"";if(type=="string")
return $.quoteString(o);if(type=='object')
{if(typeof o.toJSON=="function")
return $.toJSON(o.toJSON());if(o.constructor===Date)
{var month=o.getUTCMonth()+1;if(month<10)month='0'+month;var day=o.getUTCDate();if(day<10)day='0'+day;var year=o.getUTCFullYear();var hours=o.getUTCHours();if(hours<10)hours='0'+hours;var minutes=o.getUTCMinutes();if(minutes<10)minutes='0'+minutes;var seconds=o.getUTCSeconds();if(seconds<10)seconds='0'+seconds;var milli=o.getUTCMilliseconds();if(milli<100)milli='0'+milli;if(milli<10)milli='0'+milli;return'"'+year+'-'+month+'-'+day+'T'+
hours+':'+minutes+':'+seconds+'.'+milli+'Z"';}
if(o.constructor===Array)
{var ret=[];for(var i=0;i<o.length;i++)
ret.push($.toJSON(o[i])||"null");return"["+ret.join(",")+"]";}
var pairs=[];for(var k in o){var name;var type=typeof k;if(type=="number")
name='"'+k+'"';else if(type=="string")
name=$.quoteString(k);else
continue;if(typeof o[k]=="function")
continue;var val=$.toJSON(o[k]);pairs.push(name+":"+val);}
return"{"+pairs.join(", ")+"}";}};$.evalJSON=function(src)
{if(typeof(JSON)=='object'&&JSON.parse)
return JSON.parse(src);return eval("("+src+")");};$.secureEvalJSON=function(src)
{if(typeof(JSON)=='object'&&JSON.parse)
return JSON.parse(src);var filtered=src;filtered=filtered.replace(/\\["\\\/bfnrtu]/g,'@');filtered=filtered.replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,']');filtered=filtered.replace(/(?:^|:|,)(?:\s*\[)+/g,'');if(/^[\],:{}\s]*$/.test(filtered))
return eval("("+src+")");else
throw new SyntaxError("Error parsing JSON, source is not valid.");};$.quoteString=function(string)
{if(string.match(_escapeable))
{return'"'+string.replace(_escapeable,function(a)
{var c=_meta[a];if(typeof c==='string')return c;c=a.charCodeAt();return'\\u00'+Math.floor(c/16).toString(16)+(c%16).toString(16);})+'"';}
return'"'+string+'"';};var _escapeable=/["\\\x00-\x1f\x7f-\x9f]/g;var _meta={'\b':'\\b','\t':'\\t','\n':'\\n','\f':'\\f','\r':'\\r','"':'\\"','\\':'\\\\'};})(jQuery);

View File

@@ -1,133 +0,0 @@
( function ( $ ) {
var init = function ( htmlElement ) {
var $element = $( htmlElement );
if ( $element.css( "position" ) === undefined || $element.css( "position" ) === "static" ) {
$element.css( "position", "relative" );
};
var $scrollbar = $( "<div class='scrollbar' />" );
var $drag = $( "<div class='drag' />" ).appendTo( $scrollbar );
$element
.wrapInner( "<div class='wrapper'><div class='content' /></div>" )
.append( $scrollbar );
var $wrapper = $element.find( "> .wrapper" );
var $content = $wrapper.find( "> .content" );
var mouseOffsetY = 0;
var updateId = undefined;
var update = function ( repeat ) {
if ( updateId !== undefined && !repeat ) {
clearInterval( updateId );
updateId = undefined;
} else if ( updateId === undefined && repeat ) {
updateId = setInterval( function() { update( true ); }, 50 );
};
$wrapper.css( "height", $element.height() );
var visibleHeight = $element.height();
var contentHeight = $content.outerHeight();
var scrollTop = $wrapper.scrollTop();
var scrollTopFrac = scrollTop / contentHeight;
var visVertFrac = Math.min( visibleHeight / contentHeight, 1 );
if ( visVertFrac < 1 ) {
$scrollbar
.fadeIn( 50 )
.css( {
height: $element.innerHeight() + $scrollbar.height() - $scrollbar.outerHeight( true )
} );
$drag
.css( {
top: $scrollbar.height() * scrollTopFrac,
height: $scrollbar.height() * visVertFrac
} );
} else {
$scrollbar.fadeOut( 50 );
};
};
var scroll = function ( event ) {
event.preventDefault();
var clickFrac = ( event.pageY - $scrollbar.offset().top - mouseOffsetY ) / $scrollbar.height();
$wrapper.scrollTop( $content.outerHeight() * clickFrac );
update();
};
$element
.mousewheel( function ( event, delta) {
$wrapper.scrollTop( $wrapper.scrollTop() - 50 * delta );
update();
event.stopPropagation();
event.preventDefault();
} )
.scroll( update );
$element.get( 0 ).updateScrollbar = update;
$wrapper
.css( {
"padding-right": $scrollbar.outerWidth( true ),
height: $element.height(),
overflow: "hidden"
} );
$scrollbar
.css( {
position: "absolute",
top: 0,
right: 0,
overflow: "hidden",
cursor: "pointer"
} )
.mousedown( function ( event ) {
mouseOffsetY = $drag.outerHeight() / 2;
scroll( event );
$scrollbar.addClass( "dragOn" );
$( window )
.bind( "mousemove", scroll )
.one( "mouseup", function ( event ) {
$scrollbar.removeClass( "dragOn" );
$( window ).unbind( "mousemove", scroll );
scroll( event );
event.stopPropagation();
} );
event.preventDefault();
} )
.each( function () {
this.onselectstart = function () {
return false;
};
} );
$drag
.css( {
position: "absolute",
left: 0,
width: "100%"
} )
.mousedown( function ( event ) {
mouseOffsetY = event.pageY - $drag.offset().top;
scroll( event );
$scrollbar.addClass( "dragOn" );
$( window )
.bind( "mousemove", scroll )
.one( "mouseup", function ( event ) {
$scrollbar.removeClass( "dragOn" );
$( window ).unbind( "mousemove", scroll );
scroll( event );
event.stopPropagation();
} );
event.stopPropagation();
} );
update();
};
$.fn.scrollpanel = function () {
return this.each( function () {
init( this );
} );
};
} )( jQuery );

View File

@@ -1,24 +0,0 @@
( function( $ ) {
// http://paulirish.com/2009/log-a-lightweight-wrapper-for-consolelog/
// modified
$.log = function () {
$.log.history = $.log.history || [];
$.log.history.push( arguments );
if ( window.console ) {
window.console.log( Array.prototype.slice.call( arguments ) );
};
};
var Timer = function () {
this.start = new Date().getTime();;
this.last = this.start;
this.log = function ( label ) {
var now = new Date().getTime();
$.log( "timer", label, "+" + (now - this.last), "=" + (now - this.start) );
this.last = now;
};
};
$.timer = new Timer();
} )( jQuery );

10
src/h5ai/js/inc/lib/amplify.min.js vendored Normal file

File diff suppressed because one or more lines are too long

104
src/h5ai/js/inc/lib/date.js Normal file
View File

@@ -0,0 +1,104 @@
/**
* Version: 1.0 Alpha-1
* Build Date: 13-Nov-2007
* Copyright (c) 2006-2007, Coolite Inc. (http://www.coolite.com/). All rights reserved.
* License: Licensed under The MIT License. See license.txt and http://www.datejs.com/license/.
* Website: http://www.datejs.com/ or http://www.coolite.com/datejs/
*/
Date.CultureInfo={name:"en-US",englishName:"English (United States)",nativeName:"English (United States)",dayNames:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],abbreviatedDayNames:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],shortestDayNames:["Su","Mo","Tu","We","Th","Fr","Sa"],firstLetterDayNames:["S","M","T","W","T","F","S"],monthNames:["January","February","March","April","May","June","July","August","September","October","November","December"],abbreviatedMonthNames:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],amDesignator:"AM",pmDesignator:"PM",firstDayOfWeek:0,twoDigitYearMax:2029,dateElementOrder:"mdy",formatPatterns:{shortDate:"M/d/yyyy",longDate:"dddd, MMMM dd, yyyy",shortTime:"h:mm tt",longTime:"h:mm:ss tt",fullDateTime:"dddd, MMMM dd, yyyy h:mm:ss tt",sortableDateTime:"yyyy-MM-ddTHH:mm:ss",universalSortableDateTime:"yyyy-MM-dd HH:mm:ssZ",rfc1123:"ddd, dd MMM yyyy HH:mm:ss GMT",monthDay:"MMMM dd",yearMonth:"MMMM, yyyy"},regexPatterns:{jan:/^jan(uary)?/i,feb:/^feb(ruary)?/i,mar:/^mar(ch)?/i,apr:/^apr(il)?/i,may:/^may/i,jun:/^jun(e)?/i,jul:/^jul(y)?/i,aug:/^aug(ust)?/i,sep:/^sep(t(ember)?)?/i,oct:/^oct(ober)?/i,nov:/^nov(ember)?/i,dec:/^dec(ember)?/i,sun:/^su(n(day)?)?/i,mon:/^mo(n(day)?)?/i,tue:/^tu(e(s(day)?)?)?/i,wed:/^we(d(nesday)?)?/i,thu:/^th(u(r(s(day)?)?)?)?/i,fri:/^fr(i(day)?)?/i,sat:/^sa(t(urday)?)?/i,future:/^next/i,past:/^last|past|prev(ious)?/i,add:/^(\+|after|from)/i,subtract:/^(\-|before|ago)/i,yesterday:/^yesterday/i,today:/^t(oday)?/i,tomorrow:/^tomorrow/i,now:/^n(ow)?/i,millisecond:/^ms|milli(second)?s?/i,second:/^sec(ond)?s?/i,minute:/^min(ute)?s?/i,hour:/^h(ou)?rs?/i,week:/^w(ee)?k/i,month:/^m(o(nth)?s?)?/i,day:/^d(ays?)?/i,year:/^y((ea)?rs?)?/i,shortMeridian:/^(a|p)/i,longMeridian:/^(a\.?m?\.?|p\.?m?\.?)/i,timezone:/^((e(s|d)t|c(s|d)t|m(s|d)t|p(s|d)t)|((gmt)?\s*(\+|\-)\s*\d\d\d\d?)|gmt)/i,ordinalSuffix:/^\s*(st|nd|rd|th)/i,timeContext:/^\s*(\:|a|p)/i},abbreviatedTimeZoneStandard:{GMT:"-000",EST:"-0400",CST:"-0500",MST:"-0600",PST:"-0700"},abbreviatedTimeZoneDST:{GMT:"-000",EDT:"-0500",CDT:"-0600",MDT:"-0700",PDT:"-0800"}};
Date.getMonthNumberFromName=function(name){var n=Date.CultureInfo.monthNames,m=Date.CultureInfo.abbreviatedMonthNames,s=name.toLowerCase();for(var i=0;i<n.length;i++){if(n[i].toLowerCase()==s||m[i].toLowerCase()==s){return i;}}
return-1;};Date.getDayNumberFromName=function(name){var n=Date.CultureInfo.dayNames,m=Date.CultureInfo.abbreviatedDayNames,o=Date.CultureInfo.shortestDayNames,s=name.toLowerCase();for(var i=0;i<n.length;i++){if(n[i].toLowerCase()==s||m[i].toLowerCase()==s){return i;}}
return-1;};Date.isLeapYear=function(year){return(((year%4===0)&&(year%100!==0))||(year%400===0));};Date.getDaysInMonth=function(year,month){return[31,(Date.isLeapYear(year)?29:28),31,30,31,30,31,31,30,31,30,31][month];};Date.getTimezoneOffset=function(s,dst){return(dst||false)?Date.CultureInfo.abbreviatedTimeZoneDST[s.toUpperCase()]:Date.CultureInfo.abbreviatedTimeZoneStandard[s.toUpperCase()];};Date.getTimezoneAbbreviation=function(offset,dst){var n=(dst||false)?Date.CultureInfo.abbreviatedTimeZoneDST:Date.CultureInfo.abbreviatedTimeZoneStandard,p;for(p in n){if(n[p]===offset){return p;}}
return null;};Date.prototype.clone=function(){return new Date(this.getTime());};Date.prototype.compareTo=function(date){if(isNaN(this)){throw new Error(this);}
if(date instanceof Date&&!isNaN(date)){return(this>date)?1:(this<date)?-1:0;}else{throw new TypeError(date);}};Date.prototype.equals=function(date){return(this.compareTo(date)===0);};Date.prototype.between=function(start,end){var t=this.getTime();return t>=start.getTime()&&t<=end.getTime();};Date.prototype.addMilliseconds=function(value){this.setMilliseconds(this.getMilliseconds()+value);return this;};Date.prototype.addSeconds=function(value){return this.addMilliseconds(value*1000);};Date.prototype.addMinutes=function(value){return this.addMilliseconds(value*60000);};Date.prototype.addHours=function(value){return this.addMilliseconds(value*3600000);};Date.prototype.addDays=function(value){return this.addMilliseconds(value*86400000);};Date.prototype.addWeeks=function(value){return this.addMilliseconds(value*604800000);};Date.prototype.addMonths=function(value){var n=this.getDate();this.setDate(1);this.setMonth(this.getMonth()+value);this.setDate(Math.min(n,this.getDaysInMonth()));return this;};Date.prototype.addYears=function(value){return this.addMonths(value*12);};Date.prototype.add=function(config){if(typeof config=="number"){this._orient=config;return this;}
var x=config;if(x.millisecond||x.milliseconds){this.addMilliseconds(x.millisecond||x.milliseconds);}
if(x.second||x.seconds){this.addSeconds(x.second||x.seconds);}
if(x.minute||x.minutes){this.addMinutes(x.minute||x.minutes);}
if(x.hour||x.hours){this.addHours(x.hour||x.hours);}
if(x.month||x.months){this.addMonths(x.month||x.months);}
if(x.year||x.years){this.addYears(x.year||x.years);}
if(x.day||x.days){this.addDays(x.day||x.days);}
return this;};Date._validate=function(value,min,max,name){if(typeof value!="number"){throw new TypeError(value+" is not a Number.");}else if(value<min||value>max){throw new RangeError(value+" is not a valid value for "+name+".");}
return true;};Date.validateMillisecond=function(n){return Date._validate(n,0,999,"milliseconds");};Date.validateSecond=function(n){return Date._validate(n,0,59,"seconds");};Date.validateMinute=function(n){return Date._validate(n,0,59,"minutes");};Date.validateHour=function(n){return Date._validate(n,0,23,"hours");};Date.validateDay=function(n,year,month){return Date._validate(n,1,Date.getDaysInMonth(year,month),"days");};Date.validateMonth=function(n){return Date._validate(n,0,11,"months");};Date.validateYear=function(n){return Date._validate(n,1,9999,"seconds");};Date.prototype.set=function(config){var x=config;if(!x.millisecond&&x.millisecond!==0){x.millisecond=-1;}
if(!x.second&&x.second!==0){x.second=-1;}
if(!x.minute&&x.minute!==0){x.minute=-1;}
if(!x.hour&&x.hour!==0){x.hour=-1;}
if(!x.day&&x.day!==0){x.day=-1;}
if(!x.month&&x.month!==0){x.month=-1;}
if(!x.year&&x.year!==0){x.year=-1;}
if(x.millisecond!=-1&&Date.validateMillisecond(x.millisecond)){this.addMilliseconds(x.millisecond-this.getMilliseconds());}
if(x.second!=-1&&Date.validateSecond(x.second)){this.addSeconds(x.second-this.getSeconds());}
if(x.minute!=-1&&Date.validateMinute(x.minute)){this.addMinutes(x.minute-this.getMinutes());}
if(x.hour!=-1&&Date.validateHour(x.hour)){this.addHours(x.hour-this.getHours());}
if(x.month!==-1&&Date.validateMonth(x.month)){this.addMonths(x.month-this.getMonth());}
if(x.year!=-1&&Date.validateYear(x.year)){this.addYears(x.year-this.getFullYear());}
if(x.day!=-1&&Date.validateDay(x.day,this.getFullYear(),this.getMonth())){this.addDays(x.day-this.getDate());}
if(x.timezone){this.setTimezone(x.timezone);}
if(x.timezoneOffset){this.setTimezoneOffset(x.timezoneOffset);}
return this;};Date.prototype.clearTime=function(){this.setHours(0);this.setMinutes(0);this.setSeconds(0);this.setMilliseconds(0);return this;};Date.prototype.isLeapYear=function(){var y=this.getFullYear();return(((y%4===0)&&(y%100!==0))||(y%400===0));};Date.prototype.isWeekday=function(){return!(this.is().sat()||this.is().sun());};Date.prototype.getDaysInMonth=function(){return Date.getDaysInMonth(this.getFullYear(),this.getMonth());};Date.prototype.moveToFirstDayOfMonth=function(){return this.set({day:1});};Date.prototype.moveToLastDayOfMonth=function(){return this.set({day:this.getDaysInMonth()});};Date.prototype.moveToDayOfWeek=function(day,orient){var diff=(day-this.getDay()+7*(orient||+1))%7;return this.addDays((diff===0)?diff+=7*(orient||+1):diff);};Date.prototype.moveToMonth=function(month,orient){var diff=(month-this.getMonth()+12*(orient||+1))%12;return this.addMonths((diff===0)?diff+=12*(orient||+1):diff);};Date.prototype.getDayOfYear=function(){return Math.floor((this-new Date(this.getFullYear(),0,1))/86400000);};Date.prototype.getWeekOfYear=function(firstDayOfWeek){var y=this.getFullYear(),m=this.getMonth(),d=this.getDate();var dow=firstDayOfWeek||Date.CultureInfo.firstDayOfWeek;var offset=7+1-new Date(y,0,1).getDay();if(offset==8){offset=1;}
var daynum=((Date.UTC(y,m,d,0,0,0)-Date.UTC(y,0,1,0,0,0))/86400000)+1;var w=Math.floor((daynum-offset+7)/7);if(w===dow){y--;var prevOffset=7+1-new Date(y,0,1).getDay();if(prevOffset==2||prevOffset==8){w=53;}else{w=52;}}
return w;};Date.prototype.isDST=function(){console.log('isDST');return this.toString().match(/(E|C|M|P)(S|D)T/)[2]=="D";};Date.prototype.getTimezone=function(){return Date.getTimezoneAbbreviation(this.getUTCOffset,this.isDST());};Date.prototype.setTimezoneOffset=function(s){var here=this.getTimezoneOffset(),there=Number(s)*-6/10;this.addMinutes(there-here);return this;};Date.prototype.setTimezone=function(s){return this.setTimezoneOffset(Date.getTimezoneOffset(s));};Date.prototype.getUTCOffset=function(){var n=this.getTimezoneOffset()*-10/6,r;if(n<0){r=(n-10000).toString();return r[0]+r.substr(2);}else{r=(n+10000).toString();return"+"+r.substr(1);}};Date.prototype.getDayName=function(abbrev){return abbrev?Date.CultureInfo.abbreviatedDayNames[this.getDay()]:Date.CultureInfo.dayNames[this.getDay()];};Date.prototype.getMonthName=function(abbrev){return abbrev?Date.CultureInfo.abbreviatedMonthNames[this.getMonth()]:Date.CultureInfo.monthNames[this.getMonth()];};Date.prototype._toString=Date.prototype.toString;Date.prototype.toString=function(format){var self=this;var p=function p(s){return(s.toString().length==1)?"0"+s:s;};return format?format.replace(/dd?d?d?|MM?M?M?|yy?y?y?|hh?|HH?|mm?|ss?|tt?|zz?z?/g,function(format){switch(format){case"hh":return p(self.getHours()<13?self.getHours():(self.getHours()-12));case"h":return self.getHours()<13?self.getHours():(self.getHours()-12);case"HH":return p(self.getHours());case"H":return self.getHours();case"mm":return p(self.getMinutes());case"m":return self.getMinutes();case"ss":return p(self.getSeconds());case"s":return self.getSeconds();case"yyyy":return self.getFullYear();case"yy":return self.getFullYear().toString().substring(2,4);case"dddd":return self.getDayName();case"ddd":return self.getDayName(true);case"dd":return p(self.getDate());case"d":return self.getDate().toString();case"MMMM":return self.getMonthName();case"MMM":return self.getMonthName(true);case"MM":return p((self.getMonth()+1));case"M":return self.getMonth()+1;case"t":return self.getHours()<12?Date.CultureInfo.amDesignator.substring(0,1):Date.CultureInfo.pmDesignator.substring(0,1);case"tt":return self.getHours()<12?Date.CultureInfo.amDesignator:Date.CultureInfo.pmDesignator;case"zzz":case"zz":case"z":return"";}}):this._toString();};
Date.now=function(){return new Date();};Date.today=function(){return Date.now().clearTime();};Date.prototype._orient=+1;Date.prototype.next=function(){this._orient=+1;return this;};Date.prototype.last=Date.prototype.prev=Date.prototype.previous=function(){this._orient=-1;return this;};Date.prototype._is=false;Date.prototype.is=function(){this._is=true;return this;};Number.prototype._dateElement="day";Number.prototype.fromNow=function(){var c={};c[this._dateElement]=this;return Date.now().add(c);};Number.prototype.ago=function(){var c={};c[this._dateElement]=this*-1;return Date.now().add(c);};(function(){var $D=Date.prototype,$N=Number.prototype;var dx=("sunday monday tuesday wednesday thursday friday saturday").split(/\s/),mx=("january february march april may june july august september october november december").split(/\s/),px=("Millisecond Second Minute Hour Day Week Month Year").split(/\s/),de;var df=function(n){return function(){if(this._is){this._is=false;return this.getDay()==n;}
return this.moveToDayOfWeek(n,this._orient);};};for(var i=0;i<dx.length;i++){$D[dx[i]]=$D[dx[i].substring(0,3)]=df(i);}
var mf=function(n){return function(){if(this._is){this._is=false;return this.getMonth()===n;}
return this.moveToMonth(n,this._orient);};};for(var j=0;j<mx.length;j++){$D[mx[j]]=$D[mx[j].substring(0,3)]=mf(j);}
var ef=function(j){return function(){if(j.substring(j.length-1)!="s"){j+="s";}
return this["add"+j](this._orient);};};var nf=function(n){return function(){this._dateElement=n;return this;};};for(var k=0;k<px.length;k++){de=px[k].toLowerCase();$D[de]=$D[de+"s"]=ef(px[k]);$N[de]=$N[de+"s"]=nf(de);}}());Date.prototype.toJSONString=function(){return this.toString("yyyy-MM-ddThh:mm:ssZ");};Date.prototype.toShortDateString=function(){return this.toString(Date.CultureInfo.formatPatterns.shortDatePattern);};Date.prototype.toLongDateString=function(){return this.toString(Date.CultureInfo.formatPatterns.longDatePattern);};Date.prototype.toShortTimeString=function(){return this.toString(Date.CultureInfo.formatPatterns.shortTimePattern);};Date.prototype.toLongTimeString=function(){return this.toString(Date.CultureInfo.formatPatterns.longTimePattern);};Date.prototype.getOrdinal=function(){switch(this.getDate()){case 1:case 21:case 31:return"st";case 2:case 22:return"nd";case 3:case 23:return"rd";default:return"th";}};
(function(){Date.Parsing={Exception:function(s){this.message="Parse error at '"+s.substring(0,10)+" ...'";}};var $P=Date.Parsing;var _=$P.Operators={rtoken:function(r){return function(s){var mx=s.match(r);if(mx){return([mx[0],s.substring(mx[0].length)]);}else{throw new $P.Exception(s);}};},token:function(s){return function(s){return _.rtoken(new RegExp("^\s*"+s+"\s*"))(s);};},stoken:function(s){return _.rtoken(new RegExp("^"+s));},until:function(p){return function(s){var qx=[],rx=null;while(s.length){try{rx=p.call(this,s);}catch(e){qx.push(rx[0]);s=rx[1];continue;}
break;}
return[qx,s];};},many:function(p){return function(s){var rx=[],r=null;while(s.length){try{r=p.call(this,s);}catch(e){return[rx,s];}
rx.push(r[0]);s=r[1];}
return[rx,s];};},optional:function(p){return function(s){var r=null;try{r=p.call(this,s);}catch(e){return[null,s];}
return[r[0],r[1]];};},not:function(p){return function(s){try{p.call(this,s);}catch(e){return[null,s];}
throw new $P.Exception(s);};},ignore:function(p){return p?function(s){var r=null;r=p.call(this,s);return[null,r[1]];}:null;},product:function(){var px=arguments[0],qx=Array.prototype.slice.call(arguments,1),rx=[];for(var i=0;i<px.length;i++){rx.push(_.each(px[i],qx));}
return rx;},cache:function(rule){var cache={},r=null;return function(s){try{r=cache[s]=(cache[s]||rule.call(this,s));}catch(e){r=cache[s]=e;}
if(r instanceof $P.Exception){throw r;}else{return r;}};},any:function(){var px=arguments;return function(s){var r=null;for(var i=0;i<px.length;i++){if(px[i]==null){continue;}
try{r=(px[i].call(this,s));}catch(e){r=null;}
if(r){return r;}}
throw new $P.Exception(s);};},each:function(){var px=arguments;return function(s){var rx=[],r=null;for(var i=0;i<px.length;i++){if(px[i]==null){continue;}
try{r=(px[i].call(this,s));}catch(e){throw new $P.Exception(s);}
rx.push(r[0]);s=r[1];}
return[rx,s];};},all:function(){var px=arguments,_=_;return _.each(_.optional(px));},sequence:function(px,d,c){d=d||_.rtoken(/^\s*/);c=c||null;if(px.length==1){return px[0];}
return function(s){var r=null,q=null;var rx=[];for(var i=0;i<px.length;i++){try{r=px[i].call(this,s);}catch(e){break;}
rx.push(r[0]);try{q=d.call(this,r[1]);}catch(ex){q=null;break;}
s=q[1];}
if(!r){throw new $P.Exception(s);}
if(q){throw new $P.Exception(q[1]);}
if(c){try{r=c.call(this,r[1]);}catch(ey){throw new $P.Exception(r[1]);}}
return[rx,(r?r[1]:s)];};},between:function(d1,p,d2){d2=d2||d1;var _fn=_.each(_.ignore(d1),p,_.ignore(d2));return function(s){var rx=_fn.call(this,s);return[[rx[0][0],r[0][2]],rx[1]];};},list:function(p,d,c){d=d||_.rtoken(/^\s*/);c=c||null;return(p instanceof Array?_.each(_.product(p.slice(0,-1),_.ignore(d)),p.slice(-1),_.ignore(c)):_.each(_.many(_.each(p,_.ignore(d))),px,_.ignore(c)));},set:function(px,d,c){d=d||_.rtoken(/^\s*/);c=c||null;return function(s){var r=null,p=null,q=null,rx=null,best=[[],s],last=false;for(var i=0;i<px.length;i++){q=null;p=null;r=null;last=(px.length==1);try{r=px[i].call(this,s);}catch(e){continue;}
rx=[[r[0]],r[1]];if(r[1].length>0&&!last){try{q=d.call(this,r[1]);}catch(ex){last=true;}}else{last=true;}
if(!last&&q[1].length===0){last=true;}
if(!last){var qx=[];for(var j=0;j<px.length;j++){if(i!=j){qx.push(px[j]);}}
p=_.set(qx,d).call(this,q[1]);if(p[0].length>0){rx[0]=rx[0].concat(p[0]);rx[1]=p[1];}}
if(rx[1].length<best[1].length){best=rx;}
if(best[1].length===0){break;}}
if(best[0].length===0){return best;}
if(c){try{q=c.call(this,best[1]);}catch(ey){throw new $P.Exception(best[1]);}
best[1]=q[1];}
return best;};},forward:function(gr,fname){return function(s){return gr[fname].call(this,s);};},replace:function(rule,repl){return function(s){var r=rule.call(this,s);return[repl,r[1]];};},process:function(rule,fn){return function(s){var r=rule.call(this,s);return[fn.call(this,r[0]),r[1]];};},min:function(min,rule){return function(s){var rx=rule.call(this,s);if(rx[0].length<min){throw new $P.Exception(s);}
return rx;};}};var _generator=function(op){return function(){var args=null,rx=[];if(arguments.length>1){args=Array.prototype.slice.call(arguments);}else if(arguments[0]instanceof Array){args=arguments[0];}
if(args){for(var i=0,px=args.shift();i<px.length;i++){args.unshift(px[i]);rx.push(op.apply(null,args));args.shift();return rx;}}else{return op.apply(null,arguments);}};};var gx="optional not ignore cache".split(/\s/);for(var i=0;i<gx.length;i++){_[gx[i]]=_generator(_[gx[i]]);}
var _vector=function(op){return function(){if(arguments[0]instanceof Array){return op.apply(null,arguments[0]);}else{return op.apply(null,arguments);}};};var vx="each any all".split(/\s/);for(var j=0;j<vx.length;j++){_[vx[j]]=_vector(_[vx[j]]);}}());(function(){var flattenAndCompact=function(ax){var rx=[];for(var i=0;i<ax.length;i++){if(ax[i]instanceof Array){rx=rx.concat(flattenAndCompact(ax[i]));}else{if(ax[i]){rx.push(ax[i]);}}}
return rx;};Date.Grammar={};Date.Translator={hour:function(s){return function(){this.hour=Number(s);};},minute:function(s){return function(){this.minute=Number(s);};},second:function(s){return function(){this.second=Number(s);};},meridian:function(s){return function(){this.meridian=s.slice(0,1).toLowerCase();};},timezone:function(s){return function(){var n=s.replace(/[^\d\+\-]/g,"");if(n.length){this.timezoneOffset=Number(n);}else{this.timezone=s.toLowerCase();}};},day:function(x){var s=x[0];return function(){this.day=Number(s.match(/\d+/)[0]);};},month:function(s){return function(){this.month=((s.length==3)?Date.getMonthNumberFromName(s):(Number(s)-1));};},year:function(s){return function(){var n=Number(s);this.year=((s.length>2)?n:(n+(((n+2000)<Date.CultureInfo.twoDigitYearMax)?2000:1900)));};},rday:function(s){return function(){switch(s){case"yesterday":this.days=-1;break;case"tomorrow":this.days=1;break;case"today":this.days=0;break;case"now":this.days=0;this.now=true;break;}};},finishExact:function(x){x=(x instanceof Array)?x:[x];var now=new Date();this.year=now.getFullYear();this.month=now.getMonth();this.day=1;this.hour=0;this.minute=0;this.second=0;for(var i=0;i<x.length;i++){if(x[i]){x[i].call(this);}}
this.hour=(this.meridian=="p"&&this.hour<13)?this.hour+12:this.hour;if(this.day>Date.getDaysInMonth(this.year,this.month)){throw new RangeError(this.day+" is not a valid value for days.");}
var r=new Date(this.year,this.month,this.day,this.hour,this.minute,this.second);if(this.timezone){r.set({timezone:this.timezone});}else if(this.timezoneOffset){r.set({timezoneOffset:this.timezoneOffset});}
return r;},finish:function(x){x=(x instanceof Array)?flattenAndCompact(x):[x];if(x.length===0){return null;}
for(var i=0;i<x.length;i++){if(typeof x[i]=="function"){x[i].call(this);}}
if(this.now){return new Date();}
var today=Date.today();var method=null;var expression=!!(this.days!=null||this.orient||this.operator);if(expression){var gap,mod,orient;orient=((this.orient=="past"||this.operator=="subtract")?-1:1);if(this.weekday){this.unit="day";gap=(Date.getDayNumberFromName(this.weekday)-today.getDay());mod=7;this.days=gap?((gap+(orient*mod))%mod):(orient*mod);}
if(this.month){this.unit="month";gap=(this.month-today.getMonth());mod=12;this.months=gap?((gap+(orient*mod))%mod):(orient*mod);this.month=null;}
if(!this.unit){this.unit="day";}
if(this[this.unit+"s"]==null||this.operator!=null){if(!this.value){this.value=1;}
if(this.unit=="week"){this.unit="day";this.value=this.value*7;}
this[this.unit+"s"]=this.value*orient;}
return today.add(this);}else{if(this.meridian&&this.hour){this.hour=(this.hour<13&&this.meridian=="p")?this.hour+12:this.hour;}
if(this.weekday&&!this.day){this.day=(today.addDays((Date.getDayNumberFromName(this.weekday)-today.getDay()))).getDate();}
if(this.month&&!this.day){this.day=1;}
return today.set(this);}}};var _=Date.Parsing.Operators,g=Date.Grammar,t=Date.Translator,_fn;g.datePartDelimiter=_.rtoken(/^([\s\-\.\,\/\x27]+)/);g.timePartDelimiter=_.stoken(":");g.whiteSpace=_.rtoken(/^\s*/);g.generalDelimiter=_.rtoken(/^(([\s\,]|at|on)+)/);var _C={};g.ctoken=function(keys){var fn=_C[keys];if(!fn){var c=Date.CultureInfo.regexPatterns;var kx=keys.split(/\s+/),px=[];for(var i=0;i<kx.length;i++){px.push(_.replace(_.rtoken(c[kx[i]]),kx[i]));}
fn=_C[keys]=_.any.apply(null,px);}
return fn;};g.ctoken2=function(key){return _.rtoken(Date.CultureInfo.regexPatterns[key]);};g.h=_.cache(_.process(_.rtoken(/^(0[0-9]|1[0-2]|[1-9])/),t.hour));g.hh=_.cache(_.process(_.rtoken(/^(0[0-9]|1[0-2])/),t.hour));g.H=_.cache(_.process(_.rtoken(/^([0-1][0-9]|2[0-3]|[0-9])/),t.hour));g.HH=_.cache(_.process(_.rtoken(/^([0-1][0-9]|2[0-3])/),t.hour));g.m=_.cache(_.process(_.rtoken(/^([0-5][0-9]|[0-9])/),t.minute));g.mm=_.cache(_.process(_.rtoken(/^[0-5][0-9]/),t.minute));g.s=_.cache(_.process(_.rtoken(/^([0-5][0-9]|[0-9])/),t.second));g.ss=_.cache(_.process(_.rtoken(/^[0-5][0-9]/),t.second));g.hms=_.cache(_.sequence([g.H,g.mm,g.ss],g.timePartDelimiter));g.t=_.cache(_.process(g.ctoken2("shortMeridian"),t.meridian));g.tt=_.cache(_.process(g.ctoken2("longMeridian"),t.meridian));g.z=_.cache(_.process(_.rtoken(/^(\+|\-)?\s*\d\d\d\d?/),t.timezone));g.zz=_.cache(_.process(_.rtoken(/^(\+|\-)\s*\d\d\d\d/),t.timezone));g.zzz=_.cache(_.process(g.ctoken2("timezone"),t.timezone));g.timeSuffix=_.each(_.ignore(g.whiteSpace),_.set([g.tt,g.zzz]));g.time=_.each(_.optional(_.ignore(_.stoken("T"))),g.hms,g.timeSuffix);g.d=_.cache(_.process(_.each(_.rtoken(/^([0-2]\d|3[0-1]|\d)/),_.optional(g.ctoken2("ordinalSuffix"))),t.day));g.dd=_.cache(_.process(_.each(_.rtoken(/^([0-2]\d|3[0-1])/),_.optional(g.ctoken2("ordinalSuffix"))),t.day));g.ddd=g.dddd=_.cache(_.process(g.ctoken("sun mon tue wed thu fri sat"),function(s){return function(){this.weekday=s;};}));g.M=_.cache(_.process(_.rtoken(/^(1[0-2]|0\d|\d)/),t.month));g.MM=_.cache(_.process(_.rtoken(/^(1[0-2]|0\d)/),t.month));g.MMM=g.MMMM=_.cache(_.process(g.ctoken("jan feb mar apr may jun jul aug sep oct nov dec"),t.month));g.y=_.cache(_.process(_.rtoken(/^(\d\d?)/),t.year));g.yy=_.cache(_.process(_.rtoken(/^(\d\d)/),t.year));g.yyy=_.cache(_.process(_.rtoken(/^(\d\d?\d?\d?)/),t.year));g.yyyy=_.cache(_.process(_.rtoken(/^(\d\d\d\d)/),t.year));_fn=function(){return _.each(_.any.apply(null,arguments),_.not(g.ctoken2("timeContext")));};g.day=_fn(g.d,g.dd);g.month=_fn(g.M,g.MMM);g.year=_fn(g.yyyy,g.yy);g.orientation=_.process(g.ctoken("past future"),function(s){return function(){this.orient=s;};});g.operator=_.process(g.ctoken("add subtract"),function(s){return function(){this.operator=s;};});g.rday=_.process(g.ctoken("yesterday tomorrow today now"),t.rday);g.unit=_.process(g.ctoken("minute hour day week month year"),function(s){return function(){this.unit=s;};});g.value=_.process(_.rtoken(/^\d\d?(st|nd|rd|th)?/),function(s){return function(){this.value=s.replace(/\D/g,"");};});g.expression=_.set([g.rday,g.operator,g.value,g.unit,g.orientation,g.ddd,g.MMM]);_fn=function(){return _.set(arguments,g.datePartDelimiter);};g.mdy=_fn(g.ddd,g.month,g.day,g.year);g.ymd=_fn(g.ddd,g.year,g.month,g.day);g.dmy=_fn(g.ddd,g.day,g.month,g.year);g.date=function(s){return((g[Date.CultureInfo.dateElementOrder]||g.mdy).call(this,s));};g.format=_.process(_.many(_.any(_.process(_.rtoken(/^(dd?d?d?|MM?M?M?|yy?y?y?|hh?|HH?|mm?|ss?|tt?|zz?z?)/),function(fmt){if(g[fmt]){return g[fmt];}else{throw Date.Parsing.Exception(fmt);}}),_.process(_.rtoken(/^[^dMyhHmstz]+/),function(s){return _.ignore(_.stoken(s));}))),function(rules){return _.process(_.each.apply(null,rules),t.finishExact);});var _F={};var _get=function(f){return _F[f]=(_F[f]||g.format(f)[0]);};g.formats=function(fx){if(fx instanceof Array){var rx=[];for(var i=0;i<fx.length;i++){rx.push(_get(fx[i]));}
return _.any.apply(null,rx);}else{return _get(fx);}};g._formats=g.formats(["yyyy-MM-ddTHH:mm:ss","ddd, MMM dd, yyyy H:mm:ss tt","ddd MMM d yyyy HH:mm:ss zzz","d"]);g._start=_.process(_.set([g.date,g.time,g.expression],g.generalDelimiter,g.whiteSpace),t.finish);g.start=function(s){try{var r=g._formats.call({},s);if(r[1].length===0){return r;}}catch(e){}
return g._start.call({},s);};}());Date._parse=Date.parse;Date.parse=function(s){var r=null;if(!s){return null;}
try{r=Date.Grammar.start.call({},s);}catch(e){return null;}
return((r[1].length===0)?r[0]:null);};Date.getParseFunction=function(fx){var fn=Date.Grammar.formats(fx);return function(s){var r=null;try{r=fn.call({},s);}catch(e){return null;}
return((r[1].length===0)?r[0]:null);};};Date.parseExact=function(s,fx){return Date.getParseFunction(fx)(s);};

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,150 @@
(function ($) {
"use strict";
/*global window, jQuery */
var init = function (htmlElement) {
var $element = $(htmlElement),
$scrollbar, $drag, $wrapper, $content, mouseOffsetY, updateId,
update, scroll;
if (!$element.css("position") || $element.css("position") === "static") {
$element.css("position", "relative");
}
$scrollbar = $("<div class='scrollbar' />");
$drag = $("<div class='drag' />").appendTo($scrollbar);
$element
.wrapInner("<div class='wrapper'><div class='content' /></div>")
.append($scrollbar);
$wrapper = $element.find("> .wrapper");
$content = $wrapper.find("> .content");
mouseOffsetY = 0;
update = function (repeat) {
var visibleHeight, contentHeight, scrollTop, scrollTopFrac, visVertFrac;
if (updateId && !repeat) {
clearInterval(updateId);
updateId = undefined;
} else if (!updateId && repeat) {
updateId = setInterval(function() { update(true); }, 50);
}
$wrapper.css("height", $element.height());
visibleHeight = $element.height();
contentHeight = $content.outerHeight();
scrollTop = $wrapper.scrollTop();
scrollTopFrac = scrollTop / contentHeight;
visVertFrac = Math.min(visibleHeight / contentHeight, 1);
if (visVertFrac < 1) {
$scrollbar
.fadeIn(50)
.css({
height: $element.innerHeight() + $scrollbar.height() - $scrollbar.outerHeight(true)
});
$drag
.css({
top: $scrollbar.height() * scrollTopFrac,
height: $scrollbar.height() * visVertFrac
});
} else {
$scrollbar.fadeOut(50);
}
};
scroll = function (event) {
var clickFrac = (event.pageY - $scrollbar.offset().top - mouseOffsetY) / $scrollbar.height();
$wrapper.scrollTop($content.outerHeight() * clickFrac);
update();
event.preventDefault();
};
$element
.mousewheel(function (event, delta) {
$wrapper.scrollTop($wrapper.scrollTop() - 50 * delta);
update();
event.stopPropagation();
event.preventDefault();
})
.scroll(update);
$element.get(0).updateScrollbar = update;
$wrapper
.css({
"padding-right": $scrollbar.outerWidth(true),
height: $element.height(),
overflow: "hidden"
});
$scrollbar
.css({
position: "absolute",
top: 0,
right: 0,
overflow: "hidden",
cursor: "pointer"
})
.mousedown(function (event) {
mouseOffsetY = $drag.outerHeight() / 2;
scroll(event);
$scrollbar.addClass("dragOn");
$(window)
.bind("mousemove", scroll)
.one("mouseup", function (event) {
$scrollbar.removeClass("dragOn");
$(window).unbind("mousemove", scroll);
scroll(event);
event.stopPropagation();
});
event.preventDefault();
})
.each(function () {
this.onselectstart = function () {
return false;
};
});
$drag
.css({
position: "absolute",
left: 0,
width: "100%"
})
.mousedown(function (event) {
mouseOffsetY = event.pageY - $drag.offset().top;
scroll(event);
$scrollbar.addClass("dragOn");
$(window)
.bind("mousemove", scroll)
.one("mouseup", function (event) {
$scrollbar.removeClass("dragOn");
$(window).unbind("mousemove", scroll);
scroll(event);
event.stopPropagation();
});
event.stopPropagation();
});
update();
};
$.fn.scrollpanel = function () {
return this.each(function () {
init(this);
});
};
}(jQuery));

View File

@@ -1,465 +0,0 @@
var pathnameSplitRegEx = /^(\/(.*\/)*)([^\/]+\/?)$/;
var pathEndsWithSlashRegEx = /\/$/;
var PathCache = function () {
this.cache = {};
this.objectCache = {};
this.splitPathname = function ( pathname ) {
if ( pathname === "/" ) {
return [ "", "/" ];
};
var match = pathnameSplitRegEx.exec( pathname );
return [ match[1], match[3] ];
};
this.loadCache = function () {
var json = localStorage.getItem( "h5ai.cache" );
var objs = $.evalJSON( json );
var objectCache = {};
for ( idx in objs ) {
var obj = objs[idx];
objectCache[obj.r] = obj;
};
return objectCache;
};
this.storeCache = function () {
var objs = [];
for ( ref in this.objectCache ) {
objs.push( this.objectCache[ref] );
};
var json = $.toJSON( objs );
localStorage.setItem( "h5ai.cache", json );
};
this.pathToObject = function ( path ) {
var object = {
r: path.absHref,
s: path.status,
c: [],
o: path.treeOpen
};
if ( path.content !== undefined ) {
for ( ref in path.content ) {
object.c.push( ref );
};
};
return object;
};
this.objectToPath = function ( obj ) {
var path = this.getPathForFolder( obj.r );
path.status = obj.s;
path.content = {};
path.treeOpen = obj.o;
for ( idx in obj.c ) {
var href = obj.c[idx];
path.content[href] = this.getPathForFolder( href );
};
return path;
};
this.getAbsHref = function ( folder, tableRow ) {
if ( ! pathEndsWithSlashRegEx.test( folder ) ) {
folder += "/";
};
if ( tableRow === undefined ) {
return folder;
};
var $a = $( tableRow ).find( "td" ).eq( 1 ).find( "a" );
var isParentFolder = ( $a.text() === "Parent Directory" );
var href = $a.attr( "href" );
return isParentFolder ? undefined : folder + href;
};
this.getPathForFolder = function ( folder ) {
var absHref = this.getAbsHref( folder );
var cachedPath = this.cache[absHref];
if ( cachedPath !== undefined ) {
return cachedPath;
};
var path = new Path( this, folder );
this.cache[path.absHref] = path;
var obj = this.objectCache[absHref];
if ( obj !== undefined ) {
path.status = obj.s;
path.content = {};
path.treeOpen = obj.o;
for ( idx in obj.c ) {
var href = obj.c[idx];
path.content[href] = this.getPathForFolder( href );
};
} else {
var obj = this.pathToObject( path );
this.objectCache[obj.r] = obj;
this.storeCache();
};
return path;
};
this.getPathForTableRow = function ( parentFolder, tableRow ) {
var absHref = this.getAbsHref( parentFolder, tableRow );
var cachedPath = this.cache[absHref];
if ( cachedPath !== undefined ) {
return cachedPath;
};
var path = new Path( this, parentFolder, tableRow );
if ( ! path.isParentFolder ) {
this.cache[path.absHref] = path;
var obj = this.objectCache[absHref];
if ( obj !== undefined ) {
path.status = obj.s;
path.content = {};
path.treeOpen = obj.o;
for ( idx in obj.c ) {
var href = obj.c[idx];
path.content[href] = this.getPathForFolder( href );
};
} else {
if ( path.isFolder && path.status !== undefined ) {
var obj = this.pathToObject( path );
this.objectCache[obj.r] = obj;
this.storeCache();
};
};
};
return path;
};
this.objectCache = this.loadCache();
};
var Path = function ( pathCache, folder, tableRow ) {
this.checkedDecodeUri = function ( uri ) {
try {
return decodeURI( uri );
} catch ( err ) {
};
return uri;
}
if ( ! pathEndsWithSlashRegEx.test( folder ) ) {
folder += "/";
};
if ( tableRow !== undefined ) {
var $tds = $( tableRow ).find( "td" );
var $img = $tds.eq( 0 ).find( "img" );
var $a= $tds.eq( 1 ).find( "a" );
this.parentFolder = folder;
this.icon16 = $img.attr( "src" );
this.alt = $img.attr( "alt" );
this.label = $a.text();
this.href = $a.attr("href");
this.date = $tds.eq( 2 ).text();
this.size = $tds.eq( 3 ).text();
} else {
var splits = pathCache.splitPathname( folder );
this.parentFolder = splits[0];
this.href = splits[1];
this.label = this.checkedDecodeUri( splits[1] );
this.icon16 = "/h5ai/icons/16x16/folder.png";
this.alt = "[DIR]";
this.date = "";
this.size = "";
if ( this.label === "/" ) {
this.label = this.checkedDecodeUri( document.domain ) + "/";
};
};
if ( pathEndsWithSlashRegEx.test( this.label ) ) {
this.label = this.label.slice( 0, -1 );
};
this.icon48 = this.icon16.replace( "16x16", "48x48" );
this.isFolder = ( this.alt === "[DIR]" );
this.isParentFolder = ( this.isFolder && this.label === "Parent Directory" );
this.absHref = this.isParentFolder ? this.href : this.parentFolder + this.href;
this.isCurrentFolder = ( this.absHref === document.location.pathname );
this.isDomain = ( this.absHref === "/" );
if ( this.isParentFolder && h5ai.config.setParentFolderLabels ) {
if ( this.isDomain ) {
this.label = this.checkedDecodeUri( document.domain );
} else {
this.label = this.checkedDecodeUri( pathCache.splitPathname( pathCache.splitPathname( this.parentFolder )[0] )[1].slice( 0, -1 ) );
};
};
this.status = undefined; // undefined, "h5ai" or HTTP response code
this.content = undefined; // associative array path.absHref -> path
this.html = {
$crumb: undefined,
$extended: undefined,
$tree: undefined
};
this.treeOpen = false;
this.isEmpty = function() {
return this.content === undefined || $.isEmptyObject( this.content );
};
this.onClick = function ( context ) {
h5ai.triggerPathClick( this, context );
};
this.updateHtml = function () {
this.updateCrumbHtml();
this.updateExtendedHtml();
this.updateTreeHtml();
};
this.updateCrumbHtml = function () {
if ( this.html.$crumb !== undefined && this.html.$crumb.data( "status" ) === this.status ) {
return this.html.$crumb;
};
var $html = $( "<li class='crumb' />" ).data( "path", this );
if ( this.status !== undefined ) {
$html.data( "status", this.status );
};
try {
$html.addClass( this.isFolder ? "folder" : "file" );
var $a = $( "<a><img src='/h5ai/images/crumb.png' alt='>' />" + this.label + "</a>" );
$a.attr( "href", this.absHref );
$a.click( $.proxy( function() { this.onClick( "crumb" ); }, this ) );
$html.append( $a );
if ( this.isDomain ) {
$html.addClass( "domain" );
$a.find( "img" ).attr( "src", "/h5ai/images/home.png" );
};
if ( this.isCurrentFolder ) {
$html.addClass( "current" );
};
if ( !isNaN( this.status ) ) {
if ( this.status === 200 ) {
$( "<img class='hint' src='/h5ai/images/page.png' alt='not listable' />" ).appendTo( $a );
} else {
$( "<span class='hint'>(" + this.status + ")</span>" ).appendTo( $a );
};
};
} catch( err ) {
$( "<span class='fail'>failed</span>" ).appendTo( $html );
};
if ( this.html.$crumb !== undefined ) {
this.html.$crumb.replaceWith( $html );
};
this.html.$crumb = $html;
return $html;
};
this.updateExtendedHtml = function () {
if ( this.html.$extended !== undefined && this.html.$extended.data( "status" ) === this.status ) {
return this.html.$extended;
};
var $html = $( "<li class='entry' />" ).data( "path", this );
if ( this.status !== undefined ) {
$html.data( "status", this.status );
};
try {
$html.addClass( this.isFolder ? "folder" : "file" );
var $a = $( "<a />" ).appendTo( $html );
$a.attr( "href", this.absHref );
$a.click( $.proxy( function() { this.onClick( "extended" ); }, this ) );
$( "<span class='icon small'><img src='" + this.icon16 + "' alt='" + this.alt + "' /></span>" ).appendTo( $a );
$( "<span class='icon big'><img src='" + this.icon48 + "' alt='" + this.alt + "' /></span>" ).appendTo( $a );
var $label = $( "<span class='label'>" + this.label + "</span>" ).appendTo( $a );
$( "<span class='date'>" + this.date + "</span>" ).appendTo( $a );
$( "<span class='size'>" + this.size + "</span>" ).appendTo( $a );
if ( this.isParentFolder ) {
if ( !h5ai.config.setParentFolderLabels ) {
$label.addClass( "l10n-parentDirectory" );
};
$html.addClass( "parentfolder" );
};
if ( !isNaN( this.status ) ) {
if ( this.status === 200 ) {
$html.addClass( "page" );
$a.find( ".icon.small img" ).attr( "src", "/h5ai/icons/16x16/folder-page.png" );
$a.find( ".icon.big img" ).attr( "src", "/h5ai/icons/48x48/folder-page.png" );
} else {
$html.addClass( "error" );
$label.append( $( "<span class='hint'> " + this.status + " </span>" ) );
};
};
} catch( err ) {
$( "<span class='fail'>failed</span>" ).appendTo( $html );
};
if ( this.html.$extended !== undefined ) {
this.html.$extended.replaceWith( $html );
};
this.html.$extended = $html;
return $html;
};
this.updateTreeHtml = function () {
var $html = $( "<div class='entry' />" ).data( "path", this );
var $blank = $( "<span class='blank' />" ).appendTo( $html );
try {
$html.addClass( this.isFolder ? "folder" : "file" );
var $a = $( "<a />" )
.appendTo( $html )
.append( $( "<span class='icon'><img src='" + this.icon16 + "' /></span>" ) )
.append( $( "<span class='label'>" + this.label + "</span>" ) );
$a.attr( "href", this.absHref );
$a.click( $.proxy( function() { this.onClick( "tree" ); }, this ) );
if ( this.isFolder ) {
// indicator
if ( this.status === undefined || !this.isEmpty() ) {
var $indicator = $( "<span class='indicator'><img src='/h5ai/images/tree.png' /></span>" );
if ( this.status === undefined ) {
$indicator.addClass( "unknown" );
} else if ( this.treeOpen ) {
$indicator.addClass( "open" );
};
$indicator.click( $.proxy( function( event ) {
if ( $indicator.hasClass( "unknown" ) ) {
tree.fetchStatusAndContent( this.absHref, false, $.proxy( function ( status, content ) {
this.status = status;
this.content = content;
this.treeOpen = true;
pathCache.objectCache[this.absHref] = pathCache.pathToObject( this );
pathCache.storeCache();
$( "#tree" ).get( 0 ).updateScrollbar( true );
this.updateTreeHtml( function() {
$( "#tree" ).get( 0 ).updateScrollbar();
} );
}, this ) );
} else if ( $indicator.hasClass( "open" ) ) {
this.treeOpen = false;
pathCache.objectCache[this.absHref] = pathCache.pathToObject( this );
pathCache.storeCache();
$indicator.removeClass( "open" );
$( "#tree" ).get( 0 ).updateScrollbar( true );
$html.find( "> ul.content" ).slideUp( function() {
$( "#tree" ).get( 0 ).updateScrollbar();
} );
} else {
this.treeOpen = true;
pathCache.objectCache[this.absHref] = pathCache.pathToObject( this );
pathCache.storeCache();
$indicator.addClass( "open" );
$( "#tree" ).get( 0 ).updateScrollbar( true );
$html.find( "> ul.content" ).slideDown( function() {
$( "#tree" ).get( 0 ).updateScrollbar();
} );
};
}, this ) );
$html.addClass( "initiatedIndicator" );
$blank.replaceWith( $indicator );
};
// is this the domain?
if ( this.isDomain ) {
$html.addClass( "domain" );
$a.find( ".icon img" ).attr( "src", "/h5ai/icons/16x16/folder-home.png" );
};
// is this the current folder?
if ( this.isCurrentFolder ) {
$html.addClass( "current" );
$a.find( ".icon img" ).attr( "src", "/h5ai/icons/16x16/folder-open.png" );
};
// does it have subfolders?
if ( !this.isEmpty() ) {
var $ul = $( "<ul class='content' />" ).appendTo( $html );
for ( idx in this.content ) {
$( "<li />" ).append( this.content[idx].updateTreeHtml() ).appendTo( $ul );
};
if ( this.status === undefined || !this.treeOpen ) {
$ul.hide();
};
};
// reflect folder status
if ( !isNaN( this.status ) ) {
if ( this.status === 200 ) {
$a.find( ".icon img" ).attr( "src", "/h5ai/icons/16x16/folder-page.png" );
$a.append( $( "<span class='hint'><img src='/h5ai/images/page.png' /></span>" ) );
} else {
$html.addClass( "error" );
$a.append( $( "<span class='hint'>" + this.status + "</span>" ) );
};
};
};
} catch( err ) {
$( "<span class='fail'>failed</span>" ).appendTo( $html );
};
if ( this.html.$tree !== undefined ) {
this.html.$tree.replaceWith( $html );
};
this.html.$tree = $html;
return $html;
};
};

View File

@@ -1,149 +0,0 @@
var Tree = function ( pathCache, h5ai ) {
this.init = function () {
if ( h5ai.config.showTree ) {
this.updatePaths();
this.populateTree();
};
};
this.updatePath = function ( path ) {
if ( path.isFolder && !path.isParentFolder && path.status === undefined ) {
this.fetchStatus( path.absHref, function ( status ) {
if ( status !== "h5ai" ) {
path.status = status;
};
path.updateHtml();
h5ai.linkHoverStates();
} );
};
};
this.updatePaths = function () {
for ( var ref in pathCache.cache ) {
this.updatePath( pathCache.cache[ref] );
};
};
this.populateTree = function () {
this.fetchTree( document.location.pathname, function( path ) {
$( "#tree" )
.append( path.updateTreeHtml() )
.scrollpanel()
.show();
h5ai.shiftTree( false, true );
h5ai.linkHoverStates();
pathCache.storeCache();
setTimeout( function () {
$( "#tree" ).get( 0 ).updateScrollbar();
}, 1 );
} );
};
this.fetchTree = function ( pathname, callback, childPath ) {
this.fetchPath( pathname, $.proxy( function ( path ) {
path.treeOpen = true;
if ( childPath !== undefined ) {
path.content[ childPath.absHref ] = childPath;
};
var parent = pathCache.splitPathname( pathname )[0];
if ( parent === "" ) {
callback( path );
} else {
this.fetchTree( parent, callback, path );
};
}, this ) );
};
this.fetchPath = function ( pathname, callback ) {
this.fetchStatusAndContent( pathname, false, function ( status, content ) {
var path = pathCache.getPathForFolder( pathname );
path.status = status;
path.content = content;
callback( path );
} );
};
var THIS = this;
var contentTypeRegEx = /^text\/html;h5ai=/;
var pathnameStatusCache = {};
this.fetchStatusAndContent = function ( pathname, includeParent, callback ) {
this.fetchStatus( pathname, function ( status ) {
if ( status !== "h5ai" ) {
callback( status, {} );
return;
};
$.ajax( {
url: pathname,
type: "GET",
dataType: "html",
error: function ( xhr ) {
callback( xhr.status, {} ); // since it was checked before this should never happen
},
success: function ( html, status, xhr ) {
if ( !contentTypeRegEx.test( xhr.getResponseHeader( "Content-Type" ) ) ) {
callback( xhr.status, {} ); // since it was checked before this should never happen
return;
};
var content = {};
$( html ).find( "#table td" ).closest( "tr" ).each( function () {
var path = pathCache.getPathForTableRow( pathname, this );
if ( path.isFolder && ( !path.isParentFolder || includeParent ) ) {
content[path.absHref] = path;
THIS.updatePath( path );
};
} );
callback( "h5ai", content );
}
} );
} );
};
this.fetchStatus = function ( pathname, callback ) {
if ( h5ai.config.folderStatus[ pathname ] !== undefined ) {
callback( h5ai.config.folderStatus[ pathname ] );
return;
} else if ( pathnameStatusCache[ pathname ] !== undefined ) {
callback( pathnameStatusCache[ pathname ] );
return;
};
$.ajax( {
url: pathname,
type: "HEAD",
complete: function ( xhr ) {
var status = xhr.status;
if ( status === 200 && contentTypeRegEx.test( xhr.getResponseHeader( "Content-Type" ) ) ) {
status = "h5ai";
};
pathnameStatusCache[ pathname ] = status;
callback( status );
}
} );
};
};

File diff suppressed because one or more lines are too long

8
src/h5ai/js/libs.js Normal file
View File

@@ -0,0 +1,8 @@
// @include "inc/lib/jquery.min.js"
// @include "inc/lib/jquery.mousewheel.min.js"
// @include "inc/lib/jquery.fracs-core.min.js"
// @include "inc/lib/jquery.scrollpanel.js"
// @include "inc/lib/amplify.min.js"
// @include "inc/lib/date.js"

View File

@@ -1,42 +1,37 @@
( function( $ ) {
// @include "inc/jquery.json.min.js"
// @include "inc/jquery.mousewheel.min.js"
// @include "inc/jquery.scrollpanel.js"
// @include "inc/jquery.utils.js"
// @include "inc/path.js"
// @include "inc/extended.js"
// @include "inc/h5ai.js"
// @include "inc/tree.js"
(function($) {
"use strict";
var H5aiJs = {
factory: {},
init: function () {
/*******************************
* create
*******************************/
this.h5ai = new this.factory.H5ai(h5aiOptions, h5aiLangs);
this.pathCache = new this.factory.PathCache();
this.connector = new this.factory.Connector();
this.html = new this.factory.Html();
this.extended = new this.factory.Extended();
var pathCache = new PathCache();
var h5ai = new H5ai( h5aiOptions, h5aiLangs );
var extended = new Extended( pathCache, h5ai );
var tree = new Tree( pathCache, h5ai );
this.extended.init();
this.connector.init();
this.h5ai.init();
$.h5ai = {
click: $.proxy(this.h5ai.pathClick, this.h5ai)
};
}
};
/*******************************
* register public api
*******************************/
// @include "inc/H5ai.js"
// @include "inc/Path.js"
// @include "inc/PathCache.js"
// @include "inc/Connector.js"
// @include "inc/Html.js"
// @include "inc/Extended.js"
$.h5ai = {
click: $.proxy( h5ai.pathClick, h5ai )
};
$(function () {
/*******************************
* init after dom load
*******************************/
H5aiJs.init();
});
$( function() {
extended.init();
tree.init();
h5ai.init();
} );
} )( jQuery );
}(jQuery));

View File

@@ -1,37 +1,28 @@
( function( $ ) {
// @include "inc/jquery.json.min.js"
// @include "inc/jquery.mousewheel.min.js"
// @include "inc/jquery.scrollpanel.js"
// @include "inc/jquery.utils.js"
// @include "inc/h5ai.js"
(function($) {
"use strict";
var H5aiJs = {
factory: {},
init: function () {
/*******************************
* create
*******************************/
this.h5ai = new this.factory.H5ai(h5aiOptions, h5aiLangs);
var h5ai = new H5ai( h5aiOptions, h5aiLangs );
this.h5ai.init();
$("#tree").scrollpanel();
this.h5ai.shiftTree(false, true);
$.h5ai = {
click: $.proxy(this.h5ai.pathClick, this.h5ai)
};
}
};
/*******************************
* register public api
*******************************/
// @include "inc/H5ai.js"
$.h5ai = {
click: $.proxy( h5ai.pathClick, h5ai )
};
$(function () {
H5aiJs.init();
});
/*******************************
* init after dom load
*******************************/
$( function() {
h5ai.init();
$( "#tree" ).scrollpanel();
h5ai.shiftTree( false, true );
} );
} )( jQuery );
}(jQuery));

4
src/h5ai/js/modernizr.min.js vendored Normal file

File diff suppressed because one or more lines are too long

View File

@@ -1,97 +1,103 @@
/*
* h5ai %BUILD_VERSION%
* Options and localization
* Options and localization
*/
h5aiOptions = {
/*
* An array of view modes the user may choose from. Currently there
* are two possible values: "details" and "icons". The first value
* indicates the default view mode. If only one value is given the
* view mode is fixed and the selector buttons are hidden.
* The user selected view mode is also stored local in modern browsers
* so that it will be persistent.
*/
"viewmodes": [ "details", "icons" ],
/*
* The absolute link to h5ai.
* Don't change this unless you know what you are doing.
*/
"h5aiAbsHref": "/h5ai",
/*
* Default sort order. Valid values for column are "name", "date" and
* "size".
* If you are using the JavaScript version please make sure to change
* IndexOrderDefault in js.htaccess as well.
*/
"sortorder": {
"column": "name",
"ascending": true
},
/*
* An array of view modes the user may choose from. Currently there
* are two possible values: "details" and "icons". The first value
* indicates the default view mode. If only one value is given the
* view mode is fixed and the selector buttons are hidden.
* The user selected view mode is also stored local in modern browsers
* so that it will be persistent.
*/
"viewmodes": ["details", "icons"],
/*
* Show a folder tree, boolean.
* Note that this tree might have side effects as it sends HEAD requests
* to the folders, and therefore will invoke index.php scripts. Use
* folderStatus below to avoid such requests.
* It might also affect performance significantly.
*/
"showTree": true,
/*
* Default sort order. Valid values for column are "name", "date" and
* "size".
* If you are using the JavaScript version please make sure to change
* IndexOrderDefault in js.htaccess as well.
*/
"sortorder": {
"column": "name",
"ascending": true
},
/*
* Associative array of folders and their HTTP status codes to
* avoid HEAD requests to that folders. The key (folder) must start
* and end with a slash (/).
* For example:
* "/some/folder/": 200
* will always return HTTP status 200 (OK), which will be interpreted
* as a non auto indexed folder, that means a folder containing an
* appropriate default index file.
*/
"folderStatus": {
/*
* for example:
* "/some/folder/": 200
*/
},
/*
* Show a folder tree, boolean.
* Note that this tree might have side effects as it sends HEAD requests
* to the folders, and therefore will invoke index.php scripts. Use
* folderStatus below to avoid such requests.
* It might also affect performance significantly.
*/
"showTree": true,
/*
* Localization, for example "en", "de" etc. - see h5aiLangs below for
* possible values. Adjust it to your needs. If lang is not found in
* h5aiLangs it defaults to "en".
*/
"lang": null,
/*
* Slide tree bar into viewport if there is enough space, boolean.
*/
"slideTree": true,
/*
* Try to use browser language, falls back to previous specified lang.
*/
"useBrowserLang": true,
/*
* Set parent folder labels to real folder names.
*/
"setParentFolderLabels": true,
/*
* Link the hover effects between crumb, extended view and tree.
*/
"linkHoverStates": true,
/*
* Associative array of folders and their HTTP status codes to
* avoid HEAD requests to that folders. The key (folder) must start
* and end with a slash (/).
* For example:
* "/some/folder/": 200
* will always return HTTP status 200 (OK), which will be interpreted
* as a non auto indexed folder, that means a folder containing an
* appropriate default index file.
*/
"folderStatus": {},
/*
* Only used in PHP implementation.
* Date format in PHP syntax, for example: "Y-m-d H:i:s"
* http://www.php.net/manual/en/function.date.php
*/
"dateFormat": "Y-m-d H:i",
/*
* Localization, for example "en", "de" etc. - see h5aiLangs below for
* possible values. Adjust it to your needs. If lang is not found in
* h5aiLangs it defaults to "en".
*/
"lang": "en",
/*
* IMPORTANT: PHP implementation doesn't care about Apache's
* ignores, so you have to specify this here.
*
* Only used in PHP implementation.
* Files/folders that should never be listed. Specified
* by the complete filename or by a regular expression.
* http://www.php.net/manual/en/function.preg-match.php
*/
"ignore": [ "h5ai", "h5ai.header.html", "h5ai.footer.html" ],
"ignoreRE": [ "/^\\./" ]
/*
* Try to use browser language, falls back to previous specified lang.
*/
"useBrowserLang": true,
/*
* Set parent folder labels to real folder names.
*/
"setParentFolderLabels": true,
/*
* Link the hover effects between crumb, extended view and tree.
*/
"linkHoverStates": true,
/*
* Date format in detailed view, for example: "yyyy-MM-dd HH:mm:ss"
* Syntax as specified by date.js
* http://code.google.com/p/datejs/wiki/FormatSpecifiers
*/
"dateFormat": "yyyy-MM-dd HH:mm",
/*
* Requieres PHP on the server.
* Show thumbnails in icons view.
*/
"showThumbs": false,
/*
* Requieres PHP on the server.
* Enable zipped download of selected entries.
*/
"zippedDownload": false
};
@@ -101,159 +107,227 @@ h5aiOptions = {
*/
h5aiLangs = {
"en": {
"lang": "english",
"details": "details",
"icons": "icons",
"name": "Name",
"lastModified": "Last modified",
"size": "Size",
"parentDirectory": "Parent Directory",
"empty": "empty",
"folders": "folders",
"files": "files"
},
"en": {
"lang": "english",
"details": "details",
"icons": "icons",
"name": "Name",
"lastModified": "Last modified",
"size": "Size",
"parentDirectory": "Parent Directory",
"empty": "empty",
"folders": "folders",
"files": "files",
"download": "download"
},
"de": {
"lang": "deutsch",
"details": "Details",
"icons": "Icons",
"name": "Name",
"lastModified": "Geändert",
"size": "Größe",
"parentDirectory": "Übergeordnetes Verzeichnis",
"empty": "leer",
"folders": "Ordner",
"files": "Dateien"
},
"fr": {
"lang": "français",
"details": "détails",
"icons": "icônes",
"name": "Nom",
"lastModified": "Dernière modification",
"size": "Taille",
"parentDirectory": "Dossier parent",
"empty": "vide",
"folders": "Répertoires",
"files": "Fichiers"
},
"bg": {
"lang": "български",
"details": "детайли",
"icons": "икони",
"name": "Име",
"lastModified": "Последна промяна",
"size": "Размер",
"parentDirectory": "Предходна директория",
"empty": "празно",
"folders": "папки",
"files": "файлове",
"download": "download"
},
"nl": {
"lang": "nederlands",
"details": "details",
"icons": "iconen",
"name": "Naam",
"lastModified": "Laatste wijziging",
"size": "Grootte",
"parentDirectory": "Bovenliggende map",
"empty": "lege",
"folders": "[?folders?]",
"files": "[?files?]"
},
"cs": {
"lang": "čeština",
"details": "podrobnosti",
"icons": "ikony",
"name": "Název",
"lastModified": "Upraveno",
"size": "Velikost",
"parentDirectory": "Nadřazený adresář",
"empty": "prázdný",
"folders": "složek",
"files": "souborů",
"download": "download"
},
"sv": {
"lang": "svenska",
"details": "detaljerad",
"icons": "ikoner",
"name": "Filnamn",
"lastModified": "Senast ändrad",
"size": "Filstorlek",
"parentDirectory": "Till överordnad mapp",
"empty": "tom",
"folders": "[?folders?]",
"files": "[?files?]"
},
"de": {
"lang": "deutsch",
"details": "Details",
"icons": "Icons",
"name": "Name",
"lastModified": "Geändert",
"size": "Größe",
"parentDirectory": "Übergeordnetes Verzeichnis",
"empty": "leer",
"folders": "Ordner",
"files": "Dateien",
"download": "Download"
},
"cs": {
"lang": "čeština",
"details": "podrobnosti",
"icons": "ikony",
"name": "Název",
"lastModified": "Upraveno",
"size": "Velikost",
"parentDirectory": "Nadřazený adresář",
"empty": "prázdný",
"folders": "složek",
"files": "souborů"
},
"es": {
"lang": "español",
"details": "Detalles",
"icons": "Íconos",
"name": "Nombre",
"lastModified": "Última modificación",
"size": "Tamaño",
"parentDirectory": "Directorio superior",
"empty": "vacío",
"folders": "folders",
"files": "files",
"download": "download"
},
"sk": {
"lang": "slovenčina",
"details": "podrobnosti",
"icons": "ikony",
"name": "Názov",
"lastModified": "Upravené",
"size": "Velkosť",
"parentDirectory": "Nadriadený priečinok",
"empty": "prázdny",
"folders": "priečinkov",
"files": "súborov"
},
"fr": {
"lang": "français",
"details": "détails",
"icons": "icônes",
"name": "Nom",
"lastModified": "Dernière modification",
"size": "Taille",
"parentDirectory": "Dossier parent",
"empty": "vide",
"folders": "Répertoires",
"files": "Fichiers",
"download": "télécharger"
},
"es": {
"lang": "español",
"details": "Detalles",
"icons": "Íconos",
"name": "Nombre",
"lastModified": "Última modificación",
"size": "Tamaño",
"parentDirectory": "Directorio superior",
"empty": "vacío",
"folders": "[?folders?]",
"files": "[?files?]"
},
"it": {
"lang": "italiano",
"details": "dettagli",
"icons": "icone",
"name": "Nome",
"lastModified": "Ultima modifica",
"size": "Dimensione",
"parentDirectory": "Cartella Superiore",
"empty": "vuota",
"folders": "cartelle",
"files": "file",
"download": "download"
},
"tr": {
"lang": "türkçe",
"details": "detaylar",
"icons": "ikonlar",
"name": "İsim",
"lastModified": "Son Düzenleme",
"size": "Boyut",
"parentDirectory": "Üst Dizin",
"empty": "boş",
"folders": "[?folders?]",
"files": "[?files?]"
},
"lv": {
"lang": "latviešu",
"details": "detaļas",
"icons": "ikonas",
"name": "Nosaukums",
"lastModified": "Pēdējoreiz modificēts",
"size": "Izmērs",
"parentDirectory": "Vecākdirektorijs",
"empty": "tukšs",
"folders": "mapes",
"files": "faili",
"download": "lejupielādēt"
},
"pt": {
"lang": "português",
"details": "detalhes",
"icons": "ícones",
"name": "Nome",
"lastModified": "Última modificação",
"size": "Tamanho",
"parentDirectory": "Diretório superior",
"empty": "vazio",
"folders": "pastas",
"files": "arquivos"
},
"nl": {
"lang": "nederlands",
"details": "details",
"icons": "iconen",
"name": "Naam",
"lastModified": "Laatste wijziging",
"size": "Grootte",
"parentDirectory": "Bovenliggende map",
"empty": "lege",
"folders": "folders",
"files": "files",
"download": "download"
},
"bg": {
"lang": "български",
"details": "детайли",
"icons": "икони",
"name": "Име",
"lastModified": "Последна промяна",
"size": "Размер",
"parentDirectory": "Предходна директория",
"empty": "празно",
"folders": "папки",
"files": "файлове"
},
"pl": {
"lang": "polski",
"details": "szczegóły",
"icons": "ikony",
"name": "Nazwa",
"lastModified": "Ostatnia modyfikacja",
"size": "Rozmiar",
"parentDirectory": "Katalog nadrzędny",
"empty": "pusty",
"folders": "foldery",
"files": "pliki",
"download": "download"
},
"lv": {
"lang": "latviešu",
"details": "detaļas",
"icons": "ikonas",
"name": "Nosaukums",
"lastModified": "Pēdējoreiz modificēts",
"size": "Izmērs",
"parentDirectory": "Vecākdirektorijs",
"empty": "tukšs",
"folders": "mapes",
"files": "faili"
}
"pt": {
"lang": "português",
"details": "detalhes",
"icons": "ícones",
"name": "Nome",
"lastModified": "Última modificação",
"size": "Tamanho",
"parentDirectory": "Diretório superior",
"empty": "vazio",
"folders": "pastas",
"files": "arquivos",
"download": "download"
},
"ru": {
"lang": "русский",
"details": "детали",
"icons": "иконки",
"name": "Имя",
"lastModified": "Последние изменения",
"size": "Размер",
"parentDirectory": "Главная директория",
"empty": "пусто",
"folders": "папки",
"files": "файлы",
"download": "download"
},
"sk": {
"lang": "slovenčina",
"details": "podrobnosti",
"icons": "ikony",
"name": "Názov",
"lastModified": "Upravené",
"size": "Velkosť",
"parentDirectory": "Nadriadený priečinok",
"empty": "prázdny",
"folders": "priečinkov",
"files": "súborov",
"download": "download"
},
"sv": {
"lang": "svenska",
"details": "detaljerad",
"icons": "ikoner",
"name": "Filnamn",
"lastModified": "Senast ändrad",
"size": "Filstorlek",
"parentDirectory": "Till överordnad mapp",
"empty": "tom",
"folders": "folders",
"files": "files",
"download": "download"
},
"tr": {
"lang": "türkçe",
"details": "detaylar",
"icons": "ikonlar",
"name": "İsim",
"lastModified": "Son Düzenleme",
"size": "Boyut",
"parentDirectory": "Üst Dizin",
"empty": "boş",
"folders": "klasörler",
"files": "dosyalar",
"download": "indir"
},
"zh-cn": {
"lang": "简体中文",
"details": "详情",
"icons": "图标",
"name": "文件名",
"lastModified": "上次修改",
"size": "大小",
"parentDirectory": "上层文件夹",
"empty": "空文件夹",
"folders": "文件夹",
"files": "文件",
"download": "download"
}
};

126
src/h5ai/php/api.php Normal file
View File

@@ -0,0 +1,126 @@
<?php
function fail($code, $msg, $cond = true) {
if ($cond) {
echo "$code: $msg";
exit;
}
}
function checkKeys($keys) {
$values = array();
foreach ($keys as $key) {
fail(1, "parameter '$key' is missing", !array_key_exists($key, $_REQUEST));
$values[] = $_REQUEST[$key];
}
return $values;
}
list($action) = checkKeys(array("action"));
require_once "config.php";
require_once "inc/H5ai.php";
$h5ai = new H5ai();
$options = $h5ai->getOptions();
if ($action === "httpcodes") {
list($hrefs) = checkKeys(array("hrefs"));
function getHttpCodes($h5ai, $hrefs) {
$codes = array();
foreach ($hrefs as $href) {
$href = trim($href);
if (strlen($href) > 0) {
$codes[$href] = $h5ai->getHttpCode($href);
}
}
return $codes;
}
$hrefs = preg_split("/;/", $hrefs);
$codes = getHttpCodes($h5ai, $hrefs);
echo count($codes) === 0 ? "{}" : json_encode($codes);
}
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";
$srcAbsPath = $h5ai->getDocRoot() . rawurldecode($srcAbsHref);
if (!Thumbnail::isUsable()) {
Image::showImage($srcAbsPath);
exit;
}
$thumbnail = new Thumbnail($h5ai, $srcAbsHref, $mode, $width, $height);
$thumbnail->create(1);
if (file_exists($thumbnail->getPath())) {
Image::showImage($thumbnail->getPath());
} else {
$image = new Image();
$image->setSource($srcAbsPath);
$image->thumb($mode, $width, $height);
$image->showDest();
}
}
else if ($action === "tree") {
list($href) = checkKeys(array("href"));
require_once "inc/Tree.php";
$absHref = trim($href);
$absPath = $h5ai->getAbsPath($absHref);
$tree = new TreeEntry($h5ai, $absPath, $absHref);
$tree->loadContent();
echo $tree->contentToHtml();
}
else if ($action === "zip") {
fail(0, "zipped download is disabled", !$options["zippedDownload"]);
list($hrefs) = checkKeys(array("hrefs"));
require_once "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");
}
header("Content-Disposition: attachment; filename=\"h5ai-selection.zip\"");
header("Content-Type: application/force-download");
header("Content-Length: " . filesize($zipFile));
header("Connection: close");
readfile($zipFile);
}
else {
fail(1, "unsupported 'action' specified");
}
?>

View File

@@ -1,93 +0,0 @@
<?php
##############################################
# taken from here:
# http://www.jongales.com/blog/2009/02/18/simple-file-based-php-cache-class/
# with minor modifications
##############################################
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 ) ) {
return false;
}
$cache_path = $this->_name( $key );
if ( !@file_exists( $cache_path ) ) {
return false;
}
if ( filemtime( $cache_path ) < ( time() - $expiration ) ) {
$this->clear( $key );
return false;
}
if ( !$fp = @fopen( $cache_path, "rb" ) ) {
return false;
}
flock( $fp, LOCK_SH );
$cache = "";
if ( filesize( $cache_path ) > 0 ) {
$cache = unserialize( fread( $fp, filesize( $cache_path ) ) );
} else {
$cache = null;
}
flock( $fp, LOCK_UN );
fclose( $fp );
return $cache;
}
public function set( $key, $data ) {
if ( !is_dir( $this->dir ) || !is_writable( $this->dir ) ) {
return false;
}
$cache_path = $this->_name( $key );
if ( ! $fp = fopen( $cache_path, "wb" ) ) {
return false;
}
if ( flock( $fp, LOCK_EX ) ) {
fwrite( $fp, serialize( $data ) );
flock( $fp, LOCK_UN );
} else {
return false;
}
fclose( $fp );
@chmod( $cache_path, 0777 );
return true;
}
public function clear( $key ) {
$cache_path = $this->_name( $key );
if ( file_exists( $cache_path ) ) {
unlink( $cache_path );
return true;
}
return false;
}
}
?>

15
src/h5ai/php/config.php Normal file
View File

@@ -0,0 +1,15 @@
<?php
global $H5AI_CONFIG;
$H5AI_CONFIG = array();
$H5AI_CONFIG["DOCUMENT_ROOT"] = getenv("DOCUMENT_ROOT");
$H5AI_CONFIG["H5AI_ROOT"] = getenv("DOCUMENT_ROOT") . "/h5ai";
# Files/folders that should never 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", "h5ai.header.html", "h5ai.footer.html");
$H5AI_CONFIG["IGNORE_PATTERNS"] = array("/^\\./");
?>

View File

@@ -1,52 +0,0 @@
<?php
class Crumb {
private $h5ai, $parts;
public function __construct( $h5ai ) {
$this->h5ai = $h5ai;
$this->parts = array();
$href = $h5ai->getAbsHref();
while ( $href !== "/" && $href !== "//" ) {
$this->parts[] = $href;
$href = dirname( $href ) . "/";
}
$this->parts[] = "/";
$this->parts = array_reverse( $this->parts );
}
public function toHtml() {
$html = "";
$idx = 0;
foreach( $this->parts as $href ) {
$idx++;
$classes = "crumb folder" . ( $idx === 1 ? " domain" : "" ) . ( $idx === count( $this->parts ) ? " current" : "" );
$image = "/h5ai/images/" . ( $idx === 1 ? "home.png" : "crumb.png" );
$label = $this->h5ai->getLabel( $href );
$hint = "";
$code = $this->h5ai->getHttpCode( $href );
$classes .= " checkedHttpCode";
if ( $code !== "h5ai" ) {
if ( $code === 200 ) {
$hint = "<img class='hint' src='/h5ai/images/page.png' alt='page' />";
} else {
$hint = "<span class='hint'>(" . $code . ")</span>";
}
}
$html .= "<li class='$classes'>\n";
$html .= "\t<a href='$href'>\n";
$html .= "\t\t<img src='$image' alt='>' />" . $label . $hint . "\n";
$html .= "\t</a>\n";
$html .= "</li>\n";
}
return $html;
}
}
?>

View File

@@ -1,27 +0,0 @@
<?php
class Customize {
private $h5ai;
public function __construct( $h5ai ) {
$this->h5ai = $h5ai;
}
public function getHeader() {
return $this->getContent( $this->h5ai->getAbsPath() . "/" . "h5ai.header.html", "header" );
}
public function getFooter() {
return $this->getContent( $this->h5ai->getAbsPath() . "/" . "h5ai.footer.html", "footer" );
}
private function getContent( $file, $tag ) {
return file_exists( $file ) ? ( "<" . $tag . ">" . file_get_contents( $file ) . "</" . $tag . ">" ) : "";
}
}
?>

View File

@@ -1,205 +0,0 @@
<?php
class Entry {
private $h5ai, $label, $absPath, $absHref, $date, $isFolder, $type, $size;
public function __construct( $h5ai, $absPath, $absHref, $type = null, $label = null ) {
$this->h5ai = $h5ai;
$this->label = $label !== null ? $label : $this->h5ai->getLabel( $absHref );
$this->absPath = $this->h5ai->normalizePath( $absPath, false );
$this->isFolder = is_dir( $this->absPath );
$this->absHref = $this->h5ai->normalizePath( $absHref, $this->isFolder );
$this->date = filemtime( $this->absPath );
if ( $this->isFolder ) {
$this->type = $type !== null ? $type : "folder";
$this->size = "";
} else {
$this->type = $type !== null ? $type : $this->h5ai->getType( $this->absPath );
$this->size = filesize( $this->absPath );
}
}
public function isFolder() {
return $this->isFolder;
}
function compare( $that, $sortOrder ) {
if ( $this->isFolder && !$that->isFolder ) {
return -1;
}
if ( !$this->isFolder && $that->isFolder ) {
return 1;
}
$res = 0;
if ( $sortOrder[ "column" ] === "name" ) {
$res = strcasecmp( $this->absPath, $that->absPath );
} else if ( $sortOrder[ "column" ] === "date" ) {
$res = $this->date - $that->date;
} else if ( $sortOrder[ "column" ] === "size" ) {
$res = $this->size - $that->size;
}
if ( ! $sortOrder[ "ascending" ] ) {
$res = -$res;
}
return $res;
}
public function toHtml( $dateFormat ) {
$classes = "entry " . $this->type;
$img = $this->type;
$hint = "";
$dateLabel = date( $dateFormat, $this->date );
if ( $this->isFolder && $this->type !== "folder-parent" ) {
$code = $this->h5ai->getHttpCode( $this->absHref );
$classes .= " checkedHttpCode";
if ( $code !== "h5ai" ) {
if ( $code === 200 ) {
$img = "folder-page";
} else {
$classes .= " error";
$hint = "<span class='hint'> " . $code . " </span>";
}
}
}
$html = "\t<li class='" . $classes . "'>\n";
$html .= "\t\t<a href='" . $this->absHref . "'>\n";
$html .= "\t\t\t<span class='icon small'><img src='/h5ai/icons/16x16/" . $img . ".png' alt='" . $img . "' /></span>\n";
$html .= "\t\t\t<span class='icon big'><img src='/h5ai/icons/48x48/" . $img . ".png' alt='" . $img . "' /></span>\n";
$html .= "\t\t\t<span class='label'>" . $this->label . $hint . "</span>\n";
$html .= "\t\t\t<span class='date'>" . $dateLabel . "</span>\n";
$html .= "\t\t\t<span class='size'>" . $this->formatSize( $this->size ) . "</span>\n";
$html .= "\t\t</a>\n";
$html .= "\t</li>\n";
return $html;
}
private function formatSize( $size ) {
$units = array( 'B', 'KB', 'MB', 'GB', 'TB' );
for ( $i = 0; $size >= 1024 && $i < 4; $i++ ) {
$size /= 1024;
}
return round( $size, 0 ) . " " . $units[$i];
}
}
class Extended {
private $h5ai, $parent, $content;
public function __construct( $h5ai ) {
$this->h5ai = $h5ai;
$this->parent = null;
$this->content = array();
$this->loadContent();
}
private function loadContent() {
if ( $this->h5ai->getAbsHref() !== "/" ) {
$options = $this->h5ai->getOptions();
$parentPath = dirname( $this->h5ai->getAbsPath() );
$parentHref = dirname( $this->h5ai->getAbsHref() );
$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 );
}
$this->content = array();
$files = $this->h5ai->readDir( $this->h5ai->getAbsPath() );
foreach ( $files as $file ) {
$absPath = $this->h5ai->getAbsPath() . "/" . $file;
$absHref = $this->h5ai->getAbsHref() . rawurlencode( $file );
$this->content[$absPath] = new Entry( $this->h5ai, $absPath, $absHref );
}
$this->sort();
}
public function cmpEntries( $p1, $p2 ) {
return $p1->compare( $p2, $this->h5ai->getSortOrder() );
}
public function sort() {
uasort( $this->content, array( $this, "cmpEntries" ) );
}
public function getFolderCount() {
$count = 0;
foreach( $this->content as $entry ) {
if ( $entry->isFolder() ) {
$count++;
}
}
return $count;
}
public function getFileCount() {
$count = 0;
foreach( $this->content as $entry ) {
if ( !$entry->isFolder() ) {
$count++;
}
}
return $count;
}
public function toHtml() {
$html = "<section id='extended' class='" . $this->h5ai->getView() . "-view clearfix'>\n";
$html .= "<ul>\n";
$html .= $this->generateHeaders();
if ( $this->parent !== null ) {
$html .= $this->parent->toHtml( $this->h5ai->getDateFormat() );
}
foreach( $this->content as $entry ) {
$html .= $entry->toHtml( $this->h5ai->getDateFormat() );
}
$html .= "</ul>\n";
if ( count( $this->content ) === 0 ) {
$html .= "<div class='empty l10n-empty'>empty</div>";
}
$html .="</section>";
return $html;
}
public function generateHeaders() {
$asc = "<img src='/h5ai/images/ascending.png' class='sort' alt='ascending' />";
$desc = "<img src='/h5ai/images/descending.png' class='sort' alt='descending' />";
$so = $this->h5ai->getSortOrder();
$order = $so["ascending"] ? $asc : $desc;
$nameHref = "?col=name" . ( $so["column"] === "name" && $so["ascending"] ? "&asc=false" : "&asc=true" );
$dateHref = "?col=date" . ( $so["column"] === "date" && $so["ascending"] ? "&asc=false" : "&asc=true" );
$sizeHref = "?col=size" . ( $so["column"] === "size" && $so["ascending"] ? "&asc=false" : "&asc=true" );
$nameSort = $so["column"] === "name" ? $order : "";
$dateSort = $so["column"] === "date" ? $order : "";
$sizeSort = $so["column"] === "size" ? $order : "";
$html = "\t<li class='header'>\n";
$html .= "\t\t<a class='icon'></a>\n";
$html .= "\t\t<a class='label' href='$nameHref'><span class='l10n-name'>Name</span>$nameSort</a>\n";
$html .= "\t\t<a class='date' href='$dateHref'>$dateSort<span class='l10n-lastModified'>Last modified</span></a>\n";
$html .= "\t\t<a class='size' href='$sizeHref'>$sizeSort<span class='l10n-size'>Size</span></a>\n";
$html .= "\t</li>\n";
return $html;
}
}
?>

View File

@@ -1,265 +0,0 @@
<?php
require_once "cache.php";
class H5ai {
private static $SORT_ORDER = array( "column" => "name", "ascending" => true );
private static $VIEWMODES = array( "details", "icons" );
private $docRoot, $domain, $options, $types, $cache, $absHref, $absPath, $ignore, $ignoreRE, $sortOrder, $dateFormat, $view;
public function __construct() {
$this->docRoot = getenv( "DOCUMENT_ROOT" );
$this->domain = getenv( "HTTP_HOST" );
$this->options = $this->loadOptions( $this->docRoot . "/h5ai/options.js" );
$this->types = $this->loadTypes( $this->docRoot . "/h5ai/types.txt" );
$this->cache = new Cache( $this->docRoot . "/h5ai/cache" );
$this->absHref = $this->normalizePath( preg_replace( '/\\?.*/', '', getenv( "REQUEST_URI" ) ), true );
$this->absPath = $this->normalizePath( $this->docRoot . rawurldecode( $this->absHref ), false );
$this->ignore = $this->options["options"]["ignore"];
$this->ignoreRE = $this->options["options"]["ignoreRE"];
$defaultSortOrder = $this->options["options"]["sortorder"];
$this->sortOrder = array(
"column" => array_key_exists( "col", $_REQUEST ) ? $_REQUEST["col"] : $defaultSortOrder["column"],
"ascending" => array_key_exists( "asc", $_REQUEST ) ? $_REQUEST["asc"] !== "false" : $defaultSortOrder["ascending"]
);
$this->dateFormat = $this->options["options"]["dateFormat"];
$this->view = array_key_exists( "view", $_REQUEST ) ? $_REQUEST["view"] : $this->options["options"]["viewmodes"][0];
if ( !in_array( $this->view, H5ai::$VIEWMODES ) ) {
$this->view = H5ai::$VIEWMODES[0];
}
}
private function loadOptions( $file ) {
$str = file_exists( $file ) ? file_get_contents( $file ) : "";
$str = preg_replace( "/\/\*.*?\*\//s", "", $str );
$optstr = preg_replace( "/^.*h5aiOptions\s*=\s*/s", "", $str );
$optstr = preg_replace( "/;.*/s", "", $optstr );
$options = json_decode( $optstr, true );
$langstr = preg_replace( "/^.*h5aiLangs\s*=\s*/s", "", $str );
$langstr = preg_replace( "/;.*/s", "", $langstr );
$langs = json_decode( $langstr, true );
return array( "options" => $options, "langs" => $langs );
}
private function loadTypes( $file ) {
$lines = file( $file );
$types = array();
foreach( $lines as $line ) {
if ( substr( $line, 0, 1 ) === '#' ) {
continue;
}
$types[] = preg_split( "/\s+/", $line );
}
return $types;
}
public function getDocRoot() {
return $this->docRoot;
}
public function getDomain() {
return $this->domain;
}
public function getView() {
return $this->view;
}
public function getOptions() {
return $this->options["options"] ;
}
public function getLangs() {
return $this->options["langs"];
}
public function getAbsHref( $absPath = null, $endWithSlash = true ) {
if ( $absPath === null ) {
return $this->absHref;
}
return $this->normalizePath( rawurlencode( preg_replace( "!^" . $this->docRoot . "!", "", $absPath ) ), $endWithSlash );
}
public function getAbsPath( $absHref = null ) {
if ( $absHref === null ) {
return $this->absPath;
}
return $this->normalizePath( $this->docRoot . rawurldecode( $absHref ), false );
}
public function getSortOrder() {
return $this->sortOrder;
}
public function getDateFormat() {
return $this->dateFormat;
}
public function getTitle() {
$title = $this->domain . rawurldecode( $this->absHref );
$title = preg_replace( "/\/$/", "", $title );
$title = preg_replace( "/\//", " > ", $title );
if ( $this->absHref !== "/" ) {
$title = basename( $this->absPath ) . " - " . $title;
}
return $title;
}
public function getType( $absPath ) {
foreach( $this->types as $type ) {
foreach( array_slice( $type, 1 ) as $pattern ) {
if ( $this->endsWith( $absPath, $pattern ) ) {
return $type[0];
}
}
}
return "unknown";
}
public function ignoreThisFile( $file ) {
# always ignore
if ( $file === "." || $file === ".." || $this->startsWith( $file, '.ht' ) ) {
return true;
}
if ( in_array( $file, $this->ignore ) ) {
return true;
}
foreach ( $this->ignoreRE as $re ) {
if ( preg_match( $re, $file ) ) {
return true;
}
}
return false;
}
public function readDir( $path ) {
$content = array();
if ( is_dir( $path ) ) {
if ( $dir = opendir( $path ) ) {
while ( ( $file = readdir( $dir ) ) !== false ) {
if ( ! $this->ignoreThisFile( $file ) ) {
$content[] = $file;
}
}
closedir( $dir );
}
}
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 substr( $sequence, 0, strlen( $start ) ) === $start;
}
public function endsWith( $sequence, $end ) {
return substr( $sequence, -strlen( $end ) ) === $end;
}
public function getHttpCode( $absHref ) {
return $this->cachedHttpCode( $absHref );
#return $this->fetchHttpCode( $absHref );
#return $this->guessHttpCode( $absHref );
}
public function cachedHttpCode( $absHref ) {
$cached = $this->cache->get( $absHref );
if ( $cached === false ) {
$folderStatus = $this->options["options"]["folderStatus"];
if ( array_key_exists( $absHref, $folderStatus ) ) {
$code = $folderStatus[$absHref];
} else {
$code = $this->fetchHttpCode( $absHref );
}
$cached = array( "href" => $absHref, "code" => $code );
$this->cache->set( $absHref, $cached );
}
return $cached["code"];
}
public function fetchHttpCode( $absHref ) {
$contentType = "Content-Type:";
$h5aiContentType = "Content-Type: text/html;h5ai=";
$host = getenv( "HTTP_HOST" );
$port = getenv( "SERVER_PORT" );
$msg = "HEAD $absHref HTTP/1.1\r\nHost: $host\r\nConnection: Close\r\n\r\n";
$errno = "";
$errstr = "";
$socket = fsockopen( $host, $port, $errno, $errstr, 30 );
if( $socket === 0 ) {
return null;
}
fwrite( $socket, $msg );
$content = fgets( $socket );
$code = intval( trim( substr( $content, 9, 4 ) ) );
if ( $code === 200 ) {
while ( ! $this->startsWith( $content, $contentType ) ) {
$content = fgets( $socket );
}
if ( $this->startsWith( $content, $h5aiContentType ) ) {
$code = "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

@@ -1,23 +0,0 @@
<?php
require_once "h5ai.php";
function getHttpCodes( $h5ai, $hrefs ) {
$codes = array();
foreach ( $hrefs as $href ) {
$href = trim( $href );
if ( strlen( $href ) > 0 ) {
$codes[$href] = $h5ai->getHttpCode( $href );
}
}
return $codes;
}
$h5ai = new H5ai();
$hrefs = preg_split( "/;/", array_key_exists( "hrefs", $_REQUEST ) ? $_REQUEST[ "hrefs" ] : "" );
$codes = getHttpCodes( $h5ai, $hrefs );
echo count( $codes ) === 0 ? "{}" : json_encode( $codes );
?>

View File

@@ -0,0 +1,93 @@
<?php
##############################################
# taken from here:
# http://www.jongales.com/blog/2009/02/18/simple-file-based-php-cache-class/
# with minor modifications
##############################################
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)) {
return false;
}
$cache_path = $this->_name($key);
if (!@file_exists($cache_path)) {
return false;
}
if (filemtime($cache_path) < (time() - $expiration)) {
$this->clear($key);
return false;
}
if (!$fp = @fopen($cache_path, "rb")) {
return false;
}
flock($fp, LOCK_SH);
$cache = "";
if (filesize($cache_path) > 0) {
$cache = unserialize(fread($fp, filesize($cache_path)));
} else {
$cache = null;
}
flock($fp, LOCK_UN);
fclose($fp);
return $cache;
}
public function set($key, $data) {
if (!is_dir($this->dir) || !is_writable($this->dir)) {
return false;
}
$cache_path = $this->_name($key);
if (! $fp = fopen($cache_path, "wb")) {
return false;
}
if (flock($fp, LOCK_EX)) {
fwrite($fp, serialize($data));
flock($fp, LOCK_UN);
} else {
return false;
}
fclose($fp);
@chmod($cache_path, 0777);
return true;
}
public function clear($key) {
$cache_path = $this->_name($key);
if (file_exists($cache_path)) {
unlink($cache_path);
return true;
}
return false;
}
}
?>

View File

@@ -0,0 +1,52 @@
<?php
class Crumb {
private $h5ai, $parts;
public function __construct($h5ai) {
$this->h5ai = $h5ai;
$this->parts = array();
$href = $h5ai->getAbsHref();
while ($href !== "/" && $href !== "//") {
$this->parts[] = $href;
$href = dirname($href) . "/";
}
$this->parts[] = "/";
$this->parts = array_reverse($this->parts);
}
public function toHtml() {
$html = "";
$idx = 0;
foreach($this->parts as $href) {
$idx++;
$classes = "crumb folder" . ($idx === 1 ? " domain" : "") . ($idx === count($this->parts) ? " current" : "");
$image = $this->h5ai->image($idx === 1 ? "home" : "crumb");
$label = $this->h5ai->getLabel($href);
$hint = "";
$code = $this->h5ai->getHttpCode($href);
$classes .= " checkedHttpCode";
if ($code !== "h5ai") {
if ($code === 200) {
$hint = "<img class='hint' src='" . $this->h5ai->image("page") . "' alt='page' />";
} else {
$hint = "<span class='hint'>(" . $code . ")</span>";
}
}
$html .= "<li class='$classes'>\n";
$html .= "\t<a href='$href'>\n";
$html .= "\t\t<img src='$image' alt='>' />" . $label . $hint . "\n";
$html .= "\t</a>\n";
$html .= "</li>\n";
}
return $html;
}
}
?>

View File

@@ -0,0 +1,27 @@
<?php
class Customize {
private $h5ai;
public function __construct($h5ai) {
$this->h5ai = $h5ai;
}
public function getHeader() {
return $this->getContent($this->h5ai->getAbsPath() . "/h5ai.header.html", "header");
}
public function getFooter() {
return $this->getContent($this->h5ai->getAbsPath() . "/h5ai.footer.html", "footer");
}
private function getContent($file, $tag) {
return file_exists($file) ? ("<" . $tag . ">" . file_get_contents($file) . "</" . $tag . ">") : "";
}
}
?>

View File

@@ -0,0 +1,222 @@
<?php
require_once "Thumbnail.php";
class Entry {
private $h5ai, $label, $absPath, $absHref, $date, $isFolder, $type, $size, $thumbTypes;
public function __construct($h5ai, $absPath, $absHref, $type = null, $label = null) {
$this->h5ai = $h5ai;
$this->label = $label !== null ? $label : $this->h5ai->getLabel($absHref);
$this->absPath = $this->h5ai->normalizePath($absPath, false);
$this->isFolder = is_dir($this->absPath);
$this->absHref = $this->h5ai->normalizePath($absHref, $this->isFolder);
$this->date = filemtime($this->absPath);
if ($this->isFolder) {
$this->type = $type !== null ? $type : "folder";
$this->size = "";
} else {
$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;
}
function compare($that, $sortOrder) {
if ($this->isFolder && !$that->isFolder) {
return -1;
}
if (!$this->isFolder && $that->isFolder) {
return 1;
}
$res = 0;
if ($sortOrder[ "column" ] === "name") {
$res = strcasecmp($this->absPath, $that->absPath);
} else if ($sortOrder[ "column" ] === "date") {
$res = $this->date - $that->date;
} else if ($sortOrder[ "column" ] === "size") {
$res = $this->size - $that->size;
}
if (! $sortOrder[ "ascending" ]) {
$res = -$res;
}
return $res;
}
public function toHtml($dateFormat) {
$classes = "entry " . $this->type;
$img = $this->type;
$smallImg = $this->h5ai->icon($this->type);
$bigImg = $this->h5ai->icon($this->type, true);
$hint = "";
if ($this->isFolder && $this->type !== "folder-parent") {
$code = $this->h5ai->getHttpCode($this->absHref);
$classes .= " checkedHttpCode";
if ($code !== "h5ai") {
if ($code === 200) {
$img = "folder-page";
$smallImg = $this->h5ai->icon("folder-page");
$bigImg = $this->h5ai->icon("folder-page", true);
} else {
$classes .= " error";
$hint = "<span class='hint'> " . $code . " </span>";
}
}
}
if ($this->h5ai->showThumbs() && in_array($this->type, $this->thumbTypes)) {
$classes .= " thumb";
$thumbnail = new Thumbnail($this->h5ai, $this->absHref, "square", 16, 16);
$thumbnail->create();
$smallImg = file_exists($thumbnail->getPath()) ? $thumbnail->getHref() : $thumbnail->getLiveHref();
$thumbnail = new Thumbnail($this->h5ai,$this->absHref, "rational", 96, 46);
$thumbnail->create();
$bigImg = file_exists($thumbnail->getPath()) ? $thumbnail->getHref() : $thumbnail->getLiveHref();
}
$html = "\t<li class='" . $classes . "'>\n";
$html .= "\t\t<a href='" . $this->absHref . "'>\n";
$html .= "\t\t\t<span class='icon small'><img src='" . $smallImg . "' alt='" . $img . "' /></span>\n";
$html .= "\t\t\t<span class='icon big'><img src='" . $bigImg . "' alt='" . $img . "' /></span>\n";
$html .= "\t\t\t<span class='label'>" . $this->label . $hint . "</span>\n";
$html .= "\t\t\t<span class='date' data-time='" . $this->date . "000'></span>\n";
$html .= "\t\t\t<span class='size'>" . $this->formatSize($this->size) . "</span>\n";
$html .= "\t\t</a>\n";
$html .= "\t</li>\n";
return $html;
}
private function formatSize($size) {
$units = array('B', 'KB', 'MB', 'GB', 'TB');
for ($i = 0; $size >= 1024 && $i < 4; $i++) {
$size /= 1024;
}
return round($size, 0) . " " . $units[$i];
}
}
class Extended {
private $h5ai, $parent, $content;
public function __construct($h5ai) {
$this->h5ai = $h5ai;
$this->parent = null;
$this->content = array();
$this->loadContent();
}
private function loadContent() {
if ($this->h5ai->getAbsHref() !== "/") {
$options = $this->h5ai->getOptions();
$parentPath = dirname($this->h5ai->getAbsPath());
$parentHref = dirname($this->h5ai->getAbsHref());
$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);
}
$this->content = array();
$files = $this->h5ai->readDir($this->h5ai->getAbsPath());
foreach ($files as $file) {
$absPath = $this->h5ai->getAbsPath() . "/" . $file;
$absHref = $this->h5ai->getAbsHref() . rawurlencode($file);
$this->content[$absPath] = new Entry($this->h5ai, $absPath, $absHref);
}
$this->sort();
}
public function cmpEntries($p1, $p2) {
return $p1->compare($p2, $this->h5ai->getSortOrder());
}
public function sort() {
uasort($this->content, array($this, "cmpEntries"));
}
public function getFolderCount() {
$count = 0;
foreach($this->content as $entry) {
if ($entry->isFolder()) {
$count++;
}
}
return $count;
}
public function getFileCount() {
$count = 0;
foreach($this->content as $entry) {
if (!$entry->isFolder()) {
$count++;
}
}
return $count;
}
public function toHtml() {
$html = "<section id='extended' class='" . $this->h5ai->getView() . "-view clearfix'>\n";
$html .= "<ul>\n";
$html .= $this->generateHeaders();
if ($this->parent !== null) {
$html .= $this->parent->toHtml($this->h5ai->getDateFormat());
}
foreach($this->content as $entry) {
$html .= $entry->toHtml($this->h5ai->getDateFormat());
}
$html .= "</ul>\n";
if (count($this->content) === 0) {
$html .= "<div class='empty l10n-empty'>empty</div>";
}
$html .="</section>";
return $html;
}
public function generateHeaders() {
$asc = "<img src='" . $this->h5ai->image("ascending") . "' class='sort' alt='ascending' />";
$desc = "<img src='" . $this->h5ai->image("descending") . "' class='sort' alt='descending' />";
$so = $this->h5ai->getSortOrder();
$order = $so["ascending"] ? $asc : $desc;
$nameHref = "?col=name" . ($so["column"] === "name" && $so["ascending"] ? "&asc=false" : "&asc=true");
$dateHref = "?col=date" . ($so["column"] === "date" && $so["ascending"] ? "&asc=false" : "&asc=true");
$sizeHref = "?col=size" . ($so["column"] === "size" && $so["ascending"] ? "&asc=false" : "&asc=true");
$nameSort = $so["column"] === "name" ? $order : "";
$dateSort = $so["column"] === "date" ? $order : "";
$sizeSort = $so["column"] === "size" ? $order : "";
$html = "\t<li class='header'>\n";
$html .= "\t\t<a class='icon'></a>\n";
$html .= "\t\t<a class='label' href='$nameHref'><span class='l10n-name'>Name</span>$nameSort</a>\n";
$html .= "\t\t<a class='date' href='$dateHref'>$dateSort<span class='l10n-lastModified'>Last modified</span></a>\n";
$html .= "\t\t<a class='size' href='$sizeHref'>$sizeSort<span class='l10n-size'>Size</span></a>\n";
$html .= "\t</li>\n";
return $html;
}
}
?>

305
src/h5ai/php/inc/H5ai.php Normal file
View File

@@ -0,0 +1,305 @@
<?php
require_once "Cache.php";
class H5ai {
private static $SORT_ORDER = array("column" => "name", "ascending" => true);
private static $VIEWMODES = array("details", "icons");
private $docRoot, $h5aiRoot, $h5aiAbsHref, $domain, $options, $types, $cache, $absHref, $absPath, $ignore, $ignoreRE, $sortOrder, $dateFormat, $view;
public function __construct() {
global $H5AI_CONFIG;
$this->docRoot = $H5AI_CONFIG["DOCUMENT_ROOT"];
$this->h5aiRoot = $H5AI_CONFIG["H5AI_ROOT"];
$this->ignore = $H5AI_CONFIG["IGNORE"];
$this->ignoreRE = $H5AI_CONFIG["IGNORE_PATTERNS"];
$this->options = $this->loadOptions($this->h5aiRoot . "/options.js");
$this->types = $this->loadTypes($this->h5aiRoot . "/types.txt");
$this->cache = new Cache($this->h5aiRoot . "/cache");
$this->h5aiAbsHref = $this->options["options"]["h5aiAbsHref"];
$this->domain = getenv("HTTP_HOST");
$this->absHref = $this->normalizePath(preg_replace('/\\?.*/', '', getenv("REQUEST_URI")), true);
$this->absPath = $this->normalizePath($this->docRoot . rawurldecode($this->absHref), false);
$defaultSortOrder = $this->options["options"]["sortorder"];
$this->sortOrder = array(
"column" => array_key_exists("col", $_REQUEST) ? $_REQUEST["col"] : $defaultSortOrder["column"],
"ascending" => array_key_exists("asc", $_REQUEST) ? $_REQUEST["asc"] !== "false" : $defaultSortOrder["ascending"]
);
$this->view = array_key_exists("view", $_REQUEST) ? $_REQUEST["view"] : $this->options["options"]["viewmodes"][0];
if (!in_array($this->view, H5ai::$VIEWMODES)) {
$this->view = H5ai::$VIEWMODES[0];
}
}
private function loadOptions($file) {
$str = file_exists($file) ? file_get_contents($file) : "";
$str = preg_replace("/\/\*.*?\*\//s", "", $str);
$optstr = preg_replace("/^.*h5aiOptions\s*=\s*/s", "", $str);
$optstr = preg_replace("/;.*/s", "", $optstr);
$options = json_decode($optstr, true);
$langstr = preg_replace("/^.*h5aiLangs\s*=\s*/s", "", $str);
$langstr = preg_replace("/;.*/s", "", $langstr);
$langs = json_decode($langstr, true);
return array("options" => $options, "langs" => $langs);
}
private function loadTypes($file) {
$lines = file($file);
$types = array();
foreach($lines as $line) {
if (substr($line, 0, 1) === '#') {
continue;
}
$types[] = preg_split("/\s+/", $line);
}
return $types;
}
public function getDocRoot() {
return $this->docRoot;
}
public function getH5aiRoot() {
return $this->h5aiRoot;
}
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["options"];
}
public function getLangs() {
return $this->options["langs"];
}
public function getAbsHref($absPath = null, $endWithSlash = true) {
if ($absPath === null) {
return $this->absHref;
}
$absHref = preg_replace("!^" . $this->docRoot . "!", "", $absPath);
$parts = explode("/", $absHref);
$encodedParts = array();
foreach ($parts as $part) {
$encodedParts[] = rawurlencode($part);
}
$endodedAbsHref = implode("/", $encodedParts);
return $this->normalizePath($endodedAbsHref, $endWithSlash);
}
public function getAbsPath($absHref = null) {
if ($absHref === null) {
return $this->absPath;
}
return $this->normalizePath($this->docRoot . rawurldecode($absHref), false);
}
public function getSortOrder() {
return $this->sortOrder;
}
public function getDateFormat() {
return $this->dateFormat;
}
public function showThumbs() {
return $this->options["options"]["showThumbs"] === true;
}
public function getTitle() {
$title = $this->domain . rawurldecode($this->absHref);
$title = preg_replace("/\/$/", "", $title);
$title = preg_replace("/\//", " > ", $title);
if ($this->absHref !== "/") {
$title = basename($this->absPath) . " - " . $title;
}
return $title;
}
public function getType($absPath) {
foreach($this->types as $type) {
foreach(array_slice($type, 1) as $pattern) {
if ($this->endsWith($absPath, $pattern)) {
return $type[0];
}
}
}
return "unknown";
}
public function ignoreThisFile($file) {
# always ignore
if ($file === "." || $file === ".." || $this->startsWith($file, '.ht')) {
return true;
}
if (in_array($file, $this->ignore)) {
return true;
}
foreach ($this->ignoreRE as $re) {
if (preg_match($re, $file)) {
return true;
}
}
return false;
}
public function readDir($path) {
$content = array();
if (is_dir($path)) {
if ($dir = opendir($path)) {
while (($file = readdir($dir)) !== false) {
if (!$this->ignoreThisFile($file)) {
$content[] = $file;
}
}
closedir($dir);
}
}
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);
}
public function cachedHttpCode($absHref) {
$cached = $this->cache->get($absHref);
if ($cached === false) {
$folderStatus = $this->options["options"]["folderStatus"];
if (array_key_exists($absHref, $folderStatus)) {
$code = $folderStatus[$absHref];
} else {
$code = $this->fetchHttpCode($absHref);
}
$cached = array("href" => $absHref, "code" => $code);
$this->cache->set($absHref, $cached);
}
return $cached["code"];
}
public function fetchHttpCode($absHref) {
$contentType = "Content-Type:";
$h5aiContentType = "Content-Type: text/html;h5ai=";
$host = getenv("HTTP_HOST");
$port = getenv("SERVER_PORT");
$msg = "HEAD $absHref HTTP/1.1\r\nHost: $host\r\nConnection: Close\r\n\r\n";
$errno = "";
$errstr = "";
$socket = fsockopen($host, $port, $errno, $errstr, 30);
if($socket === 0) {
return null;
}
fwrite($socket, $msg);
$content = fgets($socket);
$code = intval(trim(substr($content, 9, 4)));
if ($code === 200) {
while (! $this->startsWith($content, $contentType)) {
$content = fgets($socket);
}
if ($this->startsWith($content, $h5aiContentType)) {
$code = "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";
}
}
?>

203
src/h5ai/php/inc/Image.php Normal file
View File

@@ -0,0 +1,203 @@
<?php
class Image {
private $sourceFile;
private $source;
private $width;
private $height;
private $type;
private $dest;
public static function isUsable() {
return GD_VERSION != "GD_VERSION";
}
public static function showImage($filename) {
$image = file_get_contents($filename);
header("content-type: image");
echo $image;
}
public function __construct($filename = null) {
$this->sourceFile = null;
$this->source = null;
$this->width = null;
$this->height = null;
$this->type = null;
$this->dest = null;
$this->setSource($filename);
}
public function __destruct() {
$this->releaseSource();
$this->releaseDest();
}
public function setSource($filename) {
$this->releaseSource();
$this->releaseDest();
if (is_null($filename)) {
return;
}
$this->sourceFile = $filename;
list($this->width, $this->height, $this->type) = getimagesize($this->sourceFile);
$this->source = imagecreatefromstring(file_get_contents($this->sourceFile));
}
public function showDest() {
if (!is_null($this->dest)) {
header("Content-type: image/jpeg");
imagejpeg($this->dest, null, 100);
}
}
public function saveDest($filename) {
if (!is_null($this->dest)) {
@imagejpeg($this->dest, $filename, 90);
@chmod($filename, 0775);
}
}
public function releaseDest() {
if (!is_null($this->dest)) {
imagedestroy($this->dest);
$this->dest = null;
}
}
public function releaseSource() {
if (!is_null($this->source)) {
imagedestroy($this->source);
$this->sourceFile = null;
$this->source = null;
$this->width = null;
$this->height = null;
$this->type = null;
}
}
private function magic($destX, $destY, $srcX, $srcY, $destWidth, $destHeight, $srcWidth, $srcHeight, $canWidth = null, $canHeight = null, $color = null) {
if (!is_null($canWidth) && !is_null($canHeight)) {
$this->dest = imagecreatetruecolor($canWidth, $canHeight);
} else {
$this->dest = imagecreatetruecolor($destWidth, $destHeight);
}
if (is_null($color)) {
$color = array(255, 255, 255);
}
$icol = imagecolorallocate($this->dest, $color[0], $color[1], $color[2]);
imagefill($this->dest, 0, 0, $icol);
imagecopyresampled($this->dest, $this->source, $destX, $destY, $srcX, $srcY, $destWidth, $destHeight, $srcWidth, $srcHeight);
}
public function thumb($mode, $width, $height = null, $color = null) {
if ($height === null) {
$height = $width;
}
if ($mode === "square") {
$this->squareThumb($width);
} elseif ($mode === "rational") {
$this->rationalThumb($width, $height);
} elseif ($mode === "center") {
$this->centerThumb($width, $height, $color);
} else {
$this->freeThumb($width, $height);
}
}
public function squareThumb($width) {
$a = min($this->width, $this->height);
$x = intval(($this->width - $a) / 2);
$y = intval(($this->height - $a) / 2);
$this->magic(0, 0, $x, $y, $width, $width, $a, $a);
}
public function rationalThumb($width, $height) {
$r = 1.0 * $this->width / $this->height;
$h = $height;
$w = $r * $h;
if ($w > $width) {
$w = $width;
$h = 1.0 / $r * $w;
}
$w = intval($w);
$h = intval($h);
$this->magic(0, 0, 0, 0, $w, $h, $this->width, $this->height);
}
public function centerThumb($width, $height, $color = null) {
$r = 1.0 * $this->width / $this->height;
$h = $height;
$w = $r * $h;
if ($w > $width) {
$w = $width;
$h = 1.0 / $r * $w;
}
$w = intval($w);
$h = intval($h);
$x = intval(($width - $w) / 2);
$y = intval(($height - $h) / 2);
$this->magic($x, $y, 0, 0, $w, $h, $this->width, $this->height, $width, $height, $color);
}
public function freeThumb($width, $height) {
$w = intval($width);
$h = intval($height);
$this->magic(0, 0, 0, 0, $w, $h, $this->width, $this->height);
}
}
?>

View File

@@ -0,0 +1,59 @@
<?php
require_once "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->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->liveHref = $this->h5ai->api() . "?action=thumb&href=" . $this->srcAbsHref . "&width=" . $this->width . "&height=" . $this->height . "&mode=" . $this->mode;
}
public function create($force = 0) {
if (
$force === 2
|| ($force === 1 && !file_exists($this->path))
|| (file_exists($this->path) && filemtime($this->srcAbsPath) >= filemtime($this->path))
) {
$image = new Image();
$image->setSource($this->srcAbsPath);
$image->thumb($this->mode, $this->width, $this->height);
$image->saveDest($this->path);
}
}
public function getHref() {
return $this->href;
}
public function getPath() {
return $this->path;
}
public function getLiveHref() {
return $this->liveHref;
}
}
?>

147
src/h5ai/php/inc/Tree.php Normal file
View File

@@ -0,0 +1,147 @@
<?php
class TreeEntry {
private $h5ai, $label, $absPath, $absHref, $isFolder, $type, $content;
public function __construct($h5ai, $absPath, $absHref, $type = null) {
$this->h5ai = $h5ai;
$this->label = $this->h5ai->getLabel($absHref);
$this->absPath = $this->h5ai->normalizePath($absPath, false);
$this->isFolder = is_dir($this->absPath);
$this->absHref = $this->h5ai->normalizePath($absHref, $this->isFolder);
$this->type = $type !== null ? $type : ($this->isFolder ? "folder" : $this->h5ai->getType($this->absPath));
$this->content = null;
}
public function loadContent() {
$this->content = array();
if ($this->h5ai->getHttpCode($this->absHref) !== "h5ai") {
return;
}
$files = $this->h5ai->readDir($this->absPath);
foreach ($files as $file) {
$tree = new TreeEntry($this->h5ai, $this->absPath . "/" . $file, $this->absHref . rawurlencode($file));
if ($tree->isFolder) {
$this->content[$tree->absPath] = $tree;
}
}
$this->sort();
}
public function cmpTrees($t1, $t2) {
if ($t1->isFolder && !$t2->isFolder) {
return -1;
}
if (!$t1->isFolder && $t2->isFolder) {
return 1;
}
return strcasecmp($t1->absPath, $t2->absPath);
}
public function sort() {
if ($this->content !== null) {
uasort($this->content, array($this, "cmpTrees"));
}
}
public function toHtml() {
$classes = "entry " . $this->type . ($this->absHref === $this->h5ai->getAbsHref() ? " current" : "");
$icon = $this->type;
if ($this->absHref === "/") {
$icon = "folder-home";
}
$hint = "";
$code = "h5ai";
if ($this->isFolder) {
$code = $this->h5ai->getHttpCode($this->absHref);
$classes .= " checkedHttpCode";
if ($code !== "h5ai") {
if ($code === 200) {
$icon = "folder-page";
$hint = "<span class='hint'><img src='" . $this->h5ai->image("page") . "' alt='page' /></span>";
} else {
$classes .= " error";
$hint = "<span class='hint'> " . $code . " </span>";
}
}
}
$html = "<div class='" . $classes ."'>\n";
if ($this->content !== null && count($this->content) === 0 || $code !== "h5ai") {
$html .= "<span class='blank'></span>\n";
} else {
$indicatorState = $this->content === null ? " unknown" : " open";
$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='label'>" . $this->label . "</span>" . $hint . "\n";
$html .= "</a>\n";
$html .= $this->contentToHtml();
$html .= "</div>\n";
return $html;
}
public function contentToHtml() {
$html = "<ul class='content'>\n";
if ($this->content !== null) {
foreach($this->content as $tree) {
$html .= "<li>" . $tree->toHtml() . "</li>";
}
}
$html .= "</ul>\n";
return $html;
}
public function getRoot() {
if ($this->absHref === "/") {
return $this;
};
$tree = new TreeEntry($this->h5ai, dirname($this->absPath), dirname($this->absHref));
$tree->loadContent();
$tree->content[ $this->absPath ] = $this;
return $tree->getRoot();
}
}
class Tree {
private $h5ai;
public function __construct($h5ai) {
$this->h5ai = $h5ai;
}
public function toHtml() {
$options = $this->h5ai->getOptions();
if ($options["showTree"] === false) {
return "";
}
$tree = new TreeEntry($this->h5ai, $this->h5ai->getAbsPath(), $this->h5ai->getAbsHref());
$tree->loadContent();
$root = $tree->getRoot();
return "<section id='tree'>\n" . $root->toHtml() . "</section>\n";
}
}
?>

View File

@@ -0,0 +1,63 @@
<?php
class ZipIt {
private $h5ai;
public function __construct($h5ai) {
$this->h5ai = $h5ai;
}
public function zip($hrefs) {
$zipFile = tempnam("/tmp", "h5ai-download");
$zip = new ZipArchive();
if (!$zip->open($zipFile, ZIPARCHIVE::CREATE)) {
return false;
}
foreach ($hrefs as $href) {
$d = dirname($href);
$n = basename($href);
if ($this->h5ai->getHttpCode($this->h5ai->getAbsHref($d)) === "h5ai" && !$this->h5ai->ignoreThisFile($n)) {
$localFile = $this->h5ai->getAbsPath($href);
$file = preg_replace("!^" . $this->h5ai->getDocRoot() . "!", "", $localFile);
if (is_dir($localFile)) {
$this->zipDir($zip, $localFile, $file);
} else {
$this->zipFile($zip, $localFile, $file);
}
}
}
$zip->close();
return $zipFile;
}
private function zipFile($zip, $localFile, $file) {
if (is_readable($localFile)) {
$zip->addFile($localFile, $file);
}
}
private function zipDir($zip, $localDir, $dir) {
if ($this->h5ai->getHttpCode($this->h5ai->getAbsHref($localDir)) === "h5ai") {
$zip->addEmptyDir($dir);
$files = $this->h5ai->readDir($localDir);
foreach ($files as $file) {
$localFile = $localDir . "/" . $file;
$file = $dir . "/" . $file;
if (is_dir($localFile)) {
$this->zipDir($zip, $localFile, $file);
} else {
$this->zipFile($zip, $localFile, $file);
}
}
}
}
}
?>

View File

@@ -1,15 +1,16 @@
<?php
require_once "h5ai.php";
require_once "crumb.php";
require_once "customize.php";
require_once "extended.php";
require_once "tree.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";
$h5ai = new H5ai();
$crumb = new Crumb( $h5ai );
$customize = new Customize( $h5ai );
$extended = new Extended( $h5ai );
$tree = new Tree( $h5ai );
$crumb = new Crumb($h5ai);
$customize = new Customize($h5ai);
$extended = new Extended($h5ai);
$tree = new Tree($h5ai);
?>

View File

@@ -1,147 +0,0 @@
<?php
class TreeEntry {
private $h5ai, $label, $absPath, $absHref, $isFolder, $type, $content;
public function __construct( $h5ai, $absPath, $absHref, $type = null ) {
$this->h5ai = $h5ai;
$this->label = $this->h5ai->getLabel( $absHref );
$this->absPath = $this->h5ai->normalizePath( $absPath, false );
$this->isFolder = is_dir( $this->absPath );
$this->absHref = $this->h5ai->normalizePath( $absHref, $this->isFolder );
$this->type = $type !== null ? $type : ( $this->isFolder ? "folder" : $this->h5ai->getType( $this->absPath ) );
$this->content = null;
}
public function loadContent() {
$this->content = array();
if ( $this->h5ai->getHttpCode( $this->absHref ) !== "h5ai" ) {
return;
}
$files = $this->h5ai->readDir( $this->absPath );
foreach ( $files as $file ) {
$tree = new TreeEntry( $this->h5ai, $this->absPath . "/" . $file, $this->absHref . rawurlencode( $file ) );
if ( $tree->isFolder ) {
$this->content[$tree->absPath] = $tree;
}
}
$this->sort();
}
public function cmpTrees( $t1, $t2 ) {
if ( $t1->isFolder && !$t2->isFolder ) {
return -1;
}
if ( !$t1->isFolder && $t2->isFolder ) {
return 1;
}
return strcasecmp( $t1->absPath, $t2->absPath );
}
public function sort() {
if ( $this->content !== null ) {
uasort( $this->content, array( $this, "cmpTrees" ) );
}
}
public function toHtml() {
$classes = "entry " . $this->type . ( $this->absHref === $this->h5ai->getAbsHref() ? " current" : "" );
$img = $this->type;
if ( $this->absHref === "/" ) {
$img = "folder-home";
}
$hint = "";
$code = "h5ai";
if ( $this->isFolder ) {
$code = $this->h5ai->getHttpCode( $this->absHref );
$classes .= " checkedHttpCode";
if ( $code !== "h5ai" ) {
if ( $code === 200 ) {
$img = "folder-page";
$hint = "<span class='hint'><img src='/h5ai/images/page.png' alt='page' /></span>";
} else {
$classes .= " error";
$hint = "<span class='hint'> " . $code . " </span>";
}
}
}
$html = "<div class='" . $classes ."'>\n";
if ( $this->content !== null && count( $this->content ) === 0 || $code !== "h5ai" ) {
$html .= "<span class='blank'></span>\n";
} else {
$indicatorState = $this->content === null ? " unknown" : " open";
$html .= "<span class='indicator" . $indicatorState . "'><img src='/h5ai/images/tree.png' alt='>' /></span>\n";
}
$html .= "<a href='" . $this->absHref . "'>\n";
$html .= "<span class='icon'><img src='/h5ai/icons/16x16/" . $img . ".png' alt='" . $img . "' /></span>\n";
$html .= "<span class='label'>" . $this->label . "</span>" . $hint . "\n";
$html .= "</a>\n";
$html .= $this->contentToHtml();
$html .= "</div>\n";
return $html;
}
public function contentToHtml() {
$html = "<ul class='content'>\n";
if ( $this->content !== null ) {
foreach( $this->content as $tree ) {
$html .= "<li>" . $tree->toHtml() . "</li>";
}
}
$html .= "</ul>\n";
return $html;
}
public function getRoot() {
if ( $this->absHref === "/" ) {
return $this;
};
$tree = new TreeEntry( $this->h5ai, dirname( $this->absPath ), dirname( $this->absHref ) );
$tree->loadContent();
$tree->content[ $this->absPath ] = $this;
return $tree->getRoot();
}
}
class Tree {
private $h5ai;
public function __construct( $h5ai ) {
$this->h5ai = $h5ai;
}
public function toHtml() {
$options = $this->h5ai->getOptions();
if ( $options["showTree"] === false ) {
return "";
}
$tree = new TreeEntry( $this->h5ai, $this->h5ai->getAbsPath(), $this->h5ai->getAbsHref() );
$tree->loadContent();
$root = $tree->getRoot();
return "<section id='tree'>\n" . $root->toHtml() . "</section>\n";
}
}
?>

View File

@@ -1,20 +0,0 @@
<?php
if ( ! array_key_exists( "href", $_REQUEST ) ) {
exit;
}
require_once "h5ai.php";
require_once "tree.php";
$h5ai = new H5ai();
$absHref = trim( $_REQUEST[ "href" ] );
$absPath = $h5ai->getAbsPath( $absHref );
$tree = new TreeEntry( $h5ai, $absPath, $absHref );
$tree->loadContent();
echo $tree->contentToHtml();
?>

View File

@@ -1,5 +1,5 @@
################################
# %BUILD_NAME% %BUILD_VERSION% (js)
# h5ai %BUILD_VERSION% (js)
# customized .htaccess
################################
@@ -27,7 +27,8 @@ IndexIgnore h5ai h5ai.header.html h5ai.footer.html
# table options
################################
# syntax for default sort order is: IndexOrderDefault Ascending|Descending Name|Date|Size
# syntax for default sort order is:
# IndexOrderDefault Ascending|Descending Name|Date|Size
IndexOrderDefault Ascending Name
IndexOptions Type=text/html;h5ai=%BUILD_VERSION%

View File

@@ -1,5 +1,5 @@
################################
# %BUILD_NAME% %BUILD_VERSION% (php)
# h5ai %BUILD_VERSION% (php)
# customized .htaccess
################################

Binary file not shown.

4
tools/wepp Executable file
View File

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

40
tools/wepp.ant.xml Normal file
View File

@@ -0,0 +1,40 @@
<?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>