Move server to separate folder.

This commit is contained in:
2019-11-02 01:40:41 +00:00
commit fd3f98384c
141 changed files with 37891 additions and 0 deletions

View File

@@ -0,0 +1,199 @@
// /***************************************************************************
// The Disc Image Chef
// ----------------------------------------------------------------------------
//
// Filename : HomeController.cs
// Author(s) : Natalia Portillo <claunia@claunia.com>
//
// Component : DiscImageChef Server.
//
// --[ Description ] ----------------------------------------------------------
//
// Provides documentation data for razor views.
//
// --[ License ] --------------------------------------------------------------
//
// This library is free software; you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as
// published by the Free Software Foundation; either version 2.1 of the
// License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, see <http://www.gnu.org/licenses/>.
//
// ----------------------------------------------------------------------------
// Copyright © 2011-2019 Natalia Portillo
// ****************************************************************************/
using System;
using System.IO;
using System.Reflection;
using System.Web.Hosting;
using System.Web.Mvc;
using Markdig;
namespace DiscImageChef.Server.Controllers
{
[RoutePrefix("Home")]
public class HomeController : Controller
{
[Route("")]
[Route("~/")]
[Route("README")]
[Route("~/README")]
public ActionResult Index()
{
StreamReader sr =
new StreamReader(Path.Combine(HostingEnvironment.MapPath("~") ?? throw new InvalidOperationException(),
"docs", "README.md"));
string mdcontent = sr.ReadToEnd();
sr.Close();
mdcontent = mdcontent.Replace(".md)", ")");
ViewBag.Markdown = Markdown.ToHtml(mdcontent);
ViewBag.lblVersion = Assembly.GetExecutingAssembly().GetName().Version.ToString();
return View();
}
[Route("Changelog")]
[Route("~/Changelog")]
public ActionResult Changelog()
{
StreamReader sr =
new StreamReader(Path.Combine(HostingEnvironment.MapPath("~") ?? throw new InvalidOperationException(),
"docs", "Changelog.md"));
string mdcontent = sr.ReadToEnd();
sr.Close();
mdcontent = mdcontent.Replace(".md)", ")");
ViewBag.Markdown = Markdown.ToHtml(mdcontent);
ViewBag.lblVersion = Assembly.GetExecutingAssembly().GetName().Version.ToString();
return View();
}
[Route("CODE_OF_CONDUCT")]
[Route("~/CODE_OF_CONDUCT")]
public ActionResult CODE_OF_CONDUCT()
{
StreamReader sr =
new StreamReader(Path.Combine(HostingEnvironment.MapPath("~") ?? throw new InvalidOperationException(),
"docs", "CODE_OF_CONDUCT.md"));
string mdcontent = sr.ReadToEnd();
sr.Close();
mdcontent = mdcontent.Replace(".md)", ")").Replace("(.github/", "(");
ViewBag.Markdown = Markdown.ToHtml(mdcontent);
ViewBag.lblVersion = Assembly.GetExecutingAssembly().GetName().Version.ToString();
return View();
}
[Route("PULL_REQUEST_TEMPLATE")]
[Route("~/PULL_REQUEST_TEMPLATE")]
public ActionResult PULL_REQUEST_TEMPLATE()
{
StreamReader sr =
new StreamReader(Path.Combine(HostingEnvironment.MapPath("~") ?? throw new InvalidOperationException(),
"docs", "PULL_REQUEST_TEMPLATE.md"));
string mdcontent = sr.ReadToEnd();
sr.Close();
mdcontent = mdcontent.Replace(".md)", ")").Replace("(.github/", "(");
ViewBag.Markdown = Markdown.ToHtml(mdcontent);
ViewBag.lblVersion = Assembly.GetExecutingAssembly().GetName().Version.ToString();
return View();
}
[Route("ISSUE_TEMPLATE")]
[Route("~/ISSUE_TEMPLATE")]
public ActionResult ISSUE_TEMPLATE()
{
StreamReader sr =
new StreamReader(Path.Combine(HostingEnvironment.MapPath("~") ?? throw new InvalidOperationException(),
"docs", "ISSUE_TEMPLATE.md"));
string mdcontent = sr.ReadToEnd();
sr.Close();
mdcontent = mdcontent.Replace(".md)", ")").Replace("(.github/", "(");
ViewBag.Markdown = Markdown.ToHtml(mdcontent);
ViewBag.lblVersion = Assembly.GetExecutingAssembly().GetName().Version.ToString();
return View();
}
[Route("CONTRIBUTING")]
[Route("~/CONTRIBUTING")]
public ActionResult CONTRIBUTING()
{
StreamReader sr =
new StreamReader(Path.Combine(HostingEnvironment.MapPath("~") ?? throw new InvalidOperationException(),
"docs", "CONTRIBUTING.md"));
string mdcontent = sr.ReadToEnd();
sr.Close();
mdcontent = mdcontent.Replace(".md)", ")").Replace("(.github/", "(");
ViewBag.Markdown = Markdown.ToHtml(mdcontent);
ViewBag.lblVersion = Assembly.GetExecutingAssembly().GetName().Version.ToString();
return View();
}
[Route("DONATING")]
[Route("~/DONATING")]
public ActionResult DONATING()
{
StreamReader sr =
new StreamReader(Path.Combine(HostingEnvironment.MapPath("~") ?? throw new InvalidOperationException(),
"docs", "DONATING.md"));
string mdcontent = sr.ReadToEnd();
sr.Close();
mdcontent = mdcontent.Replace(".md)", ")");
ViewBag.Markdown = Markdown.ToHtml(mdcontent);
ViewBag.lblVersion = Assembly.GetExecutingAssembly().GetName().Version.ToString();
return View();
}
[Route("TODO")]
[Route("~/TODO")]
public ActionResult TODO()
{
StreamReader sr =
new StreamReader(Path.Combine(HostingEnvironment.MapPath("~") ?? throw new InvalidOperationException(),
"docs", "TODO.md"));
string mdcontent = sr.ReadToEnd();
sr.Close();
mdcontent = mdcontent.Replace(".md)", ")");
ViewBag.Markdown = Markdown.ToHtml(mdcontent);
ViewBag.lblVersion = Assembly.GetExecutingAssembly().GetName().Version.ToString();
return View();
}
}
}

View File

@@ -0,0 +1,474 @@
// /***************************************************************************
// The Disc Image Chef
// ----------------------------------------------------------------------------
//
// Filename : ReportController.cs
// Author(s) : Natalia Portillo <claunia@claunia.com>
//
// Component : DiscImageChef Server.
//
// --[ Description ] ----------------------------------------------------------
//
// Fetches reports from database for Razor views.
//
// --[ License ] --------------------------------------------------------------
//
// This library is free software; you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as
// published by the Free Software Foundation; either version 2.1 of the
// License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, see <http://www.gnu.org/licenses/>.
//
// ----------------------------------------------------------------------------
// Copyright © 2011-2019 Natalia Portillo
// ****************************************************************************/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web.Mvc;
using System.Web.Routing;
using DiscImageChef.CommonTypes.Metadata;
using DiscImageChef.Decoders.PCMCIA;
using DiscImageChef.Decoders.SCSI;
using DiscImageChef.Server.Models;
using Tuple = DiscImageChef.Decoders.PCMCIA.Tuple;
namespace DiscImageChef.Server.Controllers
{
public class ReportController : Controller
{
public ActionResult Index() => RedirectToAction("View", "Report", new RouteValueDictionary {{"id", 1}});
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 class Item
{
public string Manufacturer;
public string Product;
public string ProductDescription;
public string VendorDescription;
}
public class PcmciaItem : Item
{
public string Compliance;
}
}

View File

@@ -0,0 +1,531 @@
// /***************************************************************************
// The Disc Image Chef
// ----------------------------------------------------------------------------
//
// Filename : StatsController.cs
// Author(s) : Natalia Portillo <claunia@claunia.com>
//
// Component : DiscImageChef Server.
//
// --[ Description ] ----------------------------------------------------------
//
// Fetches statistics for Razor views.
//
// --[ License ] --------------------------------------------------------------
//
// This library is free software; you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as
// published by the Free Software Foundation; either version 2.1 of the
// License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, see <http://www.gnu.org/licenses/>.
//
// ----------------------------------------------------------------------------
// Copyright © 2011-2019 Natalia Portillo
// ****************************************************************************/
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Threading;
using System.Web.Hosting;
using System.Web.Mvc;
using System.Xml;
using System.Xml.Serialization;
using DiscImageChef.CommonTypes.Interop;
using DiscImageChef.CommonTypes.Metadata;
using DiscImageChef.Server.Models;
using Highsoft.Web.Mvc.Charts;
using Filter = DiscImageChef.Server.Models.Filter;
using OperatingSystem = DiscImageChef.Server.Models.OperatingSystem;
using PlatformID = DiscImageChef.CommonTypes.Interop.PlatformID;
using Version = DiscImageChef.Server.Models.Version;
namespace DiscImageChef.Server.Controllers
{
/// <summary>
/// Renders a page with statistics, list of media type, devices, etc
/// </summary>
public class StatsController : Controller
{
DicServerContext ctx = new DicServerContext();
List<DeviceItem> devices;
List<NameValueStats> operatingSystems;
List<MediaItem> realMedia;
List<NameValueStats> versions;
List<MediaItem> virtualMedia;
public ActionResult Index()
{
ViewBag.Version = Assembly.GetExecutingAssembly().GetName().Version.ToString();
try
{
if(
System.IO.File
.Exists(Path.Combine(HostingEnvironment.MapPath("~") ?? throw new InvalidOperationException(),
"Statistics", "Statistics.xml")))
try
{
Stats statistics = new Stats();
XmlSerializer xs = new XmlSerializer(statistics.GetType());
FileStream fs =
WaitForFile(Path.Combine(HostingEnvironment.MapPath("~") ?? throw new InvalidOperationException(), "Statistics", "Statistics.xml"),
FileMode.Open, FileAccess.Read, FileShare.Read);
statistics = (Stats)xs.Deserialize(fs);
fs.Close();
StatsConverter.Convert(statistics);
System.IO.File
.Delete(Path.Combine(HostingEnvironment.MapPath("~") ?? throw new InvalidOperationException(),
"Statistics", "Statistics.xml"));
}
catch(XmlException)
{
// Do nothing
}
if(ctx.OperatingSystems.Any())
{
operatingSystems = new List<NameValueStats>();
foreach(OperatingSystem nvs in ctx.OperatingSystems)
operatingSystems.Add(new NameValueStats
{
name =
$"{DetectOS.GetPlatformName((PlatformID)Enum.Parse(typeof(PlatformID), nvs.Name), nvs.Version)}{(string.IsNullOrEmpty(nvs.Version) ? "" : " ")}{nvs.Version}",
Value = nvs.Count
});
ViewBag.repOperatingSystems = operatingSystems.OrderBy(os => os.name).ToList();
List<PieSeriesData> osPieData = new List<PieSeriesData>();
decimal totalOsCount = ctx.OperatingSystems.Sum(o => o.Count);
foreach(string os in ctx.OperatingSystems.Select(o => o.Name).Distinct().ToList())
{
decimal osCount = ctx.OperatingSystems.Where(o => o.Name == os).Sum(o => o.Count);
osPieData.Add(new PieSeriesData
{
Name =
DetectOS.GetPlatformName((PlatformID)Enum.Parse(typeof(PlatformID),
os)),
Y = (double?)(osCount / totalOsCount),
Sliced = os == "Linux",
Selected = os == "Linux"
});
}
ViewData["osPieData"] = osPieData;
List<PieSeriesData> linuxPieData = new List<PieSeriesData>();
decimal linuxCount = ctx.OperatingSystems.Where(o => o.Name == PlatformID.Linux.ToString())
.Sum(o => o.Count);
foreach(OperatingSystem version in
ctx.OperatingSystems.Where(o => o.Name == PlatformID.Linux.ToString()))
linuxPieData.Add(new PieSeriesData
{
Name =
$"{DetectOS.GetPlatformName(PlatformID.Linux, version.Version)}{(string.IsNullOrEmpty(version.Version) ? "" : " ")}{version.Version}",
Y = (double?)(version.Count / linuxCount)
});
ViewData["linuxPieData"] = linuxPieData;
List<PieSeriesData> macosPieData = new List<PieSeriesData>();
decimal macosCount = ctx.OperatingSystems.Where(o => o.Name == PlatformID.MacOSX.ToString())
.Sum(o => o.Count);
foreach(OperatingSystem version in
ctx.OperatingSystems.Where(o => o.Name == PlatformID.MacOSX.ToString()))
macosPieData.Add(new PieSeriesData
{
Name =
$"{DetectOS.GetPlatformName(PlatformID.MacOSX, version.Version)}{(string.IsNullOrEmpty(version.Version) ? "" : " ")}{version.Version}",
Y = (double?)(version.Count / macosCount)
});
ViewData["macosPieData"] = macosPieData;
List<PieSeriesData> windowsPieData = new List<PieSeriesData>();
decimal windowsCount = ctx.OperatingSystems.Where(o => o.Name == PlatformID.Win32NT.ToString())
.Sum(o => o.Count);
foreach(OperatingSystem version in
ctx.OperatingSystems.Where(o => o.Name == PlatformID.Win32NT.ToString()))
windowsPieData.Add(new PieSeriesData
{
Name =
$"{DetectOS.GetPlatformName(PlatformID.Win32NT, version.Version)}{(string.IsNullOrEmpty(version.Version) ? "" : " ")}{version.Version}",
Y = (double?)(version.Count / windowsCount)
});
ViewData["windowsPieData"] = windowsPieData;
}
if(ctx.Versions.Any())
{
versions = new List<NameValueStats>();
foreach(Version nvs in ctx.Versions)
versions.Add(new NameValueStats
{
name = nvs.Value == "previous" ? "Previous than 3.4.99.0" : nvs.Value,
Value = nvs.Count
});
ViewBag.repVersions = versions.OrderBy(ver => ver.name).ToList();
decimal totalVersionCount = ctx.Versions.Sum(o => o.Count);
ViewData["versionsPieData"] = ctx.Versions.Select(version => new PieSeriesData
{
Name =
version.Value == "previous"
? "Previous than 3.4.99.0"
: version.Value,
Y = (double?)(version.Count /
totalVersionCount),
Sliced = version.Value == "previous",
Selected = version.Value == "previous"
}).ToList();
}
if(ctx.Commands.Any())
{
ViewBag.repCommands = ctx.Commands.OrderBy(c => c.Name).ToList();
decimal totalCommandCount = ctx.Commands.Sum(o => o.Count);
ViewData["commandsPieData"] = ctx
.Commands.Select(command => new PieSeriesData
{
Name = command.Name,
Y = (double?)(command.Count /
totalCommandCount),
Sliced = command.Name == "analyze",
Selected = command.Name == "analyze"
}).ToList();
}
if(ctx.Filters.Any())
{
ViewBag.repFilters = ctx.Filters.OrderBy(filter => filter.Name).ToList();
List<PieSeriesData> filtersPieData = new List<PieSeriesData>();
decimal totalFiltersCount = ctx.Filters.Sum(o => o.Count);
foreach(Filter filter in ctx.Filters.ToList())
filtersPieData.Add(new PieSeriesData
{
Name = filter.Name,
Y = (double?)(filter.Count / totalFiltersCount),
Sliced = filter.Name == "No filter",
Selected = filter.Name == "No filter"
});
ViewData["filtersPieData"] = filtersPieData;
}
if(ctx.MediaFormats.Any())
{
ViewBag.repMediaImages = ctx.MediaFormats.OrderBy(filter => filter.Name).ToList();
List<PieSeriesData> formatsPieData = new List<PieSeriesData>();
decimal totalFormatsCount = ctx.MediaFormats.Sum(o => o.Count);
decimal top10FormatCount = 0;
foreach(MediaFormat format in ctx.MediaFormats.OrderByDescending(o => o.Count).Take(10))
{
top10FormatCount += format.Count;
formatsPieData.Add(new PieSeriesData
{
Name = format.Name, Y = (double?)(format.Count / totalFormatsCount)
});
}
formatsPieData.Add(new PieSeriesData
{
Name = "Other",
Y = (double?)((totalFormatsCount - top10FormatCount) /
totalFormatsCount),
Sliced = true,
Selected = true
});
ViewData["formatsPieData"] = formatsPieData;
}
if(ctx.Partitions.Any())
{
ViewBag.repPartitions = ctx.Partitions.OrderBy(filter => filter.Name).ToList();
List<PieSeriesData> partitionsPieData = new List<PieSeriesData>();
decimal totalPartitionsCount = ctx.Partitions.Sum(o => o.Count);
decimal top10PartitionCount = 0;
foreach(Partition partition in ctx.Partitions.OrderByDescending(o => o.Count).Take(10))
{
top10PartitionCount += partition.Count;
partitionsPieData.Add(new PieSeriesData
{
Name = partition.Name,
Y = (double?)(partition.Count / totalPartitionsCount)
});
}
partitionsPieData.Add(new PieSeriesData
{
Name = "Other",
Y = (double?)((totalPartitionsCount - top10PartitionCount) /
totalPartitionsCount),
Sliced = true,
Selected = true
});
ViewData["partitionsPieData"] = partitionsPieData;
}
if(ctx.Filesystems.Any())
{
ViewBag.repFilesystems = ctx.Filesystems.OrderBy(filter => filter.Name).ToList();
List<PieSeriesData> filesystemsPieData = new List<PieSeriesData>();
decimal totalFilesystemsCount = ctx.Filesystems.Sum(o => o.Count);
decimal top10FilesystemCount = 0;
foreach(Filesystem filesystem in ctx.Filesystems.OrderByDescending(o => o.Count).Take(10))
{
top10FilesystemCount += filesystem.Count;
filesystemsPieData.Add(new PieSeriesData
{
Name = filesystem.Name,
Y = (double?)(filesystem.Count / totalFilesystemsCount)
});
}
filesystemsPieData.Add(new PieSeriesData
{
Name = "Other",
Y = (double?)((totalFilesystemsCount - top10FilesystemCount) /
totalFilesystemsCount),
Sliced = true,
Selected = true
});
ViewData["filesystemsPieData"] = filesystemsPieData;
}
if(ctx.Medias.Any())
{
realMedia = new List<MediaItem>();
virtualMedia = new List<MediaItem>();
foreach(Media nvs in ctx.Medias)
try
{
MediaType
.MediaTypeToString((CommonTypes.MediaType)Enum.Parse(typeof(CommonTypes.MediaType), nvs.Type),
out string type, out string subtype);
if(nvs.Real)
realMedia.Add(new MediaItem {Type = type, SubType = subtype, Count = nvs.Count});
else virtualMedia.Add(new MediaItem {Type = type, SubType = subtype, Count = nvs.Count});
}
catch
{
if(nvs.Real)
realMedia.Add(new MediaItem {Type = nvs.Type, SubType = null, Count = nvs.Count});
else virtualMedia.Add(new MediaItem {Type = nvs.Type, SubType = null, Count = nvs.Count});
}
if(realMedia.Count > 0)
{
ViewBag.repRealMedia =
realMedia.OrderBy(media => media.Type).ThenBy(media => media.SubType).ToList();
List<PieSeriesData> realMediaPieData = new List<PieSeriesData>();
decimal totalRealMediaCount = realMedia.Sum(o => o.Count);
decimal top10RealMediaCount = 0;
foreach(MediaItem realMediaItem in realMedia.OrderByDescending(o => o.Count).Take(10))
{
top10RealMediaCount += realMediaItem.Count;
realMediaPieData.Add(new PieSeriesData
{
Name = $"{realMediaItem.Type} ({realMediaItem.SubType})",
Y = (double?)(realMediaItem.Count / totalRealMediaCount)
});
}
realMediaPieData.Add(new PieSeriesData
{
Name = "Other",
Y = (double?)((totalRealMediaCount - top10RealMediaCount) /
totalRealMediaCount),
Sliced = true,
Selected = true
});
ViewData["realMediaPieData"] = realMediaPieData;
}
if(virtualMedia.Count > 0)
{
ViewBag.repVirtualMedia =
virtualMedia.OrderBy(media => media.Type).ThenBy(media => media.SubType).ToList();
List<PieSeriesData> virtualMediaPieData = new List<PieSeriesData>();
decimal totalVirtualMediaCount = virtualMedia.Sum(o => o.Count);
decimal top10VirtualMediaCount = 0;
foreach(MediaItem virtualMediaItem in virtualMedia.OrderByDescending(o => o.Count).Take(10))
{
top10VirtualMediaCount += virtualMediaItem.Count;
virtualMediaPieData.Add(new PieSeriesData
{
Name =
$"{virtualMediaItem.Type} ({virtualMediaItem.SubType})",
Y = (double?)(virtualMediaItem.Count /
totalVirtualMediaCount)
});
}
virtualMediaPieData.Add(new PieSeriesData
{
Name = "Other",
Y = (double?)
((totalVirtualMediaCount - top10VirtualMediaCount) /
totalVirtualMediaCount),
Sliced = true,
Selected = true
});
ViewData["virtualMediaPieData"] = virtualMediaPieData;
}
}
if(ctx.DeviceStats.Any())
{
devices = new List<DeviceItem>();
foreach(DeviceStat device in ctx.DeviceStats.ToList())
{
string xmlFile;
if(!string.IsNullOrWhiteSpace(device.Manufacturer) &&
!string.IsNullOrWhiteSpace(device.Model) &&
!string.IsNullOrWhiteSpace(device.Revision))
xmlFile = device.Manufacturer + "_" + device.Model + "_" + device.Revision + ".xml";
else if(!string.IsNullOrWhiteSpace(device.Manufacturer) &&
!string.IsNullOrWhiteSpace(device.Model))
xmlFile = device.Manufacturer + "_" + device.Model + ".xml";
else if(!string.IsNullOrWhiteSpace(device.Model) && !string.IsNullOrWhiteSpace(device.Revision))
xmlFile = device.Model + "_" + device.Revision + ".xml";
else xmlFile = device.Model + ".xml";
xmlFile = xmlFile.Replace('/', '_').Replace('\\', '_').Replace('?', '_');
if(System.IO.File.Exists(Path.Combine(HostingEnvironment.MapPath("~"), "Reports", xmlFile)))
{
DeviceReport deviceReport = new DeviceReport();
XmlSerializer xs = new XmlSerializer(deviceReport.GetType());
FileStream fs =
WaitForFile(Path.Combine(HostingEnvironment.MapPath("~") ?? throw new InvalidOperationException(), "Reports", xmlFile),
FileMode.Open, FileAccess.Read, FileShare.Read);
deviceReport = (DeviceReport)xs.Deserialize(fs);
fs.Close();
DeviceReportV2 deviceReportV2 = new DeviceReportV2(deviceReport);
device.Report = ctx.Devices.Add(new Device(deviceReportV2));
ctx.SaveChanges();
System.IO.File
.Delete(Path.Combine(HostingEnvironment.MapPath("~") ?? throw new InvalidOperationException(),
"Reports", xmlFile));
}
devices.Add(new DeviceItem
{
Manufacturer = device.Manufacturer,
Model = device.Model,
Revision = device.Revision,
Bus = device.Bus,
ReportId = device.Report != null && device.Report.Id != 0
? device.Report.Id
: 0
});
}
ViewBag.repDevices = devices.OrderBy(device => device.Manufacturer).ThenBy(device => device.Model)
.ThenBy(device => device.Revision).ThenBy(device => device.Bus)
.ToList();
ViewData["devicesBusPieData"] = (from deviceBus in devices.Select(d => d.Bus).Distinct()
let deviceBusCount = devices.Count(d => d.Bus == deviceBus)
select new PieSeriesData
{
Name = deviceBus,
Y = deviceBusCount / (double)devices.Count
}).ToList();
ViewData["devicesManufacturerPieData"] =
(from manufacturer in
devices.Where(d => d.Manufacturer != null).Select(d => d.Manufacturer.ToLowerInvariant())
.Distinct()
let manufacturerCount = devices.Count(d => d.Manufacturer?.ToLowerInvariant() == manufacturer)
select new PieSeriesData {Name = manufacturer, Y = manufacturerCount / (double)devices.Count})
.ToList();
}
}
catch(Exception)
{
#if DEBUG
throw;
#endif
return Content("Could not read statistics");
}
return View();
}
static FileStream WaitForFile(string fullPath, FileMode mode, FileAccess access, FileShare share)
{
for(int numTries = 0; numTries < 100; numTries++)
{
FileStream fs = null;
try
{
fs = new FileStream(fullPath, mode, access, share);
return fs;
}
catch(IOException)
{
fs?.Dispose();
Thread.Sleep(50);
}
}
return null;
}
}
}

View File

@@ -0,0 +1,98 @@
// /***************************************************************************
// The Disc Image Chef
// ----------------------------------------------------------------------------
//
// Filename : UploadReportController.cs
// Author(s) : Natalia Portillo <claunia@claunia.com>
//
// Component : DiscImageChef Server.
//
// --[ Description ] ----------------------------------------------------------
//
// Handles report uploads.
//
// --[ License ] --------------------------------------------------------------
//
// This library is free software; you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as
// published by the Free Software Foundation; either version 2.1 of the
// License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, see <http://www.gnu.org/licenses/>.
//
// ----------------------------------------------------------------------------
// Copyright © 2011-2019 Natalia Portillo
// ****************************************************************************/
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Text;
using System.Web.Http;
using DiscImageChef.CommonTypes.Metadata;
using DiscImageChef.Dto;
using DiscImageChef.Server.Models;
using Newtonsoft.Json;
namespace DiscImageChef.Server.Controllers
{
public class UpdateController : ApiController
{
/// <summary>
/// Receives a report from DiscImageChef.Core, verifies it's in the correct format and stores it on the server
/// </summary>
/// <returns>HTTP response</returns>
[Route("api/update")]
[HttpGet]
public HttpResponseMessage UploadReport(long timestamp)
{
DicServerContext ctx = new DicServerContext();
SyncDto sync = new SyncDto();
DateTime lastSync = DateHandlers.UnixToDateTime(timestamp);
sync.UsbVendors = new List<UsbVendorDto>();
foreach(UsbVendor vendor in ctx.UsbVendors.Where(v => v.ModifiedWhen > lastSync))
sync.UsbVendors.Add(new UsbVendorDto {VendorId = (ushort)vendor.VendorId, Vendor = vendor.Vendor});
sync.UsbProducts = new List<UsbProductDto>();
foreach(UsbProduct product in ctx.UsbProducts.Where(p => p.ModifiedWhen > lastSync))
sync.UsbProducts.Add(new UsbProductDto
{
Id = product.Id,
Product = product.Product,
ProductId = (ushort)product.ProductId,
VendorId = (ushort)product.Vendor.VendorId
});
sync.Offsets = new List<CdOffsetDto>();
foreach(CompactDiscOffset offset in ctx.CdOffsets.Where(o => o.ModifiedWhen > lastSync))
sync.Offsets.Add(new CdOffsetDto(offset, offset.Id));
sync.Devices = new List<DeviceDto>();
foreach(Device device in ctx.Devices.Where(d => d.ModifiedWhen > lastSync).ToList())
sync.Devices.Add(new
DeviceDto(JsonConvert.DeserializeObject<DeviceReportV2>(JsonConvert.SerializeObject(device, Formatting.None, new JsonSerializerSettings {ReferenceLoopHandling = ReferenceLoopHandling.Ignore})),
device.Id, device.OptimalMultipleSectorsRead));
JsonSerializer js = JsonSerializer.Create();
StringWriter sw = new StringWriter();
js.Serialize(sw, sync);
return new HttpResponseMessage
{
StatusCode = HttpStatusCode.OK,
Content = new StringContent(sw.ToString(), Encoding.UTF8, "application/json")
};
}
}
}

View File

@@ -0,0 +1,195 @@
// /***************************************************************************
// The Disc Image Chef
// ----------------------------------------------------------------------------
//
// Filename : UploadReportController.cs
// Author(s) : Natalia Portillo <claunia@claunia.com>
//
// Component : DiscImageChef Server.
//
// --[ Description ] ----------------------------------------------------------
//
// Handles report uploads.
//
// --[ License ] --------------------------------------------------------------
//
// This library is free software; you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as
// published by the Free Software Foundation; either version 2.1 of the
// License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, see <http://www.gnu.org/licenses/>.
//
// ----------------------------------------------------------------------------
// Copyright © 2011-2019 Natalia Portillo
// ****************************************************************************/
using System;
using System.Diagnostics;
using System.IO;
using System.Net;
using System.Net.Http;
using System.Text;
using System.Web;
using System.Web.Hosting;
using System.Web.Http;
using System.Xml.Serialization;
using Cinchoo.PGP;
using DiscImageChef.CommonTypes.Metadata;
using DiscImageChef.Server.Models;
using MailKit.Net.Smtp;
using MimeKit;
using Newtonsoft.Json;
namespace DiscImageChef.Server.Controllers
{
public class UploadReportController : ApiController
{
DicServerContext ctx = new DicServerContext();
/// <summary>
/// Receives a report from DiscImageChef.Core, verifies it's in the correct format and stores it on the server
/// </summary>
/// <returns>HTTP response</returns>
[Route("api/uploadreport")]
[HttpPost]
public HttpResponseMessage UploadReport()
{
HttpResponseMessage response = new HttpResponseMessage {StatusCode = HttpStatusCode.OK};
try
{
DeviceReport newReport = new DeviceReport();
HttpRequest request = HttpContext.Current.Request;
XmlSerializer xs = new XmlSerializer(newReport.GetType());
newReport = (DeviceReport)xs.Deserialize(request.InputStream);
if(newReport == null)
{
response.Content = new StringContent("notstats", Encoding.UTF8, "text/plain");
return response;
}
DeviceReportV2 reportV2 = new DeviceReportV2(newReport);
StringWriter jsonSw = new StringWriter();
jsonSw.Write(JsonConvert.SerializeObject(reportV2, Formatting.Indented,
new JsonSerializerSettings
{
NullValueHandling = NullValueHandling.Ignore
}));
string reportV2String = jsonSw.ToString();
jsonSw.Close();
ctx.Reports.Add(new UploadedReport(reportV2));
ctx.SaveChanges();
MemoryStream pgpIn = new MemoryStream(Encoding.UTF8.GetBytes(reportV2String));
MemoryStream pgpOut = new MemoryStream();
ChoPGPEncryptDecrypt pgp = new ChoPGPEncryptDecrypt();
pgp.Encrypt(pgpIn, pgpOut,
Path.Combine(HostingEnvironment.MapPath("~") ?? throw new InvalidOperationException(),
"public.asc"), true);
pgpOut.Position = 0;
reportV2String = Encoding.UTF8.GetString(pgpOut.ToArray());
MimeMessage message = new MimeMessage
{
Subject = "New device report (old version)",
Body = new TextPart("plain") {Text = reportV2String}
};
message.From.Add(new MailboxAddress("DiscImageChef", "dic@claunia.com"));
message.To.Add(new MailboxAddress("Natalia Portillo", "claunia@claunia.com"));
using(SmtpClient client = new SmtpClient())
{
client.Connect("mail.claunia.com", 25, false);
client.Send(message);
client.Disconnect(true);
}
response.Content = new StringContent("ok", Encoding.UTF8, "text/plain");
return response;
}
// ReSharper disable once RedundantCatchClause
catch
{
#if DEBUG
if(Debugger.IsAttached) throw;
#endif
response.Content = new StringContent("error", Encoding.UTF8, "text/plain");
return response;
}
}
/// <summary>
/// Receives a report from DiscImageChef.Core, verifies it's in the correct format and stores it on the server
/// </summary>
/// <returns>HTTP response</returns>
[Route("api/uploadreportv2")]
[HttpPost]
public HttpResponseMessage UploadReportV2()
{
HttpResponseMessage response = new HttpResponseMessage {StatusCode = HttpStatusCode.OK};
try
{
HttpRequest request = HttpContext.Current.Request;
StreamReader sr = new StreamReader(request.InputStream);
string reportJson = sr.ReadToEnd();
DeviceReportV2 newReport = JsonConvert.DeserializeObject<DeviceReportV2>(reportJson);
if(newReport == null)
{
response.Content = new StringContent("notstats", Encoding.UTF8, "text/plain");
return response;
}
ctx.Reports.Add(new UploadedReport(newReport));
ctx.SaveChanges();
MemoryStream pgpIn = new MemoryStream(Encoding.UTF8.GetBytes(reportJson));
MemoryStream pgpOut = new MemoryStream();
ChoPGPEncryptDecrypt pgp = new ChoPGPEncryptDecrypt();
pgp.Encrypt(pgpIn, pgpOut,
Path.Combine(HostingEnvironment.MapPath("~") ?? throw new InvalidOperationException(),
"public.asc"), true);
pgpOut.Position = 0;
reportJson = Encoding.UTF8.GetString(pgpOut.ToArray());
MimeMessage message = new MimeMessage
{
Subject = "New device report", Body = new TextPart("plain") {Text = reportJson}
};
message.From.Add(new MailboxAddress("DiscImageChef", "dic@claunia.com"));
message.To.Add(new MailboxAddress("Natalia Portillo", "claunia@claunia.com"));
using(SmtpClient client = new SmtpClient())
{
client.Connect("mail.claunia.com", 25, false);
client.Send(message);
client.Disconnect(true);
}
response.Content = new StringContent("ok", Encoding.UTF8, "text/plain");
return response;
}
// ReSharper disable once RedundantCatchClause
catch
{
#if DEBUG
if(Debugger.IsAttached) throw;
#endif
response.Content = new StringContent("error", Encoding.UTF8, "text/plain");
return response;
}
}
}
}

View File

@@ -0,0 +1,254 @@
// /***************************************************************************
// The Disc Image Chef
// ----------------------------------------------------------------------------
//
// Filename : UploadStatsController.cs
// Author(s) : Natalia Portillo <claunia@claunia.com>
//
// Component : DiscImageChef Server.
//
// --[ Description ] ----------------------------------------------------------
//
// Handles statistics uploads.
//
// --[ License ] --------------------------------------------------------------
//
// This library is free software; you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as
// published by the Free Software Foundation; either version 2.1 of the
// License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, see <http://www.gnu.org/licenses/>.
//
// ----------------------------------------------------------------------------
// Copyright © 2011-2019 Natalia Portillo
// ****************************************************************************/
using System;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Text;
using System.Threading;
using System.Web;
using System.Web.Http;
using System.Xml.Serialization;
using DiscImageChef.CommonTypes.Metadata;
using DiscImageChef.Server.Models;
using Newtonsoft.Json;
using OperatingSystem = DiscImageChef.Server.Models.OperatingSystem;
using Version = DiscImageChef.Server.Models.Version;
namespace DiscImageChef.Server.Controllers
{
public class UploadStatsController : ApiController
{
/// <summary>
/// Receives statistics from DiscImageChef.Core, processes them and adds them to a server-side global statistics XML
/// </summary>
/// <returns>HTTP response</returns>
[Route("api/uploadstats")]
[HttpPost]
public HttpResponseMessage UploadStats()
{
HttpResponseMessage response = new HttpResponseMessage {StatusCode = HttpStatusCode.OK};
try
{
Stats newStats = new Stats();
HttpRequest request = HttpContext.Current.Request;
XmlSerializer xs = new XmlSerializer(newStats.GetType());
newStats = (Stats)xs.Deserialize(request.InputStream);
if(newStats == null)
{
response.Content = new StringContent("notstats", Encoding.UTF8, "text/plain");
return response;
}
StatsConverter.Convert(newStats);
response.Content = new StringContent("ok", Encoding.UTF8, "text/plain");
return response;
}
catch(Exception ex)
{
#if DEBUG
if(Debugger.IsAttached) throw;
#endif
response.Content = new StringContent("error", Encoding.UTF8, "text/plain");
return response;
}
}
/// <summary>
/// Receives a report from DiscImageChef.Core, verifies it's in the correct format and stores it on the server
/// </summary>
/// <returns>HTTP response</returns>
[Route("api/uploadstatsv2")]
[HttpPost]
public HttpResponseMessage UploadStatsV2()
{
HttpResponseMessage response = new HttpResponseMessage {StatusCode = HttpStatusCode.OK};
try
{
HttpRequest request = HttpContext.Current.Request;
StreamReader sr = new StreamReader(request.InputStream);
StatsDto newstats = JsonConvert.DeserializeObject<StatsDto>(sr.ReadToEnd());
if(newstats == null)
{
response.Content = new StringContent("notstats", Encoding.UTF8, "text/plain");
return response;
}
DicServerContext ctx = new DicServerContext();
if(newstats.Commands != null)
foreach(NameValueStats nvs in newstats.Commands)
{
Command existing = ctx.Commands.FirstOrDefault(c => c.Name == nvs.name);
if(existing == null) ctx.Commands.Add(new Command {Name = nvs.name, Count = nvs.Value});
else existing.Count += nvs.Value;
}
if(newstats.Versions != null)
foreach(NameValueStats nvs in newstats.Versions)
{
Version existing = ctx.Versions.FirstOrDefault(c => c.Value == nvs.name);
if(existing == null) ctx.Versions.Add(new Version {Value = nvs.name, Count = nvs.Value});
else existing.Count += nvs.Value;
}
if(newstats.Filesystems != null)
foreach(NameValueStats nvs in newstats.Filesystems)
{
Filesystem existing = ctx.Filesystems.FirstOrDefault(c => c.Name == nvs.name);
if(existing == null) ctx.Filesystems.Add(new Filesystem {Name = nvs.name, Count = nvs.Value});
else existing.Count += nvs.Value;
}
if(newstats.Partitions != null)
foreach(NameValueStats nvs in newstats.Partitions)
{
Partition existing = ctx.Partitions.FirstOrDefault(c => c.Name == nvs.name);
if(existing == null) ctx.Partitions.Add(new Partition {Name = nvs.name, Count = nvs.Value});
else existing.Count += nvs.Value;
}
if(newstats.MediaFormats != null)
foreach(NameValueStats nvs in newstats.MediaFormats)
{
MediaFormat existing = ctx.MediaFormats.FirstOrDefault(c => c.Name == nvs.name);
if(existing == null) ctx.MediaFormats.Add(new MediaFormat {Name = nvs.name, Count = nvs.Value});
else existing.Count += nvs.Value;
}
if(newstats.Filters != null)
foreach(NameValueStats nvs in newstats.Filters)
{
Filter existing = ctx.Filters.FirstOrDefault(c => c.Name == nvs.name);
if(existing == null) ctx.Filters.Add(new Filter {Name = nvs.name, Count = nvs.Value});
else existing.Count += nvs.Value;
}
if(newstats.OperatingSystems != null)
foreach(OsStats operatingSystem in newstats.OperatingSystems)
{
OperatingSystem existing =
ctx.OperatingSystems.FirstOrDefault(c => c.Name == operatingSystem.name &&
c.Version == operatingSystem.version);
if(existing == null)
ctx.OperatingSystems.Add(new OperatingSystem
{
Name = operatingSystem.name,
Version = operatingSystem.version,
Count = operatingSystem.Value
});
else existing.Count += operatingSystem.Value;
}
if(newstats.Medias != null)
foreach(MediaStats media in newstats.Medias)
{
Media existing = ctx.Medias.FirstOrDefault(c => c.Type == media.type && c.Real == media.real);
if(existing == null)
ctx.Medias.Add(new Media {Type = media.type, Real = media.real, Count = media.Value});
else existing.Count += media.Value;
}
if(newstats.Devices != null)
foreach(DeviceStats device in newstats.Devices)
{
DeviceStat existing =
ctx.DeviceStats.FirstOrDefault(c => c.Bus == device.Bus &&
c.Manufacturer == device.Manufacturer &&
c.Model == device.Model &&
c.Revision == device.Revision);
if(existing == null)
ctx.DeviceStats.Add(new DeviceStat
{
Bus = device.Bus,
Manufacturer = device.Manufacturer,
Model = device.Model,
Revision = device.Revision
});
}
ctx.SaveChanges();
response.Content = new StringContent("ok", Encoding.UTF8, "text/plain");
return response;
}
// ReSharper disable once RedundantCatchClause
catch
{
#if DEBUG
if(Debugger.IsAttached) throw;
#endif
response.Content = new StringContent("error", Encoding.UTF8, "text/plain");
return response;
}
}
FileStream WaitForFile(string fullPath, FileMode mode, FileAccess access, FileShare share)
{
for(int numTries = 0; numTries < 100; numTries++)
{
FileStream fs = null;
try
{
fs = new FileStream(fullPath, mode, access, share);
return fs;
}
catch(IOException)
{
if(fs != null) fs.Dispose();
Thread.Sleep(50);
}
}
return null;
}
}
}