h5ai

经常布置服务器,所以想搞一个软件仓库,找了下h5ai看着挺好,目前部署在windows下upupw的运行环境,会有中文目录显示乱码,打开 中文目录提示404的问题。

这里修改两行代码即可解决:

\_h5ai\private\php\core\class-context.php

public function to_href($path, $trailing_slash = true) {
$rel_path = substr($path, strlen($this->setup->get(‘ROOT_PATH’)));
$parts = explode(‘/’, $rel_path);
$encoded_parts = [];
foreach ($parts as $part) {
if ($part != ”) {
$encoded_parts[] = rawurlencode(mb_convert_encoding($part, "UTF-8", "GBK")); 
                 //rawurlencode($part);
}
}

return Util::normalize_path($this->setup->get(‘ROOT_HREF’) . implode(‘/’, $encoded_parts), $trailing_slash);
}

public function to_path($href) {
$rel_href = substr($href, strlen($this->setup->get(‘ROOT_HREF’)));

//return Util::normalize_path($this->setup->get('ROOT_PATH') . '/' .rawurldecode($rel_href));

return Util::normalize_path($this->setup->get('ROOT_PATH') . '/' . iconv( 'UTF-8', 'GBK', rawurldecode($rel_href) ));
}

找到上面这两个函数,将注释//部分修改为上面代码即可。

modern HTTP web server index

h5ai is a modern file indexer for HTTP web servers with focus on your files. Directories are displayed in a appealing way and browsing them is enhanced by different views, a breadcrumb and a tree overview. Initiallyh5ai was an acronym for HTML5 Apache Index but now it supports other web servers too.

See the demo directory with most features enabled. A reduced example and my actual use case is therelease directory for the projects on this page.

Requires PHP 5.5+ and works fine with Apache httpd, lighttpd, nginx and Cherokee. Best user experience with the latest versions of Chrome, Firefox, Opera, Vivaldi, Safari and Edge, but a static fallback is provided for older browsers or if JavaScript is disabled.

Features

There are lots of optional extensions and configuration options to customize the web appearance of your directory listings. All markup is valid HTML5 spiced up with CSS3 and finest JavaScript to build a fresh but minimal user interface and a user experience that focuses on your files.

Some of the optional features are:
sorting – view modes – localization – breadcrumb – tree view – custom headers+footers – filter+search – folder sizes – auto refresh – packaged download – QR codes – thumbnails – image+text+audio+video preview

Installation

  1. Copy folder _h5ai to the document root directory of the web server: DOC_ROOT/_h5ai.
DOC_ROOT
 ├─ _h5ai
 ├─ your files
 └─ and folders
  1. Visit http://YOUR-DOMAIN.TLD/_h5ai/public/index.php, to check if h5ai is reachable. This page shows some hints on the server's capabilities.
  2. Add /_h5ai/public/index.php (note the leading slash!) to the end of the default index-file list. In this way h5ai will manage all directories in and below DOC_ROOT that don't have a index file.

Apache httpd 2.2/2.4: in httpd.conf or in the root directory's .htaccess file set for example:

DirectoryIndex index.html index.php /_h5ai/public/index.php

lighttpd 1.4: in lighttpd.conf set for example:

index-file.names += ("index.html", "index.php", "/_h5ai/public/index.php")

nginx 1.2: in nginx.conf set for example:

index index.html index.php /_h5ai/public/index.php;

Cherokee 1.2: in cherokee.conf set for example:

vserver!1!directory_index = index.html,index.php,/_h5ai/public/index.php

Configuration

The main configuration file is _h5ai/private/conf/options.json. You might want to change some of the documented settings. But there are some more files in _h5ai/private/conf you might have a look at.

Hints

  • No web server specific things are supported, that includes access restrictions! Best chance to make restricted areas work and secure might be to place folder _h5ai completely inside that resticted area. Use it at your own risk!

  • Does not work with aliased folders in general (as available in Apache httpd). Aliased folders make it impossible to map URLs to file system folders.

  • If no icons are displayed, chances are that you have to add the SVG MIME-type to your server.

  • On Ubuntu servers you might need to install an additional package for PHP JSON support.

  • To use optional features based on shell commands the PHP functions exec and passthru must not be disabled in php.ini (have a look for disable_functions).

  • There was a security flaw in versions v0.22.0 - v0.24.1 that was fixed in v0.25.0 (summer 2014). If you are still using one of these versions you are advised to upgrade.

Custom installation

It's possible to install h5ai into any sub directory of your web server's document root. This directory will then be considered the root directory when showing a breadcrumb etc.

For example copy folder _h5ai to DOC_ROOT/some/folder/_h5ai:

DOC_ROOT
 └─ some
     └─ folder
         ├─ _h5ai
         ├─ your files
         └─ and folder

Visit http://YOUR-DOMAIN.TLD/some/folder/_h5ai/public/index.php to see if everything works fine. In this example you need to add /some/folder/_h5ai/public/index.php to your index-file list (as in step 3 above).

注意此Windows版本,带登录,更改处:

第一处文件:_h5ai/private/php/class-bootstrap.php

class Bootstrap {
    private static $autopaths = ['core', 'ext'];

    public static function run() {
        spl_autoload_register(['Bootstrap', 'autoload']);
        putenv('LANG=en_US.UTF-8');
        setlocale(LC_CTYPE, 'en_US.UTF-8');
        date_default_timezone_set(@date_default_timezone_get());
        //session_start();//更改处

第二处文件:_h5ai/public/index.php

include_once("./admin/check.php");//增加登录验证
define('H5AI_VERSION', '0.29.0');
define('MIN_PHP_VERSION', '5.5.0');

第三处文件:_h5ai/private/php/core/class-contex.php(部署在Windows服务器乱码问题)

public function to_href($path, $trailing_slash = true) {
        $rel_path = substr($path, strlen($this->setup->get('ROOT_PATH')));
        $parts = explode('/', $rel_path);
        $encoded_parts = [];
        foreach ($parts as $part) {
            if ($part != '') {
                //$encoded_parts[] = rawurlencode($part);//第一处修改
                $encoded_parts[] = rawurlencode(mb_convert_encoding($part, "UTF-8", "GBK"));
            }
        }

        return Util::normalize_path($this->setup->get('ROOT_HREF') . implode('/', $encoded_parts), $trailing_slash);
    }

    public function to_path($href) {
        $rel_href = substr($href, strlen($this->setup->get('ROOT_HREF')));
        //return Util::normalize_path($this->setup->get('ROOT_PATH') . '/' . rawurldecode($rel_href));//第二处修改
        return Util::normalize_path($this->setup->get('ROOT_PATH') . '/' . iconv( 'UTF-8', 'GBK', rawurldecode($rel_href) ));
    }

第四处更改:_h5ai/private/php/pages/index.php

<?php
//header( 'Content-type: text/html;charset=utf-8');//IE下中文乱码更改
header('Content-type: text/html;charset=GBK');
?>
<!DOCTYPE html>

第五处更改:_h5ai/public/js/script.js

function (t, e, n) {
    "use strict";
    var r = n(2), i = r.dom, o = "body",
    a = '<div id="topbar">\n
            <div id="toolbar"></div>\n
            <div id="flowbar"></div>\n
            <a class="backlink"  id="rekey" title="powered by h5ai - https://larsjung.de/h5ai/">\n  <div>修改密码</div>\n  <div>by h5ai</div>\n  </a>\n
            <a class="backlink"  id="guanli" title="powered by h5ai - https://larsjung.de/h5ai/">\n  <div>管理</div>\n  <div>by h5ai</div>\n  </a>\n
            <a href="/_h5ai/public/admin/login.php?action=logout" class="backlink" title="powered by h5ai - https://larsjung.de/h5ai/">\n  <div>退出</div>\n  <div>by h5ai</div>\n  </a>\n
         </div>',

    s = '<div id="mainrow">\n            <div id="content"></div>\n     </div>',
        u = function () {
        var t = i(o).attr("id", "root").clr().app(a).app(s);
        return {
            $root: t,
            $topbar: t.find("#topbar"),
            $toolbar: t.find("#toolbar"),
            $flowbar: t.find("#flowbar"),
            $mainrow: t.find("#mainrow"),
            $content: t.find("#content")
        }
    };
    t.exports = u();

    $('#rekey').on('click',function(){
        layer.open({
            type:2,
            title:'用户设置',
            shadeClose:true,
            shade:0.8,
            area:['360px','420px'],
            content:'/_h5ai/public/admin/admin.php'
        });
    });//修改增加

    $('#guanli').on('click',function(){
        layer.open({
            type:2,
            title:'用户设置',
            shadeClose:true,
            shade:0.8,
            area:['90%','80%'],
            content:'/admin.php'
        });
    });//修改增加
}

第六处更改_h5ai/public/js/script.js接入Dpalyer播放器

f = function(t) {
return new Promise(function(e) {
/**原代码
var n = i(u).on("loadedmetadata", function() {
return e(n)
}).attr("controls", "controls");
s.autoplay && n.attr("autoplay", "autoplay"), l(n[0]), n.attr("src", t.absHref);
**/
function loadPlayer(url) {
document.querySelector("#pv-container").classList.remove('hidden');
document.querySelector("#pv-spinner").style.display = 'none';
var dp = document.createElement('div');
dp.id = 'dplayer';
dp.style.cssText = 'width:100%;height:100%';
document.querySelector("#pv-container").appendChild(dp);

var dplayer = new DPlayer({
container: document.querySelector("#dplayer"),
autoplay: true,
mutex: true,
video: {
url: url,
type: 'auto'
},
});
console.log(a.item.label);
console.log(a);
a.setLabels([a.item.label],'','');
};
loadPlayer(t.absHref);
})

第七处更改:_h5ai/private/conf/options.json中找到resources项

将styles参数字符串中的fonts.googleapis.com更换为fonts.geekzu.org即可。

//fonts.googleapis.com/css?family=Ubuntu:300,400,700%7CUbuntu+Mono:400,700
改为:
//fonts.geekzu.org/css?family=Ubuntu:300,400,700%7CUbuntu+Mono:400,700

DirectoryLister

文件管理器部署到Windows服务器,访问中文乱码解决办法如下:

foreach ($dirArray as $key => $dir) {
$dir=mb_convert_encoding($dir,"UTF-8","GBK");  //第一处增加
 if ($dir != '.') {
$dirPath  = null;
// Build the directory path
for ($i = 0; $i <= $key; $i++) {
$dirPath = $dirPath . $dirArray[$i] . '/';
}
// Remove trailing slash
if(substr($dirPath, -1) == '/') {
$dirPath = substr($dirPath, 0, -1);
}
// Combine the base path and dir path
//$link = $this->_appURL . '?dir=' . rawurlencode($dirPath);
$link = $this->_appURL . '?dir=' . rawurlencode(mb_convert_encoding($dirPath,"UTF-8","GBK"));    //第二处修改



protected function _setDirectoryPath($dir) {
$dir=mb_convert_encoding($dir,"GBK","UTF-8");  //第三处增加
// Check for an empty variable
if (empty($dir) || $dir == '.') {
return '.';
}



if (!empty($directoryPath)) {
//$directoryPath = '?dir=' . rawurlencode($directoryPath);
$directoryPath = '?dir=' . rawurlencode(mb_convert_encoding($directoryPath, "UTF-8", "GBK")); //第四处修改
 }



if ($this->_directory != '.' || $file != 'index.php') {
// Build the file path
//$urlPath = implode('/', array_map('rawurlencode', explode('/', $relativePath)));
$urlPath = implode('/', array_map('rawurlencode', explode('/', mb_convert_encoding($relativePath, "UTF-8", "GBK"))));//第五处修改
if (is_dir($relativePath)) {
  $urlPath = '?dir=' . $urlPath;
   } else {$urlPath = $urlPath;}
preg_match('/\/([^\/]*)$/', $relativePath, $matches);
//$directoryArray[pathinfo($relativePath, PATHINFO_BASENAME)] = array( //第六处修改
$directoryArray[pathinfo(mb_convert_encoding($relativePath, "UTF-8", "GBK"), PATHINFO_BASENAME)] = array(
//$pathname = isset($matches[1]) ? $matches[1] : $relativePath;
//$directoryArray[$pathname] = array(
'file_path'  => $relativePath,
'url_path'   => $urlPath,
'file_size'  => is_dir($realPath) ? '-' : $this->getFileSize($realPath),
'mod_time'   => date('Y-m-d H:i:s', filemtime($realPath)),
'icon_class' => $iconClass,
'sort'       => $sort
);

foreach ($this->_config['hidden_files'] as $hiddenPath) {
/**
if(!function_exists('fnmatch')) {
    function fnmatch($pattern, $string) {
        return preg_match("#^".strtr(preg_quote($pattern, '#'), array('\*' => '.*', '\?' => '.'))."$#i", $string);
    } 
} //第七处修改,如果fnmatch()函数报错
**/
            if (fnmatch($hiddenPath, $filePath)) {
                return true;
            }
}

function getFileSize($filePath) {
    // Get file size
    //$bytes = filesize($filePath);

    // Array of file size suffixes
    //$sizes = array('B', 'KB', 'MB', 'GB', 'TB', 'PB');

    // Calculate file size suffix factor
    //$factor = floor((strlen($bytes) - 1) / 3);

    // Calculate the file size
    //$fileSize = sprintf('%.2f', $bytes / pow(1024, $factor)) . $sizes[$factor];
    //第八处修改
    $bytes = sprintf("%u", (int)filesize($filePath));      
    $unit = $bytes>pow(1024,3) ? array(3,"G") : ($bytes>pow(1024,2) ? array(2,"MB") : array(1,"KB"));
    $fileSize=round($bytes/(pow(1024,$unit[0])),2).$unit[1];

    return $fileSize;
}

public function getFileHash($filePath) {
    // Placeholder array
    $hashArray = array();
    //第九处修改
    $filePath = mb_convert_encoding($filePath,'GBK','UTF-8');
    // Verify file path exists and is a directory
    if (!file_exists($filePath)) {
        return json_encode($hashArray);
    }
    // Prevent access to hidden files
    if ($this->_isHidden($filePath)) {
        return json_encode($hashArray);
    }
    // Prevent access to parent folders
    if (strpos($filePath, '<') !== false || strpos($filePath, '>') !== false || strpos($filePath, '..') !== false || strpos($filePath, '/') === 0) {
        return json_encode($hashArray);
    }
    // Prevent hashing if file is too big
    if (filesize($filePath) > $this->_config['hash_size_limit']) {
        // Notify user that file is too large
        $hashArray['md5']  = '[ File size exceeds threshold ]';
        $hashArray['sha1'] = '[ File size exceeds threshold ]';
    } else {
        // Generate file hashes
        $hashArray['md5']  = hash_file('md5', $filePath);
        $hashArray['sha1'] = hash_file('sha1', $filePath);
    }
    // Return the data
    return $hashArray;
}