mirror of
https://github.com/claunia/cuetools.net.git
synced 2025-12-16 18:14:25 +00:00
CD parity information database
This commit is contained in:
BIN
CUETools.CTDB/Web/favicon.ico
Normal file
BIN
CUETools.CTDB/Web/favicon.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 2.5 KiB |
65
CUETools.CTDB/Web/index.php
Normal file
65
CUETools.CTDB/Web/index.php
Normal file
@@ -0,0 +1,65 @@
|
|||||||
|
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||||
|
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||||
|
<head>
|
||||||
|
<title>CUETools DB</title>
|
||||||
|
<style type="text/css">
|
||||||
|
.style1 {
|
||||||
|
font-size: x-small;
|
||||||
|
font-family: Arial, Helvetica, sans-serif;
|
||||||
|
}
|
||||||
|
.style_fixed {
|
||||||
|
#font-size: x-small;
|
||||||
|
font-family: Courier;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<H1>CUETools Database</H1>
|
||||||
|
<?php
|
||||||
|
require_once( 'phpmb/mbQuery.php' );
|
||||||
|
require_once( 'phpctdb/ctdb.php' );
|
||||||
|
|
||||||
|
$lines=false;
|
||||||
|
$fp = fopen('parity/list.txt','r');
|
||||||
|
$count = 10;
|
||||||
|
fseek($fp, -57 * $count, SEEK_END);
|
||||||
|
while($line=fgets($fp)) {
|
||||||
|
$name = trim($line);
|
||||||
|
if (file_exists($name))
|
||||||
|
$lines[]=$name;
|
||||||
|
if (--$count <= 0)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
fclose($fp);
|
||||||
|
printf("<h3>Recent additions:</h3>");
|
||||||
|
printf("<table border=3><tr><th>Artist</th><th>Album</th><th>Disc Id</th><th>CTDB Id</th></tr>");
|
||||||
|
if ($lines) foreach(array_reverse($lines) as $line) {
|
||||||
|
$ctdb = new phpCTDB($line);
|
||||||
|
$disc = $ctdb->db['discs'][0];
|
||||||
|
$id = @$disc['MBID']['value'];
|
||||||
|
$artist = @$disc['ART ']['value'];
|
||||||
|
$title = @$disc['nam ']['value'];
|
||||||
|
$link = $id == "" ? "<a>" : '<a href="http://musicbrainz.org/bare/cdlookup.html?id=' . $id . '">';
|
||||||
|
//echo $line . ':' . $id . '<br>';
|
||||||
|
if ($artist == "" && $title == "" && $id != "") {
|
||||||
|
//$q = new MusicBrainzQuery(new WebService('db4.cuetools.net'));
|
||||||
|
$q = new MusicBrainzQuery();
|
||||||
|
$rf = new ReleaseFilter();
|
||||||
|
try {
|
||||||
|
$rresults = $q->getReleases( $rf->discId($id) );
|
||||||
|
foreach ( $rresults as $key => $rr ) {
|
||||||
|
$rr = $rr->getRelease();
|
||||||
|
$artist = $rr->getArtist()->getName();
|
||||||
|
$title = $rr->getTitle();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch ( ResponseError $e ) {
|
||||||
|
// echo $e->getMessage() . " ";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
printf("<tr><td>%s</td><td>%s</td><td class=style_fixed>%s%s</a></td><td class=style_fixed>%x</td></tr>", $artist, $title, $link, substr($line,13,30), $ctdb->db['discs'][0]['CRC ']['int']);
|
||||||
|
}
|
||||||
|
printf("</table>");
|
||||||
|
printf("<h5>Status: %d unique discs.</h5>", filesize("parity/list.txt")/57);
|
||||||
|
?>
|
||||||
|
</body>
|
||||||
141
CUETools.CTDB/Web/phpctdb/ctdb.php
Normal file
141
CUETools.CTDB/Web/phpctdb/ctdb.php
Normal file
@@ -0,0 +1,141 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
class phpCTDB{
|
||||||
|
|
||||||
|
private $fp;
|
||||||
|
private $fpstats;
|
||||||
|
private $atoms;
|
||||||
|
public $db;
|
||||||
|
|
||||||
|
function __construct($target_file) {
|
||||||
|
$this->fp = fopen($target_file, 'rb');
|
||||||
|
$this->fpstats = fstat($this->fp);
|
||||||
|
$this->atoms = $this->parse_container_atom(0, $this->fpstats['size']);
|
||||||
|
$this->db = false;
|
||||||
|
foreach ($this->atoms as $entry) if($entry['name'] == 'CTDB') $this->db = $entry;
|
||||||
|
}
|
||||||
|
|
||||||
|
function __destruct() {
|
||||||
|
fclose($this->fp);
|
||||||
|
}
|
||||||
|
|
||||||
|
static function BigEndian2Int($byte_word, $signed = false) {
|
||||||
|
|
||||||
|
$int_value = 0;
|
||||||
|
$byte_wordlen = strlen($byte_word);
|
||||||
|
|
||||||
|
for ($i = 0; $i < $byte_wordlen; $i++) {
|
||||||
|
$int_value += ord($byte_word{$i}) * pow(256, ($byte_wordlen - 1 - $i));
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($signed) {
|
||||||
|
$sign_mask_bit = 0x80 << (8 * ($byte_wordlen - 1));
|
||||||
|
if ($int_value & $sign_mask_bit) {
|
||||||
|
$int_value = 0 - ($int_value & ($sign_mask_bit - 1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $int_value;
|
||||||
|
}
|
||||||
|
|
||||||
|
static function LittleEndian2String($number, $minbytes=1, $synchsafe=false) {
|
||||||
|
$intstring = '';
|
||||||
|
while ($number > 0) {
|
||||||
|
if ($synchsafe) {
|
||||||
|
$intstring = $intstring.chr($number & 127);
|
||||||
|
$number >>= 7;
|
||||||
|
} else {
|
||||||
|
$intstring = $intstring.chr($number & 255);
|
||||||
|
$number >>= 8;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return str_pad($intstring, $minbytes, "\x00", STR_PAD_RIGHT);
|
||||||
|
}
|
||||||
|
|
||||||
|
static function BigEndian2String($number, $minbytes=1, $synchsafe=false) {
|
||||||
|
return strrev(phpCTDB::LittleEndian2String($number, $minbytes, $synchsafe));
|
||||||
|
}
|
||||||
|
|
||||||
|
static function unparse_atom($fp, $atom)
|
||||||
|
{
|
||||||
|
// printf('unparse_atom(%s)<br>', $atom['name']);
|
||||||
|
$offset = ftell($fp);
|
||||||
|
fwrite($fp, phpCTDB::BigEndian2String(0, 4));
|
||||||
|
fwrite($fp, $atom['name']);
|
||||||
|
if (@$atom['subatoms'])
|
||||||
|
foreach ($atom['subatoms'] as $subatom)
|
||||||
|
phpCTDB::unparse_atom($fp, $subatom);
|
||||||
|
else if ($atom['value'])
|
||||||
|
fwrite($fp, $atom['value']);
|
||||||
|
else
|
||||||
|
die(sprintf("couldn't write long atom %s: size %d", $atom['name'], $atom['size']));
|
||||||
|
$pos = ftell($fp);
|
||||||
|
fseek($fp, $offset, SEEK_SET);
|
||||||
|
fwrite($fp, phpCTDB::BigEndian2String($pos - $offset, 4));
|
||||||
|
fseek($fp, $pos, SEEK_SET);
|
||||||
|
}
|
||||||
|
|
||||||
|
function read($offset, $len)
|
||||||
|
{
|
||||||
|
fseek($this->fp, $offset, SEEK_SET);
|
||||||
|
return fread($this->fp, $len);
|
||||||
|
}
|
||||||
|
|
||||||
|
function parse_container_atom($offset, $len)
|
||||||
|
{
|
||||||
|
// printf('parse_container_atom(%d, %d)<br>', $offset, $len);
|
||||||
|
$atoms = false;
|
||||||
|
$fin = $offset + $len;
|
||||||
|
while ($offset < $fin) {
|
||||||
|
fseek($this->fp, $offset, SEEK_SET);
|
||||||
|
$atom_header = fread($this->fp, 8);
|
||||||
|
$atom_size = phpCTDB::BigEndian2Int(substr($atom_header, 0, 4));
|
||||||
|
$atom_name = substr($atom_header, 4, 4);
|
||||||
|
$atom['name'] = $atom_name;
|
||||||
|
$atom['size'] = $atom_size - 8;
|
||||||
|
$atom['offset'] = $offset + 8;
|
||||||
|
if ($atom_size - 8 <= 256)
|
||||||
|
$atom['value'] = fread($this->fp, $atom_size - 8);
|
||||||
|
else
|
||||||
|
$atom['value'] = false;
|
||||||
|
// echo $len, ':', $offset, ":", $atom_size, ":", $atom_name, '<br>';
|
||||||
|
if ($atom_name == 'CTDB' || $atom_name == 'DISC' || $atom_name == 'TOC ' || ($atom_name == 'HEAD' && ($atom_size != 28 || 256 != phpCTDB::BigEndian2Int(substr($atom['value'],0,4)))))
|
||||||
|
{
|
||||||
|
$atom['subatoms'] = $this->parse_container_atom($offset + 8, $atom_size - 8);
|
||||||
|
foreach ($atom['subatoms'] as $param)
|
||||||
|
switch ($param['name']) {
|
||||||
|
case 'HEAD':
|
||||||
|
case 'CRC ':
|
||||||
|
case 'MBID':
|
||||||
|
case 'ART ':
|
||||||
|
case 'nam ':
|
||||||
|
case 'NPAR':
|
||||||
|
case 'CONF':
|
||||||
|
case 'TOTL':
|
||||||
|
case 'PAR ':
|
||||||
|
$atom[$param['name']] = $param;
|
||||||
|
break;
|
||||||
|
case 'DISC':
|
||||||
|
$atom['discs'][] = $param;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
$atom['subatoms'] = false;
|
||||||
|
switch ($atom_name)
|
||||||
|
{
|
||||||
|
case 'CRC ':
|
||||||
|
case 'NPAR':
|
||||||
|
case 'CONF':
|
||||||
|
case 'TOTL':
|
||||||
|
$atom['int'] = phpCTDB::BigEndian2Int($atom['value']);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
$offset += $atom_size;
|
||||||
|
$atoms[] = $atom;
|
||||||
|
}
|
||||||
|
if ($offset > $fin)
|
||||||
|
die(printf("bad atom: offset=%d, fin=%d", $offset, $fin));
|
||||||
|
return $atoms;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
?>
|
||||||
168
CUETools.CTDB/Web/submit.php
Normal file
168
CUETools.CTDB/Web/submit.php
Normal file
@@ -0,0 +1,168 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
require_once( 'phpctdb/ctdb.php' );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert php.ini shorthands to byte
|
||||||
|
*
|
||||||
|
* @author <gilthans dot NO dot SPAM at gmail dot com>
|
||||||
|
* @link http://de3.php.net/manual/en/ini.core.php#79564
|
||||||
|
*/
|
||||||
|
function php_to_byte($v){
|
||||||
|
$l = substr($v, -1);
|
||||||
|
$ret = substr($v, 0, -1);
|
||||||
|
switch(strtoupper($l)){
|
||||||
|
case 'P':
|
||||||
|
$ret *= 1024;
|
||||||
|
case 'T':
|
||||||
|
$ret *= 1024;
|
||||||
|
case 'G':
|
||||||
|
$ret *= 1024;
|
||||||
|
case 'M':
|
||||||
|
$ret *= 1024;
|
||||||
|
case 'K':
|
||||||
|
$ret *= 1024;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return $ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return the human readable size of a file
|
||||||
|
// @param int $size a file size
|
||||||
|
// @param int $dec a number of decimal places
|
||||||
|
|
||||||
|
function filesize_h($size, $dec = 1)
|
||||||
|
{
|
||||||
|
$sizes = array('byte(s)', 'kb', 'mb', 'gb');
|
||||||
|
$count = count($sizes);
|
||||||
|
$i = 0;
|
||||||
|
|
||||||
|
while ($size >= 1024 && ($i < $count - 1)) {
|
||||||
|
$size /= 1024;
|
||||||
|
$i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return round($size, $dec) . ' ' . $sizes[$i];
|
||||||
|
}
|
||||||
|
|
||||||
|
$file = $_FILES['uploadedfile'];
|
||||||
|
|
||||||
|
//echo $file['name'], ini_get('upload_max_filesize');
|
||||||
|
|
||||||
|
// give info on PHP catched upload errors
|
||||||
|
if($file['error']) switch($file['error']){
|
||||||
|
case 1:
|
||||||
|
case 2:
|
||||||
|
echo sprintf($lang['uploadsize'],
|
||||||
|
filesize_h(php_to_byte(ini_get('upload_max_filesize'))));
|
||||||
|
echo "Error ", $file['error'];
|
||||||
|
return;
|
||||||
|
default:
|
||||||
|
echo $lang['uploadfail'];
|
||||||
|
echo "Error ", $file['error'];
|
||||||
|
}
|
||||||
|
|
||||||
|
//if ($_SERVER['HTTP_USER_AGENT'] != "CUETools 205") {
|
||||||
|
// echo "user agent ", $_SERVER['HTTP_USER_AGENT'], " is not allowed";
|
||||||
|
// return;
|
||||||
|
//}
|
||||||
|
|
||||||
|
$tmpname = $file['tmp_name'];
|
||||||
|
$size = (@file_exists($tmpname)) ? filesize($tmpname) : 0;
|
||||||
|
if ($size == 0) {
|
||||||
|
echo "no file uploaded";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$id = $_POST['id'];
|
||||||
|
$err = sscanf($id, "%03d-%04x%04x-%04x%04x-%04x%04x", $tracks, $id1a, $id1b, $id2a, $id2b, $cddbida, $cddbidb);
|
||||||
|
$parsedid = sprintf("%03d-%04x%04x-%04x%04x-%04x%04x", $tracks, $id1a, $id1b, $id2a, $id2b, $cddbida, $cddbidb);
|
||||||
|
if ($id != $parsedid)
|
||||||
|
die("bad id ". $id);
|
||||||
|
|
||||||
|
$target_path = sprintf("parity/%x/%x/%x/%s", $id1b & 15, ($id1b >> 4) & 15, ($id1b >> 8) & 15, $parsedid);
|
||||||
|
$target_file = sprintf("%s/ctdb.bin", $target_path, $parsedid);
|
||||||
|
|
||||||
|
@mkdir($target_path, 0777, true);
|
||||||
|
|
||||||
|
$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);
|
||||||
|
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);
|
||||||
|
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);
|
||||||
|
|
||||||
|
$listfp = fopen("parity/list.txt", 'a');
|
||||||
|
fwrite($listfp, $destname);
|
||||||
|
fwrite($listfp, "\n");
|
||||||
|
fclose($listfp);
|
||||||
|
|
||||||
|
if ($merging)
|
||||||
|
printf("%s has been updated", $parsedid);
|
||||||
|
else
|
||||||
|
printf("%s has been uploaded", $parsedid);
|
||||||
|
?>
|
||||||
Reference in New Issue
Block a user