diff --git a/CUETools.CTDB/Web/favicon.ico b/CUETools.CTDB/Web/favicon.ico new file mode 100644 index 0000000..a8346ad Binary files /dev/null and b/CUETools.CTDB/Web/favicon.ico differ diff --git a/CUETools.CTDB/Web/index.php b/CUETools.CTDB/Web/index.php new file mode 100644 index 0000000..1d603f7 --- /dev/null +++ b/CUETools.CTDB/Web/index.php @@ -0,0 +1,65 @@ + + + +CUETools DB + + + +

CUETools Database

+Recent additions:"); +printf(""); +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 == "" ? "" : ''; + //echo $line . ':' . $id . '
'; + 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("
", $artist, $title, $link, substr($line,13,30), $ctdb->db['discs'][0]['CRC ']['int']); +} +printf("
ArtistAlbumDisc IdCTDB Id
%s%s%s%s%x
"); +printf("
Status: %d unique discs.
", filesize("parity/list.txt")/57); +?> + diff --git a/CUETools.CTDB/Web/phpctdb/ctdb.php b/CUETools.CTDB/Web/phpctdb/ctdb.php new file mode 100644 index 0000000..6e35c46 --- /dev/null +++ b/CUETools.CTDB/Web/phpctdb/ctdb.php @@ -0,0 +1,141 @@ +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)
', $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)
', $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, '
'; + 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; + } +} +?> diff --git a/CUETools.CTDB/Web/submit.php b/CUETools.CTDB/Web/submit.php new file mode 100644 index 0000000..a546d57 --- /dev/null +++ b/CUETools.CTDB/Web/submit.php @@ -0,0 +1,168 @@ + + * @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); +?>