35
CUETools.CTDB/Web/about.php
Normal file
@@ -0,0 +1,35 @@
|
||||
<?php include 'logo_start.php'; ?>
|
||||
<h2>What's it for?</h2>
|
||||
You probably heard about <a href=http://www.accuraterip.com/>AccurateRip</a>, a wonderfull database of CD rip checksums, which helps you make sure your CD rip is an exact copy of original CD. What it can tell you is how many other people got the same data when copying this CD.
|
||||
|
||||
CUETools Database is an extension of this idea.
|
||||
|
||||
<h2>What are the advantages?</h2>
|
||||
<ul>
|
||||
<li>The most important feature is the ability not only to detect, but also correct small amounts of errors that occured in the ripping process.
|
||||
<li>It's free of the offset problems. You don't even need to set up offset correction for your CD drive to be able to verify and what's more important, submit rips to the database. Different pressings of the same CD are treated as the same disc by the database, it doesn't care.
|
||||
<li>Verification results are easier to deal with. There are exactly three possible outcomes: rip is correct, rip contains correctable errors, rip is unknown (or contains errors beyond repair).
|
||||
<li>If there's a match, you can be certain it's really a match, because in addition to recovery record database uses a well-known CRC32 checksum of the whole CD image (except for 10*588 offset samples in the first and last seconds of the disc). This checksum is used as a rip ID in CTDB.
|
||||
</ul>
|
||||
<h2>What are the downsides and limitations?</h2>
|
||||
<ul>
|
||||
<li>CUETools DB doesn't bother with tracks. Your rip as a whole is either good/correctable, or it isn't. If one of the tracks is damaged beyound repair, CTDB cannot tell which one.
|
||||
<li>If your rip contains errors, verification/correction process will involve downloading about 200kb of data, which is much more than it takes for AccurateRp.
|
||||
<li>Verification process is slower than with AR.
|
||||
<li>Database was just born and at the moment contains much less CDs than AR.
|
||||
</ul>
|
||||
<h2>How many errors can a rip contain and still be repairable?</h2>
|
||||
<ul>
|
||||
<li>That depends. The best case scenario is when there's one continuous damaged area up to 30-40 sectors (about half a second) long.
|
||||
<li>The worst case scenario is 4 non-continuous damaged sectors in (very) unlucky positions.
|
||||
</ul>
|
||||
<h2>What information does the database contain per each submission?</h2>
|
||||
<ul>
|
||||
<li>CD TOC (Table Of Contents), i.e. length of every track.
|
||||
<li>Offset-finding checksum, i.e. small (16 byte) recovery record for a set of samples throughout the CD, which allows to detect the offset difference between the rip in database and your rip, even if your rip contains some errors.
|
||||
<li>CRC32 of the whole disc (except for some leadin/leadout samples).
|
||||
<li>Submission date, artist, title.
|
||||
<li>180kb recovery record, which is stored separately and accessed only when verifying a broken rip or repairing it.
|
||||
</ul>
|
||||
</body>
|
||||
</html>
|
||||
BIN
CUETools.CTDB/Web/img/bg_bottom.jpg
Normal file
|
After Width: | Height: | Size: 9.5 KiB |
BIN
CUETools.CTDB/Web/img/bg_left_border.jpg
Normal file
|
After Width: | Height: | Size: 9.5 KiB |
BIN
CUETools.CTDB/Web/img/bg_right_border.jpg
Normal file
|
After Width: | Height: | Size: 9.5 KiB |
BIN
CUETools.CTDB/Web/img/bg_top_border.jpg
Normal file
|
After Width: | Height: | Size: 9.5 KiB |
BIN
CUETools.CTDB/Web/img/bottom_left_corner.jpg
Normal file
|
After Width: | Height: | Size: 293 B |
BIN
CUETools.CTDB/Web/img/bottom_right_corner.jpg
Normal file
|
After Width: | Height: | Size: 290 B |
BIN
CUETools.CTDB/Web/img/top_left_corner.jpg
Normal file
|
After Width: | Height: | Size: 293 B |
BIN
CUETools.CTDB/Web/img/top_right_corner.jpg
Normal file
|
After Width: | Height: | Size: 293 B |
@@ -1,76 +1,48 @@
|
||||
<?php
|
||||
$listfile="parity/list.txt";
|
||||
$last_modified_time = filemtime($listfile);
|
||||
$etag = md5_file($listfile);
|
||||
|
||||
header("Last-Modified: ".gmdate("D, d M Y H:i:s", $last_modified_time)." GMT");
|
||||
header("ETag: $etag");
|
||||
|
||||
if (@strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE']) == $last_modified_time ||
|
||||
@trim($_SERVER['HTTP_IF_NONE_MATCH']) == $etag) {
|
||||
header("HTTP/1.1 304 Not Modified");
|
||||
exit;
|
||||
}
|
||||
include 'logo_start.php';
|
||||
require_once( 'phpmb/mbQuery.php' );
|
||||
require_once( 'phpctdb/ctdb.php' );
|
||||
|
||||
$lines=false;
|
||||
$totaldiscs=filesize($listfile)/57;
|
||||
$fp = fopen($listfile,'r');
|
||||
$count = 10;
|
||||
//$dbconn = pg_connect("dbname=ctdb user=ctdb_user")
|
||||
// or die('Could not connect: ' . pg_last_error());
|
||||
|
||||
$count = 20;
|
||||
$query = 'SELECT * FROM submissions';
|
||||
$term = ' WHERE ';
|
||||
$url = '';
|
||||
$where_discid=@$_GET['discid'];
|
||||
if ($where_discid != '')
|
||||
{
|
||||
$query = $query . $term . "discid='" . pg_escape_string($where_discid) . "'";
|
||||
$term = ' AND ';
|
||||
$url = $url . '&discid=' . urlencode($where_discid);
|
||||
}
|
||||
$where_artist=@$_GET['artist'];
|
||||
if ($where_artist != '')
|
||||
{
|
||||
$query = $query . $term . "artist ilike '%" . pg_escape_string($where_artist) . "%'";
|
||||
$term = ' AND ';
|
||||
$url = $url . '&artist=' . urlencode($where_artist);
|
||||
}
|
||||
$where_uid=@$_GET['uid'];
|
||||
if ($where_uid != '')
|
||||
{
|
||||
$query = $query . $term . "userid='" . pg_escape_string($where_uid) . "'";
|
||||
$term = ' AND ';
|
||||
$url = $url . '&uid=' . urlencode($where_uid);
|
||||
}
|
||||
$query = $query . " ORDER BY id";
|
||||
$result = pg_query($query) or die('Query failed: ' . pg_last_error());
|
||||
$start = @$_GET['start'];
|
||||
if ($start == "" || $start > $totaldiscs || $start < 0) $start = $totaldiscs - $count;
|
||||
fseek($fp, 57 * $start, SEEK_SET);
|
||||
$n = $count;
|
||||
while($line=fgets($fp)) {
|
||||
$name = trim($line);
|
||||
if (file_exists($name))
|
||||
$lines[]=$name;
|
||||
if (--$n <= 0)
|
||||
break;
|
||||
}
|
||||
fclose($fp);
|
||||
if (pg_num_rows($result) == 0)
|
||||
die('nothing found');
|
||||
if ($count > pg_num_rows($result))
|
||||
$count = pg_num_rows($result);
|
||||
if ($start == '') $start = pg_num_rows($result) - $count;
|
||||
|
||||
printf("<center><h3>Recent additions:</h3>");
|
||||
include 'table_start.php';
|
||||
?>
|
||||
<table class=classy_table cellpadding=3 cellspacing=0><tr bgcolor=#D0D0D0><th>Artist</th><th>Album</th><th>Disc Id</th><th>CTDB Id</th></tr>
|
||||
<?php
|
||||
//<tr background="img/bg_top_border.jpg"><td></td><td width=8 rowspan=12 bgcolor=#FFFFFF></td><td background="img/bg_right_border.jpg" width=4 rowspan=12></td><td></td><td></td><td></td></tr>
|
||||
$imgs = '';
|
||||
if ($lines) foreach(array_reverse($lines) as $line) {
|
||||
$ctdb = new phpCTDB($line);
|
||||
$disc = $ctdb->db['discs'][0];
|
||||
$ctdb->ParseToc();
|
||||
//$id = @$disc['MBID']['value'];
|
||||
$artist = @$disc['ART ']['value'];
|
||||
$title = @$disc['nam ']['value'];
|
||||
$discid = substr($line,13,30);
|
||||
$ctdbid = $ctdb->db['discs'][0]['CRC ']['int'];
|
||||
if ($artist == "" && $title == "")
|
||||
{
|
||||
//$q = new MusicBrainzQuery(new WebService('db4.cuetools.net'));
|
||||
$q = new MusicBrainzQuery();
|
||||
$rf = new ReleaseFilter();
|
||||
try {
|
||||
$rresults = $q->getReleases( $rf->discId($ctdb->mbid) );
|
||||
foreach ( $rresults as $key => $rr ) {
|
||||
$rr = $rr->getRelease();
|
||||
$artist = $rr->getArtist()->getName();
|
||||
$title = $rr->getTitle();
|
||||
$imgs = $imgs . '<img src="http://ec1.images-amazon.com/images/P/' . $rr->getAsin() . '.01.MZZZZZZZ.jpg">';
|
||||
}
|
||||
}
|
||||
catch ( ResponseError $e ) {
|
||||
// echo $e->getMessage() . " ";
|
||||
}
|
||||
}
|
||||
printf('<tr><td class=td_artist>%s</td><td class=td_album>%s</td><td class=td_discid><a href="http://musicbrainz.org/bare/cdlookup.html?id=%s">%s</a></td><td class=td_ctdbid><a href=show.php?discid=%s&ctdbid=%08x>%08x</a></td></tr>', htmlspecialchars($artist), htmlspecialchars($title), $ctdb->mbid, $discid, $discid, $ctdbid, $ctdbid);
|
||||
}
|
||||
printf('<tr><td colspan=4 align=right><a class=style1 href="?start=%d">More</a></td></tr>', $count * floor(($start - 1) / $count));
|
||||
printf("</table>");
|
||||
include 'table_end.php' ;
|
||||
//printf('%s', $imgs);
|
||||
include 'list.php';
|
||||
pg_free_result($result);
|
||||
printf("</center>");
|
||||
?>
|
||||
</body>
|
||||
|
||||
13
CUETools.CTDB/Web/list.php
Normal file
@@ -0,0 +1,13 @@
|
||||
<?php
|
||||
include 'table_start.php';
|
||||
?>
|
||||
<table class=classy_table cellpadding=3 cellspacing=0><tr bgcolor=#D0D0D0><th>Artist</th><th>Album</th><th>Disc Id</th><th>CTDB Id</th><th>AR</th></tr>
|
||||
<?php
|
||||
for($i = $start + $count - 1; $i >= $start; $i--) {
|
||||
$record = pg_fetch_array($result, $i);
|
||||
printf('<tr><td class=td_artist><a href=?artist=%s>%s</a></td><td class=td_album>%s</td><td class=td_discid><a href="?discid=%s">%s</a></td><td class=td_ctdbid><a href=show.php?discid=%s&ctdbid=%08x>%08x</a></td><td class=td_ar>%d</td></tr>', urlencode($record['artist']), $record['artist'], $record['title'], $record['discid'], $record['discid'], $record['discid'], $record['ctdbid'], $record['ctdbid'], $record['confidence']);
|
||||
}
|
||||
if ($start > 0) printf('<tr><td colspan=5 align=right><a class=style1 href="?start=%d%s">More</a></td></tr>', $count * floor(($start - 1) / $count), $url);
|
||||
printf("</table>");
|
||||
include 'table_end.php' ;
|
||||
?>
|
||||
@@ -34,6 +34,11 @@
|
||||
padding: 1px 5px;
|
||||
font-family: Courier;
|
||||
}
|
||||
.td_ar {
|
||||
padding: 1px 5px;
|
||||
text-align: right;
|
||||
font-family: Courier;
|
||||
}
|
||||
.classy_table {
|
||||
border-style:none;
|
||||
# border-color-right: #D0D0D0
|
||||
@@ -43,20 +48,34 @@
|
||||
</head>
|
||||
<body>
|
||||
<table border=0 cellspacing=0 cellpadding=3 align=center>
|
||||
<tr>
|
||||
<td rowspan=3><img src=ctdb.png></td>
|
||||
<td colspan=2 class=td_status>
|
||||
<tr>
|
||||
<td rowspan=3><img width=128 height=128 border=0 alt="" src=ctdb.png></td>
|
||||
<td class=td_status>
|
||||
<?php
|
||||
printf("%d unique discs", filesize("parity/list.txt")/57);
|
||||
$dbconn = pg_connect("dbname=ctdb user=ctdb_user")
|
||||
or die('Could not connect: ' . pg_last_error());
|
||||
$dbresult = pg_query('SELECT * FROM submissions');
|
||||
printf("%d unique discs", pg_num_rows($dbresult));
|
||||
pg_free_result($dbresult);
|
||||
?>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class=style_logo colspan=2>CUETools Database</td>
|
||||
</tr>
|
||||
<tr align=center>
|
||||
<td>About</td>
|
||||
<td><a href=http://www.cuetools.net>CUETools</a></td>
|
||||
</tr>
|
||||
</td>
|
||||
</tr>
|
||||
<tr align=center height=34%>
|
||||
<td class=style_logo>CUETools Database</td>
|
||||
</tr>
|
||||
<tr align=center height=33%>
|
||||
<td>
|
||||
<?php include 'table_start.php'; ?>
|
||||
<table width=300 border=0 cellspacing=8 cellpadding=0 align=center>
|
||||
<tr align=center>
|
||||
<td><a href=/>Home</a></td>
|
||||
<td><a href=/top.php>Popular</a></td>
|
||||
<td><a href=/about.php>About</a></td>
|
||||
<td><a href=http://www.cuetools.net>CUETools</a></td>
|
||||
</tr>
|
||||
</table>
|
||||
<?php include 'table_end.php'; ?>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<br clear=all>
|
||||
|
||||
@@ -7,7 +7,6 @@ class phpCTDB{
|
||||
private $atoms;
|
||||
public $db;
|
||||
public $fulltoc;
|
||||
public $mbid;
|
||||
|
||||
function __construct($target_file) {
|
||||
$this->fp = fopen($target_file, 'rb');
|
||||
@@ -25,7 +24,9 @@ class phpCTDB{
|
||||
{
|
||||
$disc = $this->db['discs'][0];
|
||||
$this->fulltoc = '';
|
||||
$mbtoc = '';
|
||||
$totalcount = 0;
|
||||
$firstaudio = 0;
|
||||
$lastaudio = 0;
|
||||
foreach ($disc['TOC ']['subatoms'] as $track)
|
||||
{
|
||||
if ($track['name']=='INFO') {
|
||||
@@ -36,15 +37,182 @@ class phpCTDB{
|
||||
if ($track['name']=='TRAK') {
|
||||
$isaudio = phpCTDB::BigEndian2Int(substr($track['value'],0,4));
|
||||
$length = phpCTDB::BigEndian2Int(substr($track['value'],4,4));
|
||||
if ($isaudio == 0 && $totalcount!=0)
|
||||
$pos += 11400;
|
||||
$this->fulltoc = sprintf('%s %d', $this->fulltoc, $pos);
|
||||
$mbtoc = sprintf('%s%08X', $mbtoc, $pos);
|
||||
$pos += $length;
|
||||
$totalcount ++;
|
||||
if ($isaudio != 0)
|
||||
$lastaudio = $totalcount;
|
||||
if ($isaudio != 0 && $firstaudio == 0)
|
||||
$firstaudio = $totalcount;
|
||||
}
|
||||
}
|
||||
$this->fulltoc = sprintf('1 %d %d%s', $trackcount, $pos, $this->fulltoc);
|
||||
$mbtoc = sprintf('01%02X%08X%s', $trackcount, $pos, $mbtoc);
|
||||
if ($trackcount != $totalcount)
|
||||
die('wrong trackcount');
|
||||
$this->fulltoc = sprintf('%d %d %d %d%s', $firstaudio, $lastaudio, $totalcount, $pos, $this->fulltoc);
|
||||
}
|
||||
|
||||
static function toc2mbtoc($fulltoc)
|
||||
{
|
||||
$ids = explode(' ', $fulltoc);
|
||||
$mbtoc = sprintf('%d %d', $ids[0], $ids[1]);
|
||||
if ($ids[1] == $ids[2])
|
||||
{
|
||||
for ($tr = 3; $tr < count($ids); $tr++)
|
||||
$mbtoc = sprintf('%s %d', $mbtoc, $ids[$tr]);
|
||||
} else // Enhanced CD
|
||||
{
|
||||
$mbtoc = sprintf('%s %d', $mbtoc, $ids[$ids[1] + 4] - 11400);
|
||||
for ($tr = 4; $tr < $ids[1] + 4; $tr++)
|
||||
$mbtoc = sprintf('%s %d', $mbtoc, $ids[$tr]);
|
||||
}
|
||||
return $mbtoc;
|
||||
}
|
||||
|
||||
static function toc2mbid($fulltoc)
|
||||
{
|
||||
$ids = explode(' ', $fulltoc);
|
||||
$mbtoc = sprintf('%02X%02X', $ids[0], $ids[1]);
|
||||
if ($ids[1] == $ids[2])
|
||||
{
|
||||
for ($tr = 3; $tr < count($ids); $tr++)
|
||||
$mbtoc = sprintf('%s%08X', $mbtoc, $ids[$tr]);
|
||||
} else // Enhanced CD
|
||||
{
|
||||
$mbtoc = sprintf('%s%08X', $mbtoc, $ids[$ids[1] + 4] - 11400);
|
||||
for ($tr = 4; $tr < $ids[1] + 4; $tr++)
|
||||
$mbtoc = sprintf('%s%08X', $mbtoc, $ids[$tr]);
|
||||
}
|
||||
// echo $fulltoc . ':' . $mbtoc . '<br>';
|
||||
$mbtoc = str_pad($mbtoc,804,'0');
|
||||
$this->mbid = str_replace('+', '.', str_replace('/', '_', str_replace('=', '-', base64_encode(pack("H*" , sha1($mbtoc))))));
|
||||
$mbid = str_replace('+', '.', str_replace('/', '_', str_replace('=', '-', base64_encode(pack("H*" , sha1($mbtoc))))));
|
||||
return $mbid;
|
||||
}
|
||||
|
||||
static function mblookup($mbid)
|
||||
{
|
||||
$mbconn = pg_connect("dbname=musicbrainz_db user=musicbrainz_user");
|
||||
if (!$mbconn)
|
||||
return false;
|
||||
$mbresult = pg_query_params('SELECT DISTINCT album'
|
||||
. ' FROM album_cdtoc, cdtoc'
|
||||
. ' WHERE album_cdtoc.cdtoc = cdtoc.id'
|
||||
. ' AND cdtoc.discid = $1',
|
||||
array($mbid)
|
||||
);
|
||||
$mbmeta = false;
|
||||
while(true == ($mbrecord = pg_fetch_array($mbresult)))
|
||||
{
|
||||
$mbresult2 = pg_query_params('SELECT a.name as albumname, ar.name as artistname, coverarturl'
|
||||
. ' FROM album a INNER JOIN albummeta m ON m.id = a.id, artist ar'
|
||||
. ' WHERE a.id = $1'
|
||||
. ' AND ar.id = a.artist',
|
||||
array($mbrecord[0]));
|
||||
$mbmeta[] = pg_fetch_array($mbresult2);
|
||||
pg_free_result($mbresult2);
|
||||
}
|
||||
pg_free_result($mbresult);
|
||||
return $mbmeta;
|
||||
}
|
||||
|
||||
function ctdb2pg($discid)
|
||||
{
|
||||
$disc = $this->db['discs'][0];
|
||||
$record = false;
|
||||
$record['discid'] = $discid;
|
||||
$record['ctdbid'] = $disc['CRC ']['int'];
|
||||
$record['confidence'] = $disc['CONF']['int'];
|
||||
$record['parity'] = base64_encode($this->read($disc['PAR ']['offset'], 16));
|
||||
$record['fulltoc'] = $this->fulltoc;
|
||||
$record['userid'] = $disc['USER']['value'];
|
||||
$record['agent'] = $disc['TOOL']['value'];
|
||||
$record['time'] = date ("Y-m-d H:i:s");
|
||||
$record['artist'] = @$disc['ART ']['value'];
|
||||
$record['title'] = @$disc['nam ']['value'];
|
||||
return $record;
|
||||
}
|
||||
|
||||
static function pg2ctdb($dbconn, $id)
|
||||
{
|
||||
$target_path = phpCTDB::discid2path($id);
|
||||
|
||||
$result = pg_query_params($dbconn, "SELECT * FROM submissions WHERE discid=$1", array($id))
|
||||
or die('Query failed: ' . pg_last_error());
|
||||
if (pg_num_rows($result) < 1) die('not found');
|
||||
|
||||
$totalconf = 0;
|
||||
$newctdb = false;
|
||||
$newctdb['name'] = 'CTDB';
|
||||
$newhead = false;
|
||||
$newhead['name'] = 'HEAD';
|
||||
$newtotal = false;
|
||||
$newtotal['name'] = 'TOTL';
|
||||
$newtotal['value'] = phpCTDB::BigEndian2String($totalconf,4);
|
||||
$newhead['subatoms'][] = $newtotal;
|
||||
$newctdb['subatoms'][] = $newhead;
|
||||
|
||||
while (TRUE == ($record = pg_fetch_array($result)))
|
||||
{
|
||||
$totalconf += $record['confidence'];
|
||||
$newdisc = false;
|
||||
$newdisc['name'] = 'DISC';
|
||||
|
||||
$newatom = false;
|
||||
$newatom['name'] = 'CRC ';
|
||||
$newatom['value'] = phpCTDB::Hex2String(sprintf('%08x',$record['ctdbid']));
|
||||
$newdisc['subatoms'][] = $newatom;
|
||||
|
||||
$newatom = false;
|
||||
$newatom['name'] = 'NPAR';
|
||||
$newatom['value'] = phpCTDB::BigEndian2String(8,4);
|
||||
$newdisc['subatoms'][] = $newatom;
|
||||
|
||||
$newatom = false;
|
||||
$newatom['name'] = 'CONF';
|
||||
$newatom['value'] = phpCTDB::BigEndian2String((int)($record['confidence']),4);
|
||||
$newdisc['subatoms'][] = $newatom;
|
||||
|
||||
$newatom = false;
|
||||
$newatom['name'] = 'PAR ';
|
||||
$newatom['value'] = base64_decode($record['parity']);
|
||||
$newdisc['subatoms'][] = $newatom;
|
||||
|
||||
$newctdb['subatoms'][] = $newdisc;
|
||||
}
|
||||
|
||||
pg_free_result($result);
|
||||
|
||||
$newctdb['subatoms'][0]['subatoms'][0]['value'] = phpCTDB::BigEndian2String($totalconf,4);
|
||||
|
||||
$ftyp=false;
|
||||
$ftyp['name'] = 'ftyp';
|
||||
$ftyp['value'] = 'CTDB';
|
||||
|
||||
$tname = sprintf("%s/ctdb.tmp", $target_path);
|
||||
$tfp = fopen($tname, 'wb');
|
||||
phpCTDB::unparse_atom($tfp,$ftyp);
|
||||
phpCTDB::unparse_atom($tfp,$newctdb);
|
||||
fclose($tfp);
|
||||
if(!rename($tname,sprintf("%s/ctdb.bin", $target_path)))
|
||||
die('error uploading file ' . $target_path);
|
||||
}
|
||||
|
||||
static function Hex2Int($hex_word, $signed = false)
|
||||
{
|
||||
$int_value = 0;
|
||||
$byte_wordlen = strlen($hex_word);
|
||||
for ($i = 0; $i < $byte_wordlen; $i++) {
|
||||
sscanf($hex_word{$i}, "%x", $digit);
|
||||
$int_value += $digit * pow(16, ($byte_wordlen - 1 - $i));
|
||||
}
|
||||
if ($signed) {
|
||||
$sign_mask_bit = 0x80 << 24;
|
||||
if ($int_value & $sign_mask_bit) {
|
||||
$int_value = 0 - ($int_value & ($sign_mask_bit - 1));
|
||||
}
|
||||
}
|
||||
return $int_value;
|
||||
}
|
||||
|
||||
static function BigEndian2Int($byte_word, $signed = false) {
|
||||
@@ -66,6 +234,17 @@ class phpCTDB{
|
||||
return $int_value;
|
||||
}
|
||||
|
||||
static function Hex2String($number)
|
||||
{
|
||||
$intstring = '';
|
||||
$hex_word = str_pad($number, 8, '0', STR_PAD_LEFT);
|
||||
for ($i = 0; $i < 4; $i++) {
|
||||
sscanf(substr($hex_word, $i*2, 2), "%x", $number);
|
||||
$intstring = $intstring.chr($number);
|
||||
}
|
||||
return $intstring;
|
||||
}
|
||||
|
||||
static function LittleEndian2String($number, $minbytes=1, $synchsafe=false) {
|
||||
$intstring = '';
|
||||
while ($number > 0) {
|
||||
@@ -154,6 +333,8 @@ class phpCTDB{
|
||||
case 'HEAD':
|
||||
case 'TOC ':
|
||||
case 'CRC ':
|
||||
case 'USER':
|
||||
case 'TOOL':
|
||||
case 'MBID':
|
||||
case 'ART ':
|
||||
case 'nam ':
|
||||
|
||||
4
CUETools.CTDB/Web/robots.txt
Normal file
@@ -0,0 +1,4 @@
|
||||
User-agent: *
|
||||
Disallow: /show.php
|
||||
Disallow: /top.php
|
||||
Disallow: /parity/
|
||||
@@ -1,37 +1,47 @@
|
||||
<?php
|
||||
//mb_http_output('UTF-8');
|
||||
//mb_internal_encoding('UTF-8');
|
||||
include 'logo_start.php';
|
||||
require_once( 'phpmb/mbQuery.php' );
|
||||
//require_once( 'phpmb/mbQuery.php' );
|
||||
require_once( 'phpctdb/ctdb.php' );
|
||||
|
||||
$discid = $_GET['discid'];
|
||||
$ctdbid = $_GET['ctdbid'];
|
||||
$path = phpCTDB::ctdbid2path($discid, $ctdbid);
|
||||
$ctdb = new phpCTDB($path);
|
||||
$disc = $ctdb->db['discs'][0];
|
||||
//$id = @$disc['MBID']['value'];
|
||||
$ctdb->ParseTOC();
|
||||
$artist = @$disc['ART ']['value'];
|
||||
$title = @$disc['nam ']['value'];
|
||||
$link = '<a href="http://musicbrainz.org/bare/cdlookup.html?id=' . $ctdb->mbid . '">';
|
||||
$q = new MusicBrainzQuery();
|
||||
$rf = new ReleaseFilter();
|
||||
$mbrr = false;
|
||||
try {
|
||||
$rresults = $q->getReleases( $rf->discId($ctdb->mbid) );
|
||||
foreach ( $rresults as $key => $rr ) {
|
||||
$mbrr = $rr->getRelease();
|
||||
}
|
||||
}
|
||||
catch ( ResponseError $e ) {
|
||||
// echo $e->getMessage() . " ";
|
||||
|
||||
$last_modified_time = filemtime($path);
|
||||
$etag = md5_file($path);
|
||||
|
||||
header("Last-Modified: ".gmdate("D, d M Y H:i:s", $last_modified_time)." GMT");
|
||||
header("ETag: $etag");
|
||||
|
||||
if (@strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE']) == $last_modified_time ||
|
||||
@trim($_SERVER['HTTP_IF_NONE_MATCH']) == $etag) {
|
||||
header("HTTP/1.1 304 Not Modified");
|
||||
exit;
|
||||
}
|
||||
|
||||
$result = pg_query_params($dbconn, "SELECT * FROM submissions WHERE discid=$1 AND ctdbid=$2", array($discid, (int)phpCTDB::Hex2Int($ctdbid)))
|
||||
or die('Query failed: ' . pg_last_error());
|
||||
if (pg_num_rows($result) < 1) die('not found');
|
||||
if (pg_num_rows($result) > 1) die('not unique');
|
||||
$record = pg_fetch_array($result);
|
||||
pg_free_result($result);
|
||||
|
||||
$mbid = phpCTDB::toc2mbid($record['fulltoc']);
|
||||
$mbmeta = phpCTDB::mblookup($mbid);
|
||||
|
||||
printf('<center>');
|
||||
if ($mbrr && $mbrr->getAsin())
|
||||
{
|
||||
include 'table_start.php';
|
||||
$imgurl = 'http://ec1.images-amazon.com/images/P/' . $mbrr->getAsin() . '.01.MZZZZZZZ.jpg';
|
||||
#$imgurl = 'http://images.amazon.com/images/P/' . $mbrr->getAsin() . '.01._SCLZZZZZZZ_PU_PU-5_.jpg';
|
||||
printf('<img src="%s">', $imgurl);
|
||||
$imgfound = false;
|
||||
if ($mbmeta)
|
||||
foreach ($mbmeta as $mbr)
|
||||
if ($mbr['coverarturl'])
|
||||
{
|
||||
if (!$imgfound) include 'table_start.php';
|
||||
printf('<img src="%s">', $mbr['coverarturl']);
|
||||
$imgfound = true;
|
||||
}
|
||||
if ($imgfound) {
|
||||
include 'table_end.php';
|
||||
printf('<br><br>');
|
||||
}
|
||||
@@ -39,14 +49,47 @@ include 'table_start.php';
|
||||
?>
|
||||
<table border=0 cellspacing=0 cellpadding=6>
|
||||
<?php
|
||||
printf('<tr><td>Full TOC</td><td>%s</td></tr>', $ctdb->fulltoc);
|
||||
printf('<tr><td>Artist</td><td>%s</td></tr>', $artist);
|
||||
if ($mbrr && $mbrr->getArtist()->getName() != $artist)
|
||||
printf('<tr><td>Artist (MB)</td><td>%s</td></tr>', $mbrr->getArtist()->getName());
|
||||
printf('<tr><td>Title</td><td>%s</td></tr>', $title);
|
||||
if ($mbrr && $mbrr->getTitle() != $title)
|
||||
printf('<tr><td>Title (MB)</td><td>%s</td></tr>', $mbrr->getTitle());
|
||||
printf('<tr><td>MusicbrainzId</td><td>%s%s</a></tr>', $link, $ctdb->mbid);
|
||||
printf('<tr><td>Disc ID</td><td>%s</td></tr>', $discid);
|
||||
printf('<tr><td>CTDB ID</td><td>%s</td></tr>', $ctdbid);
|
||||
printf('<tr><td>Musicbrainz ID</td><td><a href="http://musicbrainz.org/bare/cdlookup.html?toc=%s">%s</a> (%s)</tr>', phpCTDB::toc2mbtoc($record['fulltoc']), $mbid, $mbmeta ? count($mbmeta) : "-");
|
||||
//printf('<tr><td>Full TOC</td><td>%s</td></tr>', $record['fulltoc']);
|
||||
printf('<tr><td colspan=2>');
|
||||
?>
|
||||
<table width=100% class=classy_table cellpadding=3 cellspacing=0><tr bgcolor=#D0D0D0><th>Track</th><th>Start</th><th>Length</th><th>Start sector</th><th>End sector</th></tr>
|
||||
<?php
|
||||
function TimeToString($time)
|
||||
{
|
||||
$frame = $time % 75;
|
||||
$time = floor($time/75);
|
||||
$sec = $time % 60;
|
||||
$time = floor($time/60);
|
||||
$min = $time;
|
||||
return sprintf('%d:%02d.%02d',$min,$sec,$frame);
|
||||
}
|
||||
$ids = explode(' ', $record['fulltoc']);
|
||||
for ($tr = 4; $tr < count($ids); $tr++)
|
||||
{
|
||||
$trno = $tr + $ids[0] - 4;
|
||||
$trstart = $ids[$tr] - 150;
|
||||
$trend = (($tr + 1) < count($ids) ? $ids[$tr+1] : $ids[3]) - 151;
|
||||
$trstartmsf = TimeToString($trstart);
|
||||
$trlenmsf = TimeToString($trend + 1 - $trstart);
|
||||
printf('<tr><td class=td_ar>%d</td><td class=td_ar>%s</td><td class=td_ar>%s</td><td class=td_ar>%d</td><td class=td_ar>%d</td></tr>', $trno, $trstartmsf, $trlenmsf, $trstart, $trend);
|
||||
}
|
||||
printf("</table>");
|
||||
printf('</td></tr>');
|
||||
if ($record['artist'] != '')
|
||||
printf('<tr><td>Artist</td><td>%s</td></tr>', $record['artist']);
|
||||
if ($mbmeta)
|
||||
foreach ($mbmeta as $mbr)
|
||||
if ($mbr['artistname'] != $record['artist'])
|
||||
printf('<tr><td>Artist (MB)</td><td>%s</td></tr>', $mbr['artistname']);
|
||||
if ($record['title'] != '')
|
||||
printf('<tr><td>Title</td><td>%s</td></tr>', $record['title']);
|
||||
if ($mbmeta)
|
||||
foreach ($mbmeta as $mbr)
|
||||
if ($mbr['albumname'] != $record['title'])
|
||||
printf('<tr><td>Title (MB)</td><td>%s</td></tr>', $mbr['albumname']);
|
||||
?>
|
||||
</table>
|
||||
<?php include 'table_end.php'; ?>
|
||||
|
||||
@@ -74,86 +74,27 @@ if ($size == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
$dbconn = pg_connect("dbname=ctdb user=ctdb_user")
|
||||
or die('Could not connect: ' . pg_last_error());
|
||||
|
||||
$id = $_POST['id'];
|
||||
$target_path = phpCTDB::discid2path($id);
|
||||
@mkdir($target_path, 0777, true);
|
||||
$target_file = sprintf("%s/ctdb.bin", $target_path);
|
||||
|
||||
$ctdb = new phpCTDB($tmpname);
|
||||
$ctdb1 = @file_exists($target_file) ? new phpCTDB($target_file) : false;
|
||||
$merging = $ctdb1 ? true : false;
|
||||
|
||||
$ftyp['name'] = 'ftyp';
|
||||
$ftyp['value'] = 'CTDB';
|
||||
|
||||
$newctdb['name'] = 'CTDB';
|
||||
$newhead['name'] = 'HEAD';
|
||||
$newtotal['name'] = 'TOTL';
|
||||
$newtotal['value'] = $ctdb1 ? phpCTDB::BigEndian2String($ctdb1->db['HEAD']['TOTL']['int'] + 1,4) : $ctdb->db['HEAD']['TOTL']['value'];
|
||||
$newhead['subatoms'][] = $newtotal;
|
||||
$newctdb['subatoms'][] = $newhead;
|
||||
|
||||
if ($ctdb1)
|
||||
foreach ($ctdb1->db['subatoms'] as $disc)
|
||||
if ($disc['name'] == 'DISC')
|
||||
{
|
||||
if ($crc == $disc['CRC ']['value'])
|
||||
die("duplicate entry");
|
||||
|
||||
$newdisc = false;
|
||||
$newdisc['name'] = 'DISC';
|
||||
$newdisc['subatoms'][] = $disc['CRC '];
|
||||
$newdisc['subatoms'][] = $disc['NPAR'];
|
||||
$newdisc['subatoms'][] = $disc['CONF'];
|
||||
$newpar['name'] = 'PAR ';
|
||||
$newpar['value'] = $ctdb1->read($disc['PAR ']['offset'], 16);
|
||||
$newdisc['subatoms'][] = $newpar;
|
||||
$newctdb['subatoms'][] = $newdisc;
|
||||
}
|
||||
|
||||
$discs = 0;
|
||||
foreach ($ctdb->db['subatoms'] as $disc)
|
||||
if ($disc['name'] == 'DISC')
|
||||
{
|
||||
$crc = $disc['CRC ']['value'];
|
||||
|
||||
$newdisc = false;
|
||||
$newdisc['name'] = 'DISC';
|
||||
$newdisc['subatoms'][] = $disc['CRC '];
|
||||
$newdisc['subatoms'][] = $disc['NPAR'];
|
||||
$newdisc['subatoms'][] = $disc['CONF'];
|
||||
$newpar['name'] = 'PAR ';
|
||||
$newpar['value'] = $ctdb->read($disc['PAR ']['offset'], 16);
|
||||
$newdisc['subatoms'][] = $newpar;
|
||||
$newctdb['subatoms'][] = $newdisc;
|
||||
$discs++;
|
||||
}
|
||||
if ($discs > 1)
|
||||
die('One disc at a time, please');
|
||||
if ($discs < 1)
|
||||
die('No disc records found');
|
||||
|
||||
$tname = sprintf("%s/ctdb.tmp", $target_path);
|
||||
$tfp = fopen($tname, 'wb');
|
||||
phpCTDB::unparse_atom($tfp,$ftyp);
|
||||
phpCTDB::unparse_atom($tfp,$newctdb);
|
||||
fclose($tfp);
|
||||
$merging = @file_exists($target_file);
|
||||
$ctdb->ParseTOC();
|
||||
$record = $ctdb->ctdb2pg($id);
|
||||
unset($ctdb);
|
||||
unset($ctdb1);
|
||||
|
||||
$crca = phpCTDB::BigEndian2Int(substr($crc,0,2));
|
||||
$crcb = phpCTDB::BigEndian2Int(substr($crc,2,2));
|
||||
$destname = sprintf("%s/%04x%04x.bin", $target_path, $crca, $crcb);
|
||||
$destname = sprintf("%s/%08x.bin", $target_path, $record['ctdbid']);
|
||||
if(!move_uploaded_file($tmpname, $destname))
|
||||
die('error uploading file ' . $tmpname . ' to ' . $destname);
|
||||
|
||||
if(!rename($tname,sprintf("%s/ctdb.bin", $target_path)))
|
||||
die('error uploading file ' . $target_path);
|
||||
$subres = pg_insert($dbconn, 'submissions', $record);
|
||||
|
||||
$listfp = fopen("parity/list.txt", 'a');
|
||||
fwrite($listfp, $destname);
|
||||
fwrite($listfp, "\n");
|
||||
fclose($listfp);
|
||||
phpCTDB::pg2ctdb($dbconn, $id);
|
||||
|
||||
if ($merging)
|
||||
printf("%s has been updated", $id);
|
||||
|
||||
48
CUETools.CTDB/Web/top.php
Normal file
@@ -0,0 +1,48 @@
|
||||
<?php
|
||||
include 'logo_start.php';
|
||||
require_once( 'phpmb/mbQuery.php' );
|
||||
require_once( 'phpctdb/ctdb.php' );
|
||||
|
||||
//$dbconn = pg_connect("dbname=ctdb user=ctdb_user")
|
||||
// or die('Could not connect: ' . pg_last_error());
|
||||
|
||||
$count = 20;
|
||||
$query = 'SELECT * FROM submissions';
|
||||
$term = ' WHERE ';
|
||||
$url = '';
|
||||
|
||||
$where_discid=@$_GET['discid'];
|
||||
if ($where_discid != '')
|
||||
{
|
||||
$query = $query . $term . "discid='" . pg_escape_string($where_discid) . "'";
|
||||
$term = ' AND ';
|
||||
$url = $url . '&discid=' . urlencode($where_discid);
|
||||
}
|
||||
$where_artist=@$_GET['artist'];
|
||||
if ($where_artist != '')
|
||||
{
|
||||
$query = $query . $term . "artist ilike '" . pg_escape_string($where_artist) . "'";
|
||||
$term = ' AND ';
|
||||
$url = $url . '&artist=' . urlencode($where_artist);
|
||||
}
|
||||
if ($term == ' WHERE ')
|
||||
{
|
||||
$query = $query . $term . "confidence>=100";
|
||||
$term = ' AND ';
|
||||
}
|
||||
$query = $query . " ORDER BY confidence";
|
||||
$result = pg_query($query) or die('Query failed: ' . pg_last_error());
|
||||
$start = @$_GET['start'];
|
||||
if (pg_num_rows($result) == 0)
|
||||
die('nothing found');
|
||||
if ($count > pg_num_rows($result))
|
||||
$count = pg_num_rows($result);
|
||||
if ($start == '') $start = pg_num_rows($result) - $count;
|
||||
|
||||
printf("<center><h3>Popular discs:</h3>");
|
||||
include 'list.php';
|
||||
pg_free_result($result);
|
||||
printf("</center>");
|
||||
?>
|
||||
</body>
|
||||
</html>
|
||||