Compare commits
233 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 5f4cb20900 | |||
| aee467cb53 | |||
| 6ce6e2cccf | |||
| cd858c2215 | |||
| 7e07c07171 | |||
| 15e2806731 | |||
| 53baf4eb78 | |||
| 8c48ab6ecd | |||
| 8afe4195a9 | |||
| dcc4fcb984 | |||
| 4631903019 | |||
| 85d51c0e45 | |||
| 974a07f3bb | |||
| b576aec641 | |||
| a2aaa4c913 | |||
| 318a70d9a3 | |||
| 53e57d4017 | |||
| 143dc1b3e6 | |||
| a4f18d1d49 | |||
| 46222f2a78 | |||
| 2e091383ec | |||
| 7ace4d1c7e | |||
| f901d45d78 | |||
| 028d1ccc64 | |||
| 7b6a44921d | |||
| 23406e5e39 | |||
| 83557e6f0c | |||
| 1c90c89158 | |||
| 9924153e82 | |||
| 3ec2ea7d37 | |||
| b6945d9bbd | |||
| 6740a7479a | |||
| a3fb09440d | |||
| 7353405b16 | |||
| 6fcb1a1eae | |||
| e204ea4d5f | |||
| 0a4a2816a0 | |||
| 473b02f718 | |||
| 5a2c29ea0b | |||
| 1a8ec32f0f | |||
| 9e7daf2043 | |||
| 0c690cff5a | |||
| b55b77de9f | |||
| 937508c440 | |||
| cfe4c4b912 | |||
| d75663a219 | |||
| 1e24844e88 | |||
| 273b67c422 | |||
| 13549e7ec4 | |||
| bbb40bd5c4 | |||
| 22dad072b9 | |||
| 215e9863a2 | |||
| 190abc72dd | |||
| af75a55d44 | |||
| e05206d405 | |||
| 53eed02a4f | |||
| 57a7f67c3a | |||
| 47e11c0fd6 | |||
| 708ca16de8 | |||
| 535a3f2967 | |||
| ebd1c79f64 | |||
| 7194dd612d | |||
| 584bc07824 | |||
| 2bd9238090 | |||
| b11fa5b1d6 | |||
| 7667eaa49e | |||
| 9f7c0f965e | |||
| a274a33cf6 | |||
| 4acfd54319 | |||
| 941f1cf13e | |||
| f225edd2d4 | |||
| 5824680e2a | |||
| ed4ec890da | |||
| 56453fa081 | |||
| 11c824518f | |||
| d720303a83 | |||
| 02b29948ce | |||
| a152365312 | |||
| dba6c383f6 | |||
| ba32b3b717 | |||
| 51cebd0706 | |||
| 983bdbefb9 | |||
| be99083d6a | |||
| 4c19a1ef63 | |||
| 4f9f0fd0a8 | |||
| 05593a1466 | |||
| 2873b4be8a | |||
| 7a1ff211a0 | |||
| fcf70f724e | |||
| 99be87ed9c | |||
| 261baf669e | |||
| b0fddd491b | |||
| dff47c0e8b | |||
| ed58619919 | |||
| 2a2731b9f3 | |||
| 13e666d95a | |||
| 96cccab958 | |||
| e463a7361e | |||
| 58e467b6d6 | |||
| 81bd6ccd83 | |||
| 3e7db6b552 | |||
| 09a6369693 | |||
| 9bfeff8c42 | |||
| 3e57af394d | |||
| e11d0871c4 | |||
| f7fdfb0c8a | |||
| 806aadd161 | |||
| af4a94870e | |||
| 486ce17857 | |||
| f82b47dd46 | |||
| f1d27732c7 | |||
| 28e5901929 | |||
| e531ffe2b7 | |||
| 4fca015afa | |||
| a80ed14038 | |||
| f3e0939a06 | |||
| 2cd6ddfa24 | |||
| b4a30061e3 | |||
| cb033c0b70 | |||
| 3c197e7b2f | |||
| 9f62da9ccd | |||
| df721d7d6e | |||
| 8278efb9a6 | |||
| d477ad5d9c | |||
| 0755b6fc8a | |||
| 78dd494304 | |||
| 0497e145ea | |||
| 4d6aa18095 | |||
| fdf1bd4bc6 | |||
| 82183f6508 | |||
| d6ee70b860 | |||
| 5ce9e51ae7 | |||
| ed66f4f285 | |||
| 526f8547f7 | |||
| d8e93cb31b | |||
| 5fa74a8cc0 | |||
| a0d643eda1 | |||
| 0887eb447e | |||
| d9cade74b6 | |||
| 67261cd5b8 | |||
| aca037ecf8 | |||
| ef8df08e29 | |||
| 4c91d03385 | |||
| b52cbcb94a | |||
| 065b14b158 | |||
| cbf16a41a6 | |||
| f74d49b96e | |||
| afa548fb70 | |||
| c72c18e825 | |||
| 6df2e16a7f | |||
| 3e4dda683d | |||
| dc8a5ab806 | |||
| 0f20b16f41 | |||
| 23975f8fc3 | |||
| 062769a7e3 | |||
| 1dfa3f4f15 | |||
| e082c22983 | |||
| b286f8473a | |||
| 0a67e9544d | |||
| 687713428b | |||
| aeb9eb4d3a | |||
| 9baca7f633 | |||
| 5fcb81e9e8 | |||
| 3c521541fd | |||
| 669de7e46b | |||
| a15f3daad5 | |||
| 86faf02cf0 | |||
| 27c21175d7 | |||
| 489a5df7cc | |||
| 85425d2a1f | |||
| 4b866c9486 | |||
| acfa0e5094 | |||
| 5ea9a814d6 | |||
| 44f6d325db | |||
| 4e6093702d | |||
| d955addc26 | |||
| dee347128e | |||
| d6de5e5958 | |||
| 80f7cd0275 | |||
| 538fd2e394 | |||
| ad5aea6df2 | |||
| b070283270 | |||
| 6a017c7be9 | |||
| 6fe8d9c8e0 | |||
| 7eb17a91c9 | |||
| d2acf31b81 | |||
| 50399f4f48 | |||
| 23db0b6111 | |||
| a7b3f045d6 | |||
| 76318d8d00 | |||
| f2ac35a7fa | |||
| b1575fa321 | |||
| 4283b62803 | |||
| 7551b39b8e | |||
| 3ae99f45bb | |||
| c846fa053a | |||
| 57c2e062fc | |||
| e940c24522 | |||
| 73d6160db6 | |||
| 13c5efe5d6 | |||
| bbe4cccc91 | |||
| 41e061df54 | |||
| 35a07344cc | |||
| 4b6604df5b | |||
| 0de162fce3 | |||
| f26474fa4d | |||
| 8e2a17cfc5 | |||
| 3b0286fe11 | |||
| 12fc071786 | |||
| 1d931463a8 | |||
| f01bc940f6 | |||
| ea80876286 | |||
| 7062a40dfb | |||
| 2d8dcb6900 | |||
| 3358d9e320 | |||
| 1cc7e94646 | |||
| c528a2be26 | |||
| a43db01b96 | |||
| b78ce003a7 | |||
| 81d024618a | |||
| 4d8fec2ced | |||
| 7cbed23a74 | |||
| 6700d092b3 | |||
| 4b3905b4fc | |||
| 09b1c93bf0 | |||
| 5c5e5a23a2 | |||
| 9bfa95e263 | |||
| 2274e2201d | |||
| f4394fe2a0 | |||
| 5ba9fde10f | |||
| 67a624d5b5 | |||
| 0b79140290 | |||
| 5013fa27bd |
@@ -0,0 +1,4 @@
|
||||
[*.cs]
|
||||
|
||||
# VSSpell001: Spell Check
|
||||
dotnet_diagnostic.VSSpell001.severity = suggestion
|
||||
@@ -3,6 +3,8 @@
|
||||
## Ignore Visual Studio temporary files, build results, and
|
||||
## files generated by popular Visual Studio add-ons.
|
||||
|
||||
.vs/
|
||||
|
||||
# User-specific files
|
||||
*.suo
|
||||
*.user
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<configuration>
|
||||
<solution>
|
||||
<add key="disableSourceControlIntegration" value="true" />
|
||||
</solution>
|
||||
</configuration>
|
||||
Binary file not shown.
@@ -1,153 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">$(MSBuildProjectDirectory)\..\</SolutionDir>
|
||||
|
||||
<!-- Enable the restore command to run before builds -->
|
||||
<RestorePackages Condition=" '$(RestorePackages)' == '' ">false</RestorePackages>
|
||||
|
||||
<!-- Property that enables building a package from a project -->
|
||||
<BuildPackage Condition=" '$(BuildPackage)' == '' ">false</BuildPackage>
|
||||
|
||||
<!-- Determines if package restore consent is required to restore packages -->
|
||||
<RequireRestoreConsent Condition=" '$(RequireRestoreConsent)' != 'false' ">true</RequireRestoreConsent>
|
||||
|
||||
<!-- Download NuGet.exe if it does not already exist -->
|
||||
<DownloadNuGetExe Condition=" '$(DownloadNuGetExe)' == '' ">false</DownloadNuGetExe>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup Condition=" '$(PackageSources)' == '' ">
|
||||
<!-- Package sources used to restore packages. By default, registered sources under %APPDATA%\NuGet\NuGet.Config will be used -->
|
||||
<!-- The official NuGet package source (https://nuget.org/api/v2/) will be excluded if package sources are specified and it does not appear in the list -->
|
||||
<!--
|
||||
<PackageSource Include="https://nuget.org/api/v2/" />
|
||||
<PackageSource Include="https://my-nuget-source/nuget/" />
|
||||
-->
|
||||
</ItemGroup>
|
||||
|
||||
<PropertyGroup Condition=" '$(OS)' == 'Windows_NT'">
|
||||
<!-- Windows specific commands -->
|
||||
<NuGetToolsPath>$([System.IO.Path]::Combine($(SolutionDir), ".nuget"))</NuGetToolsPath>
|
||||
<PackagesConfig>$([System.IO.Path]::Combine($(ProjectDir), "packages.config"))</PackagesConfig>
|
||||
<PackagesDir>$([System.IO.Path]::Combine($(SolutionDir), "packages"))</PackagesDir>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition=" '$(OS)' != 'Windows_NT'">
|
||||
<!-- We need to launch nuget.exe with the mono command if we're not on windows -->
|
||||
<NuGetToolsPath>$(SolutionDir).nuget</NuGetToolsPath>
|
||||
<PackagesConfig>packages.config</PackagesConfig>
|
||||
<PackagesDir>$(SolutionDir)packages</PackagesDir>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
<!-- NuGet command -->
|
||||
<NuGetExePath Condition=" '$(NuGetExePath)' == '' ">$(NuGetToolsPath)\nuget.exe</NuGetExePath>
|
||||
<PackageSources Condition=" $(PackageSources) == '' ">@(PackageSource)</PackageSources>
|
||||
|
||||
<NuGetCommand Condition=" '$(OS)' == 'Windows_NT'">"$(NuGetExePath)"</NuGetCommand>
|
||||
<NuGetCommand Condition=" '$(OS)' != 'Windows_NT' ">mono --runtime=v4.0.30319 $(NuGetExePath)</NuGetCommand>
|
||||
|
||||
<PackageOutputDir Condition="$(PackageOutputDir) == ''">$(TargetDir.Trim('\\'))</PackageOutputDir>
|
||||
|
||||
<RequireConsentSwitch Condition=" $(RequireRestoreConsent) == 'true' ">-RequireConsent</RequireConsentSwitch>
|
||||
<!-- Commands -->
|
||||
<RestoreCommand>$(NuGetCommand) install "$(PackagesConfig)" -source "$(PackageSources)" $(RequireConsentSwitch) -o "$(PackagesDir)"</RestoreCommand>
|
||||
<BuildCommand>$(NuGetCommand) pack "$(ProjectPath)" -p Configuration=$(Configuration) -o "$(PackageOutputDir)" -symbols</BuildCommand>
|
||||
|
||||
<!-- We need to ensure packages are restored prior to assembly resolve -->
|
||||
<ResolveReferencesDependsOn Condition="$(RestorePackages) == 'true'">
|
||||
RestorePackages;
|
||||
$(ResolveReferencesDependsOn);
|
||||
</ResolveReferencesDependsOn>
|
||||
|
||||
<!-- Make the build depend on restore packages -->
|
||||
<BuildDependsOn Condition="$(BuildPackage) == 'true'">
|
||||
$(BuildDependsOn);
|
||||
BuildPackage;
|
||||
</BuildDependsOn>
|
||||
</PropertyGroup>
|
||||
|
||||
<Target Name="CheckPrerequisites">
|
||||
<!-- Raise an error if we're unable to locate nuget.exe -->
|
||||
<Error Condition="'$(DownloadNuGetExe)' != 'true' AND !Exists('$(NuGetExePath)')" Text="Unable to locate '$(NuGetExePath)'" />
|
||||
<SetEnvironmentVariable EnvKey="VisualStudioVersion" EnvValue="$(VisualStudioVersion)" Condition=" '$(VisualStudioVersion)' != '' AND '$(OS)' == 'Windows_NT' " />
|
||||
<!--
|
||||
Take advantage of MsBuild's build dependency tracking to make sure that we only ever download nuget.exe once.
|
||||
This effectively acts as a lock that makes sure that the download operation will only happen once and all
|
||||
parallel builds will have to wait for it to complete.
|
||||
-->
|
||||
<MsBuild Targets="_DownloadNuGet" Projects="$(MSBuildThisFileFullPath)" Properties="Configuration=NOT_IMPORTANT" />
|
||||
</Target>
|
||||
|
||||
<Target Name="_DownloadNuGet">
|
||||
<DownloadNuGet OutputFilename="$(NuGetExePath)" Condition=" '$(DownloadNuGetExe)' == 'true' AND !Exists('$(NuGetExePath)')" />
|
||||
</Target>
|
||||
|
||||
<Target Name="RestorePackages" DependsOnTargets="CheckPrerequisites">
|
||||
<Exec Command="$(RestoreCommand)"
|
||||
Condition="'$(OS)' != 'Windows_NT' And Exists('$(PackagesConfig)')" />
|
||||
|
||||
<Exec Command="$(RestoreCommand)"
|
||||
LogStandardErrorAsError="true"
|
||||
Condition="'$(OS)' == 'Windows_NT' And Exists('$(PackagesConfig)')" />
|
||||
</Target>
|
||||
|
||||
<Target Name="BuildPackage" DependsOnTargets="CheckPrerequisites">
|
||||
<Exec Command="$(BuildCommand)"
|
||||
Condition=" '$(OS)' != 'Windows_NT' " />
|
||||
|
||||
<Exec Command="$(BuildCommand)"
|
||||
LogStandardErrorAsError="true"
|
||||
Condition=" '$(OS)' == 'Windows_NT' " />
|
||||
</Target>
|
||||
|
||||
<UsingTask TaskName="DownloadNuGet" TaskFactory="CodeTaskFactory" AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.v4.0.dll">
|
||||
<ParameterGroup>
|
||||
<OutputFilename ParameterType="System.String" Required="true" />
|
||||
</ParameterGroup>
|
||||
<Task>
|
||||
<Reference Include="System.Core" />
|
||||
<Using Namespace="System" />
|
||||
<Using Namespace="System.IO" />
|
||||
<Using Namespace="System.Net" />
|
||||
<Using Namespace="Microsoft.Build.Framework" />
|
||||
<Using Namespace="Microsoft.Build.Utilities" />
|
||||
<Code Type="Fragment" Language="cs">
|
||||
<![CDATA[
|
||||
try {
|
||||
OutputFilename = Path.GetFullPath(OutputFilename);
|
||||
|
||||
Log.LogMessage("Downloading latest version of NuGet.exe...");
|
||||
WebClient webClient = new WebClient();
|
||||
webClient.DownloadFile("https://nuget.org/nuget.exe", OutputFilename);
|
||||
|
||||
return true;
|
||||
}
|
||||
catch (Exception ex) {
|
||||
Log.LogErrorFromException(ex);
|
||||
return false;
|
||||
}
|
||||
]]>
|
||||
</Code>
|
||||
</Task>
|
||||
</UsingTask>
|
||||
|
||||
<UsingTask TaskName="SetEnvironmentVariable" TaskFactory="CodeTaskFactory" AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.v4.0.dll">
|
||||
<ParameterGroup>
|
||||
<EnvKey ParameterType="System.String" Required="true" />
|
||||
<EnvValue ParameterType="System.String" Required="true" />
|
||||
</ParameterGroup>
|
||||
<Task>
|
||||
<Using Namespace="System" />
|
||||
<Code Type="Fragment" Language="cs">
|
||||
<![CDATA[
|
||||
try {
|
||||
Environment.SetEnvironmentVariable(EnvKey, EnvValue, System.EnvironmentVariableTarget.Process);
|
||||
}
|
||||
catch {
|
||||
}
|
||||
]]>
|
||||
</Code>
|
||||
</Task>
|
||||
</UsingTask>
|
||||
</Project>
|
||||
@@ -1,4 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="Microsoft.AspNet.SignalR.Utils" version="2.1.0" />
|
||||
</packages>
|
||||
@@ -1,96 +0,0 @@
|
||||
using System;
|
||||
using System.Drawing;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using Disco.BI.Extensions;
|
||||
using iTextSharp.text.pdf;
|
||||
|
||||
namespace Disco.BI.AttachmentBI
|
||||
{
|
||||
public static class Utilities
|
||||
{
|
||||
|
||||
public static bool GenerateThumbnail(Stream Source, string SourceMimeType, Stream OutStream)
|
||||
{
|
||||
if (Source != null)
|
||||
{
|
||||
// GDI+ (jpg, png, gif, bmp)
|
||||
if (SourceMimeType.Equals("image/jpeg", StringComparison.OrdinalIgnoreCase) || SourceMimeType.Contains("jpg") ||
|
||||
SourceMimeType.Equals("image/png", StringComparison.OrdinalIgnoreCase) || SourceMimeType.Contains("png") ||
|
||||
SourceMimeType.Equals("image/gif", StringComparison.OrdinalIgnoreCase) || SourceMimeType.Contains("gif") ||
|
||||
SourceMimeType.Equals("image/bmp", StringComparison.OrdinalIgnoreCase) || SourceMimeType.Contains("bmp"))
|
||||
{
|
||||
try
|
||||
{
|
||||
using (Image sourceImage = Image.FromStream(Source))
|
||||
{
|
||||
using (Image thumbImage = sourceImage.ResizeImage(48, 48))
|
||||
{
|
||||
using (Image mimeTypeIcon = Disco.Properties.Resources.MimeType_img16)
|
||||
thumbImage.EmbedIconOverlay(mimeTypeIcon);
|
||||
thumbImage.SaveJpg(90, OutStream);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
// Ignore Thumbnail Generation exceptions for images
|
||||
//throw;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// PDF
|
||||
if (SourceMimeType.Equals("application/pdf", StringComparison.OrdinalIgnoreCase) || SourceMimeType.Contains("pdf"))
|
||||
{
|
||||
PdfReader pdfReader = new PdfReader(Source);
|
||||
try
|
||||
{
|
||||
using (DisposableImageCollection pdfPageImages = pdfReader.PdfPageImages(1))
|
||||
{
|
||||
if (pdfPageImages.Count() > 0)
|
||||
{
|
||||
// Find Biggest Image on Page
|
||||
Image biggestImage = pdfPageImages.OrderByDescending(i => i.Height * i.Width).First();
|
||||
using (Image thumbImage = biggestImage.ResizeImage(48, 48, Brushes.White))
|
||||
{
|
||||
using (Image mimeTypeIcon = Disco.Properties.Resources.MimeType_pdf16)
|
||||
thumbImage.EmbedIconOverlay(mimeTypeIcon);
|
||||
thumbImage.SaveJpg(90, OutStream);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (pdfReader != null)
|
||||
pdfReader.Close();
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
public static bool GenerateThumbnail(string SourceFilename, string SourceMimeType, string DestinationFilename)
|
||||
{
|
||||
using (FileStream sourceStream = new FileStream(SourceFilename, FileMode.Open, FileAccess.Read))
|
||||
{
|
||||
return GenerateThumbnail(sourceStream, SourceMimeType, DestinationFilename);
|
||||
}
|
||||
}
|
||||
public static bool GenerateThumbnail(Stream Source, string SourceMimeType, string DestinationFilename)
|
||||
{
|
||||
bool result;
|
||||
using (FileStream destinationStream = new FileStream(DestinationFilename, FileMode.Create, FileAccess.Write, FileShare.None))
|
||||
{
|
||||
result = GenerateThumbnail(Source, SourceMimeType, destinationStream);
|
||||
}
|
||||
if (!result && File.Exists(DestinationFilename))
|
||||
File.Delete(DestinationFilename);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,61 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Data.Entity;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Disco.Data.Repository;
|
||||
using Disco.Models.Repository;
|
||||
|
||||
namespace Disco.BI
|
||||
{
|
||||
public static class DeviceModelBI
|
||||
{
|
||||
|
||||
// Added: 2013-02-07 G#
|
||||
// Ensure Duplicate Device Models are not created by creating only one Device Model at a time
|
||||
// http://www.discoict.com.au/forum/support/2013/2/duplicate-device-models.aspx
|
||||
// Thanks to Michael Vorster for reporting this problem.
|
||||
private static object _CreateDeviceModelLock = new object();
|
||||
public static Tuple<DeviceModel, bool> GetOrCreateDeviceModel(this DbSet<DeviceModel> DeviceModelsSet, string Manufacturer, string Model, string ModelType)
|
||||
{
|
||||
// Already Exists?
|
||||
var deviceModel = DeviceModelsSet.FirstOrDefault(dm => dm.Manufacturer == Manufacturer && dm.Model == Model);
|
||||
if (deviceModel == null)
|
||||
{
|
||||
// Ensure only one thread/request at a time
|
||||
lock (_CreateDeviceModelLock)
|
||||
{
|
||||
// Check again now that lock is enforced
|
||||
deviceModel = DeviceModelsSet.FirstOrDefault(dm => dm.Manufacturer == Manufacturer && dm.Model == Model);
|
||||
|
||||
if (deviceModel == null)
|
||||
{
|
||||
// Create the Device Model in a different DataContext so we don't have to commit unrelated changes
|
||||
using (DiscoDataContext database = new DiscoDataContext())
|
||||
{
|
||||
var addDeviceModel = new DeviceModel
|
||||
{
|
||||
Manufacturer = Manufacturer,
|
||||
Model = Model,
|
||||
ModelType = ModelType,
|
||||
Description = string.Format("{0} {1}", Manufacturer, Model)
|
||||
};
|
||||
database.DeviceModels.Add(addDeviceModel);
|
||||
database.SaveChanges();
|
||||
}
|
||||
|
||||
// Obtain the Device Model with the in-scope DataContext
|
||||
// - Overhead acknowledged, but reasonable given the infrequency of occurrence
|
||||
deviceModel = DeviceModelsSet.FirstOrDefault(dm => dm.Manufacturer == Manufacturer && dm.Model == Model);
|
||||
return new Tuple<DeviceModel, bool>(deviceModel, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return new Tuple<DeviceModel,bool>(deviceModel, false);
|
||||
}
|
||||
// Added: 2013-02-07 G#
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,668 +0,0 @@
|
||||
using Disco.BI.Extensions;
|
||||
using Disco.Data.Repository;
|
||||
using Disco.Models.ClientServices;
|
||||
using Disco.Models.Repository;
|
||||
using Disco.Services.Authorization;
|
||||
using Disco.Services.Interop.ActiveDirectory;
|
||||
using Disco.Services.Users;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.DirectoryServices.ActiveDirectory;
|
||||
using System.Linq;
|
||||
using System.Text.RegularExpressions;
|
||||
using Tamir.SharpSsh;
|
||||
|
||||
namespace Disco.BI.DeviceBI
|
||||
{
|
||||
public class DeviceEnrol
|
||||
{
|
||||
public enum EnrolmentTypes
|
||||
{
|
||||
Normal,
|
||||
Mac = 5,
|
||||
MacSecure
|
||||
}
|
||||
|
||||
private static Regex SshPromptRegEx = new Regex("[\\$,\\#]", RegexOptions.Multiline);
|
||||
public static MacSecureEnrolResponse MacSecureEnrol(DiscoDataContext Database, string Host)
|
||||
{
|
||||
MacEnrol trustedRequest = new MacEnrol();
|
||||
string sessionId = System.Guid.NewGuid().ToString("B");
|
||||
MacSecureEnrolResponse MacSecureEnrol;
|
||||
try
|
||||
{
|
||||
EnrolmentLog.LogSessionStarting(sessionId, Host, EnrolmentTypes.MacSecure);
|
||||
EnrolmentLog.LogSessionProgress(sessionId, 0, string.Format("Connecting to '{0}' as '{1}'", Host, Database.DiscoConfiguration.Bootstrapper.MacSshUsername));
|
||||
SshShell shell = new SshShell(Host, Database.DiscoConfiguration.Bootstrapper.MacSshUsername, Database.DiscoConfiguration.Bootstrapper.MacSshPassword);
|
||||
try
|
||||
{
|
||||
shell.ExpectPattern = "#";
|
||||
shell.Connect();
|
||||
EnrolmentLog.LogSessionProgress(sessionId, 10, "Connected, Authenticating");
|
||||
var output = shell.Expect(SshPromptRegEx);
|
||||
bool sessionElevated = false;
|
||||
EnrolmentLog.LogSessionDiagnosticInformation(sessionId, output);
|
||||
if (!output.TrimEnd(new char[0]).EndsWith("#"))
|
||||
{
|
||||
EnrolmentLog.LogSessionProgress(sessionId, 22, "Connected, Elevating Credentials");
|
||||
shell.WriteLine("sudo -k");
|
||||
System.Threading.Thread.Sleep(250);
|
||||
output = shell.Expect(SshPromptRegEx);
|
||||
EnrolmentLog.LogSessionProgress(sessionId, 25, "Connected, Elevating Credentials");
|
||||
EnrolmentLog.LogSessionDiagnosticInformation(sessionId, output);
|
||||
shell.WriteLine("sudo -s -S");
|
||||
System.Threading.Thread.Sleep(250);
|
||||
output = shell.Expect(":");
|
||||
EnrolmentLog.LogSessionProgress(sessionId, 27, "Connected, Elevating Credentials");
|
||||
EnrolmentLog.LogSessionDiagnosticInformation(sessionId, output);
|
||||
shell.WriteLine(Database.DiscoConfiguration.Bootstrapper.MacSshPassword);
|
||||
System.Threading.Thread.Sleep(250);
|
||||
output = shell.Expect(SshPromptRegEx);
|
||||
sessionElevated = true;
|
||||
EnrolmentLog.LogSessionDiagnosticInformation(sessionId, output);
|
||||
}
|
||||
EnrolmentLog.LogSessionProgress(sessionId, 20, "Retrieving Serial Number");
|
||||
trustedRequest.DeviceSerialNumber = ParseMacShellCommand(shell, "system_profiler SPHardwareDataType | grep \"Serial Number\" | cut -d \":\" -f 2-", sessionId);
|
||||
EnrolmentLog.LogSessionDevice(sessionId, trustedRequest.DeviceSerialNumber, null);
|
||||
EnrolmentLog.LogSessionProgress(sessionId, 30, "Retrieving Hardware UUID");
|
||||
trustedRequest.DeviceUUID = ParseMacShellCommand(shell, "system_profiler SPHardwareDataType | grep \"Hardware UUID:\" | cut -d \":\" -f 2-", sessionId);
|
||||
EnrolmentLog.LogSessionProgress(sessionId, 40, "Retrieving Computer Name");
|
||||
trustedRequest.DeviceComputerName = ParseMacShellCommand(shell, "scutil --get ComputerName", sessionId);
|
||||
EnrolmentLog.LogSessionProgress(sessionId, 50, "Retrieving Ethernet MAC Address");
|
||||
string lanNicId = ParseMacShellCommand(shell, "system_profiler SPEthernetDataType | egrep -o \"en0|en1|en2|en3|en4|en5|en6\"", sessionId);
|
||||
if (!string.IsNullOrWhiteSpace(lanNicId))
|
||||
{
|
||||
trustedRequest.DeviceLanMacAddress = ParseMacShellCommand(shell, string.Format("ifconfig {0} | grep ether | cut -d \" \" -f 2-", lanNicId), sessionId);
|
||||
}
|
||||
EnrolmentLog.LogSessionProgress(sessionId, 65, "Retrieving Wireless MAC Address");
|
||||
string wlanNicId = ParseMacShellCommand(shell, "system_profiler SPAirPortDataType | egrep -o \"en0|en1|en2|en3|en4|en5|en6\"", sessionId);
|
||||
if (!string.IsNullOrWhiteSpace(wlanNicId))
|
||||
{
|
||||
trustedRequest.DeviceWlanMacAddress = ParseMacShellCommand(shell, string.Format("ifconfig {0} | grep ether | cut -d \" \" -f 2-", wlanNicId), sessionId);
|
||||
}
|
||||
trustedRequest.DeviceManufacturer = "Apple Inc.";
|
||||
EnrolmentLog.LogSessionProgress(sessionId, 80, "Retrieving Model");
|
||||
trustedRequest.DeviceModel = ParseMacShellCommand(shell, "system_profiler SPHardwareDataType | grep \"Model Identifier:\" | cut -d \":\" -f 2-", sessionId);
|
||||
EnrolmentLog.LogSessionProgress(sessionId, 90, "Retrieving Model Type");
|
||||
trustedRequest.DeviceModelType = ParseMacModelType(ParseMacShellCommand(shell, "system_profiler SPHardwareDataType | grep \"Model Name:\" | cut -d \":\" -f 2-", sessionId));
|
||||
EnrolmentLog.LogSessionProgress(sessionId, 99, "Disconnecting");
|
||||
output = ParseMacModelType(ParseMacShellCommand(shell, "exit", sessionId));
|
||||
if (sessionElevated)
|
||||
{
|
||||
output = ParseMacModelType(ParseMacShellCommand(shell, "exit", sessionId));
|
||||
}
|
||||
if (shell.Connected)
|
||||
{
|
||||
shell.Close();
|
||||
}
|
||||
EnrolmentLog.LogSessionProgress(sessionId, 100, "Disconnected, Starting Disco Enrolment");
|
||||
MacSecureEnrolResponse response = MacSecureEnrolResponse.FromMacEnrolResponse(MacEnrol(Database, trustedRequest, true, sessionId));
|
||||
EnrolmentLog.LogSessionFinished(sessionId);
|
||||
MacSecureEnrol = response;
|
||||
}
|
||||
catch (System.Exception ex)
|
||||
{
|
||||
throw ex;
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (shell != null)
|
||||
{
|
||||
bool connected = shell.Connected;
|
||||
if (connected)
|
||||
{
|
||||
shell.Close();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (System.Exception ex)
|
||||
{
|
||||
EnrolmentLog.LogSessionError(sessionId, ex);
|
||||
throw ex;
|
||||
}
|
||||
return MacSecureEnrol;
|
||||
}
|
||||
|
||||
#region "Mac Enrol Helpers"
|
||||
|
||||
private static string ParseMacModelType(string ModelName)
|
||||
{
|
||||
string ParseMacModelType;
|
||||
if (!string.IsNullOrWhiteSpace(ModelName))
|
||||
{
|
||||
string mn = ModelName.ToLower();
|
||||
if (mn.Contains("imac") || mn.Contains("mini"))
|
||||
{
|
||||
ParseMacModelType = "Desktop";
|
||||
return ParseMacModelType;
|
||||
}
|
||||
if (mn.Contains("macbook"))
|
||||
{
|
||||
ParseMacModelType = "Mobile";
|
||||
return ParseMacModelType;
|
||||
}
|
||||
if (mn.Contains("xserve"))
|
||||
{
|
||||
ParseMacModelType = "Server";
|
||||
return ParseMacModelType;
|
||||
}
|
||||
}
|
||||
ParseMacModelType = "Unknown";
|
||||
return ParseMacModelType;
|
||||
}
|
||||
|
||||
private static string ParseMacShellCommand(SshShell Shell, string Command, string LogSessionId)
|
||||
{
|
||||
Shell.WriteLine(Command);
|
||||
System.Threading.Thread.Sleep(250);
|
||||
string Response = Shell.Expect(SshPromptRegEx);
|
||||
Response = Response.Replace("\r", string.Empty);
|
||||
EnrolmentLog.LogSessionDiagnosticInformation(LogSessionId, Response);
|
||||
bool flag = Response.Contains("\n");
|
||||
string ParseMacShellCommand;
|
||||
if (flag)
|
||||
{
|
||||
string[] ResponseLines = Response.Split(new char[]
|
||||
{
|
||||
'\n'
|
||||
});
|
||||
switch (ResponseLines.Length)
|
||||
{
|
||||
case 0:
|
||||
case 1:
|
||||
{
|
||||
ParseMacShellCommand = string.Empty;
|
||||
break;
|
||||
}
|
||||
case 2:
|
||||
case 3:
|
||||
{
|
||||
ParseMacShellCommand = ResponseLines[1].Trim();
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
System.Text.StringBuilder ResponseBuilder = new System.Text.StringBuilder();
|
||||
int num = ResponseLines.Length - 2;
|
||||
int lineIndex = 1;
|
||||
while (true)
|
||||
{
|
||||
int arg_111_0 = lineIndex;
|
||||
int num2 = num;
|
||||
if (arg_111_0 > num2)
|
||||
{
|
||||
break;
|
||||
}
|
||||
ResponseBuilder.AppendLine(ResponseLines[lineIndex]);
|
||||
lineIndex++;
|
||||
}
|
||||
ParseMacShellCommand = ResponseBuilder.ToString().Trim();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ParseMacShellCommand = Response;
|
||||
}
|
||||
return ParseMacShellCommand;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
public static MacEnrolResponse MacEnrol(DiscoDataContext Database, MacEnrol Request, bool Trusted, string OpenSessionId = null)
|
||||
{
|
||||
string sessionId;
|
||||
if (OpenSessionId == null)
|
||||
{
|
||||
sessionId = System.Guid.NewGuid().ToString("B");
|
||||
EnrolmentLog.LogSessionStarting(sessionId, Request.DeviceSerialNumber, EnrolmentTypes.Mac);
|
||||
}
|
||||
else
|
||||
{
|
||||
sessionId = OpenSessionId;
|
||||
}
|
||||
EnrolmentLog.LogSessionDeviceInfo(sessionId, Request);
|
||||
MacEnrolResponse response = new MacEnrolResponse();
|
||||
try
|
||||
{
|
||||
EnrolmentLog.LogSessionProgress(sessionId, 10, "Querying Database");
|
||||
Device RepoDevice = Database.Devices.Include("AssignedUser").Include("DeviceProfile").Include("DeviceProfile").Where(d => d.SerialNumber == Request.DeviceSerialNumber).FirstOrDefault();
|
||||
if (!Trusted)
|
||||
{
|
||||
if (RepoDevice == null)
|
||||
throw new EnrolSafeException(string.Format("Unknown Device Serial Number (SN: '{0}')", Request.DeviceSerialNumber));
|
||||
if (!RepoDevice.AllowUnauthenticatedEnrol)
|
||||
throw new EnrolSafeException(string.Format("Device isn't allowed an Unauthenticated Enrolment (SN: '{0}')", Request.DeviceSerialNumber));
|
||||
}
|
||||
if (RepoDevice == null)
|
||||
{
|
||||
EnrolmentLog.LogSessionProgress(sessionId, 50, "New Device, Building Disco Instance");
|
||||
EnrolmentLog.LogSessionTaskAddedDevice(sessionId, Request.DeviceSerialNumber);
|
||||
DeviceProfile deviceProfile = Database.DeviceProfiles.Find(Database.DiscoConfiguration.DeviceProfiles.DefaultDeviceProfileId);
|
||||
|
||||
var deviceModelResult = Database.DeviceModels.GetOrCreateDeviceModel(Request.DeviceManufacturer.Trim(), Request.DeviceModel.Trim(), Request.DeviceModelType.Trim());
|
||||
DeviceModel deviceModel = deviceModelResult.Item1;
|
||||
if (deviceModelResult.Item2)
|
||||
EnrolmentLog.LogSessionTaskCreatedDeviceModel(sessionId, Request.DeviceSerialNumber, deviceModelResult.Item1.Manufacturer, deviceModelResult.Item1.Model);
|
||||
else
|
||||
EnrolmentLog.LogSessionDevice(sessionId, Request.DeviceSerialNumber, deviceModel.Id);
|
||||
|
||||
RepoDevice = new Device
|
||||
{
|
||||
SerialNumber = Request.DeviceSerialNumber,
|
||||
DeviceDomainId = Request.DeviceComputerName,
|
||||
DeviceProfile = deviceProfile,
|
||||
DeviceModel = deviceModel,
|
||||
AllowUnauthenticatedEnrol = false,
|
||||
CreatedDate = DateTime.Now,
|
||||
EnrolledDate = DateTime.Now
|
||||
};
|
||||
Database.Devices.Add(RepoDevice);
|
||||
}
|
||||
else
|
||||
{
|
||||
EnrolmentLog.LogSessionProgress(sessionId, 50, "Existing Device, Updating Disco Instance");
|
||||
EnrolmentLog.LogSessionTaskUpdatingDevice(sessionId, Request.DeviceSerialNumber);
|
||||
if (!RepoDevice.DeviceModelId.HasValue || RepoDevice.DeviceModelId.Value == 1)
|
||||
{
|
||||
var deviceModelResult = Database.DeviceModels.GetOrCreateDeviceModel(Request.DeviceManufacturer.Trim(), Request.DeviceModel.Trim(), Request.DeviceModelType.Trim());
|
||||
DeviceModel deviceModel = deviceModelResult.Item1;
|
||||
if (deviceModelResult.Item2)
|
||||
EnrolmentLog.LogSessionTaskCreatedDeviceModel(sessionId, Request.DeviceSerialNumber, deviceModelResult.Item1.Manufacturer, deviceModelResult.Item1.Model);
|
||||
else
|
||||
EnrolmentLog.LogSessionDevice(sessionId, Request.DeviceSerialNumber, deviceModel.Id);
|
||||
|
||||
RepoDevice.DeviceModel = deviceModel;
|
||||
}
|
||||
else
|
||||
{
|
||||
EnrolmentLog.LogSessionDevice(sessionId, Request.DeviceSerialNumber, RepoDevice.DeviceModelId);
|
||||
}
|
||||
RepoDevice.DeviceDomainId = Request.DeviceComputerName;
|
||||
if (!RepoDevice.EnrolledDate.HasValue)
|
||||
{
|
||||
RepoDevice.EnrolledDate = DateTime.Now;
|
||||
}
|
||||
}
|
||||
RepoDevice.LastEnrolDate = DateTime.Now;
|
||||
RepoDevice.AllowUnauthenticatedEnrol = false;
|
||||
// Removed 2012-06-14 G# - Properties moved to DeviceProfile model & DB Migrated in DBv3.
|
||||
//DeviceProfileConfiguration RepoDeviceProfileContext = RepoDevice.DeviceProfile.Configuration(Context);
|
||||
EnrolmentLog.LogSessionProgress(sessionId, 90, "Building Response");
|
||||
//if (RepoDeviceProfileContext.DistributionType == DeviceProfileConfiguration.DeviceProfileDistributionTypes.OneToOne && RepoDevice.AssignedUser != null)
|
||||
if (RepoDevice.DeviceProfile.DistributionType == DeviceProfile.DistributionTypes.OneToOne && RepoDevice.AssignedUser != null)
|
||||
{
|
||||
ADUserAccount AssignedUserInfo = ActiveDirectory.RetrieveADUserAccount(RepoDevice.AssignedUser.UserId);
|
||||
EnrolmentLog.LogSessionTaskAssigningUser(sessionId, RepoDevice.SerialNumber, AssignedUserInfo.DisplayName, AssignedUserInfo.SamAccountName, AssignedUserInfo.Domain.NetBiosName, AssignedUserInfo.SecurityIdentifier.ToString());
|
||||
response.DeviceAssignedUserUsername = AssignedUserInfo.SamAccountName;
|
||||
response.DeviceAssignedUserDomain = AssignedUserInfo.Domain.NetBiosName;
|
||||
response.DeviceAssignedUserName = AssignedUserInfo.DisplayName;
|
||||
response.DeviceAssignedUserSID = AssignedUserInfo.SecurityIdentifier.ToString();
|
||||
}
|
||||
response.DeviceComputerName = RepoDevice.DeviceDomainId;
|
||||
EnrolmentLog.LogSessionProgress(sessionId, 100, "Completed Successfully");
|
||||
}
|
||||
catch (EnrolSafeException ex)
|
||||
{
|
||||
EnrolmentLog.LogSessionError(sessionId, ex);
|
||||
return new MacEnrolResponse { ErrorMessage = ex.Message };
|
||||
}
|
||||
catch (System.Exception ex2)
|
||||
{
|
||||
EnrolmentLog.LogSessionError(sessionId, ex2);
|
||||
throw ex2;
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (OpenSessionId == null)
|
||||
EnrolmentLog.LogSessionFinished(sessionId);
|
||||
}
|
||||
return response;
|
||||
}
|
||||
public static EnrolResponse Enrol(DiscoDataContext Database, string Username, Models.ClientServices.Enrol Request)
|
||||
{
|
||||
ADMachineAccount adMachineAccount = null;
|
||||
|
||||
EnrolResponse response = new EnrolResponse();
|
||||
|
||||
AuthorizationToken authenticatedToken = null;
|
||||
bool isAuthenticated = false;
|
||||
|
||||
ADDomain domain = null;
|
||||
Lazy<ADDomainController> domainController = new Lazy<ADDomainController>(() =>
|
||||
{
|
||||
if (domain == null)
|
||||
throw new InvalidOperationException("The [domain] variable must be initialized first");
|
||||
return domain.GetAvailableDomainController(RequireWritable: true);
|
||||
});
|
||||
|
||||
string sessionId = System.Guid.NewGuid().ToString("B");
|
||||
response.SessionId = sessionId;
|
||||
|
||||
EnrolmentLog.LogSessionStarting(sessionId, Request.DeviceSerialNumber, EnrolmentTypes.Normal);
|
||||
EnrolmentLog.LogSessionDeviceInfo(sessionId, Request);
|
||||
|
||||
try
|
||||
{
|
||||
EnrolmentLog.LogSessionProgress(sessionId, 10, "Loading User Data");
|
||||
if (!string.IsNullOrWhiteSpace(Username))
|
||||
{
|
||||
authenticatedToken = UserService.GetAuthorization(Username, Database);
|
||||
isAuthenticated = (authenticatedToken != null);
|
||||
}
|
||||
EnrolmentLog.LogSessionProgress(sessionId, 13, "Loading Device Data");
|
||||
|
||||
Device RepoDevice = Database.Devices.Include("AssignedUser").Include("DeviceModel").Include("DeviceProfile").Where(d => d.SerialNumber == Request.DeviceSerialNumber).FirstOrDefault();
|
||||
EnrolmentLog.LogSessionProgress(sessionId, 15, "Discovering User/Device Disco Permissions");
|
||||
if (isAuthenticated)
|
||||
{
|
||||
if (!authenticatedToken.Has(Claims.Device.Actions.EnrolDevices))
|
||||
{
|
||||
if (!authenticatedToken.Has(Claims.ComputerAccount))
|
||||
throw new EnrolSafeException(string.Format("Connection not correctly authenticated (SN: {0}; Auth User: {1})", Request.DeviceSerialNumber, authenticatedToken.User.UserId));
|
||||
|
||||
if (domain == null)
|
||||
domain = ActiveDirectory.Context.GetDomainByName(Request.DeviceDNSDomainName);
|
||||
|
||||
if (!authenticatedToken.User.UserId.Equals(string.Format(@"{0}\{1}$", domain.NetBiosName, Request.DeviceComputerName), System.StringComparison.OrdinalIgnoreCase))
|
||||
throw new EnrolSafeException(string.Format("Connection not correctly authenticated (SN: {0}; Auth User: {1})", Request.DeviceSerialNumber, authenticatedToken.User.UserId));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (RepoDevice == null)
|
||||
{
|
||||
throw new EnrolSafeException(string.Format("Unknown Device Serial Number (SN: '{0}')", Request.DeviceSerialNumber));
|
||||
}
|
||||
if (!RepoDevice.AllowUnauthenticatedEnrol)
|
||||
{
|
||||
if (RepoDevice.DeviceProfile.AllowUntrustedReimageJobEnrolment)
|
||||
{
|
||||
if (Database.Jobs.Count(j => j.DeviceSerialNumber == RepoDevice.SerialNumber && j.JobTypeId == JobType.JobTypeIds.SImg && !j.ClosedDate.HasValue) == 0)
|
||||
{
|
||||
throw new EnrolSafeException(string.Format("Device has no open 'Software - Reimage' job (SN: '{0}')", Request.DeviceSerialNumber));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new EnrolSafeException(string.Format("Device isn't allowed an Unauthenticated Enrolment (SN: '{0}')", Request.DeviceSerialNumber));
|
||||
}
|
||||
}
|
||||
}
|
||||
if (Request.DeviceIsPartOfDomain && !string.IsNullOrWhiteSpace(Request.DeviceComputerName))
|
||||
{
|
||||
EnrolmentLog.LogSessionProgress(sessionId, 20, "Loading Active Directory Computer Account");
|
||||
System.Guid? uuidGuid = null;
|
||||
System.Guid? macAddressGuid = null;
|
||||
if (!string.IsNullOrEmpty(Request.DeviceUUID))
|
||||
uuidGuid = ADMachineAccount.NetbootGUIDFromUUID(Request.DeviceUUID);
|
||||
if (!string.IsNullOrEmpty(Request.DeviceLanMacAddress))
|
||||
macAddressGuid = ADMachineAccount.NetbootGUIDFromMACAddress(Request.DeviceLanMacAddress);
|
||||
|
||||
if (domain == null)
|
||||
domain = ActiveDirectory.Context.GetDomainByName(Request.DeviceDNSDomainName);
|
||||
|
||||
var requestDeviceId = string.Format(@"{0}\{1}", domain.NetBiosName, Request.DeviceComputerName);
|
||||
|
||||
adMachineAccount = domainController.Value.RetrieveADMachineAccount(requestDeviceId, uuidGuid, macAddressGuid);
|
||||
}
|
||||
if (RepoDevice == null)
|
||||
{
|
||||
EnrolmentLog.LogSessionProgress(sessionId, 30, "New Device, Creating Disco Instance");
|
||||
EnrolmentLog.LogSessionTaskAddedDevice(sessionId, Request.DeviceSerialNumber);
|
||||
DeviceProfile deviceProfile = Database.DeviceProfiles.Find(Database.DiscoConfiguration.DeviceProfiles.DefaultDeviceProfileId);
|
||||
|
||||
|
||||
var deviceModelResult = Database.DeviceModels.GetOrCreateDeviceModel(Request.DeviceManufacturer.Trim(), Request.DeviceModel.Trim(), Request.DeviceModelType.Trim());
|
||||
DeviceModel deviceModel = deviceModelResult.Item1;
|
||||
if (deviceModelResult.Item2)
|
||||
EnrolmentLog.LogSessionTaskCreatedDeviceModel(sessionId, Request.DeviceSerialNumber, deviceModelResult.Item1.Manufacturer, deviceModelResult.Item1.Model);
|
||||
else
|
||||
EnrolmentLog.LogSessionDevice(sessionId, Request.DeviceSerialNumber, deviceModel.Id);
|
||||
|
||||
if (domain == null)
|
||||
domain = ActiveDirectory.Context.GetDomainByName(Request.DeviceDNSDomainName);
|
||||
|
||||
RepoDevice = new Device
|
||||
{
|
||||
SerialNumber = Request.DeviceSerialNumber,
|
||||
DeviceDomainId = string.Format(@"{0}\{1}", domain.NetBiosName, Request.DeviceComputerName),
|
||||
DeviceProfile = deviceProfile,
|
||||
DeviceModel = deviceModel,
|
||||
AllowUnauthenticatedEnrol = false,
|
||||
CreatedDate = DateTime.Now,
|
||||
EnrolledDate = DateTime.Now,
|
||||
LastEnrolDate = DateTime.Now,
|
||||
DeviceDetails = new List<DeviceDetail>()
|
||||
};
|
||||
Database.Devices.Add(RepoDevice);
|
||||
|
||||
if (!string.IsNullOrEmpty(Request.DeviceLanMacAddress))
|
||||
RepoDevice.DeviceDetails.LanMacAddress(RepoDevice, Request.DeviceLanMacAddress);
|
||||
if (!string.IsNullOrEmpty(Request.DeviceWlanMacAddress))
|
||||
RepoDevice.DeviceDetails.WLanMacAddress(RepoDevice, Request.DeviceWlanMacAddress);
|
||||
}
|
||||
else
|
||||
{
|
||||
EnrolmentLog.LogSessionProgress(sessionId, 30, "Existing Device, Updating Disco Instance");
|
||||
EnrolmentLog.LogSessionTaskUpdatingDevice(sessionId, Request.DeviceSerialNumber);
|
||||
|
||||
var deviceModelResult = Database.DeviceModels.GetOrCreateDeviceModel(Request.DeviceManufacturer.Trim(), Request.DeviceModel.Trim(), Request.DeviceModelType.Trim());
|
||||
DeviceModel deviceModel = deviceModelResult.Item1;
|
||||
if (deviceModelResult.Item2)
|
||||
EnrolmentLog.LogSessionTaskCreatedDeviceModel(sessionId, Request.DeviceSerialNumber, deviceModelResult.Item1.Manufacturer, deviceModelResult.Item1.Model);
|
||||
else
|
||||
EnrolmentLog.LogSessionDevice(sessionId, Request.DeviceSerialNumber, deviceModel.Id);
|
||||
|
||||
RepoDevice.DeviceModel = deviceModel;
|
||||
|
||||
if (!string.IsNullOrEmpty(Request.DeviceLanMacAddress))
|
||||
RepoDevice.DeviceDetails.LanMacAddress(RepoDevice, Request.DeviceLanMacAddress);
|
||||
if (!string.IsNullOrEmpty(Request.DeviceWlanMacAddress))
|
||||
RepoDevice.DeviceDetails.WLanMacAddress(RepoDevice, Request.DeviceWlanMacAddress);
|
||||
|
||||
if (!RepoDevice.EnrolledDate.HasValue)
|
||||
RepoDevice.EnrolledDate = DateTime.Now;
|
||||
RepoDevice.LastEnrolDate = DateTime.Now;
|
||||
}
|
||||
|
||||
if (adMachineAccount == null)
|
||||
{
|
||||
if (isAuthenticated || RepoDevice.AllowUnauthenticatedEnrol)
|
||||
{
|
||||
if (RepoDevice.DeviceProfile.ProvisionADAccount)
|
||||
{
|
||||
EnrolmentLog.LogSessionProgress(sessionId, 50, "Provisioning an Active Directory Computer Account");
|
||||
|
||||
if (string.IsNullOrWhiteSpace(RepoDevice.DeviceProfile.OrganisationalUnit))
|
||||
throw new InvalidOperationException("No Organisational Unit has been set in the device profile");
|
||||
if (domain == null)
|
||||
domain = ActiveDirectory.Context.GetDomainFromDistinguishedName(RepoDevice.DeviceProfile.OrganisationalUnit);
|
||||
|
||||
if (string.IsNullOrEmpty(RepoDevice.DeviceDomainId) || RepoDevice.DeviceProfile.EnforceComputerNameConvention)
|
||||
RepoDevice.DeviceDomainId = RepoDevice.ComputerNameRender(Database, domain);
|
||||
|
||||
string offlineProvisionDiagnosicInfo;
|
||||
EnrolmentLog.LogSessionTaskProvisioningADAccount(sessionId, RepoDevice.SerialNumber, RepoDevice.DeviceDomainId);
|
||||
adMachineAccount = domainController.Value.RetrieveADMachineAccount(RepoDevice.DeviceDomainId);
|
||||
|
||||
response.OfflineDomainJoin = domainController.Value.OfflineDomainJoinProvision(RepoDevice.DeviceDomainId, RepoDevice.DeviceProfile.OrganisationalUnit, ref adMachineAccount, out offlineProvisionDiagnosicInfo);
|
||||
|
||||
EnrolmentLog.LogSessionDiagnosticInformation(sessionId, offlineProvisionDiagnosicInfo);
|
||||
|
||||
response.RequireReboot = true;
|
||||
}
|
||||
if (adMachineAccount != null)
|
||||
{
|
||||
response.DeviceComputerName = adMachineAccount.Name;
|
||||
response.DeviceDomainName = adMachineAccount.Domain.NetBiosName;
|
||||
}
|
||||
else
|
||||
{
|
||||
string accountUsername;
|
||||
ADDomain accountDomain;
|
||||
ActiveDirectory.ParseDomainAccountId(RepoDevice.DeviceDomainId, out accountUsername, out accountDomain);
|
||||
|
||||
response.DeviceDomainName = accountDomain == null ? null : accountDomain.NetBiosName;
|
||||
response.DeviceComputerName = accountUsername;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
response.DeviceComputerName = Request.DeviceComputerName;
|
||||
response.DeviceDomainName = Request.DeviceDNSDomainName;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
RepoDevice.DeviceDomainId = adMachineAccount.Id.Trim('$');
|
||||
response.DeviceComputerName = adMachineAccount.Name;
|
||||
response.DeviceDomainName = adMachineAccount.Domain.NetBiosName;
|
||||
|
||||
// Enforce Computer Name Convention
|
||||
if (!adMachineAccount.IsCriticalSystemObject && RepoDevice.DeviceProfile.EnforceComputerNameConvention)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(RepoDevice.DeviceProfile.OrganisationalUnit))
|
||||
throw new InvalidOperationException("No Organisational Unit has been set in the device profile");
|
||||
if (domain == null)
|
||||
domain = ActiveDirectory.Context.GetDomainFromDistinguishedName(RepoDevice.DeviceProfile.OrganisationalUnit);
|
||||
|
||||
var calculatedComputerName = RepoDevice.ComputerNameRender(Database, domain);
|
||||
string calculatedAccountUsername;
|
||||
ActiveDirectory.ParseDomainAccountId(calculatedComputerName, out calculatedAccountUsername);
|
||||
|
||||
if (!Request.DeviceComputerName.Equals(calculatedAccountUsername, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
EnrolmentLog.LogSessionProgress(sessionId, 50, string.Format("Renaming Device: {0} -> {1}", Request.DeviceComputerName, calculatedComputerName));
|
||||
EnrolmentLog.LogSessionTaskRenamingDevice(sessionId, Request.DeviceComputerName, calculatedComputerName);
|
||||
|
||||
RepoDevice.DeviceDomainId = calculatedComputerName;
|
||||
response.DeviceDomainName = domain.NetBiosName;
|
||||
response.DeviceComputerName = calculatedAccountUsername;
|
||||
|
||||
// Create New Account
|
||||
string offlineProvisionDiagnosicInfo;
|
||||
|
||||
response.OfflineDomainJoin = domainController.Value.OfflineDomainJoinProvision(RepoDevice.DeviceDomainId, RepoDevice.DeviceProfile.OrganisationalUnit, ref adMachineAccount, out offlineProvisionDiagnosicInfo);
|
||||
|
||||
EnrolmentLog.LogSessionDiagnosticInformation(sessionId, offlineProvisionDiagnosicInfo);
|
||||
|
||||
response.RequireReboot = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Enforce Organisational Unit
|
||||
if (!adMachineAccount.IsCriticalSystemObject && response.OfflineDomainJoin == null && RepoDevice.DeviceProfile.EnforceOrganisationalUnit)
|
||||
{
|
||||
var parentDistinguishedName = adMachineAccount.ParentDistinguishedName;
|
||||
if (string.IsNullOrWhiteSpace(RepoDevice.DeviceProfile.OrganisationalUnit))
|
||||
throw new InvalidOperationException(string.Format("The Organisational Unit for the Device Profile '{0}' [{1}] is not set.", RepoDevice.DeviceProfile.Name, RepoDevice.DeviceProfile.Id));
|
||||
|
||||
if (!parentDistinguishedName.Equals(RepoDevice.DeviceProfile.OrganisationalUnit, StringComparison.OrdinalIgnoreCase)) // Custom OU
|
||||
{
|
||||
var proposedDomain = ActiveDirectory.Context.GetDomainFromDistinguishedName(RepoDevice.DeviceProfile.OrganisationalUnit);
|
||||
var currentDomain = ActiveDirectory.Context.GetDomainFromDistinguishedName(parentDistinguishedName);
|
||||
if (currentDomain != proposedDomain)
|
||||
throw new NotSupportedException("Unable to move the devices organisational unit when the source and destination domains are different.");
|
||||
if (domain == null)
|
||||
domain = proposedDomain;
|
||||
else if (domain != proposedDomain)
|
||||
throw new NotSupportedException("To many domains involved in this enrolment, contact support regarding your scenario.");
|
||||
|
||||
EnrolmentLog.LogSessionProgress(sessionId, 65, string.Format("Moving Device Organisational Unit: {0} -> {1}", parentDistinguishedName, RepoDevice.DeviceProfile.OrganisationalUnit));
|
||||
EnrolmentLog.LogSessionTaskMovingDeviceOrganisationUnit(sessionId, parentDistinguishedName, RepoDevice.DeviceProfile.OrganisationalUnit);
|
||||
adMachineAccount.MoveOrganisationalUnit(domainController.Value, RepoDevice.DeviceProfile.OrganisationalUnit);
|
||||
response.RequireReboot = true;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
if (adMachineAccount != null && !adMachineAccount.IsCriticalSystemObject)
|
||||
{
|
||||
EnrolmentLog.LogSessionProgress(sessionId, 75, "Updating Active Directory Computer Account Properties");
|
||||
adMachineAccount.UpdateNetbootGUID(Request.DeviceUUID, Request.DeviceLanMacAddress);
|
||||
if (RepoDevice.AssignedUser != null)
|
||||
adMachineAccount.SetDescription(RepoDevice);
|
||||
}
|
||||
if (RepoDevice.DeviceProfile.DistributionType == DeviceProfile.DistributionTypes.OneToOne)
|
||||
{
|
||||
if (RepoDevice.AssignedUser == null)
|
||||
{
|
||||
response.AllowBootstrapperUninstall = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
EnrolmentLog.LogSessionProgress(sessionId, 80, "Retrieving Active Directory Assigned User Account");
|
||||
ADUserAccount AssignedUserInfo = ActiveDirectory.RetrieveADUserAccount(RepoDevice.AssignedUser.UserId);
|
||||
EnrolmentLog.LogSessionTaskAssigningUser(sessionId, RepoDevice.SerialNumber, AssignedUserInfo.DisplayName, AssignedUserInfo.SamAccountName, AssignedUserInfo.Domain.NetBiosName, AssignedUserInfo.SecurityIdentifier.ToString());
|
||||
response.AllowBootstrapperUninstall = true;
|
||||
response.DeviceAssignedUserIsLocalAdmin = RepoDevice.DeviceProfile.AssignedUserLocalAdmin;
|
||||
response.DeviceAssignedUserUsername = AssignedUserInfo.SamAccountName;
|
||||
response.DeviceAssignedUserDomain = AssignedUserInfo.Domain.NetBiosName;
|
||||
response.DeviceAssignedUserName = AssignedUserInfo.DisplayName;
|
||||
response.DeviceAssignedUserSID = AssignedUserInfo.SecurityIdentifier.ToString();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
response.AllowBootstrapperUninstall = true;
|
||||
}
|
||||
if (!string.IsNullOrEmpty(Request.DeviceWlanMacAddress) && !string.IsNullOrEmpty(RepoDevice.DeviceProfile.CertificateProviderId))
|
||||
{
|
||||
EnrolmentLog.LogSessionProgress(sessionId, 90, "Provisioning a Wireless Certificate");
|
||||
|
||||
var allocationResult = RepoDevice.AllocateCertificate(Database);
|
||||
var deviceCertificate = allocationResult.Item1;
|
||||
if (deviceCertificate != null)
|
||||
{
|
||||
bool certAlreadyInstalled = false;
|
||||
if (Request.DeviceCertificates != null && Request.DeviceCertificates.Count > 0)
|
||||
{
|
||||
foreach (string existingCertName in Request.DeviceCertificates)
|
||||
{
|
||||
if (existingCertName.Contains(deviceCertificate.Name))
|
||||
{
|
||||
certAlreadyInstalled = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!certAlreadyInstalled)
|
||||
{
|
||||
EnrolmentLog.LogSessionTaskProvisioningWirelessCertificate(sessionId, RepoDevice.SerialNumber, deviceCertificate.Name);
|
||||
response.DeviceCertificate = System.Convert.ToBase64String(deviceCertificate.Content);
|
||||
}
|
||||
}
|
||||
response.DeviceCertificateRemoveExisting = allocationResult.Item2;
|
||||
}
|
||||
|
||||
// Reset 'AllowUnauthenticatedEnrol'
|
||||
if (RepoDevice.AllowUnauthenticatedEnrol)
|
||||
RepoDevice.AllowUnauthenticatedEnrol = false;
|
||||
|
||||
EnrolmentLog.LogSessionProgress(sessionId, 100, "Completed Successfully");
|
||||
}
|
||||
catch (EnrolSafeException ex)
|
||||
{
|
||||
EnrolmentLog.LogSessionError(sessionId, ex);
|
||||
return new EnrolResponse
|
||||
{
|
||||
SessionId = sessionId,
|
||||
ErrorMessage = ex.Message
|
||||
};
|
||||
}
|
||||
catch (System.Exception ex2)
|
||||
{
|
||||
EnrolmentLog.LogSessionError(sessionId, ex2);
|
||||
throw ex2;
|
||||
}
|
||||
finally
|
||||
{
|
||||
EnrolmentLog.LogSessionFinished(sessionId);
|
||||
}
|
||||
return response;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Threading;
|
||||
namespace Disco.BI
|
||||
{
|
||||
public class EnrolSafeException : System.Exception
|
||||
{
|
||||
public EnrolSafeException(string Message) : base(Message)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,482 +0,0 @@
|
||||
using Disco.Services.Logging;
|
||||
using Disco.Services.Logging.Models;
|
||||
using Disco.Models.ClientServices;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
namespace Disco.BI.DeviceBI
|
||||
{
|
||||
public class EnrolmentLog : LogBase
|
||||
{
|
||||
public enum EventTypeIds
|
||||
{
|
||||
SessionStarting = 10,
|
||||
SessionProgress,
|
||||
SessionDevice,
|
||||
SessionDeviceInfo,
|
||||
SessionFinished = 20,
|
||||
SessionDiagnosticInformation,
|
||||
SessionWarning,
|
||||
SessionError,
|
||||
SessionErrorWithInner,
|
||||
SessionClientError,
|
||||
SessionTaskAddedDevice = 50,
|
||||
SessionTaskUpdatingDevice,
|
||||
SessionTaskCreatedDeviceModel = 56,
|
||||
SessionTaskProvisioningADAccount = 58,
|
||||
SessionTaskAssigningUser = 60,
|
||||
SessionTaskProvisioningWirelessCertificate = 62,
|
||||
SessionTaskRenamingDevice = 64,
|
||||
SessionTaskMovingDeviceOrganisationUnit = 66,
|
||||
ClientError = 400
|
||||
}
|
||||
private const int _ModuleId = 50;
|
||||
public static EnrolmentLog Current
|
||||
{
|
||||
get
|
||||
{
|
||||
return (EnrolmentLog)LogContext.LogModules[50];
|
||||
}
|
||||
}
|
||||
public override string ModuleDescription
|
||||
{
|
||||
get
|
||||
{
|
||||
return "Device Enrolment";
|
||||
}
|
||||
}
|
||||
public override int ModuleId
|
||||
{
|
||||
get
|
||||
{
|
||||
return 50;
|
||||
}
|
||||
}
|
||||
public override string ModuleName
|
||||
{
|
||||
get
|
||||
{
|
||||
return "DeviceEnrolment";
|
||||
}
|
||||
}
|
||||
[System.Diagnostics.DebuggerNonUserCode]
|
||||
public EnrolmentLog()
|
||||
{
|
||||
}
|
||||
private static void Log(EnrolmentLog.EventTypeIds EventTypeId, params object[] Args)
|
||||
{
|
||||
EnrolmentLog.Current.Log((int)EventTypeId, Args);
|
||||
}
|
||||
public static void LogSessionStarting(string SessionId, string HostId, DeviceEnrol.EnrolmentTypes EnrolmentType)
|
||||
{
|
||||
EnrolmentLog.Log(EnrolmentLog.EventTypeIds.SessionStarting, new object[]
|
||||
{
|
||||
SessionId,
|
||||
HostId,
|
||||
System.Enum.GetName(EnrolmentType.GetType(), EnrolmentType)
|
||||
});
|
||||
}
|
||||
public static void LogSessionDevice(string SessionId, string DeviceSerialNumber, int? DeviceModelId)
|
||||
{
|
||||
EnrolmentLog.Log(EnrolmentLog.EventTypeIds.SessionDevice, new object[]
|
||||
{
|
||||
SessionId,
|
||||
DeviceSerialNumber,
|
||||
DeviceModelId
|
||||
});
|
||||
}
|
||||
public static void LogSessionDeviceInfo(string SessionId, string SerialNumber, string UUID, string ComputerName, string LanMacAddress, string WlanMacAddress, string Manufacturer, string Model, string ModelType)
|
||||
{
|
||||
EnrolmentLog.Log(EnrolmentLog.EventTypeIds.SessionDeviceInfo, new object[]
|
||||
{
|
||||
SessionId,
|
||||
SerialNumber,
|
||||
UUID,
|
||||
ComputerName,
|
||||
LanMacAddress,
|
||||
WlanMacAddress,
|
||||
Manufacturer,
|
||||
Model,
|
||||
ModelType
|
||||
});
|
||||
}
|
||||
public static void LogSessionDeviceInfo(string SessionId, MacEnrol Request)
|
||||
{
|
||||
EnrolmentLog.LogSessionDeviceInfo(SessionId, Request.DeviceSerialNumber, Request.DeviceUUID, Request.DeviceComputerName, Request.DeviceLanMacAddress, Request.DeviceWlanMacAddress, Request.DeviceManufacturer, Request.DeviceModel, Request.DeviceModelType);
|
||||
}
|
||||
public static void LogSessionDeviceInfo(string SessionId, Models.ClientServices.Enrol Request)
|
||||
{
|
||||
EnrolmentLog.LogSessionDeviceInfo(SessionId, Request.DeviceSerialNumber, Request.DeviceUUID, Request.DeviceComputerName, Request.DeviceLanMacAddress, Request.DeviceWlanMacAddress, Request.DeviceManufacturer, Request.DeviceModel, Request.DeviceModelType);
|
||||
}
|
||||
public static void LogSessionProgress(string SessionId, int Progress, string Status)
|
||||
{
|
||||
EnrolmentLog.Log(EnrolmentLog.EventTypeIds.SessionProgress, new object[]
|
||||
{
|
||||
SessionId,
|
||||
Progress,
|
||||
Status
|
||||
});
|
||||
}
|
||||
public static void LogSessionFinished(string SessionId)
|
||||
{
|
||||
EnrolmentLog.Log(EnrolmentLog.EventTypeIds.SessionFinished, new object[]
|
||||
{
|
||||
SessionId
|
||||
});
|
||||
}
|
||||
public static void LogSessionDiagnosticInformation(string SessionId, string Message)
|
||||
{
|
||||
EnrolmentLog.Log(EnrolmentLog.EventTypeIds.SessionDiagnosticInformation, new object[]
|
||||
{
|
||||
SessionId,
|
||||
Message
|
||||
});
|
||||
}
|
||||
public static void LogSessionWarning(string SessionId, string Message)
|
||||
{
|
||||
EnrolmentLog.Log(EnrolmentLog.EventTypeIds.SessionWarning, new object[]
|
||||
{
|
||||
SessionId,
|
||||
Message
|
||||
});
|
||||
}
|
||||
public static void LogSessionError(string SessionId, System.Exception Ex)
|
||||
{
|
||||
if (Ex.InnerException == null)
|
||||
{
|
||||
EnrolmentLog.Log(EnrolmentLog.EventTypeIds.SessionError, new object[]
|
||||
{
|
||||
SessionId,
|
||||
Ex.GetType().Name,
|
||||
Ex.Message,
|
||||
Ex.StackTrace
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
EnrolmentLog.Log(EnrolmentLog.EventTypeIds.SessionErrorWithInner, new object[]
|
||||
{
|
||||
SessionId,
|
||||
Ex.GetType().Name,
|
||||
Ex.Message,
|
||||
Ex.InnerException.GetType().Name,
|
||||
Ex.InnerException.Message,
|
||||
Ex.StackTrace,
|
||||
Ex.InnerException.StackTrace
|
||||
});
|
||||
}
|
||||
}
|
||||
public static void LogSessionClientError(string SessionId, string ClientIP, string ClientIdentifier, string ClientVersion, string Error, string RawError)
|
||||
{
|
||||
EnrolmentLog.Log(EnrolmentLog.EventTypeIds.SessionClientError, new object[]
|
||||
{
|
||||
SessionId,
|
||||
ClientIP,
|
||||
ClientIdentifier,
|
||||
ClientVersion,
|
||||
Error,
|
||||
RawError
|
||||
});
|
||||
}
|
||||
public static void LogSessionTaskAddedDevice(string SessionId, string DeviceSerialNumber)
|
||||
{
|
||||
EnrolmentLog.Log(EnrolmentLog.EventTypeIds.SessionTaskAddedDevice, new object[]
|
||||
{
|
||||
SessionId,
|
||||
DeviceSerialNumber
|
||||
});
|
||||
}
|
||||
public static void LogSessionTaskUpdatingDevice(string SessionId, string DeviceSerialNumber)
|
||||
{
|
||||
EnrolmentLog.Log(EnrolmentLog.EventTypeIds.SessionTaskUpdatingDevice, new object[]
|
||||
{
|
||||
SessionId,
|
||||
DeviceSerialNumber
|
||||
});
|
||||
}
|
||||
public static void LogSessionTaskCreatedDeviceModel(string SessionId, string DeviceSerialNumber, string Manufacturer, string Model)
|
||||
{
|
||||
EnrolmentLog.Log(EnrolmentLog.EventTypeIds.SessionTaskCreatedDeviceModel, new object[]
|
||||
{
|
||||
SessionId,
|
||||
DeviceSerialNumber,
|
||||
Manufacturer,
|
||||
Model
|
||||
});
|
||||
}
|
||||
public static void LogSessionTaskProvisioningADAccount(string SessionId, string DeviceSerialNumber, string ADAccountName)
|
||||
{
|
||||
EnrolmentLog.Log(EnrolmentLog.EventTypeIds.SessionTaskProvisioningADAccount, new object[]
|
||||
{
|
||||
SessionId,
|
||||
DeviceSerialNumber,
|
||||
ADAccountName
|
||||
});
|
||||
}
|
||||
public static void LogSessionTaskAssigningUser(string SessionId, string DeviceSerialNumber, string UserDisplayName, string UserUsername, string UserDomain, string UserSID)
|
||||
{
|
||||
EnrolmentLog.Log(EnrolmentLog.EventTypeIds.SessionTaskAssigningUser, new object[]
|
||||
{
|
||||
SessionId,
|
||||
DeviceSerialNumber,
|
||||
UserDisplayName,
|
||||
UserUsername,
|
||||
UserDomain,
|
||||
UserSID
|
||||
});
|
||||
}
|
||||
public static void LogSessionTaskProvisioningWirelessCertificate(string SessionId, string DeviceSerialNumber, string CertificateName)
|
||||
{
|
||||
EnrolmentLog.Log(EnrolmentLog.EventTypeIds.SessionTaskProvisioningWirelessCertificate, new object[]
|
||||
{
|
||||
SessionId,
|
||||
DeviceSerialNumber,
|
||||
CertificateName
|
||||
});
|
||||
}
|
||||
public static void LogSessionTaskRenamingDevice(string SessionId, string OldComputerName, string NewComputerName)
|
||||
{
|
||||
EnrolmentLog.Log(EnrolmentLog.EventTypeIds.SessionTaskRenamingDevice, new object[]
|
||||
{
|
||||
SessionId,
|
||||
OldComputerName,
|
||||
NewComputerName
|
||||
});
|
||||
}
|
||||
public static void LogSessionTaskMovingDeviceOrganisationUnit(string SessionId, string OldOrganisationUnit, string NewOrganisationUnit)
|
||||
{
|
||||
EnrolmentLog.Log(EnrolmentLog.EventTypeIds.SessionTaskMovingDeviceOrganisationUnit, new object[]
|
||||
{
|
||||
SessionId,
|
||||
OldOrganisationUnit,
|
||||
NewOrganisationUnit
|
||||
});
|
||||
}
|
||||
public static void LogClientError(string ClientIP, string ClientIdentifier, string ClientVersion, string Error, string RawError)
|
||||
{
|
||||
EnrolmentLog.Log(EnrolmentLog.EventTypeIds.ClientError, new object[]
|
||||
{
|
||||
ClientIP,
|
||||
ClientIdentifier,
|
||||
ClientVersion,
|
||||
Error,
|
||||
RawError
|
||||
});
|
||||
}
|
||||
protected override System.Collections.Generic.List<LogEventType> LoadEventTypes()
|
||||
{
|
||||
return new System.Collections.Generic.List<LogEventType>
|
||||
{
|
||||
new LogEventType
|
||||
{
|
||||
Id = 10,
|
||||
ModuleId = 50,
|
||||
Name = "Session Starting",
|
||||
Format = "Starting '{2}' Enrolment for {1} (Session# {0})",
|
||||
Severity = 0,
|
||||
UseLive = true,
|
||||
UsePersist = true,
|
||||
UseDisplay = true
|
||||
},
|
||||
new LogEventType
|
||||
{
|
||||
Id = 12,
|
||||
ModuleId = 50,
|
||||
Name = "Session Device",
|
||||
Format = null,
|
||||
Severity = 0,
|
||||
UseLive = true,
|
||||
UsePersist = true,
|
||||
UseDisplay = false
|
||||
},
|
||||
new LogEventType
|
||||
{
|
||||
Id = 11,
|
||||
ModuleId = 50,
|
||||
Name = "Session Progress",
|
||||
Format = "Processing Session# {0}; {1}% Complete; Status: {2}",
|
||||
Severity = 0,
|
||||
UseLive = true,
|
||||
UsePersist = false,
|
||||
UseDisplay = false
|
||||
},
|
||||
new LogEventType
|
||||
{
|
||||
Id = 13,
|
||||
ModuleId = 50,
|
||||
Name = "Session Device Info",
|
||||
Format = null,
|
||||
Severity = 0,
|
||||
UseLive = true,
|
||||
UsePersist = true,
|
||||
UseDisplay = true
|
||||
},
|
||||
new LogEventType
|
||||
{
|
||||
Id = 20,
|
||||
ModuleId = 50,
|
||||
Name = "Session Finished",
|
||||
Format = "Finished Session# {0}",
|
||||
Severity = 0,
|
||||
UseLive = true,
|
||||
UsePersist = true,
|
||||
UseDisplay = true
|
||||
},
|
||||
new LogEventType
|
||||
{
|
||||
Id = 21,
|
||||
ModuleId = 50,
|
||||
Name = "Session Diagnostic Information",
|
||||
Format = null,
|
||||
Severity = 0,
|
||||
UseLive = true,
|
||||
UsePersist = false,
|
||||
UseDisplay = false
|
||||
},
|
||||
new LogEventType
|
||||
{
|
||||
Id = 22,
|
||||
ModuleId = 50,
|
||||
Name = "Session Warning",
|
||||
Format = null,
|
||||
Severity = 1,
|
||||
UseLive = true,
|
||||
UsePersist = true,
|
||||
UseDisplay = true
|
||||
},
|
||||
new LogEventType
|
||||
{
|
||||
Id = 23,
|
||||
ModuleId = 50,
|
||||
Name = "Session Error",
|
||||
Format = "An Error Occurred: [{1}] {2}",
|
||||
Severity = 2,
|
||||
UseLive = true,
|
||||
UsePersist = true,
|
||||
UseDisplay = true
|
||||
},
|
||||
new LogEventType
|
||||
{
|
||||
Id = 24,
|
||||
ModuleId = 50,
|
||||
Name = "Session Error with Internal",
|
||||
Format = "An Error Occurred: [{1}] {2}; Internal Error: [{3}] {4}",
|
||||
Severity = 2,
|
||||
UseLive = true,
|
||||
UsePersist = true,
|
||||
UseDisplay = true
|
||||
},
|
||||
new LogEventType
|
||||
{
|
||||
Id = (int)EventTypeIds.SessionClientError,
|
||||
ModuleId = _ModuleId,
|
||||
Name = "Client Error",
|
||||
Format = "IP: {1}; Device ID: {2}; Version: {3} Error: {4}; Session# {0}",
|
||||
Severity = (int)LogEventType.Severities.Error,
|
||||
UseLive = true,
|
||||
UsePersist = true,
|
||||
UseDisplay = true
|
||||
},
|
||||
new LogEventType
|
||||
{
|
||||
Id = 50,
|
||||
ModuleId = 50,
|
||||
Name = "Task - Added Device",
|
||||
Format = "Creating Disco Device {1}",
|
||||
Severity = 0,
|
||||
UseLive = true,
|
||||
UsePersist = true,
|
||||
UseDisplay = true
|
||||
},
|
||||
new LogEventType
|
||||
{
|
||||
Id = 51,
|
||||
ModuleId = 50,
|
||||
Name = "Task - Updating Device",
|
||||
Format = "Updating Disco Device {1}",
|
||||
Severity = 0,
|
||||
UseLive = true,
|
||||
UsePersist = true,
|
||||
UseDisplay = true
|
||||
},
|
||||
new LogEventType
|
||||
{
|
||||
Id = 56,
|
||||
ModuleId = 50,
|
||||
Name = "Task - Creating Device Model",
|
||||
Format = "Creating Device Model '{2} {3}' for Device {1}",
|
||||
Severity = 0,
|
||||
UseLive = true,
|
||||
UsePersist = true,
|
||||
UseDisplay = true
|
||||
},
|
||||
new LogEventType
|
||||
{
|
||||
Id = 58,
|
||||
ModuleId = 50,
|
||||
Name = "Task - Provisioning Active Directory Account",
|
||||
Format = "Provisioning Active Directory Account '{2}' for Device {1}",
|
||||
Severity = 0,
|
||||
UseLive = true,
|
||||
UsePersist = true,
|
||||
UseDisplay = true
|
||||
},
|
||||
new LogEventType
|
||||
{
|
||||
Id = 60,
|
||||
ModuleId = 50,
|
||||
Name = "Task - Assigning User",
|
||||
Format = "Assigning User '{2}' ({4}\\{3} {{{5}}}) for Device {1}",
|
||||
Severity = 0,
|
||||
UseLive = true,
|
||||
UsePersist = true,
|
||||
UseDisplay = true
|
||||
},
|
||||
new LogEventType
|
||||
{
|
||||
Id = 62,
|
||||
ModuleId = 50,
|
||||
Name = "Task - Provisioning Wireless Certificate",
|
||||
Format = "Provisioning Wireless Certificate '{2}' for Device {1}",
|
||||
Severity = 0,
|
||||
UseLive = true,
|
||||
UsePersist = true,
|
||||
UseDisplay = true
|
||||
},
|
||||
new LogEventType
|
||||
{
|
||||
Id = 64,
|
||||
ModuleId = 50,
|
||||
Name = "Task - Renaming Device",
|
||||
Format = "Renaming Device '{1}' to '{2}'",
|
||||
Severity = 0,
|
||||
UseLive = true,
|
||||
UsePersist = true,
|
||||
UseDisplay = true
|
||||
},
|
||||
new LogEventType
|
||||
{
|
||||
Id = 66,
|
||||
ModuleId = 50,
|
||||
Name = "Task - Moving Device Organisation Unit",
|
||||
Format = "Moving Device Organisation Unit '{1}' to '{2}'",
|
||||
Severity = 0,
|
||||
UseLive = true,
|
||||
UsePersist = true,
|
||||
UseDisplay = true
|
||||
},
|
||||
new LogEventType
|
||||
{
|
||||
Id = (int)EventTypeIds.ClientError,
|
||||
ModuleId = _ModuleId,
|
||||
Name = "Client Error",
|
||||
Format = "IP: {0}; Device ID: {1}; Version: {2} Error: {3}",
|
||||
Severity = (int)LogEventType.Severities.Error,
|
||||
UseLive = true,
|
||||
UsePersist = true,
|
||||
UseDisplay = true
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Drawing;
|
||||
|
||||
namespace Disco.BI
|
||||
{
|
||||
public class DisposableImageCollection : List<Bitmap>, IDisposable
|
||||
{
|
||||
public void Dispose()
|
||||
{
|
||||
foreach (Image i in this)
|
||||
{
|
||||
if (i != null)
|
||||
i.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,78 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Collections.Concurrent;
|
||||
using Disco.Models.Repository;
|
||||
using Disco.Data.Repository;
|
||||
using Disco.BI.Extensions;
|
||||
using System.Web;
|
||||
using System.Drawing;
|
||||
using iTextSharp.text.pdf;
|
||||
|
||||
namespace Disco.BI.DocumentTemplateBI
|
||||
{
|
||||
class DocumentTemplateQRCodeLocationCache
|
||||
{
|
||||
private static ConcurrentDictionary<string, List<RectangleF>> _Cache = new ConcurrentDictionary<string, List<RectangleF>>();
|
||||
|
||||
public static List<RectangleF> GetLocations(DocumentTemplate dt, DiscoDataContext Database)
|
||||
{
|
||||
// Check Cache
|
||||
List<RectangleF> locations;
|
||||
if (_Cache.TryGetValue(dt.Id, out locations))
|
||||
{
|
||||
return locations;
|
||||
}
|
||||
// Generate Cache
|
||||
return GenerateLocations(dt, Database);
|
||||
}
|
||||
|
||||
public static bool InvalidateLocations(DocumentTemplate dt)
|
||||
{
|
||||
List<RectangleF> locations;
|
||||
return _Cache.TryRemove(dt.Id, out locations);
|
||||
}
|
||||
|
||||
private static bool SetValue(string DocumentTemplateId, List<RectangleF> Locations)
|
||||
{
|
||||
if (_Cache.ContainsKey(DocumentTemplateId))
|
||||
{
|
||||
List<RectangleF> oldLocations;
|
||||
if (_Cache.TryGetValue(DocumentTemplateId, out oldLocations))
|
||||
{
|
||||
return _Cache.TryUpdate(DocumentTemplateId, Locations, oldLocations);
|
||||
}
|
||||
}
|
||||
return _Cache.TryAdd(DocumentTemplateId, Locations);
|
||||
}
|
||||
|
||||
internal static List<RectangleF> GenerateLocations(DocumentTemplate dt, DiscoDataContext Database)
|
||||
{
|
||||
string templateFilename = dt.RepositoryFilename(Database);
|
||||
PdfReader pdfReader = new PdfReader(templateFilename);
|
||||
List<RectangleF> locations = new List<RectangleF>();
|
||||
|
||||
if (pdfReader.AcroFields.Fields.ContainsKey("DiscoAttachmentId"))
|
||||
{
|
||||
foreach (var pdfFieldPosition in pdfReader.AcroFields.GetFieldPositions("DiscoAttachmentId"))
|
||||
{
|
||||
var pdfPageSize = pdfReader.GetPageSize(pdfFieldPosition.page);
|
||||
// Original Position
|
||||
locations.Add(new RectangleF(
|
||||
(float)System.Math.Min(1.0, System.Math.Max(0.0, (double)(pdfFieldPosition.position.Left / pdfPageSize.Width) - 0.05)),
|
||||
(float)System.Math.Min(1.0, System.Math.Max(0.0, (double)((pdfPageSize.Height - pdfFieldPosition.position.Top) / pdfPageSize.Height) - 0.05)),
|
||||
(float)System.Math.Min(1.0, System.Math.Max(0.0, (double)(pdfFieldPosition.position.Width / pdfPageSize.Width) + 0.1)),
|
||||
(float)System.Math.Min(1.0, System.Math.Max(0.0, (double)(pdfFieldPosition.position.Height / pdfPageSize.Height) + 0.1))
|
||||
));
|
||||
}
|
||||
}
|
||||
pdfReader.Close();
|
||||
|
||||
// Update Cache
|
||||
SetValue(dt.Id, locations);
|
||||
return locations;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,204 +0,0 @@
|
||||
using Disco.Data.Repository;
|
||||
using Disco.Models.Repository;
|
||||
using Disco.Services.Interop.ActiveDirectory;
|
||||
using System;
|
||||
namespace Disco.BI.DocumentTemplateBI
|
||||
{
|
||||
public class DocumentUniqueIdentifier
|
||||
{
|
||||
private bool? _loadedComponentsOk;
|
||||
private DocumentTemplate _documentTemplate;
|
||||
private object _data;
|
||||
private string _dataDescription;
|
||||
public string TemplateTypeId { get; private set; }
|
||||
public string DataId { get; private set; }
|
||||
public string DocumentUniqueId
|
||||
{
|
||||
get
|
||||
{
|
||||
return string.Format("{0}|{1}", this.TemplateTypeId, this.DataId);
|
||||
}
|
||||
}
|
||||
public string CreatorId { get; private set; }
|
||||
public System.DateTime TimeStamp { get; private set; }
|
||||
public int Page { get; private set; }
|
||||
public string Tag { get; private set; }
|
||||
public DocumentTemplate DocumentTemplate
|
||||
{
|
||||
get
|
||||
{
|
||||
bool flag = this._loadedComponentsOk.HasValue && this._loadedComponentsOk.Value;
|
||||
if (flag)
|
||||
{
|
||||
return this._documentTemplate;
|
||||
}
|
||||
throw new System.Exception("Document Unique Identifier Components not loaded or invalid");
|
||||
}
|
||||
}
|
||||
public object Data
|
||||
{
|
||||
get
|
||||
{
|
||||
bool flag = this._loadedComponentsOk.HasValue && this._loadedComponentsOk.Value;
|
||||
if (flag)
|
||||
{
|
||||
return this._data;
|
||||
}
|
||||
throw new System.Exception("Document Unique Identifier Components not loaded or invalid");
|
||||
}
|
||||
}
|
||||
public string DataDescription
|
||||
{
|
||||
get
|
||||
{
|
||||
bool flag = this._loadedComponentsOk.HasValue && this._loadedComponentsOk.Value;
|
||||
if (flag)
|
||||
{
|
||||
return this._dataDescription;
|
||||
}
|
||||
throw new System.Exception("Document Unique Identifier Components not loaded or invalid");
|
||||
}
|
||||
}
|
||||
public string DataScope { get; private set; }
|
||||
public static bool IsDocumentUniqueIdentifier(string UniqueIdentifier)
|
||||
{
|
||||
return UniqueIdentifier.StartsWith("Disco|", System.StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
public DocumentUniqueIdentifier(string TemplateTypeId, string DataId, string CreatorId, DateTime TimeStamp, int? Page = null, string Tag = null)
|
||||
{
|
||||
this.Tag = Tag;
|
||||
this.TemplateTypeId = TemplateTypeId;
|
||||
this.DataId = DataId;
|
||||
this.CreatorId = ActiveDirectory.ParseDomainAccountId(CreatorId);
|
||||
this.TimeStamp = TimeStamp;
|
||||
this.Page = Page ?? 0;
|
||||
}
|
||||
public DocumentUniqueIdentifier(string UniqueIdentifier, string Tag)
|
||||
{
|
||||
if (!DocumentUniqueIdentifier.IsDocumentUniqueIdentifier(UniqueIdentifier))
|
||||
{
|
||||
throw new System.ArgumentException("Invalid Document Unique Identifier", "UniqueIdentifier");
|
||||
}
|
||||
this.Tag = Tag;
|
||||
string[] s = UniqueIdentifier.Split(new char[] { '|' });
|
||||
string left = s[1].ToUpper();
|
||||
if (left == "AT" || left == "1")
|
||||
{
|
||||
if (s.Length >= 3)
|
||||
{
|
||||
this.TemplateTypeId = s[2];
|
||||
}
|
||||
if (s.Length >= 4)
|
||||
{
|
||||
this.DataId = s[3];
|
||||
}
|
||||
if (s.Length >= 5)
|
||||
{
|
||||
this.CreatorId = ActiveDirectory.ParseDomainAccountId(s[4]);
|
||||
}
|
||||
if (s.Length >= 6)
|
||||
{
|
||||
System.DateTime timeStamp;
|
||||
if (System.DateTime.TryParse(s[5], out timeStamp))
|
||||
{
|
||||
this.TimeStamp = timeStamp;
|
||||
}
|
||||
}
|
||||
if (s.Length >= 7)
|
||||
{
|
||||
int page = 0;
|
||||
if (int.TryParse(s[6], out page))
|
||||
{
|
||||
this.Page = page;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
throw new System.ArgumentException(string.Format("Invalid Document Unique Identifier Version ({0})", s[1]), "UniqueIdentifier");
|
||||
}
|
||||
public bool LoadComponents(DiscoDataContext Database)
|
||||
{
|
||||
bool LoadComponents;
|
||||
if (!this._loadedComponentsOk.HasValue)
|
||||
{
|
||||
string scopeType;
|
||||
if (this.TemplateTypeId.StartsWith("--"))
|
||||
{
|
||||
string templateTypeId = this.TemplateTypeId;
|
||||
switch (this.TemplateTypeId)
|
||||
{
|
||||
case "--DEVICE":
|
||||
scopeType = DocumentTemplate.DocumentTemplateScopes.Device;
|
||||
break;
|
||||
case "--JOB":
|
||||
scopeType = DocumentTemplate.DocumentTemplateScopes.Job;
|
||||
break;
|
||||
case "--USER":
|
||||
scopeType = DocumentTemplate.DocumentTemplateScopes.User;
|
||||
break;
|
||||
default:
|
||||
scopeType = null;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
this._documentTemplate = Database.DocumentTemplates.Find(this.TemplateTypeId);
|
||||
if (this._documentTemplate != null)
|
||||
{
|
||||
scopeType = this._documentTemplate.Scope;
|
||||
}
|
||||
else
|
||||
{
|
||||
scopeType = null;
|
||||
}
|
||||
}
|
||||
if (scopeType != null)
|
||||
{
|
||||
this.DataScope = scopeType;
|
||||
switch (scopeType)
|
||||
{
|
||||
case DocumentTemplate.DocumentTemplateScopes.Device:
|
||||
Device d = Database.Devices.Find(this.DataId);
|
||||
if (d != null)
|
||||
{
|
||||
this._data = d;
|
||||
this._dataDescription = d.SerialNumber;
|
||||
this._loadedComponentsOk = true;
|
||||
LoadComponents = true;
|
||||
return LoadComponents;
|
||||
}
|
||||
break;
|
||||
case DocumentTemplate.DocumentTemplateScopes.Job:
|
||||
Job i = Database.Jobs.Find(int.Parse(this.DataId));
|
||||
if (i != null)
|
||||
{
|
||||
this._data = i;
|
||||
this._dataDescription = i.Id.ToString();
|
||||
this._loadedComponentsOk = true;
|
||||
LoadComponents = true;
|
||||
return LoadComponents;
|
||||
}
|
||||
break;
|
||||
case DocumentTemplate.DocumentTemplateScopes.User:
|
||||
User u = Database.Users.Find(ActiveDirectory.ParseDomainAccountId(this.DataId));
|
||||
if (u != null)
|
||||
{
|
||||
this._data = u;
|
||||
this._dataDescription = u.DisplayName;
|
||||
this._loadedComponentsOk = true;
|
||||
LoadComponents = true;
|
||||
return LoadComponents;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
this._loadedComponentsOk = false;
|
||||
}
|
||||
LoadComponents = this._loadedComponentsOk.Value;
|
||||
return LoadComponents;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,85 +0,0 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Web.Caching;
|
||||
using Disco.Data.Repository;
|
||||
using Quartz;
|
||||
using Quartz.Impl;
|
||||
using Quartz.Impl.Triggers;
|
||||
|
||||
namespace Disco.BI.DocumentTemplateBI.Importer
|
||||
{
|
||||
public class DocumentDropBoxMonitor : System.IDisposable
|
||||
{
|
||||
private IScheduler _scheduler;
|
||||
private FileSystemWatcher _fsw;
|
||||
private Cache _httpCache;
|
||||
|
||||
public const string WatcherFilter = "*.pdf";
|
||||
public string DropBoxLocation { get; private set; }
|
||||
|
||||
public DocumentDropBoxMonitor(DiscoDataContext Database, ISchedulerFactory SchedulerFactory, Cache HttpCache)
|
||||
{
|
||||
if (Database == null)
|
||||
throw new System.ArgumentNullException("Context");
|
||||
|
||||
this._httpCache = HttpCache;
|
||||
|
||||
var location = DataStore.CreateLocation(Database, "DocumentDropBox");
|
||||
this.DropBoxLocation = location.EndsWith(@"\") ? location : string.Concat(location, @"\");
|
||||
|
||||
this._scheduler = SchedulerFactory.GetScheduler();
|
||||
this._scheduler.Start();
|
||||
}
|
||||
public void ScheduleCurrentFiles(int Delay)
|
||||
{
|
||||
foreach (var filename in System.IO.Directory.GetFiles(this.DropBoxLocation, "*.pdf"))
|
||||
{
|
||||
this.ScheduleFile(filename, Delay);
|
||||
}
|
||||
}
|
||||
public void StartWatching()
|
||||
{
|
||||
if (this._fsw == null)
|
||||
{
|
||||
this._fsw = new FileSystemWatcher(this.DropBoxLocation, "*.pdf");
|
||||
this._fsw.Created += new FileSystemEventHandler(this.FSW_Created);
|
||||
}
|
||||
this._fsw.EnableRaisingEvents = true;
|
||||
}
|
||||
public void StopWatching()
|
||||
{
|
||||
if (this._fsw != null)
|
||||
{
|
||||
this._fsw.EnableRaisingEvents = false;
|
||||
}
|
||||
}
|
||||
public void ScheduleFile(string Filename, int Delay)
|
||||
{
|
||||
System.Guid guid = System.Guid.NewGuid();
|
||||
JobDetailImpl jd = new JobDetailImpl(guid.ToString(), typeof(DocumentImporterJob));
|
||||
jd.JobDataMap.Add("Filename", Filename);
|
||||
jd.JobDataMap.Add("RetryCount", 0);
|
||||
jd.JobDataMap.Add("HttpCache", this._httpCache);
|
||||
guid = System.Guid.NewGuid();
|
||||
|
||||
System.DateTimeOffset startTimeUtc = new System.DateTimeOffset(DateTime.Now.AddSeconds((double)Delay));
|
||||
SimpleTriggerImpl trig = new SimpleTriggerImpl(guid.ToString(), startTimeUtc);
|
||||
|
||||
this._scheduler.ScheduleJob(jd, trig);
|
||||
}
|
||||
private void FSW_Created(object sender, FileSystemEventArgs e)
|
||||
{
|
||||
if ((e.ChangeType & WatcherChangeTypes.Deleted) != WatcherChangeTypes.Deleted)
|
||||
this.ScheduleFile(e.FullPath, 5);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
this.StopWatching();
|
||||
if (this._fsw != null)
|
||||
this._fsw.Dispose();
|
||||
if (this._scheduler != null)
|
||||
this._scheduler.Shutdown(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,120 +0,0 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Web.Caching;
|
||||
using Disco.Data.Repository;
|
||||
using Quartz;
|
||||
using Quartz.Impl.Triggers;
|
||||
|
||||
namespace Disco.BI.DocumentTemplateBI.Importer
|
||||
{
|
||||
[PersistJobDataAfterExecution]
|
||||
public class DocumentImporterJob : IJob
|
||||
{
|
||||
|
||||
void IJob.Execute(IJobExecutionContext context)
|
||||
{
|
||||
string sessionId = context.JobDetail.JobDataMap["SessionId"] as string;
|
||||
if (string.IsNullOrEmpty(sessionId))
|
||||
{
|
||||
sessionId = Guid.NewGuid().ToString();
|
||||
context.JobDetail.JobDataMap["SessionId"] = sessionId;
|
||||
}
|
||||
|
||||
string filename = context.JobDetail.JobDataMap["Filename"] as string;
|
||||
int retryCount = (int)context.JobDetail.JobDataMap["RetryCount"];
|
||||
Cache httpCache = context.JobDetail.JobDataMap["HttpCache"] as Cache;
|
||||
|
||||
var friendlyFilename = filename;
|
||||
if (!string.IsNullOrEmpty(friendlyFilename))
|
||||
friendlyFilename = System.IO.Path.GetFileName(friendlyFilename);
|
||||
|
||||
DocumentImporterLog.LogImportStarting(sessionId, friendlyFilename);
|
||||
|
||||
if (!File.Exists(filename))
|
||||
{
|
||||
DocumentImporterLog.LogImportWarning(sessionId, string.Format("File not found: {0}", filename));
|
||||
DocumentImporterLog.LogImportFinished(sessionId);
|
||||
context.Scheduler.DeleteJob(context.JobDetail.Key);
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
using (DiscoDataContext database = new DiscoDataContext())
|
||||
{
|
||||
if (retryCount < 18)
|
||||
{
|
||||
context.JobDetail.JobDataMap["RetryCount"] = (++retryCount);
|
||||
bool processResult = Interop.Pdf.PdfImporter.ProcessPdfAttachment(filename, database, sessionId, httpCache);
|
||||
|
||||
if (processResult)
|
||||
{
|
||||
// Import Successful - Delete
|
||||
if (File.Exists(filename))
|
||||
File.Delete(filename);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Import Failed - Move to Errors Folder
|
||||
if (File.Exists(filename))
|
||||
{
|
||||
try
|
||||
{
|
||||
string folderError = DataStore.CreateLocation(database, "DocumentDropBox_Errors");
|
||||
string filenameError = Path.Combine(folderError, Path.GetFileName(filename));
|
||||
int filenameErrorCount = 0;
|
||||
while (File.Exists(filenameError))
|
||||
{
|
||||
filenameError = Path.Combine(folderError, string.Format("{0} ({1}){2}", Path.GetFileNameWithoutExtension(filename), ++filenameErrorCount, Path.GetExtension(filename)));
|
||||
}
|
||||
File.Move(filename, filenameError);
|
||||
}
|
||||
catch
|
||||
{
|
||||
// Ignore Errors
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// To Many Errors
|
||||
DocumentImporterLog.LogImportError(sessionId, string.Format("To many errors occurred trying to import '{1}' (SessionId: {0})", sessionId, friendlyFilename));
|
||||
// Move to Errors Folder
|
||||
if (File.Exists(filename))
|
||||
{
|
||||
try
|
||||
{
|
||||
string folderError = DataStore.CreateLocation(database, "DocumentDropBox_Errors");
|
||||
string filenameError = Path.Combine(folderError, Path.GetFileName(filename));
|
||||
int filenameErrorCount = 0;
|
||||
while (File.Exists(filenameError))
|
||||
{
|
||||
filenameError = Path.Combine(folderError, string.Format("{0} ({1}){2}", Path.GetFileNameWithoutExtension(filename), ++filenameErrorCount, Path.GetExtension(filename)));
|
||||
}
|
||||
File.Move(filename, filenameError);
|
||||
}
|
||||
catch
|
||||
{
|
||||
// Ignore Errors
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
DocumentImporterLog.LogImportFinished(sessionId);
|
||||
|
||||
// All Done
|
||||
context.Scheduler.DeleteJob(context.JobDetail.Key);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
DocumentImporterLog.LogImportWarning(sessionId, string.Format("{0}; Will try again in 10 Seconds", ex.Message));
|
||||
// Reschedule Job for 10 seconds
|
||||
SimpleTriggerImpl trig = new SimpleTriggerImpl(Guid.NewGuid().ToString(), new DateTimeOffset(DateTime.Now.AddSeconds(10)));
|
||||
context.Scheduler.RescheduleJob(context.Trigger.Key, trig);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,304 +0,0 @@
|
||||
using Disco.Services.Logging;
|
||||
using Disco.Services.Logging.Models;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
namespace Disco.BI.DocumentTemplateBI.Importer
|
||||
{
|
||||
public class DocumentImporterLog : LogBase
|
||||
{
|
||||
public enum EventTypeIds
|
||||
{
|
||||
ImportStarting = 10,
|
||||
ImportProgress,
|
||||
ImportFinished,
|
||||
ImportWarning = 15,
|
||||
ImportError,
|
||||
ImportPageStarting = 100,
|
||||
ImportPageImageUpdate = 104,
|
||||
ImportPageProgress,
|
||||
ImportPageDetected = 110,
|
||||
ImportPageUndetected = 115,
|
||||
ImportPageError = 120,
|
||||
ImportPageUndetectedStored = 150
|
||||
}
|
||||
|
||||
private const int _ModuleId = 40;
|
||||
|
||||
public static DocumentImporterLog Current
|
||||
{
|
||||
get
|
||||
{
|
||||
return (DocumentImporterLog)LogContext.LogModules[_ModuleId];
|
||||
}
|
||||
}
|
||||
|
||||
public override string ModuleDescription
|
||||
{
|
||||
get
|
||||
{
|
||||
return "Document Importer";
|
||||
}
|
||||
}
|
||||
public override int ModuleId
|
||||
{
|
||||
get
|
||||
{
|
||||
return _ModuleId;
|
||||
}
|
||||
}
|
||||
public override string ModuleName
|
||||
{
|
||||
get
|
||||
{
|
||||
return "DocumentImporter";
|
||||
}
|
||||
}
|
||||
private static void Log(DocumentImporterLog.EventTypeIds EventTypeId, params object[] Args)
|
||||
{
|
||||
DocumentImporterLog.Current.Log((int)EventTypeId, Args);
|
||||
}
|
||||
public static void LogImportStarting(string SessionId, string DocumentName)
|
||||
{
|
||||
DocumentImporterLog.Log(DocumentImporterLog.EventTypeIds.ImportStarting, new object[]
|
||||
{
|
||||
SessionId,
|
||||
DocumentName
|
||||
});
|
||||
}
|
||||
public static void LogImportProgress(string SessionId, int? Progress, string Status)
|
||||
{
|
||||
DocumentImporterLog.Log(DocumentImporterLog.EventTypeIds.ImportProgress, new object[]
|
||||
{
|
||||
SessionId,
|
||||
Progress,
|
||||
Status
|
||||
});
|
||||
}
|
||||
public static void LogImportFinished(string SessionId)
|
||||
{
|
||||
DocumentImporterLog.Log(DocumentImporterLog.EventTypeIds.ImportFinished, new object[]
|
||||
{
|
||||
SessionId
|
||||
});
|
||||
}
|
||||
public static void LogImportWarning(string SessionId, string Message)
|
||||
{
|
||||
DocumentImporterLog.Log(DocumentImporterLog.EventTypeIds.ImportWarning, new object[]
|
||||
{
|
||||
SessionId,
|
||||
Message
|
||||
});
|
||||
}
|
||||
public static void LogImportError(string SessionId, string Message)
|
||||
{
|
||||
DocumentImporterLog.Log(DocumentImporterLog.EventTypeIds.ImportError, new object[]
|
||||
{
|
||||
SessionId,
|
||||
Message
|
||||
});
|
||||
}
|
||||
public static void LogImportPageStarting(string SessionId, int PageNumber)
|
||||
{
|
||||
DocumentImporterLog.Log(DocumentImporterLog.EventTypeIds.ImportPageStarting, new object[]
|
||||
{
|
||||
SessionId,
|
||||
PageNumber
|
||||
});
|
||||
}
|
||||
public static void LogImportPageImageUpdate(string SessionId, int PageNumber)
|
||||
{
|
||||
DocumentImporterLog.Log(DocumentImporterLog.EventTypeIds.ImportPageImageUpdate, new object[]
|
||||
{
|
||||
SessionId,
|
||||
PageNumber
|
||||
});
|
||||
}
|
||||
public static void LogImportPageProgress(string SessionId, int PageNumber, int? Progress, string Status)
|
||||
{
|
||||
DocumentImporterLog.Log(DocumentImporterLog.EventTypeIds.ImportPageProgress, new object[]
|
||||
{
|
||||
SessionId,
|
||||
PageNumber,
|
||||
Progress,
|
||||
Status
|
||||
});
|
||||
}
|
||||
public static void LogImportPageDetected(string SessionId, int PageNumber, string DocumentTypeId, string DocumentTypeName, string TargetType, string AssignedId, string AssignedName)
|
||||
{
|
||||
DocumentImporterLog.Log(DocumentImporterLog.EventTypeIds.ImportPageDetected, new object[]
|
||||
{
|
||||
SessionId,
|
||||
PageNumber,
|
||||
DocumentTypeId,
|
||||
DocumentTypeName,
|
||||
TargetType,
|
||||
AssignedId,
|
||||
AssignedName
|
||||
});
|
||||
}
|
||||
public static void LogImportPageUndetected(string SessionId, int PageNumber)
|
||||
{
|
||||
DocumentImporterLog.Log(DocumentImporterLog.EventTypeIds.ImportPageUndetected, new object[]
|
||||
{
|
||||
SessionId,
|
||||
PageNumber
|
||||
});
|
||||
}
|
||||
public static void LogImportPageError(string SessionId, int PageNumber, string Message)
|
||||
{
|
||||
DocumentImporterLog.Log(DocumentImporterLog.EventTypeIds.ImportPageError, new object[]
|
||||
{
|
||||
SessionId,
|
||||
PageNumber,
|
||||
Message
|
||||
});
|
||||
}
|
||||
public static void LogImportPageUndetectedStored(string SessionId, int PageNumber)
|
||||
{
|
||||
DocumentImporterLog.Log(DocumentImporterLog.EventTypeIds.ImportPageUndetectedStored, new object[]
|
||||
{
|
||||
SessionId,
|
||||
PageNumber
|
||||
});
|
||||
}
|
||||
protected override System.Collections.Generic.List<LogEventType> LoadEventTypes()
|
||||
{
|
||||
return new System.Collections.Generic.List<LogEventType>
|
||||
{
|
||||
new LogEventType
|
||||
{
|
||||
Id = 10,
|
||||
ModuleId = 40,
|
||||
Name = "Import Starting",
|
||||
Format = "Starting import of document: {1} (SessionId: {0})",
|
||||
Severity = 0,
|
||||
UseLive = true,
|
||||
UsePersist = true,
|
||||
UseDisplay = true
|
||||
},
|
||||
new LogEventType
|
||||
{
|
||||
Id = 11,
|
||||
ModuleId = 40,
|
||||
Name = "Import Progress",
|
||||
Format = "Processing: {1}% Complete; Status: {2}",
|
||||
Severity = 0,
|
||||
UseLive = true,
|
||||
UsePersist = false,
|
||||
UseDisplay = false
|
||||
},
|
||||
new LogEventType
|
||||
{
|
||||
Id = 12,
|
||||
ModuleId = 40,
|
||||
Name = "Import Finished",
|
||||
Format = "Import of document complete (SessionId: {0})",
|
||||
Severity = 0,
|
||||
UseLive = true,
|
||||
UsePersist = true,
|
||||
UseDisplay = true
|
||||
},
|
||||
new LogEventType
|
||||
{
|
||||
Id = 15,
|
||||
ModuleId = 40,
|
||||
Name = "Import Warning",
|
||||
Format = "Import Warning: {1} (SessionId: {0})",
|
||||
Severity = 1,
|
||||
UseLive = true,
|
||||
UsePersist = true,
|
||||
UseDisplay = true
|
||||
},
|
||||
new LogEventType
|
||||
{
|
||||
Id = 16,
|
||||
ModuleId = 40,
|
||||
Name = "Import Error",
|
||||
Format = "Import Error: {1} (SessionId: {0})",
|
||||
Severity = 2,
|
||||
UseLive = true,
|
||||
UsePersist = true,
|
||||
UseDisplay = true
|
||||
},
|
||||
new LogEventType
|
||||
{
|
||||
Id = 100,
|
||||
ModuleId = 40,
|
||||
Name = "Import Page Starting",
|
||||
Format = "Starting import of page: {1} (SessionId: {0})",
|
||||
Severity = 0,
|
||||
UseLive = true,
|
||||
UsePersist = true,
|
||||
UseDisplay = true
|
||||
},
|
||||
new LogEventType
|
||||
{
|
||||
Id = 104,
|
||||
ModuleId = 40,
|
||||
Name = "Import Page Image Update",
|
||||
Format = null,
|
||||
Severity = 0,
|
||||
UseLive = true,
|
||||
UsePersist = false,
|
||||
UseDisplay = false
|
||||
},
|
||||
new LogEventType
|
||||
{
|
||||
Id = 105,
|
||||
ModuleId = 40,
|
||||
Name = "Import Page Progress",
|
||||
Format = "Processing: Page {1}; {2}% Complete; Status: {3}",
|
||||
Severity = 0,
|
||||
UseLive = true,
|
||||
UsePersist = false,
|
||||
UseDisplay = false
|
||||
},
|
||||
new LogEventType
|
||||
{
|
||||
Id = 110,
|
||||
ModuleId = 40,
|
||||
Name = "Import Page Assigned",
|
||||
Format = "Page {1} of type '{3}' assigned to {4}: '{6}'",
|
||||
Severity = 0,
|
||||
UseLive = true,
|
||||
UsePersist = true,
|
||||
UseDisplay = true
|
||||
},
|
||||
new LogEventType
|
||||
{
|
||||
Id = 115,
|
||||
ModuleId = 40,
|
||||
Name = "Import Page Undetected",
|
||||
Format = "Page {1} not detected",
|
||||
Severity = 1,
|
||||
UseLive = true,
|
||||
UsePersist = true,
|
||||
UseDisplay = true
|
||||
},
|
||||
new LogEventType
|
||||
{
|
||||
Id = 120,
|
||||
ModuleId = 40,
|
||||
Name = "Import Page Error",
|
||||
Format = "Page {1}, Import Error: {2}",
|
||||
Severity = 2,
|
||||
UseLive = true,
|
||||
UsePersist = true,
|
||||
UseDisplay = true
|
||||
},
|
||||
new LogEventType
|
||||
{
|
||||
Id = 150,
|
||||
ModuleId = 40,
|
||||
Name = "Import Page Undetected Stored",
|
||||
Format = null,
|
||||
Severity = 0,
|
||||
UseLive = true,
|
||||
UsePersist = false,
|
||||
UseDisplay = false
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,49 +0,0 @@
|
||||
using iTextSharp.text;
|
||||
using iTextSharp.text.pdf;
|
||||
|
||||
namespace Disco.BI.DocumentTemplateBI
|
||||
{
|
||||
public static class Utilities
|
||||
{
|
||||
public static System.IO.Stream JoinPdfs(params System.IO.Stream[] Pdfs)
|
||||
{
|
||||
if (Pdfs.Length == 0)
|
||||
throw new System.ArgumentNullException("Pdfs");
|
||||
|
||||
// Only One PDF - Possible Reference Bug v's Memory/Speed (Returning Param Memory Stream)
|
||||
if (Pdfs.Length == 1)
|
||||
return Pdfs[0];
|
||||
|
||||
// Join Pdfs
|
||||
System.IO.MemoryStream msBuilder = new System.IO.MemoryStream();
|
||||
|
||||
Document pdfDoc = new Document();
|
||||
PdfCopy pdfCopy = new PdfCopy(pdfDoc, msBuilder);
|
||||
pdfDoc.Open();
|
||||
pdfCopy.CloseStream = false;
|
||||
|
||||
for (int i = 0; i < Pdfs.Length; i++)
|
||||
{
|
||||
System.IO.Stream pdf = Pdfs[i];
|
||||
PdfReader pdfReader = new PdfReader(pdf);
|
||||
|
||||
for (int indexPage = 1; indexPage <= pdfReader.NumberOfPages; indexPage++)
|
||||
{
|
||||
iTextSharp.text.Rectangle pageSize = pdfReader.GetPageSizeWithRotation(indexPage);
|
||||
PdfImportedPage page = pdfCopy.GetImportedPage(pdfReader, indexPage);
|
||||
pdfDoc.SetPageSize(pageSize);
|
||||
pdfDoc.NewPage();
|
||||
pdfCopy.AddPage(page);
|
||||
}
|
||||
|
||||
pdfReader.Close();
|
||||
}
|
||||
|
||||
pdfDoc.Close();
|
||||
pdfCopy.Close();
|
||||
msBuilder.Position = 0;
|
||||
|
||||
return msBuilder;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,259 +0,0 @@
|
||||
using Disco.Data.Repository;
|
||||
using Disco.Models.BI.DocumentTemplates;
|
||||
using Disco.Models.Repository;
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Text;
|
||||
using Disco.Models.BI.Expressions;
|
||||
|
||||
namespace Disco.BI.Expressions
|
||||
{
|
||||
public sealed class Expression : System.Collections.Generic.List<IExpressionPart>
|
||||
{
|
||||
public string Name { get; private set; }
|
||||
public string Source { get; private set; }
|
||||
public bool IsDynamic { get; private set; }
|
||||
public int Ordinal { get; private set; }
|
||||
|
||||
private Expression(string Name, string Source, int Ordinal)
|
||||
{
|
||||
this.Name = Name;
|
||||
this.Source = Source;
|
||||
this.Ordinal = Ordinal;
|
||||
}
|
||||
|
||||
public static void InitializeExpressions()
|
||||
{
|
||||
Spring.Core.TypeResolution.TypeRegistry.RegisterType("DataExt", typeof(Extensions.DataExt));
|
||||
Spring.Core.TypeResolution.TypeRegistry.RegisterType("UserExt", typeof(Extensions.UserExt));
|
||||
Spring.Core.TypeResolution.TypeRegistry.RegisterType("DeviceExt", typeof(Extensions.DeviceExt));
|
||||
Spring.Core.TypeResolution.TypeRegistry.RegisterType("ImageExt", typeof(Extensions.ImageExt));
|
||||
}
|
||||
|
||||
public T EvaluateFirst<T>(object ExpressionContext, System.Collections.IDictionary Variables)
|
||||
{
|
||||
T result = default(T);
|
||||
if (this.Count > 0)
|
||||
{
|
||||
try
|
||||
{
|
||||
object expressionResult = this[0].Evaluate(ExpressionContext, Variables);
|
||||
if (expressionResult != null)
|
||||
{
|
||||
if (expressionResult is T)
|
||||
{
|
||||
result = (T)expressionResult;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new InvalidOperationException("Expression returned an invalid type");
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (System.Exception ex)
|
||||
{
|
||||
throw new InvalidOperationException("Expression evaluation resulted in an error", ex);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public Tuple<string, bool, object> Evaluate(object ExpressionContext, System.Collections.IDictionary Variables)
|
||||
{
|
||||
System.Text.StringBuilder resultValue = new System.Text.StringBuilder();
|
||||
object resultObject = null;
|
||||
bool resultError = false;
|
||||
foreach (var expressionPart in this)
|
||||
{
|
||||
try
|
||||
{
|
||||
object partValue = expressionPart.Evaluate(ExpressionContext, Variables);
|
||||
if (partValue != null)
|
||||
{
|
||||
// Check for Result Objects
|
||||
if (partValue is IImageExpressionResult)
|
||||
resultObject = partValue;
|
||||
else
|
||||
resultValue.Append(partValue.ToString());
|
||||
}
|
||||
}
|
||||
catch (System.Exception ex)
|
||||
{
|
||||
if (!expressionPart.ErrorsAllowed)
|
||||
{
|
||||
resultValue.Append("## ERROR # ");
|
||||
resultValue.Append(ex.Message);
|
||||
resultValue.Append(" ##");
|
||||
resultError = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return new Tuple<string, bool, object>(resultValue.ToString(), resultError, resultObject);
|
||||
}
|
||||
public static Expression TokenizeSingleDynamic(string Name, string ExpressionSource, int Ordinal)
|
||||
{
|
||||
Expression e = new Expression(Name, ExpressionSource, Ordinal);
|
||||
if (ExpressionSource != null && !string.IsNullOrWhiteSpace(ExpressionSource))
|
||||
e.Add(new EvaluateExpressionPart(ExpressionSource));
|
||||
e.IsDynamic = true;
|
||||
return e;
|
||||
}
|
||||
public static Expression Tokenize(string Name, string ExpressionSource, int Ordinal)
|
||||
{
|
||||
Expression e = new Expression(Name, ExpressionSource, Ordinal);
|
||||
if (!ExpressionSource.Contains("{") || !ExpressionSource.Contains("}"))
|
||||
{
|
||||
e.Add(new TextExpressionPart(ExpressionSource));
|
||||
}
|
||||
else
|
||||
{
|
||||
System.Text.StringBuilder token = new System.Text.StringBuilder();
|
||||
bool tokenEval = false;
|
||||
int tokenEvalDepth = 0;
|
||||
foreach (char c in ExpressionSource)
|
||||
{
|
||||
switch (c)
|
||||
{
|
||||
case '{':
|
||||
{
|
||||
if (!tokenEval)
|
||||
{
|
||||
if (token.Length > 0)
|
||||
{
|
||||
e.Add(new TextExpressionPart(token.ToString()));
|
||||
token = new System.Text.StringBuilder();
|
||||
}
|
||||
tokenEval = true;
|
||||
tokenEvalDepth = 0;
|
||||
}
|
||||
tokenEvalDepth++;
|
||||
token.Append(c);
|
||||
break;
|
||||
}
|
||||
case '}':
|
||||
{
|
||||
token.Append(c);
|
||||
if (tokenEval)
|
||||
{
|
||||
tokenEvalDepth--;
|
||||
if (tokenEvalDepth <= 0)
|
||||
{
|
||||
if (token.Length != 2 && (token.Length != 3 || token[1] != '@'))
|
||||
{
|
||||
e.Add(new EvaluateExpressionPart(token.ToString()));
|
||||
e.IsDynamic = true;
|
||||
token = new System.Text.StringBuilder();
|
||||
}
|
||||
tokenEval = false;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
token.Append(c);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (token.Length > 0)
|
||||
{
|
||||
e.Add(new TextExpressionPart(token.ToString()));
|
||||
}
|
||||
}
|
||||
return e;
|
||||
}
|
||||
|
||||
public static IDictionary StandardVariables(DocumentTemplate AttachmentType, DiscoDataContext Database, User User, System.DateTime TimeStamp, DocumentState DocumentState)
|
||||
{
|
||||
return new Hashtable
|
||||
{
|
||||
|
||||
{
|
||||
"DataContext",
|
||||
Database
|
||||
},
|
||||
|
||||
{
|
||||
"User",
|
||||
User
|
||||
},
|
||||
|
||||
{
|
||||
"TimeStamp",
|
||||
TimeStamp
|
||||
},
|
||||
|
||||
{
|
||||
"AttachmentType",
|
||||
AttachmentType
|
||||
},
|
||||
|
||||
{
|
||||
"State",
|
||||
DocumentState
|
||||
}
|
||||
};
|
||||
}
|
||||
public static Dictionary<string, string> StandardVariableTypes()
|
||||
{
|
||||
return new Dictionary<string, string>
|
||||
{
|
||||
|
||||
{
|
||||
"#DataContext",
|
||||
typeof(DiscoDataContext).AssemblyQualifiedName
|
||||
},
|
||||
|
||||
{
|
||||
"#User",
|
||||
typeof(User).AssemblyQualifiedName
|
||||
},
|
||||
|
||||
{
|
||||
"#TimeStamp",
|
||||
typeof(System.DateTime).AssemblyQualifiedName
|
||||
},
|
||||
|
||||
{
|
||||
"#AttachmentType",
|
||||
typeof(DocumentTemplate).AssemblyQualifiedName
|
||||
},
|
||||
|
||||
{
|
||||
"#State",
|
||||
typeof(DocumentState).AssemblyQualifiedName
|
||||
}
|
||||
};
|
||||
}
|
||||
public static Dictionary<string, string> ExtensionLibraryTypes()
|
||||
{
|
||||
return new Dictionary<string, string>
|
||||
{
|
||||
{
|
||||
"DataExt",
|
||||
typeof(Extensions.DataExt).AssemblyQualifiedName
|
||||
},
|
||||
|
||||
{
|
||||
"DeviceExt",
|
||||
typeof(Extensions.DeviceExt).AssemblyQualifiedName
|
||||
},
|
||||
|
||||
{
|
||||
"ImageExt",
|
||||
typeof(Extensions.ImageExt).AssemblyQualifiedName
|
||||
},
|
||||
|
||||
{
|
||||
"UserExt",
|
||||
typeof(Extensions.UserExt).AssemblyQualifiedName
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,103 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Collections.Concurrent;
|
||||
|
||||
namespace Disco.BI.Expressions
|
||||
{
|
||||
public static class ExpressionCache
|
||||
{
|
||||
private static ConcurrentDictionary<string, ConcurrentDictionary<string, Expression>> _Cache = new ConcurrentDictionary<string, ConcurrentDictionary<string, Expression>>();
|
||||
|
||||
public delegate Expression CreateValueDelegate();
|
||||
|
||||
public static ConcurrentDictionary<string, Expression> GetModule(string Module, bool Create = false)
|
||||
{
|
||||
ConcurrentDictionary<string, Expression> moduleCache;
|
||||
if (_Cache.TryGetValue(Module, out moduleCache))
|
||||
return moduleCache;
|
||||
else
|
||||
{
|
||||
if (Create)
|
||||
{
|
||||
moduleCache = new ConcurrentDictionary<string, Expression>();
|
||||
_Cache.TryAdd(Module, moduleCache);
|
||||
return moduleCache;
|
||||
}
|
||||
else
|
||||
return null;
|
||||
}
|
||||
}
|
||||
private static Expression GetModuleValue(string Module, string Key, CreateValueDelegate CreateValue)
|
||||
{
|
||||
ConcurrentDictionary<string, Expression> moduleCache = GetModule(Module, (CreateValue != null));
|
||||
if (moduleCache != null)
|
||||
{
|
||||
Expression expression;
|
||||
if (moduleCache.TryGetValue(Key, out expression))
|
||||
{
|
||||
return expression;
|
||||
}
|
||||
if (CreateValue != null)
|
||||
{
|
||||
expression = CreateValue();
|
||||
Expression oldExpression;
|
||||
if (moduleCache.TryGetValue(Key, out oldExpression))
|
||||
moduleCache.TryUpdate(Key, expression, oldExpression);
|
||||
else
|
||||
moduleCache.TryAdd(Key, expression);
|
||||
return expression;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static Expression GetValue(string Module, string Key, CreateValueDelegate CreateValue)
|
||||
{
|
||||
return GetModuleValue(Module, Key, CreateValue);
|
||||
}
|
||||
|
||||
public static Expression GetValue(string Module, string Key)
|
||||
{
|
||||
return GetModuleValue(Module, Key, null);
|
||||
}
|
||||
|
||||
public static bool InvalidModule(string Module)
|
||||
{
|
||||
ConcurrentDictionary<string, Expression> moduleCache;
|
||||
return _Cache.TryRemove(Module, out moduleCache);
|
||||
}
|
||||
|
||||
public static bool InvalidateKey(string Module, string Key)
|
||||
{
|
||||
Expression expression;
|
||||
ConcurrentDictionary<string, Expression> moduleCache = GetModule(Module, false);
|
||||
if (moduleCache != null)
|
||||
{
|
||||
bool removeResult = moduleCache.TryRemove(Key, out expression);
|
||||
if (moduleCache.Count == 0)
|
||||
InvalidModule(Module);
|
||||
return removeResult;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
public static bool SetValue(string Module, string Key, Expression Expression)
|
||||
{
|
||||
ConcurrentDictionary<string, Expression> moduleCache = GetModule(Module, true);
|
||||
|
||||
if (moduleCache.ContainsKey(Key))
|
||||
{
|
||||
Expression oldExpression;
|
||||
if (moduleCache.TryGetValue(Key, out oldExpression))
|
||||
{
|
||||
return moduleCache.TryUpdate(Key, Expression, oldExpression);
|
||||
}
|
||||
}
|
||||
return moduleCache.TryAdd(Key, Expression);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,61 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
namespace Disco.BI.Expressions
|
||||
{
|
||||
public class ExpressionTypeMemberDescriptor
|
||||
{
|
||||
public const string FunctionKind = "function";
|
||||
public const string PropertyKind = "property";
|
||||
public const string ParameterKind = "parameter";
|
||||
|
||||
public string Kind {get;set;}
|
||||
public string Name {get;set;}
|
||||
public string ReturnType {get;set;}
|
||||
public string ReturnExpressionType{get;set;}
|
||||
public List<ExpressionTypeMemberDescriptor> Parameters{get;set;}
|
||||
|
||||
public static ExpressionTypeMemberDescriptor Build(System.Reflection.MethodInfo m)
|
||||
{
|
||||
ExpressionTypeMemberDescriptor md = new ExpressionTypeMemberDescriptor
|
||||
{
|
||||
Kind = "function",
|
||||
Name = m.Name,
|
||||
ReturnType = m.ReturnType.Name,
|
||||
ReturnExpressionType = m.ReturnType.AssemblyQualifiedName
|
||||
};
|
||||
md.Parameters = (
|
||||
from mdp in m.GetParameters()
|
||||
select ExpressionTypeMemberDescriptor.Build(mdp)).ToList<ExpressionTypeMemberDescriptor>();
|
||||
return md;
|
||||
}
|
||||
public static ExpressionTypeMemberDescriptor Build(System.Reflection.PropertyInfo p)
|
||||
{
|
||||
ExpressionTypeMemberDescriptor md = new ExpressionTypeMemberDescriptor
|
||||
{
|
||||
Kind = "property",
|
||||
Name = p.Name,
|
||||
ReturnType = p.PropertyType.Name,
|
||||
ReturnExpressionType = p.PropertyType.AssemblyQualifiedName
|
||||
};
|
||||
md.Parameters = (
|
||||
from mdp in p.GetIndexParameters()
|
||||
select ExpressionTypeMemberDescriptor.Build(mdp)).ToList<ExpressionTypeMemberDescriptor>();
|
||||
return md;
|
||||
}
|
||||
public static ExpressionTypeMemberDescriptor Build(System.Reflection.ParameterInfo pi)
|
||||
{
|
||||
return new ExpressionTypeMemberDescriptor
|
||||
{
|
||||
Kind = "parameter",
|
||||
Name = pi.Name,
|
||||
ReturnType = pi.ParameterType.Name,
|
||||
ReturnExpressionType = pi.ParameterType.AssemblyQualifiedName
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
-70
@@ -1,70 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Disco.Models.BI.Expressions;
|
||||
using System.IO;
|
||||
using System.Drawing;
|
||||
using Disco.BI.Extensions;
|
||||
|
||||
namespace Disco.BI.Expressions.Extensions.ImageResultImplementations
|
||||
{
|
||||
public abstract class BaseImageExpressionResult : IImageExpressionResult
|
||||
{
|
||||
public byte Quality { get; set; }
|
||||
public bool LosslessFormat { get; set; }
|
||||
public bool ShowField { get; set; }
|
||||
public string BackgroundColour { get; set; }
|
||||
public bool BackgroundPreferTransparent { get; set; }
|
||||
|
||||
public BaseImageExpressionResult()
|
||||
{
|
||||
this.LosslessFormat = false;
|
||||
this.Quality = 90;
|
||||
this.ShowField = false;
|
||||
this.BackgroundPreferTransparent = true;
|
||||
}
|
||||
|
||||
public abstract Stream GetImage(int Width, int Height);
|
||||
|
||||
protected Stream RenderImage(Image SourceImage, int Width, int Height)
|
||||
{
|
||||
if (SourceImage == null)
|
||||
throw new ArgumentNullException("SourceImage");
|
||||
if (Width <= 0)
|
||||
throw new ArgumentOutOfRangeException("Width", "Width must be > 0");
|
||||
if (Height <= 0)
|
||||
throw new ArgumentOutOfRangeException("Height", "Height must be > 0");
|
||||
|
||||
Brush backgroundBrush = null;
|
||||
if (!LosslessFormat || !BackgroundPreferTransparent)
|
||||
{
|
||||
if (string.IsNullOrEmpty(this.BackgroundColour))
|
||||
backgroundBrush = Brushes.White;
|
||||
else
|
||||
backgroundBrush = new SolidBrush(ColorTranslator.FromHtml(this.BackgroundColour));
|
||||
}
|
||||
|
||||
using (Image resizedImage = SourceImage.ResizeImage(Width, Height, backgroundBrush))
|
||||
{
|
||||
return OutputImage(resizedImage);
|
||||
}
|
||||
}
|
||||
|
||||
protected Stream OutputImage(Image SourceImage)
|
||||
{
|
||||
MemoryStream imageStream = new MemoryStream();
|
||||
if (LosslessFormat)
|
||||
{ // Lossless Format - PNG
|
||||
SourceImage.SavePng(imageStream);
|
||||
}
|
||||
else
|
||||
{ // Lossy Format - JPG
|
||||
byte quality = Math.Min((byte)100, Math.Max((byte)1, this.Quality));
|
||||
SourceImage.SaveJpg(quality, imageStream);
|
||||
}
|
||||
imageStream.Position = 0;
|
||||
return imageStream;
|
||||
}
|
||||
}
|
||||
}
|
||||
-27
@@ -1,27 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.IO;
|
||||
using System.Drawing;
|
||||
|
||||
namespace Disco.BI.Expressions.Extensions.ImageResultImplementations
|
||||
{
|
||||
public class BitmapImageExpressionResult : BaseImageExpressionResult
|
||||
{
|
||||
public Image Image { get; set; }
|
||||
|
||||
public BitmapImageExpressionResult(Image Image)
|
||||
{
|
||||
if (Image == null)
|
||||
throw new ArgumentNullException("Image");
|
||||
|
||||
this.Image = Image;
|
||||
}
|
||||
|
||||
public override Stream GetImage(int Width, int Height)
|
||||
{
|
||||
return this.RenderImage(this.Image, Width, Height);
|
||||
}
|
||||
}
|
||||
}
|
||||
-32
@@ -1,32 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.IO;
|
||||
using System.Drawing;
|
||||
|
||||
namespace Disco.BI.Expressions.Extensions.ImageResultImplementations
|
||||
{
|
||||
public class FileImageExpressionResult : BaseImageExpressionResult
|
||||
{
|
||||
public string AbsoluteFilePath { get; set; }
|
||||
|
||||
public FileImageExpressionResult(string AbsoluteFilePath)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(AbsoluteFilePath))
|
||||
throw new ArgumentNullException("AbsoluteFilePath");
|
||||
if (!File.Exists(AbsoluteFilePath))
|
||||
throw new FileNotFoundException("Image not found", AbsoluteFilePath);
|
||||
|
||||
this.AbsoluteFilePath = AbsoluteFilePath;
|
||||
}
|
||||
|
||||
public override Stream GetImage(int Width, int Height)
|
||||
{
|
||||
using (Image SourceImage = Bitmap.FromFile(this.AbsoluteFilePath))
|
||||
{
|
||||
return this.RenderImage(SourceImage, Width, Height);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,95 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Disco.Models.Repository;
|
||||
using Disco.Data.Repository;
|
||||
using Disco.Services.Users;
|
||||
using Disco.Services.Authorization;
|
||||
using Disco.BI.DocumentTemplateBI.ManagedGroups;
|
||||
|
||||
namespace Disco.BI.Extensions
|
||||
{
|
||||
public static class AttachmentActionExtensions
|
||||
{
|
||||
|
||||
#region Delete
|
||||
public static bool CanDelete(this DeviceAttachment da)
|
||||
{
|
||||
if (UserService.CurrentAuthorization.Has(Claims.Device.Actions.RemoveAnyAttachments))
|
||||
return true;
|
||||
|
||||
if (UserService.CurrentAuthorization.Has(Claims.Device.Actions.RemoveOwnAttachments)
|
||||
&& da.TechUserId == UserService.CurrentUserId)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
public static void OnDelete(this DeviceAttachment da, DiscoDataContext Database)
|
||||
{
|
||||
if (!da.CanDelete())
|
||||
throw new InvalidOperationException("Deletion of Attachment is Denied");
|
||||
|
||||
var attachmentId = da.Id;
|
||||
var documentTemplateId = da.DocumentTemplateId;
|
||||
var deviceSerialNumber = da.DeviceSerialNumber;
|
||||
|
||||
da.RepositoryDelete(Database);
|
||||
Database.DeviceAttachments.Remove(da);
|
||||
|
||||
DocumentTemplateManagedGroups.TriggerDeviceAttachmentDeleted(Database, attachmentId, documentTemplateId, deviceSerialNumber);
|
||||
}
|
||||
public static bool CanDelete(this JobAttachment ja)
|
||||
{
|
||||
if (UserService.CurrentAuthorization.Has(Claims.Job.Actions.RemoveAnyAttachments))
|
||||
return true;
|
||||
|
||||
if (UserService.CurrentAuthorization.Has(Claims.Job.Actions.RemoveOwnAttachments)
|
||||
&& ja.TechUserId == UserService.CurrentUserId)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
public static void OnDelete(this JobAttachment ja, DiscoDataContext Database)
|
||||
{
|
||||
if (!ja.CanDelete())
|
||||
throw new InvalidOperationException("Deletion of Attachment is Denied");
|
||||
|
||||
var attachmentId = ja.Id;
|
||||
var documentTemplateId = ja.DocumentTemplateId;
|
||||
var jobId = ja.JobId;
|
||||
|
||||
ja.RepositoryDelete(Database);
|
||||
Database.JobAttachments.Remove(ja);
|
||||
|
||||
DocumentTemplateManagedGroups.TriggerJobAttachmentDeleted(Database, attachmentId, documentTemplateId, jobId);
|
||||
}
|
||||
public static bool CanDelete(this UserAttachment ua)
|
||||
{
|
||||
if (UserService.CurrentAuthorization.Has(Claims.User.Actions.RemoveAnyAttachments))
|
||||
return true;
|
||||
|
||||
if (UserService.CurrentAuthorization.Has(Claims.User.Actions.RemoveOwnAttachments)
|
||||
&& ua.TechUserId == UserService.CurrentUserId)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
public static void OnDelete(this UserAttachment ua, DiscoDataContext Database)
|
||||
{
|
||||
if (!ua.CanDelete())
|
||||
throw new InvalidOperationException("Deletion of Attachment is Denied");
|
||||
|
||||
var attachmentId = ua.Id;
|
||||
var documentTemplateId = ua.DocumentTemplateId;
|
||||
var userId = ua.UserId;
|
||||
|
||||
ua.RepositoryDelete(Database);
|
||||
Database.UserAttachments.Remove(ua);
|
||||
|
||||
DocumentTemplateManagedGroups.TriggerUserAttachmentDeleted(Database, attachmentId, documentTemplateId, userId);
|
||||
}
|
||||
#endregion
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,197 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Disco.Models.Repository;
|
||||
using Disco.Data.Repository;
|
||||
using System.IO;
|
||||
using Disco.BI.DocumentTemplateBI;
|
||||
using Disco.Services.Users;
|
||||
|
||||
namespace Disco.BI.Extensions
|
||||
{
|
||||
public static class AttachmentExtensions
|
||||
{
|
||||
|
||||
public static bool ImportPdfAttachment(this DocumentUniqueIdentifier UniqueIdentifier, DiscoDataContext Database, System.IO.Stream PdfContent, byte[] PdfThumbnail)
|
||||
{
|
||||
|
||||
UniqueIdentifier.LoadComponents(Database);
|
||||
DocumentTemplate documentTemplate = UniqueIdentifier.DocumentTemplate;
|
||||
string filename;
|
||||
string comments;
|
||||
|
||||
if (documentTemplate == null)
|
||||
{
|
||||
filename = string.Format("{0}_{1:yyyyMMdd-HHmmss}.pdf", UniqueIdentifier.DataId.Replace('\\', '_'), UniqueIdentifier.TimeStamp);
|
||||
comments = string.Format("Uploaded: {0:s}", UniqueIdentifier.TimeStamp);
|
||||
}
|
||||
else
|
||||
{
|
||||
filename = string.Format("{0}_{1:yyyyMMdd-HHmmss}.pdf", UniqueIdentifier.TemplateTypeId, UniqueIdentifier.TimeStamp);
|
||||
comments = string.Format("Generated: {0:s}", UniqueIdentifier.TimeStamp);
|
||||
}
|
||||
|
||||
User creatorUser = UserService.GetUser(UniqueIdentifier.CreatorId, Database);
|
||||
if (creatorUser == null)
|
||||
{
|
||||
// No Creator User (or Username invalid)
|
||||
creatorUser = UserService.CurrentUser;
|
||||
}
|
||||
switch (UniqueIdentifier.DataScope)
|
||||
{
|
||||
case DocumentTemplate.DocumentTemplateScopes.Device:
|
||||
Device d = (Device)UniqueIdentifier.Data;
|
||||
d.CreateAttachment(Database, creatorUser, filename, DocumentTemplate.PdfMimeType, comments, PdfContent, documentTemplate, PdfThumbnail);
|
||||
return true;
|
||||
case DocumentTemplate.DocumentTemplateScopes.Job:
|
||||
Job j = (Job)UniqueIdentifier.Data;
|
||||
j.CreateAttachment(Database, creatorUser, filename, DocumentTemplate.PdfMimeType, comments, PdfContent, documentTemplate, PdfThumbnail);
|
||||
return true;
|
||||
case DocumentTemplate.DocumentTemplateScopes.User:
|
||||
User u = (User)UniqueIdentifier.Data;
|
||||
u.CreateAttachment(Database, creatorUser, filename, DocumentTemplate.PdfMimeType, comments, PdfContent, documentTemplate, PdfThumbnail);
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static string RepositoryFilename(this DeviceAttachment da, DiscoDataContext Database)
|
||||
{
|
||||
return Path.Combine(DataStore.CreateLocation(Database, "DeviceAttachments", da.Timestamp), string.Format("{0}_{1}_file", da.DeviceSerialNumber, da.Id));
|
||||
}
|
||||
public static string RepositoryFilename(this JobAttachment ja, DiscoDataContext Database)
|
||||
{
|
||||
return Path.Combine(DataStore.CreateLocation(Database, "JobAttachments", ja.Timestamp), string.Format("{0}_{1}_file", ja.JobId, ja.Id));
|
||||
}
|
||||
public static string RepositoryFilename(this UserAttachment ua, DiscoDataContext Database)
|
||||
{
|
||||
return Path.Combine(DataStore.CreateLocation(Database, "UserAttachments", ua.Timestamp), string.Format("{0}_{1}_file", ua.UserId.Replace('\\', '_'), ua.Id));
|
||||
}
|
||||
|
||||
private static string RepositoryThumbnailFilenameInternal(string DirectoryPath, string Filename)
|
||||
{
|
||||
return Path.Combine(DirectoryPath, Filename);
|
||||
}
|
||||
public static string RepositoryThumbnailFilename(this DeviceAttachment da, DiscoDataContext Database)
|
||||
{
|
||||
return RepositoryThumbnailFilenameInternal(DataStore.CreateLocation(Database, "DeviceAttachments", da.Timestamp), string.Format("{0}_{1}_thumb.jpg", da.DeviceSerialNumber, da.Id));
|
||||
}
|
||||
public static string RepositoryThumbnailFilename(this JobAttachment ja, DiscoDataContext Database)
|
||||
{
|
||||
return RepositoryThumbnailFilenameInternal(DataStore.CreateLocation(Database, "JobAttachments", ja.Timestamp), string.Format("{0}_{1}_thumb.jpg", ja.JobId, ja.Id));
|
||||
}
|
||||
public static string RepositoryThumbnailFilename(this UserAttachment ua, DiscoDataContext Database)
|
||||
{
|
||||
return RepositoryThumbnailFilenameInternal(DataStore.CreateLocation(Database, "UserAttachments", ua.Timestamp), string.Format("{0}_{1}_thumb.jpg", ua.UserId.Replace('\\', '_'), ua.Id));
|
||||
}
|
||||
|
||||
public static void RepositoryDelete(this DeviceAttachment da, DiscoDataContext Database)
|
||||
{
|
||||
RepositoryDelete(da.RepositoryFilename(Database), da.RepositoryThumbnailFilename(Database));
|
||||
}
|
||||
public static void RepositoryDelete(this JobAttachment ja, DiscoDataContext Database)
|
||||
{
|
||||
RepositoryDelete(ja.RepositoryFilename(Database), ja.RepositoryThumbnailFilename(Database));
|
||||
}
|
||||
public static void RepositoryDelete(this UserAttachment ua, DiscoDataContext Database)
|
||||
{
|
||||
RepositoryDelete(ua.RepositoryFilename(Database), ua.RepositoryThumbnailFilename(Database));
|
||||
}
|
||||
private static void RepositoryDelete(params string[] filePaths)
|
||||
{
|
||||
foreach (string filePath in filePaths)
|
||||
{
|
||||
if (File.Exists(filePath))
|
||||
File.Delete(filePath);
|
||||
}
|
||||
}
|
||||
|
||||
public static string SaveAttachment(this DeviceAttachment da, DiscoDataContext Database, Stream FileContent)
|
||||
{
|
||||
string filePath = da.RepositoryFilename(Database);
|
||||
SaveAttachment(filePath, FileContent);
|
||||
return filePath;
|
||||
}
|
||||
public static string SaveAttachment(this JobAttachment ja, DiscoDataContext Database, Stream FileContent)
|
||||
{
|
||||
string filePath = ja.RepositoryFilename(Database);
|
||||
SaveAttachment(filePath, FileContent);
|
||||
return filePath;
|
||||
}
|
||||
public static string SaveAttachment(this UserAttachment ua, DiscoDataContext Database, Stream FileContent)
|
||||
{
|
||||
string filePath = ua.RepositoryFilename(Database);
|
||||
SaveAttachment(filePath, FileContent);
|
||||
return filePath;
|
||||
}
|
||||
public static string SaveThumbnailAttachment(this DeviceAttachment da, DiscoDataContext Database, byte[] FileContent)
|
||||
{
|
||||
string filePath = da.RepositoryThumbnailFilename(Database);
|
||||
File.WriteAllBytes(filePath, FileContent);
|
||||
return filePath;
|
||||
}
|
||||
public static string SaveThumbnailAttachment(this JobAttachment ja, DiscoDataContext Database, byte[] FileContent)
|
||||
{
|
||||
string filePath = ja.RepositoryThumbnailFilename(Database);
|
||||
File.WriteAllBytes(filePath, FileContent);
|
||||
return filePath;
|
||||
}
|
||||
public static string SaveThumbnailAttachment(this UserAttachment ua, DiscoDataContext Database, byte[] FileContent)
|
||||
{
|
||||
string filePath = ua.RepositoryThumbnailFilename(Database);
|
||||
File.WriteAllBytes(filePath, FileContent);
|
||||
return filePath;
|
||||
}
|
||||
private static void SaveAttachment(string FilePath, Stream FileContent)
|
||||
{
|
||||
using (FileStream sw = new FileStream(FilePath, FileMode.Create, FileAccess.Write, FileShare.None))
|
||||
{
|
||||
FileContent.CopyTo(sw);
|
||||
sw.Flush();
|
||||
sw.Close();
|
||||
}
|
||||
}
|
||||
|
||||
public static string GenerateThumbnail(this DeviceAttachment da, DiscoDataContext Database)
|
||||
{
|
||||
string filePath = da.RepositoryThumbnailFilename(Database);
|
||||
AttachmentBI.Utilities.GenerateThumbnail(da.RepositoryFilename(Database), da.MimeType, filePath);
|
||||
return filePath;
|
||||
}
|
||||
public static string GenerateThumbnail(this JobAttachment ja, DiscoDataContext Database)
|
||||
{
|
||||
string filePath = ja.RepositoryThumbnailFilename(Database);
|
||||
AttachmentBI.Utilities.GenerateThumbnail(ja.RepositoryFilename(Database), ja.MimeType, filePath);
|
||||
return filePath;
|
||||
}
|
||||
public static string GenerateThumbnail(this UserAttachment ua, DiscoDataContext Database)
|
||||
{
|
||||
string filePath = ua.RepositoryThumbnailFilename(Database);
|
||||
AttachmentBI.Utilities.GenerateThumbnail(ua.RepositoryFilename(Database), ua.MimeType, filePath);
|
||||
return filePath;
|
||||
}
|
||||
public static string GenerateThumbnail(this DeviceAttachment da, DiscoDataContext Database, Stream SourceFile)
|
||||
{
|
||||
string filePath = da.RepositoryThumbnailFilename(Database);
|
||||
AttachmentBI.Utilities.GenerateThumbnail(SourceFile, da.MimeType, filePath);
|
||||
return filePath;
|
||||
}
|
||||
public static string GenerateThumbnail(this JobAttachment ja, DiscoDataContext Database, Stream SourceFile)
|
||||
{
|
||||
string filePath = ja.RepositoryThumbnailFilename(Database);
|
||||
AttachmentBI.Utilities.GenerateThumbnail(SourceFile, ja.MimeType, filePath);
|
||||
return filePath;
|
||||
}
|
||||
public static string GenerateThumbnail(this UserAttachment ua, DiscoDataContext Database, Stream SourceFile)
|
||||
{
|
||||
string filePath = ua.RepositoryThumbnailFilename(Database);
|
||||
AttachmentBI.Utilities.GenerateThumbnail(SourceFile, ua.MimeType, filePath);
|
||||
return filePath;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,38 +0,0 @@
|
||||
using System.Linq;
|
||||
using Disco.Data.Repository;
|
||||
using Disco.Models.Repository;
|
||||
using Disco.Services.Plugins;
|
||||
using Disco.Services.Plugins.Features.CertificateProvider;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Disco.BI.Extensions
|
||||
{
|
||||
public static class DeviceCertificateExtensions
|
||||
{
|
||||
|
||||
public static Tuple<DeviceCertificate, List<string>> AllocateCertificate(this Device device, DiscoDataContext Database)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(device.DeviceProfile.CertificateProviderId))
|
||||
{
|
||||
// Load Plugin
|
||||
PluginFeatureManifest featureManifest = Plugins.GetPluginFeature(device.DeviceProfile.CertificateProviderId, typeof(CertificateProviderFeature));
|
||||
|
||||
using (CertificateProviderFeature providerFeature = featureManifest.CreateInstance<CertificateProviderFeature>())
|
||||
{
|
||||
// REMOVED 2012-07-18 G# - Plugin is responsible for checking
|
||||
// Already Allocated Certificate
|
||||
//if (deviceCertificates.Count > 0)
|
||||
// return new Tuple<DeviceCertificate, List<string>>(deviceCertificates[0], providerPlugin.RemoveExistingCertificateNames());
|
||||
//else
|
||||
|
||||
return providerFeature.AllocateCertificate(Database, device);
|
||||
}
|
||||
}
|
||||
|
||||
// Device Profile does not allow certificate allocation
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,162 +0,0 @@
|
||||
using Disco.Models.Repository;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Disco.BI.Extensions
|
||||
{
|
||||
public static class DeviceDetailExtensions
|
||||
{
|
||||
#region Helpers
|
||||
private static string GetDetail(this IEnumerable<DeviceDetail> details, string Scope, string Key)
|
||||
{
|
||||
if (details == null)
|
||||
throw new ArgumentNullException("details");
|
||||
if (string.IsNullOrEmpty(Scope))
|
||||
throw new ArgumentNullException("Scope");
|
||||
if (string.IsNullOrEmpty(Key))
|
||||
throw new ArgumentNullException("Key");
|
||||
|
||||
var detail = details.Where(d => d.Key == Key).FirstOrDefault();
|
||||
|
||||
if (detail == null)
|
||||
return null;
|
||||
else
|
||||
return detail.Value;
|
||||
}
|
||||
|
||||
private static void SetDetail(this Device device, string Scope, string Key, string Value)
|
||||
{
|
||||
if (device == null)
|
||||
throw new ArgumentNullException("device");
|
||||
if (string.IsNullOrEmpty(Scope))
|
||||
throw new ArgumentNullException("Scope");
|
||||
if (string.IsNullOrEmpty(Key))
|
||||
throw new ArgumentNullException("Key");
|
||||
|
||||
var detail = device.DeviceDetails.Where(d => d.Scope == Scope && d.Key == Key).FirstOrDefault();
|
||||
|
||||
// No Detail Stored & Set to Null
|
||||
if (detail == null && Value == null)
|
||||
return;
|
||||
|
||||
if (detail == null)
|
||||
{
|
||||
detail = new DeviceDetail()
|
||||
{
|
||||
DeviceSerialNumber = device.SerialNumber,
|
||||
Scope = Scope,
|
||||
Key = Key,
|
||||
Value = Value
|
||||
};
|
||||
device.DeviceDetails.Add(detail);
|
||||
}
|
||||
|
||||
if (detail.Value != Value)
|
||||
{
|
||||
if (Value == null)
|
||||
{
|
||||
device.DeviceDetails.Remove(detail);
|
||||
}
|
||||
else
|
||||
{
|
||||
detail.Value = Value;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region LanMacAddress
|
||||
/// <summary>
|
||||
/// Gets the LanMacAddress Device Detail Value
|
||||
/// </summary>
|
||||
/// <returns>The LanMacAddress or null</returns>
|
||||
public static string LanMacAddress(this IEnumerable<DeviceDetail> details)
|
||||
{
|
||||
return details.GetDetail(DeviceDetail.ScopeHardware, DeviceDetail.HardwareKeyLanMacAddress);
|
||||
}
|
||||
/// <summary>
|
||||
/// Sets the LanMacAddress Device Detail Value
|
||||
/// </summary>
|
||||
public static void LanMacAddress(this IEnumerable<DeviceDetail> details, Device device, string LanMacAddress)
|
||||
{
|
||||
device.SetDetail(DeviceDetail.ScopeHardware, DeviceDetail.HardwareKeyLanMacAddress, LanMacAddress);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region WLanMacAddress
|
||||
/// <summary>
|
||||
/// Gets the WLanMacAddress Device Detail Value
|
||||
/// </summary>
|
||||
/// <returns>The WLanMacAddress or null</returns>
|
||||
public static string WLanMacAddress(this IEnumerable<DeviceDetail> details)
|
||||
{
|
||||
return details.GetDetail(DeviceDetail.ScopeHardware, DeviceDetail.HardwareKeyWLanMacAddress);
|
||||
}
|
||||
/// <summary>
|
||||
/// Sets the WLanMacAddress Device Detail Value
|
||||
/// </summary>
|
||||
public static void WLanMacAddress(this IEnumerable<DeviceDetail> details, Device device, string WLanMacAddress)
|
||||
{
|
||||
device.SetDetail(DeviceDetail.ScopeHardware, DeviceDetail.HardwareKeyWLanMacAddress, WLanMacAddress);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region ACAdapter
|
||||
/// <summary>
|
||||
/// Gets the ACAdapter Device Detail Value
|
||||
/// </summary>
|
||||
/// <returns>The ACAdapter or null</returns>
|
||||
public static string ACAdapter(this IEnumerable<DeviceDetail> details)
|
||||
{
|
||||
return details.GetDetail(DeviceDetail.ScopeHardware, DeviceDetail.HardwareKeyACAdapter);
|
||||
}
|
||||
/// <summary>
|
||||
/// Sets the ACAdapter Device Detail Value
|
||||
/// </summary>
|
||||
public static void ACAdapter(this IEnumerable<DeviceDetail> details, Device device, string ACAdapter)
|
||||
{
|
||||
device.SetDetail(DeviceDetail.ScopeHardware, DeviceDetail.HardwareKeyACAdapter, ACAdapter);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Battery
|
||||
/// <summary>
|
||||
/// Gets the Battery Device Detail Value
|
||||
/// </summary>
|
||||
/// <returns>The Battery or null</returns>
|
||||
public static string Battery(this IEnumerable<DeviceDetail> details)
|
||||
{
|
||||
return details.GetDetail(DeviceDetail.ScopeHardware, DeviceDetail.HardwareKeyBattery);
|
||||
}
|
||||
/// <summary>
|
||||
/// Sets the Battery Device Detail Value
|
||||
/// </summary>
|
||||
public static void Battery(this IEnumerable<DeviceDetail> details, Device device, string Battery)
|
||||
{
|
||||
device.SetDetail(DeviceDetail.ScopeHardware, DeviceDetail.HardwareKeyBattery, Battery);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Keyboard
|
||||
/// <summary>
|
||||
/// Gets the Keyboard Device Detail Value
|
||||
/// </summary>
|
||||
/// <returns>The Keyboard or null</returns>
|
||||
public static string Keyboard(this IEnumerable<DeviceDetail> details)
|
||||
{
|
||||
return details.GetDetail(DeviceDetail.ScopeHardware, DeviceDetail.HardwareKeyKeyboard);
|
||||
}
|
||||
/// <summary>
|
||||
/// Sets the Keyboard Device Detail Value
|
||||
/// </summary>
|
||||
public static void Keyboard(this IEnumerable<DeviceDetail> details, Device device, string Keyboard)
|
||||
{
|
||||
device.SetDetail(DeviceDetail.ScopeHardware, DeviceDetail.HardwareKeyKeyboard, Keyboard);
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -1,66 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Disco.Models.Repository;
|
||||
using Disco.Data.Repository;
|
||||
using Disco.Data.Configuration.Modules;
|
||||
using Disco.Models.BI.Config;
|
||||
using Disco.Services.Users;
|
||||
using Disco.Services.Authorization;
|
||||
|
||||
namespace Disco.BI.Extensions
|
||||
{
|
||||
public static class DeviceProfileExtensions
|
||||
{
|
||||
public const string ComputerNameExpressionCacheModule = "ComputerNameTemplate";
|
||||
|
||||
public static void ComputerNameInvalidateCache(this DeviceProfile deviceProfile)
|
||||
{
|
||||
Expressions.ExpressionCache.InvalidateKey(ComputerNameExpressionCacheModule, deviceProfile.Id.ToString());
|
||||
}
|
||||
|
||||
public static OrganisationAddress DefaultOrganisationAddressDetails(this DeviceProfile deviceProfile, DiscoDataContext Database)
|
||||
{
|
||||
if (deviceProfile.DefaultOrganisationAddress.HasValue)
|
||||
{
|
||||
return Database.DiscoConfiguration.OrganisationAddresses.GetAddress(deviceProfile.DefaultOrganisationAddress.Value);
|
||||
}
|
||||
else
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static bool CanDelete(this DeviceProfile dp, DiscoDataContext Database)
|
||||
{
|
||||
if (!UserService.CurrentAuthorization.Has(Claims.Config.DeviceProfile.Delete))
|
||||
return false;
|
||||
|
||||
// Can't Delete Default Profile (Id: 1)
|
||||
if (dp.Id == 1)
|
||||
return false;
|
||||
|
||||
// Can't Delete if Contains Devices
|
||||
if (Database.Devices.Count(d => d.DeviceProfileId == dp.Id) > 0)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
public static void Delete(this DeviceProfile dp, DiscoDataContext Database)
|
||||
{
|
||||
if (!dp.CanDelete(Database))
|
||||
throw new InvalidOperationException("The state of this Device Profile doesn't allow it to be deleted");
|
||||
|
||||
// Update Defaults
|
||||
if (Database.DiscoConfiguration.DeviceProfiles.DefaultDeviceProfileId == dp.Id)
|
||||
Database.DiscoConfiguration.DeviceProfiles.DefaultDeviceProfileId = 1;
|
||||
if (Database.DiscoConfiguration.DeviceProfiles.DefaultAddDeviceOfflineDeviceProfileId == dp.Id)
|
||||
Database.DiscoConfiguration.DeviceProfiles.DefaultAddDeviceOfflineDeviceProfileId = 1;
|
||||
|
||||
// Delete Profile
|
||||
Database.DeviceProfiles.Remove(dp);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,179 +1,129 @@
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Linq;
|
||||
using System.Web;
|
||||
using Disco.Data.Repository;
|
||||
using Disco.Models.BI.DocumentTemplates;
|
||||
using Disco.Models.Repository;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using Disco.Models.Services.Documents;
|
||||
using Disco.Services;
|
||||
using Disco.Services.Documents;
|
||||
using Disco.Services.Documents.ManagedGroups;
|
||||
using Disco.Services.Expressions;
|
||||
using Disco.Services.Interop.ActiveDirectory;
|
||||
using iTextSharp.text.pdf;
|
||||
using Disco.BI.Expressions;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.IO;
|
||||
using Disco.BI.DocumentTemplateBI;
|
||||
using System.Linq;
|
||||
|
||||
namespace Disco.BI.Extensions
|
||||
{
|
||||
public static class DocumentTemplateExtensions
|
||||
{
|
||||
private const string DocumentTemplateExpressionCacheTemplate = "DocumentTemplate_{0}";
|
||||
private static Tuple<Dictionary<string, Expression>, List<DocumentField>> CreateExpressions(DocumentTemplate dt, DiscoDataContext database)
|
||||
{
|
||||
Dictionary<string, Expression> expressions = new Dictionary<string, Expression>();
|
||||
List<DocumentField> fields = new List<DocumentField>();
|
||||
|
||||
public static string RepositoryFilename(this DocumentTemplate dt, DiscoDataContext Database)
|
||||
{
|
||||
return System.IO.Path.Combine(DataStore.CreateLocation(Database, "DocumentTemplates"), string.Format("{0}.pdf", dt.Id));
|
||||
}
|
||||
public static string SavePdfTemplate(this DocumentTemplate dt, DiscoDataContext Database, Stream TemplateFile)
|
||||
{
|
||||
string filePath = dt.RepositoryFilename(Database);
|
||||
using (FileStream fs = new FileStream(filePath, FileMode.Create, FileAccess.Write))
|
||||
string templateFilename = dt.RepositoryFilename(database);
|
||||
PdfReader pdfReader = new PdfReader(templateFilename);
|
||||
int pdfFieldOrdinal = 0;
|
||||
foreach (string pdfFieldKey in pdfReader.AcroFields.Fields.Keys)
|
||||
{
|
||||
TemplateFile.CopyTo(fs);
|
||||
}
|
||||
Expressions.ExpressionCache.InvalidModule(string.Format(DocumentTemplateExpressionCacheTemplate, dt.Id));
|
||||
return filePath;
|
||||
}
|
||||
var pdfField = pdfReader.AcroFields.Fields[pdfFieldKey];
|
||||
var pdfFieldPositions = pdfReader.AcroFields.GetFieldPositions(pdfFieldKey);
|
||||
var pdfFieldFlags = pdfField.GetMerged(0).GetAsNumber(PdfName.FF)?.IntValue ?? 0;
|
||||
var isRequired = (pdfFieldFlags & 2) == 2;
|
||||
var isReadOnly = (pdfFieldFlags & 1) == 1;
|
||||
|
||||
public static DisposableImageCollection PdfPageImages(this PdfReader pdfReader, int PageNumber)
|
||||
{
|
||||
return Interop.Pdf.PdfImporter.GetPageImages(pdfReader, PageNumber);
|
||||
}
|
||||
|
||||
public static ConcurrentDictionary<string, Expression> PdfExpressionsFromCache(this DocumentTemplate dt, DiscoDataContext Database)
|
||||
{
|
||||
string cacheModuleKey = string.Format(DocumentTemplateExpressionCacheTemplate, dt.Id);
|
||||
var module = Expressions.ExpressionCache.GetModule(cacheModuleKey);
|
||||
if (module == null)
|
||||
{
|
||||
// Cache
|
||||
string templateFilename = dt.RepositoryFilename(Database);
|
||||
PdfReader pdfReader = new PdfReader(templateFilename);
|
||||
int pdfFieldOrdinal = 0;
|
||||
foreach (string pdfFieldKey in pdfReader.AcroFields.Fields.Keys)
|
||||
var pdfFieldValue = pdfReader.AcroFields.GetField(pdfFieldKey);
|
||||
var pdfFieldPosition = default(RectangleF?);
|
||||
if (pdfFieldPositions != null && pdfFieldPositions.Count > 0)
|
||||
{
|
||||
var pdfFieldValue = pdfReader.AcroFields.GetField(pdfFieldKey);
|
||||
Expressions.ExpressionCache.SetValue(cacheModuleKey, pdfFieldKey, Expressions.Expression.Tokenize(pdfFieldKey, pdfFieldValue, pdfFieldOrdinal));
|
||||
pdfFieldOrdinal++;
|
||||
var position = pdfFieldPositions.First().position;
|
||||
pdfFieldPosition = new RectangleF(position.Left, position.Top, position.Width, position.Height);
|
||||
}
|
||||
pdfReader.Close();
|
||||
module = Expressions.ExpressionCache.GetModule(cacheModuleKey, true);
|
||||
var fieldTypeId = pdfReader.AcroFields.GetFieldType(pdfFieldKey);
|
||||
var fieldType = DocumentFieldType.None;
|
||||
if (fieldTypeId <= 8 && fieldTypeId > 0)
|
||||
fieldType = (DocumentFieldType)fieldTypeId;
|
||||
|
||||
var fixedValues = default(List<string>);
|
||||
|
||||
if (fieldType == DocumentFieldType.RadioButton || fieldType == DocumentFieldType.Checkbox)
|
||||
{
|
||||
fixedValues = pdfReader.AcroFields.GetAppearanceStates(pdfFieldKey).ToList();
|
||||
}
|
||||
|
||||
expressions[pdfFieldKey] = Expression.Tokenize(pdfFieldKey, pdfFieldValue, pdfFieldOrdinal, isRequired, isReadOnly, pdfFieldPosition);
|
||||
fields.Add(new DocumentField(pdfFieldKey, pdfFieldValue, pdfFieldOrdinal, fieldType, isRequired, isReadOnly, fixedValues));
|
||||
pdfFieldOrdinal++;
|
||||
}
|
||||
return module;
|
||||
pdfReader.Close();
|
||||
|
||||
return Tuple.Create(expressions, fields);
|
||||
}
|
||||
|
||||
public static List<BI.Expressions.Expression> ExtractPdfExpressions(this DocumentTemplate dt, DiscoDataContext Database)
|
||||
public static Dictionary<string, Expression> PdfExpressionsFromCache(this DocumentTemplate dt, DiscoDataContext Database)
|
||||
{
|
||||
return ExpressionCache.GetOrCreateExpressions(dt, () => CreateExpressions(dt, Database));
|
||||
}
|
||||
|
||||
public static List<DocumentField> PdfFieldsFromCache(this DocumentTemplate dt, DiscoDataContext Database)
|
||||
{
|
||||
return ExpressionCache.GetOrCreateFields(dt, () => CreateExpressions(dt, Database));
|
||||
}
|
||||
|
||||
public static List<Expression> ExtractPdfExpressions(this DocumentTemplate dt, DiscoDataContext Database)
|
||||
{
|
||||
return dt.PdfExpressionsFromCache(Database).Values.OrderBy(e => e.Ordinal).ToList();
|
||||
}
|
||||
public static System.IO.Stream GeneratePdfBulk(this DocumentTemplate dt, DiscoDataContext Database, User CreatorUser, System.DateTime Timestamp, params string[] DataObjectsIds)
|
||||
|
||||
public static Stream GeneratePdf(this DocumentTemplate dt, DiscoDataContext Database, IAttachmentTarget Target, User CreatorUser, DateTime TimeStamp, DocumentState State, bool FlattenFields = false)
|
||||
{
|
||||
return Interop.Pdf.PdfGenerator.GenerateBulkFromTemplate(dt, Database, CreatorUser, Timestamp, DataObjectsIds);
|
||||
bool generateExpression = !string.IsNullOrEmpty(dt.OnGenerateExpression);
|
||||
string generateExpressionResult = null;
|
||||
|
||||
if (generateExpression)
|
||||
generateExpressionResult = dt.EvaluateOnGenerateExpression(Target, Database, CreatorUser, TimeStamp, State);
|
||||
|
||||
var pdfStream = Interop.Pdf.PdfGenerator.GenerateFromTemplate(dt, Database, Target, CreatorUser, TimeStamp, State, FlattenFields);
|
||||
|
||||
if (generateExpression)
|
||||
DocumentsLog.LogDocumentGenerated(dt, Target, CreatorUser, generateExpressionResult);
|
||||
else
|
||||
DocumentsLog.LogDocumentGenerated(dt, Target, CreatorUser);
|
||||
|
||||
return pdfStream;
|
||||
}
|
||||
public static System.IO.Stream GeneratePdfBulk(this DocumentTemplate dt, DiscoDataContext Database, User CreatorUser, System.DateTime Timestamp, params object[] DataObjects)
|
||||
public static Stream GeneratePdfPackage(this DocumentTemplatePackage package, DiscoDataContext Database, IAttachmentTarget Target, User CreatorUser, DateTime TimeStamp, DocumentState State)
|
||||
{
|
||||
return Interop.Pdf.PdfGenerator.GenerateBulkFromTemplate(dt, Database, CreatorUser, Timestamp, DataObjects);
|
||||
return Interop.Pdf.PdfGenerator.GenerateFromPackage(package, Database, Target, CreatorUser, TimeStamp, State);
|
||||
}
|
||||
public static System.IO.Stream GeneratePdf(this DocumentTemplate dt, DiscoDataContext Database, object Data, User CreatorUser, System.DateTime TimeStamp, DocumentState State, bool FlattenFields = false)
|
||||
public static Stream GeneratePdfPackageBulk(this DocumentTemplatePackage package, DiscoDataContext Database, User CreatorUser, DateTime Timestamp, bool InsertBlankPages, List<string> DataObjectsIds)
|
||||
{
|
||||
return Interop.Pdf.PdfGenerator.GenerateFromTemplate(dt, Database, Data, CreatorUser, TimeStamp, State, FlattenFields);
|
||||
return Interop.Pdf.PdfGenerator.GenerateBulkFromPackage(package, Database, CreatorUser, Timestamp, InsertBlankPages, DataObjectsIds);
|
||||
}
|
||||
public static Stream GeneratePdfPackageBulk(this DocumentTemplatePackage package, DiscoDataContext Database, User CreatorUser, DateTime Timestamp, bool InsertBlankPages, List<IAttachmentTarget> DataObjects)
|
||||
{
|
||||
return Interop.Pdf.PdfGenerator.GenerateBulkFromPackage(package, Database, CreatorUser, Timestamp, InsertBlankPages, DataObjects);
|
||||
}
|
||||
|
||||
public static Expression FilterExpressionFromCache(this DocumentTemplate dt)
|
||||
public static List<bool> PdfPageHasAttachmentId(this DocumentTemplate dt, DiscoDataContext Database)
|
||||
{
|
||||
return ExpressionCache.GetValue("DocumentTemplateFilterExpression", dt.Id, () => { return Expression.TokenizeSingleDynamic(null, dt.FilterExpression, 0); });
|
||||
}
|
||||
public static void FilterExpressionInvalidateCache(this DocumentTemplate dt)
|
||||
{
|
||||
ExpressionCache.InvalidateKey("DocumentTemplateFilterExpression", dt.Id);
|
||||
}
|
||||
public static bool FilterExpressionMatches(this DocumentTemplate dt, object Data, DiscoDataContext Database, User User, System.DateTime TimeStamp, DocumentState State)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(dt.FilterExpression))
|
||||
string templateFilename = dt.RepositoryFilename(Database);
|
||||
if (!File.Exists(templateFilename))
|
||||
throw new FileNotFoundException("PDF template not found", templateFilename);
|
||||
|
||||
PdfReader pdfReader = new PdfReader(templateFilename);
|
||||
var result = new bool[pdfReader.NumberOfPages];
|
||||
var fieldNames = pdfReader.AcroFields.Fields.Keys.Where(key => key.Equals("DiscoAttachmentId", StringComparison.OrdinalIgnoreCase)).ToList();
|
||||
var fieldPositions = fieldNames.SelectMany(name => pdfReader.AcroFields.GetFieldPositions(name));
|
||||
foreach (var fieldPosition in fieldPositions)
|
||||
{
|
||||
Expression compiledExpression = dt.FilterExpressionFromCache();
|
||||
System.Collections.IDictionary evaluatorVariables = Expression.StandardVariables(dt, Database, User, TimeStamp, State);
|
||||
try
|
||||
{
|
||||
object er = compiledExpression.EvaluateFirst<object>(Data, evaluatorVariables);
|
||||
if (er is bool)
|
||||
{
|
||||
return (bool)er;
|
||||
}
|
||||
bool erBool;
|
||||
if (bool.TryParse(er.ToString(), out erBool))
|
||||
{
|
||||
return erBool;
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
return false;
|
||||
}
|
||||
result[fieldPosition.page - 1] = true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
public static string GetDataId(this DocumentTemplate dt, object Data)
|
||||
{
|
||||
if (Data is string)
|
||||
{
|
||||
return (string)Data;
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (dt.Scope)
|
||||
{
|
||||
case Models.Repository.DocumentTemplate.DocumentTemplateScopes.Device:
|
||||
if (!(Data is Device))
|
||||
throw new ArgumentException("This Document Template is configured for Devices only", "Data");
|
||||
Device d = (Device)Data;
|
||||
return d.SerialNumber;
|
||||
case Models.Repository.DocumentTemplate.DocumentTemplateScopes.Job:
|
||||
if (!(Data is Job))
|
||||
throw new ArgumentException("This Document Template is configured for Jobs only", "Data");
|
||||
Job d2 = (Job)Data;
|
||||
return d2.Id.ToString();
|
||||
case Models.Repository.DocumentTemplate.DocumentTemplateScopes.User:
|
||||
if (!(Data is User))
|
||||
throw new ArgumentException("This Document Template is configured for Users only", "Data");
|
||||
User d3 = (User)Data;
|
||||
return d3.UserId;
|
||||
default:
|
||||
throw new InvalidOperationException("Invalid Document Template Scope");
|
||||
}
|
||||
}
|
||||
}
|
||||
public static string UniqueIdentifier(string DocumentTemplateId, string DataId, string CreatorId, System.DateTime Timestamp)
|
||||
{
|
||||
return string.Format("Disco|1|{0}|{1}|{2}|{3:s}",
|
||||
DocumentTemplateId,
|
||||
DataId,
|
||||
CreatorId,
|
||||
Timestamp
|
||||
);
|
||||
}
|
||||
public static string UniqueIdentifier(this DocumentTemplate dt, object Data, string CreatorId, System.DateTime Timestamp)
|
||||
{
|
||||
return string.Format("Disco|1|{0}|{1}|{2}|{3:s}",
|
||||
dt.Id,
|
||||
dt.GetDataId(System.Runtime.CompilerServices.RuntimeHelpers.GetObjectValue(Data)),
|
||||
CreatorId,
|
||||
Timestamp
|
||||
);
|
||||
}
|
||||
public static string UniquePageIdentifier(this DocumentTemplate dt, object Data, string CreatorId, System.DateTime Timestamp, int Page)
|
||||
{
|
||||
return string.Format("Disco|1|{0}|{1}|{2}|{3:s}|{4}",
|
||||
dt.Id,
|
||||
dt.GetDataId(System.Runtime.CompilerServices.RuntimeHelpers.GetObjectValue(Data)),
|
||||
CreatorId,
|
||||
Timestamp,
|
||||
Page
|
||||
);
|
||||
}
|
||||
public static List<RectangleF> QRCodeLocations(this DocumentTemplate dt, DiscoDataContext Database)
|
||||
{
|
||||
return DocumentTemplateBI.DocumentTemplateQRCodeLocationCache.GetLocations(dt, Database);
|
||||
pdfReader.Close();
|
||||
return result.ToList();
|
||||
}
|
||||
|
||||
public static void Delete(this DocumentTemplate dt, DiscoDataContext Database)
|
||||
{
|
||||
// Find & Rename all references
|
||||
@@ -202,6 +152,10 @@ namespace Disco.BI.Extensions
|
||||
a.DocumentTemplate = null;
|
||||
}
|
||||
|
||||
// Remove Linked Group
|
||||
ActiveDirectory.Context.ManagedGroups.Remove(DocumentTemplateDevicesManagedGroup.GetKey(dt));
|
||||
ActiveDirectory.Context.ManagedGroups.Remove(DocumentTemplateUsersManagedGroup.GetKey(dt));
|
||||
|
||||
// Delete SubTypes
|
||||
dt.JobSubTypes.Clear();
|
||||
|
||||
|
||||
@@ -1,232 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Disco.Models.Repository;
|
||||
using Disco.Data.Repository;
|
||||
using System.IO;
|
||||
using Disco.Models.BI.DocumentTemplates;
|
||||
using Disco.Services.Plugins;
|
||||
using Disco.Models.BI.Job;
|
||||
using Disco.Services.Authorization;
|
||||
|
||||
namespace Disco.BI.Extensions
|
||||
{
|
||||
public static class JobExtensions
|
||||
{
|
||||
public static JobAttachment CreateAttachment(this Job Job, DiscoDataContext Database, User CreatorUser, string Filename, string MimeType, string Comments, Stream Content, DocumentTemplate DocumentTemplate = null, byte[] PdfThumbnail = null)
|
||||
{
|
||||
if (string.IsNullOrEmpty(MimeType) || MimeType.Equals("unknown/unknown", StringComparison.OrdinalIgnoreCase))
|
||||
MimeType = Interop.MimeTypes.ResolveMimeType(Filename);
|
||||
|
||||
JobAttachment ja = new JobAttachment()
|
||||
{
|
||||
JobId = Job.Id,
|
||||
TechUserId = CreatorUser.UserId,
|
||||
Filename = Filename,
|
||||
MimeType = MimeType,
|
||||
Timestamp = DateTime.Now,
|
||||
Comments = Comments
|
||||
};
|
||||
|
||||
if (DocumentTemplate != null)
|
||||
ja.DocumentTemplateId = DocumentTemplate.Id;
|
||||
|
||||
Database.JobAttachments.Add(ja);
|
||||
Database.SaveChanges();
|
||||
|
||||
ja.SaveAttachment(Database, Content);
|
||||
Content.Position = 0;
|
||||
if (PdfThumbnail == null)
|
||||
ja.GenerateThumbnail(Database, Content);
|
||||
else
|
||||
ja.SaveThumbnailAttachment(Database, PdfThumbnail);
|
||||
|
||||
return ja;
|
||||
}
|
||||
|
||||
public static List<DocumentTemplate> AvailableDocumentTemplates(this Job j, DiscoDataContext Database, User User, DateTime TimeStamp)
|
||||
{
|
||||
var dts = Database.DocumentTemplates.Include("JobSubTypes")
|
||||
.Where(dt => dt.Scope == DocumentTemplate.DocumentTemplateScopes.Job)
|
||||
.ToList();
|
||||
|
||||
foreach (var dt in dts.ToArray())
|
||||
{
|
||||
if (dt.JobSubTypes.Count != 0)
|
||||
{ // Filter Applied
|
||||
bool match = false;
|
||||
foreach (var st in j.JobSubTypes)
|
||||
{
|
||||
if (dt.JobSubTypes.Contains(st))
|
||||
{
|
||||
match = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!match)
|
||||
dts.Remove(dt);
|
||||
}
|
||||
}
|
||||
|
||||
// Evaluate Filters
|
||||
dts = dts.Where(dt => dt.FilterExpressionMatches(j, Database, User, TimeStamp, DocumentState.DefaultState())).ToList();
|
||||
|
||||
return dts;
|
||||
}
|
||||
|
||||
public static DateTime ValidateDateAfterOpened(this Job j, DateTime d)
|
||||
{
|
||||
if (d < j.OpenedDate)
|
||||
{
|
||||
if (d > j.OpenedDate.AddMinutes(-1))
|
||||
return j.OpenedDate;
|
||||
else
|
||||
throw new ArgumentException("The Date must be >= the Open Date.", "d");
|
||||
}
|
||||
return d;
|
||||
}
|
||||
|
||||
public static string GenerateFaultDescription(this Job j, DiscoDataContext Database)
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
sb.AppendLine("Faulty Components:");
|
||||
foreach (var jst in j.JobSubTypes)
|
||||
sb.Append("- ").AppendLine(jst.Description).AppendLine(" - ");
|
||||
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
public static string GenerateFaultDescriptionFooter(this Job j, DiscoDataContext Database, PluginFeatureManifest WarrantyProviderDefinition)
|
||||
{
|
||||
var versionDisco = System.Reflection.Assembly.GetExecutingAssembly().GetName().Version;
|
||||
return string.Format("Automation by Disco v{0}.{1}.{2:0000}.{3:0000} (Provider: {4} v{5})",
|
||||
versionDisco.Major, versionDisco.Minor, versionDisco.Build, versionDisco.Revision, WarrantyProviderDefinition.Id, WarrantyProviderDefinition.PluginManifest.Version.ToString(4));
|
||||
}
|
||||
|
||||
public static void UpdateSubTypes(this Job j, DiscoDataContext Database, List<JobSubType> SubTypes, bool AddComponents, User TechUser)
|
||||
{
|
||||
if (SubTypes == null || SubTypes.Count == 0)
|
||||
throw new ArgumentException("The Job must contain at least one Sub Type");
|
||||
|
||||
List<JobSubType> addedSubTypes = new List<JobSubType>();
|
||||
List<JobSubType> removedSubTypes = new List<JobSubType>();
|
||||
|
||||
// Removed Sub Types
|
||||
foreach (var t in j.JobSubTypes.ToArray())
|
||||
if (!SubTypes.Contains(t))
|
||||
{
|
||||
removedSubTypes.Add(t);
|
||||
j.JobSubTypes.Remove(t);
|
||||
}
|
||||
// Added Sub Types
|
||||
foreach (var t in SubTypes)
|
||||
if (!j.JobSubTypes.Contains(t))
|
||||
{
|
||||
addedSubTypes.Add(t);
|
||||
j.JobSubTypes.Add(t);
|
||||
}
|
||||
|
||||
// Write Log
|
||||
if (addedSubTypes.Count > 0 || removedSubTypes.Count > 0)
|
||||
{
|
||||
StringBuilder logBuilder = new StringBuilder();
|
||||
logBuilder.AppendLine("Updated Job Sub Types");
|
||||
if (removedSubTypes.Count > 0)
|
||||
{
|
||||
logBuilder.AppendLine("Removed:");
|
||||
foreach (var t in removedSubTypes)
|
||||
logBuilder.Append("- ").AppendLine(t.ToString());
|
||||
}
|
||||
if (addedSubTypes.Count > 0)
|
||||
{
|
||||
logBuilder.AppendLine("Added:");
|
||||
foreach (var t in addedSubTypes)
|
||||
logBuilder.Append("- ").AppendLine(t.ToString());
|
||||
}
|
||||
Database.JobLogs.Add(new JobLog()
|
||||
{
|
||||
JobId = j.Id,
|
||||
TechUserId = TechUser.UserId,
|
||||
Timestamp = DateTime.Now,
|
||||
Comments = logBuilder.ToString()
|
||||
});
|
||||
}
|
||||
|
||||
// Add Components
|
||||
if (AddComponents && addedSubTypes.Count > 0 && j.DeviceSerialNumber != null)
|
||||
{
|
||||
var components = Database.DeviceComponents.Include("JobSubTypes").Where(c => !c.DeviceModelId.HasValue || c.DeviceModelId == j.Device.DeviceModelId);
|
||||
var addedComponents = new List<DeviceComponent>();
|
||||
foreach (var c in components)
|
||||
{
|
||||
foreach (var st in c.JobSubTypes)
|
||||
{
|
||||
foreach (var jst in addedSubTypes)
|
||||
{
|
||||
if (st.JobTypeId == jst.JobTypeId && st.Id == jst.Id)
|
||||
{
|
||||
addedComponents.Add(c);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (addedComponents.Contains(c))
|
||||
break;
|
||||
}
|
||||
}
|
||||
foreach (var c in addedComponents)
|
||||
{
|
||||
if (!j.JobComponents.Any(jc => jc.Description.Equals(c.Description, StringComparison.OrdinalIgnoreCase)))
|
||||
{ // Job Component with matching Description doesn't exist.
|
||||
Database.JobComponents.Add(new JobComponent()
|
||||
{
|
||||
Job = j,
|
||||
TechUserId = TechUser.UserId,
|
||||
Cost = c.Cost,
|
||||
Description = c.Description
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static List<string> FilterCreatableTypePermissions(AuthorizationToken Authorization)
|
||||
{
|
||||
if (!Authorization.HasAll(Claims.Job.Types.CreateHMisc, Claims.Job.Types.CreateHNWar, Claims.Job.Types.CreateHWar, Claims.Job.Types.CreateSApp, Claims.Job.Types.CreateSImg, Claims.Job.Types.CreateSOS, Claims.Job.Types.CreateUMgmt))
|
||||
{
|
||||
// Must Filter
|
||||
List<string> allowedTypes = new List<string>(6);
|
||||
if (Authorization.Has(Claims.Job.Types.CreateHMisc))
|
||||
allowedTypes.Add(JobType.JobTypeIds.HMisc);
|
||||
if (Authorization.Has(Claims.Job.Types.CreateHNWar))
|
||||
allowedTypes.Add(JobType.JobTypeIds.HNWar);
|
||||
if (Authorization.Has(Claims.Job.Types.CreateHWar))
|
||||
allowedTypes.Add(JobType.JobTypeIds.HWar);
|
||||
if (Authorization.Has(Claims.Job.Types.CreateSApp))
|
||||
allowedTypes.Add(JobType.JobTypeIds.SApp);
|
||||
if (Authorization.Has(Claims.Job.Types.CreateSImg))
|
||||
allowedTypes.Add(JobType.JobTypeIds.SImg);
|
||||
if (Authorization.Has(Claims.Job.Types.CreateSOS))
|
||||
allowedTypes.Add(JobType.JobTypeIds.SOS);
|
||||
if (Authorization.Has(Claims.Job.Types.CreateUMgmt))
|
||||
allowedTypes.Add(JobType.JobTypeIds.UMgmt);
|
||||
|
||||
return allowedTypes;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static IQueryable<JobType> FilterCreatableTypePermissions(this IQueryable<JobType> JobTypes, AuthorizationToken Authorization)
|
||||
{
|
||||
var allowedTypes = FilterCreatableTypePermissions(Authorization);
|
||||
|
||||
if (allowedTypes != null)
|
||||
{
|
||||
return JobTypes.Where(jt => allowedTypes.Contains(jt.Id));
|
||||
}
|
||||
|
||||
return JobTypes;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,73 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Disco.Models.Repository;
|
||||
using Disco.Data.Repository;
|
||||
using System.IO;
|
||||
using Disco.Models.BI.DocumentTemplates;
|
||||
using Disco.Services.Interop.ActiveDirectory;
|
||||
|
||||
namespace Disco.BI.Extensions
|
||||
{
|
||||
public static class UserExtensions
|
||||
{
|
||||
public static UserAttachment CreateAttachment(this User User, DiscoDataContext Database, User CreatorUser, string Filename, string MimeType, string Comments, Stream Content, DocumentTemplate DocumentTemplate = null, byte[] PdfThumbnail = null)
|
||||
{
|
||||
if (string.IsNullOrEmpty(MimeType) || MimeType.Equals("unknown/unknown", StringComparison.OrdinalIgnoreCase))
|
||||
MimeType = Interop.MimeTypes.ResolveMimeType(Filename);
|
||||
|
||||
UserAttachment ua = new UserAttachment()
|
||||
{
|
||||
UserId = User.UserId,
|
||||
TechUserId = CreatorUser.UserId,
|
||||
Filename = Filename,
|
||||
MimeType = MimeType,
|
||||
Timestamp = DateTime.Now,
|
||||
Comments = Comments
|
||||
};
|
||||
|
||||
if (DocumentTemplate != null)
|
||||
ua.DocumentTemplateId = DocumentTemplate.Id;
|
||||
|
||||
Database.UserAttachments.Add(ua);
|
||||
Database.SaveChanges();
|
||||
|
||||
ua.SaveAttachment(Database, Content);
|
||||
Content.Position = 0;
|
||||
if (PdfThumbnail == null)
|
||||
ua.GenerateThumbnail(Database, Content);
|
||||
else
|
||||
ua.SaveThumbnailAttachment(Database, PdfThumbnail);
|
||||
|
||||
return ua;
|
||||
}
|
||||
|
||||
public static List<DocumentTemplate> AvailableDocumentTemplates(this User u, DiscoDataContext Database, User User, DateTime TimeStamp)
|
||||
{
|
||||
var dts = Database.DocumentTemplates.Include("JobSubTypes")
|
||||
.Where(dt => dt.Scope == DocumentTemplate.DocumentTemplateScopes.User)
|
||||
.ToArray()
|
||||
.Where(dt => dt.FilterExpressionMatches(u, Database, User, TimeStamp, DocumentState.DefaultState())).ToList();
|
||||
|
||||
return dts;
|
||||
}
|
||||
|
||||
public static List<DeviceUserAssignment> CurrentDeviceUserAssignments(this User u)
|
||||
{
|
||||
return u.DeviceUserAssignments.Where(dua => !dua.UnassignedDate.HasValue).ToList();
|
||||
}
|
||||
public static ADUserAccount ActiveDirectoryAccount(this User User, params string[] AdditionalProperties)
|
||||
{
|
||||
return ActiveDirectory.RetrieveADUserAccount(User.UserId, AdditionalProperties);
|
||||
}
|
||||
|
||||
public static bool CanCreateJob(this User u)
|
||||
{
|
||||
if (!JobActionExtensions.CanCreate())
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,85 +0,0 @@
|
||||
using Disco.Data.Repository;
|
||||
using Disco.Models.Repository;
|
||||
using Disco.Services.Authorization;
|
||||
using Disco.Services.Users;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Disco.BI.Extensions
|
||||
{
|
||||
public static class UserFlagActionExtensions
|
||||
{
|
||||
|
||||
#region Edit Comments
|
||||
public static bool CanEditComments(this UserFlagAssignment fa)
|
||||
{
|
||||
return UserService.CurrentAuthorization.Has(Claims.User.Actions.EditFlags);
|
||||
}
|
||||
public static void OnEditComments(this UserFlagAssignment fa, string Comments)
|
||||
{
|
||||
if (!fa.CanEditComments())
|
||||
throw new InvalidOperationException("Editing comments for user flags is denied");
|
||||
|
||||
fa.Comments = string.IsNullOrWhiteSpace(Comments) ? null : Comments.Trim();
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Remove
|
||||
public static bool CanRemove(this UserFlagAssignment fa)
|
||||
{
|
||||
if (fa.RemovedDate.HasValue)
|
||||
return false;
|
||||
|
||||
return UserService.CurrentAuthorization.Has(Claims.User.Actions.RemoveFlags);
|
||||
}
|
||||
public static void OnRemove(this UserFlagAssignment fa, User Technician)
|
||||
{
|
||||
if (!fa.CanRemove())
|
||||
throw new InvalidOperationException("Removing user flags is denied");
|
||||
|
||||
fa.RemovedDate = DateTime.Now;
|
||||
fa.RemovedUserId = Technician.UserId;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Add
|
||||
public static bool CanAddUserFlags(this User u)
|
||||
{
|
||||
return UserService.CurrentAuthorization.Has(Claims.User.Actions.AddFlags);
|
||||
}
|
||||
public static bool CanAddUserFlag(this User u, UserFlag flag)
|
||||
{
|
||||
// Shortcut
|
||||
if (!u.CanAddUserFlags())
|
||||
return false;
|
||||
|
||||
// Already has User Flag?
|
||||
if (u.UserFlagAssignments.Any(fa => !fa.RemovedDate.HasValue && fa.UserFlagId == flag.Id))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
public static UserFlagAssignment OnAddUserFlag(this User u, DiscoDataContext Database, UserFlag flag, User Technician, string Comments)
|
||||
{
|
||||
if (!u.CanAddUserFlag(flag))
|
||||
throw new InvalidOperationException("Adding user flag is denied");
|
||||
|
||||
var fa = new UserFlagAssignment()
|
||||
{
|
||||
UserFlagId = flag.Id,
|
||||
UserId = u.UserId,
|
||||
AddedDate = DateTime.Now,
|
||||
AddedUserId = Technician.UserId,
|
||||
Comments = string.IsNullOrWhiteSpace(Comments) ? null : Comments.Trim()
|
||||
};
|
||||
|
||||
Database.UserFlagAssignments.Add(fa);
|
||||
return fa;
|
||||
}
|
||||
#endregion
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
using Disco.Models.Repository;
|
||||
using System;
|
||||
using System.Security.Cryptography.X509Certificates;
|
||||
namespace Disco.BI.Extensions
|
||||
{
|
||||
public static class WirelessCertificateExtensions
|
||||
{
|
||||
public static System.DateTime? CertificateExpirationDate(this DeviceCertificate wc)
|
||||
{
|
||||
if (wc.Content == null || wc.Content.Length == 0)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
X509Certificate2 c = new X509Certificate2(wc.Content, "password");
|
||||
return c.NotAfter;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,188 +0,0 @@
|
||||
using Disco.Data.Repository;
|
||||
using Disco.Models.BI.Interop.Community;
|
||||
using Disco.Models.Repository;
|
||||
using Disco.Services.Tasks;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Xml.Linq;
|
||||
using System.Xml.Serialization;
|
||||
|
||||
namespace Disco.BI.Interop.Community
|
||||
{
|
||||
public static class UpdateCheck
|
||||
{
|
||||
private static string UpdateUrl()
|
||||
{
|
||||
return string.Concat(Disco.Data.Configuration.CommunityHelpers.CommunityUrl(), "DiscoUpdate/V1");
|
||||
}
|
||||
|
||||
public static Version CurrentDiscoVersion()
|
||||
{
|
||||
return typeof(UpdateCheck).Assembly.GetName().Version;
|
||||
}
|
||||
public static string CurrentDiscoVersionFormatted()
|
||||
{
|
||||
var v = CurrentDiscoVersion();
|
||||
return string.Format("{0}.{1}.{2:0000}.{3:0000}", v.Major, v.Minor, v.Build, v.Revision);
|
||||
}
|
||||
|
||||
public static UpdateResponse Check(DiscoDataContext Database, bool UseProxy, IScheduledTaskStatus status)
|
||||
{
|
||||
status.UpdateStatus(10, "Building Update Request");
|
||||
|
||||
var request = BuildRequest(Database);
|
||||
|
||||
status.UpdateStatus(40, "Sending Request");
|
||||
|
||||
var DiscoBIVersion = CurrentDiscoVersionFormatted();
|
||||
|
||||
HttpWebRequest webRequest = (HttpWebRequest)HttpWebRequest.Create(UpdateUrl());
|
||||
|
||||
// Added: 2013-02-08 G#
|
||||
// Fix for Proxy Servers which dont support KeepAlive
|
||||
webRequest.KeepAlive = false;
|
||||
// End Added: 2013-02-08 G#
|
||||
|
||||
if (!UseProxy)
|
||||
webRequest.Proxy = new WebProxy();
|
||||
|
||||
webRequest.ContentType = "application/json";
|
||||
webRequest.Method = WebRequestMethods.Http.Post;
|
||||
webRequest.UserAgent = string.Format("Disco/{0} (Update)", DiscoBIVersion);
|
||||
|
||||
using (var wrStream = webRequest.GetRequestStream())
|
||||
{
|
||||
XmlSerializer xml = new XmlSerializer(typeof(UpdateRequestV1));
|
||||
xml.Serialize(wrStream, request);
|
||||
}
|
||||
status.UpdateStatus(50, "Waiting for Response");
|
||||
using (HttpWebResponse webResponse = (HttpWebResponse)webRequest.GetResponse())
|
||||
{
|
||||
if (webResponse.StatusCode == HttpStatusCode.OK)
|
||||
{
|
||||
status.UpdateStatus(90, "Reading Response");
|
||||
UpdateResponse result;
|
||||
using (var wResStream = webResponse.GetResponseStream())
|
||||
{
|
||||
XmlSerializer xml = new XmlSerializer(typeof(UpdateResponse));
|
||||
result = (UpdateResponse)xml.Deserialize(wResStream);
|
||||
}
|
||||
Database.DiscoConfiguration.UpdateLastCheck = result;
|
||||
Database.SaveChanges();
|
||||
|
||||
status.SetFinishedMessage(string.Format("The update server reported Version {0} is the latest.", result.Version));
|
||||
|
||||
return result;
|
||||
}
|
||||
else
|
||||
{
|
||||
status.SetTaskException(new WebException(string.Format("Server responded with: [{0}] {1}", webResponse.StatusCode, webResponse.StatusDescription)));
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static UpdateRequestV1 BuildRequest(DiscoDataContext Database)
|
||||
{
|
||||
var m = new UpdateRequestV1();
|
||||
|
||||
m.DeploymentId = Database.DiscoConfiguration.DeploymentId;
|
||||
|
||||
m.CurrentDiscoVersion = CurrentDiscoVersionFormatted();
|
||||
|
||||
m.OrganisationName = Database.DiscoConfiguration.OrganisationName;
|
||||
m.BroadbandDoeWanId = GetBroadbandDoeWanId();
|
||||
m.BetaDeployment = Database.DiscoConfiguration.UpdateBetaDeployment;
|
||||
|
||||
m.Stat_JobCounts = Database.Jobs.GroupBy(j => j.JobTypeId).Select(g => new Disco.Models.BI.Interop.Community.UpdateRequestV1.Stat { Key = g.Key, Count = g.Count() }).ToList();
|
||||
m.Stat_OpenJobCounts = Database.Jobs.Where(j => j.ClosedDate == null).GroupBy(j => j.JobTypeId).Select(g => new Disco.Models.BI.Interop.Community.UpdateRequestV1.Stat { Key = g.Key, Count = g.Count() }).ToList();
|
||||
m.Stat_DeviceModelCounts = Database.DeviceModels.Select(dm => new Disco.Models.BI.Interop.Community.UpdateRequestV1.Stat { Key = dm.Manufacturer + ";" + dm.Model, Count = dm.Devices.Count(d => d.DecommissionedDate == null) }).ToList();
|
||||
var activeThreshold = DateTime.Now.AddDays(-60);
|
||||
m.Stat_ActiveDeviceModelCounts = Database.DeviceModels.Select(dm => new Disco.Models.BI.Interop.Community.UpdateRequestV1.Stat { Key = dm.Manufacturer + ";" + dm.Model, Count = dm.Devices.Count(d => d.DecommissionedDate == null && (d.LastNetworkLogonDate == null || d.LastNetworkLogonDate > activeThreshold)) }).ToList();
|
||||
m.Stat_UserCounts = new List<UpdateRequestV1.Stat>() {
|
||||
new UpdateRequestV1.Stat(){
|
||||
Key = "All Users",
|
||||
Count = Database.Users.Count()
|
||||
}
|
||||
};
|
||||
|
||||
m.Stat_JobWarrantyVendorCounts = Database.Jobs.Where(j => j.JobTypeId == JobType.JobTypeIds.HWar && j.JobMetaWarranty.ExternalLoggedDate.HasValue && j.JobMetaWarranty.ExternalName != null).GroupBy(j => j.JobMetaWarranty.ExternalName).Select(g => new Disco.Models.BI.Interop.Community.UpdateRequestV1.Stat { Key = g.Key ?? "<Unknown>", Count = g.Count() }).ToList();
|
||||
|
||||
m.InstalledPlugins = Disco.Services.Plugins.Plugins.GetPlugins().Select(manifest => new Disco.Models.BI.Interop.Community.UpdateRequestV1.PluginRef { Id = manifest.Id, Version = manifest.VersionFormatted }).ToList();
|
||||
|
||||
return m;
|
||||
}
|
||||
|
||||
#region DoE Query
|
||||
public static string GetBroadbandDoeWanId()
|
||||
{
|
||||
// DnsQuery for broadband.doe.wan
|
||||
IPHostEntry doeWanDnsEntry;
|
||||
try
|
||||
{
|
||||
doeWanDnsEntry = Dns.GetHostEntry("broadband.doe.wan");
|
||||
}
|
||||
catch (Exception)
|
||||
{ return null; } // Fail on error
|
||||
|
||||
// Try using IPSearch feature
|
||||
XDocument doeWanIPSearchResult = TryDownloadDoeIPSearch(false);
|
||||
if (doeWanIPSearchResult == null)
|
||||
doeWanIPSearchResult = TryDownloadDoeIPSearch(true);
|
||||
|
||||
if (doeWanIPSearchResult == null)
|
||||
return null;
|
||||
|
||||
try
|
||||
{
|
||||
return doeWanIPSearchResult.Element("resultset").Element("site").Element("number").Value.ToLower();
|
||||
}
|
||||
catch (Exception)
|
||||
{ return null; } // Fail on error
|
||||
}
|
||||
private static XDocument TryDownloadDoeIPSearch(bool useProxy)
|
||||
{
|
||||
try
|
||||
{
|
||||
var DiscoBIVersion = CurrentDiscoVersionFormatted();
|
||||
|
||||
HttpWebRequest wReq = (HttpWebRequest)HttpWebRequest.Create("http://broadband.doe.wan/ipsearch/showresult.php");
|
||||
// Added: 2013-02-08 G#
|
||||
// Fix for Proxy Servers which dont support KeepAlive
|
||||
wReq.KeepAlive = false;
|
||||
// End Added: 2013-02-08 G#
|
||||
if (!useProxy)
|
||||
wReq.Proxy = new WebProxy(); // Empty Proxy Config
|
||||
wReq.Method = WebRequestMethods.Http.Post;
|
||||
wReq.ContentType = "application/x-www-form-urlencoded";
|
||||
wReq.UserAgent = string.Format("Disco/{0}", DiscoBIVersion);
|
||||
using (var wrStream = wReq.GetRequestStream())
|
||||
{
|
||||
using (var wrStreamWriter = new StreamWriter(wrStream))
|
||||
{
|
||||
wrStreamWriter.Write("mode=whoami");
|
||||
}
|
||||
}
|
||||
using (HttpWebResponse wRes = (HttpWebResponse)wReq.GetResponse())
|
||||
{
|
||||
if (wRes.StatusCode == HttpStatusCode.OK)
|
||||
{
|
||||
using (var wResStream = wRes.GetResponseStream())
|
||||
{
|
||||
return XDocument.Load(wResStream);
|
||||
}
|
||||
}
|
||||
else
|
||||
return null;
|
||||
}
|
||||
}
|
||||
catch (Exception)
|
||||
{ return null; } // Fail on error
|
||||
}
|
||||
#endregion
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,15 +1,18 @@
|
||||
using Disco.BI.Expressions;
|
||||
using Disco.BI.Extensions;
|
||||
using Disco.BI.Extensions;
|
||||
using Disco.Data.Repository;
|
||||
using Disco.Models.BI.DocumentTemplates;
|
||||
using Disco.Models.BI.Expressions;
|
||||
using Disco.Models.Repository;
|
||||
using Disco.Models.Services.Documents;
|
||||
using Disco.Models.Services.Expressions.Extensions;
|
||||
using Disco.Services;
|
||||
using Disco.Services.Documents;
|
||||
using Disco.Services.Expressions;
|
||||
using Disco.Services.Interop.ActiveDirectory;
|
||||
using Disco.Services.Tasks;
|
||||
using Disco.Services.Users;
|
||||
using iTextSharp.text.pdf;
|
||||
using iTextSharp.text.pdf.codec;
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
@@ -18,16 +21,118 @@ namespace Disco.BI.Interop.Pdf
|
||||
{
|
||||
public static class PdfGenerator
|
||||
{
|
||||
|
||||
public static System.IO.Stream GenerateBulkFromTemplate(DocumentTemplate dt, DiscoDataContext Database, User CreatorUser, System.DateTime Timestamp, params object[] DataObjects)
|
||||
public static Stream GenerateBulkFromPackage(DocumentTemplatePackage package, DiscoDataContext Database, User CreatorUser, DateTime Timestamp, bool InsertBlankPages, List<IAttachmentTarget> DataObjects)
|
||||
{
|
||||
if (DataObjects.Length > 0)
|
||||
if (DataObjects.Count > 0)
|
||||
{
|
||||
List<Stream> generatedPdfs = new List<Stream>(DataObjects.Length);
|
||||
using (Models.BI.DocumentTemplates.DocumentState state = Models.BI.DocumentTemplates.DocumentState.DefaultState())
|
||||
List<Stream> generatedPdfs = new List<Stream>(DataObjects.Count);
|
||||
using (var state = DocumentState.DefaultState())
|
||||
{
|
||||
foreach (object d in DataObjects)
|
||||
foreach (var d in DataObjects)
|
||||
{
|
||||
generatedPdfs.Add(package.GeneratePdfPackage(Database, d, CreatorUser, Timestamp, state));
|
||||
state.SequenceNumber++;
|
||||
state.FlushScopeCache();
|
||||
}
|
||||
}
|
||||
if (generatedPdfs.Count == 1)
|
||||
{
|
||||
return generatedPdfs[0];
|
||||
}
|
||||
else
|
||||
{
|
||||
Stream bulkPdf = Utilities.JoinPdfs(package.InsertBlankPages || InsertBlankPages, generatedPdfs);
|
||||
foreach (Stream singlePdf in generatedPdfs)
|
||||
singlePdf.Dispose();
|
||||
return bulkPdf;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static Stream GenerateBulkFromPackage(DocumentTemplatePackage package, DiscoDataContext Database, User CreatorUser, DateTime Timestamp, bool InsertBlankPages, List<string> DataObjectsIds)
|
||||
{
|
||||
List<IAttachmentTarget> DataObjects;
|
||||
|
||||
switch (package.Scope)
|
||||
{
|
||||
case AttachmentTypes.Device:
|
||||
DataObjects = Database.Devices.Where(d => DataObjectsIds.Contains(d.SerialNumber)).ToList<IAttachmentTarget>();
|
||||
break;
|
||||
case AttachmentTypes.Job:
|
||||
int[] intDataObjectsIds = DataObjectsIds.Select(i => int.Parse(i)).ToArray();
|
||||
DataObjects = Database.Jobs.Where(j => intDataObjectsIds.Contains(j.Id)).ToList<IAttachmentTarget>();
|
||||
break;
|
||||
case AttachmentTypes.User:
|
||||
DataObjects = new List<IAttachmentTarget>(DataObjectsIds.Count);
|
||||
for (int idIndex = 0; idIndex < DataObjectsIds.Count; idIndex++)
|
||||
{
|
||||
string dataObjectId = DataObjectsIds[idIndex];
|
||||
var user = UserService.GetUser(ActiveDirectory.ParseDomainAccountId(dataObjectId), Database, true);
|
||||
if (user == null)
|
||||
throw new Exception($"Unknown Username specified: {dataObjectId}");
|
||||
DataObjects.Add(user);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
throw new InvalidOperationException("Invalid DocumentType Scope");
|
||||
}
|
||||
|
||||
return GenerateBulkFromPackage(package, Database, CreatorUser, Timestamp, InsertBlankPages, DataObjects);
|
||||
}
|
||||
|
||||
public static Stream GenerateFromPackage(DocumentTemplatePackage package, DiscoDataContext Database, IAttachmentTarget Data, User CreatorUser, DateTime Timestamp, DocumentState State)
|
||||
{
|
||||
var templates = package.GetDocumentTemplates(Database);
|
||||
|
||||
if (templates.Count == 0)
|
||||
return null;
|
||||
|
||||
bool generateExpression = !string.IsNullOrEmpty(package.OnGenerateExpression);
|
||||
string generateExpressionResult = null;
|
||||
|
||||
if (generateExpression)
|
||||
generateExpressionResult = package.EvaluateOnGenerateExpression(Data, Database, CreatorUser, Timestamp, State);
|
||||
|
||||
List<Stream> generatedPdfs = new List<Stream>(templates.Count);
|
||||
foreach (var template in templates)
|
||||
{
|
||||
generatedPdfs.Add(template.GeneratePdf(Database, Data, CreatorUser, Timestamp, State, true));
|
||||
|
||||
State.SequenceNumber++;
|
||||
State.FlushScopeCache();
|
||||
}
|
||||
|
||||
if (generateExpression)
|
||||
DocumentsLog.LogDocumentPackageGenerated(package, Data, CreatorUser, generateExpressionResult);
|
||||
else
|
||||
DocumentsLog.LogDocumentPackageGenerated(package, Data, CreatorUser);
|
||||
|
||||
if (generatedPdfs.Count == 1)
|
||||
{
|
||||
return generatedPdfs[0];
|
||||
}
|
||||
else
|
||||
{
|
||||
Stream bulkPdf = Utilities.JoinPdfs(package.InsertBlankPages, generatedPdfs);
|
||||
foreach (Stream singlePdf in generatedPdfs)
|
||||
singlePdf.Dispose();
|
||||
return bulkPdf;
|
||||
}
|
||||
}
|
||||
public static Stream GenerateBulkFromTemplate(DocumentTemplate dt, DiscoDataContext Database, User CreatorUser, DateTime Timestamp, bool InsertBlankPages, List<IAttachmentTarget> DataObjects, IScheduledTaskStatus taskStatus)
|
||||
{
|
||||
if (DataObjects.Count > 0)
|
||||
{
|
||||
List<Stream> generatedPdfs = new List<Stream>(DataObjects.Count);
|
||||
var progressPerDoc = 80d / DataObjects.Count;
|
||||
var progressDoc = 10d;
|
||||
using (var state = DocumentState.DefaultState())
|
||||
{
|
||||
taskStatus.UpdateStatus(10, "Rendering", "Starting");
|
||||
foreach (var d in DataObjects)
|
||||
{
|
||||
taskStatus.UpdateStatus(progressDoc += progressPerDoc, $"Rendering {d.AttachmentReferenceId}");
|
||||
generatedPdfs.Add(dt.GeneratePdf(Database, d, CreatorUser, Timestamp, state, true));
|
||||
state.SequenceNumber++;
|
||||
state.FlushScopeCache();
|
||||
@@ -39,7 +144,8 @@ namespace Disco.BI.Interop.Pdf
|
||||
}
|
||||
else
|
||||
{
|
||||
Stream bulkPdf = DocumentTemplateBI.Utilities.JoinPdfs(generatedPdfs.ToArray());
|
||||
taskStatus.UpdateStatus(90, "Merging", "Merging documents");
|
||||
Stream bulkPdf = Utilities.JoinPdfs(InsertBlankPages, generatedPdfs);
|
||||
foreach (Stream singlePdf in generatedPdfs)
|
||||
singlePdf.Dispose();
|
||||
return bulkPdf;
|
||||
@@ -48,38 +154,60 @@ namespace Disco.BI.Interop.Pdf
|
||||
return null;
|
||||
}
|
||||
|
||||
public static System.IO.Stream GenerateBulkFromTemplate(DocumentTemplate dt, DiscoDataContext Database, User CreatorUser, System.DateTime Timestamp, params string[] DataObjectsIds)
|
||||
public static Stream GenerateBulkFromTemplate(DocumentTemplate dt, DiscoDataContext Database, User CreatorUser, DateTime Timestamp, bool InsertBlankPages, List<string> DataObjectsIds, IScheduledTaskStatus taskStatus)
|
||||
{
|
||||
object[] DataObjects;
|
||||
Dictionary<string, IAttachmentTarget> dataObjectLookup;
|
||||
List<string> dataObjectIds = DataObjectsIds;
|
||||
|
||||
taskStatus.UpdateStatus(0, "Resolving targets", "Resolving render targets");
|
||||
|
||||
switch (dt.Scope)
|
||||
{
|
||||
case DocumentTemplate.DocumentTemplateScopes.Device:
|
||||
DataObjects = Database.Devices.Where(d => DataObjectsIds.Contains(d.SerialNumber)).ToArray();
|
||||
dataObjectLookup = Database.Devices.Where(d => DataObjectsIds.Contains(d.SerialNumber)).AsEnumerable().Cast<IAttachmentTarget>().ToDictionary(i => i.AttachmentReferenceId, StringComparer.OrdinalIgnoreCase);
|
||||
break;
|
||||
case DocumentTemplate.DocumentTemplateScopes.Job:
|
||||
int[] intDataObjectsIds = DataObjectsIds.Select(i => int.Parse(i)).ToArray();
|
||||
DataObjects = Database.Jobs.Where(j => intDataObjectsIds.Contains(j.Id)).ToArray();
|
||||
var intDataObjectsIds = DataObjectsIds.Select(i => int.Parse(i)).ToList();
|
||||
dataObjectLookup = Database.Jobs.Where(j => intDataObjectsIds.Contains(j.Id)).AsEnumerable().Cast<IAttachmentTarget>().ToDictionary(i => i.AttachmentReferenceId, StringComparer.OrdinalIgnoreCase);
|
||||
break;
|
||||
case DocumentTemplate.DocumentTemplateScopes.User:
|
||||
DataObjects = new object[DataObjectsIds.Length];
|
||||
for (int idIndex = 0; idIndex < DataObjectsIds.Length; idIndex++)
|
||||
dataObjectLookup = new Dictionary<string, IAttachmentTarget>(DataObjectsIds.Count, StringComparer.OrdinalIgnoreCase);
|
||||
dataObjectIds = new List<string>(DataObjectsIds.Count);
|
||||
foreach (var userId in DataObjectsIds)
|
||||
{
|
||||
string dataObjectId = DataObjectsIds[idIndex];
|
||||
|
||||
DataObjects[idIndex] = UserService.GetUser(ActiveDirectory.ParseDomainAccountId(dataObjectId), Database, true);
|
||||
if (DataObjects[idIndex] == null)
|
||||
throw new Exception(string.Format("Unknown Username specified: {0}", dataObjectId));
|
||||
var user = UserService.GetUser(ActiveDirectory.ParseDomainAccountId(userId), Database, true);
|
||||
if (user == null)
|
||||
{
|
||||
dataObjectIds.Add(userId);
|
||||
continue;
|
||||
}
|
||||
dataObjectIds.Add(user.UserId);
|
||||
dataObjectLookup.Add(user.UserId, user);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
throw new InvalidOperationException("Invalid DocumentType Scope");
|
||||
}
|
||||
|
||||
return GenerateBulkFromTemplate(dt, Database, CreatorUser, Timestamp, DataObjects);
|
||||
// recreate list to honor the sort-order provided in DataObjectsIds
|
||||
var dataObjects = new List<IAttachmentTarget>(DataObjectsIds.Count);
|
||||
var missingIds = new List<string>();
|
||||
foreach (var id in dataObjectIds)
|
||||
{
|
||||
if (dataObjectLookup.TryGetValue(id, out var dataObject))
|
||||
dataObjects.Add(dataObject);
|
||||
else
|
||||
missingIds.Add(id);
|
||||
}
|
||||
if (missingIds.Any())
|
||||
{
|
||||
throw new Exception($"Unknown id specified: {string.Join("; ", missingIds)}");
|
||||
}
|
||||
|
||||
return GenerateBulkFromTemplate(dt, Database, CreatorUser, Timestamp, InsertBlankPages, dataObjects, taskStatus);
|
||||
}
|
||||
|
||||
public static System.IO.Stream GenerateFromTemplate(DocumentTemplate dt, DiscoDataContext Database, object Data, User CreatorUser, System.DateTime TimeStamp, DocumentState State, bool FlattenFields = false)
|
||||
public static Stream GenerateFromTemplate(DocumentTemplate dt, DiscoDataContext Database, IAttachmentTarget Data, User CreatorUser, DateTime TimeStamp, DocumentState State, bool FlattenFields = false)
|
||||
{
|
||||
// Validate Data
|
||||
switch (dt.Scope)
|
||||
@@ -106,7 +234,7 @@ namespace Disco.BI.Interop.Pdf
|
||||
if (dt.FlattenForm)
|
||||
FlattenFields = true;
|
||||
|
||||
ConcurrentDictionary<string, Expression> expressionCache = dt.PdfExpressionsFromCache(Database);
|
||||
var expressionCache = dt.PdfExpressionsFromCache(Database);
|
||||
|
||||
string templateFilename = dt.RepositoryFilename(Database);
|
||||
PdfReader pdfReader = new PdfReader(templateFilename);
|
||||
@@ -117,16 +245,16 @@ namespace Disco.BI.Interop.Pdf
|
||||
pdfStamper.FormFlattening = FlattenFields;
|
||||
pdfStamper.Writer.CloseStream = false;
|
||||
|
||||
IDictionary expressionVariables = Expression.StandardVariables(dt, Database, CreatorUser, TimeStamp, State);
|
||||
IDictionary expressionVariables = Expression.StandardVariables(dt, Database, CreatorUser, TimeStamp, State, Data);
|
||||
|
||||
foreach (string pdfFieldKey in pdfStamper.AcroFields.Fields.Keys)
|
||||
{
|
||||
if (pdfFieldKey.Equals("DiscoAttachmentId", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
AcroFields.Item fields = pdfStamper.AcroFields.Fields[pdfFieldKey];
|
||||
string fieldValue = dt.UniqueIdentifier(Data, CreatorUser.UserId, TimeStamp);
|
||||
string fieldValue = dt.CreateUniqueIdentifier(Database, Data, CreatorUser, TimeStamp, 0).ToJson();
|
||||
if (FlattenFields)
|
||||
pdfStamper.AcroFields.SetField(pdfFieldKey, String.Empty);
|
||||
pdfStamper.AcroFields.SetField(pdfFieldKey, string.Empty);
|
||||
else
|
||||
pdfStamper.AcroFields.SetField(pdfFieldKey, fieldValue);
|
||||
|
||||
@@ -134,11 +262,22 @@ namespace Disco.BI.Interop.Pdf
|
||||
for (int pdfFieldOrdinal = 0; pdfFieldOrdinal < fields.Size; pdfFieldOrdinal++)
|
||||
{
|
||||
AcroFields.FieldPosition pdfFieldPosition = pdfFieldPositions[pdfFieldOrdinal];
|
||||
string pdfBarcodeContent = dt.UniquePageIdentifier(Data, CreatorUser.UserId, TimeStamp, pdfFieldPosition.page);
|
||||
BarcodeQRCode pdfBarcode = new BarcodeQRCode(pdfBarcodeContent, (int)pdfFieldPosition.position.Width, (int)pdfFieldPosition.position.Height, null);
|
||||
iTextSharp.text.Image pdfBarcodeImage = pdfBarcode.GetImage();
|
||||
pdfBarcodeImage.SetAbsolutePosition(pdfFieldPosition.position.Left, pdfFieldPosition.position.Bottom);
|
||||
pdfStamper.GetOverContent(pdfFieldPosition.page).AddImage(pdfBarcodeImage);
|
||||
|
||||
// Create Binary Unique Identifier
|
||||
var pageUniqueId = dt.CreateUniqueIdentifier(Database, Data, CreatorUser, TimeStamp, pdfFieldPosition.page);
|
||||
var pageUniqueIdBytes = pageUniqueId.ToQRCodeBytes();
|
||||
|
||||
// Encode to QRCode byte array
|
||||
var pageUniqueIdEncoded = QRCodeBinaryEncoder.Encode(pageUniqueIdBytes, out var qrWidth, out var qrHeight);
|
||||
|
||||
// Encode byte array to Image
|
||||
var pageUniqueIdImageData = CCITTG4Encoder.Compress(pageUniqueIdEncoded, qrWidth, qrHeight);
|
||||
var pageUniqueIdImage = iTextSharp.text.Image.GetInstance(qrWidth, qrHeight, false, 256, 1, pageUniqueIdImageData, null);
|
||||
|
||||
// Add to the pdf page
|
||||
pageUniqueIdImage.SetAbsolutePosition(pdfFieldPosition.position.Left, pdfFieldPosition.position.Bottom);
|
||||
pageUniqueIdImage.ScaleToFit(pdfFieldPosition.position.Width, pdfFieldPosition.position.Height);
|
||||
pdfStamper.GetOverContent(pdfFieldPosition.page).AddImage(pageUniqueIdImage);
|
||||
}
|
||||
// Hide Fields
|
||||
PdfDictionary field = fields.GetValue(0);
|
||||
@@ -175,8 +314,24 @@ namespace Disco.BI.Interop.Pdf
|
||||
for (int pdfFieldOrdinal = 0; pdfFieldOrdinal < fields.Size; pdfFieldOrdinal++)
|
||||
{
|
||||
AcroFields.FieldPosition pdfFieldPosition = pdfFieldPositions[pdfFieldOrdinal];
|
||||
iTextSharp.text.Image pdfImage = iTextSharp.text.Image.GetInstance(imageResult.GetImage((int)pdfFieldPosition.position.Width, (int)pdfFieldPosition.position.Height));
|
||||
|
||||
iTextSharp.text.Image pdfImage;
|
||||
var imageWidth = (int)(pdfFieldPosition.position.Width * 1.6);
|
||||
var imageHeight = (int)(pdfFieldPosition.position.Height * 1.6);
|
||||
if (imageResult.Format == ImageExpressionFormat.Jpeg || imageResult.Format == ImageExpressionFormat.Png)
|
||||
{
|
||||
pdfImage = iTextSharp.text.Image.GetInstance(imageResult.GetImage(imageWidth, imageHeight));
|
||||
}
|
||||
else if (imageResult.Format == ImageExpressionFormat.CcittG4)
|
||||
{
|
||||
var imageData = imageResult.GetImage(out imageWidth, out imageHeight);
|
||||
pdfImage = iTextSharp.text.Image.GetInstance(imageWidth, imageHeight, false, 256, 1, imageData.GetBuffer(), null);
|
||||
}
|
||||
else
|
||||
throw new NotSupportedException($"Unexpected image format {imageResult.Format}");
|
||||
|
||||
pdfImage.SetAbsolutePosition(pdfFieldPosition.position.Left, pdfFieldPosition.position.Bottom);
|
||||
pdfImage.ScaleToFit(pdfFieldPosition.position.Width, pdfFieldPosition.position.Height);
|
||||
pdfStamper.GetOverContent(pdfFieldPosition.page).AddImage(pdfImage);
|
||||
}
|
||||
if (!fieldExpressionResult.Item2 && !imageResult.ShowField)
|
||||
@@ -242,7 +397,7 @@ namespace Disco.BI.Interop.Pdf
|
||||
TechUserId = CreatorUser.UserId,
|
||||
Timestamp = DateTime.Now
|
||||
};
|
||||
jl.Comments = string.Format("Document Generated{0}{1} [{2}]", Environment.NewLine, dt.Description, dt.Id);
|
||||
jl.Comments = string.Format("# Document Generated\r\n**{0}** [{1}]", dt.Description, dt.Id);
|
||||
Database.JobLogs.Add(jl);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,971 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using iTextSharp.text.pdf;
|
||||
using System.IO;
|
||||
using System.Drawing;
|
||||
using Disco.BI.DocumentTemplateBI.Importer;
|
||||
using Disco.BI.DocumentTemplateBI;
|
||||
using System.Drawing.Drawing2D;
|
||||
using com.google.zxing;
|
||||
using com.google.zxing.multi.qrcode;
|
||||
using Disco.Data.Repository;
|
||||
using System.Web.Caching;
|
||||
using Disco.BI.Extensions;
|
||||
using Disco.Models.Repository;
|
||||
using System.Collections;
|
||||
using com.google.zxing.common;
|
||||
using BitMiracle.LibTiff.Classic;
|
||||
using System.Drawing.Imaging;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Disco.BI.Interop.Pdf
|
||||
{
|
||||
public static class PdfImporter
|
||||
{
|
||||
public static RectangleF CalculateLocationRatio(this Result zxingResult, int ImageWidth, int ImageHeight)
|
||||
{
|
||||
var orderedPoints = zxingResult.ResultPoints.OrderBy(p => p.X * p.Y).ToArray();
|
||||
var topLeftPoint = orderedPoints.First();
|
||||
var bottomRightPoint = orderedPoints.Last();
|
||||
|
||||
var x = topLeftPoint.X;
|
||||
var y = topLeftPoint.Y;
|
||||
var width = bottomRightPoint.X - x;
|
||||
var height = bottomRightPoint.Y - y;
|
||||
|
||||
return new RectangleF(
|
||||
(float)System.Math.Min(1.0, System.Math.Max(0.0, (double)(x / ImageWidth) - 0.05)),
|
||||
(float)System.Math.Min(1.0, System.Math.Max(0.0, (double)(y / ImageHeight) - 0.05)),
|
||||
(float)System.Math.Min(1.0, System.Math.Max(0.0, (double)(width / ImageWidth) + 0.1)),
|
||||
(float)System.Math.Min(1.0, System.Math.Max(0.0, (double)(height / ImageHeight) + 0.1))
|
||||
);
|
||||
}
|
||||
|
||||
private class DetectImageResult : IDisposable
|
||||
{
|
||||
public Result Result { get; set; }
|
||||
public Point ResultOffset { get; set; }
|
||||
public double ResultScale { get; set; }
|
||||
|
||||
public float CalculateRotation()
|
||||
{
|
||||
var p1 = this.Result.ResultPoints[0];
|
||||
var p2 = this.Result.ResultPoints[1];
|
||||
double rotOpposite = p1.X - p2.X;
|
||||
double rotAdjacent = p1.Y - p2.Y;
|
||||
float rotation = 0;
|
||||
|
||||
if (rotOpposite != 0 || rotAdjacent != 0)
|
||||
{
|
||||
rotation = (float)(Math.Atan2(rotOpposite, rotAdjacent) * (180 / Math.PI)); // Degrees
|
||||
}
|
||||
|
||||
return rotation;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
// Do Nothing; yet...
|
||||
}
|
||||
}
|
||||
|
||||
private class DetectStateHints
|
||||
{
|
||||
public List<Tuple<RectangleF, Rotation>> PriorDetections { get; set; }
|
||||
|
||||
public DetectStateHints()
|
||||
{
|
||||
this.PriorDetections = new List<Tuple<RectangleF, Rotation>>();
|
||||
}
|
||||
}
|
||||
|
||||
private enum Rotation
|
||||
{
|
||||
None = 0,
|
||||
Degrees90 = 1,
|
||||
DegreesNeg90 = 2,
|
||||
Degrees180 = 3
|
||||
}
|
||||
|
||||
private class DetectPageResult : IDisposable
|
||||
{
|
||||
public int PageNumber { get; set; }
|
||||
public DocumentUniqueIdentifier DetectedIdentifier { get; set; }
|
||||
public Disco.BI.Extensions.UtilityExtensions.ImageMontage ThumbnailImage { get; set; }
|
||||
public MemoryStream AttachmentThumbnailImage { get; set; }
|
||||
public Disco.BI.Extensions.UtilityExtensions.ImageMontage UndetectedPageImage { get; set; }
|
||||
|
||||
public void DrawThumbnailImageResult(DetectImageResult Result, Image DetectedImage)
|
||||
{
|
||||
if (Result.Result.ResultPoints.Length == 4)
|
||||
{ // Draw Square on Thumbnail
|
||||
using (Graphics thumbnailGraphics = Graphics.FromImage(ThumbnailImage.Montage))
|
||||
{
|
||||
var thumbnailOffset = ThumbnailImage.MontageSourceImageOffsets[DetectedImage];
|
||||
|
||||
var linePoints = Result.Result.ResultPoints.Select(p => new Point((int)(thumbnailOffset + ((Result.ResultOffset.X + p.X) * Result.ResultScale * ThumbnailImage.MontageScale)), (int)((p.Y + Result.ResultOffset.Y) * Result.ResultScale * ThumbnailImage.MontageScale))).ToArray();
|
||||
using (GraphicsPath graphicsPath = new GraphicsPath())
|
||||
{
|
||||
for (int linePointIndex = 0; linePointIndex < (linePoints.Length - 1); linePointIndex++)
|
||||
graphicsPath.AddLine(linePoints[linePointIndex], linePoints[linePointIndex + 1]);
|
||||
graphicsPath.AddLine(linePoints[linePoints.Length - 1], linePoints[0]);
|
||||
using (SolidBrush graphicsBrush = new SolidBrush(Color.FromArgb(128, 255, 0, 0)))
|
||||
thumbnailGraphics.FillPath(graphicsBrush, graphicsPath);
|
||||
using (Pen graphicsPen = new Pen(Color.FromArgb(200, 255, 0, 0), 2))
|
||||
thumbnailGraphics.DrawPath(graphicsPen, graphicsPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
if (ThumbnailImage != null)
|
||||
{
|
||||
ThumbnailImage.Dispose();
|
||||
ThumbnailImage = null;
|
||||
}
|
||||
if (AttachmentThumbnailImage != null)
|
||||
{
|
||||
AttachmentThumbnailImage.Dispose();
|
||||
AttachmentThumbnailImage = null;
|
||||
}
|
||||
if (UndetectedPageImage != null)
|
||||
{
|
||||
UndetectedPageImage.Dispose();
|
||||
UndetectedPageImage = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static Tuple<Result, Rectangle, Rotation> DetectImageFromSegment(Bitmap pageImage, QRCodeMultiReader zxingReader, Hashtable zxingReaderHints, RectangleF LocationPercentage, Rotation Rotation)
|
||||
{
|
||||
System.Drawing.Rectangle region;
|
||||
|
||||
switch (Rotation)
|
||||
{
|
||||
case Rotation.None: // Original Position
|
||||
region = new Rectangle(
|
||||
(int)(pageImage.Width * LocationPercentage.Left),
|
||||
(int)(pageImage.Height * LocationPercentage.Top),
|
||||
(int)(pageImage.Width * LocationPercentage.Width),
|
||||
(int)(pageImage.Height * LocationPercentage.Height));
|
||||
break;
|
||||
case Rotation.Degrees90: // Clockwise 90 degrees
|
||||
region = new Rectangle(
|
||||
(int)(pageImage.Width - (pageImage.Width * (LocationPercentage.Top + LocationPercentage.Height))),
|
||||
(int)(pageImage.Height * LocationPercentage.Left),
|
||||
(int)(pageImage.Width * LocationPercentage.Height),
|
||||
(int)(pageImage.Height * LocationPercentage.Width));
|
||||
break;
|
||||
case Rotation.DegreesNeg90: // Anti-clockwise 90 degrees
|
||||
region = new Rectangle(
|
||||
(int)(pageImage.Width * LocationPercentage.Top),
|
||||
(int)(pageImage.Height - (pageImage.Height * (LocationPercentage.Left + LocationPercentage.Width))),
|
||||
(int)(pageImage.Width * LocationPercentage.Height),
|
||||
(int)(pageImage.Height * LocationPercentage.Width));
|
||||
break;
|
||||
case Rotation.Degrees180: // 180 degrees
|
||||
region = new Rectangle(
|
||||
(int)(pageImage.Width - (pageImage.Width * (LocationPercentage.Left + LocationPercentage.Width))),
|
||||
(int)(pageImage.Height - (pageImage.Height * (LocationPercentage.Top + LocationPercentage.Height))),
|
||||
(int)(pageImage.Width * LocationPercentage.Width),
|
||||
(int)(pageImage.Height * LocationPercentage.Height));
|
||||
break;
|
||||
default:
|
||||
throw new InvalidOperationException("Unknown Rotation");
|
||||
}
|
||||
|
||||
LuminanceSource zxingSource;
|
||||
using (Bitmap pageImageRegion = new Bitmap(region.Width, region.Height))
|
||||
{
|
||||
pageImageRegion.SetResolution(pageImage.HorizontalResolution, pageImage.VerticalResolution);
|
||||
|
||||
using (Graphics pageImageRegionGraphics = Graphics.FromImage(pageImageRegion))
|
||||
{
|
||||
pageImageRegionGraphics.DrawImage(pageImage, 0, 0, region, GraphicsUnit.Pixel);
|
||||
}
|
||||
|
||||
zxingSource = new BitmapLuminanceSource(pageImageRegion);
|
||||
}
|
||||
var zxingHB = new HybridBinarizer(zxingSource);
|
||||
var zxingBB = new BinaryBitmap(zxingHB);
|
||||
try
|
||||
{
|
||||
var zxingResult = zxingReader.decode(zxingBB, zxingReaderHints);
|
||||
if (zxingResult != null)
|
||||
return new Tuple<Result, Rectangle, Rotation>(zxingResult, region, Rotation);
|
||||
}
|
||||
catch (ReaderException)
|
||||
{
|
||||
// Ignore Location Errors
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static DetectImageResult DetectImage(DiscoDataContext Database, Bitmap pageImageOriginal, string SessionId, IEnumerable<DocumentTemplate> detectDocumentTemplates, DetectStateHints StateHints)
|
||||
{
|
||||
Bitmap pageImage = pageImageOriginal;
|
||||
double pageImageModifiedScale = 1;
|
||||
|
||||
try
|
||||
{
|
||||
// Resize if Resolution > 80; Set to 72 Dpi
|
||||
if (pageImage.HorizontalResolution > 80 || pageImage.VerticalResolution > 80)
|
||||
{
|
||||
pageImageModifiedScale = pageImage.HorizontalResolution / 72;
|
||||
int newWidth = (int)((72 / pageImage.HorizontalResolution) * pageImage.Width);
|
||||
int newHeight = (int)((72 / pageImage.VerticalResolution) * pageImage.Height);
|
||||
|
||||
pageImage = pageImage.ResizeImage(newWidth, newHeight);
|
||||
}
|
||||
|
||||
Tuple<Result, Rectangle, Rotation> result = default(Tuple<Result, Rectangle, Rotation>);
|
||||
QRCodeMultiReader zxingMfr = new QRCodeMultiReader();
|
||||
Hashtable zxingMfrHints = new Hashtable();
|
||||
zxingMfrHints.Add(DecodeHintType.TRY_HARDER, true);
|
||||
|
||||
|
||||
// Look in previously found locations
|
||||
if (StateHints.PriorDetections.Count > 0)
|
||||
{
|
||||
foreach (var previousLocation in StateHints.PriorDetections)
|
||||
{
|
||||
result = DetectImageFromSegment(pageImage, zxingMfr, zxingMfrHints,
|
||||
previousLocation.Item1, previousLocation.Item2);
|
||||
if (result != null)
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (result == null)
|
||||
{
|
||||
// Try the whole image
|
||||
var zxingSource = new BitmapLuminanceSource(pageImage);
|
||||
var zxingHB = new HybridBinarizer(zxingSource);
|
||||
var zxingBB = new BinaryBitmap(zxingHB);
|
||||
try
|
||||
{
|
||||
var zxingResult = zxingMfr.decode(zxingBB, zxingMfrHints);
|
||||
if (zxingResult != null)
|
||||
{
|
||||
result = new Tuple<Result, Rectangle, Rotation>(zxingResult, new Rectangle(0, 0, pageImage.Width, pageImage.Height), Rotation.None);
|
||||
|
||||
StateHints.PriorDetections.Insert(0, new Tuple<RectangleF, Rotation>(
|
||||
result.Item1.CalculateLocationRatio(pageImage.Width, pageImage.Height)
|
||||
, Rotation.None));
|
||||
|
||||
}
|
||||
}
|
||||
catch (ReaderException)
|
||||
{
|
||||
// Ignore Errors
|
||||
}
|
||||
}
|
||||
if (result == null)
|
||||
{
|
||||
// Look in 'Known' locations
|
||||
for (int rotationIndex = 0; rotationIndex < 4; rotationIndex++)
|
||||
{
|
||||
foreach (DocumentTemplate dt in detectDocumentTemplates)
|
||||
{
|
||||
var locationBag = dt.QRCodeLocations(Database);
|
||||
foreach (var location in locationBag)
|
||||
{
|
||||
result = DetectImageFromSegment(pageImage, zxingMfr, zxingMfrHints,
|
||||
location, (Rotation)rotationIndex);
|
||||
|
||||
StateHints.PriorDetections.Insert(0, new Tuple<RectangleF, Rotation>(location, (Rotation)rotationIndex));
|
||||
}
|
||||
if (result != null)
|
||||
break;
|
||||
}
|
||||
if (result != null)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (result != null)
|
||||
|
||||
return new DetectImageResult() { Result = result.Item1, ResultOffset = result.Item2.Location, ResultScale = pageImageModifiedScale };
|
||||
else
|
||||
return null;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw ex;
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (pageImageOriginal != pageImage)
|
||||
pageImage.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
private static DetectPageResult DetectPage(DiscoDataContext Database, PdfReader pdfReader, int PageNumber, string SessionId, string DataStoreSessionCacheLocation, IEnumerable<DocumentTemplate> detectDocumentTemplates, DetectStateHints StateHints)
|
||||
{
|
||||
DetectPageResult result = new DetectPageResult() { PageNumber = PageNumber };
|
||||
|
||||
DocumentImporterLog.LogImportPageProgress(SessionId, PageNumber, 10, "Loading Page Images");
|
||||
|
||||
using (DisposableImageCollection pageImages = pdfReader.PdfPageImages(PageNumber))
|
||||
{
|
||||
if (pageImages.Count > 0)
|
||||
{
|
||||
result.ThumbnailImage = pageImages.BuildImageMontage(256, 256);
|
||||
var pageThumbnailFilename = Path.Combine(DataStoreSessionCacheLocation, string.Format("{0}-{1}", SessionId, PageNumber));
|
||||
|
||||
result.ThumbnailImage.Montage.SavePng(pageThumbnailFilename);
|
||||
DocumentImporterLog.LogImportPageImageUpdate(SessionId, PageNumber);
|
||||
|
||||
double pageProgressInterval = 90 / pageImages.Count;
|
||||
|
||||
foreach (var pageImageOriginal in pageImages)
|
||||
{
|
||||
DocumentImporterLog.LogImportPageProgress(SessionId, PageNumber, (int)(10 + (pageProgressInterval * pageImages.IndexOf(pageImageOriginal))), String.Format("Processing Page Image {0} of {1}", pageImages.IndexOf(pageImageOriginal) + 1, pageImages.Count));
|
||||
|
||||
using (var zxingResult = DetectImage(Database, pageImageOriginal, SessionId, detectDocumentTemplates, StateHints))
|
||||
{
|
||||
if (zxingResult != null)
|
||||
{
|
||||
if (DocumentUniqueIdentifier.IsDocumentUniqueIdentifier(zxingResult.Result.Text))
|
||||
{
|
||||
float imageRotation = zxingResult.CalculateRotation();
|
||||
|
||||
result.DrawThumbnailImageResult(zxingResult, pageImageOriginal);
|
||||
|
||||
if (imageRotation != 0)
|
||||
{
|
||||
var preImageRotation = result.ThumbnailImage.Montage;
|
||||
result.ThumbnailImage.Montage = result.ThumbnailImage.Montage.RotateImage(imageRotation);
|
||||
preImageRotation.Dispose();
|
||||
}
|
||||
|
||||
result.ThumbnailImage.Montage.SavePng(pageThumbnailFilename);
|
||||
DocumentImporterLog.LogImportPageImageUpdate(SessionId, PageNumber);
|
||||
|
||||
result.AttachmentThumbnailImage = new MemoryStream();
|
||||
using (var attachmentThumbImage = pageImages.BuildImageMontage(48, 48, true))
|
||||
{
|
||||
using (Image mimeTypeIcon = Disco.Properties.Resources.MimeType_pdf16)
|
||||
attachmentThumbImage.Montage.EmbedIconOverlay(mimeTypeIcon);
|
||||
|
||||
if (imageRotation != 0)
|
||||
{
|
||||
var preImageRotation = attachmentThumbImage.Montage;
|
||||
attachmentThumbImage.Montage = attachmentThumbImage.Montage.RotateImage(imageRotation, Brushes.White);
|
||||
preImageRotation.Dispose();
|
||||
}
|
||||
|
||||
attachmentThumbImage.Montage.SaveJpg(95, result.AttachmentThumbnailImage);
|
||||
}
|
||||
|
||||
result.DetectedIdentifier = new DocumentUniqueIdentifier(zxingResult.Result.Text, PageNumber.ToString());
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Page Unassigned
|
||||
result.UndetectedPageImage = pageImages.BuildImageMontage(700, 700);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
public static bool ProcessPdfAttachment(string Filename, DiscoDataContext Database, string SessionId, Cache HttpCache)
|
||||
{
|
||||
var dataStoreUnassignedLocation = DataStore.CreateLocation(Database, "DocumentDropBox_Unassigned");
|
||||
|
||||
DocumentImporterLog.LogImportProgress(SessionId, 0, "Reading File");
|
||||
|
||||
using (FileStream fs = new FileStream(Filename, FileMode.Open, FileAccess.ReadWrite, FileShare.None))
|
||||
{
|
||||
var pdfReader = new PdfReader(fs);
|
||||
|
||||
var pdfPagesAssigned = new Dictionary<int, Tuple<DocumentUniqueIdentifier, byte[]>>();
|
||||
|
||||
var dataStoreSessionPagesCacheLocation = DataStore.CreateLocation(Database, "Cache\\DocumentDropBox_SessionPages");
|
||||
var detectDocumentTemplates = Database.DocumentTemplates.ToArray();
|
||||
|
||||
double progressInterval = 70 / pdfReader.NumberOfPages;
|
||||
|
||||
DetectStateHints detectStateHints = new DetectStateHints();
|
||||
|
||||
for (int PageNumber = 1; PageNumber <= pdfReader.NumberOfPages; PageNumber++)
|
||||
{
|
||||
DocumentImporterLog.LogImportProgress(SessionId, (int)(PageNumber * progressInterval), string.Format("Processing Page {0} of {1}", PageNumber, pdfReader.NumberOfPages));
|
||||
DocumentImporterLog.LogImportPageStarting(SessionId, PageNumber);
|
||||
|
||||
using (var pageResult = DetectPage(Database, pdfReader, PageNumber, SessionId, dataStoreSessionPagesCacheLocation, detectDocumentTemplates, detectStateHints))
|
||||
{
|
||||
if (pageResult.DetectedIdentifier != null)
|
||||
{
|
||||
var docId = pageResult.DetectedIdentifier;
|
||||
pdfPagesAssigned.Add(PageNumber, new Tuple<DocumentUniqueIdentifier, byte[]>(docId, pageResult.AttachmentThumbnailImage.ToArray()));
|
||||
|
||||
docId.LoadComponents(Database);
|
||||
DocumentImporterLog.LogImportPageDetected(SessionId, PageNumber, docId.TemplateTypeId, docId.DocumentTemplate.Description, docId.DocumentTemplate.Scope, docId.DataId, docId.DataDescription);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Undetected Page - Write Preview-Images while still in Memory
|
||||
DocumentImporterLog.LogImportPageUndetected(SessionId, PageNumber);
|
||||
|
||||
// Thumbnail:
|
||||
string unassignedImageThumbnailFilename = Path.Combine(dataStoreUnassignedLocation, string.Format("{0}_{1}_thumbnail.png", SessionId, PageNumber));
|
||||
pageResult.ThumbnailImage.Montage.SavePng(unassignedImageThumbnailFilename);
|
||||
// Large Preview
|
||||
string unassignedImageFilename = Path.Combine(dataStoreUnassignedLocation, string.Format("{0}_{1}.jpg", SessionId, PageNumber));
|
||||
pageResult.UndetectedPageImage.Montage.SaveJpg(90, unassignedImageFilename);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Write out Assigned Documents
|
||||
var assignedDocuments = pdfPagesAssigned.GroupBy(u => u.Value.Item1.DocumentUniqueId).ToList();
|
||||
if (assignedDocuments.Count > 0)
|
||||
{
|
||||
progressInterval = 20 / assignedDocuments.Count;
|
||||
|
||||
foreach (var documentPortion in assignedDocuments)
|
||||
{
|
||||
DocumentImporterLog.LogImportProgress(SessionId, (int)(70 + (assignedDocuments.IndexOf(documentPortion) * progressInterval)), string.Format("Importing Documents {0} of {1}", assignedDocuments.IndexOf(documentPortion) + 1, assignedDocuments.Count));
|
||||
|
||||
var documentPortionInfo = documentPortion.First().Value;
|
||||
var documentPortionIdentifier = documentPortionInfo.Item1;
|
||||
var documentPortionThumbnail = documentPortionInfo.Item2;
|
||||
|
||||
if (!documentPortionIdentifier.LoadComponents(Database))
|
||||
{
|
||||
// Unknown Document Unique Id
|
||||
foreach (var dp in documentPortion)
|
||||
{
|
||||
var tag = int.Parse(dp.Value.Item1.Tag);
|
||||
if (pdfPagesAssigned.ContainsKey(tag))
|
||||
pdfPagesAssigned.Remove(tag);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
using (MemoryStream msBuilder = new MemoryStream())
|
||||
{
|
||||
var pdfDoc = new iTextSharp.text.Document();
|
||||
var pdfCopy = new PdfCopy(pdfDoc, msBuilder);
|
||||
|
||||
pdfDoc.Open();
|
||||
pdfCopy.CloseStream = false;
|
||||
|
||||
foreach (var dp in documentPortion.OrderBy(dg => dg.Value.Item1.Page))
|
||||
{
|
||||
var pageSize = pdfReader.GetPageSizeWithRotation(dp.Key);
|
||||
var page = pdfCopy.GetImportedPage(pdfReader, dp.Key);
|
||||
|
||||
pdfDoc.SetPageSize(pageSize);
|
||||
pdfDoc.NewPage();
|
||||
|
||||
pdfCopy.AddPage(page);
|
||||
}
|
||||
|
||||
pdfDoc.Close();
|
||||
pdfCopy.Close();
|
||||
|
||||
msBuilder.Position = 0;
|
||||
|
||||
var attachmentSuccess = documentPortionIdentifier.ImportPdfAttachment(Database, msBuilder, documentPortionThumbnail);
|
||||
|
||||
if (!attachmentSuccess)
|
||||
{ // Unable to add Attachment
|
||||
foreach (var dp in documentPortion)
|
||||
{
|
||||
var tag = int.Parse(dp.Value.Item1.Tag);
|
||||
if (pdfPagesAssigned.ContainsKey(tag))
|
||||
pdfPagesAssigned.Remove(tag);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// Write out Unassigned Pages
|
||||
List<int> pdfPagesUnassigned = new List<int>();
|
||||
for (int PageNumber = 1; PageNumber <= pdfReader.NumberOfPages; PageNumber++)
|
||||
if (!pdfPagesAssigned.ContainsKey(PageNumber))
|
||||
pdfPagesUnassigned.Add(PageNumber);
|
||||
if (pdfPagesUnassigned.Count > 0)
|
||||
{
|
||||
progressInterval = 10 / pdfPagesUnassigned.Count;
|
||||
//dataStoreUnassignedLocation
|
||||
foreach (var PageNumber in pdfPagesUnassigned)
|
||||
{
|
||||
DocumentImporterLog.LogImportProgress(SessionId, (int)(90 + (pdfPagesUnassigned.IndexOf(PageNumber) * progressInterval)), string.Format("Processing Undetected Documents {0} of {1}", pdfPagesUnassigned.IndexOf(PageNumber) + 1, pdfPagesUnassigned.Count));
|
||||
|
||||
using (MemoryStream msBuilder = new MemoryStream())
|
||||
{
|
||||
var pdfDoc = new iTextSharp.text.Document();
|
||||
var pdfCopy = new PdfCopy(pdfDoc, msBuilder);
|
||||
|
||||
pdfDoc.Open();
|
||||
pdfCopy.CloseStream = false;
|
||||
|
||||
var pageSize = pdfReader.GetPageSizeWithRotation(PageNumber);
|
||||
var page = pdfCopy.GetImportedPage(pdfReader, PageNumber);
|
||||
pdfDoc.SetPageSize(pageSize);
|
||||
pdfDoc.NewPage();
|
||||
|
||||
pdfCopy.AddPage(page);
|
||||
pdfDoc.Close();
|
||||
pdfCopy.Close();
|
||||
|
||||
File.WriteAllBytes(Path.Combine(dataStoreUnassignedLocation, string.Format("{0}_{1}.pdf", SessionId, PageNumber)), msBuilder.ToArray());
|
||||
|
||||
DocumentImporterLog.LogImportPageUndetectedStored(SessionId, PageNumber);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
DocumentImporterLog.LogImportProgress(SessionId, 100, "Finished Importing Document");
|
||||
|
||||
return true;
|
||||
}
|
||||
public static bool ProcessPdfAttachment(string Filename, DiscoDataContext Database, string DocumentTemplateId, string DataId, string UserId, DateTime Timestamp)
|
||||
{
|
||||
using (FileStream fs = new FileStream(Filename, FileMode.Open, FileAccess.ReadWrite, FileShare.None))
|
||||
{
|
||||
DocumentUniqueIdentifier identifier = new DocumentUniqueIdentifier(DocumentTemplateId, DataId, UserId, Timestamp);
|
||||
identifier.LoadComponents(Database);
|
||||
return identifier.ImportPdfAttachment(Database, fs, null);
|
||||
}
|
||||
}
|
||||
|
||||
public static DisposableImageCollection GetPageImages(PdfReader pdfReader, int PageNumber)
|
||||
{
|
||||
var pageImages = new DisposableImageCollection();
|
||||
|
||||
var pdfPage = pdfReader.GetPageN(PageNumber);
|
||||
PdfDictionary pdfPageResouces = (PdfDictionary)((PdfDictionary)pdfPage.GetDirectObject(PdfName.RESOURCES)).GetDirectObject(PdfName.XOBJECT);
|
||||
|
||||
foreach (var pdfResKey in pdfPageResouces.Keys)
|
||||
{
|
||||
var pdfRes = pdfPageResouces.GetDirectObject(pdfResKey);
|
||||
if (pdfRes.IsStream())
|
||||
{
|
||||
var pdfResStream = (PdfStream)pdfRes;
|
||||
var pdfResSubType = pdfResStream.Get(PdfName.SUBTYPE);
|
||||
if (pdfResSubType != null && pdfResSubType == PdfName.IMAGE)
|
||||
{
|
||||
if (pdfResStream.Get(PdfName.FILTER) == PdfName.CCITTFAXDECODE)
|
||||
{ // TIFF
|
||||
// Try Using GDI+ for TIFF...
|
||||
var width = ((PdfNumber)(pdfResStream.Get(PdfName.WIDTH))).IntValue;
|
||||
var height = ((PdfNumber)(pdfResStream.Get(PdfName.HEIGHT))).IntValue;
|
||||
var bpc = ((PdfNumber)(pdfResStream.Get(PdfName.BITSPERCOMPONENT))).IntValue;
|
||||
|
||||
var compressionMethod = Compression.CCITTFAX3;
|
||||
|
||||
var decodeParams = pdfResStream.GetAsDict(PdfName.DECODEPARMS);
|
||||
if (decodeParams != null && decodeParams.Contains(PdfName.K) && decodeParams.GetAsNumber(PdfName.K).IntValue < 0)
|
||||
compressionMethod = Compression.CCITTFAX4;
|
||||
|
||||
using (MemoryStream tiffStream = PdfToTiffStream(PdfReader.GetStreamBytesRaw((PRStream)pdfResStream), width, height, bpc, compressionMethod))
|
||||
{
|
||||
pageImages.Add((Bitmap)Bitmap.FromStream(tiffStream));
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (pdfResStream.Get(PdfName.FILTER) == PdfName.DCTDECODE)
|
||||
{ // JPG
|
||||
using (MemoryStream jpgStream = new MemoryStream(PdfReader.GetStreamBytesRaw((PRStream)pdfResStream)))
|
||||
{
|
||||
pageImages.Add((Bitmap)Bitmap.FromStream(jpgStream, true, true));
|
||||
}
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return pageImages;
|
||||
}
|
||||
|
||||
private static MemoryStream PdfToTiffStream(byte[] PdfStream, int Width, int Height, int BitsPerComponent, Compression CompressionMethod)
|
||||
{
|
||||
var ms = new MemoryStream();
|
||||
|
||||
Tiff tif = Tiff.ClientOpen("in-memory", "w", ms, new TiffStream());
|
||||
tif.SetField(TiffTag.IMAGEWIDTH, Width);
|
||||
tif.SetField(TiffTag.IMAGELENGTH, Height);
|
||||
tif.SetField(TiffTag.COMPRESSION, CompressionMethod);
|
||||
tif.SetField(TiffTag.BITSPERSAMPLE, BitsPerComponent);
|
||||
tif.SetField(TiffTag.SAMPLESPERPIXEL, 1);
|
||||
tif.WriteRawStrip(0, PdfStream, PdfStream.Length);
|
||||
tif.Flush();
|
||||
|
||||
return ms;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* Copyright 2012 ZXing.Net authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
/// <summary>
|
||||
/// The base class for luminance sources which supports
|
||||
/// cropping and rotating based upon the luminance values.
|
||||
/// </summary>
|
||||
public abstract class BaseLuminanceSource : LuminanceSource
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
protected sbyte[] luminances;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="BaseLuminanceSource"/> class.
|
||||
/// </summary>
|
||||
/// <param name="width">The width.</param>
|
||||
/// <param name="height">The height.</param>
|
||||
protected BaseLuminanceSource(int width, int height)
|
||||
: base(width, height)
|
||||
{
|
||||
luminances = new sbyte[width * height];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="BaseLuminanceSource"/> class.
|
||||
/// </summary>
|
||||
/// <param name="luminanceArray">The luminance array.</param>
|
||||
/// <param name="width">The width.</param>
|
||||
/// <param name="height">The height.</param>
|
||||
protected BaseLuminanceSource(sbyte[] luminanceArray, int width, int height)
|
||||
: base(width, height)
|
||||
{
|
||||
luminances = luminanceArray;
|
||||
//Buffer.BlockCopy(luminanceArray, 0, luminances, 0, width * height);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Fetches one row of luminance data from the underlying platform's bitmap. Values range from
|
||||
/// 0 (black) to 255 (white). It is preferable for implementations of this method
|
||||
/// to only fetch this row rather than the whole image, since no 2D Readers may be installed and
|
||||
/// getMatrix() may never be called.
|
||||
/// </summary>
|
||||
/// <param name="y">The row to fetch, 0 <= y < Height.</param>
|
||||
/// <param name="row">An optional preallocated array. If null or too small, it will be ignored.
|
||||
/// Always use the returned object, and ignore the .length of the array.</param>
|
||||
/// <returns>
|
||||
/// An array containing the luminance data.
|
||||
/// </returns>
|
||||
override public sbyte[] getRow(int y, sbyte[] row)
|
||||
{
|
||||
int width = Width;
|
||||
if (row == null || row.Length < width)
|
||||
{
|
||||
row = new sbyte[width];
|
||||
}
|
||||
//for (int i = 0; i < width; i++)
|
||||
// row[i] = luminances[y * width + i];
|
||||
Buffer.BlockCopy(luminances, y * width, row, 0, width);
|
||||
return row;
|
||||
}
|
||||
|
||||
public override sbyte[] Matrix
|
||||
{
|
||||
get { return luminances; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a new object with rotated image data by 90 degrees counterclockwise.
|
||||
/// Only callable if {@link #isRotateSupported()} is true.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// A rotated version of this object.
|
||||
/// </returns>
|
||||
public override LuminanceSource rotateCounterClockwise()
|
||||
{
|
||||
var rotatedLuminances = new sbyte[Width * Height];
|
||||
var newWidth = Height;
|
||||
var newHeight = Width;
|
||||
var localLuminances = Matrix;
|
||||
for (var yold = 0; yold < Height; yold++)
|
||||
{
|
||||
for (var xold = 0; xold < Width; xold++)
|
||||
{
|
||||
var ynew = xold;
|
||||
var xnew = newWidth - yold - 1;
|
||||
rotatedLuminances[ynew * newWidth + xnew] = localLuminances[yold * Width + xold];
|
||||
}
|
||||
}
|
||||
return CreateLuminanceSource(rotatedLuminances, newWidth, newHeight);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// </summary>
|
||||
/// <returns> Whether this subclass supports counter-clockwise rotation.</returns>
|
||||
public override bool RotateSupported
|
||||
{
|
||||
get
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a new object with cropped image data. Implementations may keep a reference to the
|
||||
/// original data rather than a copy. Only callable if CropSupported is true.
|
||||
/// </summary>
|
||||
/// <param name="left">The left coordinate, 0 <= left < Width.</param>
|
||||
/// <param name="top">The top coordinate, 0 <= top <= Height.</param>
|
||||
/// <param name="width">The width of the rectangle to crop.</param>
|
||||
/// <param name="height">The height of the rectangle to crop.</param>
|
||||
/// <returns>
|
||||
/// A cropped version of this object.
|
||||
/// </returns>
|
||||
public override LuminanceSource crop(int left, int top, int width, int height)
|
||||
{
|
||||
if (left + width > Width || top + height > Height)
|
||||
{
|
||||
throw new ArgumentException("Crop rectangle does not fit within image data.");
|
||||
}
|
||||
var croppedLuminances = new sbyte[width * height];
|
||||
for (int yold = top, ynew = 0; yold < height; yold++, ynew++)
|
||||
{
|
||||
for (int xold = left, xnew = 0; xold < width; xold++, xnew++)
|
||||
{
|
||||
croppedLuminances[ynew * width + xnew] = luminances[yold * Width + xold];
|
||||
}
|
||||
}
|
||||
return CreateLuminanceSource(croppedLuminances, width, height);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// </summary>
|
||||
/// <returns> Whether this subclass supports cropping.</returns>
|
||||
public override bool CropSupported
|
||||
{
|
||||
get
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Should create a new luminance source with the right class type.
|
||||
/// The method is used in methods crop and rotate.
|
||||
/// </summary>
|
||||
/// <param name="newLuminances">The new luminances.</param>
|
||||
/// <param name="width">The width.</param>
|
||||
/// <param name="height">The height.</param>
|
||||
/// <returns></returns>
|
||||
protected abstract LuminanceSource CreateLuminanceSource(sbyte[] newLuminances, int width, int height);
|
||||
}
|
||||
public partial class BitmapLuminanceSource : BaseLuminanceSource
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="BitmapLuminanceSource"/> class.
|
||||
/// </summary>
|
||||
/// <param name="width">The width.</param>
|
||||
/// <param name="height">The height.</param>
|
||||
protected BitmapLuminanceSource(int width, int height)
|
||||
: base(width, height)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="BitmapLuminanceSource"/> class
|
||||
/// with the image of a Bitmap instance
|
||||
/// </summary>
|
||||
/// <param name="bitmap">The bitmap.</param>
|
||||
public BitmapLuminanceSource(Bitmap bitmap)
|
||||
: base(bitmap.Width, bitmap.Height)
|
||||
{
|
||||
var height = bitmap.Height;
|
||||
var width = bitmap.Width;
|
||||
|
||||
// In order to measure pure decoding speed, we convert the entire image to a greyscale array
|
||||
luminances = new sbyte[width * height];
|
||||
|
||||
// The underlying raster of image consists of bytes with the luminance values
|
||||
#if WindowsCE
|
||||
var data = bitmap.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.ReadOnly, PixelFormat.Format24bppRgb);
|
||||
#else
|
||||
var data = bitmap.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.ReadOnly, bitmap.PixelFormat);
|
||||
#endif
|
||||
try
|
||||
{
|
||||
var stride = Math.Abs(data.Stride);
|
||||
var pixelWidth = stride / width;
|
||||
|
||||
if (pixelWidth > 4)
|
||||
{
|
||||
// old slow way for unsupported bit depth
|
||||
Color c;
|
||||
for (int y = 0; y < height; y++)
|
||||
{
|
||||
int offset = y * width;
|
||||
for (int x = 0; x < width; x++)
|
||||
{
|
||||
c = bitmap.GetPixel(x, y);
|
||||
luminances[offset + x] = (sbyte)(0.3 * c.R + 0.59 * c.G + 0.11 * c.B + 0.01);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
var strideStep = data.Stride;
|
||||
var buffer = new byte[stride];
|
||||
var ptrInBitmap = data.Scan0;
|
||||
|
||||
#if !WindowsCE
|
||||
// prepare palette for 1 and 8 bit indexed bitmaps
|
||||
var luminancePalette = new sbyte[bitmap.Palette.Entries.Length];
|
||||
for (var index = 0; index < bitmap.Palette.Entries.Length; index++)
|
||||
{
|
||||
var color = bitmap.Palette.Entries[index];
|
||||
luminancePalette[index] = (sbyte)(0.3 * color.R +
|
||||
0.59 * color.G +
|
||||
0.11 * color.B + 0.01);
|
||||
}
|
||||
if (bitmap.PixelFormat == PixelFormat.Format32bppArgb ||
|
||||
bitmap.PixelFormat == PixelFormat.Format32bppPArgb)
|
||||
{
|
||||
pixelWidth = 40;
|
||||
}
|
||||
#endif
|
||||
|
||||
for (int y = 0; y < height; y++)
|
||||
{
|
||||
// copy a scanline not the whole bitmap because of memory usage
|
||||
Marshal.Copy(ptrInBitmap, buffer, 0, stride);
|
||||
#if NET40
|
||||
ptrInBitmap = IntPtr.Add(ptrInBitmap, strideStep);
|
||||
#else
|
||||
ptrInBitmap = new IntPtr(ptrInBitmap.ToInt64() + strideStep);
|
||||
#endif
|
||||
var offset = y * width;
|
||||
switch (pixelWidth)
|
||||
{
|
||||
#if !WindowsCE
|
||||
case 0:
|
||||
for (int x = 0; x * 8 < width; x++)
|
||||
{
|
||||
for (int subX = 0; subX < 8 && 8 * x + subX < width; subX++)
|
||||
{
|
||||
var index = (buffer[x] >> (7 - subX)) & 1;
|
||||
luminances[offset + 8 * x + subX] = luminancePalette[index];
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
for (int x = 0; x < width; x++)
|
||||
{
|
||||
luminances[offset + x] = luminancePalette[buffer[x]];
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
case 2:
|
||||
// should be RGB565 or RGB555, assume RGB565
|
||||
{
|
||||
for (int index = 0, x = 0; index < 2 * width; index += 2, x++)
|
||||
{
|
||||
var byte1 = buffer[index];
|
||||
var byte2 = buffer[index + 1];
|
||||
|
||||
var b5 = byte1 & 0x1F;
|
||||
var g5 = (((byte1 & 0xE0) >> 5) | ((byte2 & 0x03) << 3)) & 0x1F;
|
||||
var r5 = (byte2 >> 2) & 0x1F;
|
||||
var r8 = (r5 * 527 + 23) >> 6;
|
||||
var g8 = (g5 * 527 + 23) >> 6;
|
||||
var b8 = (b5 * 527 + 23) >> 6;
|
||||
|
||||
luminances[offset + x] = (sbyte)(0.3 * r8 + 0.59 * g8 + 0.11 * b8 + 0.01);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
for (int x = 0; x < width; x++)
|
||||
{
|
||||
var luminance = (sbyte)(0.3 * buffer[x * 3] +
|
||||
0.59 * buffer[x * 3 + 1] +
|
||||
0.11 * buffer[x * 3 + 2] + 0.01);
|
||||
luminances[offset + x] = luminance;
|
||||
}
|
||||
break;
|
||||
case 4:
|
||||
// 4 bytes without alpha channel value
|
||||
for (int x = 0; x < width; x++)
|
||||
{
|
||||
var luminance = (sbyte)(0.30 * buffer[x * 4] +
|
||||
0.59 * buffer[x * 4 + 1] +
|
||||
0.11 * buffer[x * 4 + 2] + 0.01);
|
||||
|
||||
luminances[offset + x] = luminance;
|
||||
}
|
||||
break;
|
||||
case 40:
|
||||
// with alpha channel; some barcodes are completely black if you
|
||||
// only look at the r, g and b channel but the alpha channel controls
|
||||
// the view
|
||||
for (int x = 0; x < width; x++)
|
||||
{
|
||||
var luminance = (sbyte)(0.30 * buffer[x * 4] +
|
||||
0.59 * buffer[x * 4 + 1] +
|
||||
0.11 * buffer[x * 4 + 2] + 0.01);
|
||||
|
||||
// calculating the resulting luminance based upon a white background
|
||||
// var alpha = buffer[x * pixelWidth + 3] / 255.0;
|
||||
// luminance = (byte)(luminance * alpha + 255 * (1 - alpha));
|
||||
var alpha = buffer[x * 4 + 3];
|
||||
luminance = (sbyte)(((luminance * alpha) >> 8) + (255 * (255 - alpha) >> 8));
|
||||
luminances[offset + x] = luminance;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
bitmap.UnlockBits(data);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Should create a new luminance source with the right class type.
|
||||
/// The method is used in methods crop and rotate.
|
||||
/// </summary>
|
||||
/// <param name="newLuminances">The new luminances.</param>
|
||||
/// <param name="width">The width.</param>
|
||||
/// <param name="height">The height.</param>
|
||||
/// <returns></returns>
|
||||
protected override LuminanceSource CreateLuminanceSource(sbyte[] newLuminances, int width, int height)
|
||||
{
|
||||
return new BitmapLuminanceSource(width, height) { luminances = newLuminances };
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
using iTextSharp.text;
|
||||
using iTextSharp.text.pdf;
|
||||
using iTextSharp.text.pdf.codec;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
|
||||
namespace Disco.BI.Interop.Pdf
|
||||
{
|
||||
public static class Utilities
|
||||
{
|
||||
public static Func<byte[], int, int, byte[]> GetCCITTG4EncoderCompressDelegate()
|
||||
{
|
||||
return CCITTG4Encoder.Compress;
|
||||
}
|
||||
|
||||
public static Stream JoinPdfs(bool InsertBlankPages, List<Stream> Pdfs)
|
||||
{
|
||||
if (Pdfs.Count == 0)
|
||||
throw new System.ArgumentNullException(nameof(Pdfs));
|
||||
|
||||
// Only One PDF - Possible Reference Bug v's Memory/Speed (Returning Param Memory Stream)
|
||||
if (Pdfs.Count == 1)
|
||||
return Pdfs[0];
|
||||
|
||||
// Join Pdfs
|
||||
var msBuilder = new MemoryStream();
|
||||
|
||||
var pdfLastPageSize = PageSize.A4;
|
||||
var pdfDoc = new Document();
|
||||
var pdfCopy = new PdfSmartCopy(pdfDoc, msBuilder);
|
||||
pdfDoc.Open();
|
||||
pdfCopy.CloseStream = false;
|
||||
|
||||
for (int i = 0; i < Pdfs.Count; i++)
|
||||
{
|
||||
var pdf = Pdfs[i];
|
||||
var pdfReader = new PdfReader(pdf);
|
||||
|
||||
if (InsertBlankPages && (pdfCopy.CurrentPageNumber % 2) == 0)
|
||||
{
|
||||
pdfCopy.AddPage(pdfLastPageSize, 0);
|
||||
}
|
||||
|
||||
for (int indexPage = 1; indexPage <= pdfReader.NumberOfPages; indexPage++)
|
||||
{
|
||||
pdfLastPageSize = pdfReader.GetPageSizeWithRotation(indexPage);
|
||||
var page = pdfCopy.GetImportedPage(pdfReader, indexPage);
|
||||
pdfDoc.SetPageSize(pdfLastPageSize);
|
||||
pdfCopy.AddPage(page);
|
||||
}
|
||||
|
||||
pdfReader.Close();
|
||||
}
|
||||
|
||||
pdfDoc.Close();
|
||||
pdfCopy.Close();
|
||||
msBuilder.Position = 0;
|
||||
|
||||
return msBuilder;
|
||||
}
|
||||
}
|
||||
}
|
||||
+16
-112
@@ -10,7 +10,7 @@
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>Disco</RootNamespace>
|
||||
<AssemblyName>Disco.BI</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
|
||||
<TargetFrameworkVersion>v4.6.2</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<TargetFrameworkProfile />
|
||||
<SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\</SolutionDir>
|
||||
@@ -37,9 +37,6 @@
|
||||
<Prefer32Bit>false</Prefer32Bit>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="BitMiracle.LibTiff.NET">
|
||||
<HintPath>..\Resources\Libraries\LibTiff.NET\BitMiracle.LibTiff.NET.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="EntityFramework">
|
||||
<HintPath>..\packages\EntityFramework.5.0.0\lib\net45\EntityFramework.dll</HintPath>
|
||||
</Reference>
|
||||
@@ -49,9 +46,6 @@
|
||||
<Reference Include="Quartz">
|
||||
<HintPath>..\Resources\Libraries\Quartz\Quartz.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Spring.Core">
|
||||
<HintPath>..\Resources\Libraries\Spring.NET\Spring.Core.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.ComponentModel.DataAnnotations" />
|
||||
<Reference Include="System.Core" />
|
||||
@@ -59,22 +53,16 @@
|
||||
<Reference Include="System.DirectoryServices" />
|
||||
<Reference Include="System.Drawing" />
|
||||
<Reference Include="System.Management" />
|
||||
<Reference Include="System.Reactive.Core, Version=2.2.4.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\packages\Rx-Core.2.2.4\lib\net45\System.Reactive.Core.dll</HintPath>
|
||||
<Reference Include="System.Net.Http" />
|
||||
<Reference Include="System.Net.Http.Extensions, Version=2.2.22.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Microsoft.Net.Http.2.2.22\lib\net45\System.Net.Http.Extensions.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="System.Reactive.Interfaces, Version=2.2.4.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\packages\Rx-Interfaces.2.2.4\lib\net45\System.Reactive.Interfaces.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.Reactive.Linq, Version=2.2.4.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\packages\Rx-Linq.2.2.4\lib\net45\System.Reactive.Linq.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.Reactive.PlatformServices, Version=2.2.4.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\packages\Rx-PlatformServices.2.2.4\lib\net45\System.Reactive.PlatformServices.dll</HintPath>
|
||||
<Reference Include="System.Net.Http.Primitives, Version=4.2.22.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Microsoft.Net.Http.2.2.22\lib\net45\System.Net.Http.Primitives.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="System.Net.Http.WebRequest" />
|
||||
<Reference Include="System.Runtime.Serialization" />
|
||||
<Reference Include="System.ServiceModel" />
|
||||
<Reference Include="System.Web" />
|
||||
@@ -83,77 +71,11 @@
|
||||
<Reference Include="Microsoft.CSharp" />
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Xml" />
|
||||
<Reference Include="Tamir.SharpSSH">
|
||||
<HintPath>..\Resources\Libraries\SharpSSH\Tamir.SharpSSH.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="zxing">
|
||||
<HintPath>..\Resources\Libraries\ZXing\zxing.dll</HintPath>
|
||||
</Reference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="BI\DataStore.cs" />
|
||||
<Compile Include="BI\AttachmentBI\Utilities.cs" />
|
||||
<Compile Include="BI\DeviceBI\BatchUtilities.cs" />
|
||||
<Compile Include="BI\DeviceBI\DeviceModelBI.cs" />
|
||||
<Compile Include="BI\DeviceBI\Migration\LogMacAddressImporting.cs" />
|
||||
<Compile Include="BI\DisposableImageCollection.cs" />
|
||||
<Compile Include="BI\DocumentTemplateBI\DocumentTemplateQRCodeLocationCache.cs" />
|
||||
<Compile Include="BI\DocumentTemplateBI\ManagedGroups\DocumentTemplateUsersManagedGroup.cs" />
|
||||
<Compile Include="BI\DocumentTemplateBI\ManagedGroups\DocumentTemplateDevicesManagedGroup.cs" />
|
||||
<Compile Include="BI\DocumentTemplateBI\ManagedGroups\DocumentTemplateManagedGroups.cs" />
|
||||
<Compile Include="BI\Expressions\EvaluateExpressionParseException.cs" />
|
||||
<Compile Include="BI\Expressions\ExpressionCachePreloadTask.cs" />
|
||||
<Compile Include="BI\Expressions\Extensions\DataExt.cs" />
|
||||
<Compile Include="BI\Expressions\Extensions\DeviceExt.cs" />
|
||||
<Compile Include="BI\Expressions\Extensions\ImageExt.cs" />
|
||||
<Compile Include="BI\Expressions\Extensions\ImageResultImplementations\BaseImageExpressionResult.cs" />
|
||||
<Compile Include="BI\Expressions\Extensions\ImageResultImplementations\FileMontageImageExpressionResult.cs" />
|
||||
<Compile Include="BI\Expressions\Extensions\ImageResultImplementations\FileImageExpressionResult.cs" />
|
||||
<Compile Include="BI\Expressions\Extensions\ImageResultImplementations\BitmapImageExpressionResult.cs" />
|
||||
<Compile Include="BI\Expressions\Extensions\UserExt.cs" />
|
||||
<Compile Include="BI\Extensions\AttachmentActionExtensions.cs" />
|
||||
<Compile Include="BI\Extensions\AttachmentExtensions.cs" />
|
||||
<Compile Include="BI\Extensions\AuthorizationRoleExtensions.cs" />
|
||||
<Compile Include="BI\Extensions\ClientServicesExtensions.cs" />
|
||||
<Compile Include="BI\Extensions\UserFlagActionExtensions.cs" />
|
||||
<Compile Include="BI\Extensions\DeviceActionExtensions.cs" />
|
||||
<Compile Include="BI\Extensions\DeviceBatchExtensions.cs" />
|
||||
<Compile Include="BI\Extensions\DeviceCertificateExtensions.cs" />
|
||||
<Compile Include="BI\Extensions\DeviceDetailExtensions.cs" />
|
||||
<Compile Include="BI\Extensions\DeviceModelExtensions.cs" />
|
||||
<Compile Include="BI\Extensions\DeviceProfileExtensions.cs" />
|
||||
<Compile Include="BI\Extensions\JobActionExtensions.cs" />
|
||||
<Compile Include="BI\Extensions\JobExtensions.cs" />
|
||||
<Compile Include="BI\Extensions\JobFlagExtensions.cs" />
|
||||
<Compile Include="BI\Extensions\JobQueueActionExtensions.cs" />
|
||||
<Compile Include="BI\Extensions\UserExtensions.cs" />
|
||||
<Compile Include="BI\Extensions\WirelessCertificateExtensions.cs" />
|
||||
<Compile Include="BI\Extensions\DeviceExtensions.cs" />
|
||||
<Compile Include="BI\DeviceBI\EnrolSafeException.cs" />
|
||||
<Compile Include="BI\DeviceBI\Enrol.cs" />
|
||||
<Compile Include="BI\DeviceBI\EnrolmentLog.cs" />
|
||||
<Compile Include="BI\Extensions\DocumentTemplateExtensions.cs" />
|
||||
<Compile Include="BI\DocumentTemplateBI\Utilities.cs" />
|
||||
<Compile Include="BI\DocumentTemplateBI\DocumentUniqueIdentifier.cs" />
|
||||
<Compile Include="BI\Expressions\EvaluateExpressionPart.cs" />
|
||||
<Compile Include="BI\Expressions\Expression.cs" />
|
||||
<Compile Include="BI\Expressions\ExpressionTypeDescriptor.cs" />
|
||||
<Compile Include="BI\Expressions\ExpressionTypeMemberDescriptor.cs" />
|
||||
<Compile Include="BI\Expressions\IExpressionPart.cs" />
|
||||
<Compile Include="BI\Expressions\TextExpressionPart.cs" />
|
||||
<Compile Include="BI\DocumentTemplateBI\Importer\DocumentDropBoxMonitor.cs" />
|
||||
<Compile Include="BI\DocumentTemplateBI\Importer\DocumentImporterJob.cs" />
|
||||
<Compile Include="BI\DocumentTemplateBI\Importer\DocumentImporterCleanCacheJob.cs" />
|
||||
<Compile Include="BI\DocumentTemplateBI\Importer\DocumentImporterLog.cs" />
|
||||
<Compile Include="BI\Expressions\ExpressionCache.cs" />
|
||||
<Compile Include="BI\Interop\Community\UpdateCheck.cs" />
|
||||
<Compile Include="BI\Interop\Community\UpdateCheckTask.cs" />
|
||||
<Compile Include="BI\Interop\MimeTypes.cs" />
|
||||
<Compile Include="BI\Interop\Pdf\Utilities.cs" />
|
||||
<Compile Include="BI\Interop\Pdf\PdfGenerator.cs" />
|
||||
<Compile Include="BI\Interop\Pdf\PdfImporter.cs" />
|
||||
<Compile Include="BI\JobBI\Statistics\DailyOpenedClosed.cs" />
|
||||
<Compile Include="BI\JobBI\Utilities.cs" />
|
||||
<Compile Include="BI\Extensions\UtilityExtensions.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="Properties\Resources.Designer.cs">
|
||||
<AutoGen>True</AutoGen>
|
||||
@@ -183,34 +105,16 @@
|
||||
<EmbeddedResource Include="Properties\Resources.resx">
|
||||
<Generator>ResXFileCodeGenerator</Generator>
|
||||
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
|
||||
<SubType>Designer</SubType>
|
||||
</EmbeddedResource>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="Resources\MimeType-img16.png" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="Resources\MimeType-pdf16.png" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="Resources\EmptyLogo.png" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="Resources\MimeType-doc48.png" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="Resources\MimeType-pdf48.png" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="Resources\MimeType-unknown48.png" />
|
||||
</ItemGroup>
|
||||
<ItemGroup />
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<ProjectExtensions>
|
||||
<VisualStudio>
|
||||
<UserProperties BuildVersion_StartDate="2014/6/1" BuildVersion_BuildAction="Both" BuildVersion_DetectChanges="False" BuildVersion_UseGlobalSettings="False" BuildVersion_BuildVersioningStyle="None.DeltaBaseYear.MonthAndDayStamp.TimeStamp" BuildVersion_UpdateAssemblyVersion="True" BuildVersion_UpdateFileVersion="True" />
|
||||
</VisualStudio>
|
||||
</ProjectExtensions>
|
||||
<Import Project="$(SolutionDir)\.nuget\nuget.targets" />
|
||||
<Import Project="..\packages\Microsoft.Bcl.Build.1.0.14\tools\Microsoft.Bcl.Build.targets" Condition="Exists('..\packages\Microsoft.Bcl.Build.1.0.14\tools\Microsoft.Bcl.Build.targets')" />
|
||||
<Target Name="EnsureBclBuildImported" BeforeTargets="BeforeBuild" Condition="'$(BclBuildImported)' == ''">
|
||||
<Error Condition="!Exists('..\packages\Microsoft.Bcl.Build.1.0.14\tools\Microsoft.Bcl.Build.targets')" Text="This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=317567." HelpKeyword="BCLBUILD2001" />
|
||||
<Error Condition="Exists('..\packages\Microsoft.Bcl.Build.1.0.14\tools\Microsoft.Bcl.Build.targets')" Text="The build restored NuGet packages. Build the project again to include these packages in the build. For more information, see http://go.microsoft.com/fwlink/?LinkID=317568." HelpKeyword="BCLBUILD2002" />
|
||||
</Target>
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
Other similar extension points exist, see Microsoft.Common.targets.
|
||||
<Target Name="BeforeBuild">
|
||||
|
||||
@@ -1,15 +1,14 @@
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Reflection;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// General Information about an assembly is controlled through the following
|
||||
// set of attributes. Change these attribute values to modify the information
|
||||
// associated with an assembly.
|
||||
[assembly: AssemblyTitle("Disco - Business Intelligence")]
|
||||
[assembly: AssemblyTitle("Disco ICT - Business Intelligence")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("Disco")]
|
||||
[assembly: AssemblyCompany("https://discoict.com.au")]
|
||||
[assembly: AssemblyProduct("Disco ICT")]
|
||||
[assembly: AssemblyCopyright("")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
@@ -32,5 +31,5 @@ using System.Runtime.InteropServices;
|
||||
// You can specify all the values or you can default the Build and Revision Numbers
|
||||
// by using the '*' as shown below:
|
||||
// [assembly: AssemblyVersion("1.0.*")]
|
||||
[assembly: AssemblyVersion("2.0.0626.0000")]
|
||||
[assembly: AssemblyFileVersion("2.0.0626.0000")]
|
||||
[assembly: AssemblyVersion("2.3.23161.0650")]
|
||||
[assembly: AssemblyFileVersion("2.3.23161.0650")]
|
||||
+2
-52
@@ -1,7 +1,7 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// <auto-generated>
|
||||
// This code was generated by a tool.
|
||||
// Runtime Version:4.0.30319.17929
|
||||
// Runtime Version:4.0.30319.42000
|
||||
//
|
||||
// Changes to this file may cause incorrect behavior and will be lost if
|
||||
// the code is regenerated.
|
||||
@@ -19,7 +19,7 @@ namespace Disco.Properties {
|
||||
// class via a tool like ResGen or Visual Studio.
|
||||
// To add or remove a member, edit your .ResX file then rerun ResGen
|
||||
// with the /str option, or rebuild your VS project.
|
||||
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
|
||||
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")]
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
|
||||
internal class Resources {
|
||||
@@ -59,55 +59,5 @@ namespace Disco.Properties {
|
||||
resourceCulture = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized resource of type System.Drawing.Bitmap.
|
||||
/// </summary>
|
||||
internal static System.Drawing.Bitmap MimeType_doc48 {
|
||||
get {
|
||||
object obj = ResourceManager.GetObject("MimeType_doc48", resourceCulture);
|
||||
return ((System.Drawing.Bitmap)(obj));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized resource of type System.Drawing.Bitmap.
|
||||
/// </summary>
|
||||
internal static System.Drawing.Bitmap MimeType_img16 {
|
||||
get {
|
||||
object obj = ResourceManager.GetObject("MimeType_img16", resourceCulture);
|
||||
return ((System.Drawing.Bitmap)(obj));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized resource of type System.Drawing.Bitmap.
|
||||
/// </summary>
|
||||
internal static System.Drawing.Bitmap MimeType_pdf16 {
|
||||
get {
|
||||
object obj = ResourceManager.GetObject("MimeType_pdf16", resourceCulture);
|
||||
return ((System.Drawing.Bitmap)(obj));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized resource of type System.Drawing.Bitmap.
|
||||
/// </summary>
|
||||
internal static System.Drawing.Bitmap MimeType_pdf48 {
|
||||
get {
|
||||
object obj = ResourceManager.GetObject("MimeType_pdf48", resourceCulture);
|
||||
return ((System.Drawing.Bitmap)(obj));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized resource of type System.Drawing.Bitmap.
|
||||
/// </summary>
|
||||
internal static System.Drawing.Bitmap MimeType_unknown48 {
|
||||
get {
|
||||
object obj = ResourceManager.GetObject("MimeType_unknown48", resourceCulture);
|
||||
return ((System.Drawing.Bitmap)(obj));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -117,20 +117,4 @@
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
|
||||
<data name="MimeType_doc48" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>..\Resources\MimeType-doc48.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
|
||||
</data>
|
||||
<data name="MimeType_img16" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>..\Resources\MimeType-img16.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
|
||||
</data>
|
||||
<data name="MimeType_pdf16" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>..\Resources\MimeType-pdf16.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
|
||||
</data>
|
||||
<data name="MimeType_pdf48" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>..\Resources\MimeType-pdf48.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
|
||||
</data>
|
||||
<data name="MimeType_unknown48" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>..\Resources\MimeType-unknown48.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
|
||||
</data>
|
||||
</root>
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 30 KiB |
+29
-17
@@ -1,45 +1,57 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<configuration>
|
||||
<configSections>
|
||||
<!-- For more information on Entity Framework configuration, visit http://go.microsoft.com/fwlink/?LinkID=237468 -->
|
||||
<section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
|
||||
<section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false"/>
|
||||
</configSections>
|
||||
<system.serviceModel>
|
||||
<bindings />
|
||||
<client />
|
||||
<bindings/>
|
||||
<client/>
|
||||
</system.serviceModel>
|
||||
<entityFramework>
|
||||
<defaultConnectionFactory type="System.Data.Entity.Infrastructure.SqlConnectionFactory, EntityFramework">
|
||||
<parameters>
|
||||
<parameter value="Data Source=(localdb)\v11.0; Integrated Security=True; MultipleActiveResultSets=True" />
|
||||
<parameter value="Data Source=(localdb)\v11.0; Integrated Security=True; MultipleActiveResultSets=True"/>
|
||||
</parameters>
|
||||
</defaultConnectionFactory>
|
||||
</entityFramework>
|
||||
<startup>
|
||||
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
|
||||
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.2"/>
|
||||
</startup>
|
||||
<runtime>
|
||||
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="System.Web.Mvc" publicKeyToken="31bf3856ad364e35" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-4.0.0.0" newVersion="4.0.0.0" />
|
||||
<assemblyIdentity name="System.Web.Mvc" publicKeyToken="31bf3856ad364e35" culture="neutral"/>
|
||||
<bindingRedirect oldVersion="0.0.0.0-4.0.0.0" newVersion="4.0.0.0"/>
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="System.Web.WebPages" publicKeyToken="31bf3856ad364e35" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-2.0.0.0" newVersion="2.0.0.0" />
|
||||
<assemblyIdentity name="System.Web.WebPages" publicKeyToken="31bf3856ad364e35" culture="neutral"/>
|
||||
<bindingRedirect oldVersion="0.0.0.0-2.0.0.0" newVersion="2.0.0.0"/>
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
|
||||
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral"/>
|
||||
<bindingRedirect oldVersion="0.0.0.0-13.0.0.0" newVersion="13.0.0.0"/>
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="System.Web.Razor" publicKeyToken="31bf3856ad364e35" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-2.0.0.0" newVersion="2.0.0.0" />
|
||||
<assemblyIdentity name="System.Web.Razor" publicKeyToken="31bf3856ad364e35" culture="neutral"/>
|
||||
<bindingRedirect oldVersion="0.0.0.0-2.0.0.0" newVersion="2.0.0.0"/>
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="System.Web.WebPages.Razor" publicKeyToken="31bf3856ad364e35" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-2.0.0.0" newVersion="2.0.0.0" />
|
||||
<assemblyIdentity name="System.Web.WebPages.Razor" publicKeyToken="31bf3856ad364e35" culture="neutral"/>
|
||||
<bindingRedirect oldVersion="0.0.0.0-2.0.0.0" newVersion="2.0.0.0"/>
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="Common.Logging" publicKeyToken="af08829b84f0328e" culture="neutral"/>
|
||||
<bindingRedirect oldVersion="0.0.0.0-2.0.0.0" newVersion="2.0.0.0"/>
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="Microsoft.Owin" publicKeyToken="31bf3856ad364e35" culture="neutral"/>
|
||||
<bindingRedirect oldVersion="0.0.0.0-4.2.2.0" newVersion="4.2.2.0"/>
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="Microsoft.Owin.Security" publicKeyToken="31bf3856ad364e35" culture="neutral"/>
|
||||
<bindingRedirect oldVersion="0.0.0.0-4.2.2.0" newVersion="4.2.2.0"/>
|
||||
</dependentAssembly>
|
||||
</assemblyBinding>
|
||||
</runtime>
|
||||
</configuration>
|
||||
</configuration>
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="EntityFramework" version="5.0.0" targetFramework="net45" />
|
||||
<package id="Rx-Core" version="2.2.4" targetFramework="net45" />
|
||||
<package id="Rx-Interfaces" version="2.2.4" targetFramework="net45" />
|
||||
<package id="Rx-Linq" version="2.2.4" targetFramework="net45" />
|
||||
<package id="Rx-Main" version="2.2.4" targetFramework="net45" />
|
||||
<package id="Rx-PlatformServices" version="2.2.4" targetFramework="net45" />
|
||||
<package id="Microsoft.Bcl" version="1.1.9" targetFramework="net45" />
|
||||
<package id="Microsoft.Bcl.Build" version="1.0.14" targetFramework="net45" />
|
||||
<package id="Microsoft.Net.Http" version="2.2.22" targetFramework="net45" />
|
||||
</packages>
|
||||
@@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
@@ -9,9 +9,8 @@
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>Disco.Client</RootNamespace>
|
||||
<AssemblyName>Disco.Client</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
|
||||
<TargetFrameworkVersion>v4.5.2</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<TargetFrameworkProfile>Client</TargetFrameworkProfile>
|
||||
<SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\</SolutionDir>
|
||||
<RestorePackages>true</RestorePackages>
|
||||
</PropertyGroup>
|
||||
@@ -24,6 +23,7 @@
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<Prefer32Bit>false</Prefer32Bit>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
@@ -33,6 +33,7 @@
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<Prefer32Bit>false</Prefer32Bit>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<StartupObject>Disco.Client.Program</StartupObject>
|
||||
@@ -48,8 +49,8 @@
|
||||
<ApplicationManifest>Properties\app.manifest</ApplicationManifest>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="Newtonsoft.Json">
|
||||
<HintPath>..\packages\Newtonsoft.Json.6.0.3\lib\net40\Newtonsoft.Json.dll</HintPath>
|
||||
<Reference Include="Newtonsoft.Json, Version=13.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Newtonsoft.Json.13.0.2\lib\net40\Newtonsoft.Json.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Core" />
|
||||
@@ -65,6 +66,54 @@
|
||||
<Compile Include="..\Disco.Models\ClientServices\Enrol.cs">
|
||||
<Link>Models\ClientServices\Enrol.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Disco.Models\ClientServices\EnrolmentInformation\BaseBoard.cs">
|
||||
<Link>Models\ClientServices\EnrolmentInformation\BaseBoard.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Disco.Models\ClientServices\EnrolmentInformation\Battery.cs">
|
||||
<Link>Models\ClientServices\EnrolmentInformation\Battery.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Disco.Models\ClientServices\EnrolmentInformation\Bios.cs">
|
||||
<Link>Models\ClientServices\EnrolmentInformation\Bios.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Disco.Models\ClientServices\EnrolmentInformation\Certificate.cs">
|
||||
<Link>Models\ClientServices\EnrolmentInformation\Certificate.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Disco.Models\ClientServices\EnrolmentInformation\CertificateStore.cs">
|
||||
<Link>Models\ClientServices\EnrolmentInformation\CertificateStore.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Disco.Models\ClientServices\EnrolmentInformation\ComputerSystem.cs">
|
||||
<Link>Models\ClientServices\EnrolmentInformation\ComputerSystem.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Disco.Models\ClientServices\EnrolmentInformation\DeviceHardware.cs">
|
||||
<Link>Models\ClientServices\EnrolmentInformation\DeviceHardware.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Disco.Models\ClientServices\EnrolmentInformation\DiskDrive.cs">
|
||||
<Link>Models\ClientServices\EnrolmentInformation\DiskDrive.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Disco.Models\ClientServices\EnrolmentInformation\DiskDrivePartition.cs">
|
||||
<Link>Models\ClientServices\EnrolmentInformation\DiskDrivePartition.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Disco.Models\ClientServices\EnrolmentInformation\DiskLogical.cs">
|
||||
<Link>Models\ClientServices\EnrolmentInformation\DiskLogical.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Disco.Models\ClientServices\EnrolmentInformation\NetworkAdapter.cs">
|
||||
<Link>Models\ClientServices\EnrolmentInformation\NetworkAdapter.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Disco.Models\ClientServices\EnrolmentInformation\PhysicalMemory.cs">
|
||||
<Link>Models\ClientServices\EnrolmentInformation\PhysicalMemory.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Disco.Models\ClientServices\EnrolmentInformation\Processor.cs">
|
||||
<Link>Models\ClientServices\EnrolmentInformation\Processor.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Disco.Models\ClientServices\EnrolmentInformation\WirelessProfile.cs">
|
||||
<Link>Models\ClientServices\EnrolmentInformation\WirelessProfile.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Disco.Models\ClientServices\EnrolmentInformation\WirelessProfileStore.cs">
|
||||
<Link>Models\ClientServices\EnrolmentInformation\WirelessProfileStore.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Disco.Models\ClientServices\EnrolmentInformation\WirelessProfileTransformation.cs">
|
||||
<Link>Models\ClientServices\EnrolmentInformation\WirelessProfileTransformation.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Disco.Models\ClientServices\EnrolResponse.cs">
|
||||
<Link>Models\ClientServices\EnrolResponse.cs</Link>
|
||||
</Compile>
|
||||
@@ -92,10 +141,19 @@
|
||||
<Compile Include="Extensions\EnrolExtensions.cs" />
|
||||
<Compile Include="Extensions\WhoAmIExtensions.cs" />
|
||||
<Compile Include="Interop\Certificates.cs" />
|
||||
<Compile Include="Interop\Hardware.cs" />
|
||||
<Compile Include="Interop\LocalAuthentication.cs" />
|
||||
<Compile Include="Interop\Native\NetworkConnectionStatuses.cs" />
|
||||
<Compile Include="Interop\Native\ProfileInfoFlags.cs" />
|
||||
<Compile Include="Interop\Native\WlanApi.cs" />
|
||||
<Compile Include="Interop\Native\WLAN_INTERFACE_INFO.cs" />
|
||||
<Compile Include="Interop\Native\WLAN_INTERFACE_INFO_LIST.cs" />
|
||||
<Compile Include="Interop\Native\WLAN_INTERFACE_STATE.cs" />
|
||||
<Compile Include="Interop\Native\WLAN_PROFILE_INFO.cs" />
|
||||
<Compile Include="Interop\Native\WLAN_PROFILE_INFO_LIST.cs" />
|
||||
<Compile Include="Interop\Network.cs" />
|
||||
<Compile Include="Interop\WirelessNetwork.cs" />
|
||||
<Compile Include="Presentation.cs" />
|
||||
<Compile Include="Interop\SystemAudit.cs" />
|
||||
<Compile Include="Program.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
</ItemGroup>
|
||||
@@ -119,17 +177,16 @@
|
||||
<None Include="Package Creation\7z.exe" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<ProjectExtensions>
|
||||
<VisualStudio>
|
||||
<UserProperties BuildVersion_UseGlobalSettings="False" BuildVersion_DetectChanges="False" BuildVersion_StartDate="2014/6/1" BuildVersion_BuildAction="Both" BuildVersion_BuildVersioningStyle="None.DeltaBaseYear.MonthAndDayStamp.TimeStamp" BuildVersion_UpdateAssemblyVersion="True" BuildVersion_UpdateFileVersion="True" />
|
||||
</VisualStudio>
|
||||
</ProjectExtensions>
|
||||
<PropertyGroup>
|
||||
<PostBuildEvent>DEL "$(ProjectDir)Package Creation\PreparationClient.zip"
|
||||
"$(ProjectDir)Package Creation\7z.exe" a -tzip "$(ProjectDir)Package Creation\PreparationClient.zip" "$(TargetDir)*.*" -x!*.tmp -x!*.vshost.* -x!Newtonsoft.Json.xml -x!*.pdb
|
||||
COPY "$(ProjectDir)Package Creation\PreparationClient.zip" "$(ProjectDir)..\Disco.Web\ClientBin"</PostBuildEvent>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(SolutionDir)\.nuget\nuget.targets" />
|
||||
<ProjectExtensions>
|
||||
<VisualStudio>
|
||||
<UserProperties BuildVersion_StartDate="2000/1/1" />
|
||||
</VisualStudio>
|
||||
</ProjectExtensions>
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
Other similar extension points exist, see Microsoft.Common.targets.
|
||||
<Target Name="BeforeBuild">
|
||||
|
||||
@@ -89,7 +89,7 @@ namespace Disco.Client
|
||||
string reportResponse;
|
||||
|
||||
HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(ServicePathTemplate);
|
||||
request.UserAgent = string.Format("Disco-Client/{0}", Assembly.GetExecutingAssembly().GetName().Version.ToString(3));
|
||||
request.UserAgent = $"Disco-Client/{Assembly.GetExecutingAssembly().GetName().Version.ToString(3)}";
|
||||
request.ContentType = "application/json";
|
||||
request.Method = WebRequestMethods.Http.Post;
|
||||
request.UseDefaultCredentials = true;
|
||||
|
||||
@@ -1,8 +1,4 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Disco.Client.Extensions
|
||||
{
|
||||
|
||||
@@ -1,55 +1,60 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Disco.Models.ClientServices;
|
||||
using Newtonsoft.Json;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Disco.Models.ClientServices;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Disco.Client.Extensions
|
||||
{
|
||||
public static class ClientServicesExtensions
|
||||
{
|
||||
//#if DEBUG
|
||||
// public const string ServicePathAuthenticatedTemplate = "http://WS-GSHARP:57252/Services/Client/Authenticated/{0}";
|
||||
// public const string ServicePathUnauthenticatedTemplate = "http://WS-GSHARP:57252/Services/Client/Unauthenticated/{0}";
|
||||
//#else
|
||||
public const string ServicePathAuthenticatedTemplate = "http://DISCO:9292/Services/Client/Authenticated/{0}";
|
||||
public const string ServicePathUnauthenticatedTemplate = "http://DISCO:9292/Services/Client/Unauthenticated/{0}";
|
||||
//#endif
|
||||
|
||||
public static ResponseType Post<ResponseType>(this ServiceBase<ResponseType> Service, bool Authenticated)
|
||||
{
|
||||
string jsonResponse;
|
||||
ResponseType serviceResponse;
|
||||
string serviceUrl;
|
||||
|
||||
if (Authenticated)
|
||||
serviceUrl = string.Format(ServicePathAuthenticatedTemplate, Service.Feature);
|
||||
else
|
||||
serviceUrl = string.Format(ServicePathUnauthenticatedTemplate, Service.Feature);
|
||||
|
||||
HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(serviceUrl);
|
||||
request.UserAgent = string.Format("Disco-Client/{0}", Assembly.GetExecutingAssembly().GetName().Version.ToString(3));
|
||||
request.UserAgent = $"Disco-Client/{Assembly.GetExecutingAssembly().GetName().Version.ToString(3)}";
|
||||
request.ContentType = "application/json";
|
||||
request.Method = WebRequestMethods.Http.Post;
|
||||
request.UseDefaultCredentials = true;
|
||||
request.Timeout = 300000; // 5 Minutes
|
||||
string jsonRequest = JsonConvert.SerializeObject(Service);
|
||||
|
||||
using (StreamWriter requestWriter = new StreamWriter(request.GetRequestStream()))
|
||||
var jsonSerializer = new JsonSerializer();
|
||||
|
||||
using (var requestWriter = new StreamWriter(request.GetRequestStream()))
|
||||
{
|
||||
requestWriter.Write(jsonRequest);
|
||||
using (var jsonWriter = new JsonTextWriter(requestWriter))
|
||||
{
|
||||
jsonSerializer.Serialize(jsonWriter, Service);
|
||||
}
|
||||
}
|
||||
|
||||
using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
|
||||
{
|
||||
using (StreamReader responseReader = new StreamReader(response.GetResponseStream()))
|
||||
using (var responseReader = new StreamReader(response.GetResponseStream()))
|
||||
{
|
||||
jsonResponse = responseReader.ReadToEnd();
|
||||
using (var jsonReader = new JsonTextReader(responseReader))
|
||||
{
|
||||
serviceResponse = jsonSerializer.Deserialize<ResponseType>(jsonReader);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(jsonResponse))
|
||||
return default(ResponseType);
|
||||
else
|
||||
return JsonConvert.DeserializeObject<ResponseType>(jsonResponse);
|
||||
return serviceResponse;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,13 +1,9 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Disco.Client.Interop;
|
||||
using Disco.Models.ClientServices;
|
||||
using System.Security.Cryptography.X509Certificates;
|
||||
using System.IO;
|
||||
using System.Diagnostics;
|
||||
using Microsoft.Win32;
|
||||
using System.Text.RegularExpressions;
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
|
||||
namespace Disco.Client.Extensions
|
||||
{
|
||||
@@ -16,26 +12,23 @@ namespace Disco.Client.Extensions
|
||||
|
||||
public static void Build(this Enrol enrol)
|
||||
{
|
||||
enrol.DeviceUUID = Interop.SystemAudit.DeviceUUID;
|
||||
enrol.DeviceSerialNumber = Interop.SystemAudit.DeviceSerialNumber;
|
||||
enrol.ComputerName = Environment.MachineName;
|
||||
enrol.RunningUserDomain = Environment.UserDomainName;
|
||||
enrol.RunningUserName = Environment.UserName;
|
||||
enrol.RunningInteractively = Environment.UserInteractive;
|
||||
|
||||
enrol.DeviceComputerName = Interop.LocalAuthentication.ComputerName;
|
||||
// Hardware Audit
|
||||
enrol.Hardware = Hardware.Information;
|
||||
enrol.SerialNumber = enrol.Hardware.SerialNumber;
|
||||
|
||||
enrol.DeviceManufacturer = Interop.SystemAudit.DeviceManufacturer;
|
||||
enrol.DeviceModel = Interop.SystemAudit.DeviceModel;
|
||||
enrol.DeviceModelType = Interop.SystemAudit.DeviceType;
|
||||
|
||||
enrol.DeviceIsPartOfDomain = Interop.SystemAudit.DeviceIsPartOfDomain;
|
||||
enrol.DeviceDNSDomainName = Interop.SystemAudit.DeviceDNSDomainName;
|
||||
|
||||
// LAN
|
||||
enrol.DeviceLanMacAddress = Interop.Network.PrimaryLanMacAddress;
|
||||
|
||||
// WAN
|
||||
enrol.DeviceWlanMacAddress = Interop.Network.PrimaryWlanMacAddress;
|
||||
// Apply System Information
|
||||
enrol.ApplySystemInformation();
|
||||
|
||||
// Certificates
|
||||
enrol.DeviceCertificates = Interop.Certificates.GetCertificateSubjects(StoreName.My, StoreLocation.LocalMachine);
|
||||
enrol.Certificates = Certificates.GetAllCertificates();
|
||||
|
||||
// Wireless Profiles
|
||||
enrol.WirelessProfiles = WirelessNetwork.GetWirelessProfiles();
|
||||
}
|
||||
|
||||
public static void Process(this EnrolResponse enrolResponse)
|
||||
@@ -51,12 +44,14 @@ namespace Disco.Client.Extensions
|
||||
// Offline Domain Join
|
||||
bool requireReboot = enrolResponse.ApplyOfflineDomainJoin();
|
||||
|
||||
// Certificates
|
||||
enrolResponse.ApplyDeviceCertificates();
|
||||
|
||||
// Device Owner
|
||||
enrolResponse.ApplyDeviceAssignedUser();
|
||||
|
||||
// Certificates
|
||||
enrolResponse.ApplyDeviceCertificates();
|
||||
|
||||
// Wireless Profiles
|
||||
enrolResponse.ApplyWirelessProfiles();
|
||||
|
||||
Presentation.UpdateStatus("Enrolling Device", "Device Enrolment Successfully Completed", false, 0, 1500);
|
||||
|
||||
@@ -71,15 +66,15 @@ namespace Disco.Client.Extensions
|
||||
/// <returns>Boolean indicating whether a reboot is required.</returns>
|
||||
private static bool ApplyOfflineDomainJoin(this EnrolResponse enrolResponse)
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(enrolResponse.OfflineDomainJoin))
|
||||
if (!string.IsNullOrWhiteSpace(enrolResponse.OfflineDomainJoinManifest))
|
||||
{
|
||||
Presentation.UpdateStatus("Enrolling Device", string.Format("Performing Offline Domain Join:{0}Renaming Computer: {1} -> {2}", Environment.NewLine, Interop.LocalAuthentication.ComputerName, enrolResponse.DeviceComputerName), true, -1, 1500);
|
||||
Presentation.UpdateStatus("Enrolling Device", $"Performing Offline Domain Join:\r\nRenaming Computer: {Environment.MachineName} -> {enrolResponse.ComputerName}", true, -1, 1500);
|
||||
|
||||
string odjFile = Path.GetTempFileName();
|
||||
File.WriteAllBytes(odjFile, Convert.FromBase64String(enrolResponse.OfflineDomainJoin));
|
||||
File.WriteAllBytes(odjFile, Convert.FromBase64String(enrolResponse.OfflineDomainJoinManifest));
|
||||
|
||||
string odjWindowsPath = Environment.GetEnvironmentVariable("SystemRoot");
|
||||
string odjProcessArguments = string.Format("/REQUESTODJ /LOADFILE \"{0}\" /WINDOWSPATH \"{1}\" /LOCALOS", odjFile, odjWindowsPath);
|
||||
string odjProcessArguments = $"/REQUESTODJ /LOADFILE \"{odjFile}\" /WINDOWSPATH \"{odjWindowsPath}\" /LOCALOS";
|
||||
|
||||
ProcessStartInfo odjProcessStartInfo = new ProcessStartInfo("DJOIN.EXE", odjProcessArguments)
|
||||
{
|
||||
@@ -95,17 +90,17 @@ namespace Disco.Client.Extensions
|
||||
odjResult = odjProcess.StandardOutput.ReadToEnd();
|
||||
odjProcess.WaitForExit(20000); // 20 Seconds
|
||||
}
|
||||
Presentation.UpdateStatus("Enrolling Device", string.Format("Offline Domain Join Result:{0}{1}", Environment.NewLine, odjResult), true, -1, 3000);
|
||||
Presentation.UpdateStatus("Enrolling Device", $"Offline Domain Join Result:\r\n{odjResult}", true, -1, 3000);
|
||||
|
||||
if (File.Exists(odjFile))
|
||||
File.Delete(odjFile);
|
||||
|
||||
// Flush Logged-On History
|
||||
if (!string.IsNullOrEmpty(enrolResponse.DeviceDomainName))
|
||||
if (!string.IsNullOrEmpty(enrolResponse.DomainName))
|
||||
{
|
||||
using (RegistryKey regWinlogon = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon", true))
|
||||
{
|
||||
regWinlogon.SetValue("DefaultDomainName", enrolResponse.DeviceDomainName, RegistryValueKind.String);
|
||||
regWinlogon.SetValue("DefaultDomainName", enrolResponse.DomainName, RegistryValueKind.String);
|
||||
regWinlogon.SetValue("DefaultUserName", String.Empty, RegistryValueKind.String);
|
||||
}
|
||||
using (RegistryKey regLogonUI = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Microsoft\Windows\CurrentVersion\Authentication\LogonUI", true))
|
||||
@@ -130,62 +125,44 @@ namespace Disco.Client.Extensions
|
||||
private static void ApplyDeviceAssignedUser(this EnrolResponse enrolResponse)
|
||||
{
|
||||
// Only run task if Assigned User was specified
|
||||
if (!string.IsNullOrWhiteSpace(enrolResponse.DeviceAssignedUserSID))
|
||||
if (!string.IsNullOrWhiteSpace(enrolResponse.AssignedUserSID))
|
||||
{
|
||||
Presentation.UpdateStatus("Enrolling Device", string.Format(@"Configuring the device owner:{0}{1} ({2}\{3})", Environment.NewLine, enrolResponse.DeviceAssignedUserName, enrolResponse.DeviceAssignedUserDomain, enrolResponse.DeviceAssignedUserUsername), true, -1, 3000);
|
||||
Presentation.UpdateStatus("Enrolling Device", $"Configuring the device owner:\r\n{enrolResponse.AssignedUserDescription} ({enrolResponse.AssignedUserDomain}\\{enrolResponse.AssignedUserUsername})", true, -1, 3000);
|
||||
|
||||
if (enrolResponse.DeviceAssignedUserIsLocalAdmin)
|
||||
Interop.LocalAuthentication.AddLocalGroupMembership("Administrators", enrolResponse.DeviceAssignedUserSID, enrolResponse.DeviceAssignedUserUsername, enrolResponse.DeviceAssignedUserDomain);
|
||||
if (enrolResponse.AssignedUserIsLocalAdmin)
|
||||
Interop.LocalAuthentication.AddLocalGroupMembership("Administrators", enrolResponse.AssignedUserSID, enrolResponse.AssignedUserUsername, enrolResponse.AssignedUserDomain);
|
||||
|
||||
// Make Windows think this user was the last to logon
|
||||
using (RegistryKey regWinlogon = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon", true))
|
||||
{
|
||||
regWinlogon.SetValue("DefaultDomainName", enrolResponse.DeviceAssignedUserDomain, RegistryValueKind.String);
|
||||
regWinlogon.SetValue("DefaultUserName", enrolResponse.DeviceAssignedUserUsername, RegistryValueKind.String);
|
||||
regWinlogon.SetValue("DefaultDomainName", enrolResponse.AssignedUserDomain, RegistryValueKind.String);
|
||||
regWinlogon.SetValue("DefaultUserName", enrolResponse.AssignedUserUsername, RegistryValueKind.String);
|
||||
}
|
||||
using (RegistryKey regLogonUI = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Microsoft\Windows\CurrentVersion\Authentication\LogonUI", true))
|
||||
{
|
||||
regLogonUI.SetValue("LastLoggedOnUser", string.Format(@"{0}\{1}", enrolResponse.DeviceAssignedUserDomain, enrolResponse.DeviceAssignedUserUsername), RegistryValueKind.String);
|
||||
regLogonUI.SetValue("LastLoggedOnUser", $@"{enrolResponse.AssignedUserDomain}\{enrolResponse.AssignedUserUsername}", RegistryValueKind.String);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Processes a Client Service Enrol Response for Device Certificate Actions
|
||||
/// </summary>
|
||||
/// <param name="enrolResponse"></param>
|
||||
private static void ApplyDeviceCertificates(this EnrolResponse enrolResponse)
|
||||
{
|
||||
// Only run if a Certificate was supplied
|
||||
if (!string.IsNullOrEmpty(enrolResponse.DeviceCertificate))
|
||||
if (enrolResponse.Certificates != null)
|
||||
{
|
||||
Presentation.UpdateStatus("Enrolling Device", "Configuring Wireless Certificates", true, -1, 1000);
|
||||
Presentation.UpdateStatus("Enrolling Device", "Configuring Certificates", true, -1, 1000);
|
||||
|
||||
var certPersonalBytes = Convert.FromBase64String(enrolResponse.DeviceCertificate);
|
||||
var certPersonal = new X509Certificate2(certPersonalBytes, "password", X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.PersistKeySet);
|
||||
if (certPersonal == null)
|
||||
throw new ClientServiceException("Enrolment > Device Certificate", "Unable to Import Device Certificate Provided, possibly check password.");
|
||||
|
||||
// Certificate Removal
|
||||
if (enrolResponse.DeviceCertificateRemoveExisting != null && enrolResponse.DeviceCertificateRemoveExisting.Count > 0)
|
||||
{
|
||||
List<Regex> regExMatchesSubject = new List<Regex>();
|
||||
foreach (var subjectRegEx in enrolResponse.DeviceCertificateRemoveExisting)
|
||||
regExMatchesSubject.Add(new Regex(subjectRegEx, RegexOptions.IgnoreCase));
|
||||
|
||||
// Remove from 'My' Store
|
||||
Interop.Certificates.RemoveCertificates(StoreName.My, StoreLocation.LocalMachine, regExMatchesSubject, certPersonal);
|
||||
// Remove from 'Root' Store
|
||||
Interop.Certificates.RemoveCertificates(StoreName.Root, StoreLocation.LocalMachine, regExMatchesSubject, certPersonal);
|
||||
// Remove from 'CertificateAuthority' Store
|
||||
Interop.Certificates.RemoveCertificates(StoreName.CertificateAuthority, StoreLocation.LocalMachine, regExMatchesSubject, certPersonal);
|
||||
}
|
||||
|
||||
// Add Certificate
|
||||
Presentation.UpdateStatus("Enrolling Device", string.Format("Configuring Wireless Certificates{0}Installing Certificate: {1}", Environment.NewLine, Interop.Certificates.GetCertificateFriendlyName(certPersonal)), true, -1);
|
||||
Interop.Certificates.AddCertificate(StoreName.My, StoreLocation.LocalMachine, certPersonal);
|
||||
enrolResponse.Certificates.Apply();
|
||||
}
|
||||
}
|
||||
|
||||
private static void ApplyWirelessProfiles(this EnrolResponse enrolResponse)
|
||||
{
|
||||
if (enrolResponse.WirelessProfiles != null)
|
||||
{
|
||||
Presentation.UpdateStatus("Enrolling Device", "Configuring Wireless Profiles", true, -1, 1000);
|
||||
|
||||
enrolResponse.WirelessProfiles.Apply();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,103 +1,130 @@
|
||||
using System;
|
||||
using Disco.Models.ClientServices.EnrolmentInformation;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Security.Cryptography.X509Certificates;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
namespace Disco.Client.Interop
|
||||
{
|
||||
public static class Certificates
|
||||
{
|
||||
|
||||
public static string GetCertificateFriendlyName(X509Certificate2 Certificate)
|
||||
public static List<Certificate> GetAllCertificates()
|
||||
{
|
||||
string subject = Certificate.Subject;
|
||||
return subject.Substring(subject.IndexOf("=") + 1, subject.IndexOf(",") - subject.IndexOf("=") - 1);
|
||||
var certificates = new List<Certificate>();
|
||||
|
||||
// Trusted Root Certificates
|
||||
certificates.AddRange(GetCertificates(StoreName.Root, "TrustedRoot"));
|
||||
|
||||
// Intermediate Certificates
|
||||
certificates.AddRange(GetCertificates(StoreName.CertificateAuthority, "Intermediate"));
|
||||
|
||||
// Personal Certificates
|
||||
certificates.AddRange(GetCertificates(StoreName.My, "Personal"));
|
||||
|
||||
return certificates;
|
||||
}
|
||||
|
||||
public static List<string> GetCertificateSubjects(StoreName StoreName, StoreLocation StoreLocation)
|
||||
private static IEnumerable<Certificate> GetCertificates(StoreName StoreName, string StoreDescription)
|
||||
{
|
||||
X509Store certStore = new X509Store(StoreName, StoreLocation);
|
||||
certStore.Open(OpenFlags.ReadOnly);
|
||||
var certSubjects = certStore.Certificates.Cast<X509Certificate2>().Select(c => c.Subject).ToList();
|
||||
certStore.Close();
|
||||
return certSubjects;
|
||||
}
|
||||
|
||||
public static bool AddCertificate(StoreName StoreName, StoreLocation StoreLocation, X509Certificate2 Certificate)
|
||||
{
|
||||
X509Store certStore = new X509Store(StoreName, StoreLocation);
|
||||
bool certAlreadyAdded = false;
|
||||
|
||||
certStore.Open(OpenFlags.ReadWrite);
|
||||
|
||||
var store = new X509Store(StoreName, StoreLocation.LocalMachine);
|
||||
store.Open(OpenFlags.ReadOnly);
|
||||
try
|
||||
{
|
||||
foreach (X509Certificate2 cert in certStore.Certificates)
|
||||
foreach (var certificate in store.Certificates)
|
||||
{
|
||||
if (cert.SerialNumber.Equals(Certificate.SerialNumber))
|
||||
yield return new Certificate()
|
||||
{
|
||||
certAlreadyAdded = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!certAlreadyAdded)
|
||||
{
|
||||
Presentation.UpdateStatus("Enrolling Device", string.Format("Configuring Wireless Certificates{0}Adding Certificate: '{1}' from {2}@{3}", Environment.NewLine, GetCertificateFriendlyName(Certificate), StoreName.ToString(), StoreLocation.ToString()), true, -1, 3000);
|
||||
certStore.Add(Certificate);
|
||||
Store = StoreDescription,
|
||||
SubjectName = certificate.SubjectName.Name,
|
||||
Thumbprint = certificate.Thumbprint,
|
||||
FriendlyName = certificate.FriendlyName,
|
||||
DnsName = certificate.GetNameInfo(X509NameType.DnsName, false),
|
||||
Version = certificate.Version,
|
||||
SignatureAlgorithm = certificate.SignatureAlgorithm.FriendlyName,
|
||||
Issuer = certificate.IssuerName.Name,
|
||||
NotAfter = certificate.NotAfter,
|
||||
NotBefore = certificate.NotBefore,
|
||||
HasPrivateKey = certificate.HasPrivateKey
|
||||
};
|
||||
}
|
||||
}
|
||||
catch (Exception) { throw; }
|
||||
finally
|
||||
{
|
||||
certStore.Close();
|
||||
store.Close();
|
||||
}
|
||||
|
||||
return !certAlreadyAdded;
|
||||
}
|
||||
|
||||
public static List<string> RemoveCertificates(StoreName StoreName, StoreLocation StoreLocation, List<Regex> RegExMatchesSubject, X509Certificate2 CertificateException)
|
||||
public static void Apply(this CertificateStore EnrolStore)
|
||||
{
|
||||
X509Store certStore = new X509Store(StoreName, StoreLocation);
|
||||
List<string> results = new List<string>();
|
||||
List<X509Certificate2> certStoreRemove = new List<X509Certificate2>();
|
||||
|
||||
certStore.Open(OpenFlags.ReadWrite);
|
||||
|
||||
try
|
||||
if (EnrolStore != null)
|
||||
{
|
||||
foreach (X509Certificate2 cert in certStore.Certificates)
|
||||
// Apply Trusted Root
|
||||
ApplyToStore(StoreName.Root, EnrolStore.TrustedRootCertificates, EnrolStore.TrustedRootRemoveThumbprints);
|
||||
|
||||
// Apply Intermediate
|
||||
ApplyToStore(StoreName.CertificateAuthority, EnrolStore.IntermediateCertificates, EnrolStore.IntermediateRemoveThumbprints);
|
||||
|
||||
// Apply Personal
|
||||
ApplyToStore(StoreName.My, EnrolStore.PersonalCertificates, EnrolStore.PersonalRemoveThumbprints);
|
||||
}
|
||||
}
|
||||
|
||||
private static void ApplyToStore(StoreName StoreName, List<byte[]> Certificates, List<string> RemoveThumbprints)
|
||||
{
|
||||
|
||||
if ((Certificates != null && Certificates.Count > 0) ||
|
||||
(RemoveThumbprints != null && RemoveThumbprints.Count > 0))
|
||||
{
|
||||
var store = new X509Store(StoreName, StoreLocation.LocalMachine);
|
||||
store.Open(OpenFlags.ReadWrite);
|
||||
try
|
||||
{
|
||||
if (!cert.SerialNumber.Equals(CertificateException.SerialNumber))
|
||||
var addedThumbprints = new List<string>();
|
||||
var existingThumbprints = store.Certificates.Cast<X509Certificate2>().GroupBy(c => c.Thumbprint).ToDictionary(c => c.Key, c => c.ToList(), StringComparer.OrdinalIgnoreCase);
|
||||
|
||||
// Add
|
||||
if (Certificates != null && Certificates.Count > 0)
|
||||
{
|
||||
foreach (var subjectRegEx in RegExMatchesSubject)
|
||||
foreach (var certificateBytes in Certificates)
|
||||
{
|
||||
if (subjectRegEx.IsMatch(cert.Subject))
|
||||
var certificate = new X509Certificate2(certificateBytes, "password", X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.PersistKeySet);
|
||||
|
||||
// check if it already exists
|
||||
if (!existingThumbprints.ContainsKey(certificate.Thumbprint) && !addedThumbprints.Contains(certificate.Thumbprint))
|
||||
{
|
||||
certStoreRemove.Add(cert);
|
||||
break;
|
||||
Presentation.UpdateStatus("Enrolling Device", $"Configuring Certificates\r\nAdding Certificate: '{certificate.GetNameInfo(X509NameType.DnsName, false)}' from {store.Name}@{store.Location}", true, -1, 1000);
|
||||
store.Add(certificate);
|
||||
addedThumbprints.Add(certificate.Thumbprint);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Remove
|
||||
if (RemoveThumbprints != null && RemoveThumbprints.Count > 0)
|
||||
{
|
||||
foreach (var thumbprint in RemoveThumbprints)
|
||||
{
|
||||
List<X509Certificate2> certificates;
|
||||
if (existingThumbprints.TryGetValue(thumbprint, out certificates) && !addedThumbprints.Contains(thumbprint))
|
||||
{
|
||||
foreach (var certificate in certificates)
|
||||
{
|
||||
Presentation.UpdateStatus("Enrolling Device", $"Configuring Certificates\r\nRemoving Certificate: '{certificate.GetNameInfo(X509NameType.DnsName, false)}' from {store.Name}@{store.Location}", true, -1, 1000);
|
||||
store.Remove(certificate);
|
||||
existingThumbprints.Remove(thumbprint);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var cert in certStoreRemove)
|
||||
finally
|
||||
{
|
||||
results.Add(cert.Subject);
|
||||
|
||||
Presentation.UpdateStatus("Enrolling Device", string.Format("Configuring Wireless Certificates{0}Removing Certificate: '{1}' from {2}@{3}", Environment.NewLine, GetCertificateFriendlyName(cert), StoreName.ToString(), StoreLocation.ToString()), true, -1, 1500);
|
||||
certStore.Remove(cert);
|
||||
store.Close();
|
||||
}
|
||||
}
|
||||
catch (Exception) { throw; }
|
||||
finally
|
||||
{
|
||||
certStore.Close();
|
||||
}
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,690 @@
|
||||
using Disco.Models.ClientServices;
|
||||
using Disco.Models.ClientServices.EnrolmentInformation;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Management;
|
||||
|
||||
namespace Disco.Client.Interop
|
||||
{
|
||||
public static class Hardware
|
||||
{
|
||||
private static DeviceHardware information;
|
||||
|
||||
public static DeviceHardware Information
|
||||
{
|
||||
get
|
||||
{
|
||||
if (information == null)
|
||||
{
|
||||
information = GatherInformation();
|
||||
}
|
||||
return information;
|
||||
}
|
||||
}
|
||||
|
||||
private static DeviceHardware GatherInformation()
|
||||
{
|
||||
var audit = new DeviceHardware();
|
||||
|
||||
audit.ApplyBIOSInformation();
|
||||
audit.ApplySystemInformation();
|
||||
audit.ApplyBaseBoardInformation();
|
||||
audit.ApplySystemProductInformation();
|
||||
|
||||
if (string.IsNullOrWhiteSpace(audit.SerialNumber))
|
||||
{
|
||||
throw new Exception("This device has no serial number stored in BIOS or BaseBoard");
|
||||
}
|
||||
if (audit.SerialNumber.Length > 60)
|
||||
{
|
||||
throw new Exception($"The serial number reported by this device is over 60 characters long:\r\n{audit.SerialNumber}");
|
||||
}
|
||||
|
||||
audit.ApplyProcessorInformation();
|
||||
audit.ApplyPhysicalMemoryInformation();
|
||||
audit.ApplyDiskDriveInformation();
|
||||
audit.ApplyBatteryInformation();
|
||||
|
||||
audit.NetworkAdapters = Network.GetNetworkAdapters();
|
||||
|
||||
return audit;
|
||||
}
|
||||
|
||||
private static void ApplyProcessorInformation(this DeviceHardware deviceHardware)
|
||||
{
|
||||
try
|
||||
{
|
||||
using (var mSearcher = new ManagementObjectSearcher("SELECT DeviceID, Manufacturer, Name, Description, Architecture, Family, MaxClockSpeed, NumberOfCores, NumberOfLogicalProcessors FROM Win32_Processor"))
|
||||
{
|
||||
using (var mResults = mSearcher.Get())
|
||||
{
|
||||
if (mResults.Count > 0)
|
||||
{
|
||||
var processors = new List<Processor>(mResults.Count);
|
||||
foreach (var mItem in mResults.Cast<ManagementObject>())
|
||||
{
|
||||
if (mItem != null)
|
||||
{
|
||||
var processor = new Processor();
|
||||
|
||||
processor.DeviceID = (string)mItem.GetPropertyValue("DeviceID");
|
||||
processor.Manufacturer = (string)mItem.GetPropertyValue("Manufacturer");
|
||||
processor.Name = (string)mItem.GetPropertyValue("Name");
|
||||
processor.Description = (string)mItem.GetPropertyValue("Description");
|
||||
processor.Family = (ushort?)mItem.GetPropertyValue("Family");
|
||||
processor.MaxClockSpeed = (uint?)mItem.GetPropertyValue("MaxClockSpeed");
|
||||
processor.NumberOfCores = (uint?)mItem.GetPropertyValue("NumberOfCores");
|
||||
processor.NumberOfLogicalProcessors = (uint?)mItem.GetPropertyValue("NumberOfLogicalProcessors");
|
||||
processor.Architecture = ((ProcessorArchitectures?)(ushort?)mItem.GetPropertyValue("Architecture"))?.ToString();
|
||||
|
||||
processors.Add(processor);
|
||||
}
|
||||
}
|
||||
deviceHardware.Processors = processors;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
// ignore errors to ensure backwards compatibility
|
||||
}
|
||||
}
|
||||
|
||||
private static void ApplyPhysicalMemoryInformation(this DeviceHardware deviceHardware)
|
||||
{
|
||||
try
|
||||
{
|
||||
using (var mSearcher = new ManagementObjectSearcher("SELECT Tag, SerialNumber, Manufacturer, PartNumber, Capacity, ConfiguredClockSpeed, Speed, DeviceLocator FROM Win32_PhysicalMemory"))
|
||||
{
|
||||
using (var mResults = mSearcher.Get())
|
||||
{
|
||||
if (mResults.Count > 0)
|
||||
{
|
||||
var physicalMemories = new List<PhysicalMemory>(mResults.Count);
|
||||
foreach (var mItem in mResults.Cast<ManagementObject>())
|
||||
{
|
||||
if (mItem != null)
|
||||
{
|
||||
var physicalMemory = new PhysicalMemory();
|
||||
|
||||
physicalMemory.Tag = (string)mItem.GetPropertyValue("Tag");
|
||||
physicalMemory.SerialNumber = (string)mItem.GetPropertyValue("SerialNumber");
|
||||
physicalMemory.Manufacturer = (string)mItem.GetPropertyValue("Manufacturer");
|
||||
physicalMemory.PartNumber = (string)mItem.GetPropertyValue("PartNumber");
|
||||
physicalMemory.Capacity = (ulong?)mItem.GetPropertyValue("Capacity");
|
||||
physicalMemory.ConfiguredClockSpeed = (uint?)mItem.GetPropertyValue("ConfiguredClockSpeed");
|
||||
physicalMemory.Speed = (uint?)mItem.GetPropertyValue("Speed");
|
||||
physicalMemory.DeviceLocator = (string)mItem.GetPropertyValue("DeviceLocator");
|
||||
|
||||
physicalMemories.Add(physicalMemory);
|
||||
}
|
||||
}
|
||||
deviceHardware.PhysicalMemory = physicalMemories;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
// ignore errors to ensure backwards compatibility
|
||||
}
|
||||
}
|
||||
|
||||
private static void ApplyDiskDriveInformation(this DeviceHardware deviceHardware)
|
||||
{
|
||||
try
|
||||
{
|
||||
using (var diskSearcher = new ManagementObjectSearcher("SELECT DeviceID, Manufacturer, Model, MediaType, InterfaceType, SerialNumber, FirmwareRevision, Size FROM Win32_DiskDrive"))
|
||||
{
|
||||
using (var diskResults = diskSearcher.Get())
|
||||
{
|
||||
if (diskResults.Count > 0)
|
||||
{
|
||||
var diskDrives = new List<DiskDrive>(diskResults.Count);
|
||||
foreach (var diskResult in diskResults.Cast<ManagementObject>())
|
||||
{
|
||||
if (diskResult != null)
|
||||
{
|
||||
var diskDrive = new DiskDrive();
|
||||
|
||||
diskDrive.DeviceID = (string)diskResult.GetPropertyValue("DeviceID");
|
||||
diskDrive.Manufacturer = (string)diskResult.GetPropertyValue("Manufacturer");
|
||||
diskDrive.Model = (string)diskResult.GetPropertyValue("Model");
|
||||
diskDrive.MediaType = (string)diskResult.GetPropertyValue("MediaType");
|
||||
diskDrive.InterfaceType = (string)diskResult.GetPropertyValue("InterfaceType");
|
||||
diskDrive.SerialNumber = (string)diskResult.GetPropertyValue("SerialNumber");
|
||||
diskDrive.FirmwareRevision = (string)diskResult.GetPropertyValue("FirmwareRevision");
|
||||
diskDrive.Size = (ulong?)diskResult.GetPropertyValue("Size");
|
||||
|
||||
using (var partitionSearcher = new ManagementObjectSearcher($"ASSOCIATORS OF {{Win32_DiskDrive.DeviceID=\"{diskDrive.DeviceID.Replace(@"\", @"\\")}\"}} WHERE AssocClass = Win32_DiskDriveToDiskPartition"))
|
||||
{
|
||||
using (var partitionResults = partitionSearcher.Get())
|
||||
{
|
||||
if (partitionResults.Count > 0)
|
||||
{
|
||||
var partitions = new List<DiskDrivePartition>(partitionResults.Count);
|
||||
foreach (var partitionResult in partitionResults.Cast<ManagementObject>())
|
||||
{
|
||||
if (partitionResult != null)
|
||||
{
|
||||
var partition = new DiskDrivePartition();
|
||||
|
||||
partition.DeviceID = (string)partitionResult.GetPropertyValue("DeviceID");
|
||||
partition.Bootable = (bool?)partitionResult.GetPropertyValue("Bootable");
|
||||
partition.BootPartition = (bool?)partitionResult.GetPropertyValue("BootPartition");
|
||||
partition.PrimaryParition = (bool?)partitionResult.GetPropertyValue("PrimaryPartition");
|
||||
partition.Size = (ulong?)partitionResult.GetPropertyValue("Size");
|
||||
partition.StartingOffset = (ulong?)partitionResult.GetPropertyValue("StartingOffset");
|
||||
partition.Type = (string)partitionResult.GetPropertyValue("Type");
|
||||
|
||||
using (var logicalSearcher = new ManagementObjectSearcher($"ASSOCIATORS OF {{Win32_DiskPartition.DeviceID=\"{partition.DeviceID}\"}} WHERE AssocClass = Win32_LogicalDiskToPartition"))
|
||||
{
|
||||
using (var logicalResults = logicalSearcher.Get())
|
||||
{
|
||||
if (logicalResults.Count > 0)
|
||||
{
|
||||
foreach (var logicalResult in logicalResults.Cast<ManagementObject>().Take(1))
|
||||
{
|
||||
if (logicalResult != null)
|
||||
{
|
||||
var logical = new DiskLogical();
|
||||
|
||||
logical.DeviceID = (string)logicalResult.GetPropertyValue("DeviceID");
|
||||
logical.Description = (string)logicalResult.GetPropertyValue("Description");
|
||||
logical.DriveType = ((DiskLogicalDriveTypes?)(uint?)logicalResult.GetPropertyValue("DriveType")).ToString();
|
||||
logical.MediaType = ((DiskLogicalMediaTypes?)(uint?)logicalResult.GetPropertyValue("MediaType")).ToString();
|
||||
logical.FileSystem = (string)logicalResult.GetPropertyValue("FileSystem");
|
||||
logical.Size = (ulong?)logicalResult.GetPropertyValue("Size");
|
||||
logical.FreeSpace = (ulong?)logicalResult.GetPropertyValue("FreeSpace");
|
||||
logical.VolumeName = (string)logicalResult.GetPropertyValue("VolumeName");
|
||||
logical.VolumeSerialNumber = (string)logicalResult.GetPropertyValue("VolumeSerialNumber");
|
||||
|
||||
partition.LogicalDisk = logical;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
partitions.Add(partition);
|
||||
}
|
||||
}
|
||||
diskDrive.Partitions = partitions;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
diskDrives.Add(diskDrive);
|
||||
}
|
||||
}
|
||||
|
||||
deviceHardware.DiskDrives = diskDrives;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
// ignore errors to ensure backwards compatibility
|
||||
}
|
||||
}
|
||||
private static void ApplyBatteryInformation(this DeviceHardware deviceHardware)
|
||||
{
|
||||
try
|
||||
{
|
||||
using (var mSearcher = new ManagementObjectSearcher("SELECT DeviceID, Availability, Chemistry, Description, DesignCapacity, DesignVoltage, FullChargeCapacity, Name FROM Win32_Battery"))
|
||||
{
|
||||
using (var mResults = mSearcher.Get())
|
||||
{
|
||||
if (mResults.Count > 0)
|
||||
{
|
||||
var batteries = new List<Battery>(mResults.Count);
|
||||
foreach (var mItem in mResults.Cast<ManagementObject>())
|
||||
{
|
||||
if (mItem != null)
|
||||
{
|
||||
var battery = new Battery();
|
||||
|
||||
battery.Availability = ((BatteryAvailability?)(ushort?)mItem.GetPropertyValue("Availability"))?.ToString();
|
||||
battery.Chemistry = ((BatteryChemistry?)(ushort?)mItem.GetPropertyValue("Chemistry"))?.ToString();
|
||||
battery.Description = (string)mItem.GetPropertyValue("Description");
|
||||
battery.DesignCapacity = (uint?)mItem.GetPropertyValue("DesignCapacity");
|
||||
battery.DeviceID = (string)mItem.GetPropertyValue("DeviceID");
|
||||
battery.FullChargeCapacity = (uint?)mItem.GetPropertyValue("FullChargeCapacity");
|
||||
battery.Name = (string)mItem.GetPropertyValue("Name");
|
||||
|
||||
batteries.Add(battery);
|
||||
}
|
||||
}
|
||||
deviceHardware.Batteries = batteries;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
// ignore errors to ensure backwards compatibility
|
||||
}
|
||||
}
|
||||
|
||||
private static void ApplyBIOSInformation(this DeviceHardware deviceHardware)
|
||||
{
|
||||
try
|
||||
{
|
||||
using (var mSearcher = new ManagementObjectSearcher("SELECT BIOSVersion, Manufacturer, ReleaseDate, SerialNumber, SMBIOSBIOSVersion, SMBIOSMajorVersion, SMBIOSMinorVersion, SystemBiosMajorVersion, SystemBiosMinorVersion FROM Win32_BIOS WHERE PrimaryBios=true"))
|
||||
{
|
||||
using (var mResults = mSearcher.Get())
|
||||
{
|
||||
using (var mItem = mResults.Cast<ManagementObject>().FirstOrDefault())
|
||||
{
|
||||
if (mItem != null)
|
||||
{
|
||||
var serialNumber = (string)mItem.GetPropertyValue("SerialNumber");
|
||||
if (!string.IsNullOrWhiteSpace(serialNumber))
|
||||
deviceHardware.SerialNumber = serialNumber.Trim();
|
||||
|
||||
var manufacturer = (string)mItem.GetPropertyValue("Manufacturer");
|
||||
if (deviceHardware.Manufacturer == null && !string.IsNullOrWhiteSpace(manufacturer))
|
||||
deviceHardware.Manufacturer = manufacturer.Trim();
|
||||
|
||||
ErrorReporting.DeviceIdentifier = deviceHardware.SerialNumber;
|
||||
|
||||
var biosVersion = (string[])mItem.GetPropertyValue("BIOSVersion");
|
||||
var releaseDate = default(DateTime?);
|
||||
var releaseDateString = (string)mItem.GetPropertyValue("ReleaseDate");
|
||||
if (releaseDateString != null && releaseDateString.Length == 25 && int.TryParse(releaseDateString.Substring(22), out var offsetMinutes))
|
||||
{
|
||||
releaseDateString = $"{releaseDateString.Substring(0, 22)}{offsetMinutes / 60:00}:{Math.Abs(offsetMinutes % 60):00}";
|
||||
if (DateTime.TryParseExact(releaseDateString, "yyyyMMddHHmmss.ffffffzzz", CultureInfo.InvariantCulture, DateTimeStyles.AdjustToUniversal, out var releaseDateResult))
|
||||
releaseDate = releaseDateResult;
|
||||
}
|
||||
var sMBIOSBIOSVersion = (string)mItem.GetPropertyValue("SMBIOSBIOSVersion");
|
||||
var sMBIOSMajorVersion = (ushort?)mItem.GetPropertyValue("SMBIOSMajorVersion");
|
||||
var sMBIOSMinorVersion = (ushort?)mItem.GetPropertyValue("SMBIOSMinorVersion");
|
||||
var systemBiosMajorVersion = (byte?)mItem.GetPropertyValue("SystemBiosMajorVersion");
|
||||
var systemBiosMinorVersion = (byte?)mItem.GetPropertyValue("SystemBiosMinorVersion");
|
||||
|
||||
var bios = new Bios()
|
||||
{
|
||||
BIOSVersion = biosVersion,
|
||||
Manufacturer = manufacturer,
|
||||
ReleaseDate = releaseDate,
|
||||
SerialNumber = serialNumber,
|
||||
SMBIOSBIOSVersion = sMBIOSBIOSVersion,
|
||||
SMBIOSMajorVersion = sMBIOSMajorVersion,
|
||||
SMBIOSMinorVersion = sMBIOSMinorVersion,
|
||||
SystemBiosMajorVersion = systemBiosMajorVersion,
|
||||
SystemBiosMinorVersion = systemBiosMinorVersion,
|
||||
};
|
||||
deviceHardware.Bios = new List<Bios>() { bios };
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new Exception("No Win32_BIOS WHERE PrimaryBios=true was found");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw new Exception("Disco ICT Client was unable to retrieve BIOS information from WMI", ex);
|
||||
}
|
||||
}
|
||||
|
||||
private static void ApplySystemInformation(this DeviceHardware deviceHardware)
|
||||
{
|
||||
try
|
||||
{
|
||||
using (var mSearcher = new ManagementObjectSearcher("SELECT ChassisSKUNumber, CurrentTimeZone, Description, Manufacturer, Model, OEMStringArray, PCSystemType, PrimaryOwnerContact, PrimaryOwnerName, Roles, SystemSKUNumber, SystemType FROM Win32_ComputerSystem"))
|
||||
{
|
||||
using (var mResults = mSearcher.Get())
|
||||
{
|
||||
using (var mItem = mResults.Cast<ManagementObject>().FirstOrDefault())
|
||||
{
|
||||
if (mItem != null)
|
||||
{
|
||||
var manufacturer = (string)mItem.GetPropertyValue("Manufacturer");
|
||||
if (!string.IsNullOrWhiteSpace(manufacturer))
|
||||
deviceHardware.Manufacturer = manufacturer.Trim();
|
||||
|
||||
var model = (string)mItem.GetPropertyValue("Model");
|
||||
if (!string.IsNullOrWhiteSpace(model))
|
||||
deviceHardware.Model = model;
|
||||
|
||||
deviceHardware.ModelType = ((PCSystemTypes)mItem.GetPropertyValue("PCSystemType")).Description();
|
||||
|
||||
var chassisSKUNumber = (string)mItem.GetPropertyValue("ChassisSKUNumber");
|
||||
var currentTimeZone = (short?)mItem.GetPropertyValue("CurrentTimeZone");
|
||||
var description = (string)mItem.GetPropertyValue("Description");
|
||||
var oemStringArray = (string[])mItem.GetPropertyValue("OEMStringArray");
|
||||
var pcSystemType = ((PCSystemTypes)mItem.GetPropertyValue("PCSystemType")).ToString();
|
||||
var primaryOwnerContact = (string)mItem.GetPropertyValue("PrimaryOwnerContact");
|
||||
var primaryOwnerName = (string)mItem.GetPropertyValue("PrimaryOwnerName");
|
||||
var roles = (string[])mItem.GetPropertyValue("Roles");
|
||||
var systemSKUNumber = (string)mItem.GetPropertyValue("SystemSKUNumber");
|
||||
var systemType = (string)mItem.GetPropertyValue("SystemType");
|
||||
|
||||
var computerSystem = new ComputerSystem()
|
||||
{
|
||||
ChassisSKUNumber = chassisSKUNumber,
|
||||
CurrentTimeZone = currentTimeZone,
|
||||
Description = description,
|
||||
OEMStringArray = oemStringArray,
|
||||
PCSystemType = pcSystemType,
|
||||
PrimaryOwnerContact = primaryOwnerContact,
|
||||
PrimaryOwnerName = primaryOwnerName,
|
||||
Roles = roles,
|
||||
SystemSKUNumber = systemSKUNumber,
|
||||
SystemType = systemType,
|
||||
};
|
||||
|
||||
deviceHardware.ComputerSystem = new List<ComputerSystem>() { computerSystem };
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new Exception("No Win32_ComputerSystem was found");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw new Exception("Disco ICT Client was unable to retrieve ComputerSystem information from WMI", ex);
|
||||
}
|
||||
}
|
||||
|
||||
public static void ApplySystemInformation(this Enrol enrol)
|
||||
{
|
||||
try
|
||||
{
|
||||
using (var mSearcher = new ManagementObjectSearcher("SELECT PartOfDomain, Domain FROM Win32_ComputerSystem"))
|
||||
{
|
||||
using (var mResults = mSearcher.Get())
|
||||
{
|
||||
using (var mItem = mResults.Cast<ManagementObject>().FirstOrDefault())
|
||||
{
|
||||
if (mItem != null)
|
||||
{
|
||||
enrol.IsPartOfDomain = (bool)mItem.GetPropertyValue("PartOfDomain");
|
||||
|
||||
if (enrol.IsPartOfDomain)
|
||||
{
|
||||
enrol.DNSDomainName = (string)mItem.GetPropertyValue("Domain");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new Exception("No Win32_ComputerSystem was found");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw new Exception("Disco ICT Client was unable to retrieve ComputerSystem information from WMI", ex);
|
||||
}
|
||||
}
|
||||
|
||||
private static void ApplyBaseBoardInformation(this DeviceHardware deviceHardware)
|
||||
{
|
||||
try
|
||||
{
|
||||
using (var mSearcher = new ManagementObjectSearcher("SELECT ConfigOptions, Manufacturer, Model, PartNumber, Product, SerialNumber, SKU, Version FROM Win32_BaseBoard"))
|
||||
{
|
||||
using (var mResults = mSearcher.Get())
|
||||
{
|
||||
using (var mItem = mResults.Cast<ManagementObject>().FirstOrDefault())
|
||||
{
|
||||
if (mItem != null)
|
||||
{
|
||||
// Apply Manufacturer/Model information only if not previously found in Win32_ComputerSystem
|
||||
var manufacturer = (string)mItem.GetPropertyValue("Manufacturer");
|
||||
if (deviceHardware.Manufacturer == null && !string.IsNullOrWhiteSpace(manufacturer))
|
||||
{
|
||||
deviceHardware.Manufacturer = manufacturer.Trim();
|
||||
}
|
||||
|
||||
var model = (string)mItem.GetPropertyValue("Model");
|
||||
if (deviceHardware.Model == null && !string.IsNullOrWhiteSpace(model))
|
||||
{
|
||||
deviceHardware.Model = model;
|
||||
}
|
||||
|
||||
var product = (string)mItem.GetPropertyValue("Product");
|
||||
if (deviceHardware.Model == null && !string.IsNullOrWhiteSpace(product))
|
||||
{
|
||||
deviceHardware.Model = product;
|
||||
}
|
||||
|
||||
// Added 2012-11-22 G# - Lenovo IdeaPad Serial SHIM
|
||||
// http://www.discoict.com.au/forum/feature-requests/2012/11/serial-number-detection-on-ideapads.aspx
|
||||
var serialNumber = (string)mItem.GetPropertyValue("SerialNumber");
|
||||
if (!string.IsNullOrWhiteSpace(serialNumber) &&
|
||||
(deviceHardware.SerialNumber == null ||
|
||||
((deviceHardware.Manufacturer?.Equals("LENOVO", StringComparison.OrdinalIgnoreCase) ?? false) &&
|
||||
((deviceHardware.Model?.Equals("S10-3", StringComparison.OrdinalIgnoreCase) ?? false) // S10-3
|
||||
|| (deviceHardware.Model?.Equals("2957", StringComparison.OrdinalIgnoreCase) ?? false)))))
|
||||
{
|
||||
deviceHardware.SerialNumber = serialNumber.Trim();
|
||||
ErrorReporting.DeviceIdentifier = deviceHardware.SerialNumber;
|
||||
}
|
||||
|
||||
var configOptions = (string[])mItem.GetPropertyValue("ConfigOptions");
|
||||
var partNumber = (string)mItem.GetPropertyValue("PartNumber");
|
||||
var sku = (string)mItem.GetPropertyValue("SKU");
|
||||
var version = (string)mItem.GetPropertyValue("Version");
|
||||
|
||||
var baseBoard = new BaseBoard()
|
||||
{
|
||||
ConfigOptions = configOptions,
|
||||
Manufacturer = manufacturer,
|
||||
Model = model,
|
||||
PartNumber = partNumber,
|
||||
Product = product,
|
||||
SerialNumber = serialNumber,
|
||||
SKU = sku,
|
||||
Version = version,
|
||||
};
|
||||
|
||||
deviceHardware.BasebBoard = new List<BaseBoard>() { baseBoard };
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new Exception("No Win32_BaseBoard was found");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw new Exception("Disco ICT Client was unable to retrieve BaseBoard information from WMI", ex);
|
||||
}
|
||||
}
|
||||
|
||||
private static void ApplySystemProductInformation(this DeviceHardware deviceHardware)
|
||||
{
|
||||
try
|
||||
{
|
||||
using (var mSearcher = new ManagementObjectSearcher("SELECT IdentifyingNumber, UUID FROM Win32_ComputerSystemProduct"))
|
||||
{
|
||||
using (var mResults = mSearcher.Get())
|
||||
{
|
||||
using (var mItem = mResults.Cast<ManagementObject>().FirstOrDefault())
|
||||
{
|
||||
if (mItem != null)
|
||||
{
|
||||
if (deviceHardware.SerialNumber == null)
|
||||
{
|
||||
var serialNumber = mItem.GetPropertyValue("IdentifyingNumber") as string;
|
||||
if (!string.IsNullOrWhiteSpace(serialNumber))
|
||||
{
|
||||
deviceHardware.SerialNumber = serialNumber.Trim();
|
||||
ErrorReporting.DeviceIdentifier = deviceHardware.SerialNumber;
|
||||
}
|
||||
}
|
||||
|
||||
var uUID = (string)mItem.GetPropertyValue("UUID");
|
||||
if (!string.IsNullOrWhiteSpace(uUID))
|
||||
{
|
||||
deviceHardware.UUID = uUID.Trim();
|
||||
|
||||
// if serial number is absent attempt using UUID if valid
|
||||
if (string.IsNullOrWhiteSpace(deviceHardware.SerialNumber))
|
||||
{
|
||||
Guid uuidGuid;
|
||||
if (Guid.TryParse(deviceHardware.UUID, out uuidGuid) && uuidGuid != Guid.Empty)
|
||||
{
|
||||
deviceHardware.SerialNumber = $"UUID{uuidGuid:N}";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new Exception("No Win32_ComputerSystemProduct was found");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw new Exception("Disco ICT Client was unable to retrieve ComputerSystemProduct information from WMI", ex);
|
||||
}
|
||||
}
|
||||
|
||||
private static string Description(this PCSystemTypes type)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case PCSystemTypes.Desktop:
|
||||
return "Desktop";
|
||||
case PCSystemTypes.Mobile:
|
||||
return "Mobile";
|
||||
case PCSystemTypes.Workstation:
|
||||
return "Workstation";
|
||||
case PCSystemTypes.EnterpriseServer:
|
||||
return "Enterprise Server";
|
||||
case PCSystemTypes.SmallOfficeAndHomeOfficeServer:
|
||||
return "Small Office And Home Office Server";
|
||||
case PCSystemTypes.AppliancePC:
|
||||
return "Appliance PC";
|
||||
case PCSystemTypes.PerformanceServer:
|
||||
return "Performance Server";
|
||||
case PCSystemTypes.Maximum:
|
||||
return "Maximum";
|
||||
case PCSystemTypes.Unknown:
|
||||
default:
|
||||
return "Unknown";
|
||||
}
|
||||
}
|
||||
|
||||
private enum PCSystemTypes : ushort
|
||||
{
|
||||
Unknown = 0,
|
||||
Desktop,
|
||||
Mobile,
|
||||
Workstation,
|
||||
EnterpriseServer,
|
||||
SmallOfficeAndHomeOfficeServer,
|
||||
AppliancePC,
|
||||
PerformanceServer,
|
||||
Maximum
|
||||
}
|
||||
|
||||
private enum ProcessorArchitectures : ushort
|
||||
{
|
||||
x86 = 0,
|
||||
MIPS = 1,
|
||||
Alpha = 2,
|
||||
PowerPC = 3,
|
||||
ia64 = 6,
|
||||
x64 = 9,
|
||||
}
|
||||
|
||||
private enum DiskLogicalDriveTypes : uint
|
||||
{
|
||||
Unknown = 0,
|
||||
NoRootDirectory,
|
||||
Removable,
|
||||
Fixed,
|
||||
Remote,
|
||||
CDRom,
|
||||
RAMDisk,
|
||||
}
|
||||
|
||||
private enum DiskLogicalMediaTypes : uint
|
||||
{
|
||||
Unknown = 0,
|
||||
F5_1Pt2_512,
|
||||
F3_1Pt44_512,
|
||||
F3_2Pt88_512,
|
||||
F3_20Pt8_512,
|
||||
F3_720_512,
|
||||
F5_360_512,
|
||||
F5_320_512,
|
||||
F5_320_1024,
|
||||
F5_180_512,
|
||||
F5_160_512,
|
||||
RemovableMedia,
|
||||
FixedMedia,
|
||||
F3_120M_512,
|
||||
F3_640_512,
|
||||
F5_640_512,
|
||||
F5_720_512,
|
||||
F3_1Pt2_512,
|
||||
F3_1Pt23_1024,
|
||||
F5_1Pt23_1024,
|
||||
F3_128Mb_512,
|
||||
F3_230Mb_512,
|
||||
F8_256_128,
|
||||
F3_200Mb_512,
|
||||
F3_240M_512,
|
||||
F3_32M_512,
|
||||
}
|
||||
|
||||
private enum BatteryAvailability : ushort
|
||||
{
|
||||
Other = 1,
|
||||
Unknown = 2,
|
||||
RunningFullPower = 3,
|
||||
Warning = 4,
|
||||
InTest = 5,
|
||||
NotApplicable = 6,
|
||||
PowerOff = 7,
|
||||
OffLine = 8,
|
||||
OffDuty = 9,
|
||||
Degraded = 10,
|
||||
NotInstalled = 11,
|
||||
InstallError = 12,
|
||||
PowerSaveUnknown = 13,
|
||||
PowerSaveLowPowerMode = 14,
|
||||
PowerSaveStandby = 15,
|
||||
PowerCycle = 16,
|
||||
PowerSaveWarning = 17,
|
||||
Paused = 18,
|
||||
NotReady = 19,
|
||||
NotConfigured = 20,
|
||||
Quiesced = 21,
|
||||
}
|
||||
|
||||
private enum BatteryChemistry : ushort
|
||||
{
|
||||
Other = 1,
|
||||
Unknown = 2,
|
||||
LeadAcid = 3,
|
||||
NickelCadmium = 4,
|
||||
NickelMetalHydride = 5,
|
||||
LithiumIon = 6,
|
||||
ZincAir = 7,
|
||||
LithiumPolymer = 8,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,10 +1,6 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.DirectoryServices;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Disco.Client.Interop
|
||||
{
|
||||
@@ -14,7 +10,7 @@ namespace Disco.Client.Interop
|
||||
public static bool AddLocalGroupMembership(string GroupName, string UserSID, string Username, string UserDomain)
|
||||
{
|
||||
|
||||
using (DirectoryEntry group = new DirectoryEntry(string.Format("WinNT://./{0},group", GroupName)))
|
||||
using (DirectoryEntry group = new DirectoryEntry($"WinNT://./{GroupName},group"))
|
||||
{
|
||||
// Check to see if the User is already a member
|
||||
foreach (object memberRef in (IEnumerable)group.Invoke("Members"))
|
||||
@@ -22,38 +18,15 @@ namespace Disco.Client.Interop
|
||||
using (DirectoryEntry member = new DirectoryEntry(memberRef))
|
||||
{
|
||||
var memberPath = member.Path;
|
||||
if (memberPath.Equals(string.Format("WinNT://{0}/{1}", UserDomain, Username), StringComparison.OrdinalIgnoreCase) ||
|
||||
memberPath.Equals(string.Format("WinNT://{0}", UserSID), StringComparison.OrdinalIgnoreCase))
|
||||
if (memberPath.Equals($"WinNT://{UserDomain}/{Username}", StringComparison.OrdinalIgnoreCase) ||
|
||||
memberPath.Equals($"WinNT://{UserSID}", StringComparison.OrdinalIgnoreCase))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
group.Invoke("Add", string.Format("WinNT://{0}", UserSID));
|
||||
group.Invoke("Add", $"WinNT://{UserSID}");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public static string CurrentUserDomain
|
||||
{
|
||||
get
|
||||
{
|
||||
return Environment.UserDomainName;
|
||||
}
|
||||
}
|
||||
public static string CurrentUserName
|
||||
{
|
||||
get
|
||||
{
|
||||
return Environment.UserName;
|
||||
}
|
||||
}
|
||||
|
||||
public static string ComputerName
|
||||
{
|
||||
get
|
||||
{
|
||||
return Environment.MachineName;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace Disco.Client.Interop.Native
|
||||
{
|
||||
public enum NetworkConnectionStatuses : ushort
|
||||
{
|
||||
Disconnected = 0,
|
||||
Connecting,
|
||||
Connected,
|
||||
Disconnecting,
|
||||
HardwareNotPresent,
|
||||
HardwareDisabled,
|
||||
HardwareMalfunction,
|
||||
MediaDisconnected,
|
||||
Authenticating,
|
||||
AuthenticationSucceeded,
|
||||
AuthenticationFailed,
|
||||
InvalidAddress,
|
||||
CredentialsRequired
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
using System;
|
||||
|
||||
namespace Disco.Client.Interop.Native
|
||||
{
|
||||
[Flags]
|
||||
public enum ProfileInfoFlags : uint
|
||||
{
|
||||
WLAN_PROFILE_GROUP_POLICY = 1,
|
||||
WLAN_PROFILE_USER = 2
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Disco.Client.Interop.Native
|
||||
{
|
||||
/// <summary >
|
||||
/// The WLAN_INTERFACE_INFO structure contains information about a wireless LAN interface.
|
||||
/// </summary >
|
||||
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
|
||||
public struct WLAN_INTERFACE_INFO
|
||||
{
|
||||
/// <summary>
|
||||
/// Contains the GUID of the interface.
|
||||
/// </summary>
|
||||
public Guid InterfaceGuid;
|
||||
|
||||
/// <summary>
|
||||
/// Contains the description of the interface.
|
||||
/// </summary>
|
||||
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
|
||||
public string strInterfaceDescription;
|
||||
|
||||
/// <summary>
|
||||
/// Contains a WLAN_INTERFACE_STATE value that indicates the current state of the interface.
|
||||
/// Windows XP with SP3 and Wireless LAN API for Windows XP with SP2: Only the wlan_interface_state_connected,
|
||||
/// wlan_interface_state_disconnected, and wlan_interface_state_authenticating values are supported.
|
||||
/// </summary>
|
||||
public WLAN_INTERFACE_STATE isState;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Disco.Client.Interop.Native
|
||||
{
|
||||
/// <summary>
|
||||
/// The WLAN_INTERFACE_INFO_LIST structure contains an array of NIC interface information.
|
||||
/// </summary>
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct WLAN_INTERFACE_INFO_LIST
|
||||
{
|
||||
/// <summary>
|
||||
/// Contains the number of items in the InterfaceInfo member.
|
||||
/// </summary>
|
||||
public uint dwNumberOfItems;
|
||||
/// <summary>
|
||||
/// The index of the current item. The index of the first item is 0. dwIndex must be less than dwNumberOfItems.
|
||||
/// This member is not used by the wireless service. Applications can use this member when processing individual
|
||||
/// interfaces in the WLAN_INTERFACE_INFO_LIST structure. When an application passes this structure from one
|
||||
/// function to another, it can set the value of dwIndex to the index of the item currently being processed.
|
||||
/// This can help an application maintain state.
|
||||
/// dwIndex should always be initialized before use.
|
||||
/// </summary>
|
||||
public uint dwIndex;
|
||||
|
||||
private IntPtr InterfaceInfoPtr;
|
||||
|
||||
/// <summary>
|
||||
/// An array of WLAN_INTERFACE_INFO structures containing interface information.
|
||||
/// </summary>
|
||||
public IEnumerable<WLAN_INTERFACE_INFO> InterfaceInfo
|
||||
{
|
||||
get
|
||||
{
|
||||
var size = Marshal.SizeOf(typeof(WLAN_INTERFACE_INFO));
|
||||
for (int i = 0; i < dwNumberOfItems; i++)
|
||||
{
|
||||
yield return (WLAN_INTERFACE_INFO)Marshal.PtrToStructure(InterfaceInfoPtr + (i * size), typeof(WLAN_INTERFACE_INFO));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public WLAN_INTERFACE_INFO_LIST(IntPtr Pointer)
|
||||
{
|
||||
dwNumberOfItems = (uint)Marshal.ReadInt32(Pointer, 0);
|
||||
dwIndex = (uint)Marshal.ReadInt32(Pointer, 4);
|
||||
InterfaceInfoPtr = Pointer + 8;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
namespace Disco.Client.Interop.Native
|
||||
{
|
||||
/// <summary>
|
||||
/// The WLAN_INTERFACE_STATE enumerated type indicates the state of an interface.
|
||||
/// Windows XP with SP3 and Wireless LAN API for Windows XP with SP2: Only the wlan_interface_state_connected,
|
||||
/// wlan_interface_state_disconnected, and wlan_interface_state_authenticating values are supported.
|
||||
/// </summary>
|
||||
public enum WLAN_INTERFACE_STATE
|
||||
{
|
||||
/// <summary>
|
||||
/// The interface is not ready to operate.
|
||||
/// </summary>
|
||||
wlan_interface_state_not_ready = 0,
|
||||
/// <summary>
|
||||
/// The interface is connected to a network.
|
||||
/// </summary>
|
||||
wlan_interface_state_connected = 1,
|
||||
/// <summary>
|
||||
/// The interface is the first node in an ad hoc network. No peer has connected.
|
||||
/// </summary>
|
||||
wlan_interface_state_ad_hoc_network_formed = 2,
|
||||
/// <summary>
|
||||
/// The interface is disconnecting from the current network.
|
||||
/// </summary>
|
||||
wlan_interface_state_disconnecting = 3,
|
||||
/// <summary>
|
||||
/// The interface is not connected to any network.
|
||||
/// </summary>
|
||||
wlan_interface_state_disconnected = 4,
|
||||
/// <summary>
|
||||
/// The interface is attempting to associate with a network.
|
||||
/// </summary>
|
||||
wlan_interface_state_associating = 5,
|
||||
/// <summary>
|
||||
/// Auto configuration is discovering the settings for the network.
|
||||
/// </summary>
|
||||
wlan_interface_state_discovering = 6,
|
||||
/// <summary>
|
||||
/// The interface is in the process of authenticating.
|
||||
/// </summary>
|
||||
wlan_interface_state_authenticating = 7,
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Disco.Client.Interop.Native
|
||||
{
|
||||
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
|
||||
public struct WLAN_PROFILE_INFO
|
||||
{
|
||||
/// <summary>
|
||||
/// The name of the profile. This value may be the name of a domain if the profile is for provisioning. Profile names are case-sensitive.
|
||||
/// This string must be NULL-terminated.
|
||||
/// Windows XP with SP3 and Wireless LAN API for Windows XP with SP2: The name of the profile is derived automatically from
|
||||
/// the SSID of the wireless network. For infrastructure network profiles, the name of the profile is the SSID of the network.
|
||||
/// For ad hoc network profiles, the name of the profile is the SSID of the ad hoc network followed by -adhoc.
|
||||
/// </summary>
|
||||
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
|
||||
public string strInterfaceDescription;
|
||||
|
||||
/// <summary>
|
||||
/// A set of flags specifying settings for wireless profile. These values are defined in the Wlanapi.h header file.
|
||||
/// Windows XP with SP3 and Wireless LAN API for Windows XP with SP2: dwFlags must be 0. Per-user profiles are not supported.
|
||||
/// </summary>
|
||||
public ProfileInfoFlags dwFlags;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Disco.Client.Interop.Native
|
||||
{
|
||||
public struct WLAN_PROFILE_INFO_LIST
|
||||
{
|
||||
/// <summary>
|
||||
/// The number of wireless profile entries in the ProfileInfo member.
|
||||
/// </summary>
|
||||
public uint dwNumberOfItems;
|
||||
|
||||
/// <summary>
|
||||
/// The index of the current item. The index of the first item is 0. The dwIndex member must be less than the dwNumberOfItems member.
|
||||
/// This member is not used by the wireless service. Applications can use this member when processing individual profiles in the
|
||||
/// WLAN_PROFILE_INFO_LIST structure. When an application passes this structure from one function to another, it can set the value
|
||||
/// of dwIndex to the index of the item currently being processed. This can help an application maintain state.
|
||||
/// dwIndex should always be initialized before use.
|
||||
/// </summary>
|
||||
public uint dwIndex;
|
||||
|
||||
private IntPtr ProfileInfoPointer;
|
||||
|
||||
/// <summary>
|
||||
/// An array of WLAN_PROFILE_INFO structures containing interface information. The number of items in the array is specified in the dwNumberOfItems member.
|
||||
/// </summary>
|
||||
public IEnumerable<WLAN_PROFILE_INFO> ProfileInfo
|
||||
{
|
||||
get
|
||||
{
|
||||
var size = Marshal.SizeOf(typeof(WLAN_PROFILE_INFO));
|
||||
for (int i = 0; i < dwNumberOfItems; i++)
|
||||
{
|
||||
yield return (WLAN_PROFILE_INFO)Marshal.PtrToStructure(ProfileInfoPointer + (i * size), typeof(WLAN_PROFILE_INFO));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public WLAN_PROFILE_INFO_LIST(IntPtr Pointer)
|
||||
{
|
||||
dwNumberOfItems = (uint)Marshal.ReadInt32(Pointer, 0);
|
||||
dwIndex = (uint)Marshal.ReadInt32(Pointer, 4);
|
||||
ProfileInfoPointer = Pointer + 8;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,208 @@
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
|
||||
namespace Disco.Client.Interop.Native
|
||||
{
|
||||
public static class WlanApi
|
||||
{
|
||||
|
||||
public const uint WLAN_API_VERSION_2_0 = 2; // Windows Vista WiFi API Version
|
||||
public const int ERROR_SUCCESS = 0;
|
||||
public const int ERROR_INVALID_PARAMETER = 87;
|
||||
public const int ERROR_NOT_ENOUGH_MEMORY = 8;
|
||||
public const int ERROR_SERVICE_NOT_ACTIVE = 1062; // The service has not been started.
|
||||
|
||||
/// <summary>
|
||||
/// The WlanOpenHandle function opens a connection to the server.
|
||||
/// </summary>
|
||||
/// <param name="dwClientVersion">The highest version of the WLAN API that the client supports.
|
||||
/// 1 = Client version for Windows XP with SP3 and Wireless LAN API for Windows XP with SP2.
|
||||
/// 2 = Client version for Windows Vista and Windows Server 2008</param>
|
||||
/// <param name="pReserved">Reserved for future use. Must be set to NULL.</param>
|
||||
/// <param name="pdwNegotiatedVersion">The version of the WLAN API that will be used in this session. This value is usually the highest version supported by both the client and server.</param>
|
||||
/// <param name="phClientHandle">A handle for the client to use in this session. This handle is used by other functions throughout the session.</param>
|
||||
/// <returns>
|
||||
/// If the function succeeds, the return value is ERROR_SUCCESS.
|
||||
/// If the function fails, the return value may be one of the following return codes.
|
||||
/// ERROR_INVALID_PARAMETER: pdwNegotiatedVersion is NULL, phClientHandle is NULL, or pReserved is not NULL.
|
||||
/// ERROR_NOT_ENOUGH_MEMORY: Failed to allocate memory to create the client context.
|
||||
/// RPC_STATUS: Various error codes.
|
||||
/// ERROR_REMOTE_SESSION_LIMIT_EXCEEDED: Too many handles have been issued by the server.
|
||||
/// </returns>
|
||||
/// <remarks>
|
||||
/// The version number specified by dwClientVersion and pdwNegotiatedVersion is a composite version number
|
||||
/// made up of both major and minor versions. The major version is specified by the low-order word, and the
|
||||
/// minor version is specified by the high-order word. The macros WLAN_API_VERSION_MAJOR(_v) and
|
||||
/// WLAN_API_VERSION_MINOR(_v) return the major and minor version numbers respectively.
|
||||
/// You can construct a version number using the macro WLAN_API_MAKE_VERSION(_major, _minor).
|
||||
/// Windows XP with SP3 and Wireless LAN API for Windows XP with SP2: WlanOpenHandle will return an
|
||||
/// error message if the Wireless Zero Configuration (WZC) service has not been started or if the WZC service is not responsive.
|
||||
/// </remarks>
|
||||
[DllImport("Wlanapi.dll", SetLastError = true)]
|
||||
public static extern uint WlanOpenHandle(uint dwClientVersion, IntPtr pReserved, out uint pdwNegotiatedVersion, out IntPtr phClientHandle);
|
||||
|
||||
/// <summary>
|
||||
/// The WlanCloseHandle function closes a connection to the server.
|
||||
/// </summary>
|
||||
/// <param name="hClientHandle">The client's session handle, which identifies the connection to be closed. This handle was obtained by a previous call to the WlanOpenHandle function.</param>
|
||||
/// <param name="pReserved">Reserved for future use. Set this parameter to NULL.</param>
|
||||
/// <returns>
|
||||
/// If the function succeeds, the return value is ERROR_SUCCESS.
|
||||
/// If the function fails, the return value may be one of the following return codes.
|
||||
/// ERROR_INVALID_PARAMETER: hClientHandle is NULL or invalid, or pReserved is not NULL.
|
||||
/// ERROR_INVALID_HANDLE: The handle hClientHandle was not found in the handle table.
|
||||
/// RPC_STATUS: Various error codes.
|
||||
/// </returns>
|
||||
/// <remarks>
|
||||
/// After a connection has been closed, any attempted use of the closed handle can cause unexpected errors.
|
||||
/// Upon closing, all outstanding notifications are discarded.
|
||||
/// Do not call WlanCloseHandle from a callback function. If the client is in the middle of a
|
||||
/// notification callback when WlanCloseHandle is called, the function waits for the callback to
|
||||
/// finish before returning a value. Calling this function inside a callback function will result in
|
||||
/// the call never completing. If both the callback function and the thread that closes the handle try
|
||||
/// to acquire the same lock, a deadlock may occur. In addition, do not call WlanCloseHandle from
|
||||
/// the DllMain function in an application DLL. This could also cause a deadlock.
|
||||
/// </remarks>
|
||||
[DllImport("Wlanapi", SetLastError = true)]
|
||||
public static extern uint WlanCloseHandle(IntPtr hClientHandle, IntPtr pReserved);
|
||||
|
||||
/// <summary>
|
||||
/// The WlanEnumInterfaces function enumerates all of the wireless LAN interfaces currently enabled on the local computer.
|
||||
/// </summary>
|
||||
/// <param name="hClientHandle">The client's session handle, obtained by a previous call to the WlanOpenHandle function.</param>
|
||||
/// <param name="pReserved">Reserved for future use. This parameter must be set to NULL.</param>
|
||||
/// <param name="ppInterfaceList">
|
||||
/// A pointer to storage for a pointer to receive the returned list of wireless LAN interfaces in a WLAN_INTERFACE_INFO_LIST structure.
|
||||
/// The buffer for the WLAN_INTERFACE_INFO_LIST returned is allocated by the WlanEnumInterfaces function if the call succeeds.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// If the function succeeds, the return value is ERROR_SUCCESS.
|
||||
/// If the function fails, the return value may be one of the following return codes.
|
||||
/// ERROR_INVALID_PARAMETER: A parameter is incorrect. This error is returned if the hClientHandle or ppInterfaceList parameter is NULL. This error is returned if the pReserved is not NULL.
|
||||
/// This error is also returned if the hClientHandle parameter is not valid.
|
||||
/// ERROR_INVALID_HANDLE: The handle hClientHandle was not found in the handle table.
|
||||
/// RPC_STATUS: Various error codes.
|
||||
/// ERROR_NOT_ENOUGH_MEMORY: Not enough memory is available to process this request and allocate memory for the query results.
|
||||
/// </returns>
|
||||
/// <remarks>
|
||||
/// The WlanEnumInterfaces function allocates memory for the list of returned interfaces that is returned in the
|
||||
/// buffer pointed to by the ppInterfaceList parameter when the function succeeds. The memory used for the buffer
|
||||
/// pointed to by ppInterfaceList parameter should be released by calling the WlanFreeMemory function
|
||||
/// after the buffer is no longer needed.
|
||||
/// </remarks>
|
||||
[DllImport("Wlanapi", SetLastError = true)]
|
||||
public static extern uint WlanEnumInterfaces(IntPtr hClientHandle, IntPtr pReserved, out IntPtr ppInterfaceList);
|
||||
|
||||
/// <summary>
|
||||
/// The WlanGetProfileList function retrieves the list of profiles in preference order.
|
||||
/// </summary>
|
||||
/// <param name="hClientHandle">The client's session handle, obtained by a previous call to the WlanOpenHandle function.</param>
|
||||
/// <param name="pInterfaceGuid">The GUID of the wireless interface.</param>
|
||||
/// <param name="pReserved">Reserved for future use. Must be set to NULL.</param>
|
||||
/// <param name="ppProfileList">A PWLAN_PROFILE_INFO_LIST structure that contains the list of profile information.</param>
|
||||
/// <returns>
|
||||
/// If the function succeeds, the return value is ERROR_SUCCESS.
|
||||
/// If the function fails, the return value may be one of the following return codes.
|
||||
/// ERROR_INVALID_HANDLE: The handle hClientHandle was not found in the handle table.
|
||||
/// ERROR_INVALID_PARAMETER: A parameter is incorrect.
|
||||
/// ERROR_NOT_ENOUGH_MEMORY: Not enough memory is available to process this request and allocate memory for the query results.
|
||||
/// RPC_STATUS: Various error codes.
|
||||
/// </returns>
|
||||
/// <remarks>
|
||||
/// The WlanGetProfileList function returns only the basic information on the wireless profiles on a wireless interface.
|
||||
/// The list of wireless profiles on a wireless interface are retrieved in the preference order. The WlanSetProfilePosition
|
||||
/// can be used to change the preference order for the wireless profiles on a wireless interface.
|
||||
/// More detailed information for a wireless profile on a wireless interface can be retrieved by using the WlanGetProfile
|
||||
/// function. The WlanGetProfileCustomUserData function can be used to retrieve custom user data for a wireless profile on
|
||||
/// a wireless interface. A list of the wireless interfaces and associated GUIDs on the local computer can be retrieved
|
||||
/// using the WlanEnumInterfaces function.
|
||||
/// The WlanGetProfileList function allocates memory for the list of profiles returned in the buffer pointed to by the
|
||||
/// ppProfileList parameter. The caller is responsible for freeing this memory using the WlanFreeMemory function when
|
||||
/// this buffer is no longer needed.
|
||||
/// Windows XP with SP3 and Wireless LAN API for Windows XP with SP2: Guest profiles, profiles with Wireless Provisioning
|
||||
/// Service (WPS) authentication, and profiles with Wi-Fi Protected Access-None (WPA-None) authentication are not
|
||||
/// supported. These types of profiles are not returned by WlanGetProfileList, even if a profile of this type appears
|
||||
/// on the preferred profile list.
|
||||
/// </remarks>
|
||||
[DllImport("Wlanapi", SetLastError = true)]
|
||||
public static extern uint WlanGetProfileList(IntPtr hClientHandle, [MarshalAs(UnmanagedType.LPStruct)] Guid pInterfaceGuid, IntPtr pReserved, out IntPtr ppProfileList);
|
||||
|
||||
/// <summary>
|
||||
/// The WlanGetProfile function retrieves all information about a specified wireless profile.
|
||||
/// </summary>
|
||||
/// <param name="hClientHandle">The client's session handle, obtained by a previous call to the WlanOpenHandle function.</param>
|
||||
/// <param name="pInterfaceGuid">The GUID of the wireless interface. </param>
|
||||
/// <param name="strProfileName">The name of the profile. Profile names are case-sensitive. This string must be NULL-terminated. The maximum length of the profile name is 255 characters. This means that the maximum length of this string, including the NULL terminator, is 256 characters.</param>
|
||||
/// <param name="pReserved">Reserved for future use. Must be set to NULL.</param>
|
||||
/// <param name="pstrProfileXml">A string that is the XML representation of the queried profile. There is no predefined maximum string length.</param>
|
||||
/// <param name="pdwFlags">On input, a pointer to the address location used to provide additional information about the request. If this parameter is NULL on input, then no information on profile flags will be returned. On output, a pointer to the address location used to receive profile flags.</param>
|
||||
/// <param name="pdwGrantedAccess">The access mask of the all-user profile.</param>
|
||||
/// <returns>If the function succeeds, the return value is ERROR_SUCCESS.</returns>
|
||||
[DllImport("Wlanapi", CharSet = CharSet.Unicode, SetLastError = true)]
|
||||
public static extern uint WlanGetProfile(IntPtr hClientHandle, [MarshalAs(UnmanagedType.LPStruct)] Guid pInterfaceGuid, [MarshalAs(UnmanagedType.LPWStr)] string strProfileName, IntPtr pReserved, out IntPtr pstrProfileXml, out uint pdwFlags, out IntPtr pdwGrantedAccess);
|
||||
|
||||
/// <summary>
|
||||
/// The WlanSetProfile function sets the content of a specific profile.
|
||||
/// </summary>
|
||||
/// <param name="hClientHandle">The client's session handle, obtained by a previous call to the WlanOpenHandle function.</param>
|
||||
/// <param name="pInterfaceGuid">The GUID of the interface.</param>
|
||||
/// <param name="dwFlags">The flags to set on the profile.</param>
|
||||
/// <param name="strProfileXml">Contains the XML representation of the profile. The WLANProfile element is the root profile element. To view sample profiles, see Wireless Profile Samples. There is no predefined maximum string length.</param>
|
||||
/// <param name="strAllUserProfileSecurity">Sets the security descriptor string on the all-user profile. For more information about profile permissions, see the Remarks section.</param>
|
||||
/// <param name="bOverwrite">Specifies whether this profile is overwriting an existing profile. If this parameter is FALSE and the profile already exists, the existing profile will not be overwritten and an error will be returned.</param>
|
||||
/// <param name="pReserved">Reserved for future use. Must be set to NULL.</param>
|
||||
/// <param name="pdwReasonCode">A WLAN_REASON_CODE value that indicates why the profile is not valid.</param>
|
||||
/// <returns>If the function succeeds, the return value is ERROR_SUCCESS.</returns>
|
||||
[DllImport("Wlanapi", CharSet = CharSet.Unicode, SetLastError = true)]
|
||||
public static extern uint WlanSetProfile(IntPtr hClientHandle, [MarshalAs(UnmanagedType.LPStruct)] Guid pInterfaceGuid, uint dwFlags, [MarshalAs(UnmanagedType.LPWStr)] string strProfileXml, [MarshalAs(UnmanagedType.LPWStr)] string strAllUserProfileSecurity, bool bOverwrite, IntPtr pReserved, out uint pdwReasonCode);
|
||||
|
||||
/// <summary>
|
||||
/// The WlanDeleteProfile function deletes a wireless profile for a wireless interface on the local computer.
|
||||
/// </summary>
|
||||
/// <param name="hClientHandle">The client's session handle, obtained by a previous call to the WlanOpenHandle function.</param>
|
||||
/// <param name="pInterfaceGuid">The GUID of the interface from which to delete the profile. </param>
|
||||
/// <param name="strProfileName">The name of the profile to be deleted. Profile names are case-sensitive. This string must be NULL-terminated.</param>
|
||||
/// <param name="pReserved">Reserved for future use. Must be set to NULL.</param>
|
||||
/// <returns>
|
||||
/// If the function succeeds, the return value is ERROR_SUCCESS.
|
||||
/// If the function fails, the return value may be one of the following return codes.
|
||||
/// ERROR_INVALID_PARAMETER: The hClientHandle parameter is NULL or not valid, the pInterfaceGuid parameter is NULL, the strProfileName parameter is NULL, or pReserved is not NULL.
|
||||
/// ERROR_INVALID_HANDLE: The handle specified in the hClientHandle parameter was not found in the handle table.
|
||||
/// ERROR_NOT_FOUND: The wireless profile specified by strProfileName was not found in the profile store.
|
||||
/// ERROR_ACCESS_DENIED: The caller does not have sufficient permissions to delete the profile.
|
||||
/// RPC_STATUS: Various error codes.
|
||||
/// </returns>
|
||||
/// <remarks>
|
||||
/// The WlanDeleteProfile function deletes a wireless profile for a wireless interface on the local computer.
|
||||
/// All wireless LAN functions require an interface GUID for the wireless interface when performing profile operations.
|
||||
/// When a wireless interface is removed, its state is cleared from Wireless LAN Service (WLANSVC) and no profile operations are possible.
|
||||
/// The WlanDeleteProfile function can fail with ERROR_INVALID_PARAMETER if the wireless interface specified in the pInterfaceGuid parameter
|
||||
/// for the wireless LAN profile has been removed from the system (a USB wireless adapter that has been removed, for example).
|
||||
/// </remarks>
|
||||
[DllImport("Wlanapi", CharSet = CharSet.Unicode, SetLastError = true)]
|
||||
public static extern uint WlanDeleteProfile(IntPtr hClientHandle, [MarshalAs(UnmanagedType.LPStruct)] Guid pInterfaceGuid, [MarshalAs(UnmanagedType.LPWStr)] string strProfileName, IntPtr pReserved);
|
||||
|
||||
/// <summary>
|
||||
/// The WlanReasonCodeToString function retrieves a string that describes a specified reason code.
|
||||
/// </summary>
|
||||
/// <param name="dwReasonCode">A WLAN_REASON_CODE value of which the string description is requested.</param>
|
||||
/// <param name="dwBufferSize">The size of the buffer used to store the string, in WCHAR. If the reason code string is longer than the buffer, it will be truncated and NULL-terminated. If dwBufferSize is larger than the actual amount of memory allocated to pStringBuffer, then an access violation will occur in the calling program.</param>
|
||||
/// <param name="pStringBuffer">Pointer to a buffer that will receive the string. The caller must allocate memory to pStringBuffer before calling WlanReasonCodeToString.</param>
|
||||
/// <param name="pReserved">Reserved for future use. Must be set to NULL.</param>
|
||||
/// <returns>If the function succeeds, the return value is a pointer to a constant string.</returns>
|
||||
[DllImport("Wlanapi", CharSet = CharSet.Unicode, SetLastError = true)]
|
||||
public static extern uint WlanReasonCodeToString(uint dwReasonCode, uint dwBufferSize, ref StringBuilder pStringBuffer, IntPtr pReserved);
|
||||
|
||||
/// <summary>
|
||||
/// The WlanFreeMemory function frees memory. Any memory returned from Native Wifi functions must be freed.
|
||||
/// </summary>
|
||||
/// <param name="pMemory">Pointer to the memory to be freed.</param>
|
||||
/// <remarks>
|
||||
/// If pMemory points to memory that has already been freed, an access violation or heap corruption may occur.
|
||||
/// </remarks>
|
||||
[DllImport("Wlanapi")]
|
||||
public static extern void WlanFreeMemory(IntPtr pMemory);
|
||||
|
||||
}
|
||||
}
|
||||
+77
-301
@@ -1,335 +1,111 @@
|
||||
using System;
|
||||
using Disco.Client.Interop.Native;
|
||||
using Disco.Models.ClientServices.EnrolmentInformation;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Management;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
|
||||
namespace Disco.Client.Interop
|
||||
{
|
||||
public static class Network
|
||||
{
|
||||
private static List<NetworkAdapterInfo> NetworkAdapters { get; set; }
|
||||
private static NetworkAdapterInfo PrimaryLanNetworkAdapter { get; set; }
|
||||
private static NetworkAdapterInfo PrimaryWlanNetworkAdapter { get; set; }
|
||||
|
||||
public static void Initialize()
|
||||
public static List<NetworkAdapter> GetNetworkAdapters()
|
||||
{
|
||||
// Get All Adapters
|
||||
RetrieveLanAdapters();
|
||||
var adapters = GetWmiNetworkAdapters();
|
||||
|
||||
if (NetworkAdapters.Count > 0)
|
||||
if (adapters != null && adapters.Count > 0)
|
||||
{
|
||||
// Only Retrieve Wlan Adapters if at least one adapter was found by WMI
|
||||
try
|
||||
{
|
||||
RetrieveWlanAdapters();
|
||||
}
|
||||
catch (DllNotFoundException)
|
||||
{
|
||||
// Ignore DllNotFoundException
|
||||
// This which indicates 'Wlanapi.dll' isn't present (eg. Windows Servers)
|
||||
}
|
||||
|
||||
// Determine Primary Adapters
|
||||
|
||||
// Lan
|
||||
PrimaryLanNetworkAdapter = NetworkAdapters.Where(n => !n.IsWLanAdapter && n.NetConnectionId.StartsWith("Local Area Connection", StringComparison.OrdinalIgnoreCase)).OrderByDescending(n => n.Speed).FirstOrDefault();
|
||||
// Might be too restrictive - remove name restriction just in case.
|
||||
if (PrimaryLanNetworkAdapter == null)
|
||||
PrimaryLanNetworkAdapter = NetworkAdapters.Where(n => !n.IsWLanAdapter).OrderByDescending(n => n.Speed).FirstOrDefault();
|
||||
|
||||
// Wan
|
||||
PrimaryWlanNetworkAdapter = NetworkAdapters.Where(n => n.IsWLanAdapter).OrderByDescending(n => n.Speed).FirstOrDefault();
|
||||
// Apply Wlan Information
|
||||
adapters.ApplyWlanInformation();
|
||||
}
|
||||
}
|
||||
|
||||
private static void RetrieveLanAdapters()
|
||||
return adapters;
|
||||
}
|
||||
|
||||
private static List<NetworkAdapter> GetWmiNetworkAdapters()
|
||||
{
|
||||
// Get NetworkAdapter Information
|
||||
try
|
||||
{
|
||||
using (ManagementObjectSearcher mSearcher = new ManagementObjectSearcher("SELECT Index, GUID, MACAddress, Name, NetConnectionID, Speed FROM Win32_NetworkAdapter WHERE PhysicalAdapter=true AND MACAddress IS NOT NULL AND Name IS NOT NULL AND NetConnectionID IS NOT NULL AND Speed IS NOT NULL"))
|
||||
// Load Physical Adapters
|
||||
using (var wmiSearcher = new ManagementObjectSearcher("SELECT DeviceID, GUID, Manufacturer, ProductName, AdapterType, MACAddress, Speed, NetConnectionID, NetConnectionStatus, NetEnabled FROM Win32_NetworkAdapter WHERE PhysicalAdapter=true AND MACAddress IS NOT NULL AND NetConnectionID IS NOT NULL AND Speed IS NOT NULL"))
|
||||
{
|
||||
using (ManagementObjectCollection mResults = mSearcher.Get())
|
||||
using (var wmiResults = wmiSearcher.Get())
|
||||
{
|
||||
NetworkAdapters = new List<NetworkAdapterInfo>();
|
||||
foreach (var mResult in mResults.Cast<ManagementObject>())
|
||||
{
|
||||
NetworkAdapterInfo nic = new NetworkAdapterInfo()
|
||||
return wmiResults
|
||||
.Cast<ManagementObject>()
|
||||
.Select(wmiResult =>
|
||||
{
|
||||
Index = (UInt32)mResult.GetPropertyValue("Index"),
|
||||
Guid = Guid.Parse((string)mResult.GetPropertyValue("GUID")),
|
||||
MacAddress = mResult.GetPropertyValue("MACAddress").ToString(),
|
||||
Name = mResult.GetPropertyValue("Name").ToString(),
|
||||
NetConnectionId = mResult.GetPropertyValue("NetConnectionID").ToString(),
|
||||
Speed = Convert.ToUInt64(mResult.GetPropertyValue("Speed")),
|
||||
IsWLanAdapter = false
|
||||
};
|
||||
NetworkAdapters.Add(nic);
|
||||
}
|
||||
var adapter = new NetworkAdapter()
|
||||
{
|
||||
DeviceID = (string)wmiResult.GetPropertyValue("DeviceID"),
|
||||
ConnectionIdentifier = Guid.Parse((string)wmiResult.GetPropertyValue("GUID")),
|
||||
Manufacturer = (string)wmiResult.GetPropertyValue("Manufacturer"),
|
||||
ProductName = (string)wmiResult.GetPropertyValue("ProductName"),
|
||||
AdapterType = (string)wmiResult.GetPropertyValue("AdapterType"),
|
||||
MACAddress = (string)wmiResult.GetPropertyValue("MACAddress"),
|
||||
Speed = (ulong)wmiResult.GetPropertyValue("Speed"),
|
||||
NetConnectionID = (string)wmiResult.GetPropertyValue("NetConnectionID"),
|
||||
NetConnectionStatus = ((NetworkConnectionStatuses)wmiResult.GetPropertyValue("NetConnectionStatus")).Description(),
|
||||
NetEnabled = (bool)wmiResult.GetPropertyValue("NetEnabled")
|
||||
};
|
||||
|
||||
using (var wmiRelatedResults = wmiResult.GetRelated("Win32_NetworkAdapterConfiguration", "Win32_NetworkAdapterSetting", null, null, null, null, false, null))
|
||||
{
|
||||
var wmiConfiguration = wmiRelatedResults.Cast<ManagementObject>().First();
|
||||
|
||||
adapter.IPEnabled = (bool)wmiConfiguration.GetPropertyValue("IPEnabled");
|
||||
if (adapter.IPEnabled)
|
||||
{
|
||||
adapter.IPAddresses = ((string[])wmiConfiguration.GetPropertyValue("IPAddress")).ToList();
|
||||
}
|
||||
}
|
||||
|
||||
return adapter;
|
||||
})
|
||||
.ToList();
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw new Exception("Disco Client was unable to retrieve NetworkAdapter information from WMI", ex);
|
||||
throw new Exception("Disco ICT Client was unable to retrieve NetworkAdapter information from WMI", ex);
|
||||
}
|
||||
}
|
||||
|
||||
private static void RetrieveWlanAdapters()
|
||||
public static string Description(this NetworkConnectionStatuses Status)
|
||||
{
|
||||
WLAN_INTERFACE_INFO_LIST wlanApiInterfaceList;
|
||||
|
||||
IntPtr wlanApiHandle = IntPtr.Zero;
|
||||
uint wlanApiServiceVersion = 0;
|
||||
|
||||
if (WlanOpenHandle(WLAN_API_VERSION_2_0, IntPtr.Zero, out wlanApiServiceVersion, ref wlanApiHandle) == ERROR_SUCCESS)
|
||||
switch (Status)
|
||||
{
|
||||
IntPtr wlanApiInterfaceListPointer = IntPtr.Zero;
|
||||
|
||||
if (WlanEnumInterfaces(wlanApiHandle, IntPtr.Zero, ref wlanApiInterfaceListPointer) == ERROR_SUCCESS)
|
||||
{
|
||||
wlanApiInterfaceList = new WLAN_INTERFACE_INFO_LIST(wlanApiInterfaceListPointer);
|
||||
WlanFreeMemory(wlanApiInterfaceListPointer);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Error - No Wlan Adapters Reported
|
||||
WlanCloseHandle(wlanApiHandle, IntPtr.Zero);
|
||||
return;
|
||||
}
|
||||
|
||||
WlanCloseHandle(wlanApiHandle, IntPtr.Zero);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Error - No Wlan Adapters Reported
|
||||
return;
|
||||
}
|
||||
|
||||
if (wlanApiInterfaceList.InterfaceInfo != null)
|
||||
{
|
||||
foreach (var wlanApiAdapter in wlanApiInterfaceList.InterfaceInfo)
|
||||
{
|
||||
var wlanApiAdapterInfo = wlanApiAdapter;
|
||||
var wmiAdapterInfo = NetworkAdapters.FirstOrDefault(n => n.Guid == wlanApiAdapterInfo.InterfaceGuid);
|
||||
if (wmiAdapterInfo != null)
|
||||
{
|
||||
wmiAdapterInfo.IsWLanAdapter = true;
|
||||
wmiAdapterInfo.WlanState = wlanApiAdapterInfo.isState;
|
||||
}
|
||||
}
|
||||
case NetworkConnectionStatuses.Disconnected:
|
||||
return "Disconnected";
|
||||
case NetworkConnectionStatuses.Connecting:
|
||||
return "Connecting";
|
||||
case NetworkConnectionStatuses.Connected:
|
||||
return "Connected";
|
||||
case NetworkConnectionStatuses.Disconnecting:
|
||||
return "Disconnecting";
|
||||
case NetworkConnectionStatuses.HardwareNotPresent:
|
||||
return "Hardware Not Present";
|
||||
case NetworkConnectionStatuses.HardwareDisabled:
|
||||
return "Hardware Disabled";
|
||||
case NetworkConnectionStatuses.HardwareMalfunction:
|
||||
return "Hardware Malfunction";
|
||||
case NetworkConnectionStatuses.MediaDisconnected:
|
||||
return "Media Disconnected";
|
||||
case NetworkConnectionStatuses.Authenticating:
|
||||
return "Authenticating";
|
||||
case NetworkConnectionStatuses.AuthenticationSucceeded:
|
||||
return "Authentication Succeeded";
|
||||
case NetworkConnectionStatuses.AuthenticationFailed:
|
||||
return "Authentication Failed";
|
||||
case NetworkConnectionStatuses.InvalidAddress:
|
||||
return "Invalid Address";
|
||||
case NetworkConnectionStatuses.CredentialsRequired:
|
||||
return "Credentials Required";
|
||||
default:
|
||||
return "Unknown";
|
||||
}
|
||||
}
|
||||
|
||||
public static string PrimaryLanMacAddress
|
||||
{
|
||||
get
|
||||
{
|
||||
// Return null if no Primary LAN Network Adapter found on this Device
|
||||
|
||||
return (PrimaryLanNetworkAdapter == null) ? null : PrimaryLanNetworkAdapter.MacAddress;
|
||||
}
|
||||
}
|
||||
public static string PrimaryWlanMacAddress
|
||||
{
|
||||
get
|
||||
{
|
||||
// Return null if no Primary WLAN Network Adapter found on this Device
|
||||
|
||||
return (PrimaryWlanNetworkAdapter == null) ? null : PrimaryWlanNetworkAdapter.MacAddress;
|
||||
}
|
||||
}
|
||||
|
||||
private class NetworkAdapterInfo
|
||||
{
|
||||
public UInt32 Index { get; set; }
|
||||
public Guid Guid { get; set; }
|
||||
public string Name { get; set; }
|
||||
public string NetConnectionId { get; set; }
|
||||
public string MacAddress { get; set; }
|
||||
public UInt64 Speed { get; set; }
|
||||
|
||||
public bool IsWLanAdapter { get; set; }
|
||||
public WLAN_INTERFACE_STATE WlanState { get; set; }
|
||||
|
||||
public string WlanStateDescription
|
||||
{
|
||||
get
|
||||
{
|
||||
switch (WlanState)
|
||||
{
|
||||
case WLAN_INTERFACE_STATE.wlan_interface_state_not_ready:
|
||||
return "Not Ready";
|
||||
case WLAN_INTERFACE_STATE.wlan_interface_state_connected:
|
||||
return "Connected";
|
||||
case WLAN_INTERFACE_STATE.wlan_interface_state_ad_hoc_network_formed:
|
||||
return "Ad Hoc Network Formed";
|
||||
case WLAN_INTERFACE_STATE.wlan_interface_state_disconnecting:
|
||||
return "Disconnecting";
|
||||
case WLAN_INTERFACE_STATE.wlan_interface_state_disconnected:
|
||||
return "Disconnected";
|
||||
case WLAN_INTERFACE_STATE.wlan_interface_state_associating:
|
||||
return "Associating";
|
||||
case WLAN_INTERFACE_STATE.wlan_interface_state_discovering:
|
||||
return "Discovering";
|
||||
case WLAN_INTERFACE_STATE.wlan_interface_state_authenticating:
|
||||
return "Authenticating";
|
||||
default:
|
||||
return "Unknown";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#region Wlan Win32 Interop
|
||||
|
||||
private const uint WLAN_API_VERSION_2_0 = 2; // Windows Vista WiFi API Version
|
||||
private const int ERROR_SUCCESS = 0;
|
||||
|
||||
/// <summary >
|
||||
/// Opens a connection to the server
|
||||
/// </summary >
|
||||
[DllImport("Wlanapi.dll")]
|
||||
private static extern int WlanOpenHandle(
|
||||
uint dwClientVersion,
|
||||
IntPtr pReserved, //not in MSDN but required
|
||||
[Out] out uint pdwNegotiatedVersion,
|
||||
ref IntPtr ClientHandle);
|
||||
|
||||
/// <summary >
|
||||
/// Closes a connection to the server
|
||||
/// </summary >
|
||||
[DllImport("Wlanapi", EntryPoint = "WlanCloseHandle")]
|
||||
private static extern uint WlanCloseHandle(
|
||||
[In] IntPtr hClientHandle,
|
||||
IntPtr pReserved);
|
||||
|
||||
/// <summary >
|
||||
/// Enumerates all wireless interfaces in the laptop
|
||||
/// </summary >
|
||||
[DllImport("Wlanapi", EntryPoint = "WlanEnumInterfaces")]
|
||||
private static extern uint WlanEnumInterfaces(
|
||||
[In] IntPtr hClientHandle,
|
||||
IntPtr pReserved,
|
||||
ref IntPtr ppInterfaceList);
|
||||
|
||||
/// <summary >
|
||||
/// Frees memory returned by native WiFi functions
|
||||
/// </summary >
|
||||
[DllImport("Wlanapi", EntryPoint = "WlanFreeMemory")]
|
||||
private static extern void WlanFreeMemory([In] IntPtr pMemory);
|
||||
|
||||
/// <summary>
|
||||
/// Defines the state of the interface. e.g. connected, disconnected.
|
||||
/// </summary>
|
||||
private enum WLAN_INTERFACE_STATE
|
||||
{
|
||||
/// <summary>
|
||||
/// wlan_interface_state_not_ready -> 0
|
||||
/// </summary>
|
||||
wlan_interface_state_not_ready = 0,
|
||||
/// <summary>
|
||||
/// wlan_interface_state_connected -> 1
|
||||
/// </summary>
|
||||
wlan_interface_state_connected = 1,
|
||||
/// <summary>
|
||||
/// wlan_interface_state_ad_hoc_network_formed -> 2
|
||||
/// </summary>
|
||||
wlan_interface_state_ad_hoc_network_formed = 2,
|
||||
/// <summary>
|
||||
/// wlan_interface_state_disconnecting -> 3
|
||||
/// </summary>
|
||||
wlan_interface_state_disconnecting = 3,
|
||||
/// <summary>
|
||||
/// wlan_interface_state_disconnected -> 4
|
||||
/// </summary>
|
||||
wlan_interface_state_disconnected = 4,
|
||||
/// <summary>
|
||||
/// wlan_interface_state_associating -> 5
|
||||
/// </summary>
|
||||
wlan_interface_state_associating = 5,
|
||||
/// <summary>
|
||||
/// wlan_interface_state_discovering -> 6
|
||||
/// </summary>
|
||||
wlan_interface_state_discovering = 6,
|
||||
/// <summary>
|
||||
/// wlan_interface_state_authenticating -> 7
|
||||
/// </summary>
|
||||
wlan_interface_state_authenticating = 7,
|
||||
}
|
||||
|
||||
|
||||
/// <summary >
|
||||
/// Stores interface info
|
||||
/// </summary >
|
||||
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
|
||||
private struct WLAN_INTERFACE_INFO
|
||||
{
|
||||
/// GUID->_GUID
|
||||
public Guid InterfaceGuid;
|
||||
|
||||
/// WCHAR[256]
|
||||
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
|
||||
public string strInterfaceDescription;
|
||||
|
||||
/// WLAN_INTERFACE_STATE->_WLAN_INTERFACE_STATE
|
||||
public WLAN_INTERFACE_STATE isState;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Contains an array of NIC information
|
||||
/// </summary>
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
private struct WLAN_INTERFACE_INFO_LIST
|
||||
{
|
||||
/// <summary>
|
||||
/// Length of <see cref="InterfaceInfo"/> array
|
||||
/// </summary>
|
||||
public Int32 dwNumberOfItems;
|
||||
/// <summary>
|
||||
/// This member is not used by the wireless service. Applications can use this member when processing individual interfaces.
|
||||
/// </summary>
|
||||
public Int32 dwIndex;
|
||||
/// <summary>
|
||||
/// Array of WLAN interfaces.
|
||||
/// </summary>
|
||||
public WLAN_INTERFACE_INFO[] InterfaceInfo;
|
||||
|
||||
/// <summary>
|
||||
/// Constructor for WLAN_INTERFACE_INFO_LIST.
|
||||
/// Constructor is needed because the InterfaceInfo member varies based on how many adapters are in the system.
|
||||
/// </summary>
|
||||
/// <param name="pList">the unmanaged pointer containing the list.</param>
|
||||
public WLAN_INTERFACE_INFO_LIST(IntPtr pList)
|
||||
{
|
||||
// The first 4 bytes are the number of WLAN_INTERFACE_INFO structures.
|
||||
dwNumberOfItems = Marshal.ReadInt32(pList, 0);
|
||||
|
||||
// The next 4 bytes are the index of the current item in the unmanaged API.
|
||||
dwIndex = Marshal.ReadInt32(pList, 4);
|
||||
|
||||
// Construct the array of WLAN_INTERFACE_INFO structures.
|
||||
InterfaceInfo = new WLAN_INTERFACE_INFO[dwNumberOfItems];
|
||||
|
||||
for (int i = 0; i <= dwNumberOfItems - 1; i++)
|
||||
{
|
||||
// The offset of the array of structures is 8 bytes past the beginning.
|
||||
// Then, take the index and multiply it by the number of bytes in the
|
||||
// structure.
|
||||
// The length of the WLAN_INTERFACE_INFO structure is 532 bytes - this
|
||||
// was determined by doing a Marshall.SizeOf(WLAN_INTERFACE_INFO)
|
||||
IntPtr pItemList = new IntPtr(pList.ToInt64() + (i * 532) + 8);
|
||||
|
||||
// Construct the WLAN_INTERFACE_INFO structure, marshal the unmanaged
|
||||
// structure into it, then copy it to the array of structures.
|
||||
InterfaceInfo[i] = (WLAN_INTERFACE_INFO)Marshal.PtrToStructure(pItemList, typeof(WLAN_INTERFACE_INFO));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,201 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Management;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Disco.Client.Interop
|
||||
{
|
||||
public static class SystemAudit
|
||||
{
|
||||
|
||||
public static string DeviceSerialNumber { get; private set; }
|
||||
public static string DeviceSMBIOSVersion { get; private set; }
|
||||
public static string DeviceManufacturer { get; private set; }
|
||||
public static string DeviceModel { get; private set; }
|
||||
public static string DeviceType { get; private set; }
|
||||
public static string DeviceUUID { get; private set; }
|
||||
public static bool DeviceIsPartOfDomain { get; private set; }
|
||||
public static string DeviceDNSDomainName { get; private set; }
|
||||
|
||||
public static void Initialize()
|
||||
{
|
||||
// Get BIOS Information
|
||||
try
|
||||
{
|
||||
using (ManagementObjectSearcher mSearcher = new ManagementObjectSearcher("SELECT SerialNumber, SMBIOSBIOSVersion FROM Win32_BIOS WHERE PrimaryBios=true"))
|
||||
{
|
||||
using (ManagementObjectCollection mResults = mSearcher.Get())
|
||||
{
|
||||
using (var mItem = mResults.Cast<ManagementObject>().FirstOrDefault())
|
||||
{
|
||||
if (mItem != null)
|
||||
{
|
||||
DeviceSerialNumber = mItem.GetPropertyValue("SerialNumber") as string;
|
||||
if (!string.IsNullOrEmpty(DeviceSerialNumber))
|
||||
DeviceSerialNumber = DeviceSerialNumber.Trim();
|
||||
|
||||
ErrorReporting.DeviceIdentifier = DeviceSerialNumber;
|
||||
DeviceSMBIOSVersion = mItem.GetPropertyValue("SMBIOSBIOSVersion") as string;
|
||||
if (!string.IsNullOrEmpty(DeviceSMBIOSVersion))
|
||||
DeviceSMBIOSVersion = DeviceSMBIOSVersion.Trim();
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new Exception("No Win32_BIOS WHERE PrimaryBios=true was found");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw new Exception("Disco Client was unable to retrieve BIOS information from WMI", ex);
|
||||
}
|
||||
|
||||
// Get System Information
|
||||
try
|
||||
{
|
||||
using (ManagementObjectSearcher mSearcher = new ManagementObjectSearcher("SELECT Manufacturer, Model, PartOfDomain, PCSystemType, Domain FROM Win32_ComputerSystem"))
|
||||
{
|
||||
using (ManagementObjectCollection mResults = mSearcher.Get())
|
||||
{
|
||||
using (var mItem = mResults.Cast<ManagementObject>().FirstOrDefault())
|
||||
{
|
||||
if (mItem != null)
|
||||
{
|
||||
DeviceManufacturer = mItem.GetPropertyValue("Manufacturer") as string;
|
||||
if (!string.IsNullOrEmpty(DeviceManufacturer))
|
||||
DeviceManufacturer = DeviceManufacturer.Trim();
|
||||
|
||||
DeviceModel = mItem.GetPropertyValue("Model") as string;
|
||||
if (!string.IsNullOrEmpty(DeviceModel))
|
||||
DeviceModel = DeviceModel.Trim();
|
||||
|
||||
DeviceIsPartOfDomain = (bool)mItem.GetPropertyValue("PartOfDomain");
|
||||
DeviceType = PCSystemTypeToString((UInt16)mItem.GetPropertyValue("PCSystemType"));
|
||||
|
||||
DeviceDNSDomainName = DeviceIsPartOfDomain ? mItem.GetPropertyValue("Domain") as string : null;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new Exception("No Win32_ComputerSystem was found");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw new Exception("Disco Client was unable to retrieve ComputerSystem information from WMI", ex);
|
||||
}
|
||||
|
||||
// Get System Product Information
|
||||
string ComputerSystemProductSerialNumber;
|
||||
try
|
||||
{
|
||||
using (ManagementObjectSearcher mSearcher = new ManagementObjectSearcher("SELECT IdentifyingNumber, UUID FROM Win32_ComputerSystemProduct"))
|
||||
{
|
||||
using (ManagementObjectCollection mResults = mSearcher.Get())
|
||||
{
|
||||
using (var mItem = mResults.Cast<ManagementObject>().FirstOrDefault())
|
||||
{
|
||||
if (mItem != null)
|
||||
{
|
||||
ComputerSystemProductSerialNumber = mItem.GetPropertyValue("IdentifyingNumber") as string;
|
||||
if (!string.IsNullOrEmpty(ComputerSystemProductSerialNumber))
|
||||
ComputerSystemProductSerialNumber = ComputerSystemProductSerialNumber.Trim();
|
||||
|
||||
DeviceUUID = mItem.GetPropertyValue("UUID") as string;
|
||||
if (!string.IsNullOrEmpty(DeviceUUID))
|
||||
DeviceUUID = DeviceUUID.Trim();
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new Exception("No Win32_ComputerSystemProduct was found");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw new Exception("Disco Client was unable to retrieve ComputerSystemProduct information from WMI", ex);
|
||||
}
|
||||
|
||||
// Added 2012-11-22 G# - Lenovo IdeaPad Serial SHIM
|
||||
// http://www.discoict.com.au/forum/feature-requests/2012/11/serial-number-detection-on-ideapads.aspx
|
||||
if (string.IsNullOrWhiteSpace(DeviceSerialNumber) ||
|
||||
(DeviceManufacturer.Equals("LENOVO", StringComparison.OrdinalIgnoreCase) &&
|
||||
(DeviceModel.Equals("S10-3", StringComparison.OrdinalIgnoreCase) // S10-3
|
||||
|| DeviceModel.Equals("2957", StringComparison.OrdinalIgnoreCase)))) // S10-2
|
||||
{
|
||||
try
|
||||
{
|
||||
using (ManagementObjectSearcher mSearcher = new ManagementObjectSearcher("SELECT SerialNumber FROM Win32_BaseBoard"))
|
||||
{
|
||||
using (ManagementObjectCollection mResults = mSearcher.Get())
|
||||
{
|
||||
using (var mItem = mResults.Cast<ManagementObject>().FirstOrDefault())
|
||||
{
|
||||
if (mItem != null)
|
||||
{
|
||||
DeviceSerialNumber = mItem.GetPropertyValue("SerialNumber") as string;
|
||||
if (!string.IsNullOrEmpty(DeviceSerialNumber))
|
||||
DeviceSerialNumber = DeviceSerialNumber.Trim();
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new Exception("No Win32_BaseBoard was found");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw new Exception("Disco Client was unable to retrieve BaseBoard information from WMI", ex);
|
||||
}
|
||||
if (string.IsNullOrWhiteSpace(DeviceSerialNumber))
|
||||
DeviceSerialNumber = ComputerSystemProductSerialNumber;
|
||||
}
|
||||
// End Added 2012-11-22 G#
|
||||
|
||||
ErrorReporting.DeviceIdentifier = DeviceSerialNumber;
|
||||
|
||||
// Validate Device 'State'
|
||||
if (string.IsNullOrWhiteSpace(DeviceSerialNumber))
|
||||
throw new Exception("This device has no serial number stored in BIOS or BaseBoard");
|
||||
if (DeviceSerialNumber.Length > 60)
|
||||
throw new Exception(string.Format("The serial number reported by this device is over 60 characters long:{0}{1}", Environment.NewLine, DeviceSerialNumber));
|
||||
}
|
||||
|
||||
private static string PCSystemTypeToString(UInt16 PCSystemType)
|
||||
{
|
||||
switch (PCSystemType)
|
||||
{
|
||||
case 0:
|
||||
return "Unknown";
|
||||
case 1:
|
||||
return "Desktop";
|
||||
case 2:
|
||||
return "Mobile";
|
||||
case 3:
|
||||
return "Workstation";
|
||||
case 4:
|
||||
return "EnterpriseServer";
|
||||
case 5:
|
||||
return "SmallOfficeAndHomeOfficeServer";
|
||||
case 6:
|
||||
return "AppliancePC";
|
||||
case 7:
|
||||
return "PerformanceServer";
|
||||
case 8:
|
||||
return "Maximum";
|
||||
default:
|
||||
return "Unknown";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,388 @@
|
||||
using Disco.Client.Interop.Native;
|
||||
using Disco.Models.ClientServices.EnrolmentInformation;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Xml.Linq;
|
||||
|
||||
namespace Disco.Client.Interop
|
||||
{
|
||||
public static class WirelessNetwork
|
||||
{
|
||||
|
||||
public static void ApplyWlanInformation(this List<NetworkAdapter> Adapters)
|
||||
{
|
||||
try
|
||||
{
|
||||
IntPtr wlanHandle;
|
||||
uint wlanServiceVersion;
|
||||
|
||||
if (WlanApi.WlanOpenHandle(WlanApi.WLAN_API_VERSION_2_0, IntPtr.Zero, out wlanServiceVersion, out wlanHandle) == WlanApi.ERROR_SUCCESS)
|
||||
{
|
||||
try
|
||||
{
|
||||
IntPtr wlanInterfacesPtr;
|
||||
|
||||
if (WlanApi.WlanEnumInterfaces(wlanHandle, IntPtr.Zero, out wlanInterfacesPtr) == WlanApi.ERROR_SUCCESS)
|
||||
{
|
||||
try
|
||||
{
|
||||
var wlanInterfaces = new WLAN_INTERFACE_INFO_LIST(wlanInterfacesPtr);
|
||||
|
||||
foreach (var wlanInterface in wlanInterfaces.InterfaceInfo)
|
||||
{
|
||||
var adapter = Adapters.FirstOrDefault(a => a.ConnectionIdentifier == wlanInterface.InterfaceGuid);
|
||||
if (adapter != null)
|
||||
{
|
||||
adapter.IsWlanAdapter = true;
|
||||
adapter.WlanStatus = wlanInterface.isState.Description();
|
||||
}
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
WlanApi.WlanFreeMemory(wlanInterfacesPtr);
|
||||
}
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
WlanApi.WlanCloseHandle(wlanHandle, IntPtr.Zero);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (DllNotFoundException)
|
||||
{
|
||||
// Ignore
|
||||
// Indicates 'Wlanapi.dll' isn't present (ie. Servers)
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw new Exception("Disco ICT Client was unable to retrieve Wireless NetworkAdapter information from WlanApi", ex);
|
||||
}
|
||||
}
|
||||
|
||||
public static List<WirelessProfile> GetWirelessProfiles()
|
||||
{
|
||||
try
|
||||
{
|
||||
IntPtr wlanHandle;
|
||||
uint wlanServiceVersion;
|
||||
uint interopResult;
|
||||
|
||||
// Connect to wireless service
|
||||
interopResult = WlanApi.WlanOpenHandle(WlanApi.WLAN_API_VERSION_2_0, IntPtr.Zero, out wlanServiceVersion, out wlanHandle);
|
||||
if (interopResult == WlanApi.ERROR_SERVICE_NOT_ACTIVE)
|
||||
{
|
||||
// Indicates the Wlan service has not been started on the client
|
||||
// typically as it is not needed (no wireless adapter) or if it
|
||||
// has been forcibly disabled.
|
||||
return null;
|
||||
}
|
||||
if (interopResult != WlanApi.ERROR_SUCCESS)
|
||||
{
|
||||
throw new Exception($"Unable to connect to local wireless service. WlanOpenHandle returned: {interopResult}");
|
||||
}
|
||||
try
|
||||
{
|
||||
return GetWirelessProfiles(wlanHandle);
|
||||
}
|
||||
finally
|
||||
{
|
||||
WlanApi.WlanCloseHandle(wlanHandle, IntPtr.Zero);
|
||||
}
|
||||
}
|
||||
catch (DllNotFoundException)
|
||||
{
|
||||
// Indicates 'Wlanapi.dll' isn't present (ie. Servers)
|
||||
return null;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw new Exception("Disco ICT Client was unable to retrieve Wireless Profiles from WlanApi", ex);
|
||||
}
|
||||
}
|
||||
|
||||
private static List<WirelessProfile> GetWirelessProfiles(IntPtr wlanHandle)
|
||||
{
|
||||
uint interopResult;
|
||||
IntPtr wlanInterfacesPtr;
|
||||
|
||||
// Enumerate wireless interfaces
|
||||
interopResult = WlanApi.WlanEnumInterfaces(wlanHandle, IntPtr.Zero, out wlanInterfacesPtr);
|
||||
if (interopResult != WlanApi.ERROR_SUCCESS)
|
||||
{
|
||||
throw new Exception($"Unable to list interfaces with the local wireless service. WlanEnumInterfaces returned: {interopResult}");
|
||||
}
|
||||
try
|
||||
{
|
||||
var wlanInterfaces = new WLAN_INTERFACE_INFO_LIST(wlanInterfacesPtr);
|
||||
var profiles = new List<WirelessProfile>();
|
||||
|
||||
foreach (var wlanInterface in wlanInterfaces.InterfaceInfo)
|
||||
{
|
||||
IntPtr wlanProfilesPtr;
|
||||
// Enumerate wireless profiles for interface
|
||||
interopResult = WlanApi.WlanGetProfileList(wlanHandle, wlanInterface.InterfaceGuid, IntPtr.Zero, out wlanProfilesPtr);
|
||||
if (interopResult != WlanApi.ERROR_SUCCESS)
|
||||
{
|
||||
throw new Exception($"Unable to list wireless profiles for the {wlanInterface.InterfaceGuid} interface with the local wireless service. WlanGetProfileList returned: {interopResult}");
|
||||
}
|
||||
try
|
||||
{
|
||||
var wlanProfiles = new WLAN_PROFILE_INFO_LIST(wlanProfilesPtr);
|
||||
|
||||
foreach (var wlanProfile in wlanProfiles.ProfileInfo)
|
||||
{
|
||||
profiles.Add(new WirelessProfile()
|
||||
{
|
||||
Name = wlanProfile.strInterfaceDescription,
|
||||
InterfaceGuid = wlanInterface.InterfaceGuid,
|
||||
IsGroupPolicy = wlanProfile.dwFlags.HasFlag(ProfileInfoFlags.WLAN_PROFILE_GROUP_POLICY)
|
||||
});
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
WlanApi.WlanFreeMemory(wlanProfilesPtr);
|
||||
}
|
||||
}
|
||||
|
||||
return profiles;
|
||||
}
|
||||
finally
|
||||
{
|
||||
WlanApi.WlanFreeMemory(wlanInterfacesPtr);
|
||||
}
|
||||
}
|
||||
|
||||
public static void Apply(this WirelessProfileStore ProfileStore)
|
||||
{
|
||||
var adapters = Network.GetNetworkAdapters().Where(a => a.IsWlanAdapter).ToList();
|
||||
|
||||
try
|
||||
{
|
||||
IntPtr wlanHandle;
|
||||
uint wlanServiceVersion;
|
||||
uint interopResult;
|
||||
|
||||
// Connect to wireless service
|
||||
interopResult = WlanApi.WlanOpenHandle(WlanApi.WLAN_API_VERSION_2_0, IntPtr.Zero, out wlanServiceVersion, out wlanHandle);
|
||||
if (interopResult == WlanApi.ERROR_SERVICE_NOT_ACTIVE)
|
||||
{
|
||||
// Indicates the Wlan service has not been started on the client
|
||||
// typically as it is not needed (no wireless adapter) or if it
|
||||
// has been forcibly disabled.
|
||||
Presentation.UpdateStatus("Enrolling Device", $"Configuring Wireless Profiles\r\nSkipping, the WLAN service is not enabled", true, -1, 3000);
|
||||
return;
|
||||
}
|
||||
if (interopResult != WlanApi.ERROR_SUCCESS)
|
||||
{
|
||||
throw new Exception($"Unable to connect to local wireless service. WlanOpenHandle returned: {interopResult}");
|
||||
}
|
||||
try
|
||||
{
|
||||
var existingProfiles = GetWirelessProfiles(wlanHandle);
|
||||
var addedProfiles = new List<string>();
|
||||
|
||||
// Remove Profiles
|
||||
if (ProfileStore.RemoveNames != null && ProfileStore.RemoveNames.Count > 0)
|
||||
{
|
||||
var profileRemoved = false;
|
||||
|
||||
foreach (var removeName in ProfileStore.RemoveNames)
|
||||
{
|
||||
var foundProfiles = existingProfiles.Where(p => p.Name == removeName);
|
||||
foreach (var profile in foundProfiles)
|
||||
{
|
||||
var adapter = adapters.FirstOrDefault(a => a.ConnectionIdentifier == profile.InterfaceGuid);
|
||||
|
||||
if (profile.IsGroupPolicy == true)
|
||||
{
|
||||
Presentation.UpdateStatus("Enrolling Device", $"Configuring Wireless Profiles\r\nUnable to remove Group Policy Wireless Profile '{removeName}' from '{adapter?.NetConnectionID ?? profile.InterfaceGuid.ToString()}'", true, -1, 3000);
|
||||
}
|
||||
else
|
||||
{
|
||||
Presentation.UpdateStatus("Enrolling Device", $"Configuring Wireless Profiles\r\nRemoving Wireless Profile '{removeName}' from '{adapter?.NetConnectionID ?? profile.InterfaceGuid.ToString()}'", true, -1, 1000);
|
||||
|
||||
interopResult = WlanApi.WlanDeleteProfile(wlanHandle, profile.InterfaceGuid.Value, profile.Name, IntPtr.Zero);
|
||||
|
||||
if (interopResult != WlanApi.ERROR_SUCCESS)
|
||||
{
|
||||
Presentation.UpdateStatus("Enrolling Device", $"Configuring Wireless Profiles\r\nFailed to remove Wireless Profile '{removeName}' from '{adapter?.NetConnectionID ?? profile.InterfaceGuid.ToString()}'; WlanDeleteProfile returned: {interopResult}", true, -1, 3000);
|
||||
}
|
||||
profileRemoved = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (profileRemoved)
|
||||
{
|
||||
existingProfiles = GetWirelessProfiles(wlanHandle);
|
||||
}
|
||||
}
|
||||
|
||||
// Add Profiles
|
||||
if (ProfileStore.Profiles != null && ProfileStore.Profiles.Count > 0)
|
||||
{
|
||||
foreach (var addProfile in ProfileStore.Profiles)
|
||||
{
|
||||
foreach (var adapter in adapters)
|
||||
{
|
||||
var existingProfile = existingProfiles.FirstOrDefault(p => p.Name == addProfile.Name && p.InterfaceGuid == adapter.ConnectionIdentifier);
|
||||
|
||||
if (addProfile.ForceDeployment.Value ||
|
||||
existingProfile == null)
|
||||
{
|
||||
if (existingProfile != null && existingProfile.IsGroupPolicy.Value)
|
||||
{
|
||||
Presentation.UpdateStatus("Enrolling Device", $"Configuring Wireless Profiles\r\nSkipped Wireless Profile '{addProfile.Name}' on '{adapter.NetConnectionID}' as this profile is managed by Group Policy", true, -1, 3000);
|
||||
}
|
||||
else
|
||||
{
|
||||
uint pdwReasonCode;
|
||||
Presentation.UpdateStatus("Enrolling Device", $"Configuring Wireless Profiles\r\nAdding Wireless Profile '{addProfile.Name}' on '{adapter.NetConnectionID}'", true, -1, 1000);
|
||||
interopResult = WlanApi.WlanSetProfile(wlanHandle, adapter.ConnectionIdentifier, 0, addProfile.ProfileXml, null, true, IntPtr.Zero, out pdwReasonCode);
|
||||
|
||||
if (interopResult != WlanApi.ERROR_SUCCESS)
|
||||
{
|
||||
// Get Reason Code
|
||||
var reason = new StringBuilder(256);
|
||||
WlanApi.WlanReasonCodeToString(pdwReasonCode, (uint)reason.Capacity, ref reason, IntPtr.Zero);
|
||||
|
||||
Presentation.UpdateStatus("Enrolling Device", $"Configuring Wireless Profiles\r\nFailed to add Wireless Profile '{addProfile.Name}' on '{adapter.NetConnectionID}'; WlanSetProfile returned: {interopResult}; {reason.ToString()}", true, -1, 3000);
|
||||
}
|
||||
}
|
||||
addedProfiles.Add(addProfile.Name);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Transform Profiles
|
||||
if (ProfileStore.Transformations != null && ProfileStore.Transformations.Count > 0)
|
||||
{
|
||||
foreach (var transformGroup in ProfileStore.Transformations.GroupBy(t => t.Name))
|
||||
{
|
||||
var profileName = transformGroup.Key;
|
||||
|
||||
// Don't transform if just added
|
||||
if (!addedProfiles.Contains(transformGroup.Key))
|
||||
{
|
||||
foreach (var adapter in adapters)
|
||||
{
|
||||
var existingProfile = existingProfiles.FirstOrDefault(p => p.Name == profileName && p.InterfaceGuid == adapter.ConnectionIdentifier);
|
||||
|
||||
if (existingProfile != null)
|
||||
{
|
||||
if (existingProfile.IsGroupPolicy.Value)
|
||||
{
|
||||
Presentation.UpdateStatus("Enrolling Device", $"Configuring Wireless Profiles\r\nSkipped Wireless Profile '{profileName}' on '{adapter.NetConnectionID}' as this profile is managed by Group Policy", true, -1, 3000);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Load profile
|
||||
IntPtr pstrProfileXml;
|
||||
uint pdwFlags;
|
||||
IntPtr pdwGrantAccess;
|
||||
|
||||
interopResult = WlanApi.WlanGetProfile(wlanHandle, adapter.ConnectionIdentifier, profileName, IntPtr.Zero, out pstrProfileXml, out pdwFlags, out pdwGrantAccess);
|
||||
|
||||
if (interopResult == WlanApi.ERROR_SUCCESS)
|
||||
{
|
||||
try
|
||||
{
|
||||
var profileXml = Marshal.PtrToStringUni(pstrProfileXml);
|
||||
var originalProfileXml = XElement.Parse(profileXml);
|
||||
var transformProfileXml = originalProfileXml.ToString(SaveOptions.DisableFormatting);
|
||||
|
||||
// Apply Transforms
|
||||
foreach (var transform in transformGroup)
|
||||
{
|
||||
var regex = new Regex(transform.RegularExpression, RegexOptions.Singleline);
|
||||
transformProfileXml = regex.Replace(transformProfileXml, transform.RegularExpressionReplacement);
|
||||
}
|
||||
|
||||
// Compare XML
|
||||
var transformedProfileXml = XElement.Parse(transformProfileXml);
|
||||
|
||||
if (!XNode.DeepEquals(originalProfileXml, transformedProfileXml))
|
||||
{
|
||||
// Set Profile
|
||||
uint pdwReasonCode;
|
||||
Presentation.UpdateStatus("Enrolling Device", $"Configuring Wireless Profiles\r\nModifying Wireless Profile '{profileName}' on '{adapter.NetConnectionID}'", true, -1, 1000);
|
||||
transformProfileXml = transformedProfileXml.ToString(SaveOptions.None);
|
||||
interopResult = WlanApi.WlanSetProfile(wlanHandle, adapter.ConnectionIdentifier, 0, transformProfileXml, null, true, IntPtr.Zero, out pdwReasonCode);
|
||||
|
||||
if (interopResult != WlanApi.ERROR_SUCCESS)
|
||||
{
|
||||
// Get Reason Code
|
||||
var reason = new StringBuilder(256);
|
||||
WlanApi.WlanReasonCodeToString(pdwReasonCode, (uint)reason.Capacity, ref reason, IntPtr.Zero);
|
||||
|
||||
Presentation.UpdateStatus("Enrolling Device", $"Configuring Wireless Profiles\r\nFailed to modify Wireless Profile '{profileName}' to '{adapter.NetConnectionID}'; WlanSetProfile returned: {interopResult}; {reason.ToString()}", true, -1, 3000);
|
||||
}
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
WlanApi.WlanFreeMemory(pstrProfileXml);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Presentation.UpdateStatus("Enrolling Device", $"Configuring Wireless Profiles\r\nFailed to transform Wireless Profile '{profileName}' on '{adapter.NetConnectionID}'; WlanGetProfile returned: {interopResult}", true, -1, 3000);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
finally
|
||||
{
|
||||
WlanApi.WlanCloseHandle(wlanHandle, IntPtr.Zero);
|
||||
}
|
||||
}
|
||||
catch (DllNotFoundException)
|
||||
{
|
||||
// Indicates 'Wlanapi.dll' isn't present (ie. Servers)
|
||||
// Ignore policies
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw new Exception("Disco ICT Client was unable to apply Wireless Profile Changes using WlanApi", ex);
|
||||
}
|
||||
}
|
||||
|
||||
public static string Description(this WLAN_INTERFACE_STATE State)
|
||||
{
|
||||
switch (State)
|
||||
{
|
||||
case WLAN_INTERFACE_STATE.wlan_interface_state_not_ready:
|
||||
return "Not Ready";
|
||||
case WLAN_INTERFACE_STATE.wlan_interface_state_connected:
|
||||
return "Connected";
|
||||
case WLAN_INTERFACE_STATE.wlan_interface_state_ad_hoc_network_formed:
|
||||
return "Ad Hoc Network";
|
||||
case WLAN_INTERFACE_STATE.wlan_interface_state_disconnecting:
|
||||
return "Disconnecting";
|
||||
case WLAN_INTERFACE_STATE.wlan_interface_state_disconnected:
|
||||
return "Disconnected";
|
||||
case WLAN_INTERFACE_STATE.wlan_interface_state_associating:
|
||||
return "Associating";
|
||||
case WLAN_INTERFACE_STATE.wlan_interface_state_discovering:
|
||||
return "Discovering";
|
||||
case WLAN_INTERFACE_STATE.wlan_interface_state_authenticating:
|
||||
return "Authenticating";
|
||||
default:
|
||||
return "Unknown";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5,6 +5,7 @@ using System.Reflection;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using Disco.Client.Extensions;
|
||||
using Disco.Client.Interop;
|
||||
|
||||
namespace Disco.Client
|
||||
{
|
||||
@@ -38,8 +39,8 @@ namespace Disco.Client
|
||||
public static void WriteBanner()
|
||||
{
|
||||
StringBuilder message = new StringBuilder();
|
||||
message.Append("Version: ").AppendLine(Assembly.GetExecutingAssembly().GetName().Version.ToString(3));
|
||||
message.Append("Device: ").Append(Interop.SystemAudit.DeviceSerialNumber).Append(" (").Append(Interop.SystemAudit.DeviceManufacturer).Append(" ").Append(Interop.SystemAudit.DeviceModel).AppendLine(")");
|
||||
message.AppendLine($"Version: {Assembly.GetExecutingAssembly().GetName().Version.ToString(3)}");
|
||||
message.AppendLine($"Device: {Hardware.Information.SerialNumber} ({Hardware.Information.Manufacturer} {Hardware.Information.Model})");
|
||||
Console.ForegroundColor = ConsoleColor.Yellow;
|
||||
UpdateStatus("Preparation Client Started", message.ToString(), false, 0);
|
||||
Console.ForegroundColor = ConsoleColor.White;
|
||||
@@ -52,8 +53,8 @@ namespace Disco.Client
|
||||
ClientServiceException clientServiceException = ex as ClientServiceException;
|
||||
if (clientServiceException != null)
|
||||
{
|
||||
UpdateStatus(string.Format("An error occurred during {0}", clientServiceException.ServiceFeature),
|
||||
clientServiceException.Message, false, 0);
|
||||
UpdateStatus($"An error occurred during {clientServiceException.ServiceFeature}",
|
||||
clientServiceException.Message, false, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
+11
-4
@@ -20,6 +20,17 @@ namespace Disco.Client
|
||||
{
|
||||
bool keepProcessing;
|
||||
|
||||
#if DEBUG
|
||||
if (args != null && args.Any(a => a.Equals("debug", StringComparison.OrdinalIgnoreCase)))
|
||||
{
|
||||
do
|
||||
{
|
||||
Console.WriteLine("Waiting for Debugger to Attach");
|
||||
System.Threading.Thread.Sleep(1000);
|
||||
} while (!System.Diagnostics.Debugger.IsAttached);
|
||||
}
|
||||
#endif
|
||||
|
||||
// Initialize Environment Settings
|
||||
SetupEnvironment();
|
||||
|
||||
@@ -59,10 +70,6 @@ namespace Disco.Client
|
||||
{
|
||||
Presentation.DelayUI = true; // Add Delays on Error
|
||||
}
|
||||
|
||||
// Initialize Interop
|
||||
Interop.SystemAudit.Initialize();
|
||||
Interop.Network.Initialize();
|
||||
}
|
||||
|
||||
public static bool WhoAmI()
|
||||
|
||||
@@ -1,15 +1,14 @@
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Reflection;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// General Information about an assembly is controlled through the following
|
||||
// set of attributes. Change these attribute values to modify the information
|
||||
// associated with an assembly.
|
||||
[assembly: AssemblyTitle("Disco - Client")]
|
||||
[assembly: AssemblyTitle("Disco ICT - Client")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("Disco")]
|
||||
[assembly: AssemblyCompany("https://discoict.com.au")]
|
||||
[assembly: AssemblyProduct("Disco ICT")]
|
||||
[assembly: AssemblyCopyright("")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
@@ -32,5 +31,5 @@ using System.Runtime.InteropServices;
|
||||
// You can specify all the values or you can default the Build and Revision Numbers
|
||||
// by using the '*' as shown below:
|
||||
// [assembly: AssemblyVersion("1.0.*")]
|
||||
[assembly: AssemblyVersion("2.0.0626.0000")]
|
||||
[assembly: AssemblyFileVersion("2.0.0626.0000")]
|
||||
[assembly: AssemblyVersion("2.3.23161.0650")]
|
||||
[assembly: AssemblyFileVersion("2.3.23161.0650")]
|
||||
@@ -1,4 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="Newtonsoft.Json" version="6.0.3" targetFramework="net40-Client" />
|
||||
<package id="Newtonsoft.Json" version="13.0.2" targetFramework="net40-client" />
|
||||
</packages>
|
||||
@@ -1,6 +1,4 @@
|
||||
//#define Debug
|
||||
|
||||
using System;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
@@ -22,6 +20,14 @@ namespace Disco.ClientBootstrapper
|
||||
private StringBuilder errorMessage;
|
||||
private Process clientProcess;
|
||||
|
||||
//#if DEBUG
|
||||
// public const string DiscoServerName = "WS-GSHARP";
|
||||
// public const int DiscoServerPort = 57252;
|
||||
//#else
|
||||
public const string DiscoServerName = "DISCO";
|
||||
public const int DiscoServerPort = 9292;
|
||||
//#endif
|
||||
|
||||
public BootstrapperLoop(IStatus StatusUI, LoopCompleteCallback Callback)
|
||||
{
|
||||
this.statusUI = StatusUI;
|
||||
@@ -79,12 +85,12 @@ namespace Disco.ClientBootstrapper
|
||||
|
||||
// Check for Network Connectivity
|
||||
statusUI.UpdateStatus(null, "Detecting Network", "Checking network connectivity, Please wait...", true, -1);
|
||||
if (!Interop.NetworkInterop.PingDisco())
|
||||
if (!Interop.NetworkInterop.PingDiscoIct(DiscoServerName))
|
||||
{
|
||||
statusUI.UpdateStatus(null, "Detecting Network", "No network connectivity detected, Diagnosing...", true, -1);
|
||||
statusUI_WriteAdapterInfo();
|
||||
|
||||
if (!Interop.NetworkInterop.PingDisco())
|
||||
if (!Interop.NetworkInterop.PingDiscoIct(DiscoServerName))
|
||||
{
|
||||
// Check for Wireless
|
||||
var hasWireless = (Interop.NetworkInterop.NetworkAdapters.Count(na => na.IsWireless) > 0);
|
||||
@@ -99,17 +105,17 @@ namespace Disco.ClientBootstrapper
|
||||
statusUI_WriteAdapterInfo();
|
||||
statusUI.UpdateStatus(null, null, null, true, i);
|
||||
Program.SleepThread(500, false);
|
||||
if (Interop.NetworkInterop.PingDisco())
|
||||
if (Interop.NetworkInterop.PingDiscoIct(DiscoServerName))
|
||||
break;
|
||||
}
|
||||
if (!Interop.NetworkInterop.PingDisco())
|
||||
if (!Interop.NetworkInterop.PingDiscoIct(DiscoServerName))
|
||||
{
|
||||
statusUI.UpdateStatus(null, "Wireless Network Failed", "Unable to connect to the wireless network, please connect the network cable...", false);
|
||||
Program.SleepThread(3000, false);
|
||||
}
|
||||
}
|
||||
|
||||
if (!Interop.NetworkInterop.PingDisco())
|
||||
if (!Interop.NetworkInterop.PingDiscoIct(DiscoServerName))
|
||||
{
|
||||
// Instruct user to connect network cable
|
||||
statusUI.UpdateStatus(null, "Please connect the network cable", null);
|
||||
@@ -118,13 +124,13 @@ namespace Disco.ClientBootstrapper
|
||||
statusUI_WriteAdapterInfo();
|
||||
statusUI.UpdateStatus(null, null, null, true, i);
|
||||
Program.SleepThread(500, false);
|
||||
if (Interop.NetworkInterop.PingDisco())
|
||||
if (Interop.NetworkInterop.PingDiscoIct(DiscoServerName))
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!Interop.NetworkInterop.PingDisco())
|
||||
if (!Interop.NetworkInterop.PingDiscoIct(DiscoServerName))
|
||||
{
|
||||
// Client Failed
|
||||
if (this.mLoopCompleteCallback != null)
|
||||
@@ -143,7 +149,7 @@ namespace Disco.ClientBootstrapper
|
||||
// Don't use a proxy when downloading the Client
|
||||
webClient.Proxy = new WebProxy();
|
||||
|
||||
webClient.DownloadFile("http://disco:9292/Services/Client/PreparationClient", clientSourceLocation);
|
||||
webClient.DownloadFile($"http://{DiscoServerName}:{DiscoServerPort}/Services/Client/PreparationClient", clientSourceLocation);
|
||||
}
|
||||
|
||||
// Unzip Client
|
||||
|
||||
@@ -8,4 +8,4 @@ BootstrapperLocation = Mid(WScript.ScriptFullName, 1, InStrRev(WScript.ScriptFul
|
||||
|
||||
Call objShell.Run("""" & BootstrapperLocation & """ /Install", , True)
|
||||
|
||||
WScript.Echo "Disco Client Bootstrapper Installed"
|
||||
WScript.Echo "Disco ICT Client Bootstrapper Installed"
|
||||
@@ -10,8 +10,7 @@
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>Disco.ClientBootstrapper</RootNamespace>
|
||||
<AssemblyName>Disco.ClientBootstrapper</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
|
||||
<TargetFrameworkProfile>Client</TargetFrameworkProfile>
|
||||
<TargetFrameworkVersion>v4.5.2</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<PublishUrl>publish\</PublishUrl>
|
||||
<Install>true</Install>
|
||||
@@ -317,11 +316,6 @@
|
||||
</ItemGroup>
|
||||
<ItemGroup />
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<ProjectExtensions>
|
||||
<VisualStudio>
|
||||
<UserProperties BuildVersion_StartDate="2014/6/1" BuildVersion_DetectChanges="False" BuildVersion_UpdateAssemblyVersion="True" BuildVersion_UpdateFileVersion="True" BuildVersion_UseGlobalSettings="False" BuildVersion_BuildAction="Both" BuildVersion_BuildVersioningStyle="None.DeltaBaseYear.MonthAndDayStamp.TimeStamp" />
|
||||
</VisualStudio>
|
||||
</ProjectExtensions>
|
||||
<PropertyGroup>
|
||||
<PostBuildEvent>COPY "$(TargetPath)" "$(ProjectDir)..\Disco.Web\ClientBin"</PostBuildEvent>
|
||||
</PropertyGroup>
|
||||
|
||||
+2
-2
@@ -85,7 +85,7 @@
|
||||
this.labelVersion.Name = "labelVersion";
|
||||
this.labelVersion.Size = new System.Drawing.Size(167, 20);
|
||||
this.labelVersion.TabIndex = 0;
|
||||
this.labelVersion.Text = "Disco Bootstrapper v";
|
||||
this.labelVersion.Text = "Disco ICT Bootstrapper v";
|
||||
this.labelVersion.TextAlign = System.Drawing.ContentAlignment.TopRight;
|
||||
//
|
||||
// FormStatus
|
||||
@@ -106,7 +106,7 @@
|
||||
this.ShowIcon = false;
|
||||
this.ShowInTaskbar = false;
|
||||
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
|
||||
this.Text = "Disco - Client Bootstrapper";
|
||||
this.Text = "Disco ICT - Client Bootstrapper";
|
||||
this.TopMost = true;
|
||||
this.TransparencyKey = System.Drawing.Color.Magenta;
|
||||
this.ResumeLayout(false);
|
||||
|
||||
@@ -1,7 +1,4 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
|
||||
namespace Disco.ClientBootstrapper
|
||||
@@ -14,11 +11,13 @@ namespace Disco.ClientBootstrapper
|
||||
private CompleteCallback mCompleteCallback;
|
||||
private string InstallLocation;
|
||||
private string WimImageId;
|
||||
private string TempPath;
|
||||
|
||||
public InstallLoop(string InstallLocation, string WimImageId = null)
|
||||
public InstallLoop(string InstallLocation, string WimImageId, string TempPath)
|
||||
{
|
||||
this.InstallLocation = InstallLocation;
|
||||
this.WimImageId = WimImageId;
|
||||
this.TempPath = TempPath;
|
||||
}
|
||||
|
||||
public void Start(CompleteCallback Callback)
|
||||
@@ -34,7 +33,7 @@ namespace Disco.ClientBootstrapper
|
||||
|
||||
//Program.Status.UpdateStatus(null, null, "Testing UI");
|
||||
//Program.SleepThread(5000, false);
|
||||
Interop.InstallInterop.Install(this.InstallLocation, this.WimImageId);
|
||||
Interop.InstallInterop.Install(this.InstallLocation, this.WimImageId, this.TempPath);
|
||||
if (this.mCompleteCallback != null)
|
||||
{
|
||||
this.mCompleteCallback.BeginInvoke(null, null);
|
||||
|
||||
@@ -16,8 +16,9 @@ namespace Disco.ClientBootstrapper.Interop
|
||||
if (_tempCerts != null && _tempCerts.Count > 0)
|
||||
{
|
||||
Remove(StoreName.My, StoreLocation.LocalMachine, _tempCerts);
|
||||
Remove(StoreName.CertificateAuthority, StoreLocation.LocalMachine, _tempCerts);
|
||||
Remove(StoreName.Root, StoreLocation.LocalMachine, _tempCerts);
|
||||
// dont remove root/intermediate certs as they may be have installed by client
|
||||
//Remove(StoreName.CertificateAuthority, StoreLocation.LocalMachine, _tempCerts);
|
||||
//Remove(StoreName.Root, StoreLocation.LocalMachine, _tempCerts);
|
||||
}
|
||||
}
|
||||
public static void AddTempCerts()
|
||||
@@ -106,7 +107,26 @@ namespace Disco.ClientBootstrapper.Interop
|
||||
public static string ShortSubjectName(this X509Certificate2 Certificate)
|
||||
{
|
||||
string s = Certificate.Subject;
|
||||
return s.Substring(s.IndexOf("=") + 1, s.IndexOf(",") - s.IndexOf("=") - 1);
|
||||
if (string.IsNullOrWhiteSpace(s))
|
||||
{
|
||||
return $"Unknown Certificate: {Certificate.Thumbprint}";
|
||||
}
|
||||
else
|
||||
{
|
||||
if (s.Length > 3 && s.StartsWith("CN=", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
var nameLength = s.IndexOf(',') - 3;
|
||||
if (nameLength > 0)
|
||||
{
|
||||
return s.Substring(3, nameLength);
|
||||
}
|
||||
else
|
||||
{
|
||||
return s.Substring(3);
|
||||
}
|
||||
}
|
||||
return s;
|
||||
}
|
||||
}
|
||||
|
||||
public static bool Add(StoreName StoreName, StoreLocation StoreLocation, X509Certificate2 Certificate)
|
||||
|
||||
@@ -1,13 +1,9 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Windows.Forms;
|
||||
using System.Diagnostics;
|
||||
using System.Runtime.InteropServices;
|
||||
using Microsoft.Win32;
|
||||
using Microsoft.Win32;
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Threading;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
|
||||
namespace Disco.ClientBootstrapper.Interop
|
||||
{
|
||||
@@ -187,7 +183,7 @@ namespace Disco.ClientBootstrapper.Interop
|
||||
#endregion
|
||||
}
|
||||
|
||||
public static void Install(string InstallLocation, string WimImageId = null)
|
||||
public static void Install(string InstallLocation, string WimImageId, string TempPath)
|
||||
{
|
||||
Program.Status.UpdateStatus("Installing Bootstrapper", "Starting", "Please wait...", false);
|
||||
|
||||
@@ -234,12 +230,12 @@ namespace Disco.ClientBootstrapper.Interop
|
||||
}
|
||||
|
||||
// Get Temp Path
|
||||
var wimMountPath = Path.Combine(Path.GetTempPath(), "DiscoClientBootstrapperWimMount");
|
||||
var wimMountPath = Path.Combine(TempPath ?? Path.GetTempPath(), "DiscoClientBootstrapperWimMount");
|
||||
if (Directory.Exists(wimMountPath))
|
||||
Directory.Delete(wimMountPath, true);
|
||||
Directory.CreateDirectory(wimMountPath);
|
||||
|
||||
var wimTempMountPath = Path.Combine(Path.GetTempPath(), "DiscoClientBootstrapperWimTempMount");
|
||||
var wimTempMountPath = Path.Combine(TempPath ?? Path.GetTempPath(), "DiscoClientBootstrapperWimTempMount");
|
||||
if (Directory.Exists(wimTempMountPath))
|
||||
Directory.Delete(wimTempMountPath, true);
|
||||
Directory.CreateDirectory(wimTempMountPath);
|
||||
|
||||
@@ -165,13 +165,13 @@ namespace Disco.ClientBootstrapper.Interop
|
||||
}
|
||||
}
|
||||
|
||||
public static bool PingDisco()
|
||||
public static bool PingDiscoIct(string ServerName)
|
||||
{
|
||||
using (Ping p = new Ping())
|
||||
{
|
||||
try
|
||||
{
|
||||
PingReply pr = p.Send("disco", 2000);
|
||||
PingReply pr = p.Send(ServerName, 2000);
|
||||
if (pr.Status == IPStatus.Success)
|
||||
return true;
|
||||
else
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Windows.Forms;
|
||||
using System.Threading;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace Disco.ClientBootstrapper
|
||||
{
|
||||
@@ -40,11 +39,14 @@ namespace Disco.ClientBootstrapper
|
||||
statusForm.Show();
|
||||
string installLocation = null;
|
||||
string wimImage = null;
|
||||
string tempPath = null;
|
||||
if (args.Length > 1)
|
||||
installLocation = args[1];
|
||||
if (args.Length > 2)
|
||||
wimImage = args[2];
|
||||
InstallLoop = new InstallLoop(installLocation, wimImage);
|
||||
if (args.Length > 3)
|
||||
tempPath = args[3];
|
||||
InstallLoop = new InstallLoop(installLocation, wimImage, tempPath);
|
||||
InstallLoop.Start(new InstallLoop.CompleteCallback(InstallComplete));
|
||||
Application.Run();
|
||||
return;
|
||||
|
||||
@@ -1,15 +1,14 @@
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Reflection;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// General Information about an assembly is controlled through the following
|
||||
// set of attributes. Change these attribute values to modify the information
|
||||
// associated with an assembly.
|
||||
[assembly: AssemblyTitle("Disco - Client Bootstrapper")]
|
||||
[assembly: AssemblyTitle("Disco ICT - Client Bootstrapper")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("Disco")]
|
||||
[assembly: AssemblyCompany("https://discoict.com.au")]
|
||||
[assembly: AssemblyProduct("Disco ICT")]
|
||||
[assembly: AssemblyCopyright("")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
@@ -32,5 +31,5 @@ using System.Runtime.InteropServices;
|
||||
// You can specify all the values or you can default the Build and Revision Numbers
|
||||
// by using the '*' as shown below:
|
||||
// [assembly: AssemblyVersion("1.0.*")]
|
||||
[assembly: AssemblyVersion("2.0.0626.0000")]
|
||||
[assembly: AssemblyFileVersion("2.0.0626.0000")]
|
||||
[assembly: AssemblyVersion("2.3.23161.0650")]
|
||||
[assembly: AssemblyFileVersion("2.3.23161.0650")]
|
||||
@@ -15,6 +15,6 @@
|
||||
</defaultConnectionFactory>
|
||||
</entityFramework>
|
||||
<startup>
|
||||
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
|
||||
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.2"/>
|
||||
</startup>
|
||||
</configuration>
|
||||
</configuration>
|
||||
|
||||
@@ -1,29 +0,0 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
|
||||
namespace Disco.Data.Configuration
|
||||
{
|
||||
public static class CommunityHelpers
|
||||
{
|
||||
public static string CommunityUrl()
|
||||
{
|
||||
// Special case for DiscoCommunity Hosting Network
|
||||
try
|
||||
{
|
||||
var ip = (from addr in Dns.GetHostEntry(Dns.GetHostName()).AddressList
|
||||
where addr.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork
|
||||
&& addr.ToString().StartsWith("10.131.200.")
|
||||
select addr).FirstOrDefault();
|
||||
if (ip != null)
|
||||
{
|
||||
return "http://hades3:9393/base/";
|
||||
}
|
||||
}
|
||||
catch (Exception)
|
||||
{ } // Ignore Errors
|
||||
|
||||
return "https://discoict.com.au/base/";
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -34,11 +34,11 @@ namespace Disco.Data.Configuration
|
||||
|
||||
private void SetValue<T>(string Key, T Value)
|
||||
{
|
||||
ConfigurationCache.SetValue(Database, this.Scope, Key, Value);
|
||||
ConfigurationCache.Helpers<T>.SetValue(Database, this.Scope, Key, Value);
|
||||
}
|
||||
private T GetValue<T>(string Key, T Default)
|
||||
{
|
||||
return ConfigurationCache.GetValue(Database, this.Scope, Key, Default);
|
||||
return ConfigurationCache.Helpers<T>.GetValue(Database, this.Scope, Key, Default);
|
||||
}
|
||||
|
||||
protected void Set<T>(T Value, [CallerMemberName] string Key = null)
|
||||
|
||||
@@ -202,89 +202,95 @@ namespace Disco.Data.Configuration
|
||||
#endregion
|
||||
|
||||
#region Cache Getters/Setters
|
||||
internal static T GetValue<T>(DiscoDataContext Database, string Scope, string Key, T Default)
|
||||
internal static class Helpers<T>
|
||||
{
|
||||
var item = CacheGetItem(Database, Scope, Key);
|
||||
private static readonly IEqualityComparer<T> comparer = EqualityComparer<T>.Default;
|
||||
|
||||
if (item == null)
|
||||
return Default;
|
||||
else
|
||||
internal static T GetValue(DiscoDataContext Database, string Scope, string Key, T Default)
|
||||
{
|
||||
if (item.Item2 != null && item.Item2.GetType() == typeof(T))
|
||||
{
|
||||
// Return Cached Item
|
||||
return (T)item.Item2;
|
||||
}
|
||||
var item = CacheGetItem(Database, Scope, Key);
|
||||
|
||||
if (item == null)
|
||||
return Default;
|
||||
else
|
||||
{
|
||||
// Convert Serialized Item
|
||||
Type itemType = typeof(T);
|
||||
object itemValue;
|
||||
|
||||
if (itemType == typeof(string))
|
||||
if (item.Item2 != null && item.Item2.GetType() == typeof(T))
|
||||
{
|
||||
// string
|
||||
itemValue = item.Item1.Value;
|
||||
}
|
||||
else if (itemType == typeof(object))
|
||||
{
|
||||
// object
|
||||
itemValue = item.Item1.Value;
|
||||
}
|
||||
else if (IsConvertableFromString(itemType))
|
||||
{
|
||||
// IConvertable
|
||||
itemValue = Convert.ChangeType(item.Item1.Value, itemType);
|
||||
}
|
||||
else if (itemType.BaseType != null && itemType.BaseType == typeof(Enum))
|
||||
{
|
||||
// Enum
|
||||
itemValue = Enum.Parse(typeof(T), item.Item1.Value);
|
||||
// Return Cached Item
|
||||
return (T)item.Item2;
|
||||
}
|
||||
else
|
||||
{
|
||||
// JSON Deserialize
|
||||
itemValue = JsonConvert.DeserializeObject<T>(item.Item1.Value);
|
||||
// Convert Serialized Item
|
||||
Type itemType = typeof(T);
|
||||
object itemValue;
|
||||
|
||||
if (itemType == typeof(string))
|
||||
{
|
||||
// string
|
||||
itemValue = item.Item1.Value;
|
||||
}
|
||||
else if (itemType == typeof(object))
|
||||
{
|
||||
// object
|
||||
itemValue = item.Item1.Value;
|
||||
}
|
||||
else if (IsConvertableFromString(itemType))
|
||||
{
|
||||
// IConvertable
|
||||
itemValue = Convert.ChangeType(item.Item1.Value, itemType);
|
||||
}
|
||||
else if (itemType.BaseType != null && itemType.BaseType == typeof(Enum))
|
||||
{
|
||||
// Enum
|
||||
itemValue = Enum.Parse(typeof(T), item.Item1.Value);
|
||||
}
|
||||
else
|
||||
{
|
||||
// JSON Deserialize
|
||||
itemValue = JsonConvert.DeserializeObject<T>(item.Item1.Value);
|
||||
}
|
||||
|
||||
// Set Item in Cache
|
||||
SetItemTypeValue(item, itemValue);
|
||||
|
||||
return (T)itemValue;
|
||||
}
|
||||
|
||||
// Set Item in Cache
|
||||
SetItemTypeValue(item, itemValue);
|
||||
|
||||
return (T)itemValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
internal static void SetValue<T>(DiscoDataContext Database, string Scope, string Key, T Value)
|
||||
{
|
||||
Type valueType = typeof(T);
|
||||
string stringValue;
|
||||
internal static void SetValue(DiscoDataContext Database, string Scope, string Key, T Value)
|
||||
{
|
||||
Type valueType = typeof(T);
|
||||
string stringValue;
|
||||
|
||||
if (Value == null)
|
||||
{
|
||||
stringValue = null;
|
||||
}
|
||||
else if (valueType == typeof(object))
|
||||
{
|
||||
throw new ArgumentException(string.Format("Cannot serialize the configuration item [{0}].[{1}] which defines a type of [System.Object]", Scope, Key), "Value");
|
||||
}
|
||||
else if (IsConvertableFromString(valueType))
|
||||
{
|
||||
// string or supports IConvertable
|
||||
stringValue = Value.ToString();
|
||||
}
|
||||
else if (valueType.BaseType != null && valueType.BaseType == typeof(Enum))
|
||||
{
|
||||
// Enum
|
||||
stringValue = Value.ToString();
|
||||
}
|
||||
else
|
||||
{
|
||||
// JSON Serialize
|
||||
stringValue = JsonConvert.SerializeObject(Value);
|
||||
}
|
||||
if (comparer.Equals(Value, default(T)))
|
||||
{
|
||||
stringValue = null;
|
||||
}
|
||||
else if (valueType == typeof(object))
|
||||
{
|
||||
throw new ArgumentException(string.Format("Cannot serialize the configuration item [{0}].[{1}] which defines a type of [System.Object]", Scope, Key), "Value");
|
||||
}
|
||||
else if (IsConvertableFromString(valueType))
|
||||
{
|
||||
// string or supports IConvertable
|
||||
stringValue = Value.ToString();
|
||||
}
|
||||
else if (valueType.BaseType != null && valueType.BaseType == typeof(Enum))
|
||||
{
|
||||
// Enum
|
||||
stringValue = Value.ToString();
|
||||
}
|
||||
else
|
||||
{
|
||||
// JSON Serialize
|
||||
stringValue = JsonConvert.SerializeObject(Value);
|
||||
}
|
||||
|
||||
CacheSetItem(Database, Scope, Key, stringValue, Value);
|
||||
CacheSetItem(Database, Scope, Key, stringValue, Value);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Cache Helpers
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
using Disco.Data.Repository;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
|
||||
namespace Disco.Data.Configuration.Modules
|
||||
{
|
||||
@@ -24,10 +26,44 @@ namespace Disco.Data.Configuration.Modules
|
||||
}
|
||||
}
|
||||
|
||||
[Obsolete("User SearchAllServers instead"), EditorBrowsable(EditorBrowsableState.Never)]
|
||||
public bool? SearchAllForestServers
|
||||
{
|
||||
get { return Get<bool?>(null); }
|
||||
set { Set(value); }
|
||||
}
|
||||
|
||||
public bool? SearchAllServers
|
||||
{
|
||||
get {
|
||||
var value = Get<bool?>(null);
|
||||
|
||||
/// migrate <see cref="SearchAllForestServers"/>
|
||||
#pragma warning disable CS0618 // Type or member is obsolete
|
||||
if (value == null)
|
||||
{
|
||||
value = SearchAllForestServers;
|
||||
if (value != null)
|
||||
{
|
||||
SearchAllForestServers = null;
|
||||
SearchAllServers = value;
|
||||
}
|
||||
}
|
||||
#pragma warning restore CS0618 // Type or member is obsolete
|
||||
|
||||
return value;
|
||||
}
|
||||
set { Set(value); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// If true LDAP filters contain wildcards only at the end of the search term.
|
||||
/// This greatly improves performance in very large AD environments (ie: EDU001/EDU002)
|
||||
/// </summary>
|
||||
public bool SearchWildcardSuffixOnly
|
||||
{
|
||||
get { return Get(true); }
|
||||
set { Set(value); }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
using Disco.Data.Repository;
|
||||
using Disco.Models.Services.Documents;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Disco.Data.Configuration.Modules
|
||||
{
|
||||
public class DocumentsConfiguration : ConfigurationBase
|
||||
{
|
||||
public DocumentsConfiguration(DiscoDataContext Database) : base(Database) { }
|
||||
|
||||
public override string Scope { get { return "Documents"; } }
|
||||
|
||||
public List<DocumentTemplatePackage> Packages
|
||||
{
|
||||
get { return Get<List<DocumentTemplatePackage>>(null); }
|
||||
set { Set(value); }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
using Disco.Data.Repository;
|
||||
using Disco.Models.BI.Job;
|
||||
using Disco.Models.Services.Job;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
@@ -41,15 +41,43 @@ namespace Disco.Data.Configuration.Modules
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Theme used in noticeboards by default.
|
||||
/// <see cref="Disco.Services.Extensions.UIHelpers.NoticeboardThemes"/>
|
||||
/// </summary>
|
||||
public string DefaultNoticeboardTheme
|
||||
{
|
||||
get { return Get("default"); }
|
||||
set
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(value))
|
||||
throw new ArgumentNullException("DefaultNoticeboardTheme");
|
||||
|
||||
Set(value);
|
||||
}
|
||||
}
|
||||
|
||||
public LocationModes LocationMode
|
||||
{
|
||||
get { return Get<LocationModes>(LocationModes.Unrestricted); }
|
||||
get { return Get(LocationModes.Unrestricted); }
|
||||
set { Set(value); }
|
||||
}
|
||||
|
||||
public List<string> LocationList
|
||||
{
|
||||
get { return Get<List<string>>(new List<string>()); }
|
||||
get { return Get(new List<string>()); }
|
||||
set { Set(value); }
|
||||
}
|
||||
|
||||
public string OnCreateExpression
|
||||
{
|
||||
get { return Get<string>(null); }
|
||||
set { Set(value); }
|
||||
}
|
||||
|
||||
public string OnCloseExpression
|
||||
{
|
||||
get { return Get<string>(null); }
|
||||
set { Set(value); }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,7 +16,7 @@ namespace Disco.Data.Configuration.Modules
|
||||
|
||||
public OrganisationAddress GetAddress(int Id)
|
||||
{
|
||||
return this.Get<OrganisationAddress>(null, Id.ToString());
|
||||
return Get<OrganisationAddress>(null, Id.ToString());
|
||||
}
|
||||
public OrganisationAddress SetAddress(OrganisationAddress Address)
|
||||
{
|
||||
@@ -25,21 +25,21 @@ namespace Disco.Data.Configuration.Modules
|
||||
Address.Id = NextOrganisationAddressId;
|
||||
}
|
||||
|
||||
this.Set(Address, Address.Id.ToString());
|
||||
Set(Address, Address.Id.ToString());
|
||||
|
||||
return Address;
|
||||
}
|
||||
public void RemoveAddress(int Id)
|
||||
{
|
||||
// Remove Configuration Item
|
||||
this.RemoveItem(Id.ToString());
|
||||
RemoveItem(Id.ToString());
|
||||
}
|
||||
|
||||
public List<OrganisationAddress> Addresses
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.ItemKeys.Select(key => this.Get<OrganisationAddress>(null, key)).ToList();
|
||||
return ItemKeys.Select(key => Get<OrganisationAddress>(null, key)).ToList();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -50,7 +50,7 @@ namespace Disco.Data.Configuration.Modules
|
||||
int nextId = 0;
|
||||
while (true)
|
||||
{
|
||||
if (this.Get<string>(null, nextId.ToString()) == null)
|
||||
if (Get<string>(null, nextId.ToString()) == null)
|
||||
break;
|
||||
nextId++;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
using Disco.Data.Repository;
|
||||
using Disco.Models.BI.Interop.Community;
|
||||
using Disco.Models.Services.Interop.DiscoServices;
|
||||
using System;
|
||||
using System.IO;
|
||||
|
||||
@@ -11,12 +11,13 @@ namespace Disco.Data.Configuration
|
||||
: base(Database)
|
||||
{
|
||||
// Init Modules
|
||||
this.moduleBootstrapperConfiguration = new Lazy<Modules.BootstrapperConfiguration>(() => new Modules.BootstrapperConfiguration(Database));
|
||||
this.moduleDeviceProfilesConfiguration = new Lazy<Modules.DeviceProfilesConfiguration>(() => new Modules.DeviceProfilesConfiguration(Database));
|
||||
this.moduleOrganisationAddressesConfiguration = new Lazy<Modules.OrganisationAddressesConfiguration>(() => new Modules.OrganisationAddressesConfiguration(Database));
|
||||
this.moduleJobPreferencesConfiguration = new Lazy<Modules.JobPreferencesConfiguration>(() => new Modules.JobPreferencesConfiguration(Database));
|
||||
this.moduleActiveDirectoryConfiguration = new Lazy<Modules.ActiveDirectoryConfiguration>(() => new Modules.ActiveDirectoryConfiguration(Database));
|
||||
this.moduleDevicesConfiguration = new Lazy<Modules.DevicesConfiguration>(() => new Modules.DevicesConfiguration(Database));
|
||||
moduleBootstrapperConfiguration = new Lazy<Modules.BootstrapperConfiguration>(() => new Modules.BootstrapperConfiguration(Database));
|
||||
moduleDeviceProfilesConfiguration = new Lazy<Modules.DeviceProfilesConfiguration>(() => new Modules.DeviceProfilesConfiguration(Database));
|
||||
moduleOrganisationAddressesConfiguration = new Lazy<Modules.OrganisationAddressesConfiguration>(() => new Modules.OrganisationAddressesConfiguration(Database));
|
||||
moduleJobPreferencesConfiguration = new Lazy<Modules.JobPreferencesConfiguration>(() => new Modules.JobPreferencesConfiguration(Database));
|
||||
moduleActiveDirectoryConfiguration = new Lazy<Modules.ActiveDirectoryConfiguration>(() => new Modules.ActiveDirectoryConfiguration(Database));
|
||||
moduleDevicesConfiguration = new Lazy<Modules.DevicesConfiguration>(() => new Modules.DevicesConfiguration(Database));
|
||||
moduleDocumentsConfiguration = new Lazy<Modules.DocumentsConfiguration>(() => new Modules.DocumentsConfiguration(Database));
|
||||
}
|
||||
|
||||
#region Configuration Modules
|
||||
@@ -27,6 +28,7 @@ namespace Disco.Data.Configuration
|
||||
private Lazy<Modules.JobPreferencesConfiguration> moduleJobPreferencesConfiguration;
|
||||
private Lazy<Modules.ActiveDirectoryConfiguration> moduleActiveDirectoryConfiguration;
|
||||
private Lazy<Modules.DevicesConfiguration> moduleDevicesConfiguration;
|
||||
private Lazy<Modules.DocumentsConfiguration> moduleDocumentsConfiguration;
|
||||
|
||||
public Modules.BootstrapperConfiguration Bootstrapper
|
||||
{
|
||||
@@ -71,6 +73,14 @@ namespace Disco.Data.Configuration
|
||||
}
|
||||
}
|
||||
|
||||
public Modules.DocumentsConfiguration Documents
|
||||
{
|
||||
get
|
||||
{
|
||||
return moduleDocumentsConfiguration.Value;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
public override string Scope { get { return "System"; } }
|
||||
@@ -79,7 +89,7 @@ namespace Disco.Data.Configuration
|
||||
{
|
||||
get
|
||||
{
|
||||
var result = this.Get<string>(null);
|
||||
var result = Get<string>(null);
|
||||
if (result == null)
|
||||
{
|
||||
var appDataPath = System.Web.HttpContext.Current.Server.MapPath("~/App_Data");
|
||||
@@ -102,7 +112,7 @@ namespace Disco.Data.Configuration
|
||||
storePath = value;
|
||||
else
|
||||
storePath = string.Concat(value, '\\');
|
||||
this.Set(storePath);
|
||||
Set(storePath);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -110,7 +120,7 @@ namespace Disco.Data.Configuration
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.Get<string>("Domain Admins,Disco Admins");
|
||||
return Get("Domain Admins,Disco Admins");
|
||||
}
|
||||
set
|
||||
{
|
||||
@@ -123,23 +133,32 @@ namespace Disco.Data.Configuration
|
||||
{
|
||||
get
|
||||
{
|
||||
return System.IO.Path.Combine(this.DataStoreLocation, @"Plugins\");
|
||||
return System.IO.Path.Combine(DataStoreLocation, @"Plugins\");
|
||||
}
|
||||
}
|
||||
public string PluginStorageLocation
|
||||
{
|
||||
get
|
||||
{
|
||||
return System.IO.Path.Combine(this.DataStoreLocation, @"PluginStorage\");
|
||||
return System.IO.Path.Combine(DataStoreLocation, @"PluginStorage\");
|
||||
}
|
||||
}
|
||||
public string PluginPackagesLocation
|
||||
{
|
||||
get
|
||||
{
|
||||
return System.IO.Path.Combine(this.DataStoreLocation, @"PluginPackages\");
|
||||
return System.IO.Path.Combine(DataStoreLocation, @"PluginPackages\");
|
||||
}
|
||||
}
|
||||
|
||||
public string PluginUserPhotosLocation
|
||||
=> Path.Combine(DataStoreLocation, @"PluginUserPhotos\");
|
||||
|
||||
public DateTime PluginDetailsCacheExpiration
|
||||
{
|
||||
get => Get(DateTime.MinValue);
|
||||
set => Set(value);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Organisation Details
|
||||
@@ -155,7 +174,7 @@ namespace Disco.Data.Configuration
|
||||
{
|
||||
get
|
||||
{
|
||||
var path = this.OrganisationLogoPath;
|
||||
var path = OrganisationLogoPath;
|
||||
if (File.Exists(path))
|
||||
return File.GetLastWriteTimeUtc(path).ToBinary().ToString();
|
||||
else
|
||||
@@ -166,7 +185,7 @@ namespace Disco.Data.Configuration
|
||||
{
|
||||
get
|
||||
{
|
||||
var path = this.OrganisationLogoPath;
|
||||
var path = OrganisationLogoPath;
|
||||
if (File.Exists(path))
|
||||
return new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read);
|
||||
else
|
||||
@@ -174,7 +193,7 @@ namespace Disco.Data.Configuration
|
||||
}
|
||||
set
|
||||
{
|
||||
string organisationLogoPath = this.OrganisationLogoPath;
|
||||
string organisationLogoPath = OrganisationLogoPath;
|
||||
if (value == null)
|
||||
{
|
||||
if (System.IO.File.Exists(organisationLogoPath))
|
||||
@@ -194,22 +213,22 @@ namespace Disco.Data.Configuration
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.Get<string>(null);
|
||||
return Get<string>(null);
|
||||
}
|
||||
set
|
||||
{
|
||||
this.Set(value);
|
||||
Set(value);
|
||||
}
|
||||
}
|
||||
public bool MultiSiteMode
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.Get(false);
|
||||
return Get(false);
|
||||
}
|
||||
set
|
||||
{
|
||||
this.Set(value);
|
||||
Set(value);
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
@@ -219,79 +238,140 @@ namespace Disco.Data.Configuration
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.Get<string>(null);
|
||||
return Get<string>(null);
|
||||
}
|
||||
set
|
||||
{
|
||||
this.Set(value);
|
||||
Set(value);
|
||||
}
|
||||
}
|
||||
public int ProxyPort
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.Get(8080);
|
||||
return Get(8080);
|
||||
}
|
||||
set
|
||||
{
|
||||
this.Set(value);
|
||||
Set(value);
|
||||
}
|
||||
}
|
||||
public string ProxyUsername
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.Get<string>(null);
|
||||
return Get<string>(null);
|
||||
}
|
||||
set
|
||||
{
|
||||
this.Set(value);
|
||||
Set(value);
|
||||
}
|
||||
}
|
||||
public string ProxyPassword
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.GetDeobsfucated(null);
|
||||
return GetDeobsfucated(null);
|
||||
}
|
||||
set
|
||||
{
|
||||
this.SetObsfucated(value);
|
||||
SetObsfucated(value);
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Email Configuration
|
||||
public string EmailSmtpServer
|
||||
{
|
||||
get => Get<string>(null);
|
||||
set => Set(value);
|
||||
}
|
||||
public int EmailSmtpPort
|
||||
{
|
||||
get => Get(25);
|
||||
set => Set(value);
|
||||
}
|
||||
public bool EmailEnableSsl
|
||||
{
|
||||
get => Get(false);
|
||||
set => Set(value);
|
||||
}
|
||||
public string EmailFromAddress
|
||||
{
|
||||
get => Get<string>(null);
|
||||
set => Set(value);
|
||||
}
|
||||
public string EmailReplyToAddress
|
||||
{
|
||||
get => Get<string>(null);
|
||||
set => Set(value);
|
||||
}
|
||||
public string EmailUsername
|
||||
{
|
||||
get => Get<string>(null);
|
||||
set => Set(value);
|
||||
}
|
||||
public string EmailPassword
|
||||
{
|
||||
get => GetDeobsfucated(null);
|
||||
set => SetObsfucated(value);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region UpdateCheck
|
||||
public string DeploymentId
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.Get<string>(null);
|
||||
return Get<string>(null);
|
||||
}
|
||||
}
|
||||
public UpdateResponse UpdateLastCheck
|
||||
public string DeploymentSecret
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.Get<UpdateResponse>(null);
|
||||
return Get<string>(null);
|
||||
}
|
||||
}
|
||||
public short DeploymentChecksum
|
||||
{
|
||||
get
|
||||
{
|
||||
var deploymentIdBytes = Guid.Parse(DeploymentId).ToByteArray();
|
||||
return
|
||||
(short)(BitConverter.ToInt16(deploymentIdBytes, 0) ^
|
||||
BitConverter.ToInt16(deploymentIdBytes, 2) ^
|
||||
BitConverter.ToInt16(deploymentIdBytes, 4) ^
|
||||
BitConverter.ToInt16(deploymentIdBytes, 6) ^
|
||||
BitConverter.ToInt16(deploymentIdBytes, 8) ^
|
||||
BitConverter.ToInt16(deploymentIdBytes, 10) ^
|
||||
BitConverter.ToInt16(deploymentIdBytes, 12) ^
|
||||
BitConverter.ToInt16(deploymentIdBytes, 14));
|
||||
}
|
||||
}
|
||||
public UpdateResponseV2 UpdateLastCheckResponse
|
||||
{
|
||||
get
|
||||
{
|
||||
return Get<UpdateResponseV2>(null);
|
||||
}
|
||||
set
|
||||
{
|
||||
this.Set(value);
|
||||
Set(value);
|
||||
}
|
||||
}
|
||||
public bool UpdateBetaDeployment
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.Get<bool>(false);
|
||||
return Get(false);
|
||||
}
|
||||
}
|
||||
public Version InstalledDatabaseVersion
|
||||
{
|
||||
get
|
||||
{
|
||||
var versionString = this.Get<string>(null);
|
||||
var versionString = Get<string>(null);
|
||||
if (string.IsNullOrEmpty(versionString))
|
||||
return null;
|
||||
else
|
||||
@@ -299,7 +379,7 @@ namespace Disco.Data.Configuration
|
||||
}
|
||||
set
|
||||
{
|
||||
this.Set<string>(value.ToString(4));
|
||||
Set(value.ToString(4));
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>Disco.Data</RootNamespace>
|
||||
<AssemblyName>Disco.Data</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
|
||||
<TargetFrameworkVersion>v4.6.2</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<TargetFrameworkProfile />
|
||||
<SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\</SolutionDir>
|
||||
@@ -40,8 +40,8 @@
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\packages\EntityFramework.5.0.0\lib\net45\EntityFramework.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Newtonsoft.Json">
|
||||
<HintPath>..\packages\Newtonsoft.Json.6.0.3\lib\net45\Newtonsoft.Json.dll</HintPath>
|
||||
<Reference Include="Newtonsoft.Json, Version=13.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Newtonsoft.Json.13.0.2\lib\net45\Newtonsoft.Json.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.ComponentModel.DataAnnotations" />
|
||||
@@ -49,21 +49,21 @@
|
||||
<Reference Include="System.Data.Entity" />
|
||||
<Reference Include="System.DirectoryServices" />
|
||||
<Reference Include="System.Drawing" />
|
||||
<Reference Include="System.Reactive.Core, Version=2.2.4.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||
<Reference Include="System.Reactive.Core, Version=2.2.5.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\packages\Rx-Core.2.2.4\lib\net45\System.Reactive.Core.dll</HintPath>
|
||||
<HintPath>..\packages\Rx-Core.2.2.5\lib\net45\System.Reactive.Core.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.Reactive.Interfaces, Version=2.2.4.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||
<Reference Include="System.Reactive.Interfaces, Version=2.2.5.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\packages\Rx-Interfaces.2.2.4\lib\net45\System.Reactive.Interfaces.dll</HintPath>
|
||||
<HintPath>..\packages\Rx-Interfaces.2.2.5\lib\net45\System.Reactive.Interfaces.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.Reactive.Linq, Version=2.2.4.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||
<Reference Include="System.Reactive.Linq, Version=2.2.5.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\packages\Rx-Linq.2.2.4\lib\net45\System.Reactive.Linq.dll</HintPath>
|
||||
<HintPath>..\packages\Rx-Linq.2.2.5\lib\net45\System.Reactive.Linq.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.Reactive.PlatformServices, Version=2.2.4.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||
<Reference Include="System.Reactive.PlatformServices, Version=2.2.5.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\packages\Rx-PlatformServices.2.2.4\lib\net45\System.Reactive.PlatformServices.dll</HintPath>
|
||||
<HintPath>..\packages\Rx-PlatformServices.2.2.5\lib\net45\System.Reactive.PlatformServices.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.Web" />
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
@@ -73,11 +73,11 @@
|
||||
<Reference Include="System.Xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Configuration\CommunityHelpers.cs" />
|
||||
<Compile Include="Configuration\ConfigurationBase.cs" />
|
||||
<Compile Include="Configuration\ConfigurationCache.cs" />
|
||||
<Compile Include="Configuration\Modules\ActiveDirectoryConfiguration.cs" />
|
||||
<Compile Include="Configuration\Modules\DevicesConfiguration.cs" />
|
||||
<Compile Include="Configuration\Modules\DocumentsConfiguration.cs" />
|
||||
<Compile Include="Configuration\Modules\JobPreferencesConfiguration.cs" />
|
||||
<Compile Include="Configuration\SystemConfiguration.cs" />
|
||||
<Compile Include="Configuration\Modules\BootstrapperConfiguration.cs" />
|
||||
@@ -143,6 +143,42 @@
|
||||
<Compile Include="Migrations\201406160912525_DBv14.Designer.cs">
|
||||
<DependentUpon>201406160912525_DBv14.cs</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Migrations\201407100413342_DBv15.cs" />
|
||||
<Compile Include="Migrations\201407100413342_DBv15.Designer.cs">
|
||||
<DependentUpon>201407100413342_DBv15.cs</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Migrations\201407260624238_DBv16.cs" />
|
||||
<Compile Include="Migrations\201407260624238_DBv16.Designer.cs">
|
||||
<DependentUpon>201407260624238_DBv16.cs</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Migrations\201609260741183_DBv17.cs" />
|
||||
<Compile Include="Migrations\201609260741183_DBv17.Designer.cs">
|
||||
<DependentUpon>201609260741183_DBv17.cs</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Migrations\201611090729100_DBv18.cs" />
|
||||
<Compile Include="Migrations\201611090729100_DBv18.Designer.cs">
|
||||
<DependentUpon>201611090729100_DBv18.cs</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Migrations\201611100557315_DBv19.cs" />
|
||||
<Compile Include="Migrations\201611100557315_DBv19.Designer.cs">
|
||||
<DependentUpon>201611100557315_DBv19.cs</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Migrations\202011260525547_DBv20.cs" />
|
||||
<Compile Include="Migrations\202011260525547_DBv20.Designer.cs">
|
||||
<DependentUpon>202011260525547_DBv20.cs</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Migrations\202102110443550_DBv21.cs" />
|
||||
<Compile Include="Migrations\202102110443550_DBv21.Designer.cs">
|
||||
<DependentUpon>202102110443550_DBv21.cs</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Migrations\202304150715559_DBv22.cs" />
|
||||
<Compile Include="Migrations\202304150715559_DBv22.Designer.cs">
|
||||
<DependentUpon>202304150715559_DBv22.cs</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Migrations\202401130531317_DBv23.cs" />
|
||||
<Compile Include="Migrations\202401130531317_DBv23.Designer.cs">
|
||||
<DependentUpon>202401130531317_DBv23.cs</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Migrations\Configuration.cs" />
|
||||
<Compile Include="Migrations\DiscoDataMigrator.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
@@ -200,6 +236,33 @@
|
||||
<EmbeddedResource Include="Migrations\201406160912525_DBv14.resx">
|
||||
<DependentUpon>201406160912525_DBv14.cs</DependentUpon>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Include="Migrations\201407100413342_DBv15.resx">
|
||||
<DependentUpon>201407100413342_DBv15.cs</DependentUpon>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Include="Migrations\201407260624238_DBv16.resx">
|
||||
<DependentUpon>201407260624238_DBv16.cs</DependentUpon>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Include="Migrations\201609260741183_DBv17.resx">
|
||||
<DependentUpon>201609260741183_DBv17.cs</DependentUpon>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Include="Migrations\201611090729100_DBv18.resx">
|
||||
<DependentUpon>201611090729100_DBv18.cs</DependentUpon>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Include="Migrations\201611100557315_DBv19.resx">
|
||||
<DependentUpon>201611100557315_DBv19.cs</DependentUpon>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Include="Migrations\202011260525547_DBv20.resx">
|
||||
<DependentUpon>202011260525547_DBv20.cs</DependentUpon>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Include="Migrations\202102110443550_DBv21.resx">
|
||||
<DependentUpon>202102110443550_DBv21.cs</DependentUpon>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Include="Migrations\202304150715559_DBv22.resx">
|
||||
<DependentUpon>202304150715559_DBv22.cs</DependentUpon>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Include="Migrations\202401130531317_DBv23.resx">
|
||||
<DependentUpon>202401130531317_DBv23.cs</DependentUpon>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Include="Properties\Resources.resx">
|
||||
<Generator>ResXFileCodeGenerator</Generator>
|
||||
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
|
||||
@@ -213,10 +276,9 @@
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<ProjectExtensions>
|
||||
<VisualStudio>
|
||||
<UserProperties BuildVersion_UpdateFileVersion="True" BuildVersion_UpdateAssemblyVersion="True" BuildVersion_BuildVersioningStyle="None.DeltaBaseYear.MonthAndDayStamp.TimeStamp" BuildVersion_StartDate="2014/6/1" BuildVersion_DetectChanges="False" BuildVersion_UseGlobalSettings="False" BuildVersion_BuildAction="Both" />
|
||||
<UserProperties BuildVersion_StartDate="2000/1/1" />
|
||||
</VisualStudio>
|
||||
</ProjectExtensions>
|
||||
<Import Project="$(SolutionDir)\.nuget\nuget.targets" />
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
Other similar extension points exist, see Microsoft.Common.targets.
|
||||
<Target Name="BeforeBuild">
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
// <auto-generated />
|
||||
namespace Disco.Data.Migrations
|
||||
{
|
||||
using System.Data.Entity.Migrations;
|
||||
using System.Data.Entity.Migrations.Infrastructure;
|
||||
using System.Resources;
|
||||
|
||||
public sealed partial class DBv15 : IMigrationMetadata
|
||||
{
|
||||
private readonly ResourceManager Resources = new ResourceManager(typeof(DBv15));
|
||||
|
||||
string IMigrationMetadata.Id
|
||||
{
|
||||
get { return "201407100413342_DBv15"; }
|
||||
}
|
||||
|
||||
string IMigrationMetadata.Source
|
||||
{
|
||||
get { return null; }
|
||||
}
|
||||
|
||||
string IMigrationMetadata.Target
|
||||
{
|
||||
get { return Resources.GetString("Target"); }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
namespace Disco.Data.Migrations
|
||||
{
|
||||
using System;
|
||||
using System.Data.Entity.Migrations;
|
||||
|
||||
public partial class DBv15 : DbMigration
|
||||
{
|
||||
public override void Up()
|
||||
{
|
||||
AddColumn("dbo.DeviceModels", "DefaultRepairProvider", c => c.String(maxLength: 40));
|
||||
|
||||
// Clear UpdateLastCheck due to Update Protocol v2
|
||||
Sql("DELETE [Configuration] WHERE [Scope]='System' AND [Key]='UpdateLastCheck'");
|
||||
}
|
||||
|
||||
public override void Down()
|
||||
{
|
||||
DropColumn("dbo.DeviceModels", "DefaultRepairProvider");
|
||||
}
|
||||
}
|
||||
}
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1,27 @@
|
||||
// <auto-generated />
|
||||
namespace Disco.Data.Migrations
|
||||
{
|
||||
using System.Data.Entity.Migrations;
|
||||
using System.Data.Entity.Migrations.Infrastructure;
|
||||
using System.Resources;
|
||||
|
||||
public sealed partial class DBv16 : IMigrationMetadata
|
||||
{
|
||||
private readonly ResourceManager Resources = new ResourceManager(typeof(DBv16));
|
||||
|
||||
string IMigrationMetadata.Id
|
||||
{
|
||||
get { return "201407260624238_DBv16"; }
|
||||
}
|
||||
|
||||
string IMigrationMetadata.Source
|
||||
{
|
||||
get { return null; }
|
||||
}
|
||||
|
||||
string IMigrationMetadata.Target
|
||||
{
|
||||
get { return Resources.GetString("Target"); }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
namespace Disco.Data.Migrations
|
||||
{
|
||||
using System;
|
||||
using System.Data.Entity.Migrations;
|
||||
|
||||
public partial class DBv16 : DbMigration
|
||||
{
|
||||
public override void Up()
|
||||
{
|
||||
AddColumn("dbo.DocumentTemplates", "OnGenerateExpression", c => c.String());
|
||||
AddColumn("dbo.DocumentTemplates", "OnImportAttachmentExpression", c => c.String());
|
||||
AlterColumn("dbo.DocumentTemplates", "FilterExpression", c => c.String());
|
||||
}
|
||||
|
||||
public override void Down()
|
||||
{
|
||||
AlterColumn("dbo.DocumentTemplates", "FilterExpression", c => c.String(maxLength: 250));
|
||||
DropColumn("dbo.DocumentTemplates", "OnImportAttachmentExpression");
|
||||
DropColumn("dbo.DocumentTemplates", "OnGenerateExpression");
|
||||
}
|
||||
}
|
||||
}
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1,27 @@
|
||||
// <auto-generated />
|
||||
namespace Disco.Data.Migrations
|
||||
{
|
||||
using System.Data.Entity.Migrations;
|
||||
using System.Data.Entity.Migrations.Infrastructure;
|
||||
using System.Resources;
|
||||
|
||||
public sealed partial class DBv17 : IMigrationMetadata
|
||||
{
|
||||
private readonly ResourceManager Resources = new ResourceManager(typeof(DBv17));
|
||||
|
||||
string IMigrationMetadata.Id
|
||||
{
|
||||
get { return "201609260741183_DBv17"; }
|
||||
}
|
||||
|
||||
string IMigrationMetadata.Source
|
||||
{
|
||||
get { return null; }
|
||||
}
|
||||
|
||||
string IMigrationMetadata.Target
|
||||
{
|
||||
get { return Resources.GetString("Target"); }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
namespace Disco.Data.Migrations
|
||||
{
|
||||
using System;
|
||||
using System.Data.Entity.Migrations;
|
||||
|
||||
public partial class DBv17 : DbMigration
|
||||
{
|
||||
public override void Up()
|
||||
{
|
||||
RenameColumn("dbo.DeviceProfiles", "CertificateProviderId", "CertificateProviders");
|
||||
AlterColumn("dbo.DeviceProfiles", "CertificateProviders", c => c.String(maxLength: 200));
|
||||
AddColumn("dbo.DeviceProfiles", "CertificateAuthorityProviders", c => c.String(maxLength: 200));
|
||||
AddColumn("dbo.DeviceProfiles", "WirelessProfileProviders", c => c.String(maxLength: 200));
|
||||
|
||||
// Migration support for eduSTAR.net plugin
|
||||
Sql("UPDATE [DeviceProfiles] SET [CertificateAuthorityProviders]='EduSTARnetCertificateAuthorityProvider', [WirelessProfileProviders]='EduSTARnetWirelessProfileProvider' WHERE [CertificateProviders]='EduSTARnetCertificateProvider'");
|
||||
}
|
||||
|
||||
public override void Down()
|
||||
{
|
||||
AddColumn("dbo.DeviceProfiles", "CertificateProviderId", c => c.String(maxLength: 64));
|
||||
DropColumn("dbo.DeviceProfiles", "WirelessProfileProviders");
|
||||
DropColumn("dbo.DeviceProfiles", "CertificateAuthorityProviders");
|
||||
DropColumn("dbo.DeviceProfiles", "CertificateProviders");
|
||||
}
|
||||
}
|
||||
}
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1,27 @@
|
||||
// <auto-generated />
|
||||
namespace Disco.Data.Migrations
|
||||
{
|
||||
using System.Data.Entity.Migrations;
|
||||
using System.Data.Entity.Migrations.Infrastructure;
|
||||
using System.Resources;
|
||||
|
||||
public sealed partial class DBv18 : IMigrationMetadata
|
||||
{
|
||||
private readonly ResourceManager Resources = new ResourceManager(typeof(DBv18));
|
||||
|
||||
string IMigrationMetadata.Id
|
||||
{
|
||||
get { return "201611090729100_DBv18"; }
|
||||
}
|
||||
|
||||
string IMigrationMetadata.Source
|
||||
{
|
||||
get { return null; }
|
||||
}
|
||||
|
||||
string IMigrationMetadata.Target
|
||||
{
|
||||
get { return Resources.GetString("Target"); }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
namespace Disco.Data.Migrations
|
||||
{
|
||||
using System;
|
||||
using System.Data.Entity.Migrations;
|
||||
|
||||
public partial class DBv18 : DbMigration
|
||||
{
|
||||
public override void Up()
|
||||
{
|
||||
AddColumn("dbo.UserFlagAssignments", "OnAssignmentExpressionResult", c => c.String());
|
||||
AddColumn("dbo.UserFlagAssignments", "OnUnassignmentExpressionResult", c => c.String());
|
||||
AddColumn("dbo.UserFlags", "OnAssignmentExpression", c => c.String());
|
||||
AddColumn("dbo.UserFlags", "OnUnassignmentExpression", c => c.String());
|
||||
}
|
||||
|
||||
public override void Down()
|
||||
{
|
||||
DropColumn("dbo.UserFlags", "OnUnassignmentExpression");
|
||||
DropColumn("dbo.UserFlags", "OnAssignmentExpression");
|
||||
DropColumn("dbo.UserFlagAssignments", "OnUnassignmentExpressionResult");
|
||||
DropColumn("dbo.UserFlagAssignments", "OnAssignmentExpressionResult");
|
||||
}
|
||||
}
|
||||
}
|
||||
File diff suppressed because one or more lines are too long
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user