using Newtonsoft.Json; using Org.BouncyCastle.Crypto; using Org.BouncyCastle.Crypto.IO; using Org.BouncyCastle.Crypto.Parameters; using Org.BouncyCastle.Security; using Publisher.Models; using Publisher.Models.Confluence; using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.IO; using System.Linq; using System.Security.Cryptography; using System.Text; using System.Threading; using System.Threading.Tasks; using System.Windows.Forms; namespace Publisher { public partial class Main : Form { private delegate void UpdateOutputStatusDelegate(string message); private static string MemoryMasterKey = "!ZEqy2Zsb#VK6<8`H6;W~VxJ$r:w.{ffzwDt=(json); } } catch (Exception ex) { MessageBox.Show(ex.Message); } } if(config != null) { if(config.Inside != null) { txtServiceInsideProjectFile.Text = config.Inside.Path; cbxServiceInsideAutoIncrement.CheckState = (config.Inside.VersionAutoIncrement ? CheckState.Checked : CheckState.Unchecked); config.Inside.OnUpdateStatus += Service_OnUpdateStatus; } if (config.Outside != null) { txtServiceOutsideProjectFile.Text = config.Outside.Path; cbxServiceOutsideAutoIncrement.CheckState = (config.Outside.VersionAutoIncrement ? CheckState.Checked : CheckState.Unchecked); config.Outside.OnUpdateStatus += Service_OnUpdateStatus; } txtConfluenceURL.Text = config.ConfluenceUrl; txtConfluenceParentPageId.Text = config.ConfluenceParentPageId.ToString(); txtConfluenceUsername.Text = config.ConfluenceUsername; txtConfluencePassword.Text = Decrypt(config.ConfluencePassword); txtOutputDirectory.Text = config.OutputDirectory; txtOutputZipPassword.Text = Decrypt(config.ZipPassword); } } private void Service_OnUpdateStatus(object sender, StatusUpdateArgs e) { string line = (!string.IsNullOrEmpty(LogsText) ? LogsText : "") +DateTime.Now.ToString("dd.MM.yyyy HH:mm:ss") + "[" + e.Type + "]:" + e.Data + "\r\n"; LogsText = line; UpdateOutputStatus(line); } private void UpdateOutputStatus(string message) { if(lblStatus.InvokeRequired) { lblStatus.Invoke(new UpdateOutputStatusDelegate(UpdateOutputStatus), message); } else { lblStatus.Text = message; } } private void button1_Click(object sender, EventArgs e) { Logs logs = new Logs(LogsText); logs.ShowDialog(); } private void SaveConfig() { try { lblStatus.Text = ""; if (string.IsNullOrEmpty(txtOutputDirectory.Text)) { lblStatus.Text = "Please select the output directory"; } else if (string.IsNullOrEmpty(txtOutputZipPassword.Text)) { lblStatus.Text = "Please enter output zip file password"; } else if (string.IsNullOrEmpty(txtConfluenceURL.Text)) { lblStatus.Text = "Please enter a confluence url"; } else if (string.IsNullOrEmpty(txtConfluenceUsername.Text)) { lblStatus.Text = "Please enter a confluence username"; } else if (string.IsNullOrEmpty(txtConfluencePassword.Text)) { lblStatus.Text = "Please enter a confluence password"; } else if (string.IsNullOrEmpty(txtConfluenceParentPageId.Text)) { lblStatus.Text = "Please enter a confluence parent page id"; } else { if (config == null) { config = new Config(); } /** Confluence **/ config.ConfluenceUrl = txtConfluenceURL.Text; config.ConfluenceUsername = txtConfluenceUsername.Text; config.ConfluencePassword = Encrypt(txtConfluencePassword.Text); config.ConfluenceParentPageId = Convert.ToInt32(txtConfluenceParentPageId.Text); /** Output **/ config.OutputDirectory = txtOutputDirectory.Text; config.ZipPassword = Encrypt(txtOutputZipPassword.Text); /** Inside **/ if (!string.IsNullOrEmpty(txtServiceInsideProjectFile.Text)) { if (config.Inside == null) { config.Inside = new Project(); } config.Inside.Name = "ServiceInside"; config.Inside.Path = txtServiceInsideProjectFile.Text; config.Inside.Platform = Project.Platforms.NET_CORE; config.Inside.VersionAutoIncrement = cbxServiceInsideAutoIncrement.CheckState == CheckState.Checked; } /** Outside **/ if (!string.IsNullOrEmpty(txtServiceOutsideProjectFile.Text)) { if (config.Outside == null) { config.Outside = new Project(); } config.Outside.Name = "ServiceOutside"; config.Outside.Path = txtServiceOutsideProjectFile.Text; config.Outside.Platform = Project.Platforms.NET_CORE; config.Outside.VersionAutoIncrement = cbxServiceOutsideAutoIncrement.CheckState == CheckState.Checked; } string json = JsonConvert.SerializeObject(config); File.WriteAllText(ConfigPath, json); if (File.Exists(ConfigPath)) { lblStatus.Text = "Configuration has been successfully saved"; } } } catch (Exception ex) { MessageBox.Show(ex.Message); } } public static string Encrypt(string value) { string result = null; try { IBufferedCipher encCipher = CipherUtilities.GetCipher("AES/GCM/NoPadding"); byte[] keyBytes = GetKey(MemoryMasterKey); KeyParameter key = new KeyParameter(keyBytes); byte[] nonce = new byte[12]; RandomNumberGenerator.Create().GetBytes(nonce); encCipher.Init(true, new ParametersWithIV(key, nonce)); byte[] plainText = Encoding.UTF8.GetBytes(value); byte[] chiperBuffer = null; byte[] tag = new byte[16]; byte[] resultBuffer = null; using (MemoryStream memStream = new MemoryStream()) { using (CipherStream encStream = new CipherStream(memStream, null, encCipher)) { encStream.Write(plainText, 0, plainText.Length); } chiperBuffer = memStream.ToArray(); resultBuffer = nonce.Concat(chiperBuffer).ToArray(); } result = Convert.ToBase64String(resultBuffer); } catch { result = null; } return result; } public static string Decrypt(string value) { string result = null; try { IBufferedCipher decCipher = CipherUtilities.GetCipher("AES/GCM/NoPadding"); byte[] keyBytes = GetKey(MemoryMasterKey); KeyParameter key = new KeyParameter(keyBytes); byte[] combined = Convert.FromBase64String(value); byte[] tag = combined.Skip(combined.Length - 16).ToArray(); byte[] nonce = combined.Take(12).ToArray(); byte[] chiperText = combined.Skip(nonce.Length).Take(combined.Length - nonce.Length).ToArray(); byte[] plainTextBuffer = null; decCipher.Init(false, new ParametersWithIV(key, nonce)); using (MemoryStream memStream = new MemoryStream(chiperText, false)) { MemoryStream dataStream = new MemoryStream(); using (dataStream) { using (CipherStream decStream = new CipherStream(memStream, (IBufferedCipher)decCipher, null)) { int ch; while ((ch = decStream.ReadByte()) >= 0) { dataStream.WriteByte((byte)ch); } } } plainTextBuffer = dataStream.ToArray(); result = Encoding.UTF8.GetString(plainTextBuffer); } } catch { result = null; } return result; } public static byte[] GetKey(string password) { byte[] result = null; try { if (!string.IsNullOrEmpty(password)) { if (password.Length < 32) { password = password.PadRight(32, '@'); } else if (password.Length > 32) { password = MD5Encrypt(password); } result = Encoding.ASCII.GetBytes(password); } } catch (Exception ex) { } return result; } public static string MD5Encrypt(string value) { string result = null; try { byte[] bytes = Encoding.UTF8.GetBytes(value); using (System.Security.Cryptography.MD5 hash = System.Security.Cryptography.MD5.Create()) { byte[] hashedInputBytes = hash.ComputeHash(bytes); StringBuilder hashedInputStringBuilder = new StringBuilder(128); foreach (var b in hashedInputBytes) { hashedInputStringBuilder.Append(b.ToString("X2")); } result = hashedInputStringBuilder.ToString().ToLower(); } } catch { result = null; } return result; } private void button2_Click(object sender, EventArgs e) { FolderBrowserDialog folderBrowserDialog = new FolderBrowserDialog(); if(folderBrowserDialog.ShowDialog() == DialogResult.OK) { txtOutputDirectory.Text = folderBrowserDialog.SelectedPath; } } private void btnSelectServiceOutsideProjectFile_Click(object sender, EventArgs e) { OpenFileDialog openFileDialog = new OpenFileDialog(); openFileDialog.Filter = "Project File (*.csproj)|*.csproj"; if (openFileDialog.ShowDialog() == DialogResult.OK) { txtServiceOutsideProjectFile.Text = openFileDialog.FileName; } } private void btnSelectServiceInsideProjectFile_Click(object sender, EventArgs e) { OpenFileDialog openFileDialog = new OpenFileDialog(); openFileDialog.Filter = "Project File (*.csproj)|*.csproj"; if (openFileDialog.ShowDialog() == DialogResult.OK) { txtServiceInsideProjectFile.Text = openFileDialog.FileName; } } private void btnPublish_Click(object sender, EventArgs e) { LogsText = ""; if (this.config == null) { button1_Click(null, null); } if(this.config != null && !string.IsNullOrEmpty(this.config.ConfluenceUrl) && !string.IsNullOrEmpty(this.config.ConfluenceUsername) && !string.IsNullOrEmpty(this.config.ConfluencePassword) && this.config.ConfluenceParentPageId > 0 && !string.IsNullOrEmpty(this.config.OutputDirectory) && !string.IsNullOrEmpty(this.config.ZipPassword)) { string html = tinyMCE1.HtmlContent; Thread thread = new Thread(() => { UpdateOutputStatus("Publishing..."); string dotnet_exe = @"C:\Program Files\dotnet\dotnet.exe"; /** inside **/ string zipInside = null; if (cbxReleaseServiceInside.CheckState == CheckState.Checked) { UpdateOutputStatus("Create release package of ServiceInside..."); zipInside = this.config.Inside.Publish(dotnet_exe, this.config.OutputDirectory, Decrypt(this.config.ZipPassword)); } /** outside **/ string zipOutside = null; if (cbxReleaseServiceOutside.CheckState == CheckState.Checked) { UpdateOutputStatus("Create release package of ServiceOutside..."); zipOutside = this.config.Outside.Publish(dotnet_exe, this.config.OutputDirectory, Decrypt(this.config.ZipPassword)); } Services.Confluence confluence = new Services.Confluence(config.ConfluenceUrl, config.ConfluenceUsername, Decrypt(config.ConfluencePassword)); UpdateOutputStatus("Create confluence Release Page..."); string release = config.Outside.GetVersion(); html = html.Replace("[RELEASE]", release); string ts = DateTime.Now.ToString("dd.MM.yyyy HH:mm:ss"); html = html.Replace("[SERVICE_INSIDE]", config.Inside.Name); html = html.Replace("[SERVICE_INSIDE_VERSION]", config.Inside.GetVersion(false)); html = html.Replace("[SERVICE_INSIDE_PUBLISHED_ON]", ts); html = html.Replace("[SERVICE_OUTSIDE]", config.Outside.Name); html = html.Replace("[SERVICE_OUTSIDE_VERSION]", config.Outside.GetVersion(false)); html = html.Replace("[SERVICE_OUTSIDE_PUBLISHED_ON]", ts); html = html.Replace("[SERVICE_SUPPORT]", config.Support.Name); html = html.Replace("[SERVICE_SUPPORT_VERSION]", config.Support.GetVersion(false)); html = html.Replace("[SERVICE_SUPPORT_PUBLISHED_ON]", ts); /** delete old **/ confluence.DeleteOldChildPages(config.ConfluenceParentPageId, 4); ResponsePage res = confluence.CreatePage(release, "PB", html, config.ConfluenceParentPageId); ResponseAttachment res1 = null; ResponseAttachment res2 = null; ResponseAttachment res3 = null; if (res != null) { string downloadURL = config.ConfluenceUrl + "/download/attachments/" + res.id.ToString() + "/"; UpdateOutputStatus("Confluence page has been created (" + res.title + ", " + res.id + ")"); if (!string.IsNullOrEmpty(zipInside)) { UpdateOutputStatus("Upload ServiceInside to confluence (" + Path.GetFileName(zipInside) + ")"); res1 = confluence.AddAttachment(res.id, zipInside, "application/zip"); UpdateOutputStatus(Path.GetFileName(zipInside) + " has been successfully uploaded"); } if (!string.IsNullOrEmpty(zipOutside)) { UpdateOutputStatus("Upload ServiceOutside to confluence (" + Path.GetFileName(zipOutside) + ")"); res2 = confluence.AddAttachment(res.id, zipOutside, "application/zip"); UpdateOutputStatus(Path.GetFileName(zipOutside) + " has been successfully uploaded"); } /** Updates Links **/ if (res1 != null && !string.IsNullOrEmpty(res1.id) && !string.IsNullOrEmpty(res1.title)) { html = html.Replace("[SERVICE_INSIDE_LINK]", "Download"); } else { html = html.Replace("[SERVICE_INSIDE_LINK]", ""); } if (res2 != null && !string.IsNullOrEmpty(res2.id) && !string.IsNullOrEmpty(res2.title)) { html = html.Replace("[SERVICE_OUTSIDE_LINK]", "Download"); } else { html = html.Replace("[SERVICE_OUTSIDE_LINK]", ""); } if (res3 != null && !string.IsNullOrEmpty(res3.id) && !string.IsNullOrEmpty(res3.title)) { html = html.Replace("[SERVICE_SUPPORT_LINK]", "Download"); } else { html = html.Replace("[SERVICE_SUPPORT_LINK]", ""); } ResponsePage resUpdate = confluence.UpdatePage(release, "PB", res.id, html); if(resUpdate != null && !string.IsNullOrEmpty(resUpdate.id)) { UpdateOutputStatus(release + " has been successfully published"); } else { UpdateOutputStatus(release + " dwonload links could not be updated"); } } }); thread.Start(); } } private void Main_Load(object sender, EventArgs e) { tinyMCE1.CreateEditor(); } } }