<?php
header('Content-Type: text/html; charset=utf-8');
set_time_limit(0);
/* Notes:
This code not designed for public consumption. It may work, but the code is quick and dirty.
The coding style used in this code is not reflective of my professional work, but rather my
"lets get it done now" style of work. It is only used by me in my LAN environment. This is not
secure, so do not use it in a production environment. Protect it with .htaccess/.htpasswd and
use common sense. The apache user (or suPHP user) will need write access to the Greyhole shares,
and read access to /etc/greyhole.conf
"Copies", when the result is a directory, is more like "Spanned across X drives".
"Copies", when the result is a file, is an accurate representation of how many drives
that specific file is on.
This was merely created to suit my needs and make it easier to purge/restore deleted items
from a greyhole share's trash. It is not a complete management system, nor does it have all the
features that it could. Basically, it does what I need. I share the code in case someone else
desires the same functionality, or would like to expand it (either for personal or commercial
use. My only request is if you expand this code and sell it, that I get a free license ;)
An example gallery can be found here: http://imgur.com/a/rTg3x
Created by Zefie of Zefie Networks. BSD License, or whatever. Do what you want with it.
Updated 2014-02-11, because I started using Greyhole again and noticed some missing features.
Added: Last Modified, Size, and UTF-8 support.
*/
$drives = getDrives();
if (@$_GET['path']) $ext = $_GET['path'];
else $ext = "";
if (@$_GET['view']) $view = $_GET['view'];
else $view = "";
if (@$_GET['drive']) $drive = $_GET['drive'];
else $drive = "";
if (@$_GET['action']) $action = $_GET['action'];
else $action = "";
if (@$_GET['confirm']) $confirm = $_GET['confirm'];
else $confirm = "";
if (($drive == "" || $view == "") && $action == "") {
$ptitle = "Greyhole Trash Manager";
if ($ext != "") {
$ptitle .= " - ".$ext;
}
echo "<html>\n";
echo "<head>\n";
echo "<title>".$ptitle."</title>\n";
echo "<style type=\"text/css\">\n";
echo "td, th {\n";
echo "\tpadding: 7px 5px 7px 5px;\n";
echo "\tborder: 1px dotted #000;\n";
echo "}\n";
echo "th {\n";
echo "\ttext-align: left;\n";
echo "\tfont-weight: bold;\n";
echo "\tfont-style: italic;\n";
echo "}\n";
echo "form {\n";
echo "\tdisplay: inline;\n";
echo "}\n";
echo ".ral {\n";
echo "\ttext-align: right\n";
echo "}\n";
echo "</style>\n";
echo "</head>\n";
echo "<body>\n";
echo "<h2>".$ptitle."</h2>\n";
echo "<table>\n";
echo "<tr>\n";
echo "<th>Path</th>\n";
echo "<th>Size</th>\n";
echo "<th>Modified</th>\n";
echo "<th>Copies</th>\n";
echo "<th>Actions</th>\n";
echo "</tr>\n";
if ($ext != "") {
$meh = split("/",$ext);
$c = (count($meh) - 1);
$meh2 = "";
for ($i = 0; $i < $c; $i++) {
$meh2 .= $meh[$i]."/";
}
$meh2 = rtrim($meh2,"/");
echo "<tr>\n";
echo "<td><a href=\"?path=".rawurlencode($meh2)."\">Parent Directory</a></td>\n";
echo "<td> - </td>\n";
echo "<td> - </td>\n";
echo "<td> - </td>\n";
echo "<td> - </td>\n";
echo "</tr>\n";
}
foreach ($drives as $d) {
$path = $d."/.gh_trash/".$ext;
if ($h = @opendir($path)) {
while (false !== ($e = readdir($h))) {
if ($e != "." && $e != "..") {
$list[] = array($e,$d);
}
}
closedir($h);
}
}
if (@count($list) > 0) {
foreach ($list as $l) {
if (@in_array($l[0],@$r)) {
$q[$l[0]] = (@$q[$l[0]] + 1);
} else {
$r[] = $l[0];
// First drive is fine
if (!isset($z[$l[0]])) {
$z[$l[0]] = $l[1];
}
}
}
}
if (@count($r) > 0) {
foreach ($r as $k) {
echo "<tr>\n";
if (is_dir($z[$k]."/.gh_trash/".$ext."/".$k)) {
echo "<td><a href=\"?path=".rawurlencode($ext."/".$k)."\">".$k."</a></td>\n";
echo "<td>-</td>\n";
echo "<td>-</td>\n";
echo "<td>".(@$q[$k]+1)."</td>\n";
} else {
$dr = (array_search($z[$k],$drives)+1);
echo "<td><a href=\"?view=".rawurlencode($ext."/".$k)."&drive=".$dr."\">".$k."</a></td>\n";
$fsize = filesize($z[$k]."/.gh_trash/".$ext."/".$k);
echo "<td>".$fsize." bytes (".friendlyBytes($fsize).")</td>\n";
$ftime = filemtime($z[$k]."/.gh_trash/".$ext."/".$k);
echo "<td>".strftime("%m/%e/%Y %r",$ftime)."</td>\n";
echo "<td>".(@$q[$k]+1)."</td>\n";
}
echo "<td>\n";
echo "<form method=\"GET\"><input type=\"hidden\" name=\"path\" value=\"".$ext."/".$k."\" /><input type=\"hidden\" name=\"action\" value=\"remove\" /><input type=\"submit\" value=\"Delete Permanently\" /></form>\n";
echo "<form method=\"GET\"><input type=\"hidden\" name=\"path\" value=\"".$ext."/".$k."\" /><input type=\"hidden\" name=\"action\" value=\"restore\" /><input type=\"submit\" value=\"Restore\" /></form>\n";
echo "</td>\n";
echo "</tr>";
}
}
echo "<tr>\n";
echo "<td colspan=\"3\" class=\"ral\">\n";
$space = getSpace(true);
echo "<strong>Disk Space Status:</strong><br />\n";
echo "<table class=\"ral\" width=\"100%\">\n";
echo "<tr><td>Total:</td><td>".$space['total']."</td></tr>\n";
echo "<tr><td>Used:</td><td>".$space['used']."</td></tr>\n";
echo "<tr><td>Available:</td><td>".$space['avail']."</td></tr>\n";
echo "<tr><td>Trash:</td><td>".$space['trash']."</td></tr>\n";
echo "<tr><td>Possible:</td><td>".$space['possible']."</td></tr>\n";
echo "</body>\n";
echo "</table>\n";
echo "</table>\n";
echo "</html>\n";
} else {
if ($view != "" && $drive != "") {
$dpath = $drives[($drive-1)]."/.gh_trash";
$fpath = $dpath.$view;
$meh = split("/",$fpath);
$file = $meh[(count($meh)-1)];
$mime = mime_content_type($fpath);
http_send_content_disposition($file,true);
http_send_content_type($mime);
http_send_file($fpath);
exit();
}
if ($action == "remove" && $ext != "") {
if ($confirm != "Yes") {
echo "<h2>Removing ".$ext."</h2>\n";
if (is_dir($ext)) {
echo "Are you sure you want to recursively destroy all copies of this directory, and the files within it?<br />\n";
} else {
echo "Are you sure you want to destroy all copies of this file in the trash?<br />\n";
}
echo "This action is not reversable!<br />\n";
echo "<form method=\"GET\">\n";
echo "<input type=\"hidden\" name=\"path\" value=\"".$ext."\" />\n";
echo "<input type=\"hidden\" name=\"action\" value=\"remove\" />\n";
echo "<input type=\"submit\" name=\"confirm\" value=\"Yes\" />\n";
echo "<input type=\"button\" onclick=\"history.go(-1)\" value=\"No\" />\n";
echo "</form>\n";
} else {
foreach ($drives as $driv) {
$file = $driv."/.gh_trash".$ext;
if (is_dir($file)) {
rrmdir($file);
$removed[] = $file;
} else {
if (file_exists($file)) {
unlink($file);
$removed[] = $file;
}
}
}
if (count(@$removed) > 0) {
echo "<h2>Removed ".$ext."</h2>\n";
echo "The file has been removed from all Greyhole drives.<br />\n";
echo "<br />\n";
echo "Removed from:<br />\n";
foreach ($removed as $r) {
echo $r."<br />\n";
}
} else {
echo "No such file. Perhaps it was already removed, or you refreshed the page.<br />";
}
echo "<br />\n";
$meh = split("/",$ext);
$c = (count($meh) - 1);
$meh2 = "";
for ($i = 0; $i < $c; $i++) {
$meh2 .= $meh[$i]."/";
}
$meh2 = rtrim($meh2,"/");
echo "<a href=\"?path=".$meh2."\">Back to directory</a>";
}
}
if ($action == "restore" && $ext != "") {
$dest = "/media/share".$ext;
foreach ($drives as $driv) {
$file = $driv."/.gh_trash".$ext;
if (file_exists($file)) {
$sources[] = $file;
}
}
$meh = split("/",$ext);
$c = (count($meh) - 1);
$meh2 = "";
for ($i = 0; $i < $c; $i++) {
$meh2 .= $meh[$i]."/";
}
$meh2 = rtrim($meh2,"/");
// First one is fine
$source = @$sources[0];
// Unless its an entire folder...
if (is_dir($source)) {
foreach ($sources as $s) {
xcopy($s,$dest);
}
} elseif (file_exists($source)) {
if (!is_dir(dirname($dest))) {
mkdir(dirname($dest),0770,true);
}
copy($source,$dest);
} else {
echo "No such file. If you restored the file, it has been purged from the trash. Did you refresh the page?<br />";
}
// Delete all copies from trash after restoring
if (file_exists($dest)) {
foreach ($sources as $s) {
if (is_dir($s)) {
rrmdir($s);
}
else {
if (file_exists($s)) {
unlink($s);
}
}
}
} else {
echo "Internal error: failed to restore file. Trash untouched.\n";
echo "<br />\n";
echo "<a href=\"?path=".$meh2."\">Back to directory</a>";
exit();
}
echo "<h2>Restored ".$ext."</h2>\n";
echo "The file has been restored to the share. It will no longer appear in the trash.<br />\n";
echo "<br />\n";
echo "<a href=\"?path=".$meh2."\">Back to directory</a>";
}
}
function rrmdir($dir) {
if (is_dir($dir)) {
$objects = scandir($dir);
foreach ($objects as $object) {
if ($object != "." && $object != "..") {
if (filetype($dir."/".$object) == "dir") {
rrmdir($dir."/".$object);
} else {
unlink($dir."/".$object);
}
}
}
reset($objects);
rmdir($dir);
}
}
function xcopy($src,$dest) {
if (!is_dir($dest)) {
mkdir($dest);
}
foreach (scandir($src) as $file) {
if (!is_readable($src.'/'.$file)) continue;
if (is_dir($src.'/'.$file)) {
if (($file!='.') && ($file!='..')) {
if(!is_dir($dest.'/'.$file)) {
mkdir($dest . '/' . $file);
}
xcopy($src.'/'.$file, $dest.'/'.$file);
}
} else {
if (!file_exists($dest.'/'.$file)) {
copy($src.'/'.$file, $dest.'/'.$file);
}
}
}
}
function getSpace($friendlyBytes = false) {
$dat = `/usr/bin/greyhole-dfree`;
$dat = split(" ",$dat);
$space['total'] = $dat[0];
$space['avail'] = $dat[1];
$space['used'] = ($space['total'] - $space['avail']);
$space['trash'] = 0;
$drives = getDrives();
foreach ($drives as $d) {
$dudat = `du -sk $d/.gh_trash/`;
$space['trash'] = ($space['trash'] + $dudat);
}
$space['possible'] = ($space['avail'] + $space['trash']);
if ($friendlyBytes) {
foreach ($space as $k => $v) {
$space[$k] = friendlyBytes($v * 1024);
}
}
return $space;
}
function getDrives() {
$gh = '/etc/greyhole.conf';
$dat = "";
$fp = fopen($gh,'r');
if (!$fp) die("Access to /etc/greyhole.conf denied");
while (!feof($fp)) {
$dat .= fread($fp,128);
}
fclose($fp);
$dat = split("\n",$dat);
foreach ($dat as $l) {
if (substr($l,0,10) == "storage_po") {
$m = split(" = ",$l);
$n = split(",",$m[1]);
$drives[] = $n[0];
}
}
return $drives;
}
function friendlyBytes($size) {
// Uncomment below to enable rounding to Terabytes.
// Leave commented to function as shown in example screenshots.
// if ($size > 1099511627776) {
// return round(($size / 1099511627776),2)."TB";
// }
if ($size > 1073741824) {
return round(($size / 1073741824),2)."GB";
}
if ($size > 1048576) {
return round(($size / 1048576),2)."MB";
}
if ($size > 1024) {
return round(($size / 1024),2)."KB";
}
return $size."B";
}
Comments