".$bpath; echo $banner."\n".str_repeat("-", strlen($banner))."\n"; // Disk info ////////////////////////////////////////// echo "Gathering system info...\n"; $host = gethostname(); $disks = shell_exec("diskutil list 2>&1"); if (substr($zpath, 0, 9) != "/Volumes/") { $zbase = "/"; } else { $zparts = explode("/", $zpath); $zbase = "/Volumes/".$zparts[2]; } $diskutil = shell_exec("diskutil info ".$zbase." 2>&1"); $getstats = array( "Volume Name", "Protocol", "Volume UUID", "Device Location", "Volume Total Space", "Volume Available Space", "Level Type" ); foreach ($getstats as $stat) { preg_match("/(".$stat.":)(.*)(\n)/",$diskutil,$matches); if (isset($matches[2])) { if (substr($stat, -5, 5) == "Space") { $pieces = explode(" ", trim($matches[2])); $summary = $pieces[0]." ".$pieces[1]; $stats[$stat] = $summary; } else { $stats[$stat] = trim($matches[2]); } } } $dstats = serialize($stats); if ($zpath == "/") { $type = "Startup disk"; } elseif (strtolower($zpath) == strtolower("/Volumes/".$stats["Volume Name"])) { if ($stats["Protocol"] == "Disk Image") { $type = "Disk image"; } else { $type = "External disk"; } } else { $type = "Folder"; } if ($wopt_noprofile) { $profile = "disabled"; } else { $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 ////////////////////////////////////////// echo "Building database...\n"; $stamp = date("Y-m-d_H-i-s", time()); $dbo = new PDO("sqlite:".$bpath."/".$stamp.".sqlite3"); $dbo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); /* $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->exec("CREATE TABLE _walkwalk ( version TEXT, opts TEXT, host TEXT, uid INTEGER, zpath TEXT, bpath TEXT, type TEXT, passed_file INTEGER, passed_dir INTEGER, passed_link INTEGER, passed_total INTEGER, nodescended INTEGER, ignored INTEGER, dupes INTEGER, stats TEXT, qlmanage TEXT, sysvers TEXT, diskutil TEXT, disks TEXT, profile TEXT, status TEXT )"); $dbo->exec("CREATE TABLE family ( pid TEXT, fid TEXT, children TEXT )"); /* Gather for each file: A. IDs pid (path ID) fid (file ID) B. splFileInfo methods Pathname Path Filename Extension Type Inode Perms Owner ATime CTime MTime LinkTarget RealPath C. External methods stat items newest gfi_type gfi_attr gfi_created D. Aggregates Size (splFileInfo, du) Title (exiftool, kMDItemTitle, mediainfo) PixelWidth (kMDItemPixelWidth, exiftool, mediainfo) PixelHeight (kMDItemPixelHeight, exiftool, mediainfo) Duration (kMDItemDurationSeconds, mediainfo, exiftool) DateTimeOriginal (exiftool[DateTimeOriginal],mediainfo[EncodedDate],exiftool[CreateDate,MediaCreateDate],kMDItemContentCreationDate) Origin (exiftool[CameraModelName,Producer,CreatorTool,WriterName,Software,Encoder],mediainfo[WritingApplication]) GPS (exiftool[GPSPosition], kMDItemLatitude.kMDItemLongitude) Author (exiftool[Author,Artist,Creator,By-line]) E. Spotlight spotlight (whole plist) kMDItemDateAdded kMDItemLastUsedDate kMDItemUseCount kMDItemContentModificationDate kMDItemContentType kMDItemCreator kMDItemFSCreatorCode kMDItemKind kMDItemFSTypeCode kMDItemUserTags kMDItemFSInvisible kMDItemNumberOfPages kMDItemPageHeight kMDItemPageWidth kMDItemWhereFroms kMDItemEncodingApplications F. Pool has_exif has_mediainfo has_hash thumb_filename thumb_width thumb_height G. Exiftool ProfileDescription BitDepth Compression WhiteBalance Orientation LensType H. Mediainfo VideoFormat AudioFormat Tracks Profile Bitrate */ $dbo->exec("CREATE TABLE files ( pid TEXT, fid TEXT, Pathname TEXT, Path TEXT, Filename TEXT, Extension TEXT, Type TEXT, Inode INTEGER, Perms INTEGER, Owner TEXT, ATime INTEGER, CTime INTEGER, MTime INTEGER, LinkTarget TEXT, RealPath TEXT, stat TEXT, items INTEGER, newest INTEGER, gfi_type TEXT, gfi_attr TEXT, gfi_created TEXT, Size INTEGER, Title TEXT, PixelWidth INTEGER, PixelHeight INTEGER, Duration INTEGER, DateTimeOriginal INTEGER, Origin TEXT, GPS TEXT, Author TEXT, spotlight TEXT, kMDItemDateAdded INTEGER, kMDItemLastUsedDate INTEGER, kMDItemUseCount INTEGER, kMDItemContentModificationDate INTEGER, kMDItemContentType TEXT, kMDItemCreator TEXT, kMDItemFSCreatorCode TEXT, kMDItemKind TEXT, kMDItemFSTypeCode TEXT, kMDItemUserTags TEXT, kMDItemFSInvisible INTEGER, kMDItemNumberOfPages INTEGER, kMDItemPageHeight INTEGER, kMDItemPageWidth INTEGER, kMDItemWhereFroms TEXT, kMDItemEncodingApplications TEXT, has_exif INTEGER, has_mediainfo INTEGER, has_hash INTEGER, thumb_filename TEXT, thumb_width INTEGER, thumb_height INTEGER, ProfileDescription TEXT, BitDepth INTEGER, Compression TEXT, Orientation INTEGER, LensType TEXT, VideoFormat TEXT, AudioFormat TEXT, Tracks INTEGER, Profile TEXT, Bitrate INTEGER )"); $stmt = $dbo->prepare("INSERT INTO _walkwalk VALUES (:version, :opts, :host, :uid, :zpath, :bpath, :type, :passed_file, :passed_dir, :passed_link, :passed_total, :nodescended, :ignored, :dupes, :stats, :qlmanage, :sysvers, :diskutil, :disks, :profile, :status)"); $stmt->BindValue(":version",$version); $stmt->BindValue(":opts",serialize($p)); $stmt->BindValue(":host",$host); $stmt->BindValue(":uid",posix_getuid()); $stmt->BindValue(":zpath",$zpath); $stmt->BindValue(":bpath",$bpath); $stmt->BindValue(":type",$type); $stmt->BindValue(":stats",$dstats); $stmt->BindValue(":qlmanage",$qlmanage); $stmt->BindValue(":sysvers",$sysvers); $stmt->BindValue(":diskutil",$diskutil); $stmt->BindValue(":disks",$disks); $stmt->BindValue(":profile",$profile); $stmt->BindValue(":status","aborted"); $stmt->execute(); // Iterator ////////////////////////////////////////// $first_run = 1; $passed_file = $passed_dir = $passed_link = $passed_total = $nodescended = $ignored = 0; $files = new RecursiveIteratorIterator( new RecursiveCallbackFilterIterator( new RecursiveDirectoryIterator( $zpath, RecursiveDirectoryIterator::SKIP_DOTS ), function ($current, $key, $iterator) use ($p) { global $nodescended, $ignored, $passed_file, $passed_dir, $passed_link, $passed_total, $first_run; $clean = true; // identify ignore files if (is_array($p['ignore'])) { foreach ($p['ignore'] as $wildcard) { if (fnmatch($wildcard, $current->getFilename())) { $clean = false; if ($first_run) { $ignored++; } } } } // identify nodescend dirs if (is_array($p['nodescend'])) { foreach ($p['nodescend'] as $wildcard) { if (fnmatch($wildcard, $current->getPath())) { $clean = false; if ($first_run) { $nodescended++; } } } } //tally stats if ($clean && $first_run) { if ($current->getType() == "file") { $passed_file++; } elseif ($current->getType() == "dir") { $passed_dir++; } elseif ($current->getType() == "link") { $passed_link++; } $passed_total++; } return $clean; } ), RecursiveIteratorIterator::SELF_FIRST, RecursiveIteratorIterator::CATCH_GET_CHILD ); // Tally ////////////////////////////////////////// foreach ($files as $null) { } $first_run = 0; // Permissions ////////////////////////////////////////// if (posix_getuid()) { echo ProgressBar::start($passed_total,"File permissions"); echo "You are not root. Checking file readability"; $oops = 0; foreach ($files as $splFileInfo) { $path = $splFileInfo->getRealPath(); if ($path && !is_readable($path)) { $oops = 1; echo "x"; } else { echo "."; } echo ProgressBar::next(); //echo "\t".$path."\n"; } echo ProgressBar::finish(); echo "\n"; if ($oops) { echo "Some files could not be read. Stopping."; die; } } else { echo "Running as root. Some QuickLook plugins may not be available."; echo "\n"; } if ($p['paranoid']) { echo "Filesystem is writable. "; if ($p['fixatimes']) { echo "Preserving atimes."; } else { echo "Preserving ctimes."; } echo "\n"; } // Pool DB ////////////////////////////////////////// $dbp = new PDO("sqlite:".$bpath."/pool.sqlite3"); $dbp->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); $dbp->exec("CREATE TABLE IF NOT EXISTS md5 (fid TEXT, hash TEXT)"); $dbp->exec("CREATE TABLE IF NOT EXISTS exiftool (fid TEXT, tags TEXT)"); $dbp->exec("CREATE TABLE IF NOT EXISTS mediainfo (fid TEXT, info TEXT)"); $dbp->exec("CREATE TABLE IF NOT EXISTS thumbs (fid TEXT, created INTEGER, relative_path TEXT, width INTEGER, height INTEGER, tool TEXT)"); // Prescan ////////////////////////////////////////// $family = array(); $fids = array(); echo ProgressBar::start($passed_total,"Prescan"); foreach ($files as $splFileInfo) { $pathname = $splFileInfo->getPathname(); $path = $splFileInfo->getPath(); $key = md5($pathname); $pkey = md5($path); if (array_key_exists($key, $family)) { echo "Duplicate key on ".$pathname."\n"; die; } $family[$key] = array(); // Path-agnostic Unique File ID (to prevent redundant hashes and thumbs) if ($splFileInfo->getType() != "dir" && $splFileInfo->getType() != "link") { $fid = md5($splFileInfo->getSize().$splFileInfo->getMtime().$splFileInfo->getBasename()); $dx[$fid][] = $pathname; $fx[] = array($fid, $pathname); $family[$key]['fid'] = $fid; } // Parents //$family[$key]['parents'] = getParents($zpath, $pathname); // Children $family[$pkey]['children'][] = $key; echo ProgressBar::next(); } echo ProgressBar::finish(); // Debug record of duplicate FIDs $dupes = array_filter($dx, function($a) { return count($a) > 1; }); $dxo = var_export($dupes, true); if (strlen($dxo)) { file_put_contents($bpath."/".$stamp."_dupes.txt",$dxo); $dupecount = count($dupes,COUNT_RECURSIVE) - count($dupes); echo floor(($dupecount/$passed_total)*100)." percent of files look like duplicates\n"; } // Write family to DB $message = "Writing family to DB: "; $message .= $passed_file." files, "; $message .= $passed_dir." dirs, "; $message .= $nodescended." bundles, "; $message .= $passed_link." links, "; $message .= $ignored." ignored, "; $message .= ($dupecount ? $dupecount : 0)." dupes"; echo ProgressBar::start(count($family),$message); foreach ($family as $key => $item) { $stmt = $dbo->prepare("INSERT INTO family VALUES (:pid, :fid, :children)"); $stmt->BindValue(":pid",$key); if (@$item['fid']) { $stmt->BindValue(":fid",$item['fid']); } if (@$item['children'] && is_array(@$item['children'])) { $stmt->BindValue(":children",serialize($item['children'])); } $stmt->execute(); echo ProgressBar::next(); } echo ProgressBar::finish(); unset($dx, $dxo, $dupes); // stats $stmt = "UPDATE _walkwalk SET "; $stmt .= "passed_file=".$passed_file.", "; $stmt .= "passed_dir=".$passed_dir.", "; $stmt .= "passed_link=".$passed_link.", "; $stmt .= "passed_total=".$passed_total.", "; $stmt .= "nodescended=".$nodescended.", "; $stmt .= "ignored=".$ignored.", "; $stmt .= "dupes=".($dupecount ? $dupecount : 0); $dbo->exec($stmt); // Thumbnails ////////////////////////////////////////// if ($p['thumbs']) { echo ProgressBar::start(count($fx),"Generating thumbnails"); foreach ($fx as $array) { $fid = $array[0]; $pathname = $array[1]; $ext = pathinfo($pathname,PATHINFO_EXTENSION); $tpath = $bpath."/thumbs/".substr($fid, 0, 2); if (!is_dir($tpath)) { mkdir($tpath); } $tfile = $tpath."/".$fid.".jpg"; // HACK for ql-thumbnail bug $t_skip = array("emlx"); if (count($t_skip) && in_array($ext, $t_skip)) { echo ProgressBar::next("Skipping ".shortlabel($pathname)); continue; } // if no thumb file, then poll database if (file_exists($tfile)) { echo ProgressBar::next("Thumb file found for ".shortlabel($pathname)); continue; } elseif ($dbp->query("SELECT EXISTS(SELECT 1 FROM thumbs WHERE fid='".$fid."')")->fetch()[0]) { echo ProgressBar::next("Thumb record found for ".shortlabel($pathname)); continue; } else { echo ProgressBar::next("Generating thumb for ".shortlabel($pathname)); } $stmt = $dbp->prepare("INSERT INTO thumbs VALUES (:fid, :created, :relative_path, :width, :height, :tool)"); $stmt->BindValue(":fid",$fid); $stmt->BindValue(":created",time()); $shellpath = escapeshellarg($pathname); // first try to make a thumb with external tools $cmd = null; if (in_array($ext, $t_files['sips'])) { //$cmd = $bin_tv." ".$shellpath." -o ".$tfile."[Q=90,optimize_coding] --size=".$p['thumb_size']; $cmd = "sips -s format jpeg -s formatOptions 80 --resampleHeightWidthMax ".$p['thumb_size']." ".$shellpath." --out ".$tfile; $stmt->BindValue(":tool","sips"); } elseif (in_array($ext, $t_files['ffmpeg'])) { //$cmd = $bin_tf." -i ".$shellpath." -o ".$tfile." -s ".$p['thumb_size']." -c jpg -q 8.5"; $cmd = $bin_ffmpeg." -ss $(( $(".$bin_mediainfo." --Inform='Video;%Duration%' ".$shellpath.") / 10000 )) -i ".$shellpath." -vframes 1 -filter:v scale='400:-1' -q:v 3 ".$tfile; $stmt->BindValue(":tool","ffmpeg"); } if ($cmd) { shell_exec($cmd." 2>&1"); } // if those tools failed, try quicklook if (!@filesize($tfile)) { //$cmd = $bin_qlthumb." ".$shellpath." ".$tfile." public.jpeg-2000 ".$p['thumb_size']." ".$p['thumb_size']." .8"; $cmd = $bin_qlthumb." ".$shellpath." ".$tfile." public.jpeg ".$p['thumb_size']." ".$p['thumb_size']." .8"; shell_exec($cmd." 2>&1"); $stmt->BindValue(":tool","quicklook"); } // success, move thumb into the bundle if (file_exists($tfile) && @filesize($tfile)) { $stmt->BindValue(":relative_path",substr($tfile, strlen($bpath))); list($width, $height) = getimagesize($tfile); $stmt->BindValue(":width",$width); $stmt->BindValue(":height",$height); } $stmt->execute(); } echo ProgressBar::finish(); } // External metadata ////////////////////////////////////////// if ($p['meta']) { echo ProgressBar::start(count($fx),"Collecting external metadata"); foreach ($fx as $array) { $fid = $array[0]; $pathname = $array[1]; $shellpath = escapeshellarg($pathname); $ext = pathinfo($pathname,PATHINFO_EXTENSION); if (!in_array($ext, $e_files) && !in_array($ext, $m_files)) { echo ProgressBar::next("Not a media file: ".shortlabel($pathname)); continue; } else { echo ProgressBar::next("Metadata: ".shortlabel($pathname)); } if (in_array($ext, $e_files)) { $check = $dbp->query("SELECT EXISTS(SELECT 1 FROM exiftool WHERE fid='".$fid."')")->fetch()[0]; if (!$check) { $rawexif = eval("return ".`$bin_exiftool -php $shellpath`); $stmt = $dbp->prepare("INSERT INTO exiftool VALUES (:fid, :tags)"); $stmt->BindValue(":fid",$fid); $stmt->BindValue(":tags",serialize($rawexif[0])); $stmt->execute(); } } if (in_array($ext, $m_files)) { $check = $dbp->query("SELECT EXISTS(SELECT 1 FROM mediainfo WHERE fid='".$fid."')")->fetch()[0]; if (!$check) { $stmt = $dbp->prepare("INSERT INTO mediainfo VALUES (:fid, :info)"); $stmt->BindValue(":fid",$fid); $stmt->BindValue(":info",serialize(parseMediaInfo(shell_exec($bin_mediainfo." --Output=OLDXML ".$shellpath." 2>&1")))); $stmt->execute(); } } } echo ProgressBar::finish(); } // Hashes ////////////////////////////////////////// if ($p['hash']) { if ($p['hash_limit']) { $message = "Generating hashes for files under ".$p['hash_limit']."GB"; } else { $message = "Generating hashes for all files"; } echo ProgressBar::start(count($fx),$message); foreach ($fx as $array) { $fid = $array[0]; $pathname = $array[1]; $size = filesize($pathname); $limit = $p['hash_limit']*1000000000; $check = $dbp->query("SELECT EXISTS(SELECT 1 FROM md5 WHERE fid='".$fid."')")->fetch()[0]; if ($check) { echo ProgressBar::next("Hash already exists: ".shortlabel($pathname)); } elseif ($p['hash_limit'] && ($size > $limit)) { echo ProgressBar::next("Too big to hash: ".shortlabel($pathname)." (".human_filesize($size).")"); } else { echo ProgressBar::next("Generating hash: ".shortlabel($pathname)); $stmt = $dbp->prepare("INSERT INTO md5 VALUES (:fid, :hash)"); $stmt->BindValue(":fid",$fid); $stmt->BindValue(":hash",md5_file($pathname)); $stmt->execute(); } } echo ProgressBar::finish(); } // Files ////////////////////////////////////////// echo ProgressBar::start($passed_total,"Processing files"); foreach ($files as $splFileInfo) { echo "\n"; // DB $stmt = $dbo->prepare("INSERT INTO files VALUES (:pid, :fid, :Pathname, :Path, :Filename, :Extension, :Type, :Inode, :Perms, :Owner, :ATime, :CTime, :MTime, :LinkTarget, :RealPath, :stat, :items, :newest, :gfi_type, :gfi_attr, :gfi_created, :Size, :Title, :PixelWidth, :PixelHeight, :Duration, :DateTimeOriginal, :Origin, :GPS, :Author, :spotlight, :kMDItemDateAdded, :kMDItemLastUsedDate, :kMDItemUseCount, :kMDItemContentModificationDate, :kMDItemContentType, :kMDItemCreator, :kMDItemFSCreatorCode, :kMDItemKind, :kMDItemFSTypeCode, :kMDItemUserTags, :kMDItemFSInvisible, :kMDItemNumberOfPages, :kMDItemPageHeight, :kMDItemPageWidth, :kMDItemWhereFroms, :kMDItemEncodingApplications, :has_exif, :has_mediainfo, :has_hash, :thumb_filename, :thumb_width, :thumb_height, :ProfileDescription, :BitDepth, :Compression, :Orientation, :LensType, :VideoFormat, :AudioFormat, :Tracks, :Profile, :Bitrate)"); // Identify dir, file, link or bundle dir $type = $splFileInfo->getType(); if ($type == "dir") { foreach ($p['bundles'] as $bundle) { $check = ".".$bundle; if (substr($splFileInfo->getFilename(), -(strlen($check)), strlen($check)) == $check) { $type = "bundle"; } } } $stmt->BindValue(":Type",$type); // Cache atime before it gets modified if ($type != "link") { $atime = $splFileInfo->getATime(); } // Path basics $pathname = $splFileInfo->getPathname(); $path = $splFileInfo->getPath(); $filename = $splFileInfo->getFilename(); $extension = $splFileInfo->getExtension(); $shellpath = escapeshellarg($pathname); $stmt->BindValue(":Pathname",$pathname); $stmt->BindValue(":Path",$path); $stmt->BindValue(":Filename",$filename); $stmt->BindValue(":Extension",$extension); 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()); } echo shortlabel($pathname,50,1); // ------------------------------------------------ // // Get stat if ($type != "link") { $stat = chop(@shell_exec("stat -x ".$shellpath." 2>&1")); } else { $stat = null; } $stmt->BindValue(":stat",@$stat); // Cache stat if ($type != "link" && $p['paranoid']) { $pre_access = null; $pre_modify = null; $pre_change = null; foreach (explode("\n", $stat) as $line) { $check = substr($line, 0, 6); if ($check == "Access") { $pre_access = $line; } if ($check == "Modify") { $pre_modify = $line; } if ($check == "Change") { $pre_change = $line; } } } // Generate PID and FID $pid = md5($pathname); $stmt->BindValue(":pid",$pid); if ($type == "file") { $fid = md5($splFileInfo->getSize().$splFileInfo->getMtime().$splFileInfo->getBasename()); $stmt->BindValue(":fid",$fid); } else { $stmt->BindValue(":fid",null); } // Size if ($type == "dir" || $type == "bundle") { $size = trim(shell_exec("du -ks ".$shellpath." | cut -f1"))*1024; } elseif ($type == "file") { $size = $splFileInfo->getSize(); } else { $size = null; } $stmt->BindValue(":Size",@$size); stringPrint(floor($size/1024)."k"); // ------------------------------------------------ // // Items if ($type == "dir" || $type == "bundle" ) { $items = chop(@shell_exec("find ".$shellpath." \( ! -regex '.*/\..*' \) | wc -l 2>&1"))-1; $stmt->BindValue(":items",@$items); stringPrint($items ? "ITEMS" : "items"); } else { $items = null; stringPrint(" "); } // ------------------------------------------------ // // Newest if ($type == "dir") { $newest = @filemtime(chop(shell_exec("find ".$shellpath." -type f -not -path '*/\.*' -print0 | xargs -0 stat -f \"%m %N\" | sort -rn 2>&1 | head -1 | cut -f2- -d\" \""))); $stmt->BindValue(":newest",@$newest); stringPrint($newest ? "NEWEST" : "newest"); } else { $newest = null; stringPrint(" "); } // ------------------------------------------------ // // GetFileInfo $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; } } $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"); // ------------------------------------------------ // // Spotlight $mdls = null; $mdls = shell_exec("mdls -plist - ".$shellpath." 2>&1"); if ($mdls != $pathname.": could not find ".$pathname.".\n") { $parser = new plistParser(); $spotlight = $parser->parseString($mdls); //$stmt->BindValue(":spotlight",serialize($spotlight)); $stmt->BindValue(":spotlight",$mdls); } else { $spotlight = array(); $stmt->BindValue(":spotlight",null); } stringPrint($mdls ? "MDLS" : "mdls"); unset($breakout, $schema, $item, $ready); $breakout[] = array ("kMDItemDateAdded", "date"); $breakout[] = array ("kMDItemLastUsedDate", "date"); $breakout[] = array ("kMDItemUseCount", 0); $breakout[] = array ("kMDItemContentModificationDate", "date"); $breakout[] = array ("kMDItemContentType", 0); $breakout[] = array ("kMDItemCreator", 0); $breakout[] = array ("kMDItemFSCreatorCode", 0); $breakout[] = array ("kMDItemKind", 0); $breakout[] = array ("kMDItemFSTypeCode", 0); $breakout[] = array ("kMDItemUserTags", "array"); $breakout[] = array ("kMDItemFSInvisible", 0); $breakout[] = array ("kMDItemNumberOfPages", 0); $breakout[] = array ("kMDItemPageHeight", 0); $breakout[] = array ("kMDItemPageWidth", 0); $breakout[] = array ("kMDItemWhereFroms", "array"); $breakout[] = array ("kMDItemEncodingApplications", "array"); foreach ($breakout as $schema) { if (!isset($spotlight[$schema[0]])) { $stmt->BindValue(":".$schema[0],null); continue; } if ($schema[1] === "date") { $ready = strtotime($spotlight[$schema[0]]); } elseif ($schema[1] === "array") { $ready = serialize($spotlight[$schema[0]]); } else { $ready = $spotlight[$schema[0]]; } $stmt->BindValue(":".$schema[0],$ready); } unset($breakout); // ------------------------------------------------ // // Pool if ($type == "file") { unset($fetch_exif, $fetch_media, $fetch_hash, $fetch_thumb, $yes_exif, $yes_media, $yes_hash); $fetch_exif = @unserialize($dbp->query("SELECT tags FROM exiftool WHERE fid='".$fid."'")->fetch()[0]); is_array($fetch_exif) ? $yes_exif = 1 : $yes_exif = 0; $stmt->BindValue(":has_exif",$yes_exif); stringPrint($yes_exif ? "EXIF" : "exif"); $fetch_media = @unserialize($dbp->query("SELECT info FROM mediainfo WHERE fid='".$fid."'")->fetch()[0]); is_array($fetch_media) ? $yes_media = 1 : $yes_media = 0; $stmt->BindValue(":has_mediainfo",$yes_media); stringPrint($yes_media ? "MEDIA" : "media"); $yes_hash = $dbp->query("SELECT EXISTS(SELECT 1 FROM md5 WHERE fid='".$fid."')")->fetch()[0]; $stmt->BindValue(":has_hash",$yes_hash); stringPrint($yes_hash ? "HASH" : "hash"); $fetch_thumb = $dbp->query("SELECT * FROM thumbs WHERE fid='".$fid."'")->fetch(); if (@$fetch_thumb['relative_path']) { $stmt->BindValue(":thumb_filename",$fetch_thumb['relative_path']); $stmt->BindValue(":thumb_width",$fetch_thumb['width']); $stmt->BindValue(":thumb_height",$fetch_thumb['height']); stringPrint("THUMB"); } else { $stmt->BindValue(":thumb_filename",null); stringPrint("thumb"); } $breakout[] = "ProfileDescription"; $breakout[] = "BitDepth_BitsPerSample"; $breakout[] = "Compression"; $breakout[] = "Aperture,LightSource,WhiteBalance"; $breakout[] = "Orientation"; $breakout[] = "LensType,FocalLength"; $breakout['profile'] = "ProfileDescription"; $breakout['bits'] = "BitDepth_BitsPerSample"; $breakout['compression'] = "Compression"; $breakout[] = "Aperture,LightSource,WhiteBalance"; $breakout[] = "Orientation"; $breakout[] = "LensType,FocalLength"; /* function parseConditionalItem($data, $item) { if (strpos($item, "_")) { $list = explode("_", $item); foreach ($list as $piece) { // left off here } } function parseItem($data, $item) { if (strpos($item, ",")) { $list = explode(",", $item); foreach ($list as $piece) { $cleared[] = parseConditionalItem($piece); } } else { $cleared[] = parseConditionalItem($item); } foreach ($cleared as $check) { if (isset($data[$check])) { $ready[] = $data[$check]; } } if (@count($ready) > 1) { return implode(", ",$ready); } elseif (@count($ready) == 1) { return $ready[0]; } else { return null; } } // left off here foreach ($breakout as $item) { unset($ready); if (strpos($item, ",")) { $list = explode(",", $item) { foreach ($list as $multi) { if (isset($fetch_exif[$multi])) { $ready[] = $fetch_exif[$multi]; } } } elseif (strpos($item, "_")) { $list = explode("_", $item) { foreach ($list as $multi) { if (isset($ready) { continue; } if (isset($fetch_exif[$multi])) { $ready[] = $fetch_exif[$multi]; } */ unset($breakout); //print_r($fetch_exif); //print_r($fetch_media); } // Write to DB $stmt->execute(); stringPrint("DB"); // Set fileatime back to original value if ($type != "link" && is_writable($pathname) && $p['fixatimes']) { @exec("touch -at `date -r ".$atime." +%Y%m%d%H%M.%S` ".$shellpath." 2>&1"); stringPrint("touch"); } // Double check stat for file against pre-run value if ($type != "link" && $p['paranoid']) { $restat = chop(@shell_exec("stat -x ".$shellpath." 2>&1")); $post_access = null; $post_modify = null; $post_change = null; foreach (explode("\n", $restat) as $line) { $check = substr($line, 0, 6); if ($check == "Access") { $post_access = $line; } if ($check == "Modify") { $post_modify = $line; } if ($check == "Change") { $post_change = $line; } } $message = array(); if ($pre_access != $post_access) { $message[] = "ATIME"; } if ($pre_modify != $post_modify) { $message[] = "MTIME"; } if ($pre_change != $post_change) { $message[] = "CTIME"; } if (count($message)) { stringPrint("Changed: ".implode(", ", $message)); } } echo "\n"; echo ProgressBar::next(); } echo ProgressBar::finish(); // Cleanup ////////////////////////////////////////// echo "\n"; $seconds = floor($time = microtime(true)-$_SERVER["REQUEST_TIME_FLOAT"]); $dbo->exec("UPDATE _walkwalk SET status='completed_in_".$seconds."'"); echo "Finished in ".$seconds." seconds\n\n"; unset($dbo, $dbp, $files, $family, $fx); ?>