mirror of
https://github.com/aaru-dps/Aaru.Server.git
synced 2025-12-16 19:24:27 +00:00
Move server to separate folder.
This commit is contained in:
199
DiscImageChef.Server/Controllers/HomeController.cs
Normal file
199
DiscImageChef.Server/Controllers/HomeController.cs
Normal 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();
|
||||
}
|
||||
}
|
||||
}
|
||||
474
DiscImageChef.Server/Controllers/ReportController.cs
Normal file
474
DiscImageChef.Server/Controllers/ReportController.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
531
DiscImageChef.Server/Controllers/StatsController.cs
Normal file
531
DiscImageChef.Server/Controllers/StatsController.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
98
DiscImageChef.Server/Controllers/UpdateController.cs
Normal file
98
DiscImageChef.Server/Controllers/UpdateController.cs
Normal 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")
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
195
DiscImageChef.Server/Controllers/UploadReportController.cs
Normal file
195
DiscImageChef.Server/Controllers/UploadReportController.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
254
DiscImageChef.Server/Controllers/UploadStatsController.cs
Normal file
254
DiscImageChef.Server/Controllers/UploadStatsController.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user