public static void UpdateMasterDatabase(bool create) { DicContext mctx = DicContext.Create(Settings.Settings.MasterDbPath); mctx.Database.Migrate(); mctx.SaveChanges(); try { long lastUpdate = 0; DateTime latest = DateTime.MinValue; if (!create) { List <DateTime> latestAll = new List <DateTime>(); if (mctx.UsbVendors.Any()) { latestAll.Add(mctx.UsbVendors.Max(v => v.ModifiedWhen)); } if (mctx.UsbProducts.Any()) { latestAll.Add(mctx.UsbProducts.Max(p => p.ModifiedWhen)); } if (mctx.CdOffsets.Any()) { latestAll.Add(mctx.CdOffsets.Max(o => o.ModifiedWhen)); } if (mctx.Devices.Any()) { latestAll.Add(mctx.Devices.Max(d => d.LastSynchronized)); } if (latestAll.Any()) { latest = latestAll.Max(t => t); lastUpdate = (latest.ToFileTimeUtc() - new DateTime(1970, 1, 1).ToFileTimeUtc()) / 10000000; } } if (lastUpdate == 0) { create = true; DicConsole.WriteLine("Creating master database"); } else { DicConsole.WriteLine("Updating master database"); DicConsole.WriteLine("Last update: {0}", latest); } DateTime updateStart = DateTime.UtcNow; WebRequest request = WebRequest.Create($"https://www.discimagechef.app/api/update?timestamp={lastUpdate}"); ((HttpWebRequest)request).UserAgent = $"DiscImageChef {typeof(Version).Assembly.GetName().Version}"; request.Method = "GET"; request.ContentType = "application/json"; WebResponse response = request.GetResponse(); if (((HttpWebResponse)response).StatusCode != HttpStatusCode.OK) { DicConsole.ErrorWriteLine("Error {0} when trying to get updated entities.", ((HttpWebResponse)response).StatusCode); return; } Stream data = response.GetResponseStream(); StreamReader reader = new StreamReader(data ?? throw new InvalidOperationException()); SyncDto sync = JsonConvert.DeserializeObject <SyncDto>(reader.ReadToEnd()); if (create) { DicConsole.WriteLine("Adding USB vendors"); foreach (UsbVendorDto vendor in sync.UsbVendors) { mctx.UsbVendors.Add(new UsbVendor(vendor.VendorId, vendor.Vendor)); } DicConsole.WriteLine("Added {0} usb vendors", sync.UsbVendors.Count); DicConsole.WriteLine("Adding USB products"); foreach (UsbProductDto product in sync.UsbProducts) { mctx.UsbProducts.Add(new UsbProduct(product.VendorId, product.ProductId, product.Product)); } DicConsole.WriteLine("Added {0} usb products", sync.UsbProducts.Count); DicConsole.WriteLine("Adding CompactDisc read offsets"); foreach (CdOffsetDto offset in sync.Offsets) { mctx.CdOffsets.Add(new CdOffset(offset) { Id = offset.Id }); } DicConsole.WriteLine("Added {0} CompactDisc read offsets", sync.Offsets.Count); DicConsole.WriteLine("Adding known devices"); foreach (DeviceDto device in sync.Devices) { mctx.Devices.Add(new Device(device) { Id = device.Id }); } DicConsole.WriteLine("Added {0} known devices", sync.Devices.Count); } else { long addedVendors = 0; long addedProducts = 0; long addedOffsets = 0; long addedDevices = 0; long modifiedVendors = 0; long modifiedProducts = 0; long modifiedOffsets = 0; long modifiedDevices = 0; DicConsole.WriteLine("Updating USB vendors"); foreach (UsbVendorDto vendor in sync.UsbVendors) { UsbVendor existing = mctx.UsbVendors.FirstOrDefault(v => v.Id == vendor.VendorId); if (existing != null) { modifiedVendors++; existing.Vendor = vendor.Vendor; existing.ModifiedWhen = updateStart; mctx.UsbVendors.Update(existing); } else { addedVendors++; mctx.UsbVendors.Add(new UsbVendor(vendor.VendorId, vendor.Vendor)); } } DicConsole.WriteLine("Added {0} USB vendors", addedVendors); DicConsole.WriteLine("Modified {0} USB vendors", modifiedVendors); DicConsole.WriteLine("Updating USB products"); foreach (UsbProductDto product in sync.UsbProducts) { UsbProduct existing = mctx.UsbProducts.FirstOrDefault(p => p.VendorId == product.VendorId && p.ProductId == product.ProductId); if (existing != null) { modifiedProducts++; existing.Product = product.Product; existing.ModifiedWhen = updateStart; mctx.UsbProducts.Update(existing); } else { addedProducts++; mctx.UsbProducts.Add(new UsbProduct(product.VendorId, product.ProductId, product.Product)); } } DicConsole.WriteLine("Added {0} USB products", addedProducts); DicConsole.WriteLine("Modified {0} USB products", modifiedProducts); DicConsole.WriteLine("Updating CompactDisc read offsets"); foreach (CdOffsetDto offset in sync.Offsets) { CdOffset existing = mctx.CdOffsets.FirstOrDefault(o => o.Id == offset.Id); if (existing != null) { modifiedOffsets++; existing.Agreement = offset.Agreement; existing.Manufacturer = offset.Manufacturer; existing.Model = offset.Model; existing.Submissions = offset.Submissions; existing.Offset = offset.Offset; existing.ModifiedWhen = updateStart; mctx.CdOffsets.Update(existing); } else { addedOffsets++; mctx.CdOffsets.Add(new CdOffset(offset) { Id = offset.Id }); } } DicConsole.WriteLine("Added {0} CompactDisc read offsets", addedOffsets); DicConsole.WriteLine("Modified {0} CompactDisc read offsets", modifiedOffsets); DicConsole.WriteLine("Updating known devices"); foreach (DeviceDto device in sync.Devices) { Device existing = mctx.Devices.FirstOrDefault(d => d.Id == device.Id); if (existing != null) { modifiedDevices++; mctx.Remove(existing); existing = new Device(device) { Id = device.Id, OptimalMultipleSectorsRead = device.OptimalMultipleSectorsRead }; mctx.Devices.Add(existing); } else { addedDevices++; mctx.Devices.Add(new Device(device) { Id = device.Id, OptimalMultipleSectorsRead = device.OptimalMultipleSectorsRead }); } } DicConsole.WriteLine("Added {0} known devices", addedDevices); DicConsole.WriteLine("Modified {0} known devices", modifiedDevices); } } catch (Exception ex) { DicConsole.ErrorWriteLine("Exception {0} when updating database.", ex); } finally { DicConsole.WriteLine("Saving changes..."); mctx.SaveChanges(); } }
public ActionResult View(int?id) { if (id == null || id <= 0) { return(Content("Incorrect device report request")); } try { DicServerContext ctx = new DicServerContext(); Device report = ctx.Devices.FirstOrDefault(d => d.Id == id); if (report is null) { return(Content("Cannot find requested report")); } ViewBag.lblManufacturer = report.Manufacturer; ViewBag.lblModel = report.Model; ViewBag.lblRevision = report.Revision; if (report.USB != null) { string usbVendorDescription = null; string usbProductDescription = null; UsbProduct dbProduct = ctx.UsbProducts.FirstOrDefault(p => p.ProductId == report.USB.ProductID && p.Vendor != null && p.Vendor.VendorId == report.USB.VendorID); if (dbProduct is null) { UsbVendor dbVendor = ctx.UsbVendors.FirstOrDefault(v => v.VendorId == report.USB.VendorID); if (!(dbVendor is null)) { usbVendorDescription = dbVendor.Vendor; } } else { usbProductDescription = dbProduct.Product; usbVendorDescription = dbProduct.Vendor.Vendor; } ViewBag.UsbItem = new Item { Manufacturer = report.USB.Manufacturer, Product = report.USB.Product, VendorDescription = usbVendorDescription != null ? $"0x{report.USB.VendorID:x4} ({usbVendorDescription})" : $"0x{report.USB.VendorID:x4}", ProductDescription = usbProductDescription != null ? $"0x{report.USB.ProductID:x4} ({usbProductDescription})" : $"0x{report.USB.ProductID:x4}" }; } if (report.FireWire != null) { ViewBag.FireWireItem = new Item { Manufacturer = report.FireWire.Manufacturer, Product = report.FireWire.Product, VendorDescription = $"0x{report.FireWire.VendorID:x8}", ProductDescription = $"0x{report.FireWire.ProductID:x8}" } } ; if (report.PCMCIA != null) { ViewBag.PcmciaItem = new PcmciaItem { Manufacturer = report.PCMCIA.Manufacturer, Product = report.PCMCIA.ProductName, VendorDescription = $"0x{report.PCMCIA.ManufacturerCode:x4}", ProductDescription = $"0x{report.PCMCIA.CardCode:x4}", Compliance = report.PCMCIA.Compliance }; Tuple[] tuples = CIS.GetTuples(report.PCMCIA.CIS); if (tuples != null) { Dictionary <string, string> decodedTuples = new Dictionary <string, string>(); foreach (Tuple tuple in tuples) { switch (tuple.Code) { case TupleCodes.CISTPL_NULL: case TupleCodes.CISTPL_END: case TupleCodes.CISTPL_MANFID: case TupleCodes.CISTPL_VERS_1: break; case TupleCodes.CISTPL_DEVICEGEO: case TupleCodes.CISTPL_DEVICEGEO_A: DeviceGeometryTuple geom = CIS.DecodeDeviceGeometryTuple(tuple.Data); if (geom?.Geometries != null) { foreach (DeviceGeometry geometry in geom.Geometries) { decodedTuples.Add("Device width", $"{(1 << (geometry.CardInterface - 1)) * 8} bits"); decodedTuples.Add("Erase block", $"{(1 << (geometry.EraseBlockSize - 1)) * (1 << (geometry.Interleaving - 1))} bytes"); decodedTuples.Add("Read block", $"{(1 << (geometry.ReadBlockSize - 1)) * (1 << (geometry.Interleaving - 1))} bytes"); decodedTuples.Add("Write block", $"{(1 << (geometry.WriteBlockSize - 1)) * (1 << (geometry.Interleaving - 1))} bytes"); decodedTuples.Add("Partition alignment", $"{(1 << (geometry.EraseBlockSize - 1)) * (1 << (geometry.Interleaving - 1)) * (1 << (geometry.Partitions - 1))} bytes"); } } break; case TupleCodes.CISTPL_ALTSTR: case TupleCodes.CISTPL_BAR: case TupleCodes.CISTPL_BATTERY: case TupleCodes.CISTPL_BYTEORDER: case TupleCodes.CISTPL_CFTABLE_ENTRY: case TupleCodes.CISTPL_CFTABLE_ENTRY_CB: case TupleCodes.CISTPL_CHECKSUM: case TupleCodes.CISTPL_CONFIG: case TupleCodes.CISTPL_CONFIG_CB: case TupleCodes.CISTPL_DATE: case TupleCodes.CISTPL_DEVICE: case TupleCodes.CISTPL_DEVICE_A: case TupleCodes.CISTPL_DEVICE_OA: case TupleCodes.CISTPL_DEVICE_OC: case TupleCodes.CISTPL_EXTDEVIC: case TupleCodes.CISTPL_FORMAT: case TupleCodes.CISTPL_FORMAT_A: case TupleCodes.CISTPL_FUNCE: case TupleCodes.CISTPL_FUNCID: case TupleCodes.CISTPL_GEOMETRY: case TupleCodes.CISTPL_INDIRECT: case TupleCodes.CISTPL_JEDEC_A: case TupleCodes.CISTPL_JEDEC_C: case TupleCodes.CISTPL_LINKTARGET: case TupleCodes.CISTPL_LONGLINK_A: case TupleCodes.CISTPL_LONGLINK_C: case TupleCodes.CISTPL_LONGLINK_CB: case TupleCodes.CISTPL_LONGLINK_MFC: case TupleCodes.CISTPL_NO_LINK: case TupleCodes.CISTPL_ORG: case TupleCodes.CISTPL_PWR_MGMNT: case TupleCodes.CISTPL_SPCL: case TupleCodes.CISTPL_SWIL: case TupleCodes.CISTPL_VERS_2: decodedTuples.Add("Undecoded tuple ID", tuple.Code.ToString()); break; default: decodedTuples.Add("Unknown tuple ID", $"0x{(byte)tuple.Code:X2}"); break; } } if (decodedTuples.Count > 0) { ViewBag.repPcmciaTuples = decodedTuples; } } } bool removable = true; List <TestedMedia> testedMedia = null; bool ata = false; bool atapi = false; bool sscMedia = false; if (report.ATA != null || report.ATAPI != null) { ata = true; List <string> ataOneValue = new List <string>(); Dictionary <string, string> ataTwoValue = new Dictionary <string, string>(); CommonTypes.Metadata.Ata ataReport; if (report.ATAPI != null) { ViewBag.AtaItem = "ATAPI"; ataReport = report.ATAPI; atapi = true; } else { ViewBag.AtaItem = "ATA"; ataReport = report.ATA; } bool cfa = report.CompactFlash; if (atapi && !cfa) { ViewBag.lblAtaDeviceType = "ATAPI device"; } else if (!atapi && cfa) { ViewBag.lblAtaDeviceType = "CompactFlash device"; } else { ViewBag.lblAtaDeviceType = "ATA device"; } Ata.Report(ataReport, cfa, atapi, ref removable, ref ataOneValue, ref ataTwoValue, ref testedMedia); ViewBag.repAtaOne = ataOneValue; ViewBag.repAtaTwo = ataTwoValue; } if (report.SCSI != null) { List <string> scsiOneValue = new List <string>(); Dictionary <string, string> modePages = new Dictionary <string, string>(); Dictionary <string, string> evpdPages = new Dictionary <string, string>(); string vendorId = StringHandlers.CToString(report.SCSI.Inquiry?.VendorIdentification); if (report.SCSI.Inquiry != null) { Inquiry.SCSIInquiry inq = report.SCSI.Inquiry.Value; ViewBag.lblScsiVendor = VendorString.Prettify(vendorId) != vendorId ? $"{vendorId} ({VendorString.Prettify(vendorId)})" : vendorId; ViewBag.lblScsiProduct = StringHandlers.CToString(inq.ProductIdentification); ViewBag.lblScsiRevision = StringHandlers.CToString(inq.ProductRevisionLevel); } scsiOneValue.AddRange(ScsiInquiry.Report(report.SCSI.Inquiry)); if (report.SCSI.SupportsModeSense6) { scsiOneValue.Add("Device supports MODE SENSE (6)"); } if (report.SCSI.SupportsModeSense10) { scsiOneValue.Add("Device supports MODE SENSE (10)"); } if (report.SCSI.SupportsModeSubpages) { scsiOneValue.Add("Device supports MODE SENSE subpages"); } if (report.SCSI.ModeSense != null) { PeripheralDeviceTypes devType = PeripheralDeviceTypes.DirectAccess; if (report.SCSI.Inquiry != null) { devType = (PeripheralDeviceTypes)report.SCSI.Inquiry.Value.PeripheralDeviceType; } ScsiModeSense.Report(report.SCSI.ModeSense, vendorId, devType, ref scsiOneValue, ref modePages); } if (modePages.Count > 0) { ViewBag.repModeSense = modePages; } if (report.SCSI.EVPDPages != null) { ScsiEvpd.Report(report.SCSI.EVPDPages, vendorId, ref evpdPages); } if (evpdPages.Count > 0) { ViewBag.repEvpd = evpdPages; } if (report.SCSI.MultiMediaDevice != null) { testedMedia = report.SCSI.MultiMediaDevice.TestedMedia; if (report.SCSI.MultiMediaDevice.ModeSense2A != null) { List <string> mmcModeOneValue = new List <string>(); ScsiMmcMode.Report(report.SCSI.MultiMediaDevice.ModeSense2A, ref mmcModeOneValue); if (mmcModeOneValue.Count > 0) { ViewBag.repScsiMmcMode = mmcModeOneValue; } } if (report.SCSI.MultiMediaDevice.Features != null) { List <string> mmcFeaturesOneValue = new List <string>(); ScsiMmcFeatures.Report(report.SCSI.MultiMediaDevice.Features, ref mmcFeaturesOneValue); if (mmcFeaturesOneValue.Count > 0) { ViewBag.repScsiMmcFeatures = mmcFeaturesOneValue; } } } else if (report.SCSI.SequentialDevice != null) { ViewBag.divScsiSscVisible = true; ViewBag.lblScsiSscGranularity = report.SCSI.SequentialDevice.BlockSizeGranularity?.ToString() ?? "Unspecified"; ViewBag.lblScsiSscMaxBlock = report.SCSI.SequentialDevice.MaxBlockLength?.ToString() ?? "Unspecified"; ViewBag.lblScsiSscMinBlock = report.SCSI.SequentialDevice.MinBlockLength?.ToString() ?? "Unspecified"; if (report.SCSI.SequentialDevice.SupportedDensities != null) { ViewBag.repScsiSscDensities = report.SCSI.SequentialDevice.SupportedDensities; } if (report.SCSI.SequentialDevice.SupportedMediaTypes != null) { ViewBag.repScsiSscMedias = report.SCSI.SequentialDevice.SupportedMediaTypes; } if (report.SCSI.SequentialDevice.TestedMedia != null) { List <string> mediaOneValue = new List <string>(); SscTestedMedia.Report(report.SCSI.SequentialDevice.TestedMedia, ref mediaOneValue); if (mediaOneValue.Count > 0) { sscMedia = true; ViewBag.repTestedMedia = mediaOneValue; } } } else if (report.SCSI.ReadCapabilities != null) { removable = false; scsiOneValue.Add(""); if (report.SCSI.ReadCapabilities.Blocks.HasValue && report.SCSI.ReadCapabilities.BlockSize.HasValue) { scsiOneValue .Add($"Device has {report.SCSI.ReadCapabilities.Blocks} blocks of {report.SCSI.ReadCapabilities.BlockSize} bytes each"); if (report.SCSI.ReadCapabilities.Blocks * report.SCSI.ReadCapabilities.BlockSize / 1024 / 1024 > 1000000) { scsiOneValue .Add($"Device size: {report.SCSI.ReadCapabilities.Blocks * report.SCSI.ReadCapabilities.BlockSize} bytes, {report.SCSI.ReadCapabilities.Blocks * report.SCSI.ReadCapabilities.BlockSize / 1000 / 1000 / 1000 / 1000} Tb, {(double)(report.SCSI.ReadCapabilities.Blocks * report.SCSI.ReadCapabilities.BlockSize) / 1024 / 1024 / 1024 / 1024:F2} TiB"); } else if (report.SCSI.ReadCapabilities.Blocks * report.SCSI.ReadCapabilities.BlockSize / 1024 / 1024 > 1000) { scsiOneValue .Add($"Device size: {report.SCSI.ReadCapabilities.Blocks * report.SCSI.ReadCapabilities.BlockSize} bytes, {report.SCSI.ReadCapabilities.Blocks * report.SCSI.ReadCapabilities.BlockSize / 1000 / 1000 / 1000} Gb, {(double)(report.SCSI.ReadCapabilities.Blocks * report.SCSI.ReadCapabilities.BlockSize) / 1024 / 1024 / 1024:F2} GiB"); } else { scsiOneValue .Add($"Device size: {report.SCSI.ReadCapabilities.Blocks * report.SCSI.ReadCapabilities.BlockSize} bytes, {report.SCSI.ReadCapabilities.Blocks * report.SCSI.ReadCapabilities.BlockSize / 1000 / 1000} Mb, {(double)(report.SCSI.ReadCapabilities.Blocks * report.SCSI.ReadCapabilities.BlockSize) / 1024 / 1024:F2} MiB"); } } if (report.SCSI.ReadCapabilities.MediumType.HasValue) { scsiOneValue.Add($"Medium type code: {report.SCSI.ReadCapabilities.MediumType:X2}h"); } if (report.SCSI.ReadCapabilities.Density.HasValue) { scsiOneValue.Add($"Density code: {report.SCSI.ReadCapabilities.Density:X2}h"); } if ((report.SCSI.ReadCapabilities.SupportsReadLong == true || report.SCSI.ReadCapabilities.SupportsReadLong16 == true) && report.SCSI.ReadCapabilities.LongBlockSize.HasValue) { scsiOneValue.Add($"Long block size: {report.SCSI.ReadCapabilities.LongBlockSize} bytes"); } if (report.SCSI.ReadCapabilities.SupportsReadCapacity == true) { scsiOneValue.Add("Device supports READ CAPACITY (10) command."); } if (report.SCSI.ReadCapabilities.SupportsReadCapacity16 == true) { scsiOneValue.Add("Device supports READ CAPACITY (16) command."); } if (report.SCSI.ReadCapabilities.SupportsRead6 == true) { scsiOneValue.Add("Device supports READ (6) command."); } if (report.SCSI.ReadCapabilities.SupportsRead10 == true) { scsiOneValue.Add("Device supports READ (10) command."); } if (report.SCSI.ReadCapabilities.SupportsRead12 == true) { scsiOneValue.Add("Device supports READ (12) command."); } if (report.SCSI.ReadCapabilities.SupportsRead16 == true) { scsiOneValue.Add("Device supports READ (16) command."); } if (report.SCSI.ReadCapabilities.SupportsReadLong == true) { scsiOneValue.Add("Device supports READ LONG (10) command."); } if (report.SCSI.ReadCapabilities.SupportsReadLong16 == true) { scsiOneValue.Add("Device supports READ LONG (16) command."); } } else { testedMedia = report.SCSI.RemovableMedias; } ViewBag.repScsi = scsiOneValue; } if (report.MultiMediaCard != null) { List <string> mmcOneValue = new List <string>(); if (report.MultiMediaCard.CID != null) { mmcOneValue.Add(Decoders.MMC.Decoders.PrettifyCID(report.MultiMediaCard.CID) .Replace("\n", "<br/>")); mmcOneValue.Add(""); } if (report.MultiMediaCard.CSD != null) { mmcOneValue.Add(Decoders.MMC.Decoders.PrettifyCSD(report.MultiMediaCard.CSD) .Replace("\n", "<br/>")); mmcOneValue.Add(""); } if (report.MultiMediaCard.ExtendedCSD != null) { mmcOneValue.Add(Decoders.MMC.Decoders.PrettifyExtendedCSD(report.MultiMediaCard.ExtendedCSD) .Replace("\n", "<br/>")); mmcOneValue.Add(""); } if (report.MultiMediaCard.OCR != null) { mmcOneValue.Add(Decoders.MMC.Decoders.PrettifyCSD(report.MultiMediaCard.OCR) .Replace("\n", "<br/>")); mmcOneValue.Add(""); } ViewBag.repMMC = mmcOneValue; } if (report.SecureDigital != null) { List <string> sdOneValue = new List <string>(); if (report.SecureDigital.CID != null) { sdOneValue.Add(Decoders.SecureDigital.Decoders.PrettifyCID(report.SecureDigital.CID) .Replace("\n", "<br/>")); sdOneValue.Add(""); } if (report.SecureDigital.CSD != null) { sdOneValue.Add(Decoders.SecureDigital.Decoders.PrettifyCSD(report.SecureDigital.CSD) .Replace("\n", "<br/>")); sdOneValue.Add(""); } if (report.SecureDigital.SCR != null) { sdOneValue.Add(Decoders.SecureDigital.Decoders.PrettifySCR(report.SecureDigital.SCR) .Replace("\n", "<br/>")); sdOneValue.Add(""); } if (report.SecureDigital.OCR != null) { sdOneValue.Add(Decoders.SecureDigital.Decoders.PrettifyCSD(report.SecureDigital.OCR) .Replace("\n", "<br/>")); sdOneValue.Add(""); } ViewBag.repSD = sdOneValue; } if (removable && !sscMedia && testedMedia != null) { List <string> mediaOneValue = new List <string>(); App_Start.TestedMedia.Report(testedMedia, ref mediaOneValue); if (mediaOneValue.Count > 0) { ViewBag.repTestedMedia = mediaOneValue; } } } catch (Exception) { #if DEBUG throw; #endif return(Content("Could not load device report")); } return(View()); }
public static void Main(string[] args) { DateTime start, end; int counter = 0; start = DateTime.UtcNow; System.Console.WriteLine("{0}: Connecting to database...", DateTime.UtcNow); var ctx = new AaruServerContext(); end = DateTime.UtcNow; System.Console.WriteLine("{0}: Took {1:F2} seconds", end, (end - start).TotalSeconds); System.Console.WriteLine("{0}: Migrating database to latest version...", DateTime.UtcNow); start = DateTime.UtcNow; ctx.Database.Migrate(); end = DateTime.UtcNow; System.Console.WriteLine("{0}: Took {1:F2} seconds", DateTime.UtcNow, (end - start).TotalSeconds); WebClient client; try { System.Console.WriteLine("{0}: Retrieving USB IDs from Linux USB...", DateTime.UtcNow); start = DateTime.UtcNow; client = new WebClient(); var sr = new StringReader(client.DownloadString("http://www.linux-usb.org/usb.ids")); end = DateTime.UtcNow; System.Console.WriteLine("{0}: Took {1:F2} seconds", end, (end - start).TotalSeconds); UsbVendor vendor = null; int newVendors = 0; int newProducts = 0; int modifiedVendors = 0; int modifiedProducts = 0; start = DateTime.UtcNow; System.Console.WriteLine("{0}: Adding and updating database entries...", DateTime.UtcNow); do { if (counter == 1000) { DateTime start2 = DateTime.UtcNow; System.Console.WriteLine("{0}: Saving changes", start2); ctx.SaveChanges(); end = DateTime.UtcNow; System.Console.WriteLine("{0}: Took {1:F2} seconds", end, (end - start2).TotalSeconds); counter = 0; } string line = sr.ReadLine(); if (line is null) { break; } if (line.Length == 0 || line[0] == '#') { continue; } ushort number; string name; if (line[0] == '\t') { try { number = Convert.ToUInt16(line.Substring(1, 4), 16); } catch (FormatException) { continue; } if (number == 0) { continue; } name = line.Substring(7); UsbProduct product = ctx.UsbProducts.FirstOrDefault(p => p.ProductId == number && p.Vendor != null && p.Vendor.VendorId == vendor.VendorId); if (product is null) { product = new UsbProduct(vendor, number, name); ctx.UsbProducts.Add(product); System.Console.WriteLine("{0}: Will add product {1} with ID {2:X4} and vendor {3} ({4:X4})", DateTime.UtcNow, product.Product, product.ProductId, product.Vendor?.Vendor ?? "null", product.Vendor?.VendorId ?? 0); newProducts++; counter++; } else if (name != product.Product) { System.Console. WriteLine("{0}: Will modify product with ID {1:X4} and vendor {2} ({3:X4}) from \"{4}\" to \"{5}\"", DateTime.UtcNow, product.ProductId, product.Vendor?.Vendor ?? "null", product.Vendor?.VendorId ?? 0, product.Product, name); product.Product = name; product.ModifiedWhen = DateTime.UtcNow; modifiedProducts++; counter++; } continue; } try { number = Convert.ToUInt16(line.Substring(0, 4), 16); } catch (FormatException) { continue; } if (number == 0) { continue; } name = line.Substring(6); vendor = ctx.UsbVendors.FirstOrDefault(v => v.VendorId == number); if (vendor is null) { vendor = new UsbVendor(number, name); ctx.UsbVendors.Add(vendor); System.Console.WriteLine("{0}: Will add vendor {1} with ID {2:X4}", DateTime.UtcNow, vendor.Vendor, vendor.VendorId); newVendors++; counter++; } else if (name != vendor.Vendor) { System.Console.WriteLine("{0}: Will modify vendor with ID {1:X4} from \"{2}\" to \"{3}\"", DateTime.UtcNow, vendor.VendorId, vendor.Vendor, name); vendor.Vendor = name; vendor.ModifiedWhen = DateTime.UtcNow; modifiedVendors++; counter++; } } while(true); end = DateTime.UtcNow; System.Console.WriteLine("{0}: Took {1:F2} seconds", end, (end - start).TotalSeconds); System.Console.WriteLine("{0}: Saving database changes...", DateTime.UtcNow); start = DateTime.UtcNow; ctx.SaveChanges(); end = DateTime.UtcNow; System.Console.WriteLine("{0}: Took {1:F2} seconds", end, (end - start).TotalSeconds); System.Console.WriteLine("{0}: {1} vendors added.", DateTime.UtcNow, newVendors); System.Console.WriteLine("{0}: {1} products added.", DateTime.UtcNow, newProducts); System.Console.WriteLine("{0}: {1} vendors modified.", DateTime.UtcNow, modifiedVendors); System.Console.WriteLine("{0}: {1} products modified.", DateTime.UtcNow, modifiedProducts); System.Console.WriteLine("{0}: Looking up a vendor", DateTime.UtcNow); start = DateTime.UtcNow; vendor = ctx.UsbVendors.FirstOrDefault(v => v.VendorId == 0x8086); if (vendor is null) { System.Console.WriteLine("{0}: Error, could not find vendor.", DateTime.UtcNow); } else { System.Console.WriteLine("{0}: Found {1}.", DateTime.UtcNow, vendor.Vendor); } end = DateTime.UtcNow; System.Console.WriteLine("{0}: Took {1:F2} seconds", end, (end - start).TotalSeconds); System.Console.WriteLine("{0}: Looking up a product", DateTime.UtcNow); start = DateTime.UtcNow; UsbProduct prd = ctx.UsbProducts.FirstOrDefault(p => p.ProductId == 0x0001 && p.Vendor.VendorId == 0x8086); if (prd is null) { System.Console.WriteLine("{0}: Error, could not find product.", DateTime.UtcNow); } else { System.Console.WriteLine("{0}: Found {1}.", DateTime.UtcNow, prd.Product); } end = DateTime.UtcNow; System.Console.WriteLine("{0}: Took {1:F2} seconds", end, (end - start).TotalSeconds); } catch (Exception ex) { #if DEBUG if (Debugger.IsAttached) { throw; } #endif System.Console.WriteLine("{0}: Exception {1} filling USB IDs...", DateTime.UtcNow, ex); } System.Console.WriteLine("{0}: Fixing all devices without modification time...", DateTime.UtcNow); start = DateTime.UtcNow; foreach (Device device in ctx.Devices.Where(d => d.ModifiedWhen == null)) { device.ModifiedWhen = device.AddedWhen; } end = DateTime.UtcNow; System.Console.WriteLine("{0}: Took {1:F2} seconds", end, (end - start).TotalSeconds); System.Console.WriteLine("{0}: Committing changes...", DateTime.UtcNow); start = DateTime.UtcNow; ctx.SaveChanges(); end = DateTime.UtcNow; System.Console.WriteLine("{0}: Took {1:F2} seconds", end, (end - start).TotalSeconds); try { System.Console.WriteLine("{0}: Retrieving CompactDisc read offsets from AccurateRip...", DateTime.UtcNow); start = DateTime.UtcNow; client = new WebClient(); string html = client.DownloadString("http://www.accuraterip.com/driveoffsets.htm"); end = DateTime.UtcNow; System.Console.WriteLine("{0}: Took {1:F2} seconds", end, (end - start).TotalSeconds); // The HTML is too malformed to process easily, so find start of table html = "<html><body><table><tr>" + html.Substring(html.IndexOf("<td bgcolor=\"#000000\">", StringComparison.Ordinal)); var doc = new HtmlDocument(); doc.LoadHtml(html); HtmlNode firstTable = doc.DocumentNode.SelectSingleNode("/html[1]/body[1]/table[1]"); bool firstRow = true; int addedOffsets = 0; int modifiedOffsets = 0; System.Console.WriteLine("{0}: Processing offsets...", DateTime.UtcNow); start = DateTime.UtcNow; foreach (HtmlNode row in firstTable.Descendants("tr")) { HtmlNode[] columns = row.Descendants("td").ToArray(); if (columns.Length != 4) { System.Console.WriteLine("{0}: Row does not have correct number of columns...", DateTime.UtcNow); continue; } string column0 = columns[0].InnerText; string column1 = columns[1].InnerText; string column2 = columns[2].InnerText; string column3 = columns[3].InnerText; if (firstRow) { if (column0.ToLowerInvariant() != "cd drive") { System.Console.WriteLine("{0}: Unexpected header \"{1}\" found...", DateTime.UtcNow, columns[0].InnerText); break; } if (column1.ToLowerInvariant() != "correction offset") { System.Console.WriteLine("{0}: Unexpected header \"{1}\" found...", DateTime.UtcNow, columns[1].InnerText); break; } if (column2.ToLowerInvariant() != "submitted by") { System.Console.WriteLine("{0}: Unexpected header \"{1}\" found...", DateTime.UtcNow, columns[2].InnerText); break; } if (column3.ToLowerInvariant() != "percentage agree") { System.Console.WriteLine("{0}: Unexpected header \"{1}\" found...", DateTime.UtcNow, columns[3].InnerText); break; } firstRow = false; continue; } string manufacturer; string model; if (column0[0] == '-' && column0[1] == ' ') { manufacturer = null; model = column0.Substring(2).Trim(); } else { int cutOffset = column0.IndexOf(" - ", StringComparison.Ordinal); if (cutOffset == -1) { manufacturer = null; model = column0; } else { manufacturer = column0.Substring(0, cutOffset).Trim(); model = column0.Substring(cutOffset + 3).Trim(); } } switch (manufacturer) { case "Lite-ON": manufacturer = "JLMS"; break; case "LG Electronics": manufacturer = "HL-DT-ST"; break; case "Panasonic": manufacturer = "MATSHITA"; break; } CompactDiscOffset cdOffset = ctx.CdOffsets.FirstOrDefault(o => o.Manufacturer == manufacturer && o.Model == model); if (column1.ToLowerInvariant() == "[purged]") { if (cdOffset != null) { ctx.CdOffsets.Remove(cdOffset); } continue; } if (!short.TryParse(column1, out short offset)) { continue; } if (!int.TryParse(column2, out int submissions)) { continue; } if (column3[^ 1] != '%')