This commit is contained in:
2017-05-25 15:38:19 -07:00
parent 2ad83fcb34
commit 62dab3d734
67 changed files with 747 additions and 118 deletions

583
Yuba.php
View File

@@ -1,11 +1,135 @@
#!/usr/bin/php
<?php
error_reporting(E_ALL & ~E_NOTICE & ~E_WARNING);
date_default_timezone_set("America/Los_Angeles");
// Yuba
// //
//////////////////////////////////////////
$version = "0.2.1";
$thumb_size = "256";
$thumb_factor = $thumb_size/128;
$version = "0.3.8.1";
// 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; }
// Do not descend into matching directories
$wopt_nodescend = array("*.app", "*.sparsebundle", "*.Spotlight-V100", "*.fseventsd");
// Ignore matching files and directories
$wopt_ignore = array(".DS_Store", "*.jdk");
if (in_array("-hash", $argv)) { $wopt_hash = 1; } else { $wopt_hash = 0; }
//$wopt_hash_limit = ""; // don't hash large files nyi
//$wopt_mediainfo = 1; // not yet implemented
//$wopt_exiftool = 1; // not yet implemented
//$wopt_thumb = 1; // not yet implemented
$wopt_thumb_size = "256";
$wopt_thumb_factor = $wopt_thumb_size/128;
// Location of binaries used to collect metadata
$bin_gfi = "/Applications/Xcode.app/Contents/Developer/usr/bin/GetFileInfo";
$bin_mediainfo = "/opt/local/bin/mediainfo";
$bin_exiftool = "/opt/local/bin/exiftool";
// Functions
function stringPrint($string) {
echo $string.str_repeat(" ", (10-strlen($string)));
}
function getWoptString() {
global $wopt_nodescend, $wopt_ignore, $wopt_hash, $wopt_mediainfo, $wopt_exiftool, $wopt_thumb_size, $wopt_thumb_factor, $wopt_tmpdir, $wopt_paranoid;
return array( array("nodescend", $wopt_nodescend),
array("ignore", $wopt_ignore),
array("hash", $wopt_hash),
array("mediainfo", $wopt_mediainfo),
array("exiftool", $wopt_exiftool),
array("thumb_size", $wopt_thumb_size),
array("thumb_factor", $wopt_thumb_factor),
array("wopt_paranoid", $wopt_paranoid)
);
}
class plistParser extends XMLReader {
public function parseString($string) { $this->XML($string); return $this->process(); }
private function process() {
$this->read();
if($this->nodeType !== XMLReader::DOC_TYPE || $this->name !== "plist") { throw new Exception(sprintf("Error parsing plist. nodeType: %d -- Name: %s", $this->nodeType, $this->name), 2); }
if(!$this->next("plist") || $this->nodeType !== XMLReader::ELEMENT || $this->name !== "plist") { throw new Exception(sprintf("Error parsing plist. nodeType: %d -- Name: %s", $this->nodeType, $this->name), 3); }
$plist = array(); while($this->read()) { if($this->nodeType == XMLReader::ELEMENT) { $plist[] = $this->parse_node(); } }
if(count($plist) == 1 && $plist[0]) { return $plist[0]; } else { return $plist; }
}
private function parse_node() {
if($this->nodeType !== XMLReader::ELEMENT) return;
switch($this->name) {
case 'data': return base64_decode($this->getNodeText()); break;
case 'real': return floatval($this->getNodeText()); break;
case 'string': return $this->getNodeText(); break;
case 'integer': return intval($this->getNodeText()); break;
case 'date': return $this->getNodeText(); break;
case 'true': return true; break;
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);
}
}
private function parse_dict() {
$array = array(); $this->nextOfType(XMLReader::ELEMENT);
do { if($this->nodeType !== XMLReader::ELEMENT || $this->name !== "key") { if(!$this->next("key")) { return $array; } } $key = $this->getNodeText(); $this->nextOfType(XMLReader::ELEMENT); $array[$key] = $this->parse_node(); $this->nextOfType(XMLReader::ELEMENT, XMLReader::END_ELEMENT); }
while($this->nodeType && !$this->isNodeOfTypeName(XMLReader::END_ELEMENT, "dict")); return $array;
}
private function parse_array() {
$array = array(); $this->nextOfType(XMLReader::ELEMENT);
do { $array[] = $this->parse_node(); $this->nextOfType(XMLReader::ELEMENT, XMLReader::END_ELEMENT); }
while($this->nodeType && !$this->isNodeOfTypeName(XMLReader::END_ELEMENT, "array")); return $array;
}
private function getNodeText() { $string = $this->readString(); $this->nextOfType(XMLReader::END_ELEMENT); return $string; }
private function nextOfType() { $types = func_get_args(); $this->read(); while($this->nodeType && !(in_array($this->nodeType, $types))) { $this->read(); } }
private function isNodeOfTypeName($type, $name) { return $this->nodeType === $type && $this->name === $name; }
}
function parseMediaInfo ($xml) {
$xml = simplexml_load_string($xml);
$data = array();
$data['version'] = (string) $xml['version'];
foreach ($xml->File->track as $track) {
$trackType = strtolower($track['type']);
$trackId = isset($track['streamid']) ? $track['streamid'] : 1;
$trackId = (string)$trackId;
$trackData = [];
foreach ($track as $rawKey => $rawVal) {
$key = strtolower($rawKey);
$val = (string)$rawVal;
if ($key == 'stream_identifier') { continue; }
if (!array_key_exists($key, $trackData)) {
$trackData[$key] = array($val);
} elseif (!in_array($val, $trackData[$key])) {
$trackData[$key][] = $val;
}
}
if ($trackType == 'general') {
$data['file']['general'] = $trackData;
} else {
$data['file'][$trackType][$trackId] = $trackData;
}
}
return $data;
}
function bashcolor($str,$fgcolor="white",$bgcolor=null) {
static $fgcolors = array('black' => '0;30', 'dark gray' => '1;30', 'blue' => '0;34', 'light blue' => '1;34', 'green' => '0;32', 'light green' => '1;32', 'cyan' => '0;36', 'light cyan' => '1;36', 'red' => '0;31', 'light red' => '1;31', 'purple' => '0;35', 'light purple' => '1;35', 'brown' => '0;33', 'yellow' => '1;33', 'light gray' => '0;37', 'white' => '1;37', 'underline' => '4');
static $bgcolors = array('black' => '40', 'red' => '41', 'green' => '42', 'yellow' => '43', 'blue' => '44', 'magenta' => '45', 'cyan' => '46', 'light gray' => '47');
$out="";
if (!isset($fgcolors[$fgcolor])) { $fgcolor='white'; }
if (!isset($bgcolors[$bgcolor])) { $bgcolor=null; }
if ($fgcolor) { $out .= "\033[{$fgcolors[$fgcolor]}m"; }
if ($bgcolor) { $out .= "\033[{$bgcolors[$bgcolor]}m"; }
$out .= $str."\033[0m";
return $out;
}
// Path arguments
@@ -22,8 +146,8 @@ if (isset($argv[2]) && is_dir($argv[2])) {
date_default_timezone_set("America/Los_Angeles");
$time_start = microtime(true);
$stamp = date("Y-m-d_H-i-s", time());
$tmpdir = "/tmp/WalkWalk_".$stamp."/";
if (!is_dir($tmpdir)) { mkdir($tmpdir); }
$wopt_tmpdir = "/tmp/WalkWalk_".$stamp."/";
if (!is_dir($wopt_tmpdir)) { mkdir($wopt_tmpdir); }
$base = preg_replace("/[^A-Za-z0-9\.]/", "_", basename($zpath));
$dbfile = $dbprefix."/".$stamp."_".$base.".sqlite3";
if (file_exists($dbfile)) { echo "File \"".$dbfile."\" already exists!"; die; }
@@ -90,62 +214,163 @@ $profile = shell_exec("system_profiler SPHardwareDataType SPStorageDataType SPTh
$dbo = new PDO("sqlite:".$dbfile);
$dbo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$dbo->exec("CREATE TABLE IF NOT EXISTS \"".$base."\" (
$dbo->exec("CREATE TABLE files (
id INTEGER PRIMARY KEY,
parent INTEGER,
path TEXT,
ext TEXT,
type TEXT,
size INTEGER,
Pathname TEXT,
Path TEXT,
Filename TEXT,
Extension TEXT,
Type TEXT,
stat TEXT,
LinkTarget TEXT,
RealPath TEXT,
Inode INTEGER,
Size INTEGER,
Perms INTEGER,
Owner TEXT,
ATime INTEGER,
MTime INTEGER,
CTime INTEGER,
gfi_type TEXT,
gfi_attr TEXT,
gfi_created TEXT,
hash TEXT,
perms INTEGER,
owner TEXT,
inode INTEGER,
mtime INTEGER,
atime INTEGER,
ctime INTEGER,
mdls TEXT,
tags TEXT,
mediainfo TEXT,
exiftool TEXT,
tinfo TEXT)");
tinfo TEXT
)");
$dbo->exec("CREATE TABLE IF NOT EXISTS thumbs (
$dbo->exec("CREATE TABLE mdls (
id INTEGER PRIMARY KEY,
thumb BLOB)");
hasmeta INTEGER,
DateAdded TEXT,
ContentType TEXT,
Creator TEXT,
Kind TEXT,
UserTags TEXT,
FSInvisible INTEGER,
PixelWidth INTEGER,
PixelHeight INTEGER,
spotlight TEXT
)");
$dbo->exec("CREATE TABLE metadata (
id INTEGER PRIMARY KEY,
duration TEXT,
mediainfo TEXT,
exiftool TEXT
)");
$dbo->exec("CREATE TABLE thumbs (
id INTEGER PRIMARY KEY,
thumb BLOB
)");
$dbo->exec("CREATE TABLE IF NOT EXISTS _walkwalk (
version TEXT,
opts TEXT,
host TEXT,
zpath TEXT,
type TEXT,
nodescended INTEGER,
ignored INTEGER,
stats TEXT,
diskutil TEXT,
disks TEXT,
profile TEXT)");
profile TEXT,
status TEXT
)");
$insert = "INSERT INTO _walkwalk VALUES (:version, :host, :zpath, :type, :stats, :diskutil, :disks, :profile)";
$stmt = $dbo->prepare($insert);
$stmt = $dbo->prepare("INSERT INTO _walkwalk VALUES (:version, :opts, :host, :zpath, :type, :nodescended, :ignored, :stats, :diskutil, :disks, :profile, :status)");
$stmt->BindValue(":version",$version." (".posix_getuid().")");
$stmt->BindValue(":opts",serialize(getWoptString()));
$stmt->BindValue(":host",$host);
$stmt->BindValue(":zpath",$zpath);
$stmt->BindValue(":type",$type);
$stmt->BindValue(":nodescended",null);
$stmt->BindValue(":ignored",null);
$stmt->BindValue(":stats",$dstats);
$stmt->BindValue(":diskutil",$diskutil);
$stmt->BindValue(":disks",$disks);
$stmt->BindValue(":profile",$profile);
$stmt->BindValue(":status","aborted");
$stmt->execute();
// Iterate
$dir_iter = new RecursiveDirectoryIterator($zpath,
RecursiveDirectoryIterator::SKIP_DOTS
);
$iter = new RecursiveIteratorIterator($dir_iter,
RecursiveIteratorIterator::SELF_FIRST,
RecursiveIteratorIterator::CATCH_GET_CHILD
);
$nodescended = 0;
$ignored = 0;
$files = new RecursiveIteratorIterator(
new RecursiveCallbackFilterIterator(
new RecursiveDirectoryIterator(
$zpath,
RecursiveDirectoryIterator::SKIP_DOTS
),
function ($current, $key, $iterator) use ($wopt_ignore, $wopt_nodescend) {
global $nodescended, $ignored;
$clean = true;
if (is_array($wopt_ignore)) {
foreach ($wopt_ignore as $wildcard) {
if (fnmatch($wildcard, $current->getFilename())) {
$clean = false;
$ignored++;
echo "\nSkipping: ".$current->getRealpath()."\n\n";
}
}
}
if (is_array($wopt_nodescend)) {
foreach ($wopt_nodescend as $wildcard) {
if (fnmatch($wildcard, $current->getPath())) {
$clean = false;
$nodescended++;
echo "\nNodescending: ".$current->getRealpath()."\n\n";
}
}
}
return $clean;
}
),
RecursiveIteratorIterator::SELF_FIRST,
RecursiveIteratorIterator::CATCH_GET_CHILD
);
// Debug input array
/*
foreach ($files as $splFileInfo) {
echo "====================================================================================\n";
print_r($splFileInfo);
echo "====================================================================================\n";
echo "getRealPath = ".$splFileInfo->getRealPath()."\n";
echo "getPathname = ".$splFileInfo->getPathname()."\n";
echo "isLink = ".$splFileInfo->isLink()."\n";
if ($splFileInfo->isLink()) {
echo "getLinkTarget = ".$splFileInfo->getLinkTarget()."\n";
} else {
echo "getLinkTarget = N/A\n";
}
echo "getType = ".$splFileInfo->getType()." (".filetype($splFileInfo->getPathname()).")\n";
echo "isDir = ".$splFileInfo->isDir()."\n";
echo "isFile = ".$splFileInfo->isFile()."\n";
echo "-----------------------------------------------------------------------\n";
echo "getPath = ".$splFileInfo->getPath()."\n";
echo "getFilename = ".$splFileInfo->getFilename()."\n";
echo "getBasename = ".$splFileInfo->getBasename()." (".basename($splFileInfo->getPathname()).")\n";
echo "getExtension = ".$splFileInfo->getExtension()."\n";
echo "-----------------------------------------------------------------------\n";
if (!$splFileInfo->isLink()) {
echo "getATime = ".$splFileInfo->getAtime()." (".fileatime($splFileInfo->getPathname()).")\n";
echo "getMTime = ".$splFileInfo->getMtime()." (".filemtime($splFileInfo->getPathname()).")\n";
echo "getCTime = ".$splFileInfo->getCtime()." (".filectime($splFileInfo->getPathname()).")\n";
echo "getInode = ".$splFileInfo->getInode()." (".fileinode($splFileInfo->getPathname()).")\n";
echo "getPerms = ".$splFileInfo->getPerms()." (".fileperms($splFileInfo->getPathname()).")\n";
echo "getGroup = ".$splFileInfo->getGroup()." (".filegroup($splFileInfo->getPathname()).")\n";
echo "getOwner = ".$splFileInfo->getOwner()." (".fileowner($splFileInfo->getPathname()).")\n";
echo "getSize = ".$splFileInfo->getSize()." (".filesize($splFileInfo->getPathname()).")\n";
}
}
die;
*/
// Check perms
if (posix_getuid()) {
@@ -153,7 +378,7 @@ if (posix_getuid()) {
echo "You are not root. Checking file readability: ";
$oops = 0;
foreach ($iter as $splFileInfo) {
foreach ($files as $splFileInfo) {
$path = $splFileInfo->getRealPath();
if (!is_readable($path)) {
$oops = 1;
@@ -175,7 +400,7 @@ if (posix_getuid()) {
}
}
// Filetypes
// Filetypes for special handling
$m_files = array( "mkv",
"ogg",
@@ -271,104 +496,226 @@ $e_files = array( "ai",
"xmp",
"zip" );
// Insert
// Inserts
foreach ($iter as $splFileInfo) {
$path = $splFileInfo->getRealPath();
echo $path.": ";
$line = array();
$info = pathinfo($path);
$select = "SELECT id from \"".$base."\" WHERE (path=\"".$info['dirname']."\")";
$slct = $dbo->query($select);
$row = $slct->fetchObject();
if (@$row->id) {
$line['parent'] = $row->id;
foreach ($files as $splFileInfo) {
$type = $splFileInfo->getType();
if ($type != "link") { $atime = $splFileInfo->getATime(); }
$pathname = $splFileInfo->getPathname();
$path = $splFileInfo->getPath();
$filename = $splFileInfo->getFilename();
$extension = $splFileInfo->getExtension();
$shellpath = escapeshellarg($pathname);
if (!$type) { echo "\nBREAK: can't determine type of ".$pathname; die; }
if ($type != "link") {
$stat = chop(@shell_exec("stat -x ".$shellpath." 2>&1"));
if ($wopt_paranoid && !$atime) { echo "\nBREAK: Cannot determine atime of ".$pathname; die; }
} else {
$line['parent'] = 0;
$stat = null;
}
$line['path'] = $path;
$line['ext'] = strtolower(@$info['extension']);
$line['type'] = filetype($path);
if ($line['type'] == "dir") {
$line['size'] = @shell_exec("du -ks \"".$path."\"")*1024;
echo str_replace($zpath."/","",$pathname).": ";
$pad = 140;
if (strlen($pathname) < $pad) {
echo str_repeat(" ",($pad-strlen($pathname)));
}
// Determine ID of parent dir by querying database
$parent = $dbo->query("SELECT id FROM files WHERE (Pathname='".str_replace("'", "''", $path)."')")->fetch()['id'];
stringPrint("parent");
// 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)");
if ($type == "dir") {
$size = shell_exec("du -ks ".$shellpath)*1024;
} elseif ($type == "file") {
$size = $splFileInfo->getSize();
} else {
$line['size'] = filesize($path);
$size = null;
}
echo floor($line['size']/1024)."k; ";
$line['hash'] = md5_file($path);
echo "hashed; ";
$line['perms'] = fileperms($path);
$line['owner'] = fileowner($path).":".filegroup($path);
$line['inode'] = fileinode($path);
$line['mtime'] = filemtime($path);
$line['atime'] = fileatime($path);
$line['ctime'] = filectime($path);
echo "perms; ";
$spotlight = shell_exec("mdls \"".$path."\" 2>&1");
if ($spotlight != $path.": could not find ".$path.".\n") {
$line['mdls'] = $spotlight;
if (strpos($spotlight, "kMDItemUserTags")) {
$jlines = array_slice(explode("\n", @shell_exec("mdls -name kMDItemUserTags -raw \"".$path."\" 2>&1")), 1, -1);
$colors = array();
foreach ($jlines as $jline) {
$colors[] = chop($jline,",");
}
$line['tags'] = serialize($colors);
$stmt->BindValue(":Size",@$size);
stringPrint(floor($size/1024)."k");
if ($parent) {
$stmt->BindValue(":parent",$parent);
} else {
$stmt->BindValue(":parent",0);
}
$stmt->BindValue(":stat",@$stat);
$stmt->BindValue(":Pathname",$pathname);
$stmt->BindValue(":Path",$path);
$stmt->BindValue(":Filename",$filename);
$stmt->BindValue(":Extension",$extension);
$stmt->BindValue(":Type",$type);
if ($type == "link") {
$stmt->BindValue(":LinkTarget",$splFileInfo->getLinkTarget());
$stmt->BindValue(":RealPath",$splFileInfo->getRealPath());
} else {
$stmt->BindValue(":Inode",$splFileInfo->getInode());
$stmt->BindValue(":Perms",$splFileInfo->getPerms());
$stmt->BindValue(":Owner",$splFileInfo->getOwner().":".$splFileInfo->getGroup());
$stmt->BindValue(":ATime",$atime);
$stmt->BindValue(":CTime",$splFileInfo->getCTime());
$stmt->BindValue(":MTime",$splFileInfo->getMTime());
}
stringPrint("attr");
$gfiparts = explode("\n", chop(shell_exec($bin_gfi." -P ".$shellpath." 2>&1")));
if (is_array($gfiparts)) {
foreach ($gfiparts as $line) {
list($label, $value) = explode(": ", $line);
$gfi[$label] = isset($value) ? trim($value,"\"") : null;
}
}
echo "mdls; ";
$thumb = $tmpdir.basename($path).".png";
@exec("qlmanage -t -f ".$thumb_factor." -o ".$tmpdir." \"".$path."\" 2>&1");
if (!file_exists($thumb) && (in_array($line['ext'], $m_files) | in_array($line['ext'], $e_files))) {
@exec("ffmpegthumbnailer -i \"".$path."\" -o \"".$thumb."\" -s ".$thumb_size." -c png 2>&1");
echo "ffmpeg-";
$writegfitype = @$gfi['type'].":".@$gfi['creator'];
if ($writegfitype == "\\0\\0\\0\\0:\\0\\0\\0\\0" || $writegfitype == ":") { $writegfitype = null; }
$stmt->BindValue("gfi_type",$writegfitype);
$stmt->BindValue("gfi_attr",@$gfi['attributes']);
$stmt->BindValue("gfi_created",strtotime($gfi['created']));
stringPrint("gfi");
if ($wopt_hash && $type != "link") {
$stmt->BindValue(":hash",md5_file($pathname));
StringPrint("hash");
} else {
$stmt->BindValue(":hash",null);
StringPrint("(x)hash");
}
$thumb = $wopt_tmpdir.$filename.".png";
@exec("qlmanage -t -f ".$wopt_thumb_factor." -o ".$wopt_tmpdir." ".$shellpath." 2>&1");
stringPrint("thumb");
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");
stringPrint("fthumb");
} else {
stringPrint("(x)fthumb");
}
if (file_exists($thumb) && filesize($thumb)) {
$line['thumb'] = file_get_contents($thumb);
$line['tinfo'] = serialize(getimagesize($thumb));
$stmt->BindValue(":tinfo",serialize(getimagesize($thumb)));
}
echo "thumb; ";
if ($line['ext'] && in_array($line['ext'], $m_files)) {
$line['mediainfo'] = shell_exec("mediainfo \"".$path."\" 2>&1");
}
echo "media; ";
if ($line['ext'] && in_array($line['ext'], $e_files)) {
$line['exiftool'] = shell_exec("exiftool \"".$path."\" 2>&1");
}
echo "exif ";
$insert = "INSERT INTO \"".$base."\" VALUES (:id, :parent, :path, :ext, :type, :size, :hash, :perms, :owner, :inode, :mtime, :atime, :ctime, :mdls, :tags, :mediainfo, :exiftool, :tinfo)";
$stmt = $dbo->prepare($insert);
$stmt->BindValue(":parent",$line['parent']);
$stmt->BindValue(":path",$line['path']);
$stmt->BindValue(":ext",$line['ext']);
$stmt->BindValue(":type",$line['type']);
$stmt->BindValue(":size",$line['size']);
$stmt->BindValue(":hash",$line['hash']);
$stmt->BindValue(":perms",$line['perms']);
$stmt->BindValue(":owner",$line['owner']);
$stmt->BindValue(":inode",$line['inode']);
$stmt->BindValue(":mtime",$line['mtime']);
$stmt->BindValue(":atime",$line['atime']);
$stmt->BindValue(":ctime",$line['ctime']);
$stmt->BindValue(":mdls",$line['mdls']);
$stmt->BindValue(":tags",@$line['tags']);
$stmt->BindValue(":mediainfo",@$line['mediainfo']);
$stmt->BindValue(":exiftool",@$line['exiftool']);
$stmt->BindValue(":tinfo",@$line['tinfo']);
$stmt->execute();
echo "-> sql";
$insert = "INSERT INTO thumbs VALUES (:id, :thumb)";
$stmt = $dbo->prepare($insert);
$stmt->BindValue(":thumb",@$line['thumb']);
$stmt->execute();
if (@$line['thumb']) {
echo " (thumb)";
stringPrint("->files");
// Gather spotlight metadata
$stmt = $dbo->prepare("INSERT INTO mdls VALUES (:id, :hasmeta, :DateAdded, :ContentType, :Creator, :Kind, :UserTags, :FSInvisible, :PixelWidth, :PixelHeight, :spotlight)");
$mdls = shell_exec("mdls -plist - ".$shellpath." 2>&1");
stringPrint("mdls");
if ($mdls != $pathname.": could not find ".$pathname.".\n") {
$stmt->BindValue(":hasmeta",1);
$parser = new plistParser();
$spotlight = $parser->parseString($mdls);
$stmt->BindValue(":DateAdded",@$spotlight['kMDItemDateAdded']);
$stmt->BindValue(":ContentType",@$spotlight['kMDItemContentType']);
$stmt->BindValue(":Creator",@$spotlight['kMDItemCreator']);
$stmt->BindValue(":Kind",@$spotlight['kMDItemKind']);
if (isset($spotlight['kMDItemUserTags'])) {
$stmt->BindValue(":UserTags",serialize($spotlight['kMDItemUserTags']));
}
$stmt->BindValue(":FSInvisible",@$spotlight['kMDItemFSInvisible']);
$stmt->BindValue(":PixelWidth",@$spotlight['kMDItemPixelWidth']);
$stmt->BindValue(":PixelHeight",@$spotlight['kMDItemPixelHeight']);
$stmt->BindValue(":spotlight",serialize($spotlight));
} else {
$stmt->BindValue(":hasmeta",0);
}
$stmt->execute();
stringPrint("->mdls");
// Gather external metadata
$stmt = $dbo->prepare("INSERT INTO metadata VALUES (:id, :duration, :mediainfo, :exiftool)");
if ($type != "dir" && in_array($extension, $m_files)) {
$minfo = parseMediaInfo(shell_exec($bin_mediainfo." --Output=XML ".$shellpath." 2>&1"));
if ($minfo['file']['general']['duration'][0]) {
$stmt->BindValue(":duration",$minfo['file']['general']['duration'][0]);
} else {
$stmt->BindValue(":duration",null);
}
$stmt->BindValue(":mediainfo",serialize($minfo));
stringPrint("minfo");
} else {
$stmt->BindValue(":duration",null);
$stmt->BindValue(":mediainfo",null);
stringPrint("(x)info");
}
if ($type != "dir" && $type != "link" && in_array($extension, $e_files)) {
$stmt->BindValue(":exiftool",serialize(eval("return ".`$bin_exiftool -php $shellpath`)));
stringPrint("etool");
} else {
$stmt->BindValue(":exiftool",null);
stringPrint("(x)etool");
}
$stmt->execute();
stringPrint("->meta");
// Gather thumbnail
$stmt = $dbo->prepare("INSERT INTO thumbs VALUES (:id, :thumb)");
if (file_exists($thumb) && filesize($thumb)) {
$stmt->BindValue(":thumb",file_get_contents($thumb));
} else {
$stmt->BindValue(":thumb",null);
}
$stmt->execute();
stringPrint("->thumb");
// Set fileatime back to original value
if ($type != "link" && is_writable($pathname)) {
@exec("touch -at `date -r ".$atime." +%Y%m%d%H%M.%S` ".$shellpath." 2>&1");
stringPrint("touch");
}
echo "\n";
// Double check stat for file against pre-run value
echo bashcolor(str_replace(array("\n"," "),array(" ",""),$stat)."\n","blue");
if ($wopt_paranoid && $type != "link") {
$restat = chop(@shell_exec("stat -x ".$shellpath." 2>&1"));
echo bashcolor(str_replace(array("\n"," "),array(" ",""),$restat)."\n","green");
if ($stat != $restat) { echo "\nBREAK: stat changed on ".$pathname; die; }
}
}
$fbanner = "Finished in ".floor($time = microtime(true)-$_SERVER["REQUEST_TIME_FLOAT"])." seconds";
// Footer
$seconds = floor($time = microtime(true)-$_SERVER["REQUEST_TIME_FLOAT"]);
$fbanner = "Finished in ".$seconds." seconds";
echo str_repeat("-", strlen($fbanner))."\n".$fbanner."\n";
echo "Files ignored: ".$ignored." / Files nodescended: ".$nodescended."\n";
// Write app summary values
$dbo->exec("UPDATE _walkwalk SET nodescended=".$nodescended.", ignored=".$ignored.", status='completed_in_".$seconds."'");
?>