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 breadcrumbs($zpath, $pathname) { if (!$pathname) { return array(array(null,basename($zpath))); } else { $pathname_adjusted = str_replace($zpath."/", "", $pathname); $parts = explode("/", $pathname_adjusted); $i = count($parts); while ($i) { $search_path = $zpath."/".implode("/", array_slice($parts, 0, $i)); if ($i == count($parts)) { $result[] = array(null, basename($search_path)); } else { $result[] = array(md5($search_path), basename($search_path)); } $i--; } $result[] = array("",basename($zpath)); return array_reverse($result); } } function shortlabel($filename, $max = 40) { $suffix = "(...).".pathinfo($filename)['extension']; if (strlen($filename) > $max) { $return = substr($filename, 0, ($max-strlen($suffix))).$suffix; } else { $return = $filename; } return $return; } function findicon($filename) { $ext = pathinfo($filename)['extension']; $good = "icons/null.png"; foreach (glob("icons/*.png") as $file) { if (pathinfo($file)['filename'] == $ext) { $good = $file; } } return $good; } ///////////////////////////////////////////////////////////////// $db_file = $_GET['db']; $pid = $_GET['pid']; $search = $_POST['query']; $parser = new plistParser(); if ($db_file) { echo "db list"; echo "
"; if (!is_readable($db_file)) { echo "can't read db file"; die; } $dbo = new PDO("sqlite:".$db_file); $dbx = new PDO("sqlite:".dirname($db_file)."/pool.sqlite3"); $dbo->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC); $dbx->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC); // Get zpath $zpath = $dbo->query("SELECT zpath FROM _skim")->fetch()['zpath']; // Check for initial view 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']); $view['profile'] = "hidden"; //array($view['profile']); if ($view['details']) { $view['details'] = unserialize($view['details']); } if (substr($view['disks'],0,5) == "parseString(utf8_for_xml($view['disks'])); $view['disks'] = "hidden"; } else { $view['disks'] = "hidden"; } if (substr($view['diskutil'],0,5) == "parseString(utf8_for_xml($view['diskutil'])); } else { $view['diskutil'] = "hidden"; } if ($view['vdisks']) { $view['vdisks'] = $parser->parseString(utf8_for_xml($view['vdisks'])); } if ($view['hdiutil']) { $view['hdiutil'] = $parser->parseString(utf8_for_xml($view['hdiutil'])); } } else { $view = $dbo->query("SELECT rowid, * FROM files WHERE (pid='".$pid."')")->fetch(); if (is_serial($view['stat'])) { $view['stat'] = unserialize($view['stat']); } $dirmdls = $dbo->query("SELECT rowid, * FROM mdls WHERE (rowid='".$view['rowid']."')")->fetch(); } // Breadcrumbs $crumb = breadcrumbs($zpath,$view['Pathname']); $xc = ""; foreach ($crumb as $myparts) { if ($myparts[0] === null) { $xc .= $myparts[1]; } else { $xc .= "".$myparts[1]." > "; } } if (!$search) { echo $xc; echo "
"; } // Search echo "
"; echo "
"; $array = $dbo->query("SELECT children FROM family WHERE (pid='".$pid."')")->fetch()['children']; $children = unserialize($array); if (!$children && !$search) { ///////////////////////////////////////////////////////////////// // File view $skim_version = $dbo->query("SELECT version FROM _skim")->fetch()['version']; $spotlight_status = $dbo->query("SELECT mdutil FROM _skim")->fetch()['mdutil']; echo ""; echo ""; echo ""; echo "
"; $row_a = $dbo->query("SELECT rowid, * FROM files WHERE (pid='".$pid."')")->fetch(); if (is_serial($row_a['stat'])) { $row_a['stat'] = unserialize($row_a['stat']); } if (!strpos($spotlight_status,"disabled")) { $row_b = $dbo->query("SELECT * FROM mdls WHERE (rowid='".$row_a['rowid']."')")->fetch(); $row_e = @$dbo->query("SELECT * FROM milk WHERE (rowid='".$row_a['rowid']."')")->fetch(); } if (version_compare($skim_version,"0.7.7b") > -1) { // newer version stores rowid rather than 0 or 1 for has_exif etc if (isset($row_a['has_exif'])) { $row_c = $dbx->query("SELECT * FROM exiftool WHERE (rowid='".$row_a['has_exif']."')")->fetch(); } if (isset($row_a['has_mediainfo'])) { $row_d = $dbx->query("SELECT * FROM mediainfo WHERE (rowid='".$row_a['has_mediainfo']."')")->fetch(); } } else { // fetch exif and mediainfo by slower fid $row_c = $dbx->query("SELECT * FROM exiftool WHERE (fid='".$row_a['fid']."')")->fetch(); $row_d = $dbx->query("SELECT * FROM mediainfo WHERE (fid='".$row_a['fid']."')")->fetch(); } if ($row_a['thumb_filename']) { $width = $row_a['thumb_width']; $height = $row_a['thumb_height']; $realfile = dirname($db_file).$row_a['thumb_filename']; $icon = ""; } elseif ($row_a['Type'] == "dir") { $icon = ""; } else { $icon = ""; } if ($row_a['contents_filename']) { $realcfile = dirname($db_file).$row_a['contents_filename']; $icon = ""; } echo $icon; // debug milk if (count(@$row_e) > 1) { echo "
"; foreach($row_e as $title => $val) { if ($title == "GPS" && $val) { if (strpos($val,"deg") != false) { $val = get_gps($val); } $print = "".$val.""; } else { $print = $val; } echo "
".$title."".$print."
"; } echo "
"; } // debug file times $fileinfo['atime (php)'] = date("F jS, Y h:i:s",$row_a['ATime']); $fileinfo['mtime (php)'] = date("F jS, Y h:i:s",$row_a['MTime']); $fileinfo['ctime (php)'] = date("F jS, Y h:i:s",$row_a['CTime']); if ($row_a['stat']) { if (is_array($row_a['stat'])) { $fileinfo['atime (stat)'] = date("F jS, Y h:i:s",$row_a['stat']['st_atime']); $fileinfo['mtime (stat)'] = date("F jS, Y h:i:s",$row_a['stat']['st_mtime']); $fileinfo['ctime (stat)'] = date("F jS, Y h:i:s",$row_a['stat']['st_ctime']); $fileinfo['btime (stat)'] = date("F jS, Y h:i:s",$row_a['stat']['st_birthtime']); } else { // parse old version stat preg_match('/^Access: ([^\r\n]*)/m', $row_a['stat'], $access); $fileinfo['atime (stat)'] = date("F jS, Y h:i:s",strtotime($access[1])); preg_match('/^Modify: ([^\r\n]*)/m', $row_a['stat'], $modify); $fileinfo['mtime (stat)'] = date("F jS, Y h:i:s",strtotime($modify[1])); preg_match('/^Change: ([^\r\n]*)/m', $row_a['stat'], $change); $fileinfo['ctime (stat)'] = date("F jS, Y h:i:s",strtotime($change[1])); } } if ($row_b['spotlight']) { $row_b['spotlight'] = $parser->parseString(utf8_for_xml($row_b['spotlight'])); $fileinfo['added (mdls)'] = date("F jS, Y h:i:s",$row_b['DateAdded']); $fileinfo['mtime (mdls)'] = date("F jS, Y h:i:s",$row_b['ContentModificationDate']); $fileinfo['btime (mdls)'] = date("F jS, Y h:i:s",$row_b['ContentCreationDate']); } ksort($fileinfo); echo "
"; foreach ($fileinfo as $title => $value) { echo "
".$title."".$value."
"; } echo "
"; echo "
"; debug(array($row_a),"file"); if ($row_b['spotlight']) { debug(array($row_b),"mdls"); } echo ""; if ($row_c) { debug(array(unserialize($row_c['tags'])),"exiftool"); } if ($row_d) { debug(array(json_decode(json_encode(simplexml_load_string($row_d['info'])))),"mediainfo"); } echo "
"; ///////////////////////////////////////////////////////////////// // Dir view } elseif (!$search) { echo "
"; echo "
"; foreach ($children as $item) { echo "
"; ///////////////////////// $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']) { $visibility = "hidden"; } else { $visibility = "unhidden"; } if ($row_a['thumb_filename']) { $aspect = $row_a['thumb_width']/$row_a['thumb_height']; if ($aspect > 1) { $width = $icon_size; $height = $icon_size/$aspect; } else { $width = $icon_size*$aspect; $height = $icon_size; } $realfile = dirname($db_file).$row_a['thumb_filename']; $icon = ""; } elseif ($row_a['Type'] == "dir") { $icon = ""; } else { $icon = ""; } echo "\n".$icon.""; echo "
"; if ($row_b['UserTags']) { foreach (unserialize($row_b['UserTags']) as $tag) { echo ""; } echo " "; } echo htmlentities(shortlabel($row_a['Filename'])); echo "
"; if ($row_a['Size']) { echo "
".human_filesize($row_a['Size'])."
"; } if ($row_a['Type'] == "dir" && $row_a['items']) { echo "
".number_format($row_a['items'])." items
"; } echo "
"; echo "
"; } echo str_repeat("
", 100); echo "
"; echo "
"; debug($view,$view['Pathname']); if ($dirmdls['spotlight']) { $dirmdls['spotlight'] = $parser->parseString(utf8_for_xml($dirmdls['spotlight'])); debug(array($dirmdls),"mdls"); } echo "
"; } else { ///////////////////////////////////////////////////////////////// // Search $result = $dbo->query("SELECT * FROM files WHERE (Filename LIKE '%".$search."%')")->fetchAll(); if (count($result)) { echo count($result)." results
"; foreach ($result as $row) { $pathbold = str_ireplace($search,"".$search."",$row['Pathname']); echo "\n".$pathbold."
"; } } else { echo "No results for ".$search; } } } else { ///////////////////////////////////////////////////////////////// // DB List $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) { echo "
"; $dbs = array_reverse(glob($bundle."/*.sqlite3")); array_shift($dbs); if ($dbs[0]) { $dbo = new PDO("sqlite:".$dbs[0]); $type = $dbo->query("SELECT type FROM _skim")->fetch()['type']; echo ""; } echo "

".pathinfo($bundle)['filename']."

"; foreach ($dbs as $db_file) { $dbo = new PDO("sqlite:".$db_file); $info = $dbo->query("SELECT * FROM _skim")->fetch(); if (strpos($info['status'],"completed") === 0) { $seconds = str_replace("completed_in_","",$info['status']); $status = gmdate("H:i:s",$seconds); echo "
"; } else { echo "
"; } echo "".pathinfo($db_file)['filename']." "; echo $info['version'].", "; echo number_format($info['passed_total'])." files, "; if ($info['image_file']) { echo $info['image_file'].", "; } echo $status; if (strpos($info['spotlight_status'],"disabled")) { echo " (no spotlight)"; } echo "
"; } echo "
"; } } ///////////////////////////////////////////////////////////////// echo "

".round($time = microtime(true)-$_SERVER["REQUEST_TIME_FLOAT"],2)." seconds"; ?>