#!/usr/bin/php <?php /* Copyright (C) 2005 Martin Furter, Ram Yalamanchili This file is part of Ices2Web Ices2Web is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. Ices2Web is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Ices2Web; see the file COPYING. If not, write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. ------------------------------------------------------------------------------*/ include( "db.php" ); include( "cfg.php" ); function printarray( $name, $array ) { echo "<h3>$name</h3>\n"; echo "<pre>\n"; reset( $array ); while( list($k,$v) = each( $array ) ) { echo "$k = $v\n"; } echo "</pre>\n"; } function str_to_sql( $str ) { if( $str == "" ) { return "null"; } else { return "'" . pg_escape_string( $str ) . "'"; } } function number_to_sql( $number ) { if( $number == "" ) { return "null"; } else { return $number; } } function epoch_to_sql( $epoch ) { if( $epoch == "" ) { return "null"; } else { return "to_timestamp( '" . strftime( $GLOBALS["strftimefmt"], $epoch ) . "', " . $GLOBALS["datefmt"] . " )"; } } function db_remove( $conn, $reldir, $name, $type ) { // echo "db_remove $type '$reldir/$name'\n"; if( $name == "" ) { return; } $sql = "delete from " . "ices2_oggfiles " . " where " . "iof_directory = " . str_to_sql( $reldir ) . " and " . "iof_name = " . str_to_sql( $name ); // echo "SQL <$sql>\n"; pg_exec( $conn, $sql ); if( $type == "dir" ) { if( $reldir == "/" ) { $dir = $name; } else { $dir = $reldir . "/" . $name; } $dirlen = strlen($dir) + 1; $dir = pg_escape_string( $dir ); $sql = "delete from " . "ices2_oggfiles " . "where " . "iof_directory = '$dir' or " . "substr( iof_directory, 1, $dirlen ) = '$dir/'"; // echo "SQL <$sql>\n"; pg_exec( $conn, $sql ); } } function db_insert( $conn, $reldir, $name, $props ) { $type = $props["type"]; // echo "db_insert $type '$reldir/$name'\n"; if( $type == "file" ) { $sql = "insert into ices2_oggfiles ( " . "iof_directory, " . "iof_name, " . "iof_is_file, " . "iof_title, " . "iof_artist, " . "iof_album, " . "iof_track_nr, " . "iof_genre, " . "iof_length, " . "iof_bitrate, " . "iof_filesize, " . "iof_date_mod " . ") values ( " . str_to_sql( $reldir ) . ", " . str_to_sql( $name ) . ", " . "true, " . str_to_sql( $props["title"] ) . ", " . str_to_sql( $props["artist"] ) . ", " . str_to_sql( $props["album"] ) . ", " . str_to_sql( $props["track"] ) . ", " . str_to_sql( $props["genre"] ) . ", " . number_to_sql( $props["length"] ) . ", " . number_to_sql( $props["bitrate"] ) . ", " . number_to_sql( $props["filesize"] ) . ", " . epoch_to_sql( $props["date_mod"] ) . " )"; } else { $sql = "insert into ices2_oggfiles ( " . "iof_directory, " . "iof_name, " . "iof_is_file " . ") values ( " . str_to_sql( $reldir ) . ", " . str_to_sql( $name ) . ", " . "false " . " )"; } pg_exec( $conn, $sql ); } function db_update_file( $conn, $reldir, $name, $props ) { $type = $props["type"]; // echo "db_update_file $type '$reldir/$name'\n"; if( $type != "file" ) { return; } $sql = "update " . "ices2_oggfiles " . "set" . " iof_title = " . str_to_sql( $props["title"] ) . ", iof_artist = " . str_to_sql( $props["artist"] ) . ", iof_album = " . str_to_sql( $props["album"] ) . ", iof_track_nr = " . str_to_sql( $props["track"] ) . ", iof_genre = " . str_to_sql( $props["genre"] ) . ", iof_length = " . number_to_sql( $props["length"] ) . ", iof_bitrate = " . number_to_sql( $props["bitrate"] ) . ", iof_filesize = " . number_to_sql( $props["filesize"] ) . ", iof_date_mod = " . epoch_to_sql( $props["date_mod"] ) . " where " . "iof_directory = " . str_to_sql( $reldir ) . " and " . "iof_name = " . str_to_sql( $name ); // echo "SQL <$sql>\n"; pg_exec( $conn, $sql ); } function get_db_dir( $conn, $reldir ) { $dir = array(); $sql = "select " . "iof_name, " . "iof_is_file, " . "iof_title, iof_artist, iof_album, iof_track_nr, " . "iof_genre, iof_length, iof_bitrate, iof_filesize, " . "extract(epoch from iof_date_mod) as iof_date_mod " . "from " . "ices2_oggfiles " . "where ". "iof_directory = '" . pg_escape_string($reldir) . "'"; $rs = pg_exec( $conn, $sql ); if( $rs ) { while( $row = pg_fetch_array( $rs ) ) { $node = array(); if( $row["iof_is_file"]== "t" ) { $node["type"] = "file"; // echo "db file '$name'\n"; } else { $node["type"] = "dir"; // echo "db dir '$name'\n"; } $node["title"] = $row["iof_title"]; $node["artist"] = $row["iof_artist"]; $node["album"] = $row["iof_album"]; $node["track"] = $row["iof_track_nr"]; $node["genre"] = $row["iof_genre"]; $node["length"] = $row["iof_length"]; $node["bitrate"] = $row["iof_bitrate"]; $node["filesize"] = $row["iof_filesize"]; $node["date_mod"] = $row["iof_date_mod"]; $dir[$row["iof_name"]] = $node; } } return $dir; } function get_ogg_info( $absfile, &$props ) { $lines = array(); exec( "ogginfo " . escapeshellarg( $absfile ), $lines, $rc ); if( $rc != 0 ) { return; } $n = count($lines); $i = 0; while( $i < $n && !ereg( "^Nominal bitrate: ", $lines[$i] ) ) { $i++; } if( $i >= $n ) return; $tmp = split( " *", $lines[$i] ); $props["bitrate"] = ereg_replace( "[.].*\$", "", $tmp[2] ); while( $i < $n && !ereg( "^User comments section follows", $lines[$i] ) ) { $i++; } $i++; if( $i >= $n ) return; while( $i < $n && ereg( "^\t[a-z][a-z]*=", $lines[$i] ) ) { $tmp = split( "=", trim( $lines[$i] ), 2 ); switch( $tmp[0] ) { case "genre": $props["genre"] = $tmp[1]; break; case "title": $props["title"] = $tmp[1]; break; case "artist": $props["artist"] = $tmp[1]; break; case "album": $props["album"] = $tmp[1]; break; // tracknum ??? } $i++; } while( $i < $n && !ereg( "^\tPlayback length: ", $lines[$i] ) ) { $i++; } if( $i >= $n ) return; $tmp = split( " *", $lines[$i] ); $tmp = split( ":", $tmp[2] ); $tn = count($tmp); $i = 0; $secs = 0; while( $i < $tn ) { switch( substr( $tmp[$i], strlen($tmp[$i])-1 ) ) { case "h": $secs += 3600 * substr( $tmp[$i], 0, strlen($tmp[$i])-1 ); break; case "m": $secs += 60 * substr( $tmp[$i], 0, strlen($tmp[$i])-1 ); break; case "s": $secs += ereg_replace( "[.m].*\$", "", $tmp[$i] ); break; } $i++; } $props["length"] = $secs; } function get_fs_dir( $reldir, $music_dir ) { $absdir = $music_dir . "/" . $reldir; $dir = array(); if( is_dir( $absdir ) ) { $dh = opendir( $absdir ); if( $dh ) { while( $name = readdir( $dh ) ) { if( substr( $name, 0, 1 ) != "." ) { $node = array( "indb" => false ); if( is_dir( $absdir . "/" . $name ) ) { $node["type"] = "dir"; // echo "fs dir '$name'\n"; } else if( is_file( $absdir . "/" . $name ) && ereg( "[.]ogg\$", $name ) ) { $abspath = $absdir . "/" . $name; $node["type"] = "file"; $node["filesize"] = filesize( $abspath ); $node["date_mod"] = filemtime( $abspath ); // echo "fs file '$name'\n"; } if( isset( $node["type"] ) ) { $dir[$name] = $node; } } } closedir( $dh ); } } return $dir; } function scan_files( $conn, $reldir, $music_dir ) { echo "*** directory '$reldir' ***\n"; $dbfiles = get_db_dir( $conn, $reldir ); $fsfiles = get_fs_dir( $reldir, $music_dir ); reset( $dbfiles ); while( list( $name, $props ) = each( $dbfiles ) ) { if( !isset( $fsfiles[$name] ) ) { echo " removed '$name'\n"; db_remove( $conn, $reldir, $name, $props["type"] ); } else if( $fsfiles[$name]["type"] != $props["type"] ) { echo " mismatch '$name'\n"; db_remove( $conn, $reldir, $name, $props["type"] ); } else { if( $props["type"] == "file" && ( $fsfiles[$name]["date_mod"] != $props["date_mod"] || $fsfiles[$name]["filesize"] != $props["filesize"] ) ) { echo " modified '$name'\n"; // echo " " . $props["date_mod"] . "\n"; // echo " " . $fsfiles[$name]["date_mod"] . "\n"; $props["date_mod"] = $fsfiles[$name]["date_mod"]; $props["filesize"] = $fsfiles[$name]["filesize"]; if( $reldir == "/" ) { $abspath = $music_dir . "/" . $name; } else { $abspath = $music_dir . "/" . $reldir . "/" . $name; } get_ogg_info( $abspath, $props ); db_update_file( $conn, $reldir, $name, $props ); } $fsfiles[$name]["indb"] = true; } } reset( $fsfiles ); while( list( $name, $props ) = each( $fsfiles ) ) { if( $reldir == "/" ) { $newreldir = $name; $abspath = $music_dir . "/" . $name; } else { $newreldir = $reldir . "/" . $name; $abspath = $music_dir . "/" . $reldir . "/" . $name; } if( !$props["indb"] ) { echo " added '$name'\n"; if( $props["type"] == "file" ) { get_ogg_info( $abspath, $props ); } db_insert( $conn, $reldir, $name, $props ); } if( $props["type"] == "dir" ) { scan_files( $conn, $newreldir, $music_dir ); } } } // printarray( "_SERVER", $_SERVER ); if( !isset( $_SERVER["SERVER_SOFTWARE"] ) ) { $conn = db_connect(); scan_files( $conn, "/", $music_dir ); } ?>