using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Security.Authentication; using System.Text; using System.Text.RegularExpressions; using System.Threading.Tasks; using FluentFTP; using Microsoft.Azure.Management.AppService.Fluent; using Microsoft.Azure.Management.Fluent; namespace Tango.AzureUtils.FTP { public class FtpManager : AzureUtilsComponentBase { private IProgress _ftpDownloadProgress; private IProgress _ftpUploadProgress; private String _currentDownloadFile; public FtpManager(IAzure azure) : base(azure) { _ftpDownloadProgress = new Progress((p) => { OnProgress(AzureUtilsStage.FtpDownload, $"Downloading {_currentDownloadFile}...", p.Progress, 100, false); }); _ftpUploadProgress = new Progress((p) => { OnProgress(AzureUtilsStage.FtpUpload, $"Uploading {_currentDownloadFile}...", p.Progress, 100, false); }); } private FtpClient CreateFtpClient(String address, String userName, String password) { Uri uri = new Uri("ftp://" + address); string host = uri.Host; FtpClient client = new FtpClient(host, userName, password); //client.EncryptionMode = FtpEncryptionMode.Explicit; client.SslProtocols = SslProtocols.Tls; client.ValidateAnyCertificate = true; client.DataConnectionType = FtpDataConnectionType.PASV; client.DownloadDataType = FtpDataType.Binary; client.RetryAttempts = 5; client.SocketPollInterval = 1000; client.ConnectTimeout = 2000; client.ReadTimeout = 2000; client.DataConnectionConnectTimeout = 2000; client.DataConnectionReadTimeout = 2000; client.OnLogEvent = (ev, msg) => { if (msg.Contains("DownloadFileAsync") || msg.Contains("UploadFileAsync")) { var matches = Regex.Matches(msg, "(?<=\").+?(?=\")"); var match = matches.OfType().LastOrDefault(); if (match != null) { _currentDownloadFile = match.ToString(); } } }; return client; } public async Task> DownloadWebAppFiles(IWebAppBase app, String targetFolder) { OnProgress(AzureUtilsStage.FtpDownload, $"Downloading web app files for '{app.Name}'..."); var profile = await app.GetPublishingProfileAsync(); using (var ftp = CreateFtpClient(profile.FtpUrl, profile.FtpUsername, profile.FtpPassword)) { await ftp.ConnectAsync(); var downloadResults = await ftp.DownloadDirectoryAsync(targetFolder, "/site/wwwroot", progress: _ftpDownloadProgress); foreach (var downloadResult in downloadResults) { if (downloadResult.IsFailed) { throw downloadResult.Exception; } } return downloadResults; } } public async Task> UploadWebAppFiles(IWebAppBase app, String sourceFolder) { OnProgress(AzureUtilsStage.FtpUpload, $"Uploading web app files for '{app.Name}'..."); var profile = await app.GetPublishingProfileAsync(); using (var ftp = CreateFtpClient(profile.FtpUrl, profile.FtpUsername, profile.FtpPassword)) { var uploadResults = await ftp.UploadDirectoryAsync(sourceFolder, "/site/wwwroot", existsMode: FtpRemoteExists.Overwrite, progress: _ftpUploadProgress); foreach (var uploadResult in uploadResults) { if (uploadResult.IsFailed) { throw uploadResult.Exception; } } return uploadResults; } } public async Task CopyAppFiles(IWebAppBase sourceApp, IWebAppBase targetApp) { var webAppFilesTempFolder = TemporaryManager.CreateFolder(); var downloadResults = await DownloadWebAppFiles(sourceApp, webAppFilesTempFolder); var uploadResults = await UploadWebAppFiles(targetApp, webAppFilesTempFolder); } public async Task GetMachineServiceVersion(IWebAppBase app) { var exeTempFile = TemporaryManager.CreateImaginaryFile(".dll"); var profile = await app.GetPublishingProfileAsync(); using (var ftp = CreateFtpClient(profile.FtpUrl, profile.FtpUsername, profile.FtpPassword)) { await ftp.ConnectAsync(); await ftp.DownloadFileAsync(exeTempFile, "/site/wwwroot/bin/Tango.MachineService.dll"); String version = FileVersionInfo.GetVersionInfo(exeTempFile).ProductVersion; await exeTempFile.DeleteAsync(); return version; } } } }