Ejemplo n.º 1
0
        /// <summary>
        /// Runs when the <see cref="fileSystemWatcher"/> triggers
        /// </summary>
        /// <param name="sender">The sender of the event</param>
        /// <param name="e">The <see cref="FileSystemEventArgs"/></param>
        async void HandleWrite(object sender, FileSystemEventArgs e)         // this is what async void was made for
        {
            try
            {
                var fileBytes = await ioManager.ReadAllBytes(e.FullPath, cancellationToken).ConfigureAwait(false);

                var file = Encoding.UTF8.GetString(fileBytes);

                logger.LogTrace("Read interop command json: {0}", file);

                CommCommand command;
                try
                {
                    command = new CommCommand
                    {
                        Parameters = JsonConvert.DeserializeObject <IReadOnlyDictionary <string, object> >(file),
                        RawJson    = file
                    };
                }
                catch (JsonException ex)
                {
                    // file not fully written yet
                    logger.LogDebug("Suppressing json convert exception for command file write: {0}", ex);
                    return;
                }

                await(handler?.HandleInterop(command, cancellationToken) ?? Task.CompletedTask).ConfigureAwait(false);
            }
            catch (OperationCanceledException) { }
            catch (Exception ex)
            {
                logger.LogError("Exception while trying to handle command json write: {0}", ex);
            }
        }
Ejemplo n.º 2
0
        /// <inheritdoc />
        public async Task TrustDmbPath(string fullDmbPath, CancellationToken cancellationToken)
        {
            if (fullDmbPath == null)
            {
                throw new ArgumentNullException(nameof(fullDmbPath));
            }

            using (await SemaphoreSlimContext.Lock(trustedFileSemaphore, cancellationToken).ConfigureAwait(false))
            {
                string trustedFileText;

                if (await ioManager.FileExists(trustedFilePath, cancellationToken).ConfigureAwait(false))
                {
                    var trustedFileBytes = await ioManager.ReadAllBytes(trustedFilePath, cancellationToken).ConfigureAwait(false);

                    trustedFileText = Encoding.UTF8.GetString(trustedFileBytes);
                    trustedFileText = $"{trustedFileText.Trim()}{Environment.NewLine}";
                }
                else
                {
                    trustedFileText = String.Empty;
                }

                if (trustedFileText.Contains(fullDmbPath, StringComparison.Ordinal))
                {
                    return;
                }

                trustedFileText = $"{trustedFileText}{fullDmbPath}{Environment.NewLine}";

                var newTrustedFileBytes = Encoding.UTF8.GetBytes(trustedFileText);
                await ioManager.WriteAllBytes(trustedFilePath, newTrustedFileBytes, cancellationToken).ConfigureAwait(false);
            }
        }
Ejemplo n.º 3
0
        /// <inheritdoc />
        public async Task <IReadOnlyList <CustomCommand> > GetCustomCommands(CancellationToken cancellationToken)
        {
            try
            {
                var resultBytes = await ioManager.ReadAllBytes(commandsPath, cancellationToken).ConfigureAwait(false);

                var resultJson = Encoding.UTF8.GetString(resultBytes);
                var result     = JsonConvert.DeserializeObject <List <CustomCommand> >(resultJson, new JsonSerializerSettings
                {
                    ContractResolver = new DefaultContractResolver
                    {
                        NamingStrategy = new SnakeCaseNamingStrategy()
                    }
                });
                foreach (var I in result)
                {
                    I.SetHandler(customCommandHandler);
                }
                return(result);
            }
            catch
            {
                return(new List <CustomCommand>());
            }
        }
Ejemplo n.º 4
0
        /// <summary>
        /// Adds server side includes to the .dme being compiled
        /// </summary>
        /// <param name="job">The <see cref="Models.CompileJob"/> for the operation</param>
        /// <param name="cancellationToken">The <see cref="CancellationToken"/> for the operation</param>
        /// <returns>A <see cref="Task"/> representing the running operation</returns>
        async Task ModifyDme(Models.CompileJob job, CancellationToken cancellationToken)
        {
            var dirA        = ioManager.ConcatPath(job.DirectoryName.ToString(), ADirectoryName);
            var dmeFileName = String.Join('.', job.DmeName, DmeExtension);
            var dmePath     = ioManager.ConcatPath(dirA, dmeFileName);
            var dmeReadTask = ioManager.ReadAllBytes(dmePath, cancellationToken);

            var dmeModificationsTask = configuration.CopyDMFilesTo(dmeFileName, ioManager.ResolvePath(dirA), cancellationToken);

            var dmeBytes = await dmeReadTask.ConfigureAwait(false);

            var dme = Encoding.UTF8.GetString(dmeBytes);

            var dmeModifications = await dmeModificationsTask.ConfigureAwait(false);

            if (dmeModifications == null || dmeModifications.TotalDmeOverwrite)
            {
                if (dmeModifications != null)
                {
                    logger.LogDebug(".dme replacement configured!");
                }
                else
                {
                    logger.LogTrace("No .dme modifications required.");
                }
                return;
            }

            if (dmeModifications.HeadIncludeLine != null)
            {
                logger.LogDebug("Head .dme include line: {0}", dmeModifications.HeadIncludeLine);
            }
            if (dmeModifications.TailIncludeLine != null)
            {
                logger.LogDebug("Tail .dme include line: {0}", dmeModifications.TailIncludeLine);
            }

            var dmeLines = new List <string>(dme.Split(new[] { Environment.NewLine }, StringSplitOptions.None));

            for (var I = 0; I < dmeLines.Count; ++I)
            {
                var line = dmeLines[I];
                if (line.Contains("BEGIN_INCLUDE", StringComparison.Ordinal) && dmeModifications.HeadIncludeLine != null)
                {
                    dmeLines.Insert(I + 1, dmeModifications.HeadIncludeLine);
                    ++I;
                }
                else if (line.Contains("END_INCLUDE", StringComparison.Ordinal) && dmeModifications.TailIncludeLine != null)
                {
                    dmeLines.Insert(I, dmeModifications.TailIncludeLine);
                    break;
                }
            }

            dmeBytes = Encoding.UTF8.GetBytes(String.Join(Environment.NewLine, dmeLines));
            await ioManager.WriteAllBytes(dmePath, dmeBytes, cancellationToken).ConfigureAwait(false);
        }
Ejemplo n.º 5
0
        public async Task <IActionResult> GetLog(string path, CancellationToken cancellationToken)
        {
            if (path == null)
            {
                throw new ArgumentNullException(nameof(path));
            }

            path = HttpUtility.UrlDecode(path);

            // guard against directory navigation
            var sanitizedPath = ioManager.GetFileName(path);

            if (path != sanitizedPath)
            {
                return(Forbid());
            }

            var fullPath = ioManager.ConcatPath(
                fileLoggingConfiguration.GetFullLogDirectory(ioManager, assemblyInformationProvider, platformIdentifier),
                path);

            try
            {
                var fileTransferTicket = fileTransferService.CreateDownload(
                    new FileDownloadProvider(
                        () => null,
                        null,
                        fullPath,
                        true));

                var readTask = ioManager.ReadAllBytes(fullPath, cancellationToken);

                return(Ok(new LogFileResponse
                {
                    Name = path,
                    LastModified = await ioManager.GetLastModified(fullPath, cancellationToken).ConfigureAwait(false),
                    FileTicket = fileTransferTicket.FileTicket,
                }));
            }
            catch (IOException ex)
            {
                return(Conflict(new ErrorMessageResponse(ErrorCode.IOError)
                {
                    AdditionalData = ex.ToString(),
                }));
            }
        }
Ejemplo n.º 6
0
        /// <inheritdoc />
        public async Task SymlinkStaticFilesTo(string destination, CancellationToken cancellationToken)
        {
            async Task <IReadOnlyList <string> > GetIgnoreFiles()
            {
                var ignoreFileBytes = await ioManager.ReadAllBytes(StaticIgnorePath(), cancellationToken).ConfigureAwait(false);

                var ignoreFileText = Encoding.UTF8.GetString(ignoreFileBytes);

                var results = new List <string> {
                    StaticIgnoreFile
                };

                //we don't want to lose trailing whitespace on linux
                using (var reader = new StringReader(ignoreFileText))
                {
                    cancellationToken.ThrowIfCancellationRequested();
                    var line = await reader.ReadLineAsync().ConfigureAwait(false);

                    if (!String.IsNullOrEmpty(line))
                    {
                        results.Add(line);
                    }
                }

                return(results);
            };

            IReadOnlyList <string> ignoreFiles;

            async Task SymlinkBase(bool files)
            {
                Task <IReadOnlyList <string> > task;

                if (files)
                {
                    task = ioManager.GetFiles(GameStaticFilesSubdirectory, cancellationToken);
                }
                else
                {
                    task = ioManager.GetDirectories(GameStaticFilesSubdirectory, cancellationToken);
                }
                var entries = await task.ConfigureAwait(false);

                await Task.WhenAll(entries.Select(async x =>
                {
                    var fileName = ioManager.GetFileName(x);

                    bool ignored;
                    if (platformIdentifier.IsWindows)
                    {
                        //need to normalize
                        ignored = ignoreFiles.Any(y => fileName.ToUpperInvariant() == y.ToUpperInvariant());
                    }
                    else
                    {
                        ignored = ignoreFiles.Any(y => fileName == y);
                    }

                    if (ignored)
                    {
                        logger.LogTrace("Ignoring static file {0}...", fileName);
                        return;
                    }

                    var destPath = ioManager.ConcatPath(destination, fileName);
                    logger.LogTrace("Symlinking {0} to {1}...", x, destPath);
                    var fileExistsTask = ioManager.FileExists(destPath, cancellationToken);
                    if (await ioManager.DirectoryExists(destPath, cancellationToken).ConfigureAwait(false))
                    {
                        await ioManager.DeleteDirectory(destPath, cancellationToken).ConfigureAwait(false);
                    }
                    var fileExists = await fileExistsTask.ConfigureAwait(false);
                    if (fileExists)
                    {
                        await ioManager.DeleteFile(destPath, cancellationToken).ConfigureAwait(false);
                    }
                    await symlinkFactory.CreateSymbolicLink(ioManager.ResolvePath(x), ioManager.ResolvePath(destPath), cancellationToken).ConfigureAwait(false);
                })).ConfigureAwait(false);
            }

            using (await SemaphoreSlimContext.Lock(semaphore, cancellationToken).ConfigureAwait(false))
            {
                await EnsureDirectories(cancellationToken).ConfigureAwait(false);

                ignoreFiles = await GetIgnoreFiles().ConfigureAwait(false);

                await Task.WhenAll(SymlinkBase(true), SymlinkBase(false)).ConfigureAwait(false);
            }
        }
Ejemplo n.º 7
0
        /// <inheritdoc />
        public async Task <bool> CheckRunWizard(CancellationToken cancellationToken)
        {
            var setupWizardMode = generalConfiguration.SetupWizardMode;

            logger.LogTrace("Checking if setup wizard should run. SetupWizardMode: {0}", setupWizardMode);

            if (setupWizardMode == SetupWizardMode.Never)
            {
                logger.LogTrace("Skipping due to configuration...");
                return(false);
            }

            var forceRun = setupWizardMode == SetupWizardMode.Force || setupWizardMode == SetupWizardMode.Only;

            if (!console.Available)
            {
                if (forceRun)
                {
                    throw new InvalidOperationException("Asked to run setup wizard with no console avaliable!");
                }
                logger.LogTrace("Skipping due to console not being available...");
                return(false);
            }

            var userConfigFileName = String.Format(CultureInfo.InvariantCulture, "appsettings.{0}.json", hostingEnvironment.EnvironmentName);
            var exists             = await ioManager.FileExists(userConfigFileName, cancellationToken).ConfigureAwait(false);

            bool shouldRunBasedOnAutodetect;

            if (exists)
            {
                var bytes = await ioManager.ReadAllBytes(userConfigFileName, cancellationToken).ConfigureAwait(false);

                var contents = Encoding.UTF8.GetString(bytes);
                var existingConfigIsEmpty = String.IsNullOrWhiteSpace(contents);
                logger.LogTrace("Configuration json detected. Empty: {0}", existingConfigIsEmpty);
                shouldRunBasedOnAutodetect = existingConfigIsEmpty;
            }
            else
            {
                shouldRunBasedOnAutodetect = true;
                logger.LogTrace("No configuration json detected");
            }


            if (!shouldRunBasedOnAutodetect)
            {
                if (forceRun)
                {
                    logger.LogTrace("Asking user to bypass due to force run request...");
                    await console.WriteAsync(String.Format(CultureInfo.InvariantCulture, "The configuration settings are requesting the setup wizard be run, but you already appear to have a configuration file ({0})!", userConfigFileName), true, cancellationToken).ConfigureAwait(false);

                    forceRun = await PromptYesNo("Continue running setup wizard? (y/n): ", cancellationToken).ConfigureAwait(false);
                }
                if (!forceRun)
                {
                    return(false);
                }
            }

            //flush the logs to prevent console conflicts
            await Task.Delay(TimeSpan.FromSeconds(1), cancellationToken).ConfigureAwait(false);

            await RunWizard(userConfigFileName, cancellationToken).ConfigureAwait(false);

            return(true);
        }
Ejemplo n.º 8
0
        /// <inheritdoc />
        public async Task StartAsync(CancellationToken cancellationToken)
        {
            async Task <byte[]> GetActiveVersion()
            {
                var activeVersionFileExists = await ioManager.FileExists(ActiveVersionFileName, cancellationToken).ConfigureAwait(false);

                return(!activeVersionFileExists ? null : await ioManager.ReadAllBytes(ActiveVersionFileName, cancellationToken).ConfigureAwait(false));
            }

            var activeVersionBytesTask = GetActiveVersion();

            // Create local cfg directory in case it doesn't exist
            var localCfgDirectory = ioManager.ConcatPath(
                byondInstaller.PathToUserByondFolder,
                CfgDirectoryName);
            await ioManager.CreateDirectory(
                localCfgDirectory,
                cancellationToken).ConfigureAwait(false);

            // Delete trusted.txt so it doesn't grow too large
            var trustedFilePath =
                ioManager.ConcatPath(
                    localCfgDirectory,
                    TrustedDmbFileName);

            logger.LogTrace("Deleting trusted .dmbs file {0}", trustedFilePath);
            await ioManager.DeleteFile(
                trustedFilePath,
                cancellationToken).ConfigureAwait(false);

            var byondDirectory = ioManager.ResolvePath();
            await ioManager.CreateDirectory(byondDirectory, cancellationToken).ConfigureAwait(false);

            var directories = await ioManager.GetDirectories(byondDirectory, cancellationToken).ConfigureAwait(false);

            async Task ReadVersion(string path)
            {
                var versionFile = ioManager.ConcatPath(path, VersionFileName);

                if (!await ioManager.FileExists(versionFile, cancellationToken).ConfigureAwait(false))
                {
                    logger.LogInformation("Cleaning unparsable version path: {0}", ioManager.ResolvePath(path));
                    await ioManager.DeleteDirectory(path, cancellationToken).ConfigureAwait(false);                     // cleanup

                    return;
                }

                var bytes = await ioManager.ReadAllBytes(versionFile, cancellationToken).ConfigureAwait(false);

                var text = Encoding.UTF8.GetString(bytes);

                if (Version.TryParse(text, out var version))
                {
                    var key = VersionKey(version);
                    lock (installedVersions)
                        if (!installedVersions.ContainsKey(key))
                        {
                            logger.LogDebug("Adding detected BYOND version {0}...", key);
                            installedVersions.Add(key, Task.CompletedTask);
                            return;
                        }
                }

                await ioManager.DeleteDirectory(path, cancellationToken).ConfigureAwait(false);
            }

            await Task.WhenAll(directories.Select(x => ReadVersion(x))).ConfigureAwait(false);

            var activeVersionBytes = await activeVersionBytesTask.ConfigureAwait(false);

            if (activeVersionBytes != null)
            {
                var  activeVersionString = Encoding.UTF8.GetString(activeVersionBytes);
                bool hasRequestedActiveVersion;
                lock (installedVersions)
                    hasRequestedActiveVersion = installedVersions.ContainsKey(activeVersionString);
                if (hasRequestedActiveVersion && Version.TryParse(activeVersionString, out var activeVersion))
                {
                    ActiveVersion = activeVersion.Semver();
                }
                else
                {
                    logger.LogWarning("Failed to load saved active version {0}!", activeVersionString);
                    await ioManager.DeleteFile(ActiveVersionFileName, cancellationToken).ConfigureAwait(false);
                }
            }
        }
Ejemplo n.º 9
0
        /// <summary>
        /// Check if it should and run the <see cref="SetupWizard"/> if necessary.
        /// </summary>
        /// <param name="cancellationToken">The <see cref="CancellationToken"/> for the operation.</param>
        /// <returns>A <see cref="Task"/> representing the running operation.</returns>
        async Task CheckRunWizard(CancellationToken cancellationToken)
        {
            var setupWizardMode = generalConfiguration.SetupWizardMode;

            if (setupWizardMode == SetupWizardMode.Never)
            {
                return;
            }

            var forceRun = setupWizardMode == SetupWizardMode.Force || setupWizardMode == SetupWizardMode.Only;

            if (!console.Available)
            {
                if (forceRun)
                {
                    throw new InvalidOperationException("Asked to run setup wizard with no console avaliable!");
                }
                return;
            }

            var userConfigFileName = String.Format(CultureInfo.InvariantCulture, "appsettings.{0}.json", hostingEnvironment.EnvironmentName);

            async Task HandleSetupCancel()
            {
                // DCTx2: Operation should always run
                await console.WriteAsync(String.Empty, true, default).ConfigureAwait(false);

                await console.WriteAsync("Aborting setup!", true, default).ConfigureAwait(false);
            }

            // Link passed cancellationToken with cancel key press
            Task finalTask = Task.CompletedTask;

            using (var cts = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, console.CancelKeyPress))
                using ((cancellationToken = cts.Token).Register(() => finalTask = HandleSetupCancel()))
                    try
                    {
                        var exists = await ioManager.FileExists(userConfigFileName, cancellationToken).ConfigureAwait(false);

                        bool shouldRunBasedOnAutodetect;
                        if (exists)
                        {
                            var bytes = await ioManager.ReadAllBytes(userConfigFileName, cancellationToken).ConfigureAwait(false);

                            var contents = Encoding.UTF8.GetString(bytes);
                            var existingConfigIsEmpty = String.IsNullOrWhiteSpace(contents) || contents.Trim() == "{}";
                            shouldRunBasedOnAutodetect = existingConfigIsEmpty;
                        }
                        else
                        {
                            shouldRunBasedOnAutodetect = true;
                        }

                        if (!shouldRunBasedOnAutodetect)
                        {
                            if (forceRun)
                            {
                                await console.WriteAsync(String.Format(CultureInfo.InvariantCulture, "The configuration settings are requesting the setup wizard be run, but you already appear to have a configuration file ({0})!", userConfigFileName), true, cancellationToken).ConfigureAwait(false);

                                forceRun = await PromptYesNo("Continue running setup wizard? (y/n): ", cancellationToken).ConfigureAwait(false);
                            }

                            if (!forceRun)
                            {
                                return;
                            }
                        }

                        // flush the logs to prevent console conflicts
                        await asyncDelayer.Delay(TimeSpan.FromSeconds(1), cancellationToken).ConfigureAwait(false);

                        await RunWizard(userConfigFileName, cancellationToken).ConfigureAwait(false);
                    }
                    finally
                    {
                        await finalTask.ConfigureAwait(false);
                    }
        }
Ejemplo n.º 10
0
        /// <inheritdoc />
        public async Task StartAsync(CancellationToken cancellationToken)
        {
            async Task <byte[]> GetActiveVersion()
            {
                var activeVersionFileExists = await ioManager.FileExists(ActiveVersionFileName, cancellationToken).ConfigureAwait(false);

                return(!activeVersionFileExists ? null : await ioManager.ReadAllBytes(ActiveVersionFileName, cancellationToken).ConfigureAwait(false));
            }

            var activeVersionBytesTask = GetActiveVersion();

            await ioManager.CreateDirectory(".", cancellationToken).ConfigureAwait(false);

            var directories = await ioManager.GetDirectories(".", cancellationToken).ConfigureAwait(false);

            async Task ReadVersion(string path)
            {
                var versionFile = ioManager.ConcatPath(path, VersionFileName);

                if (!await ioManager.FileExists(versionFile, cancellationToken).ConfigureAwait(false))
                {
                    logger.LogInformation("Cleaning unparsable version path: {0}", ioManager.ResolvePath(path));
                    await ioManager.DeleteDirectory(path, cancellationToken).ConfigureAwait(false);                     // cleanup

                    return;
                }

                var bytes = await ioManager.ReadAllBytes(versionFile, cancellationToken).ConfigureAwait(false);

                var text = Encoding.UTF8.GetString(bytes);

                if (Version.TryParse(text, out var version))
                {
                    var key = VersionKey(version);
                    lock (installedVersions)
                        if (!installedVersions.ContainsKey(key))
                        {
                            installedVersions.Add(key, Task.CompletedTask);
                            return;
                        }
                }

                await ioManager.DeleteDirectory(path, cancellationToken).ConfigureAwait(false);
            }

            await Task.WhenAll(directories.Select(x => ReadVersion(x))).ConfigureAwait(false);

            var activeVersionBytes = await activeVersionBytesTask.ConfigureAwait(false);

            if (activeVersionBytes != null)
            {
                var activeVersionString = Encoding.UTF8.GetString(activeVersionBytes);
                if (Version.TryParse(activeVersionString, out var activeVersion))
                {
                    ActiveVersion = activeVersion;
                }
                else
                {
                    await ioManager.DeleteFile(ActiveVersionFileName, cancellationToken).ConfigureAwait(false);
                }
            }
        }