AmagnoVirtualPrinter/Common/AmagnoVirtualPrinter.Agent.Lib/Misc/JobFactory.cs
2023-05-30 17:22:56 +02:00

218 lines
7.6 KiB
C#

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Security.Principal;
using AmagnoVirtualPrinter.Agent.Core.Enums;
using AmagnoVirtualPrinter.Agent.Core.Interfaces;
using AmagnoVirtualPrinter.Agent.Core.Model;
using AmagnoVirtualPrinter.Logging;
using Cassia;
using JetBrains.Annotations;
using AmagnoVirtualPrinter.Agent.Core;
namespace AmagnoVirtualPrinter.Agent.Lib.Misc
{
public class JobFactory : IJobFactory
{
[NotNull]
private readonly IVirtualPrinterLogger<JobFactory> _logger;
private readonly IDirectoryHelper _directoryHelper;
[NotNull]
private readonly IRegistryRepository _registryRepository;
public JobFactory
(
[NotNull]IRegistryRepository registryRepository,
[NotNull]IVirtualPrinterLogger<JobFactory> logger,
[NotNull]IDirectoryHelper directoryHelper
)
{
if (registryRepository == null)
{
throw new ArgumentNullException(nameof(registryRepository));
}
if (logger == null)
{
throw new ArgumentNullException(nameof(logger));
}
if (directoryHelper == null)
{
throw new ArgumentNullException(nameof(logger));
}
_registryRepository = registryRepository;
_logger = logger;
_directoryHelper = directoryHelper;
}
public IJob Create(string printerName, Stream stream)
{
if (printerName == null)
{
throw new ArgumentNullException(nameof(printerName));
}
if (stream == null)
{
throw new ArgumentNullException(nameof(stream));
}
try
{
var now = DateTime.Now;
var jobInfo = PrintJobReader.GetCurrentPrintJobs(printerName).FirstOrDefault();
if (jobInfo == null)
{
throw new InvalidOperationException();
}
var sessions = GetCurrentSessions(jobInfo).ToArray();
var session = sessions.FirstOrDefault(s => s.FoundDomain) ?? sessions.FirstOrDefault();
var config = _registryRepository.GetRegistryConfig();
var userConfig = _registryRepository.GetUserRegistryConfig(session.Sid);
var root = _directoryHelper.GetOutputDirectory(userConfig);
var iniName = GenerateFileName(now, jobInfo.JobId, 0, config.FileNameMask, "ini");
var iniPath = Path.Combine(root, iniName);
var extension = GetRawFileExtension(config.IntermediateFormat);
var rawName = $"{Path.GetFileNameWithoutExtension(iniName)}.{extension}";
var rawPath = Path.Combine(root, rawName);
using (var output = File.Create(rawPath))
{
stream.CopyTo(output);
}
return new Job
{
RawDataPath = rawPath,
IniDataPath = iniPath,
JobInfo = jobInfo,
SessionInfo = session
};
}
catch (Exception exception)
{
LogError(exception, "Failed to create job.");
return null;
}
}
public IJob Create(string iniPath, string rawPath, IJobInfo jobInfo, ISessionInfo sessionInfo)
{
if (string.IsNullOrWhiteSpace(iniPath))
{
throw new ArgumentException("Value cannot be null or whitespace.", nameof(iniPath));
}
if (string.IsNullOrWhiteSpace(rawPath))
{
throw new ArgumentException("Value cannot be null or whitespace.", nameof(rawPath));
}
return new Job
{
IniDataPath = iniPath,
RawDataPath = rawPath,
JobInfo = jobInfo,
SessionInfo = sessionInfo
};
}
[NotNull]
private string GenerateFileName(DateTime time, int job, int page, [NotNull]string pattern, [NotNull]string ending)
{
var fileName = pattern;
fileName = fileName.Replace("{yyyy}", $"{time.Year:0000}");
fileName = fileName.Replace("{MM}", $"{time.Month:00}");
fileName = fileName.Replace("{DD}", $"{time.Day:00}");
fileName = fileName.Replace("{hh}", $"{time.Hour:00}");
fileName = fileName.Replace("{mm}", $"{time.Minute:00}");
fileName = fileName.Replace("{ss}", $"{time.Second:00}");
fileName = fileName.Replace("{fff}", $"{time.Millisecond:000}");
fileName = fileName.Replace("{job05}", $"{job:00000}");
fileName = fileName.Replace("{page03}", $"{page:000}");
return $"{fileName}.{ending}";
}
private IEnumerable<SessionInfo> GetCurrentSessions([NotNull]IJobInfo job)
{
var domain = job.DomainName;
var machine = job.MachineName?.TrimStart('\\');
var username = job.UserName;
LogDebug($"Searching for session of {domain}\\{username} on {machine} !");
if (domain == null || machine == null || username == null)
{
yield break;
}
const StringComparison cmp = StringComparison.OrdinalIgnoreCase;
using (var server = new TerminalServicesManager().GetLocalServer())
{
var sessions = server.GetSessions().Where(s => s.UserName != null && s.DomainName != null);
foreach (var session in sessions)
{
if (!session.UserName.Equals(username, cmp))
{
continue;
}
var isSingleUser = session.DomainName.Equals(machine, cmp);
var isDomainUser = session.DomainName.Equals(domain, cmp);
if (!isSingleUser && !isDomainUser)
{
LogWarn("Found Session {sessionId} for {username} but its not of domain {domain} or {machine}", session.SessionId, username, domain, machine);
}
var sessionId = session.SessionId;
var desktopName = session.WindowStationName;
var account = session.UserAccount;
yield return new SessionInfo
{
Id = sessionId,
Desktop = desktopName,
Sid = account.Translate(typeof(SecurityIdentifier)).Value,
FoundDomain = isSingleUser || isDomainUser
};
}
}
}
[NotNull]
private string GetRawFileExtension(IntermediateFormat format)
{
switch (format)
{
case IntermediateFormat.Xps:
return "xps";
case IntermediateFormat.Ps:
return "ps";
default:
throw new ArgumentOutOfRangeException();
}
}
private void LogDebug(string message)
{
_logger.Debug(message);
}
private void LogError(Exception exception, string message, params object[] args)
{
_logger.Error(exception, message, args);
}
private void LogWarn(string message, params object[] args)
{
_logger.Warn(message, args);
}
}
}