Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Additional log and notification, more control on file access through PHP #64

Open
wants to merge 9 commits into
base: master
Choose a base branch
from
10 changes: 10 additions & 0 deletions .htaccess
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
IndexIgnore *
Order Deny,Allow
Deny from all

<Files "index.php">
Allow from all
</Files>
<Files ".">
Allow from all
</Files>
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@ You have to upload index.php into your server.
If you open index.php you can edit several settings.
You should make sure the edited file will be saved in UTF-8!

An example of how to protect direct Access through .htaccess (apache)
is available and must be adjusted to the webserver.


License
----------------------------------
Expand Down
145 changes: 130 additions & 15 deletions index.php
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,10 @@
// If set to true, you should specify some users as well (see below).
// Important: This only prevents people from seeing the list.
// They will still be able to access the files with a direct link.
// Addition: Combine htaccess and require_login to disallow
// direct access to file. File access gets logged more precisely.
// Attention: Be advised, the file is processed by PHP,
// large/slow downloads might break due to php_script_timeout
// Default: $_CONFIG['require_login'] = false;
//
$_CONFIG['require_login'] = false;
Expand Down Expand Up @@ -787,7 +791,7 @@
//Polish
$_TRANSLATIONS["pl"] = array(
"file_name" => "Nazwa pliku",
"size" => "Rozmiar",
"size" => "Rozmiar",
"last_changed" => "Data zmiany",
"total_used_space" => "Cała przestrzeń",
"free_space" => "Wolna przestrzeń",
Expand All @@ -796,17 +800,17 @@
"failed_upload" => "Przesłanie pliku nie powiodło się",
"failed_move" => "Przenoszenie pliku nie powiodło się!",
"wrong_password" => "Niepoprawne hasło",
"make_directory" => "Nowy folder",
"make_directory" => "Nowy folder",
"new_dir_failed" => "Błąd podczas tworzenia nowego folderu",
"chmod_dir_failed" => "Błąd podczas zmiany uprawnień folderu",
"unable_to_read_dir" => "Odczytanie folderu nie powiodło się",
"location" => "Miejsce",
"location" => "Miejsce",
"root" => "Start",
"log_file_permission_error" => "Brak uprawnień aby utworzyć dziennik działań.",
"upload_not_allowed" => "Konfiguracja zabrania przesłania pliku do tego folderu.",
"upload_dir_not_writable" => "Nie można zapisać pliku do tego folderu.",
"mobile_version" => "Wersja mobilna",
"standard_version" => "Widok standardowy",
"standard_version" => "Widok standardowy",
"page_load_time" => "Załadowano w %.2f ms",
"wrong_pass" => "Niepoprawna nazwa użytkownika lub złe hasło",
"username" => "Użytkownik",
Expand Down Expand Up @@ -1728,6 +1732,10 @@ function css()
$_IMAGES["xlsx"] = $_IMAGES["spreadsheet"];
$_IMAGES["xml"] = $_IMAGES["code"];
$_IMAGES["zip"] = $_IMAGES["archive"];
$_IMAGES["download"] = "iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAQAAAC1+jfqAAAAAmJLR0QA/4ePzL8AAAAJcEhZcwAA
CxMAAAsTAQCanBgAAAAHdElNRQfhAxUJJiDGyieZAAAAeklEQVQoz62QsQqAMAxEn7Wbn9NZP0Dw
/0e/Qu0QGhcrTakI4mVIAncXLvCCzmz+6tImeyKCEG9ioclbX6tcMStquiEMuMLN4xis00hC0KuE
xFgfC0QSipKIhFaKiQNFOZievhLY2dvqjIWFb1jvBLlW+8m5zs3GTzgBdP0qMaa27WIAAAAASUVO";

/***************************************************************************/
/* HERE COMES THE CODE. */
Expand Down Expand Up @@ -1926,8 +1934,12 @@ public static function log($message)
public static function logAccess($path, $isDir)
{
$message = $_SERVER['REMOTE_ADDR']." ".GateKeeper::getUserName()." accessed ";
$message .= $isDir?"dir":"file";
$message .= $isDir && !(isset($_GET['file']) || isset($_GET['dl'])) ? "dir" : "file";
$message .= " ".$path;
if (isset($_GET['file']))
$message.= $_GET['file'];
if (isset($_GET['dl']))
$message.= $_GET['dl'];
Logger::log($message);
}

Expand All @@ -1950,6 +1962,14 @@ public static function logCreation($path, $isDir)
Logger::log($message);
}

public static function logDeletion($path, $isDir)
{
$message = $_SERVER['REMOTE_ADDR']." ".GateKeeper::getUserName()." deleted ";
$message .= $isDir?"dir":"file";
$message .= " ".$path;
Logger::log($message);
}

public static function emailNotification($path, $isFile)
{
if(strlen(EncodeExplorer::getConfig('upload_email')) > 0)
Expand All @@ -1961,6 +1981,18 @@ public static function emailNotification($path, $isFile)
mail(EncodeExplorer::getConfig('upload_email'), "Upload notification", $message);
}
}

public static function emailNotificationDeletion($path, $isFile)
{
if(strlen(EncodeExplorer::getConfig('upload_email')) > 0)
{
$message = "This is a message to let you know that ".GateKeeper::getUserName()." ";
$message .= ($isFile?"deleted a file":"deleted a directory")." in Encode Explorer.\n\n";
$message .= "Path : ".$path."\n";
$message .= "IP : ".$_SERVER['REMOTE_ADDR']."\n";
mail(EncodeExplorer::getConfig('delete_email'), "Deletion notification", $message);
}
}
}

//
Expand Down Expand Up @@ -2097,6 +2129,18 @@ public static function showLoginBox(){
return true;
return false;
}


public static function isAccessAllowedOnFile($filepath) {
$path = str_replace(basename($filepath), "", $filepath);

foreach(explode("/", $path) as $dir) {
if (in_array($dir, EncodeExplorer::getConfig('hidden_dirs')))
return false;
}

return !in_array(basename($filepath), EncodeExplorer::getConfig('hidden_files'));
}
}

//
Expand Down Expand Up @@ -2208,6 +2252,56 @@ function uploadFile($location, $userfile)
}
}

function downloadFile($filepath)
{
$filepath = EncodeExplorer::getConfig('basedir').$filepath;
if (strpos($filepath, '../') !== false)
return; // Not allowed
if( file_exists( $filepath ) )
{
header( 'Cache-Control: public' );
header( 'Content-Description: File Transfer' );
header( 'Content-Disposition: attachment; filename='.basename($filepath) );
header( 'Content-Type: '.File::getFileMime($filepath) ); // application/octet-stream
header( 'Content-Length: '.filesize($filepath));
header( 'Content-Transfer-Encoding: binary' );
readfile( $filepath );
exit;
}
}

function provideFile($filepath)
{
$filepath = EncodeExplorer::getConfig('basedir').$filepath;
if (strpos($filepath, '../') !== false)
return; // Not allowed
if( file_exists( $filepath ) )
{
$mtime = gmdate('r', filemtime($_SERVER['SCRIPT_FILENAME']));
$etag = md5($mtime.$_SERVER['SCRIPT_FILENAME']);

if ((isset($_SERVER['HTTP_IF_MODIFIED_SINCE']) && $_SERVER['HTTP_IF_MODIFIED_SINCE'] == $mtime)
|| (isset($_SERVER['HTTP_IF_NONE_MATCH']) && str_replace('"', '', stripslashes($_SERVER['HTTP_IF_NONE_MATCH'])) == $etag))
{
header('HTTP/1.1 304 Not Modified');
return true;
}
else {
header( 'ETag: "'.$etag.'"' );
header( 'Last-Modified: '.$mtime );
header( 'Cache-Control: public' );
//header( 'Content-Description: File Transfer' );
header( 'Content-Disposition: filename='.basename($filepath) );
header( 'Content-type: '.File::getFileMime($filepath) );
header( 'Content-Length: '.filesize($filepath));
header( 'Content-Transfer-Encoding: binary' );
readfile( $filepath );
exit;
}
return true;
}
}

public static function delete_dir($dir) {
if (is_dir($dir)) {
$objects = scandir($dir);
Expand All @@ -2221,12 +2315,16 @@ public static function delete_dir($dir) {
}
reset($objects);
rmdir($dir);
Logger::logDeletion("./".$dir, true);
Logger::emailNotificationDeletion("./".$dir, false);
}
}

public static function delete_file($file){
if(is_file($file)){
unlink($file);
Logger::logDeletion("./".$file, false);
Logger::emailNotificationDeletion("./".$file, true);
}
}

Expand Down Expand Up @@ -2265,6 +2363,11 @@ function run($location)
FileManager::delete_file($path);
}
}

if (isset($_GET['dl']) && !empty($_GET['dl']) && GateKeeper::isAccessAllowed() && GateKeeper::isAccessAllowedOnFile($_GET['dl']))
$this->downloadFile($_GET['dl']);
if (isset($_GET['file']) && !empty($_GET['file']) && GateKeeper::isAccessAllowed() && GateKeeper::isAccessAllowedOnFile($_GET['file']))
$this->provideFile($_GET['file']);
}
}

Expand Down Expand Up @@ -2626,7 +2729,7 @@ function init()
if(function_exists('date_default_timezone_get') && function_exists('date_default_timezone_set'))
{
@date_default_timezone_set(date_default_timezone_get());
}
}

if(isset($_GET['lang']) && is_scalar($_GET['lang']) && isset($_TRANSLATIONS[$_GET['lang']]))
$this->lang = $_GET['lang'];
Expand Down Expand Up @@ -2726,8 +2829,8 @@ function sort()
usort($this->dirs, array('EncodeExplorer', 'cmp_'.$sort_by));
if($this->sort_as == "desc") {
$this->dirs = array_reverse($this->dirs);
}
}
}

// Here we filter the comparison functions supported by our file object
$sort_by = in_array($this->sort_by, array('name', 'size', 'mod')) ? $this->sort_by : 'name';
Expand All @@ -2736,7 +2839,7 @@ function sort()
usort($this->files, array('EncodeExplorer', 'cmp_'.$sort_by));
if($this->sort_as == "desc") {
$this->files = array_reverse($this->files);
}
}
}
}

Expand Down Expand Up @@ -2979,7 +3082,7 @@ function outputHtml()
});
<?php
}
if($this->logging == true)
if($this->logging == true && !GateKeeper::isLoginRequired())
{
?>
function logFileClick(path)
Expand All @@ -2994,7 +3097,7 @@ function logFileClick(path)
}

$("a.file").click(function(){
logFileClick("<?php print $this->location->getDir(true, true, false, 0);?>" + $(this).html());
logFileClick("./" + $(this).attr('href').replace("?dl=","").replace("?file=",""));
return true;
});
<?php
Expand All @@ -3016,7 +3119,7 @@ function positionThumbnail(e) {

$("a.thumb").hover(function(e){
$("#thumb").remove();
$("body").append("<div id=\"thumb\"><img src=\"?thumb="+ $(this).attr("href") +"\" alt=\"Preview\" \/><\/div>");
$("body").append("<div id=\"thumb\"><img src=\"?thumb="+ $(this).attr("href").replace("?dl=","").replace("?file=","") +"\" alt=\"Preview\" \/><\/div>");
positionThumbnail(e);
$("#thumb").fadeIn("medium");
},
Expand Down Expand Up @@ -3107,13 +3210,14 @@ function(){
<?php if($this->mobile == false && GateKeeper::isDeleteAllowed()){?>
<td class="del"><?php print EncodeExplorer::getString("del"); ?></td>
<?php } ?>
<td class="icon">DL</td>
</tr>
<?php
}
?>
<tr class="row two">
<td class="icon"><img alt="dir" src="?img=directory" /></td>
<td colspan="<?php print (($this->mobile == true?1:(GateKeeper::isDeleteAllowed()?4:3))); ?>" class="long">
<td colspan="<?php print (($this->mobile == true?1:(GateKeeper::isDeleteAllowed()?5:4))); ?>" class="long">
<a class="item" href="<?php print $this->makeLink(false, false, null, null, null, $this->location->getDir(false, true, false, 1)); ?>">..</a>
</td>
</tr>
Expand Down Expand Up @@ -3146,6 +3250,7 @@ function(){
{
print "<td class=\"del\"><a data-name=\"".htmlentities($dir->getName())."\" href=\"".$this->makeLink(false, false, null, null, $this->location->getDir(false, true, false, 0).$dir->getNameEncoded(), $this->location->getDir(false, true, false, 0))."\"><img src=\"?img=del\" alt=\"Delete\" /></a></td>";
}
print "<td></td>";
print "</tr>\n";
$row =! $row;
}
Expand All @@ -3162,8 +3267,10 @@ function(){
$row_style = ($row ? "one" : "two");
print "<tr class=\"row ".$row_style.(++$count == count($this->files)?" last":"")."\">\n";
print "<td class=\"icon\"><img alt=\"".$file->getType()."\" src=\"".$this->makeIcon($file->getType())."\" /></td>\n";
print "<td class=\"name\" colspan=\"1\">\n";
print "\t\t<a href=\"".$this->location->getDir(false, true, false, 0).$file->getNameEncoded()."\"";
print "<td class=\"name\">\n";
print GateKeeper::isLoginRequired()
? "\t\t<a href=\"?file=".$this->location->getDir(false, true, false, 0).$file->getNameEncoded()."\""
: "\t\t<a href=\"".$this->location->getDir(false, true, false, 0).$file->getNameEncoded()."\"";
if(EncodeExplorer::getConfig('open_in_new_window') == true)
print "target=\"_blank\"";
print " class=\"item file";
Expand All @@ -3190,6 +3297,14 @@ function(){
</a>
</td>";
}

print "<td class=\"icon\">";
print GateKeeper::isLoginRequired()
? "<a href=\"?dl=".$this->location->getDir(false, true, false, 0).$file->getNameEncoded()."\" class=\"item file\" download>"
: "<a href=\"".$this->location->getDir(false, true, false, 0).$file->getNameEncoded()."\" class=\"item file\" download>";
print "<img alt=\"download\" src=\"?img=download\" />";
print "</a></td>\n";

print "</tr>\n";
$row =! $row;
}
Expand Down Expand Up @@ -3230,7 +3345,7 @@ function(){
{
?>
<!-- START: Upload area -->
<form enctype="multipart/form-data" method="post">
<form enctype="multipart/form-data" method="post" <?=isset($_GET['dir'])? 'action="?dir='.$_GET['dir'].'">' : ''?>>
<div id="upload">
<?php
if(GateKeeper::isNewdirAllowed()){
Expand Down