This commit is contained in:
2019-04-27 00:48:25 -07:00
parent 9884d19108
commit 756ea17f99
5 changed files with 263 additions and 67 deletions

View File

@@ -3,9 +3,9 @@
// Yuba
// //
//////////////////////////////////////////
$version = "0.7.9.3";
$version = "0.7.10.3";
ini_set('memory_limit', '4096M');
ini_set('memory_limit', '10240M');
date_default_timezone_set("America/Los_Angeles");
// Includes & Prefs
@@ -62,6 +62,7 @@ foreach ($p['bundles'] as $bundle) {
// Ignore matching files and directories
$p['ignore'] = array( ".DS_Store",
".Trashes",
".DocumentRevisions-V100",
".Spotlight-V100",
".TemporaryItems",
@@ -116,7 +117,6 @@ $vdisks_parsed = $parser->parseString(utf8_for_xml($vdisks));
//print_r($vdisks_parsed);
$df = shell_exec("df 2>&1");
// old method, new method is to parse plist
//$df_volume = trim(shell_exec("df ".escapeshellarg($zpath)." | tail -n 1 | rev | cut -d' ' -f1 | rev"));
//$df_device = trim(shell_exec("df ".escapeshellarg($zpath)." | tail -n 1 | cut -d' ' -f1"));
@@ -124,7 +124,7 @@ $df = shell_exec("df 2>&1");
$df_volume = $diskutil_parsed['MountPoint'];
$df_device = "/dev/".$diskutil_parsed['ParentWholeDisk'];
$mdutil = shell_exec("mdutil -s ".$df_volume);
$mdutil = shell_exec("mdutil -sv ".$df_volume);
if (strpos($mdutil,"disabled")) {
echo msg("Warning: spotlight indexing is disabled");
$p['spotlight'] = false;
@@ -268,6 +268,7 @@ $dbo->exec("CREATE TABLE files (
stat TEXT,
items INTEGER,
newest INTEGER,
fkind TEXT,
gfi_type TEXT,
gfi_attr TEXT,
gfi_created TEXT,
@@ -767,7 +768,8 @@ $mb['i'] = array( "PixelWidth",
"FSInvisible",
"NumberOfPages",
"PageHeight",
"PageWidth" );
"PageWidth",
"TotalBitRate" );
$mb['t'] = array( "Title",
"ContentType",
@@ -863,7 +865,7 @@ foreach ($files as $splFileInfo) {
// DB
$stmt = $dbo->prepare("INSERT INTO files VALUES (:pid, :fid, :Pathname, :Path, :Filename, :Extension, :Type, :Size, :Inode, :Perms, :Owner, :ATime, :MTime, :CTime, :LinkTarget, :RealPath, :stat, :items, :newest, :gfi_type, :gfi_attr, :gfi_created, :has_exif, :has_mediainfo, :has_hash, :thumb_filename, :thumb_width, :thumb_height, :contents_filename)");
$stmt = $dbo->prepare("INSERT INTO files VALUES (:pid, :fid, :Pathname, :Path, :Filename, :Extension, :Type, :Size, :Inode, :Perms, :Owner, :ATime, :MTime, :CTime, :LinkTarget, :RealPath, :stat, :items, :newest, :fkind, :gfi_type, :gfi_attr, :gfi_created, :has_exif, :has_mediainfo, :has_hash, :thumb_filename, :thumb_width, :thumb_height, :contents_filename)");
// Identify dir, file, link or bundle dir
@@ -975,6 +977,17 @@ foreach ($files as $splFileInfo) {
// ------------------------------------------------ //
// Kind
unset($fkind);
if ($type == "file") {
$fkind = trim(shell_exec("file -b -p ".$shellpath." | cut -f1 -d,"));
$stmt->BindValue(":fkind",@$fkind);
}
// ------------------------------------------------ //
// Pool
if ($type == "file") {
@@ -1046,29 +1059,30 @@ echo ProgressBar::finish();
// Milk
//////////////////////////////////////////
$milk['t*Title'] = ["e^Title","k^Title","m^Track_name"];
$milk['t*DocTitle'] = ["e^Title","k^Title","m^Track_name"];
$milk['t*Format'] = ["m^Format","e^Compression","e^MIMEType"];
$milk['t*Dimensions'] = ["k^PixelWidth.k^PixelHeight","e^PixelWidth.e^PixelHeight","m^SkimDims"];
$milk['t*Dimensions'] = ["k^PixelWidth.k^PixelHeight","e^PixelWidth.e^PixelHeight","m^SkimDims","k^SkimPageDims"];
$milk['s*Seconds'] = ["k^DurationSeconds","e^Duration","m^Duration"];
$milk['d*DateTime'] = ["e^DateTimeOriginal","m^EncodedDate","e^CreateDate","e^MediaCreateDate","k^ContentCreationDate"];
$milk['t*Origin'] = ["e^CameraModelName","e^Producer","e^CreatorTool","e^WriterName","e^Software","e^Encoder","k^Creator"];
$milk['t*GPS'] = ["k^Latitude.k^Longitude","e^GPSPosition"];
$milk['t*Author'] = ["e^Author","e^Artist","e^Creator","e^By-line"];
$milk['t*Author'] = ["e^Author","e^Artist","e^Creator","e^By-line","k^Copyright"];
$milk['i*Tracks'] = ["m^SkimTrackCount"];
$milk['i*Tracks'] = ["m^SkimTrackCount","k^NumberOfPages"];
$milk['t*Writer'] = ["m^Writing_application.m^Writing_library"];
$milk['t*Bitrate'] = ["m^Overall_bit_rate"];
$milk['t*Bitrate'] = ["m^Overall_bit_rate","e^AvgBitrate","k^TotalBitRate"];
$milk['i*Orientation'] = ["e^Orientation"];
$milk['t*Profile'] = ["e^Profile"];
$milk['i*BitDepth'] = ["e^BitDepth"];
$milk['t*LensType'] = ["e^LensType"];
$milk['t*FocalLength'] = ["e^FocalLength"];
$milk['t*Aperture'] = ["e^Aperture"];
$milk['t*LightSource'] = ["e^LightSource"];
$milk['t*WhiteBalance'] = ["e^WhiteBalance"];
//$milk['i*Orientation'] = ["e^Orientation"];
//$milk['t*Profile'] = ["e^Profile"];
//$milk['i*BitDepth'] = ["e^BitDepth"];
//$milk['t*LensType'] = ["e^LensType"];
//$milk['t*FocalLength'] = ["e^FocalLength"];
//$milk['t*Aperture'] = ["e^Aperture"];
//$milk['t*LightSource'] = ["e^LightSource"];
//$milk['t*WhiteBalance'] = ["e^WhiteBalance"];
$delimiter = ",";
$display_delimiter = " x ";
// Build DB
@@ -1102,6 +1116,13 @@ while ($row_a = $loop->fetch()) {
$row_b = @$dbo->query("SELECT * FROM mdls WHERE (rowid='".$row_a['rowid']."')")->fetch();
if (count(@$row_b) > 1) {
$m['k'] = $row_b;
//custom values
if ($m['k']['PageWidth'] && $m['k']['PageHeight']) {
$m['k']['SkimPageDims'] = round($m['k']['PageWidth']/72,2)."in".$display_delimiter.round($m['k']['PageHeight']/72,2)."in";
}
} else {
$m['k'] = null;
}
@@ -1125,7 +1146,7 @@ while ($row_a = $loop->fetch()) {
foreach (@$decoded['File']['track'] as $track) {
if (!@$m['m']['SkimDims'] && @$track['Width'] && @$track['Height']) {
$m['m']['SkimDims'] = sanitize($track['Width'],"i").$delimiter.sanitize($track['Height'],"i");
$m['m']['SkimDims'] = sanitize($track['Width'],"i").$display_delimiter.sanitize($track['Height'],"i");
}
}

View File

@@ -1,8 +1,19 @@
<?php
// Filetypes
// 0.7.10.3
//////////////////////////////////////////
$c_files = array( "txt",
"log",
"csv",
"webloc",
"svg",
"rtf",
"rtfd",
"doc",
"docx" );
$t_files['ffmpeg'] = array( "mkv",
"avi",
"mpeg",
@@ -26,7 +37,8 @@ $t_files['sips'] = array( "jpg",
"tiff",
"gif",
"psd",
"png" );
"png",
"heic" );
$m_files = array( "mkv",
"ogg",
@@ -71,6 +83,7 @@ $e_files = array( "ai",
"flac",
"flv",
"gif",
"heic",
"icc",
"iso",
"jpg",
@@ -122,6 +135,7 @@ $e_files = array( "ai",
"xmp",
"zip" );
foreach ($c_files as $ext) { $c_files[] = strtoupper($ext); }
foreach ($e_files as $ext) { $e_files[] = strtoupper($ext); }
foreach ($m_files as $ext) { $m_files[] = strtoupper($ext); }
foreach ($t_files['ffmpeg'] as $ext) { $t_files['ffmpeg'][] = strtoupper($ext); }

View File

@@ -1,6 +1,7 @@
<?php
// Classes
// 0.7.10.3
//////////////////////////////////////////
class ProgressBar {
@@ -184,7 +185,8 @@ class plistParser extends XMLReader {
case 'false': return false; break;
case 'array': return $this->parse_array(); break;
case 'dict': return $this->parse_dict(); break;
default: throw new Exception(sprintf("Not a valid plist. %s is not a valid type", $this->name), 4);
// why the fuck cant this plist parser handle the plist generated from an hdiutil list with no dimgs attached?
//default: throw new Exception(sprintf("Not a valid plist. %s is not a valid type", $this->name), 4);
}
}
private function parse_dict() {

27
web/handle_zip.php Normal file
View File

@@ -0,0 +1,27 @@
<?
$types['txt'] = "text/plain";
$types['log'] = "text/plain";
$types['csv'] = "text/plain";
$types['webloc'] = "application/xml";
$types['svg'] = "image/svg+xml";
//$types['rtf'] = "application/rtf";
$types['rtfd'] = "application/rtf";
$types['doc'] = "application/msword";
$types['docx'] = "application/msword";
require "togggle.php";
$zip = new ZipArchive;
$zip->open($_GET['file']);
$stat = $zip->statIndex(0);
if (!$mime = $types[pathinfo($stat['name'],PATHINFO_EXTENSION)]) {
$mime = "text/plain";
}
header("Content-Type: ".$mime);
header("Content-Length: ".$stat['size']);
echo $zip->getFromIndex(0);
?>

View File

@@ -4,14 +4,14 @@
// Yuba RTC Browser
/////////////////////////////////////////////////////////////////
$browser_version = "0.7.9.2";
$browser_version = "0.7.10.3";
require "togggle.php";
require "lib/debug.php";
$db_dir = "skim";
$icon_size = 64;
$pad = 28;
$db_dir = "data/skim";
$icon_size = 96;
$pad = 40;
?>
@@ -25,10 +25,16 @@ html { font-family: Helvetica; word-wrap: break-word; }
div#exectime { position: absolute; right: 8px; top: 8px; }
div.container { display: flex; flex-flow: row wrap; justify-content: center; }
div.item { width: <?=$icon_size+$pad;?>px; height: <?=$icon_size+$pad;?>px; padding: <?=$pad;?>px; }
div.item { width: <?=$icon_size+$pad;?>px; height: <?=$icon_size+$pad;?>px; padding-bottom: <?=$pad;?> }
div.item { font-size: 11px; }
div.flexfill { width: <?=$icon_size+($pad*3);?>px; height: 1px; }
div.flexfill { width: <?=$icon_size+$pad;?>px; height: 1px; }
div.aborted { text-decoration: line-through; }
.slider, .slow_slider { position: absolute !important; top: 50px; right: 10px; width: 200px; }
.controls { position: absolute !important; top: 85px; right: 10px; width: 30px; }
form { margin-block-end: 0em !important; }
.arrow { font-size: 8px; opacity: .7; }
img.tiny { vertical-align: middle; width: 18px; height: 18px; margin: 0px 4px 0px 0px; }
.red { background-color: #ea6c60; }
.green { background-color: #9cde70; }
@@ -66,9 +72,85 @@ a.hidden img { opacity: .3; }
iframe { width: 425px; height: 550px; padding: 6px; border: 1px solid black; }
div.dblist { display: none; }
</style>
<script src="lib/lazysizes.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.4.0/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.12.1/jquery-ui.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/lazysizes/4.1.5/lazysizes.min.js"></script>
<link type="text/css" rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.12.1/jquery-ui.css">
<script type="text/javascript">
function wrapImg(xfactor) {
var maxWidth = 0;
var maxHeight = 0;
$('div.item').each(function() {
$(this).width((<?=$icon_size?>*xfactor)+<?=$pad;?>);
$(this).height((<?=$icon_size?>*xfactor)+<?=$pad;?>);
img = $(this).find('img');
swidth = $(img).data('width')*xfactor;
sheight = $(img).data('height')*xfactor;
$(img).width(swidth);
$(img).height(sheight);
fileinfo = $(this).find('div.title');
if (xfactor > 2) {
$(this).css("font-size", 16);
} else if (xfactor < .7) {
$(this).css("font-size", 9);
} else {
$(this).css("font-size", 12);
}
})
$('div.flexfill').width((<?=$icon_size?>*xfactor)+<?=$pad;?>);
}
$(function(){
$("h2").click(function(){
$(this).next('.dblist').toggle();
});
$(".toggler").click(function(){
$('.dblist').toggle();
});
$(".info").click(function(){
$('.sidebar').toggle();
});
$(".slider").slider({
step: .01,
min: .5,
max: 3,
value: 1,
slide: function(event, ui) {
wrapImg(ui.value);
},
});
$(".slow_slider").slider({
step: .25,
min: .5,
max: 3,
value: 1,
stop: function(event, ui) {
wrapImg(ui.value);
},
});
$("select").on("change", function () {
var db = $(this).val();
var href = new URL(window.location.href);
href.searchParams.set('db', db);
window.location = href;
});
});
</script>
</head>
@@ -151,7 +233,7 @@ class plistParser extends XMLReader {
case 'false': return false; break;
case 'array': return $this->parse_array(); break;
case 'dict': return $this->parse_dict(); break;
default: throw new Exception(sprintf("Not a valid plist. %s is not a valid type", $this->name), 4);
//default: throw new Exception(sprintf("Not a valid plist. %s is not a valid type", $this->name), 4);
}
}
private function parse_dict() {
@@ -191,9 +273,12 @@ function breadcrumbs($zpath, $pathname) {
}
function shortlabel($filename, $max = 40) {
$suffix = "(...).".pathinfo($filename)['extension'];
if (strlen($filename) > $max) {
$return = substr($filename, 0, ($max-strlen($suffix))).$suffix;
if (mb_strlen($filename, mb_detect_encoding($filename)) > $max) {
// more work is needed to figure out what is going on with non EN chars
//echo "(-) ";
$prefix = mb_substr($filename, 0, floor($max*.66), mb_detect_encoding($filename));
$suffix = substr($filename, -floor($max*.33));
$return = $prefix."...".$suffix;
} else {
$return = $filename;
}
@@ -220,9 +305,6 @@ $parser = new plistParser();
if ($db_file) {
echo "<a href='?db='>db list</a>";
echo "<hr>";
if (!is_readable($db_file)) { echo "can't read db file"; die; }
$dbo = new PDO("sqlite:".$db_file);
@@ -237,9 +319,10 @@ if ($db_file) {
// Check for initial view
$view = $dbo->query("SELECT * FROM _skim")->fetch();
if (!$pid) {
$pid = $dbo->query("SELECT pid FROM family WHERE (rowid=2)")->fetch()['pid'];
$view = $dbo->query("SELECT * FROM _skim")->fetch();
// handle special strings
$view['opts'] = unserialize($view['opts']);
$view['qlmanage'] = "hidden"; //array($view['qlmanage']);
@@ -264,6 +347,7 @@ if ($db_file) {
if ($view['hdiutil']) {
$view['hdiutil'] = $parser->parseString(utf8_for_xml($view['hdiutil']));
}
$view['Type'] = "dir";
} else {
$view = $dbo->query("SELECT rowid, * FROM files WHERE (pid='".$pid."')")->fetch();
if (is_serial($view['stat'])) {
@@ -272,6 +356,22 @@ if ($db_file) {
$dirmdls = $dbo->query("SELECT rowid, * FROM mdls WHERE (rowid='".$view['rowid']."')")->fetch();
}
// Header
echo "<a href='?db='><img class='tiny' src='icons/home.png'>Home</a> <span class='arrow'>&#9658; </span>";
$dbs = glob(pathinfo($_GET['db'],PATHINFO_DIRNAME)."/????-??-??_??-??-??.sqlite3");
rsort($dbs);
echo "<select>";
foreach ($dbs as $db) {
echo "<option value='".$db."'";;
if ($_GET['db'] == $db) {
echo " selected";
}
echo ">".basename($db)."</option>";
}
echo "</select>";
echo "<hr>";
// Breadcrumbs
$crumb = breadcrumbs($zpath,$view['Pathname']);
@@ -279,9 +379,14 @@ if ($db_file) {
foreach ($crumb as $myparts) {
if ($myparts[0] === null) {
$xc .= $myparts[1];
if ($view['Type'] == "dir") {
$myicon = "icons/directory.png";
} else {
$xc .= "<a href='?db=".$db_file."&pid=".$myparts[0]."'>".$myparts[1]."</a> > ";
$myicon = "icons/null.png";
}
$xc .= "<img class='tiny' src='".$myicon."'>".$myparts[1];
} else {
$xc .= "<a href='?db=".$db_file."&pid=".$myparts[0]."'><img class='tiny' src='icons/directory.png'>".$myparts[1]."</a> <span class='arrow'>&#9658;</span> ";
}
}
if (!$search) { echo $xc; echo "<hr>"; }
@@ -450,29 +555,42 @@ if ($db_file) {
} elseif (!$search) {
if (count($children) > 3000) {
echo "<div class='slow_slider'></div>";
} else {
echo "<div class='slider'></div>";
}
echo "<div class='controls'><a href='#' class='info'>info</a></div>";
echo "<table><tr><td valign='top'>";
echo "<div class='container'>";
foreach ($children as $item) {
$spotlight_status = $dbo->query("SELECT mdutil FROM _skim")->fetch()['mdutil'];
$sql = "SELECT mdls.*, files.*, milk.* FROM files ";
$sql .= "LEFT JOIN mdls ON (files.rowid = mdls.rowid) ";
$sql .= "LEFT JOIN milk ON (files.rowid = milk.rowid) ";
$sql .= "WHERE files.rowid IN (".implode(",",$children).") ";
$sql .= "ORDER BY files.Filename COLLATE NOCASE";
$rows = $dbo->query($sql)->fetchAll();
foreach ($rows as $item) {
//print_r($item);
$myname = $item['Filename'];
echo "<div class='item'>";
/////////////////////////
$row_a = $dbo->query("SELECT rowid, * FROM files WHERE (rowid='".$item."')")->fetch();
$row_b = $dbo->query("SELECT rowid, * FROM mdls WHERE (rowid='".$item."')")->fetch();
//$row_c = $dbo->query("SELECT * FROM milk WHERE (rowid='".$item."')")->fetch();
/////////////////////////
if ($row_b['FSInvisible']) {
if ($item['FSInvisible'] | substr($item['Filename'],0,1) == ".") {
$visibility = "hidden";
} else {
$visibility = "unhidden";
}
if ($row_a['thumb_filename']) {
$aspect = $row_a['thumb_width']/$row_a['thumb_height'];
if ($item['thumb_filename']) {
$aspect = $item['thumb_width']/$item['thumb_height'];
if ($aspect > 1) {
$width = $icon_size;
$height = $icon_size/$aspect;
@@ -480,35 +598,35 @@ if ($db_file) {
$width = $icon_size*$aspect;
$height = $icon_size;
}
$realfile = dirname($db_file).$row_a['thumb_filename'];
$icon = "<img id='thumb' class='lazyload' data-src='".$realfile."' width='".$width."' height='".$height."'>";
} elseif ($row_a['Type'] == "dir") {
$icon = "<img src='/icons/directory.png' width='".$icon_size."' height='".$icon_size."'>";
$realfile = dirname($db_file).$item['thumb_filename'];
$icon = "<img id='thumb' class='lazyload' data-src='".$realfile."' width='".$width."' height='".$height."' data-width='".$width."' data-height='".$height."'>";
} elseif ($item['Type'] == "dir") {
$icon = "<img src='/icons/directory.png' width='".$icon_size."' height='".$icon_size."' data-width='".$icon_size."' data-height='".$icon_size."'>";
} else {
$icon = "<img src='".findicon($row_a['Filename'])."' width='".$icon_size."' height='".$icon_size."'>";
$icon = "<img src='".findicon($item['Filename'])."' width='".$icon_size."' height='".$icon_size."' data-width='".$icon_size."' data-height='".$icon_size."'>";
}
echo "\n<a class='".$visibility."' href='?db=".$db_file."&pid=".$row_a['pid']."'>".$icon."</a>";
echo "\n<a class='".$visibility."' href='?db=".$db_file."&pid=".$item['pid']."'>".$icon."</a>";
echo "<div class='title'>";
if ($row_b['UserTags']) {
foreach (unserialize($row_b['UserTags']) as $tag) {
if ($item['UserTags']) {
foreach (unserialize($item['UserTags']) as $tag) {
echo "<span class='tag ".$tag."'></span>";
}
echo "&nbsp;";
}
echo htmlentities(shortlabel($row_a['Filename']));
echo htmlentities(shortlabel($item['Filename']));
echo "</div>";
if ($row_a['Size']) {
echo "<div class='size'>".human_filesize($row_a['Size'])."</div>";
if ($item['Size']) {
echo "<div class='size'>".human_filesize($item['Size'])."</div>";
}
if ($row_a['Type'] == "dir" && $row_a['items']) {
echo "<div class='size'>".number_format($row_a['items'])." items</div>";
if ($item['Type'] == "dir" && $item['items']) {
echo "<div class='size'>".number_format($item['items'])." items</div>";
}
echo "</div>";
@@ -518,7 +636,7 @@ if ($db_file) {
echo str_repeat("<div class='flexfill'></div>", 100);
echo "</div>";
echo "</td><td valign='top'>";
echo "</td><td valign='top' class='sidebar'>";
debug($view,$view['Pathname']);
@@ -555,13 +673,23 @@ if ($db_file) {
// DB List
echo "<a href='#' class='toggler'>toggle all</a>";
$icons['Disk image'] = "/icons/dmg.png";
$icons['Folder'] = "/icons/directory.png";
$icons['External disk'] = "/icons/firewire.png";
$icons['Startup disk'] = "/icons/internal.png";
$bundles = glob($db_dir."/*.bundle");
foreach ($bundles as $bundle) {
$exploded = explode("_", $bundle);
$sorted_bundles[$exploded[1]] = $bundle;
}
ksort($sorted_bundles);
foreach ($sorted_bundles as $key => $bundle) {
echo "<div id='bundle'>";
$dbs = array_reverse(glob($bundle."/*.sqlite3"));
array_shift($dbs);
@@ -570,7 +698,10 @@ if ($db_file) {
$type = $dbo->query("SELECT type FROM _skim")->fetch()['type'];
echo "<img id='item' src='".$icons[$type]."'>";
}
echo "<h2>".pathinfo($bundle)['filename']."</h2>";
$dbo = new PDO("sqlite:".$dbs[0]);
$info = $dbo->query("SELECT * FROM _skim")->fetch();
echo "<h2><a href='#'>".pathinfo($bundle)['filename']." (".$info['passed_total'].")</a></h2>";
echo "<div class='dblist'>";
foreach ($dbs as $db_file) {
$dbo = new PDO("sqlite:".$db_file);
$info = $dbo->query("SELECT * FROM _skim")->fetch();
@@ -590,6 +721,7 @@ if ($db_file) {
echo "</div>";
}
echo "</div>";
echo "</div>";
}
}