Files
Aaru/DiscImageChef.Server/Statistics.aspx.cs

336 lines
16 KiB
C#
Raw Normal View History

// /***************************************************************************
// The Disc Image Chef
// ----------------------------------------------------------------------------
//
// Filename : Statistics.aspx.cs
// Author(s) : Natalia Portillo <claunia@claunia.com>
//
// Component : DiscImageChef Server.
//
// --[ Description ] ----------------------------------------------------------
//
// Renders statistics and links to reports.
//
// --[ 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-2018 Natalia Portillo
// ****************************************************************************/
using System;
using System.Collections.Generic;
2017-12-19 19:33:46 +00:00
using System.IO;
using System.Linq;
2017-12-19 19:33:46 +00:00
using System.Reflection;
2017-12-21 14:30:38 +00:00
using System.Threading;
2017-12-19 19:33:46 +00:00
using System.Web;
2017-12-21 14:30:38 +00:00
using System.Web.Hosting;
using System.Web.UI;
using System.Xml;
using System.Xml.Serialization;
using DiscImageChef.CommonTypes.Interop;
using DiscImageChef.CommonTypes.Metadata;
2018-12-22 05:00:30 +00:00
using DiscImageChef.Server.Models;
using OperatingSystem = DiscImageChef.Server.Models.OperatingSystem;
using PlatformID = DiscImageChef.CommonTypes.Interop.PlatformID;
2018-12-22 05:00:30 +00:00
using Version = DiscImageChef.Server.Models.Version;
2017-06-03 01:10:46 +01:00
namespace DiscImageChef.Server
{
/// <summary>
/// Renders a page with statistics, list of media type, devices, etc
/// </summary>
2017-12-21 14:30:38 +00:00
public partial class Statistics : Page
2017-06-03 01:10:46 +01:00
{
2018-12-22 05:00:30 +00:00
DicServerContext ctx = new DicServerContext();
2018-01-28 16:05:54 +00:00
List<DeviceItem> devices;
List<NameValueStats> operatingSystems;
2018-01-28 16:05:54 +00:00
List<MediaItem> realMedia;
2017-06-04 02:24:04 +01:00
List<NameValueStats> versions;
2018-01-28 16:05:54 +00:00
List<MediaItem> virtualMedia;
protected void Page_Load(object sender, EventArgs e)
{
lblVersion.Text = Assembly.GetExecutingAssembly().GetName().Version.ToString();
try
{
if(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);
File.Delete(Path.Combine(HostingEnvironment.MapPath("~") ?? throw new InvalidOperationException(),
"Statistics", "Statistics.xml"));
}
catch(XmlException)
{
// Do nothing
}
2018-12-22 05:00:30 +00:00
if(ctx.OperatingSystems.Any())
{
operatingSystems = new List<NameValueStats>();
2018-12-22 05:00:30 +00:00
foreach(OperatingSystem nvs in ctx.OperatingSystems)
2017-12-19 20:33:03 +00:00
operatingSystems.Add(new NameValueStats
{
name =
2018-12-22 05:00:30 +00:00
$"{DetectOS.GetPlatformName((PlatformID)Enum.Parse(typeof(PlatformID), nvs.Name), nvs.Version)}{(string.IsNullOrEmpty(nvs.Version) ? "" : " ")}{nvs.Version}",
Value = nvs.Count
2017-12-19 20:33:03 +00:00
});
repOperatingSystems.DataSource = operatingSystems.OrderBy(os => os.name).ToList();
repOperatingSystems.DataBind();
}
2017-12-19 20:33:03 +00:00
else divOperatingSystems.Visible = false;
2018-12-22 05:00:30 +00:00
if(ctx.Versions.Any())
2017-06-04 02:24:04 +01:00
{
versions = new List<NameValueStats>();
2018-12-22 05:00:30 +00:00
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
});
2017-12-19 20:33:03 +00:00
2017-06-04 02:24:04 +01:00
repVersions.DataSource = versions.OrderBy(ver => ver.name).ToList();
repVersions.DataBind();
}
2017-12-19 20:33:03 +00:00
else divVersions.Visible = false;
2017-06-04 02:24:04 +01:00
2018-12-22 05:00:30 +00:00
if(ctx.Commands.Any())
{
2018-12-22 05:00:30 +00:00
lblAnalyze.Text = ctx.Commands.FirstOrDefault(c => c.Name == "analyze")?.Count.ToString() ?? "0";
lblCompare.Text = ctx.Commands.FirstOrDefault(c => c.Name == "compare")?.Count.ToString() ?? "0";
lblChecksum.Text = ctx.Commands.FirstOrDefault(c => c.Name == "checksum")?.Count.ToString() ?? "0";
lblEntropy.Text = ctx.Commands.FirstOrDefault(c => c.Name == "entropy")?.Count.ToString() ?? "0";
lblVerify.Text = ctx.Commands.FirstOrDefault(c => c.Name == "verify")?.Count.ToString() ?? "0";
lblPrintHex.Text = ctx.Commands.FirstOrDefault(c => c.Name == "printhex")?.Count.ToString() ?? "0";
lblDecode.Text = ctx.Commands.FirstOrDefault(c => c.Name == "decode")?.Count.ToString() ?? "0";
lblDeviceInfo.Text = ctx.Commands.FirstOrDefault(c => c.Name == "device-info")?.Count.ToString() ??
"0";
lblMediaInfo.Text = ctx.Commands.FirstOrDefault(c => c.Name == "media-info")?.Count.ToString() ??
"0";
lblMediaScan.Text = ctx.Commands.FirstOrDefault(c => c.Name == "media-scan")?.Count.ToString() ??
"0";
lblFormats.Text = ctx.Commands.FirstOrDefault(c => c.Name == "formats")?.Count.ToString() ?? "0";
lblBenchmark.Text =
ctx.Commands.FirstOrDefault(c => c.Name == "benchmark")?.Count.ToString() ?? "0";
lblCreateSidecar.Text =
ctx.Commands.FirstOrDefault(c => c.Name == "create-sidecar")?.Count.ToString() ?? "0";
lblDumpMedia.Text = ctx.Commands.FirstOrDefault(c => c.Name == "dump-media")?.Count.ToString() ??
"0";
lblDeviceReport.Text =
ctx.Commands.FirstOrDefault(c => c.Name == "device-report")?.Count.ToString() ?? "0";
lblLs.Text = ctx.Commands.FirstOrDefault(c => c.Name == "ls")?.Count.ToString() ?? "0";
lblExtractFiles.Text =
ctx.Commands.FirstOrDefault(c => c.Name == "extract-files")?.Count.ToString() ?? "0";
lblListDevices.Text =
ctx.Commands.FirstOrDefault(c => c.Name == "list-devices")?.Count.ToString() ?? "0";
lblListEncodings.Text =
ctx.Commands.FirstOrDefault(c => c.Name == "list-encodings")?.Count.ToString() ?? "0";
lblConvertImage.Text =
ctx.Commands.FirstOrDefault(c => c.Name == "convert-image")?.Count.ToString() ?? "0";
lblImageInfo.Text = ctx.Commands.FirstOrDefault(c => c.Name == "image-info")?.Count.ToString() ??
"0";
}
2017-12-19 20:33:03 +00:00
else divCommands.Visible = false;
2018-12-22 05:00:30 +00:00
if(ctx.Filters.Any())
{
2018-12-22 05:00:30 +00:00
repFilters.DataSource = ctx.Filters.OrderBy(filter => filter.Name).ToList();
repFilters.DataBind();
}
2017-12-19 20:33:03 +00:00
else divFilters.Visible = false;
2018-12-22 05:00:30 +00:00
if(ctx.MediaFormats.Any())
{
2018-12-22 05:00:30 +00:00
repMediaImages.DataSource = ctx.MediaFormats.OrderBy(filter => filter.Name).ToList();
repMediaImages.DataBind();
}
2017-12-19 20:33:03 +00:00
else divMediaImages.Visible = false;
2018-12-22 05:00:30 +00:00
if(ctx.Partitions.Any())
{
2018-12-22 05:00:30 +00:00
repPartitions.DataSource = ctx.Partitions.OrderBy(filter => filter.Name).ToList();
repPartitions.DataBind();
}
2017-12-19 20:33:03 +00:00
else divPartitions.Visible = false;
2018-12-22 05:00:30 +00:00
if(ctx.Filesystems.Any())
{
2018-12-22 05:00:30 +00:00
repFilesystems.DataSource = ctx.Filesystems.OrderBy(filter => filter.Name).ToList();
repFilesystems.DataBind();
}
2017-12-19 20:33:03 +00:00
else divFilesystems.Visible = false;
2018-12-22 05:00:30 +00:00
if(ctx.Medias.Any())
{
2018-01-28 16:05:54 +00:00
realMedia = new List<MediaItem>();
virtualMedia = new List<MediaItem>();
2018-12-22 05:00:30 +00:00
foreach(Media nvs in ctx.Medias)
try
{
MediaType
.MediaTypeToString((CommonTypes.MediaType)Enum.Parse(typeof(CommonTypes.MediaType), nvs.Type),
out string type, out string subtype);
2018-12-22 05:00:30 +00:00
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)
{
2017-12-19 20:33:03 +00:00
repRealMedia.DataSource =
realMedia.OrderBy(media => media.Type).ThenBy(media => media.SubType).ToList();
repRealMedia.DataBind();
}
2017-12-19 20:33:03 +00:00
else divRealMedia.Visible = false;
if(virtualMedia.Count > 0)
{
2017-12-19 20:33:03 +00:00
repVirtualMedia.DataSource =
virtualMedia.OrderBy(media => media.Type).ThenBy(media => media.SubType).ToList();
repVirtualMedia.DataBind();
}
2017-12-19 20:33:03 +00:00
else divVirtualMedia.Visible = false;
}
else
{
2018-01-28 16:05:54 +00:00
divRealMedia.Visible = false;
divVirtualMedia.Visible = false;
}
2018-12-22 05:00:30 +00:00
if(ctx.DeviceStats != null)
{
devices = new List<DeviceItem>();
2018-12-22 05:00:30 +00:00
foreach(DeviceStat device in ctx.DeviceStats)
{
2017-12-21 16:07:20 +00:00
string url;
string xmlFile;
2017-12-19 20:33:03 +00:00
if(!string.IsNullOrWhiteSpace(device.Manufacturer) &&
2018-01-28 16:05:54 +00:00
!string.IsNullOrWhiteSpace(device.Model) &&
!string.IsNullOrWhiteSpace(device.Revision))
{
xmlFile = device.Manufacturer + "_" + device.Model + "_" + device.Revision + ".xml";
2018-06-22 08:08:38 +01:00
url =
$"ViewReport.aspx?manufacturer={HttpUtility.UrlPathEncode(device.Manufacturer)}&model={HttpUtility.UrlPathEncode(device.Model)}&revision={HttpUtility.UrlPathEncode(device.Revision)}";
}
2017-12-19 20:33:03 +00:00
else if(!string.IsNullOrWhiteSpace(device.Manufacturer) &&
!string.IsNullOrWhiteSpace(device.Model))
{
xmlFile = device.Manufacturer + "_" + device.Model + ".xml";
2018-06-22 08:08:38 +01:00
url =
$"ViewReport.aspx?manufacturer={HttpUtility.UrlPathEncode(device.Manufacturer)}&model={HttpUtility.UrlPathEncode(device.Model)}";
}
else if(!string.IsNullOrWhiteSpace(device.Model) && !string.IsNullOrWhiteSpace(device.Revision))
{
xmlFile = device.Model + "_" + device.Revision + ".xml";
2018-06-22 08:08:38 +01:00
url =
$"ViewReport.aspx?model={HttpUtility.UrlPathEncode(device.Model)}&revision={HttpUtility.UrlPathEncode(device.Revision)}";
}
else
{
xmlFile = device.Model + ".xml";
2018-01-28 16:05:54 +00:00
url = $"ViewReport.aspx?model={HttpUtility.UrlPathEncode(device.Model)}";
}
xmlFile = xmlFile.Replace('/', '_').Replace('\\', '_').Replace('?', '_');
if(!File.Exists(Path.Combine(HostingEnvironment.MapPath("~"), "Reports", xmlFile))) url = null;
devices.Add(new DeviceItem
{
Manufacturer = device.Manufacturer,
2018-01-28 16:05:54 +00:00
Model = device.Model,
Revision = device.Revision,
Bus = device.Bus,
2018-12-22 05:00:30 +00:00
ReportLink =
url == null ? "No" : $"<a href=\"{url}\" target=\"_blank\">Yes</a>"
});
}
2017-12-19 20:33:03 +00:00
repDevices.DataSource = devices.OrderBy(device => device.Manufacturer)
.ThenBy(device => device.Model).ThenBy(device => device.Revision)
.ThenBy(device => device.Bus).ToList();
repDevices.DataBind();
}
2017-12-19 20:33:03 +00:00
else divDevices.Visible = false;
}
2017-12-21 16:37:35 +00:00
catch(Exception)
{
content.InnerHtml = "<b>Could not load statistics</b>";
2018-01-28 16:05:54 +00:00
#if DEBUG
throw;
2018-01-28 16:05:54 +00:00
#endif
}
}
static FileStream WaitForFile(string fullPath, FileMode mode, FileAccess access, FileShare share)
2017-06-03 01:10:46 +01:00
{
for(int numTries = 0; numTries < 100; numTries++)
2017-06-03 01:10:46 +01:00
{
FileStream fs = null;
try
{
fs = new FileStream(fullPath, mode, access, share);
return fs;
}
catch(IOException)
{
fs?.Dispose();
2017-12-21 14:30:38 +00:00
Thread.Sleep(50);
}
2017-06-03 01:10:46 +01:00
}
return null;
2017-06-03 01:10:46 +01:00
}
class MediaItem
{
2018-01-28 16:05:54 +00:00
public string Type { get; set; }
public string SubType { get; set; }
2018-01-28 16:05:54 +00:00
public long Count { get; set; }
}
class DeviceItem
{
public string Manufacturer { get; set; }
2018-01-28 16:05:54 +00:00
public string Model { get; set; }
public string Revision { get; set; }
public string Bus { get; set; }
public string ReportLink { get; set; }
}
2017-06-03 01:10:46 +01:00
}
2017-12-19 20:33:03 +00:00
}