#!/usr/bin/env ruby
# cddb.rb $Revision: 2 $
# Copyright (C) 2006  Michitaka Ohno <elpeo@mars.dti.ne.jp>
# You can redistribute it and/or modify it under GPL2.

BEGIN { $stdout.binmode }

require 'nkf'
require 'open-uri'
require 'tmpdir'
require 'rexml/document'

@nkf_option = '-s'

@tmpdir = Dir::tmpdir + '/cddb'
@genre = 'misc'
@cdrom = '/dev/cdrom'

def getXML( query )
	return unless query
	ary = query.split( / / )
	discid = ary.shift
	q = ary.map{|i| '%X' % i.to_i}.join( '+' )
	uri = 'http://windowsmedia.com/redir/QueryTOC.asp?cd=' + q
	open( uri ){|f| f.read}
end

def getInfo( query )
	ret = []
	return ret unless query
	ary = query.split( / / )
	discid = ary.shift
	file = "#{@tmpdir}/#{discid}"
	begin
		ret = File::readlines( file )
	rescue
		return ret if ary.empty?
		xml = getXML( query )
		root = REXML::Document::new( xml ).root
		return unless root
		name = root.elements['//OMI/name']
		author = root.elements['//OMI/author']
		ret << author.text + ' / ' + name.text if name && author
		root.elements.each( '//OMI/track' ){|e| ret << e.elements['name'].text}
		unless ret.empty? then
			Dir::mkdir( @tmpdir ) unless File::directory?( @tmpdir )
			open( file, 'w' ) do |f|
				ret.each{|i| f.puts i}
			end
		end
	end
	ret
end

if ENV['REQUEST_METHOD'] then
	require 'cgi'
	cgi = CGI.new
	cmd = cgi.include?( 'cmd' ) ? cgi.params['cmd'][0].split( / / ) : []
	if cmd[0] == 'motd' then
		print cgi.header( 'type' => 'text/plain' )
		print <<-TEXT
210 Last modified: 04/02/2001 12:00:00 MOTD follows (until terminating `.')
Welcome to #{cgi.server_name}.
This is WindowsMedia to CDDB converter.
.
		TEXT
		exit
	end
	if cmd[0] == 'sites' then
		print cgi.header( 'type' => 'text/plain' )
		print <<-TEXT
210 OK, site information follows (until terminating `.')
#{cgi.server_name} http 80 #{cgi.script_name} N000.00 W000.00 WindowsMedia to CDDB converter
.
		TEXT
		exit
	end
	if cmd[0] != 'cddb' then
		print cgi.header( 'type' => 'text/plain' )
		puts "500 Unrecognized command."
		exit
	end
	case cmd[1]
	when 'query'
		info = getInfo( cmd[2..-1].join( ' ' ) )
		print cgi.header( 'type' => 'text/plain' )
		if info.empty? then
			puts "202 No match for disc ID #{cmd[2]}."
		else
			puts NKF::nkf( "-m0 -W #{@nkf_option}", "200 #{@genre} #{cmd[2]} #{info[0]}" )
		end
	when 'read'
		info = getInfo( cmd[3] )
		print cgi.header( 'type' => 'text/plain' )
		if info.empty? then
			puts "401 #{cmd[2]} #{cmd[3]} No such CD entry in database."
		else
			puts "210 #{cmd[2]} #{cmd[3]} CD database entry follows (until terminating `.')"
			puts "DISCID=#{cmd[3]}"
			title = info.shift
			puts NKF::nkf( "-m0 -W #{@nkf_option}", "DTITLE=#{title}" );
			info.each_index do |i|
				puts NKF::nkf( "-m0 -W #{@nkf_option}", "TTITLE#{i}=#{info[i]}" );
			end
			print <<-TEXT
EXTD=
EXTT0=
EXTT1=
EXTT2=
EXTT3=
EXTT4=
EXTT5=
EXTT6=
EXTT7=
EXTT8=
EXTT9=
EXTT10=
EXTT11=
EXTT12=
PLAYORDER=
.
			TEXT
		end
	else
		print cgi.header( 'type' => 'text/plain' )
		puts "500 Unrecognized command."
	end
	exit
else
	require 'freedb'
	db = Freedb.new( ARGV[0] || @cdrom )
	getInfo( db.query ).each_with_index do |item, index|
		print '%2d. ' % index if index != 0
		puts NKF::nkf( '-m0 -W', item)
	end
end
