2010-02-18 21:12:44 +00:00
|
|
|
|
using System;
|
|
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
|
using System.Collections.Specialized;
|
|
|
|
|
|
using System.Globalization;
|
|
|
|
|
|
using System.IO;
|
2010-02-23 15:15:08 +00:00
|
|
|
|
using System.Management;
|
2010-02-18 21:12:44 +00:00
|
|
|
|
using System.Net;
|
2010-06-11 17:54:37 +00:00
|
|
|
|
using System.Security.Cryptography;
|
2011-10-24 14:32:51 +00:00
|
|
|
|
using System.Text;
|
|
|
|
|
|
using System.Xml.Serialization;
|
2010-04-23 19:59:42 +00:00
|
|
|
|
using CUETools.AccurateRip;
|
2011-10-24 14:32:51 +00:00
|
|
|
|
using CUETools.CDImage;
|
2011-10-27 20:50:11 +00:00
|
|
|
|
using CUETools.Parity;
|
2010-02-18 21:12:44 +00:00
|
|
|
|
using Krystalware.UploadHelper;
|
|
|
|
|
|
|
|
|
|
|
|
namespace CUETools.CTDB
|
|
|
|
|
|
{
|
|
|
|
|
|
public class CUEToolsDB
|
|
|
|
|
|
{
|
2011-06-13 20:25:13 +00:00
|
|
|
|
const string defaultServer = "db.cuetools.net";
|
2011-06-11 19:26:25 +00:00
|
|
|
|
string urlbase;
|
2010-02-28 21:04:34 +00:00
|
|
|
|
string userAgent;
|
2011-05-06 20:22:21 +00:00
|
|
|
|
string driveName;
|
2010-02-23 23:24:54 +00:00
|
|
|
|
|
2010-02-18 21:12:44 +00:00
|
|
|
|
private CDRepairEncode verify;
|
|
|
|
|
|
private CDImageLayout toc;
|
2010-02-23 15:15:08 +00:00
|
|
|
|
private string subResult;
|
2010-02-18 21:12:44 +00:00
|
|
|
|
private int length;
|
|
|
|
|
|
private int total;
|
2011-05-28 15:03:49 +00:00
|
|
|
|
private List<DBEntry> entries = new List<DBEntry>();
|
|
|
|
|
|
private List<CTDBResponseMeta> metadata = new List<CTDBResponseMeta>();
|
|
|
|
|
|
private DBEntry selectedEntry;
|
|
|
|
|
|
private IWebProxy proxy;
|
|
|
|
|
|
private HttpUploadHelper uploadHelper;
|
|
|
|
|
|
private HttpWebRequest currentReq;
|
|
|
|
|
|
private int connectTimeout, socketTimeout;
|
2010-02-18 21:12:44 +00:00
|
|
|
|
|
2010-02-23 15:15:08 +00:00
|
|
|
|
public CUEToolsDB(CDImageLayout toc, IWebProxy proxy)
|
2010-02-18 21:12:44 +00:00
|
|
|
|
{
|
|
|
|
|
|
this.toc = toc;
|
|
|
|
|
|
this.length = (int)toc.AudioLength * 588;
|
2010-02-23 15:15:08 +00:00
|
|
|
|
this.proxy = proxy;
|
|
|
|
|
|
this.uploadHelper = new HttpUploadHelper();
|
2011-05-28 15:03:49 +00:00
|
|
|
|
this.QueryExceptionStatus = WebExceptionStatus.Pending;
|
|
|
|
|
|
this.connectTimeout = 15000;
|
|
|
|
|
|
this.socketTimeout = 30000;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public void CancelRequest()
|
|
|
|
|
|
{
|
|
|
|
|
|
var r = currentReq;
|
|
|
|
|
|
// copy link to currentReq, because it can be set to null by other thread.
|
|
|
|
|
|
if (r != null)
|
|
|
|
|
|
{
|
|
|
|
|
|
r.Abort();
|
|
|
|
|
|
}
|
2010-02-18 21:12:44 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
2011-09-08 18:25:54 +00:00
|
|
|
|
public void ContactDB(string server, string userAgent, string driveName, bool ctdb, bool fuzzy, CTDBMetadataSearch metadataSearch)
|
2010-02-18 21:12:44 +00:00
|
|
|
|
{
|
2011-05-06 20:22:21 +00:00
|
|
|
|
this.driveName = driveName;
|
|
|
|
|
|
this.userAgent = userAgent + " (" + Environment.OSVersion.VersionString + ")" + (driveName != null ? " (" + driveName + ")" : "");
|
2011-06-11 19:26:25 +00:00
|
|
|
|
this.urlbase = "http://" + (server ?? defaultServer);
|
2010-03-20 07:09:07 +00:00
|
|
|
|
this.total = 0;
|
2010-02-18 21:12:44 +00:00
|
|
|
|
|
2011-05-15 17:41:14 +00:00
|
|
|
|
HttpWebRequest req = (HttpWebRequest)WebRequest.Create(urlbase
|
2011-06-26 00:02:29 +00:00
|
|
|
|
+ "/lookup2.php"
|
|
|
|
|
|
+ "?ctdb=" + (ctdb ? "1" : "0")
|
2011-09-08 18:25:54 +00:00
|
|
|
|
+ "&fuzzy=" + (fuzzy ? 1 : 0)
|
|
|
|
|
|
+ "&metadata=" + (metadataSearch == CTDBMetadataSearch.None ? "none" : metadataSearch == CTDBMetadataSearch.Fast ? "fast" : metadataSearch == CTDBMetadataSearch.Default ? "default" : "extensive")
|
2011-05-15 17:41:14 +00:00
|
|
|
|
+ "&toc=" + toc.ToString());
|
2010-03-20 07:09:07 +00:00
|
|
|
|
req.Method = "GET";
|
|
|
|
|
|
req.Proxy = proxy;
|
2011-05-15 17:41:14 +00:00
|
|
|
|
req.UserAgent = this.userAgent;
|
2011-05-28 15:03:49 +00:00
|
|
|
|
req.Timeout = connectTimeout;
|
|
|
|
|
|
req.ReadWriteTimeout = socketTimeout;
|
2011-06-13 20:25:13 +00:00
|
|
|
|
req.AutomaticDecompression = DecompressionMethods.Deflate | DecompressionMethods.GZip;
|
2010-03-20 07:09:07 +00:00
|
|
|
|
|
|
|
|
|
|
if (uploadHelper.onProgress != null)
|
|
|
|
|
|
uploadHelper.onProgress(this, new UploadProgressEventArgs(req.RequestUri.AbsoluteUri, 0));
|
|
|
|
|
|
|
2011-05-28 15:03:49 +00:00
|
|
|
|
currentReq = req;
|
2010-03-20 07:09:07 +00:00
|
|
|
|
try
|
|
|
|
|
|
{
|
2011-05-28 15:03:49 +00:00
|
|
|
|
using (HttpWebResponse resp = (HttpWebResponse)req.GetResponse())
|
2010-03-20 07:09:07 +00:00
|
|
|
|
{
|
2011-05-28 15:03:49 +00:00
|
|
|
|
this.QueryExceptionStatus = WebExceptionStatus.ProtocolError;
|
|
|
|
|
|
this.QueryResponseStatus = resp.StatusCode;
|
|
|
|
|
|
if (this.QueryResponseStatus == HttpStatusCode.OK)
|
2010-03-20 07:09:07 +00:00
|
|
|
|
{
|
2011-05-28 15:03:49 +00:00
|
|
|
|
XmlSerializer serializer = new XmlSerializer(typeof(CTDBResponse));
|
|
|
|
|
|
this.total = 0;
|
|
|
|
|
|
using (Stream responseStream = resp.GetResponseStream())
|
|
|
|
|
|
{
|
|
|
|
|
|
CTDBResponse ctdbResp = serializer.Deserialize(responseStream) as CTDBResponse;
|
|
|
|
|
|
if (ctdbResp.entry != null)
|
|
|
|
|
|
foreach (var ctdbRespEntry in ctdbResp.entry)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (ctdbRespEntry.toc == null)
|
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
|
|
var parity = Convert.FromBase64String(ctdbRespEntry.parity);
|
|
|
|
|
|
var entry_toc = CDImageLayout.FromString(ctdbRespEntry.toc);
|
|
|
|
|
|
this.total += ctdbRespEntry.confidence;
|
2011-10-27 20:50:11 +00:00
|
|
|
|
|
|
|
|
|
|
if (parity.Length != ctdbRespEntry.npar * 2)
|
|
|
|
|
|
throw new Exception("invalid parity length");
|
|
|
|
|
|
//if (verify.Stride != ctdbRespEntry.stride * 2)
|
|
|
|
|
|
// throw new Exception("invalid stride length");
|
|
|
|
|
|
var syndrome = ParityToSyndrome.Parity2Syndrome(1, ctdbRespEntry.npar, ctdbRespEntry.npar, parity);
|
2011-05-28 15:03:49 +00:00
|
|
|
|
var entry = new DBEntry(
|
2011-10-27 20:50:11 +00:00
|
|
|
|
syndrome,
|
2011-05-28 15:03:49 +00:00
|
|
|
|
ctdbRespEntry.confidence,
|
2011-10-27 20:50:11 +00:00
|
|
|
|
ctdbRespEntry.stride * 2,
|
2011-05-28 15:03:49 +00:00
|
|
|
|
uint.Parse(ctdbRespEntry.crc32, NumberStyles.HexNumber),
|
|
|
|
|
|
ctdbRespEntry.id,
|
|
|
|
|
|
entry_toc,
|
|
|
|
|
|
ctdbRespEntry.hasparity);
|
|
|
|
|
|
entries.Add(entry);
|
|
|
|
|
|
}
|
|
|
|
|
|
if (ctdbResp.musicbrainz != null && ctdbResp.musicbrainz.Length != 0)
|
|
|
|
|
|
metadata.AddRange(ctdbResp.musicbrainz);
|
|
|
|
|
|
}
|
|
|
|
|
|
if (entries.Count == 0)
|
|
|
|
|
|
this.QueryResponseStatus = HttpStatusCode.NotFound;
|
|
|
|
|
|
else
|
|
|
|
|
|
this.QueryExceptionStatus = WebExceptionStatus.Success;
|
2010-03-20 07:09:07 +00:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
catch (WebException ex)
|
|
|
|
|
|
{
|
2011-05-28 15:03:49 +00:00
|
|
|
|
this.QueryExceptionStatus = ex.Status;
|
|
|
|
|
|
this.QueryExceptionMessage = ex.Message;
|
|
|
|
|
|
if (this.QueryExceptionStatus == WebExceptionStatus.ProtocolError)
|
|
|
|
|
|
this.QueryResponseStatus = (ex.Response as HttpWebResponse).StatusCode;
|
|
|
|
|
|
}
|
|
|
|
|
|
catch (Exception ex)
|
|
|
|
|
|
{
|
|
|
|
|
|
this.QueryExceptionStatus = WebExceptionStatus.UnknownError;
|
|
|
|
|
|
this.QueryExceptionMessage = ex.Message;
|
|
|
|
|
|
}
|
|
|
|
|
|
finally
|
|
|
|
|
|
{
|
|
|
|
|
|
currentReq = null;
|
2010-03-20 07:09:07 +00:00
|
|
|
|
}
|
2010-02-23 23:24:54 +00:00
|
|
|
|
}
|
2010-02-18 21:12:44 +00:00
|
|
|
|
|
2011-05-26 18:18:26 +00:00
|
|
|
|
public void FetchDB(DBEntry entry)
|
2010-02-23 23:24:54 +00:00
|
|
|
|
{
|
2011-05-26 18:18:26 +00:00
|
|
|
|
string url = entry.hasParity[0] == '/' ? urlbase + entry.hasParity : entry.hasParity;
|
2010-02-18 21:12:44 +00:00
|
|
|
|
HttpWebRequest req = (HttpWebRequest)WebRequest.Create(url);
|
|
|
|
|
|
req.Method = "GET";
|
2010-02-23 15:15:08 +00:00
|
|
|
|
req.Proxy = proxy;
|
2011-05-15 17:41:14 +00:00
|
|
|
|
req.UserAgent = this.userAgent;
|
2011-05-28 15:03:49 +00:00
|
|
|
|
req.Timeout = connectTimeout;
|
|
|
|
|
|
req.ReadWriteTimeout = socketTimeout;
|
2011-06-03 19:15:28 +00:00
|
|
|
|
req.AutomaticDecompression = DecompressionMethods.None;
|
|
|
|
|
|
|
|
|
|
|
|
if (uploadHelper.onProgress != null)
|
|
|
|
|
|
uploadHelper.onProgress(url, new UploadProgressEventArgs(req.RequestUri.AbsoluteUri, 0.0));
|
2010-02-18 21:12:44 +00:00
|
|
|
|
|
2011-05-28 15:03:49 +00:00
|
|
|
|
currentReq = req;
|
2010-02-18 21:12:44 +00:00
|
|
|
|
try
|
|
|
|
|
|
{
|
2011-05-28 15:03:49 +00:00
|
|
|
|
using (HttpWebResponse resp = (HttpWebResponse)req.GetResponse())
|
2010-02-18 21:12:44 +00:00
|
|
|
|
{
|
2011-05-28 15:03:49 +00:00
|
|
|
|
entry.httpStatus = resp.StatusCode;
|
|
|
|
|
|
|
2011-06-03 19:15:28 +00:00
|
|
|
|
if (entry.httpStatus == HttpStatusCode.OK)
|
|
|
|
|
|
{
|
2011-10-27 20:50:11 +00:00
|
|
|
|
if (resp.ContentLength < entry.Npar * entry.stride * 2 ||
|
|
|
|
|
|
resp.ContentLength > entry.Npar * entry.stride * 4)
|
2011-06-03 19:15:28 +00:00
|
|
|
|
{
|
|
|
|
|
|
entry.httpStatus = HttpStatusCode.PartialContent;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2011-05-28 15:03:49 +00:00
|
|
|
|
if (entry.httpStatus == HttpStatusCode.OK)
|
2010-02-18 21:12:44 +00:00
|
|
|
|
{
|
2011-05-28 15:03:49 +00:00
|
|
|
|
using (Stream responseStream = resp.GetResponseStream())
|
2010-02-18 21:12:44 +00:00
|
|
|
|
{
|
2011-06-03 19:15:28 +00:00
|
|
|
|
byte[] contents = new byte[resp.ContentLength];
|
|
|
|
|
|
int pos = 0, count = 0;
|
|
|
|
|
|
do
|
2010-02-18 21:12:44 +00:00
|
|
|
|
{
|
2011-06-03 19:15:28 +00:00
|
|
|
|
count = responseStream.Read(contents, pos, Math.Min(contents.Length - pos, 32768));
|
|
|
|
|
|
pos += count;
|
|
|
|
|
|
if (uploadHelper.onProgress != null)
|
|
|
|
|
|
uploadHelper.onProgress(url, new UploadProgressEventArgs(req.RequestUri.AbsoluteUri, ((double)pos) / contents.Length));
|
|
|
|
|
|
} while (count != 0);
|
|
|
|
|
|
if (!Parse(contents, entry))
|
|
|
|
|
|
entry.httpStatus = HttpStatusCode.NoContent;
|
2010-02-18 21:12:44 +00:00
|
|
|
|
}
|
|
|
|
|
|
}
|
2010-02-23 23:24:54 +00:00
|
|
|
|
}
|
2010-02-18 21:12:44 +00:00
|
|
|
|
}
|
|
|
|
|
|
catch (WebException ex)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (ex.Status == WebExceptionStatus.ProtocolError)
|
2011-04-24 21:07:50 +00:00
|
|
|
|
entry.httpStatus = ((HttpWebResponse)ex.Response).StatusCode;
|
2010-02-18 21:12:44 +00:00
|
|
|
|
else
|
2011-04-24 21:07:50 +00:00
|
|
|
|
entry.httpStatus = HttpStatusCode.BadRequest;
|
2010-02-18 21:12:44 +00:00
|
|
|
|
}
|
2011-05-28 15:03:49 +00:00
|
|
|
|
finally
|
|
|
|
|
|
{
|
|
|
|
|
|
currentReq = null;
|
|
|
|
|
|
}
|
2010-02-18 21:12:44 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
2010-03-20 07:09:07 +00:00
|
|
|
|
static string uuidInfo = null;
|
2010-02-23 15:15:08 +00:00
|
|
|
|
|
2010-03-20 07:09:07 +00:00
|
|
|
|
public static string GetUUID()
|
2010-02-23 15:15:08 +00:00
|
|
|
|
{
|
2010-03-20 07:09:07 +00:00
|
|
|
|
if (uuidInfo == null)
|
2010-02-23 15:15:08 +00:00
|
|
|
|
{
|
2010-06-11 17:54:37 +00:00
|
|
|
|
string id = "CTDB userid";
|
|
|
|
|
|
using (ManagementClass mc = new ManagementClass("Win32_ComputerSystemProduct"))
|
|
|
|
|
|
foreach (ManagementObject mo in mc.GetInstances())
|
|
|
|
|
|
{
|
|
|
|
|
|
id = id + mo.Properties["UUID"].Value.ToString();
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
byte[] hashBytes = (new SHA1CryptoServiceProvider()).ComputeHash(Encoding.ASCII.GetBytes(id));
|
|
|
|
|
|
uuidInfo = Convert.ToBase64String(hashBytes).Replace('+', '.').Replace('/', '_').Replace('=', '-');
|
2010-02-23 15:15:08 +00:00
|
|
|
|
}
|
2010-06-11 17:54:37 +00:00
|
|
|
|
return uuidInfo;
|
2010-02-23 15:15:08 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
2011-06-11 19:26:25 +00:00
|
|
|
|
public string Submit(int confidence, int quality, string artist, string title, string barcode)
|
2010-02-28 21:04:34 +00:00
|
|
|
|
{
|
2011-05-28 15:03:49 +00:00
|
|
|
|
if (this.QueryExceptionStatus != WebExceptionStatus.Success &&
|
|
|
|
|
|
(this.QueryExceptionStatus != WebExceptionStatus.ProtocolError || this.QueryResponseStatus != HttpStatusCode.NotFound))
|
2011-05-06 20:22:21 +00:00
|
|
|
|
return this.DBStatus;
|
2011-10-27 20:50:11 +00:00
|
|
|
|
int npar = AccurateRipVerify.maxNpar;
|
|
|
|
|
|
var parity = verify.AR.GetParity(npar);
|
2011-10-30 23:39:20 +00:00
|
|
|
|
var confirms = this.MatchingEntries;
|
|
|
|
|
|
if (confirms.Count > 0)
|
|
|
|
|
|
{
|
|
|
|
|
|
confidence = 1;
|
|
|
|
|
|
foreach (var confirm in confirms)
|
|
|
|
|
|
{
|
|
|
|
|
|
subResult = null;
|
|
|
|
|
|
DoSubmit(confidence, quality, artist, title, barcode, false, confirm, parity, npar);
|
|
|
|
|
|
if (subResult == "parity needed")
|
|
|
|
|
|
DoSubmit(confidence, quality, artist, title, barcode, true, confirm, parity, npar);
|
|
|
|
|
|
}
|
|
|
|
|
|
return subResult;
|
|
|
|
|
|
}
|
|
|
|
|
|
DoSubmit(confidence, quality, artist, title, barcode, false, null, parity, npar);
|
2011-05-06 20:22:21 +00:00
|
|
|
|
if (subResult == "parity needed")
|
2011-10-30 23:39:20 +00:00
|
|
|
|
DoSubmit(confidence, quality, artist, title, barcode, true, null, parity, npar);
|
2011-05-06 20:22:21 +00:00
|
|
|
|
return subResult;
|
2010-02-28 21:04:34 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
2011-10-27 20:50:11 +00:00
|
|
|
|
protected string DoSubmit(int confidence, int quality, string artist, string title, string barcode, bool upload, DBEntry confirm, byte[] parity, int npar)
|
2010-02-18 21:12:44 +00:00
|
|
|
|
{
|
2011-04-24 21:07:50 +00:00
|
|
|
|
UploadFile[] files;
|
|
|
|
|
|
if (upload)
|
2010-02-18 21:12:44 +00:00
|
|
|
|
{
|
2011-04-24 21:07:50 +00:00
|
|
|
|
MemoryStream newcontents = new MemoryStream();
|
|
|
|
|
|
using (DBHDR FTYP = new DBHDR(newcontents, "ftyp"))
|
|
|
|
|
|
FTYP.Write("CTDB");
|
|
|
|
|
|
using (DBHDR CTDB = new DBHDR(newcontents, "CTDB"))
|
2010-02-18 21:12:44 +00:00
|
|
|
|
{
|
2011-04-24 21:07:50 +00:00
|
|
|
|
using (DBHDR HEAD = CTDB.HDR("HEAD"))
|
2010-02-18 21:12:44 +00:00
|
|
|
|
{
|
2011-04-24 21:07:50 +00:00
|
|
|
|
using (DBHDR VERS = HEAD.HDR("VERS")) VERS.Write(0x101);
|
|
|
|
|
|
}
|
|
|
|
|
|
using (DBHDR DISC = CTDB.HDR("DISC"))
|
|
|
|
|
|
{
|
|
|
|
|
|
using (DBHDR CONF = DISC.HDR("CONF")) CONF.Write(confidence);
|
2011-10-27 20:50:11 +00:00
|
|
|
|
using (DBHDR NPAR = DISC.HDR("NPAR")) NPAR.Write(npar);
|
2011-04-24 21:07:50 +00:00
|
|
|
|
using (DBHDR CRC_ = DISC.HDR("CRC ")) CRC_.Write(verify.CRC);
|
2011-10-27 20:50:11 +00:00
|
|
|
|
using (DBHDR PAR_ = DISC.HDR("PAR ")) PAR_.Write(parity);
|
2010-02-18 21:12:44 +00:00
|
|
|
|
}
|
|
|
|
|
|
}
|
2011-04-24 21:07:50 +00:00
|
|
|
|
newcontents.Position = 0;
|
|
|
|
|
|
files = new UploadFile[1] { new UploadFile(newcontents, "parityfile", "data.bin", "image/binary") };
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
files = new UploadFile[0];
|
2010-02-18 21:12:44 +00:00
|
|
|
|
}
|
2011-10-30 23:39:20 +00:00
|
|
|
|
|
|
|
|
|
|
long maxId = 0;
|
|
|
|
|
|
foreach (var e in this.entries)
|
|
|
|
|
|
{
|
|
|
|
|
|
maxId = Math.Max(maxId, e.id);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2011-04-24 21:07:50 +00:00
|
|
|
|
HttpWebRequest req = (HttpWebRequest)WebRequest.Create(urlbase + "/submit2.php");
|
2010-02-23 15:15:08 +00:00
|
|
|
|
req.Proxy = proxy;
|
2011-05-15 17:41:14 +00:00
|
|
|
|
req.UserAgent = this.userAgent;
|
2011-05-28 15:03:49 +00:00
|
|
|
|
req.Timeout = connectTimeout;
|
|
|
|
|
|
req.ReadWriteTimeout = socketTimeout;
|
2010-02-18 21:12:44 +00:00
|
|
|
|
NameValueCollection form = new NameValueCollection();
|
2011-04-24 21:07:50 +00:00
|
|
|
|
if (upload)
|
|
|
|
|
|
form.Add("parityfile", "1");
|
2011-05-06 20:22:21 +00:00
|
|
|
|
if (confirm != null)
|
2011-10-30 23:39:20 +00:00
|
|
|
|
form.Add("confirmid", confirm.id.ToString());
|
|
|
|
|
|
form.Add("maxid", maxId.ToString());
|
2011-05-15 17:41:14 +00:00
|
|
|
|
form.Add("toc", toc.ToString());
|
2011-04-24 21:07:50 +00:00
|
|
|
|
form.Add("crc32", ((int)verify.CRC).ToString());
|
|
|
|
|
|
form.Add("trackcrcs", verify.TrackCRCs);
|
2011-10-27 20:50:11 +00:00
|
|
|
|
form.Add("parity", Convert.ToBase64String(parity, 0, npar * 2));
|
2010-03-20 07:09:07 +00:00
|
|
|
|
form.Add("confidence", confidence.ToString());
|
|
|
|
|
|
form.Add("userid", GetUUID());
|
2011-05-06 20:22:21 +00:00
|
|
|
|
form.Add("quality", quality.ToString());
|
2011-06-11 19:26:25 +00:00
|
|
|
|
if (driveName != null && driveName != "") form.Add("drivename", driveName);
|
|
|
|
|
|
if (barcode != null && barcode != "") form.Add("barcode", barcode);
|
2010-03-20 07:09:07 +00:00
|
|
|
|
if (artist != null && artist != "") form.Add("artist", artist);
|
|
|
|
|
|
if (title != null && title != "") form.Add("title", title);
|
2011-04-24 21:07:50 +00:00
|
|
|
|
|
|
|
|
|
|
var ExceptionStatus = WebExceptionStatus.Pending;
|
|
|
|
|
|
string ExceptionMessage = null;
|
|
|
|
|
|
HttpStatusCode ResponseStatus = HttpStatusCode.OK;
|
2011-05-28 15:03:49 +00:00
|
|
|
|
currentReq = req;
|
2011-04-24 21:07:50 +00:00
|
|
|
|
try
|
|
|
|
|
|
{
|
|
|
|
|
|
using (HttpWebResponse resp = uploadHelper.Upload(req, files, form))
|
|
|
|
|
|
{
|
|
|
|
|
|
ExceptionStatus = WebExceptionStatus.ProtocolError;
|
|
|
|
|
|
ResponseStatus = resp.StatusCode;
|
|
|
|
|
|
if (ResponseStatus == HttpStatusCode.OK)
|
|
|
|
|
|
{
|
|
|
|
|
|
ExceptionStatus = WebExceptionStatus.Success;
|
|
|
|
|
|
using (Stream s = resp.GetResponseStream())
|
|
|
|
|
|
using (StreamReader sr = new StreamReader(s))
|
|
|
|
|
|
subResult = sr.ReadToEnd();
|
|
|
|
|
|
return subResult;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
catch (WebException ex)
|
|
|
|
|
|
{
|
|
|
|
|
|
ExceptionStatus = ex.Status;
|
|
|
|
|
|
ExceptionMessage = ex.Message;
|
|
|
|
|
|
if (ExceptionStatus == WebExceptionStatus.ProtocolError)
|
|
|
|
|
|
ResponseStatus = (ex.Response as HttpWebResponse).StatusCode;
|
|
|
|
|
|
}
|
2011-05-28 15:03:49 +00:00
|
|
|
|
finally
|
|
|
|
|
|
{
|
|
|
|
|
|
currentReq = null;
|
|
|
|
|
|
}
|
2011-04-24 21:07:50 +00:00
|
|
|
|
subResult = ExceptionStatus == WebExceptionStatus.Success ? null :
|
|
|
|
|
|
ExceptionStatus != WebExceptionStatus.ProtocolError ? ("database access error: " + (ExceptionMessage ?? ExceptionStatus.ToString())) :
|
|
|
|
|
|
ResponseStatus != HttpStatusCode.NotFound ? "database access error: " + ResponseStatus.ToString() :
|
|
|
|
|
|
"disk not present in database";
|
2010-02-23 15:15:08 +00:00
|
|
|
|
return subResult;
|
2010-02-18 21:12:44 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
2011-04-24 21:07:50 +00:00
|
|
|
|
private bool Parse(byte[] contents, DBEntry entry)
|
2010-02-18 21:12:44 +00:00
|
|
|
|
{
|
2011-10-27 20:50:11 +00:00
|
|
|
|
if (contents.Length == entry.Npar * entry.stride * 2)
|
2011-04-24 21:07:50 +00:00
|
|
|
|
{
|
2011-10-27 20:50:11 +00:00
|
|
|
|
entry.syndrome = ParityToSyndrome.Parity2Syndrome(entry.stride, entry.Npar, entry.Npar, contents);
|
2011-04-24 21:07:50 +00:00
|
|
|
|
return true;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2010-02-23 23:24:54 +00:00
|
|
|
|
ReadDB rdr = new ReadDB(contents);
|
2010-02-18 21:12:44 +00:00
|
|
|
|
|
|
|
|
|
|
int end;
|
2010-02-23 23:24:54 +00:00
|
|
|
|
string hdr = rdr.ReadHDR(out end);
|
|
|
|
|
|
uint magic = rdr.ReadUInt();
|
|
|
|
|
|
if (hdr != "ftyp" || magic != 0x43544442 || end != rdr.pos)
|
2010-02-23 15:15:08 +00:00
|
|
|
|
throw new Exception("invalid CTDB file");
|
2010-02-23 23:24:54 +00:00
|
|
|
|
hdr = rdr.ReadHDR(out end);
|
2011-04-24 21:07:50 +00:00
|
|
|
|
if (hdr != "CTDB" || end != contents.Length)
|
2010-02-23 15:15:08 +00:00
|
|
|
|
throw new Exception("invalid CTDB file");
|
2010-02-23 23:24:54 +00:00
|
|
|
|
hdr = rdr.ReadHDR(out end);
|
2011-04-24 21:07:50 +00:00
|
|
|
|
if (hdr != "HEAD")
|
2010-02-23 15:15:08 +00:00
|
|
|
|
throw new Exception("invalid CTDB file");
|
2010-02-23 23:24:54 +00:00
|
|
|
|
int endHead = end;
|
|
|
|
|
|
while (rdr.pos < endHead)
|
2010-02-18 21:12:44 +00:00
|
|
|
|
{
|
2010-02-23 23:24:54 +00:00
|
|
|
|
hdr = rdr.ReadHDR(out end);
|
|
|
|
|
|
rdr.pos = end;
|
|
|
|
|
|
}
|
2010-02-25 17:04:49 +00:00
|
|
|
|
rdr.pos = endHead;
|
2010-02-23 23:24:54 +00:00
|
|
|
|
while (rdr.pos < contents.Length)
|
|
|
|
|
|
{
|
|
|
|
|
|
hdr = rdr.ReadHDR(out end);
|
2010-02-18 21:12:44 +00:00
|
|
|
|
if (hdr != "DISC")
|
|
|
|
|
|
{
|
2010-02-23 23:24:54 +00:00
|
|
|
|
rdr.pos = end;
|
2010-02-18 21:12:44 +00:00
|
|
|
|
continue;
|
|
|
|
|
|
}
|
|
|
|
|
|
int endDisc = end;
|
2011-04-24 21:07:50 +00:00
|
|
|
|
int parPos = 0, parLen = 0;
|
2010-02-23 23:24:54 +00:00
|
|
|
|
while (rdr.pos < endDisc)
|
2010-02-18 21:12:44 +00:00
|
|
|
|
{
|
2010-02-23 23:24:54 +00:00
|
|
|
|
hdr = rdr.ReadHDR(out end);
|
2010-02-23 15:15:08 +00:00
|
|
|
|
if (hdr == "PAR ")
|
2010-02-18 21:12:44 +00:00
|
|
|
|
{
|
2010-02-23 23:24:54 +00:00
|
|
|
|
parPos = rdr.pos;
|
|
|
|
|
|
parLen = end - rdr.pos;
|
2010-02-18 21:12:44 +00:00
|
|
|
|
}
|
2010-02-23 23:24:54 +00:00
|
|
|
|
rdr.pos = end;
|
2010-02-18 21:12:44 +00:00
|
|
|
|
}
|
2011-04-24 21:07:50 +00:00
|
|
|
|
if (parPos != 0)
|
|
|
|
|
|
{
|
2011-10-27 20:50:11 +00:00
|
|
|
|
if (parLen != entry.Npar * entry.stride * 2)
|
|
|
|
|
|
return false;
|
|
|
|
|
|
entry.syndrome = ParityToSyndrome.Parity2Syndrome(entry.stride, entry.Npar, entry.Npar, contents, parPos);
|
2011-04-24 21:07:50 +00:00
|
|
|
|
return true;
|
|
|
|
|
|
}
|
2010-02-18 21:12:44 +00:00
|
|
|
|
}
|
2011-04-24 21:07:50 +00:00
|
|
|
|
return false;
|
2010-02-18 21:12:44 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public void DoVerify()
|
|
|
|
|
|
{
|
2011-05-28 15:03:49 +00:00
|
|
|
|
if (this.QueryExceptionStatus != WebExceptionStatus.Success)
|
2011-05-06 20:22:21 +00:00
|
|
|
|
return;
|
2010-02-18 21:12:44 +00:00
|
|
|
|
foreach (DBEntry entry in entries)
|
|
|
|
|
|
{
|
2011-10-27 20:50:11 +00:00
|
|
|
|
if (entry.toc.Pregap != toc.Pregap || entry.toc.AudioLength != toc.AudioLength || entry.stride != verify.Stride)
|
2010-03-20 07:09:07 +00:00
|
|
|
|
{
|
2011-04-24 21:07:50 +00:00
|
|
|
|
entry.hasErrors = true;
|
2010-03-20 07:09:07 +00:00
|
|
|
|
entry.canRecover = false;
|
|
|
|
|
|
continue;
|
|
|
|
|
|
}
|
2011-10-27 20:50:11 +00:00
|
|
|
|
if (!verify.FindOffset(entry.syndrome, entry.crc, out entry.offset, out entry.hasErrors))
|
2010-02-23 15:15:08 +00:00
|
|
|
|
entry.canRecover = false;
|
|
|
|
|
|
else if (entry.hasErrors)
|
|
|
|
|
|
{
|
2011-05-26 18:18:26 +00:00
|
|
|
|
if (entry.hasParity == null || entry.hasParity == "")
|
2010-02-23 23:24:54 +00:00
|
|
|
|
entry.canRecover = false;
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
2011-05-26 18:18:26 +00:00
|
|
|
|
FetchDB(entry);
|
2011-04-24 21:07:50 +00:00
|
|
|
|
if (entry.httpStatus != HttpStatusCode.OK)
|
|
|
|
|
|
entry.canRecover = false;
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
2011-10-27 20:50:11 +00:00
|
|
|
|
entry.repair = verify.VerifyParity(entry.syndrome, entry.offset);
|
2011-04-24 21:07:50 +00:00
|
|
|
|
entry.canRecover = entry.repair.CanRecover;
|
|
|
|
|
|
}
|
2010-02-23 23:24:54 +00:00
|
|
|
|
}
|
2010-02-23 15:15:08 +00:00
|
|
|
|
}
|
2010-02-18 21:12:44 +00:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2011-06-26 00:02:29 +00:00
|
|
|
|
public int Confidence
|
|
|
|
|
|
{
|
|
|
|
|
|
get
|
|
|
|
|
|
{
|
|
|
|
|
|
if (this.QueryExceptionStatus != WebExceptionStatus.Success)
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
int res = 0;
|
|
|
|
|
|
foreach (DBEntry entry in this.Entries)
|
|
|
|
|
|
if (entry.toc.ToString() == this.toc.ToString() && !entry.hasErrors)
|
|
|
|
|
|
res += entry.conf;
|
|
|
|
|
|
return res;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2011-10-30 23:39:20 +00:00
|
|
|
|
public List<DBEntry> MatchingEntries
|
2011-06-11 19:26:25 +00:00
|
|
|
|
{
|
2011-10-30 23:39:20 +00:00
|
|
|
|
get
|
|
|
|
|
|
{
|
|
|
|
|
|
var res = new List<DBEntry>();
|
|
|
|
|
|
if (this.QueryExceptionStatus != WebExceptionStatus.Success)
|
|
|
|
|
|
return res;
|
|
|
|
|
|
foreach (DBEntry entry in this.Entries)
|
|
|
|
|
|
if (entry.toc.ToString() == this.toc.ToString() && !entry.hasErrors)
|
|
|
|
|
|
res.Add(entry);
|
|
|
|
|
|
return res;
|
|
|
|
|
|
}
|
2011-06-11 19:26:25 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public void Init(AccurateRipVerify ar)
|
2010-02-18 21:12:44 +00:00
|
|
|
|
{
|
2011-10-27 20:50:11 +00:00
|
|
|
|
verify = new CDRepairEncode(ar, 10 * 588 * 2);
|
2010-02-18 21:12:44 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
2010-05-18 17:18:37 +00:00
|
|
|
|
public CDImageLayout TOC
|
|
|
|
|
|
{
|
|
|
|
|
|
get
|
|
|
|
|
|
{
|
|
|
|
|
|
return toc;
|
|
|
|
|
|
}
|
|
|
|
|
|
set
|
|
|
|
|
|
{
|
|
|
|
|
|
toc = value;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2010-02-18 21:12:44 +00:00
|
|
|
|
public int Total
|
|
|
|
|
|
{
|
|
|
|
|
|
get
|
|
|
|
|
|
{
|
|
|
|
|
|
return total;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2011-05-28 15:03:49 +00:00
|
|
|
|
public WebExceptionStatus QueryExceptionStatus { get; private set; }
|
|
|
|
|
|
|
|
|
|
|
|
public string QueryExceptionMessage { get; private set; }
|
|
|
|
|
|
|
|
|
|
|
|
public HttpStatusCode QueryResponseStatus { get; private set; }
|
|
|
|
|
|
|
|
|
|
|
|
public string DBStatus
|
2010-02-18 21:12:44 +00:00
|
|
|
|
{
|
|
|
|
|
|
get
|
|
|
|
|
|
{
|
2011-05-28 15:03:49 +00:00
|
|
|
|
return QueryExceptionStatus == WebExceptionStatus.Success ? null :
|
|
|
|
|
|
QueryExceptionStatus != WebExceptionStatus.ProtocolError ? ("database access error: " + (QueryExceptionMessage ?? QueryExceptionStatus.ToString())) :
|
|
|
|
|
|
QueryResponseStatus != HttpStatusCode.NotFound ? "database access error: " + QueryResponseStatus.ToString() :
|
|
|
|
|
|
"disk not present in database";
|
2010-02-18 21:12:44 +00:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public CDRepairEncode Verify
|
|
|
|
|
|
{
|
|
|
|
|
|
get
|
|
|
|
|
|
{
|
|
|
|
|
|
return verify;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2010-02-25 17:04:49 +00:00
|
|
|
|
public string SubStatus
|
|
|
|
|
|
{
|
|
|
|
|
|
get
|
|
|
|
|
|
{
|
|
|
|
|
|
return subResult;
|
|
|
|
|
|
}
|
2010-05-18 17:18:37 +00:00
|
|
|
|
set
|
|
|
|
|
|
{
|
|
|
|
|
|
subResult = value;
|
|
|
|
|
|
}
|
2010-02-25 17:04:49 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
2010-02-23 15:15:08 +00:00
|
|
|
|
public DBEntry SelectedEntry
|
|
|
|
|
|
{
|
|
|
|
|
|
set
|
|
|
|
|
|
{
|
|
|
|
|
|
selectedEntry = value;
|
|
|
|
|
|
}
|
|
|
|
|
|
get
|
|
|
|
|
|
{
|
|
|
|
|
|
return selectedEntry;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2010-02-18 21:12:44 +00:00
|
|
|
|
public string Status
|
|
|
|
|
|
{
|
|
|
|
|
|
get
|
|
|
|
|
|
{
|
|
|
|
|
|
//sw.WriteLine("CUETools DB CRC: {0:x8}", Verify.CRC);
|
2010-02-23 15:15:08 +00:00
|
|
|
|
string res = null;
|
2010-02-18 21:12:44 +00:00
|
|
|
|
if (DBStatus != null)
|
2010-02-23 15:15:08 +00:00
|
|
|
|
res = DBStatus;
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
DBEntry popular = null;
|
|
|
|
|
|
foreach (DBEntry entry in entries)
|
2010-03-20 07:09:07 +00:00
|
|
|
|
if (entry.toc.Pregap == toc.Pregap && (!entry.hasErrors || entry.canRecover))
|
2010-02-23 15:15:08 +00:00
|
|
|
|
if (popular == null || entry.conf > popular.conf)
|
|
|
|
|
|
popular = entry;
|
|
|
|
|
|
if (popular != null)
|
|
|
|
|
|
res = popular.Status;
|
|
|
|
|
|
foreach (DBEntry entry in entries)
|
2010-03-20 07:09:07 +00:00
|
|
|
|
if (entry != popular && entry.toc.Pregap == toc.Pregap && (!entry.hasErrors || entry.canRecover))
|
2010-02-23 15:15:08 +00:00
|
|
|
|
res += ", or " + entry.Status;
|
|
|
|
|
|
if (res == null)
|
|
|
|
|
|
res = "could not be verified";
|
|
|
|
|
|
}
|
|
|
|
|
|
if (subResult != null)
|
|
|
|
|
|
res += ", " + subResult;
|
|
|
|
|
|
return res;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public IEnumerable<DBEntry> Entries
|
|
|
|
|
|
{
|
|
|
|
|
|
get
|
|
|
|
|
|
{
|
|
|
|
|
|
return entries;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2011-05-15 17:41:14 +00:00
|
|
|
|
public IEnumerable<CTDBResponseMeta> Metadata
|
|
|
|
|
|
{
|
|
|
|
|
|
get
|
|
|
|
|
|
{
|
|
|
|
|
|
return metadata;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2010-02-23 15:15:08 +00:00
|
|
|
|
public HttpUploadHelper UploadHelper
|
|
|
|
|
|
{
|
|
|
|
|
|
get
|
|
|
|
|
|
{
|
|
|
|
|
|
return uploadHelper;
|
2010-02-18 21:12:44 +00:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|