This commit is contained in:
2017-06-16 00:14:32 -07:00
parent 62dab3d734
commit 403c9a8efc
2 changed files with 488 additions and 119 deletions

150
Yuba.php
View File

@@ -3,20 +3,46 @@
error_reporting(E_ALL & ~E_NOTICE & ~E_WARNING); error_reporting(E_ALL & ~E_NOTICE & ~E_WARNING);
date_default_timezone_set("America/Los_Angeles"); date_default_timezone_set("America/Los_Angeles");
$time_start = microtime(true);
// Yuba // Yuba
// // // //
////////////////////////////////////////// //////////////////////////////////////////
$version = "0.3.8.1"; $version = "0.4.6";
// Stat each file before and after reading (will fail on ctime unless volume is RO) // Stat each file before and after reading (will fail on ctime unless volume is RO)
if (in_array("-paranoid", $argv)) { $wopt_paranoid = 1; } else { $wopt_paranoid = 0; } if (in_array("-paranoid", $argv)) { $wopt_paranoid = 1; } else { $wopt_paranoid = 0; }
// Do not descend into matching directories // Treat these directories as files
$wopt_nodescend = array("*.app", "*.sparsebundle", "*.Spotlight-V100", "*.fseventsd"); $wopt_bundles = array( "app",
"bundle",
"sparsebundle",
"photoslibrary",
"aplibrary",
"apvault",
"abbu",
"calendar",
"framework",
"plugin",
"kext",
"rtfd"
);
foreach ($wopt_bundles as $bundle) {
$wopt_nodescend[] = "*.".$bundle;
}
// Ignore matching files and directories // Ignore matching files and directories
$wopt_ignore = array(".DS_Store", "*.jdk"); $wopt_ignore = array( ".DS_Store",
".DocumentRevisions-V100",
".Spotlight-V100",
".TemporaryItems",
".apdisk",
".com.apple.timemachine.donotpresent",
".fseventsd",
".metadata-never-index",
".neofinder.abemeda.volinfo.xml"
);
if (in_array("-hash", $argv)) { $wopt_hash = 1; } else { $wopt_hash = 0; } if (in_array("-hash", $argv)) { $wopt_hash = 1; } else { $wopt_hash = 0; }
//$wopt_hash_limit = ""; // don't hash large files nyi //$wopt_hash_limit = ""; // don't hash large files nyi
@@ -35,8 +61,15 @@ $bin_exiftool = "/opt/local/bin/exiftool";
// Functions // Functions
function debugStat() {
global $shellpath;
echo "\n\n";
echo $shellpath." - ".chop(@shell_exec("stat -x ".$shellpath." | tail -n1"));
echo "\n\n";
}
function stringPrint($string) { function stringPrint($string) {
echo $string.str_repeat(" ", (10-strlen($string))); echo $string.@str_repeat(" ", (10-strlen($string)));
} }
function getWoptString() { function getWoptString() {
@@ -143,12 +176,11 @@ if (isset($argv[2]) && is_dir($argv[2])) {
// File checks // File checks
date_default_timezone_set("America/Los_Angeles");
$time_start = microtime(true);
$stamp = date("Y-m-d_H-i-s", time()); $stamp = date("Y-m-d_H-i-s", time());
$wopt_tmpdir = "/tmp/WalkWalk_".$stamp."/"; $wopt_tmpdir = "/tmp/WalkWalk_".$stamp."/";
if (!is_dir($wopt_tmpdir)) { mkdir($wopt_tmpdir); } if (!is_dir($wopt_tmpdir)) { mkdir($wopt_tmpdir); }
$base = preg_replace("/[^A-Za-z0-9\.]/", "_", basename($zpath)); $base = preg_replace("/[^A-Za-z0-9\.]/", "_", basename($zpath));
if (!$base) { $base = "root"; }
$dbfile = $dbprefix."/".$stamp."_".$base.".sqlite3"; $dbfile = $dbprefix."/".$stamp."_".$base.".sqlite3";
if (file_exists($dbfile)) { echo "File \"".$dbfile."\" already exists!"; die; } if (file_exists($dbfile)) { echo "File \"".$dbfile."\" already exists!"; die; }
@@ -208,12 +240,26 @@ if ($zpath == "/") {
} }
$profile = shell_exec("system_profiler SPHardwareDataType SPStorageDataType SPThunderboltDataType SPUSBDataType 2>&1"); $profile = shell_exec("system_profiler SPHardwareDataType SPStorageDataType SPThunderboltDataType SPUSBDataType 2>&1");
$qlmanage = shell_exec("qlmanage -m 2>&1");
$sysvers = shell_exec("sw_vers 2>&1");
// Database // Database
// use mysql?
//$dbo = new PDO("mysql:dbname=testdb;host=127.0.0.1", $user, $pass);
$dbo = new PDO("sqlite:".$dbfile); $dbo = new PDO("sqlite:".$dbfile);
$dbo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); $dbo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
// test: try to set values for better performance
//$dbo->query("PRAGMA page_size = 4096");
//$dbo->query("PRAGMA cache_size = 10000");
//$dbo->query("PRAGMA locking_mode = EXCLUSIVE");
//$dbo->query("PRAGMA synchronous = NORMAL");
//$dbo->query("PRAGMA journal_mode = WAL");
//$dbo->query("PRAGMA cache_size = 5000");
// end test
$dbo->exec("CREATE TABLE files ( $dbo->exec("CREATE TABLE files (
id INTEGER PRIMARY KEY, id INTEGER PRIMARY KEY,
parent INTEGER, parent INTEGER,
@@ -222,6 +268,7 @@ $dbo->exec("CREATE TABLE files (
Filename TEXT, Filename TEXT,
Extension TEXT, Extension TEXT,
Type TEXT, Type TEXT,
items INTEGER,
stat TEXT, stat TEXT,
LinkTarget TEXT, LinkTarget TEXT,
RealPath TEXT, RealPath TEXT,
@@ -265,7 +312,7 @@ $dbo->exec("CREATE TABLE thumbs (
thumb BLOB thumb BLOB
)"); )");
$dbo->exec("CREATE TABLE IF NOT EXISTS _walkwalk ( $dbo->exec("CREATE TABLE _walkwalk (
version TEXT, version TEXT,
opts TEXT, opts TEXT,
host TEXT, host TEXT,
@@ -274,13 +321,15 @@ $dbo->exec("CREATE TABLE IF NOT EXISTS _walkwalk (
nodescended INTEGER, nodescended INTEGER,
ignored INTEGER, ignored INTEGER,
stats TEXT, stats TEXT,
qlmanage TEXT,
sysvers TEXT,
diskutil TEXT, diskutil TEXT,
disks TEXT, disks TEXT,
profile TEXT, profile TEXT,
status TEXT status TEXT
)"); )");
$stmt = $dbo->prepare("INSERT INTO _walkwalk VALUES (:version, :opts, :host, :zpath, :type, :nodescended, :ignored, :stats, :diskutil, :disks, :profile, :status)"); $stmt = $dbo->prepare("INSERT INTO _walkwalk VALUES (:version, :opts, :host, :zpath, :type, :nodescended, :ignored, :stats, :qlmanage, :sysvers, :diskutil, :disks, :profile, :status)");
$stmt->BindValue(":version",$version." (".posix_getuid().")"); $stmt->BindValue(":version",$version." (".posix_getuid().")");
$stmt->BindValue(":opts",serialize(getWoptString())); $stmt->BindValue(":opts",serialize(getWoptString()));
$stmt->BindValue(":host",$host); $stmt->BindValue(":host",$host);
@@ -289,6 +338,8 @@ $stmt->BindValue(":type",$type);
$stmt->BindValue(":nodescended",null); $stmt->BindValue(":nodescended",null);
$stmt->BindValue(":ignored",null); $stmt->BindValue(":ignored",null);
$stmt->BindValue(":stats",$dstats); $stmt->BindValue(":stats",$dstats);
$stmt->BindValue(":qlmanage",$qlmanage);
$stmt->BindValue(":sysvers",$sysvers);
$stmt->BindValue(":diskutil",$diskutil); $stmt->BindValue(":diskutil",$diskutil);
$stmt->BindValue(":disks",$disks); $stmt->BindValue(":disks",$disks);
$stmt->BindValue(":profile",$profile); $stmt->BindValue(":profile",$profile);
@@ -302,12 +353,18 @@ $ignored = 0;
$files = new RecursiveIteratorIterator( $files = new RecursiveIteratorIterator(
new RecursiveCallbackFilterIterator( new RecursiveCallbackFilterIterator(
new RecursiveDirectoryIterator( new RecursiveDirectoryIterator(
$zpath, // start in parent dir to include self
dirname($zpath),
RecursiveDirectoryIterator::SKIP_DOTS RecursiveDirectoryIterator::SKIP_DOTS
), ),
function ($current, $key, $iterator) use ($wopt_ignore, $wopt_nodescend) { function ($current, $key, $iterator) use ($wopt_ignore, $wopt_nodescend) {
global $nodescended, $ignored; global $nodescended, $ignored, $zpath;
$clean = true; $clean = true;
// ensure we don't traverse zpath siblings
if ($zpath != "/" && (substr($current->getRealpath(), 0, strlen($zpath)+1) != $zpath."/") && ($current->getRealpath() != $zpath)) {
$clean = false;
}
// filenames to ignore
if (is_array($wopt_ignore)) { if (is_array($wopt_ignore)) {
foreach ($wopt_ignore as $wildcard) { foreach ($wopt_ignore as $wildcard) {
if (fnmatch($wildcard, $current->getFilename())) { if (fnmatch($wildcard, $current->getFilename())) {
@@ -317,6 +374,7 @@ $files = new RecursiveIteratorIterator(
} }
} }
} }
// directories to ignore
if (is_array($wopt_nodescend)) { if (is_array($wopt_nodescend)) {
foreach ($wopt_nodescend as $wildcard) { foreach ($wopt_nodescend as $wildcard) {
if (fnmatch($wildcard, $current->getPath())) { if (fnmatch($wildcard, $current->getPath())) {
@@ -375,7 +433,7 @@ die;
if (posix_getuid()) { if (posix_getuid()) {
echo "You are not root. Checking file readability: "; echo bashcolor("You are not root. Checking file readability: ", "red");
$oops = 0; $oops = 0;
foreach ($files as $splFileInfo) { foreach ($files as $splFileInfo) {
@@ -398,6 +456,11 @@ if (posix_getuid()) {
echo "Exiting!\n"; die; echo "Exiting!\n"; die;
} }
} }
} else {
echo bashcolor("Running as root. Some QuickLook plugins may not be available.", "red");
} }
// Filetypes for special handling // Filetypes for special handling
@@ -496,11 +559,21 @@ $e_files = array( "ai",
"xmp", "xmp",
"zip" ); "zip" );
foreach ($e_files as $ext) { $e_files[] = strtoupper($ext); }
foreach ($m_files as $ext) { $m_files[] = strtoupper($ext); }
// Inserts // Inserts
foreach ($files as $splFileInfo) { foreach ($files as $splFileInfo) {
$type = $splFileInfo->getType(); $type = $splFileInfo->getType();
if ($type == "dir") {
foreach ($wopt_bundles as $bundle) {
$check = ".".$bundle;
if (substr($splFileInfo->getFilename(), -(strlen($check)), strlen($check)) == $check) { $type = "bundle"; }
}
}
if ($type != "link") { $atime = $splFileInfo->getATime(); } if ($type != "link") { $atime = $splFileInfo->getATime(); }
$pathname = $splFileInfo->getPathname(); $pathname = $splFileInfo->getPathname();
$path = $splFileInfo->getPath(); $path = $splFileInfo->getPath();
@@ -508,6 +581,8 @@ foreach ($files as $splFileInfo) {
$extension = $splFileInfo->getExtension(); $extension = $splFileInfo->getExtension();
$shellpath = escapeshellarg($pathname); $shellpath = escapeshellarg($pathname);
debugStat();
if (!$type) { echo "\nBREAK: can't determine type of ".$pathname; die; } if (!$type) { echo "\nBREAK: can't determine type of ".$pathname; die; }
if ($type != "link") { if ($type != "link") {
@@ -516,11 +591,18 @@ foreach ($files as $splFileInfo) {
} else { } else {
$stat = null; $stat = null;
} }
echo str_replace($zpath."/","",$pathname).": "; if ($type == "dir" || $type == "bundle" ) {
$pad = 140; $items = chop(@shell_exec("find ".$shellpath." \( ! -regex '.*/\..*' \) | wc -l 2>&1"))-1;
if (strlen($pathname) < $pad) { } else {
echo str_repeat(" ",($pad-strlen($pathname))); $items = null;
}
$echolabel = basename($pathname);
echo $echolabel.": ";
$pad = 80;
if (strlen($echolabel) < $pad) {
echo str_repeat(" ",($pad-strlen($echolabel)));
} }
// Determine ID of parent dir by querying database // Determine ID of parent dir by querying database
@@ -528,13 +610,15 @@ foreach ($files as $splFileInfo) {
$parent = $dbo->query("SELECT id FROM files WHERE (Pathname='".str_replace("'", "''", $path)."')")->fetch()['id']; $parent = $dbo->query("SELECT id FROM files WHERE (Pathname='".str_replace("'", "''", $path)."')")->fetch()['id'];
stringPrint("parent"); stringPrint("parent");
debugStat();
// Gather file attributes // Gather file attributes
$stmt = $dbo->prepare("INSERT INTO files VALUES (:id, :parent, :Pathname, :Path, :Filename, :Extension, :Type, :stat, :LinkTarget, :RealPath, :Inode, :Size, :Perms, :Owner, :ATime, :MTime, :CTime, :gfi_type, :gfi_attr, :gfi_created, :hash, :tinfo)"); $stmt = $dbo->prepare("INSERT INTO files VALUES (:id, :parent, :Pathname, :Path, :Filename, :Extension, :Type, :items, :stat, :LinkTarget, :RealPath, :Inode, :Size, :Perms, :Owner, :ATime, :MTime, :CTime, :gfi_type, :gfi_attr, :gfi_created, :hash, :tinfo)");
if ($type == "dir") { if ($type == "dir") {
$size = shell_exec("du -ks ".$shellpath)*1024; $size = shell_exec("du -ks ".$shellpath)*1024;
} elseif ($type == "file") { } elseif ($type == "file" || $type == "bundle") {
$size = $splFileInfo->getSize(); $size = $splFileInfo->getSize();
} else { } else {
$size = null; $size = null;
@@ -548,6 +632,7 @@ foreach ($files as $splFileInfo) {
$stmt->BindValue(":parent",0); $stmt->BindValue(":parent",0);
} }
$stmt->BindValue(":items",@$items);
$stmt->BindValue(":stat",@$stat); $stmt->BindValue(":stat",@$stat);
$stmt->BindValue(":Pathname",$pathname); $stmt->BindValue(":Pathname",$pathname);
@@ -573,6 +658,8 @@ foreach ($files as $splFileInfo) {
} }
debugStat();
stringPrint("attr"); stringPrint("attr");
$gfiparts = explode("\n", chop(shell_exec($bin_gfi." -P ".$shellpath." 2>&1"))); $gfiparts = explode("\n", chop(shell_exec($bin_gfi." -P ".$shellpath." 2>&1")));
@@ -601,7 +688,16 @@ foreach ($files as $splFileInfo) {
} }
$thumb = $wopt_tmpdir.$filename.".png"; $thumb = $wopt_tmpdir.$filename.".png";
@exec("qlmanage -t -f ".$wopt_thumb_factor." -o ".$wopt_tmpdir." ".$shellpath." 2>&1"); /*
// insane workaround for insane apple bug
if (@pathinfo($pathname)['extension'] == "mp3" | "MP3" | "m4a" | "M4A" | "m4b" | "M4B" ) {
$zprefix = "sudo qlmanage";
} else {
$zprefix = "qlmanage";
}
*/
$zprefix = "qlmanage";
@exec($zprefix." -t -f ".$wopt_thumb_factor." -o ".$wopt_tmpdir." ".$shellpath." 2>&1");
stringPrint("thumb"); stringPrint("thumb");
if ($size && !file_exists($thumb) && (in_array($extension, $m_files) || in_array($extension, $e_files))) { if ($size && !file_exists($thumb) && (in_array($extension, $m_files) || in_array($extension, $e_files))) {
@exec("ffmpegthumbnailer -i ".$shellpath." -o \"".$thumb."\" -s ".$wopt_thumb_size." -c png 2>&1"); @exec("ffmpegthumbnailer -i ".$shellpath." -o \"".$thumb."\" -s ".$wopt_thumb_size." -c png 2>&1");
@@ -613,6 +709,8 @@ foreach ($files as $splFileInfo) {
$stmt->BindValue(":tinfo",serialize(getimagesize($thumb))); $stmt->BindValue(":tinfo",serialize(getimagesize($thumb)));
} }
debugStat();
$stmt->execute(); $stmt->execute();
stringPrint("->files"); stringPrint("->files");
@@ -628,7 +726,7 @@ foreach ($files as $splFileInfo) {
$parser = new plistParser(); $parser = new plistParser();
$spotlight = $parser->parseString($mdls); $spotlight = $parser->parseString($mdls);
$stmt->BindValue(":DateAdded",@$spotlight['kMDItemDateAdded']); $stmt->BindValue(":DateAdded",@strtotime($spotlight['kMDItemDateAdded']));
$stmt->BindValue(":ContentType",@$spotlight['kMDItemContentType']); $stmt->BindValue(":ContentType",@$spotlight['kMDItemContentType']);
$stmt->BindValue(":Creator",@$spotlight['kMDItemCreator']); $stmt->BindValue(":Creator",@$spotlight['kMDItemCreator']);
$stmt->BindValue(":Kind",@$spotlight['kMDItemKind']); $stmt->BindValue(":Kind",@$spotlight['kMDItemKind']);
@@ -677,6 +775,8 @@ foreach ($files as $splFileInfo) {
// Gather thumbnail // Gather thumbnail
debugStat();
$stmt = $dbo->prepare("INSERT INTO thumbs VALUES (:id, :thumb)"); $stmt = $dbo->prepare("INSERT INTO thumbs VALUES (:id, :thumb)");
if (file_exists($thumb) && filesize($thumb)) { if (file_exists($thumb) && filesize($thumb)) {
$stmt->BindValue(":thumb",file_get_contents($thumb)); $stmt->BindValue(":thumb",file_get_contents($thumb));
@@ -688,10 +788,10 @@ foreach ($files as $splFileInfo) {
// Set fileatime back to original value // Set fileatime back to original value
if ($type != "link" && is_writable($pathname)) { //if ($type != "link" && is_writable($pathname)) {
@exec("touch -at `date -r ".$atime." +%Y%m%d%H%M.%S` ".$shellpath." 2>&1"); // @exec("touch -at `date -r ".$atime." +%Y%m%d%H%M.%S` ".$shellpath." 2>&1");
stringPrint("touch"); // stringPrint("touch");
} // }
echo "\n"; echo "\n";

View File

@@ -4,7 +4,11 @@
// Yuba RTC Browser // Yuba RTC Browser
///////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////
$browser_version = "0.3.8"; $browser_version = "0.4.5";
date_default_timezone_set("America/Los_Angeles");
$method = "id";
?> ?>
@@ -12,40 +16,73 @@ $browser_version = "0.3.8";
<head> <head>
<meta charset="utf-8"> <meta charset="utf-8">
<meta name="viewport" content="width=device-width, user-scalable=no" />
<meta name="apple-mobile-web-app-capable" content="yes" />
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script> <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<link rel="stylesheet" href="https://ajax.googleapis.com/ajax/libs/jqueryui/1.12.1/themes/smoothness/jquery-ui.css"> <link rel="stylesheet" href="https://ajax.googleapis.com/ajax/libs/jqueryui/1.12.1/themes/smoothness/jquery-ui.css">
<script src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.js"></script> <script src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.js"></script>
<script src="https://raw.githubusercontent.com/bd808/php-unserialize-js/master/phpUnserialize.js"></script> <script src="https://raw.githubusercontent.com/bd808/php-unserialize-js/master/phpUnserialize.js"></script>
<script>
$(document).ready(function() {
$("a").contextmenu(function() {
window.location.href=$(this).attr('title');
return false;
})
})
</script>
<style> <style>
body { margin: 20px; font-family: helvetica; font-size: 11px; } body { margin: 20px; font-family: helvetica; font-size: 16px; }
*:focus { outline: none !important } *:focus { outline: none !important }
a { color: black; } a { color: black; }
div { font-size: 11px; }
div.container { display: flex; flex-flow: row wrap; justify-content: center; } div.container { display: flex; flex-flow: row wrap; justify-content: center; }
div.flexfill { width: 220px; height: 1px; } div.flexfill { width: 220px; height: 1px; }
div.item { width: 180px; height: 220px; padding: 20px; } div.item { width: 190px; height: 220px; padding: 20px; }
div.item img { margin-bottom: 20px; padding: 10px; border: 1px solid grey; } div.item img.thumb { margin-bottom: 20px; padding: 5px; border: 1px solid #e7e6dc; }
div.item img:not(.thumb) { margin-left: -10px; }
span.material { display: block; word-break:break-all; } span.material { display: block; word-break:break-all; }
span.materialsub { display: block; color: #bdbdbd; } span.materialsub { display: block; color: #bdbdbd; }
i { font-style: normal; color: red; } i { font-style: normal; color: red; }
div#spacer { display: inline; float: left; width: 5px; }
div#label { display: inline; float: left; width: 10px; height: 10px; border-radius: 50%; }
div#label.Red { background: #ef7063; }
div#label.Orange { background: #f3ad5f; }
div#label.Yellow { background: #f8d76b; }
div#label.Green { background: #9bde76; }
div#label.Blue { background: #73bcf4; }
div#label.Purple { background: #cc94e2; }
div#label.Gray { background: #a4a4a7; }
td { height: 32px; padding-left: 10px; padding-right: 10px; }
td.list { font-size: 11px; }
pre { overflow-x:scroll; }
div.item {
user-drag: none;
user-select: none;
-moz-user-select: none;
-ms-user-select: none;
-webkit-user-drag: none;
-webkit-user-select: none;
-webkit-tap-highlight-color: rgba(0,0,0,0);
}
.tooltip:hover:after{
font-size: 9px;
display: block;
unicode-bidi: embed;
font-family: monospace;
white-space: pre;
background: #333;
background: rgba(0,0,0,.8);
border-radius: 5px;
bottom: 26px;
color: #fff;
content: attr(tooltip);
right: 20%;
padding: 5px 15px;
position: absolute;
z-index: 98;
width: 500px;
}
</style> </style>
</head> </head>
@@ -53,6 +90,15 @@ i { font-style: normal; color: red; }
<? <?
$db_dir = "data/db/";
$db = $_GET['db'];
$id = $_GET['id'];
$view = $_GET['view'];
$sort = $_GET['sort'];
$db_file = $db_dir.$db.".sqlite3";
if (!$view) { $view = "icon"; }
function array_unserialize($array) { function array_unserialize($array) {
foreach ($array as $key => $string) { foreach ($array as $key => $string) {
if (substr($string, 0, 2) == "a:") { if (substr($string, 0, 2) == "a:") {
@@ -68,6 +114,14 @@ function human_filesize($bytes, $decimals = 2) {
return sprintf("%.{$decimals}f", $bytes / pow(1024, $factor)) . @$size[$factor]; return sprintf("%.{$decimals}f", $bytes / pow(1024, $factor)) . @$size[$factor];
} }
function human_date($epoch, $short = null) {
if ($short) {
return date("m/d/Y", $epoch);
} else {
return date("m/d/Y g:iA", $epoch);
}
}
function dumpme($mixed = null) { function dumpme($mixed = null) {
ob_start(); ob_start();
var_dump($mixed); var_dump($mixed);
@@ -76,34 +130,101 @@ function dumpme($mixed = null) {
return $content; return $content;
} }
function breadcrumbs($dbo, $pathname) { function hasicon($filename) {
$zpath = $dbo->query("SELECT zpath FROM _walkwalk")->fetch()['zpath']; $ext = pathinfo($filename)['extension'];
$pathname_adjusted = str_replace($zpath."/", "", $pathname); $good = "icons/null.png";
$parts = explode("/", $pathname_adjusted); foreach (glob("icons/*.png") as $file) {
$i = count($parts); if (pathinfo($file)['filename'] == $ext) {
while ($i) { $good = $file;
$search_path = $zpath."/".implode("/", array_slice($parts, 0, $i)); }
$id = $dbo->query("SELECT id FROM files WHERE (Pathname='".$search_path."')")->fetch()['id'];
$result[] = array($id, basename($search_path));
$i--;
}
$home = array("0",basename($zpath));
if (basename($zpath) == $pathname) {
return array($home);
} else {
$result[] = $home;
return array_reverse($result);
} }
return $good;
} }
$db_dir = "db/"; function makeicon($dbo, $id) {
$db = $_GET['db'];
$id = $_GET['id'];
$view = $_GET['view'];
$sort = $_GET['sort'];
$db_file = $db_dir.$db.".sqlite3";
if (!$view) { $view = "icon"; } global $db, $view, $sort;
$item = $dbo->query("SELECT * FROM files WHERE (id=".$id.")")->fetchAll()[0];
$mdls = $dbo->query("SELECT * FROM mdls WHERE (id=".$id.")")->fetchAll()[0];
if ($view == "list") {
$size = 32;
$multiplier = 8;
} else {
$size = 128;
$multiplier = 2;
}
if ($mdls['FSInvisible']) {
$diricon = "/icons/directory_invisible.png";
$fileicon = "/icons/null_invisible.png";
} elseif ($mdls['Kind'] == "Alias" || $item['Type'] == "link") {
$diricon = "/icons/directory_alias.png";
$fileicon = "/icons/null_alias.png";
} else {
$diricon = "/icons/directory.png";
$fileicon = hasicon($item['Filename']);
}
$out = "\n<a href='finder.php?db=".$db."&id=".$item['id']."&view=".$view."&sort=".$sort."'>";
$isdir = false;
if ($item['Type'] == "link") {
$target_type = $dbo->query("SELECT Type FROM files WHERE (pathname='".$item['RealPath']."')")->fetch()['Type'];
}
if ($item['Type'] == "dir" || $target_type == "dir") {
$out .= "<img src='".$diricon."' width='".$size."' height='".$size."'></a>";
} elseif (isset($item['tinfo'])) {
list ($twidth, $theight) = unserialize($item['tinfo']);
$out .= "<img src='/image.php?db=".$db."&id=".$item['id']."' width='".($twidth/$multiplier)."' height='".($theight/$multiplier)."' class='thumb'>";
} else {
$out .= "<img src='".$fileicon."' width='".$size."' height='".$size."'>";
}
$out .= "</a>";
return $out;
}
function breadcrumbs($dbo, $pathname) {
$zpath = $dbo->query("SELECT zpath FROM _walkwalk")->fetch()['zpath'];
$pathname_adjusted = str_replace($zpath."/", "", $pathname);
//echo "pathname = ".$pathname."<br>pathname_adjusted = ".$pathname_adjusted."<br>zpath = ".$zpath."<br>";
$parts = explode("/", $pathname_adjusted);
$i = count($parts);
while ($i) {
$search_path = $zpath."/".implode("/", array_slice($parts, 0, $i));
$id = $dbo->query("SELECT id FROM files WHERE (Pathname='".str_replace("'", "''", $search_path)."')")->fetch()['id'];
if ($i == count($parts)) {
$result[] = array(null, basename($search_path));
} else {
$result[] = array($id, basename($search_path));
}
$i--;
}
if ($pathname == $zpath) {
return array(array(null,basename($zpath)));
} else {
$result[] = array("1",basename($zpath));
return array_reverse($result);
}
}
// there is no db, show a list of sqlite files // there is no db, show a list of sqlite files
@@ -112,66 +233,86 @@ if (!$db) {
echo "<div class='container'>"; echo "<div class='container'>";
$files = glob($db_dir."*.sqlite3"); $files = glob($db_dir."*.sqlite3");
rsort($files); rsort($files);
foreach ($files as $file) { foreach ($files as $file) {
$dbo = new PDO("sqlite:".$file); $dbo = new PDO("sqlite:".$file);
$dbo->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC); $dbo->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);
$row = $dbo->query("SELECT * FROM _walkwalk")->fetchAll(); $row = $dbo->query("SELECT * FROM _walkwalk")->fetchAll();
if ($row[0]['type'] == "External disk") { $icon = "icons/firewire.png"; } if ($row[0]['type'] == "External disk") { $icon = "icons/firewire.png"; }
if ($row[0]['type'] == "Startup disk") { $icon = "icons/internal.png"; } if ($row[0]['type'] == "Startup disk") { $icon = "icons/internal.png"; }
if ($row[0]['type'] == "Disk image") { $icon = "icons/image.png"; } if ($row[0]['type'] == "Disk image") { $icon = "icons/image.png"; }
if ($row[0]['type'] == "Folder") { $icon = "icons/directory.png"; } if ($row[0]['type'] == "Folder") { $icon = "icons/directory.png"; }
$version = $dbo->query("SELECT version FROM _walkwalk")->fetch()['version'];
$base = basename($file,".sqlite3");
echo "\n<div class='item'>"; echo "\n<div class='item'>";
echo "\n<a href='?db=".basename($file,".sqlite3")."&view=".$view."'><img src='".$icon."' title='".$row[0]['stats']."' width='128' height='128'></a>"; echo "\n<a href='?db=".$base."&id=1&view=".$view."&sort=name'><img src='".$icon."' title='".$row[0]['stats']."' width='128' height='128'></a>";
$parts = explode("_",basename($file, ".sqlite3")); $title = substr($base, 20,strlen($base));
echo "\n<span class='material'>".$parts[2]." (".$parts[0].")</a></span>"; $date = substr($base, 0,10);
echo "\n<span class='materialsub'>".$dbo->query("SELECT Count(*) FROM files")->fetch()['Count(*)']." Files"; echo "\n<span class='material'>".$title." (".$date.")</a></span>";
if ($dbo->query("SELECT status FROM _walkwalk")->fetch()[0] == "aborted") {
if (str_replace(".","",substr($version,0,5)) > 44) {
echo "\n<span class='materialsub'>".$dbo->query("SELECT items FROM files WHERE (".$method."=1)")->fetch()['items']." items";
}
if ($dbo->query("SELECT status FROM _walkwalk")->fetch()['status'] == "aborted") {
echo " <i>(Aborted)</i>"; echo " <i>(Aborted)</i>";
} }
echo "\n<span class='materialsub'>".$version."</span>";
echo "\n</span>"; echo "\n</span>";
echo "\n</div>"; echo "\n</div>";
$dbo = null;
} }
} else { } else {
$dbo = new PDO("sqlite:".$db_file); $dbo = new PDO("sqlite:".$db_file);
$dbo->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC); $dbo->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);
$dbo->query("PRAGMA page_size = 8192");
$dbo->query("PRAGMA cache_size = 20000");
$dbo->query("PRAGMA locking_mode = EXCLUSIVE");
$dbo->query("PRAGMA synchronous = NORMAL");
$dbo->query("PRAGMA journal_mode = WAL");
$zpath = $dbo->query("SELECT zpath FROM _walkwalk")->fetch()['zpath']; $zpath = $dbo->query("SELECT zpath FROM _walkwalk")->fetch()['zpath'];
// there is no id, must be initial view
if (!$id) { $myview = $dbo->query("SELECT * FROM files WHERE (".$method."=".$id.")")->fetchAll()[0];
$type = $myview['Type'];
$id = 0;
$type = "dir";
$myview['Pathname'] = basename($zpath);
} else {
$myview = $dbo->query("SELECT * FROM files WHERE (id=".$id.")")->fetchAll()[0];
$type = $myview['Type'];
}
echo "<table width='100%'><tr><td>"; echo "<table width='100%'><tr><td>";
echo "<a href='finder.php'>&larr;</a>&nbsp;&nbsp;";
$crumb = breadcrumbs($dbo, $myview['Pathname']); $crumb = breadcrumbs($dbo, $myview['Pathname']);
foreach ($crumb as $myparts) { foreach ($crumb as $myparts) {
if ($crumb[count($crumb)-1] != $myparts) { if ($myparts[0] === null) {
echo "\n<a href='finder.php?db=".$db."&id=".$myparts[0]."&view=".$view."'>".$myparts[1]."</a>";
echo " > ";
} else {
echo $myparts[1]; echo $myparts[1];
} else {
echo "\n<a href='finder.php?db=".$db."&id=".$myparts[0]."&view=".$view."&sort=".$sort."'>".$myparts[1]."</a> > ";
} }
} }
echo "</td><td width='200'>"; echo "</td><td width='200'>";
if ($view == "icon") { if ($view == "icon") {
echo "icon | <a href='finder.php?db=".$db."&id=".$id."&view=list'>list</a>"; echo "icon | <a href='finder.php?db=".$db."&id=".$id."&view=list&sort=".$sort."'>list</a>";
} else { } else {
echo "<a href='finder.php?db=".$db."&id=".$id."&view=icon'>icon</a> | list"; echo "<a href='finder.php?db=".$db."&id=".$id."&view=icon&sort=".$sort."'>icon</a> | list";
} }
echo " | ";
echo "<select onchange=\"window.location = 'finder.php?db=".$db."&id=".$id."&view=".$view."&sort='+this.value;\">";
echo "<option value='name' "; if ($sort == "name") { echo "selected"; } echo ">name</option>";
echo "<option value='size' "; if ($sort == "size") { echo "selected"; } echo ">size</option>";
echo "<option value='modified' "; if ($sort == "modified") { echo "selected"; } echo ">modified</option>";
echo "</select>";
echo "</td></tr></table>"; echo "</td></tr></table>";
@@ -179,38 +320,41 @@ if (!$db) {
echo "<div class='container'>"; echo "<div class='container'>";
// directory view $row = $dbo->query("SELECT * FROM _walkwalk")->fetchAll();
if ($row[0]['type'] == "Startup disk") { echo "Finder.php cannot handle \"/\""; die; }
if ($type == "dir") { if ($type == "dir") {
$items = $dbo->query("SELECT * FROM files WHERE (parent=".$id.")")->fetchAll(); if ($sort == "name") { $sortby = "Filename ASC"; }
if ($sort == "size") { $sortby = "Size DESC"; }
if ($sort == "modified") { $sortby = "MTime DESC"; }
//$build = unserialize($dbo->query("SELECT children FROM patch WHERE (id=".$id.")")->fetch()['children']);
//$items = $dbo->query("SELECT * FROM files WHERE id IN (".implode(", ", $build).") ORDER BY ".$sortby)->fetchAll();
//foreach ($dbo->query("SELECT id FROM patch WHERE (parent=".$id.")")->fetchAll() as $array) { $build[] = $array['id']; }
//$items = $dbo->query("SELECT * FROM files WHERE id IN (".implode(", ", $build).") ORDER BY ".$sortby)->fetchAll();
$items = $dbo->query("SELECT * FROM files WHERE (parent=".$id.") ORDER BY ".$sortby)->fetchAll();
if ($view == "icon") { if ($view == "icon") {
foreach ($items as $item) { foreach ($items as $item) {
echo "\n<div class='item'>"; echo "\n<div class='item'>";
echo "\n<a href='finder.php?db=".$db."&id=".$item['id']."&view=".$view."' title='launch.php?db=".$db."&id=".$item['id']."'>"; echo makeicon($dbo, $item['id']);
if ($item['Type'] == "dir") { echo "\n<span class='material'>";
$tags = null;
echo "<img src='/icons/directory.png' width='128' height='128'></a>"; $tags = @unserialize($dbo->query("SELECT UserTags FROM mdls WHERE (id=".$item['id'].")")->fetch()['UserTags']);
if ($tags) {
} elseif (isset($item['tinfo'])) { foreach ($tags as $tag) {
echo "<div id='label' class='".$tag."'>&nbsp;</div>";
list ($twidth, $theight) = unserialize($item['tinfo']); }
echo "<img src='/image.php?db=".$db."&id=".$item['id']."' width='".($twidth/2)."' height='".($theight/2)."'>"; echo "<div id='spacer'>&nbsp;</div>";
} else {
echo "<img src='/icons/null.png' width='128' height='128'>";
} }
echo $item['Filename'];
echo "</a>"; if ($item['Type'] == "dir" || $item['Type'] == "bundle" ) {
echo "\n<span class='material'>".$item['Filename']; echo " (".$item['items']." Items)";
if ($item['Type'] == "dir") {
echo " (".count($dbo->query("SELECT * FROM files WHERE (parent=".$item['id'].")")->fetchAll())." Items)";
} }
echo "\n</span>"; echo "\n</span>";
echo "\n<span class='materialsub'>".human_date($item['MTime'],1)."</span>";
echo "\n<span class='materialsub'>".human_filesize($item['Size'])."</span>"; echo "\n<span class='materialsub'>".human_filesize($item['Size'])."</span>";
echo "\n</div>"; echo "\n</div>";
@@ -218,7 +362,117 @@ if (!$db) {
} else { } else {
echo "list"; ?>
<table>
<thead>
<tr>
<th>&nbsp;</th>
<th>Filename</th>
<th>Size</th>
<th>Kind</th>
<th>Items</th>
<th>Modified</th>
<th>Created</th>
<th>Added</th>
<th>Dimensions</th>
<th>Duration</th>
<th>DateTime</th>
<th>Metadata</th>
</tr>
</thead><tbody>
<?
foreach ($items as $item) {
$mdls = $dbo->query("SELECT * FROM mdls WHERE (".$method."=".$item['id'].")")->fetchAll()[0];
$meta = $dbo->query("SELECT * FROM metadata WHERE (".$method."=".$item['id'].")")->fetchAll()[0];
$etool = null;
$minfo = null;
$sinfo = @unserialize($mdls['spotlight']);
$etool = @unserialize($meta['exiftool']);
$minfo = @unserialize($meta['mediainfo']);
$build = array();
$build[] = makeicon($dbo, $item['id']);
$subbuild = array();
if ($tags) {
foreach ($tags as $tag) {
$subbuild[] = "<div id='label' class='".$tag."'>&nbsp;</div>";
}
$subbuild[] = "<div id='spacer'>&nbsp;</div>";
}
$subbuild[] = $item['Filename'];
$build[] = implode($subbuild);
$build[] = human_filesize($item['Size']);
$kind = null;
if ($mdls['Kind']) {
$kind = $mdls['Kind'];
} elseif ($item['gfi_type']) {
$kind = $item['gfi_type'];
} elseif ($mdls['Kind'] == "Alias") {
$kind = "Alias";
} else {
$kind = ucfirst($item['Type']);
}
$build[] = $kind;
$build[] = $item['items'];
$build[] = @human_date($item['MTime']);
$build[] = @human_date($item['gfi_created']);
$build[] = @human_date($mdls['DateAdded']);
if ($mdls['PixelWidth']) {
$build[] = $mdls['PixelWidth']." x ".$mdls['PixelHeight']." pixels";
} elseif ($etool[0]['ImageWidth']) {
$build[] = $etool[0]['ImageWidth']." x ".$etool[0]['ImageHeight']." pixels";
} elseif ($sinfo['kMDItemPageWidth']) {
$build[] = round($sinfo['kMDItemPageWidth'],2)." x ".round($sinfo['kMDItemPageHeight'], 2)." points";
} else {
$build[] = "";
}
$duration = null;
if ($meta['duration']) {
$duration = $meta['duration'];
} elseif ($etool[0]['MediaDuration']) {
$duration = $etool[0]['MediaDuration'];
}
$build[] = $duration;
$dto = null;
if ($etool[0]['DateTimeOriginal']) {
$dto = @human_date(strtotime($etool[0]['DateTimeOriginal']));
}
$build[] = $dto;
$subbuild = array();
if ($minfo) {
$subbuild[] = "<a tooltip='".str_replace("'", "&#39;",htmlentities(dumpme($minfo)))."' class='tooltip'>[M]</a>";
}
if ($etool) {
$subbuild[] = "<a tooltip='".str_replace("'", "&#39;",htmlentities(dumpme($etool)))."' class='tooltip'>[E]</a>";
}
$build[] = implode(" ", $subbuild);
echo "<tr>";
foreach ($build as $piece) {
echo "<td class='list'>".$piece."</td>";
}
echo "</tr>";
}
echo "</tbody></table>";
} }
@@ -229,15 +483,19 @@ if (!$db) {
echo "<pre>"; echo "<pre>";
$fdeep = $dbo->query("SELECT * FROM files WHERE (id=".$id.")")->fetchAll()[0]; $fdeep = $dbo->query("SELECT * FROM files WHERE (id=".$id.")")->fetchAll()[0];
$sdeep = $mdls = $dbo->query("SELECT * FROM mdls WHERE (id=".$id.")")->fetchAll()[0]; $sdeep = $dbo->query("SELECT * FROM mdls WHERE (id=".$id.")")->fetchAll()[0];
$mdeep = $meta = $dbo->query("SELECT * FROM metadata WHERE (id=".$id.")")->fetchAll()[0]; $mdeep = $dbo->query("SELECT * FROM metadata WHERE (id=".$id.")")->fetchAll()[0];
echo "<h1>".$fdeep['Pathname']."</h1><hr>"; echo "<h1>".$fdeep['Pathname']."</h1><hr>";
echo "<textarea rows='1' cols='100'>file://".$fdeep['Pathname']."</textarea>";
echo "<textarea rows='1' cols='100'>show ".escapeshellarg($fdeep['Pathname'])."</textarea>";
echo "<textarea rows='1' cols='40'>".$fdeep['hash']."</textarea><br><br>";
if (isset($fdeep['tinfo'])) { if (isset($fdeep['tinfo'])) {
echo "<img src='/image.php?db=".$db."&id=".$id."' width='".$twidth."' height='".$theight."'><br>"; echo "<img src='/image.php?db=".$db."&id=".$id."' width='".$twidth."' height='".$theight."' class='thumb'><br><br>";
} else { } else {
echo "<img src='/icons/null.png' width='128' height='128'><br>"; echo "<img src='/icons/null.png' width='128' height='128'><br><br>";
} }
echo dumpme(array_unserialize($fdeep)); echo dumpme(array_unserialize($fdeep));
@@ -254,8 +512,19 @@ if (!$db) {
echo str_repeat("<div class='flexfill'></div>", 100); echo str_repeat("<div class='flexfill'></div>", 100);
echo "</div>";
if ($type == "dir") {
echo "<hr>";
echo count($dbo->query("SELECT * FROM files WHERE (parent=".$id.")")->fetchAll())." Items, ";
echo human_filesize($dbo->query("SELECT Size FROM files WHERE (id=".$id.")")->fetch()['Size']);
}
echo " ~ ".round(microtime(true)-$_SERVER["REQUEST_TIME_FLOAT"],2)." seconds";
$dbo = null;
?> ?>
</div>
</body> </body>
</html> </html>