/// <summary> /// 序列化为 XmlDocument /// </summary> /// <param name="value"></param> /// <param name="encoding"></param> /// <returns></returns> public string SerializeToXmlDocument(object value, Encoding encoding = null) { var doc = new XmlDocument(); var nav = doc.CreateNavigator(); // 写入 XmlDocument using (var xmlWriter = nav.AppendChild()) { this.SerializeToXml(xmlWriter, value); } //return doc.OuterXml; // 从 XmlDocument 写入 字符串 encoding = encoding ?? this.DefaultEncoding; using (var stringWriter = new StringWriterWithEncoding(encoding)) { var xmlWriterSettings = new XmlWriterSettings { Indent = true, IndentChars = "\t", Encoding = encoding }; using (var xmlTextWriter = XmlWriter.Create(stringWriter, xmlWriterSettings)) { doc.WriteTo(xmlTextWriter); xmlTextWriter.Flush(); return(stringWriter.GetStringBuilder().ToString()); } } }
private string ToString(bool inline) { var doc = new XmlDocument(); var xml = ToXml(doc); if (inline) { return(xml.First().OuterXml); } var writerSettings = new XmlWriterSettings() { ConformanceLevel = ConformanceLevel.Document, Indent = true }; using (var stringWriter = new StringWriterWithEncoding(Encoding.UTF8)) using (var xmlWriter = XmlWriter.Create(stringWriter, writerSettings)) { xmlWriter.WriteDocType("svg", "-//W3C/DTD SVG 1.1//EN", "http://www.w3c.org/Graphics/SVG/1.1/DTD/svg11.dtd", null); foreach (var node in xml) { node.WriteTo(xmlWriter); } xmlWriter.Flush(); return(stringWriter.GetStringBuilder().ToString()); } }
public string AsUTF8Xml(XmlDocument xdoc) { var sb = new StringBuilder(); using (var stringWriter = new StringWriterWithEncoding(sb, Encoding.UTF8)) using (var xmlTextWriter = XmlWriter.Create(stringWriter)) { xdoc.WriteTo(xmlTextWriter); xmlTextWriter.Flush(); return(stringWriter.GetStringBuilder().ToString()); } }
public async Task <string> GenerateFeed(IEnumerable <ReleaseViewModel> releases) { const string title = "Changelog Feed"; var id = new UniqueId(); var updated = DateTimeOffset.UtcNow; var sw = new StringWriterWithEncoding(Encoding.UTF8); using (var xmlWriter = XmlWriter.Create(sw, new XmlWriterSettings() { Async = true, Indent = true })) { var writer = new AtomFeedWriter(xmlWriter); await writer.WriteTitle(title); await writer.WriteId(id.ToString()); await writer.WriteUpdated(updated); foreach (var release in releases) { var item = new SyndicationItem() { Title = release.ReleaseVersion, Id = new UniqueId(release.ReleaseId).ToString(), LastUpdated = release.ReleaseDate }; release.Authors.ForEach(x => item.AddContributor(new SyndicationPerson(x, $"{x}@test.com")) ); var sb = new StringBuilder(); foreach (var workItemViewModel in release.WorkItems) { sb.Append(workItemViewModel.WorkItemTypeString) .Append(": ") .AppendLine(workItemViewModel.Description) ; } item.Description = sb.ToString(); await writer.Write(item); } xmlWriter.Flush(); } return(sw.GetStringBuilder().ToString()); }
/// <summary> /// Initializes a new instance of XmlResult class. /// </summary> /// <param name="data"></param> /// <param name="encoding"></param> /// <exception cref="System.ArgumentNullException"><paramref name="data"/> is null.</exception> public XmlResult(object data, Encoding encoding) { if (data == null) { throw new ArgumentNullException("data"); } using (StringWriter writer = new StringWriterWithEncoding(encoding = encoding ?? Encoding.UTF8)) { new XmlSerializer(data.GetType()).Serialize(writer, data); this.m_content = writer.GetStringBuilder().ToString(); } this.m_encoding = encoding; }
public static void SetEventData <T>(this AddressSyndicationItem syndicationItem, T message, string eventName) { var xmlElement = message.ToXml(eventName); using (var stringWriter = new StringWriterWithEncoding(Encoding.UTF8)) { using (var xmlWriter = new XmlTextWriter(stringWriter) { Formatting = Formatting.None }) xmlElement.WriteTo(xmlWriter); syndicationItem.EventDataAsXml = stringWriter.GetStringBuilder().ToString(); } }
string XmlToString(XmlDocument doc) { XmlWriterSettings settings = new XmlWriterSettings(); settings.Encoding = new UTF8Encoding(false); settings.ConformanceLevel = ConformanceLevel.Document; settings.Indent = true; var sb = new StringBuilder(); using (var stringWriter = new StringWriterWithEncoding(sb, Encoding.UTF8)) using (var xmlTextWriter = XmlWriter.Create(stringWriter, settings)) { doc.WriteTo(xmlTextWriter); xmlTextWriter.Flush(); return(stringWriter.GetStringBuilder().ToString()); } }
public static string Serialize(CommandModel model) { var settings = new XmlWriterSettings { Indent = true, IndentChars = " ", NewLineChars = "\n", OmitXmlDeclaration = false, Encoding = Encoding.UTF8, }; using (var buffer = new StringWriterWithEncoding(Encoding.UTF8)) using (var xmlWriter = XmlWriter.Create(buffer, settings)) { SerializeModel(model).WriteTo(xmlWriter); xmlWriter.Flush(); return(buffer.GetStringBuilder().ToString()); } }
public async Task <string> WriteRssAsync() { var feed = GetItemCollection(FeedItemCollection); var settings = new XmlWriterSettings { Async = true }; var sw = new StringWriterWithEncoding(Encoding.UTF8); await using var xmlWriter = XmlWriter.Create(sw, settings); var writer = new RssFeedWriter(xmlWriter); await writer.WriteTitle(HeadTitle); await writer.WriteDescription(HeadDescription); await writer.Write(new SyndicationLink(new(TrackBackUrl))); await writer.WritePubDate(DateTimeOffset.UtcNow); await writer.WriteCopyright(Copyright); await writer.WriteGenerator(Generator); foreach (var item in feed) { await writer.Write(item); } await xmlWriter.FlushAsync(); xmlWriter.Close(); await sw.FlushAsync(); sw.GetStringBuilder(); var xml = sw.ToString(); return(xml); }
public async Task <string> WriteAtomAsync() { var feed = GetItemCollection(FeedItemCollection); var settings = new XmlWriterSettings { Async = true }; var sw = new StringWriterWithEncoding(Encoding.UTF8); await using var xmlWriter = XmlWriter.Create(sw, settings); var writer = new AtomFeedWriter(xmlWriter); await writer.WriteTitle(HeadTitle); await writer.WriteSubtitle(HeadDescription); await writer.WriteRights(Copyright); await writer.WriteUpdated(DateTime.UtcNow); await writer.WriteGenerator(Generator, HostUrl, GeneratorVersion); foreach (var item in feed) { await writer.Write(item); } await xmlWriter.FlushAsync(); xmlWriter.Close(); await sw.FlushAsync(); sw.GetStringBuilder(); var xml = sw.ToString(); return(xml); }
public static string Build(IEnumerable<LabelInfo> labels) { using (var writer = new StringWriterWithEncoding(Encoding.Default)) { foreach(var labelInfo in labels) { writer.WriteLine(string.Format("{0}\t{1}}\t{2}\t{3}\t{4}\t{5}\t{6}\t{7}\t{8}", labelInfo.FirstName , labelInfo.LastName , labelInfo.CorpName, labelInfo.Address, labelInfo.PostalCode , labelInfo.City, labelInfo.State , labelInfo.IsoCountryCode , labelInfo)); } } var content = writer.GetStringBuilder().ToString(); return content; }
/// <summary> /// To the XML string. /// </summary> /// <param name="cv">The cv.</param> /// <returns></returns> public static string ToXmlString(Model.SkillsPassport cv) { XmlDocument xml = new XmlDocument(); using (XmlWriter writer = xml.CreateNavigator().AppendChild()) { new XmlSerializer(cv.GetType()).Serialize(writer, cv); } var settings = new XmlWriterSettings { Encoding = new UnicodeEncoding(false, false), Indent = true, OmitXmlDeclaration = false }; using (var stringWriter = new StringWriterWithEncoding(Encoding.UTF8)) using (var xmlTextWriter = XmlWriter.Create(stringWriter, settings)) { xml.WriteTo(xmlTextWriter); xmlTextWriter.Flush(); return(stringWriter.GetStringBuilder().ToString()); } }
private string OrderToXml(Order order) { var doc = new XmlDocument(); XmlElement el = (XmlElement)doc.AppendChild(doc.CreateElement("OrderXML")); var methodNode = doc.CreateElement("Method"); methodNode.InnerText = "SEND ORDER"; el.AppendChild(methodNode); var usernameNode = doc.CreateElement("Username"); usernameNode.InnerText = this.Username; var passwordNode = doc.CreateElement("Password"); passwordNode.InnerText = this.Password; var authenticationNode = doc.CreateElement("Authentication"); authenticationNode.AppendChild(usernameNode); authenticationNode.AppendChild(passwordNode); el.AppendChild(authenticationNode); if (this.IsTesting) { var testingNode = doc.CreateElement("TestMode"); testingNode.InnerText = this.IsTesting ? "YES" : "NO"; el.AppendChild(testingNode); } var returnResultURLNode = doc.CreateElement("ReturnResultURL"); returnResultURLNode.InnerText = order.ReturnResultUrl; el.AppendChild(returnResultURLNode); var orderNode = doc.CreateElement("Order"); var billingReferenceCodeNode = doc.CreateElement("BillingReferenceCode"); billingReferenceCodeNode.InnerText = order.BillingReference; orderNode.AppendChild(billingReferenceCodeNode); var subjectNode = order.OrderSubject.ToXml(doc); orderNode.AppendChild(subjectNode); var packageServiceCodeNode = doc.CreateElement("PackageServiceCode"); packageServiceCodeNode.InnerText = order.PackageServiceCode; packageServiceCodeNode.SetAttribute("orderid", order.ID); orderNode.AppendChild(packageServiceCodeNode); foreach (var orderDetail in order.OrderDetails) { var orderDetailNode = orderDetail.ToXml(doc, order.ID); orderNode.AppendChild(orderDetailNode); } el.AppendChild(orderNode); using (var stringWriter = new StringWriterWithEncoding(Encoding.UTF8)) using (var xmlTextWriter = XmlWriter.Create(stringWriter)) { doc.WriteTo(xmlTextWriter); xmlTextWriter.Flush(); return(stringWriter.GetStringBuilder().ToString()); } }
private static void UpdateServiceDefinition(IVsTextLines lines, string roleType, string projectName) { if (lines == null) { throw new ArgumentException("lines"); } int lastLine, lastIndex; string text; ErrorHandler.ThrowOnFailure(lines.GetLastLineIndex(out lastLine, out lastIndex)); ErrorHandler.ThrowOnFailure(lines.GetLineText(0, 0, lastLine, lastIndex, out text)); var doc = new XmlDocument(); doc.LoadXml(text); UpdateServiceDefinition(doc, roleType, projectName); var encoding = Encoding.UTF8; var userData = lines as IVsUserData; if (userData != null) { var guid = VSConstants.VsTextBufferUserDataGuid.VsBufferEncodingVSTFF_guid; object data; int cp; if (ErrorHandler.Succeeded(userData.GetData(ref guid, out data)) && (cp = (data as int? ?? (int)(data as uint? ?? 0)) & (int)__VSTFF.VSTFF_CPMASK) != 0) { try { encoding = Encoding.GetEncoding(cp); } catch (NotSupportedException) { } catch (ArgumentException) { } } } var sw = new StringWriterWithEncoding(encoding); doc.Save(XmlWriter.Create( sw, new XmlWriterSettings { Indent = true, IndentChars = " ", NewLineHandling = NewLineHandling.Entitize, Encoding = encoding } )); var sb = sw.GetStringBuilder(); var len = sb.Length; var pStr = Marshal.StringToCoTaskMemUni(sb.ToString()); try { ErrorHandler.ThrowOnFailure(lines.ReplaceLines(0, 0, lastLine, lastIndex, pStr, len, new TextSpan[1])); } finally { Marshal.FreeCoTaskMem(pStr); } }
/// <inheritdoc /> public override void LinkFiles(TaskGraph graph, BuildOptions options, string outputFilePath) { var linkEnvironment = options.LinkEnv; var task = graph.Add <LinkTask>(); // Setup arguments var args = new List <string>(); SetupLinkFilesArgs(graph, options, args); { // Suppress startup banner args.Add("/NOLOGO"); // Report internal compiler errors args.Add("/ERRORREPORT:PROMPT"); // Output File Name args.Add(string.Format("/OUT:\"{0}\"", outputFilePath)); // Specify target platform switch (Architecture) { case TargetArchitecture.x86: args.Add("/MACHINE:x86"); break; case TargetArchitecture.x64: args.Add("/MACHINE:x64"); break; case TargetArchitecture.ARM: case TargetArchitecture.ARM64: args.Add("/MACHINE:ARM"); break; default: throw new InvalidArchitectureException(Architecture); } // Specify subsystem args.Add("/SUBSYSTEM:WINDOWS"); // Generate Windows Metadata if (linkEnvironment.GenerateWindowsMetadata) { args.Add("/WINMD"); args.Add(string.Format("/WINMDFILE:\"{0}\"", Path.ChangeExtension(outputFilePath, "winmd"))); args.Add("/APPCONTAINER"); if (linkEnvironment.Output == LinkerOutput.SharedLibrary) { args.Add("/DYNAMICBASE"); } } if (linkEnvironment.LinkTimeCodeGeneration) { // Link-time code generation args.Add("/LTCG"); } if (linkEnvironment.Output == LinkerOutput.ImportLibrary) { // Create an import library args.Add("/DEF"); // Ignore libraries args.Add("/NODEFAULTLIB"); // Specify the name args.Add(string.Format("/NAME:\"{0}\"", Path.GetFileNameWithoutExtension(outputFilePath))); // Ignore warnings about files with no public symbols args.Add("/IGNORE:4221"); } else { // Don't create Side-by-Side Assembly Manifest args.Add("/MANIFEST:NO"); // Fixed Base Address args.Add("/FIXED:NO"); if (Architecture == TargetArchitecture.x86) { // Handle Large Addresses args.Add("/LARGEADDRESSAWARE"); } // Compatible with Data Execution Prevention args.Add("/NXCOMPAT"); // Allow delay-loaded DLLs to be explicitly unloaded args.Add("/DELAY:UNLOAD"); if (linkEnvironment.Output == LinkerOutput.SharedLibrary) { // Build a DLL args.Add("/DLL"); } // Redirect imports LIB file auto-generated for EXE/DLL var libFile = Path.ChangeExtension(outputFilePath, Platform.StaticLibraryFileExtension); args.Add("/IMPLIB:\"" + libFile + "\""); task.ProducedFiles.Add(libFile); // Don't embed the full PDB path args.Add("/PDBALTPATH:%_PDB%"); // Optimize if (linkEnvironment.Optimization && !linkEnvironment.UseIncrementalLinking) { // Generate an EXE checksum args.Add("/RELEASE"); // Eliminate unreferenced symbols args.Add("/OPT:REF"); // Remove redundant COMDATs args.Add("/OPT:ICF"); } else { // Keep symbols that are unreferenced args.Add("/OPT:NOREF"); // Disable identical COMDAT folding args.Add("/OPT:NOICF"); } // Link Incrementally if (linkEnvironment.UseIncrementalLinking) { args.Add("/INCREMENTAL"); } else { args.Add("/INCREMENTAL:NO"); } if (linkEnvironment.DebugInformation) { // Generate debug information if (Toolset != WindowsPlatformToolset.v140 && linkEnvironment.UseFastPDBLinking) { args.Add("/DEBUG:FASTLINK"); } else if (linkEnvironment.UseFullDebugInformation) { args.Add("/DEBUG:FULL"); } else { args.Add("/DEBUG"); } // Use Program Database var pdbFile = Path.ChangeExtension(outputFilePath, Platform.ProgramDatabaseFileExtension); args.Add(string.Format("/PDB:\"{0}\"", pdbFile)); task.ProducedFiles.Add(pdbFile); } } } // Delay-load DLLs if (linkEnvironment.Output == LinkerOutput.Executable || linkEnvironment.Output == LinkerOutput.SharedLibrary) { foreach (var dll in options.DelayLoadLibraries) { args.Add(string.Format("/DELAYLOAD:\"{0}\"", dll)); } } // Additional lib paths foreach (var libpath in linkEnvironment.LibraryPaths) { args.Add(string.Format("/LIBPATH:\"{0}\"", libpath)); } // Input libraries task.PrerequisiteFiles.AddRange(linkEnvironment.InputLibraries); foreach (var library in linkEnvironment.InputLibraries) { args.Add(string.Format("\"{0}\"", library)); } // Input files task.PrerequisiteFiles.AddRange(linkEnvironment.InputFiles); foreach (var file in linkEnvironment.InputFiles) { args.Add(string.Format("\"{0}\"", file)); } // Use a response file (it can contain any commands that you would specify on the command line) bool useResponseFile = true; string responseFile = null; if (useResponseFile) { responseFile = Path.Combine(options.IntermediateFolder, Path.GetFileName(outputFilePath) + ".response"); task.PrerequisiteFiles.Add(responseFile); Utilities.WriteFileIfChanged(responseFile, string.Join(Environment.NewLine, args)); } // Link task.WorkingDirectory = options.WorkingDirectory; task.CommandPath = linkEnvironment.Output == LinkerOutput.ImportLibrary ? _libToolPath : _linkerPath; task.CommandArguments = useResponseFile ? string.Format("@\"{0}\"", responseFile) : string.Join(" ", args); if (linkEnvironment.Output == LinkerOutput.ImportLibrary) { task.InfoMessage = "Building import library " + outputFilePath; } else { task.InfoMessage = "Linking " + outputFilePath; } task.Cost = task.PrerequisiteFiles.Count; task.ProducedFiles.Add(outputFilePath); // Check if need to generate documentation if (linkEnvironment.GenerateDocumentation) { args.Clear(); var docTask = graph.Add <Task>(); // Use old input format args.Add("/old"); args.Add(string.Format("\"{0}\"", Path.GetFileNameWithoutExtension(outputFilePath))); // Suppress copyright message args.Add("/nologo"); // Output file var outputDocFile = Path.ChangeExtension(outputFilePath, "xml"); docTask.ProducedFiles.Add(outputDocFile); args.Add(string.Format("/Fo\"{0}\"", outputDocFile)); // Input files docTask.PrerequisiteFiles.AddRange(linkEnvironment.DocumentationFiles); foreach (var file in linkEnvironment.DocumentationFiles) { args.Add(string.Format("/Fs\"{0}\"", file)); } // Generate docs docTask.WorkingDirectory = options.WorkingDirectory; docTask.CommandPath = _xdcmakePath; docTask.CommandArguments = string.Join(" ", args); docTask.Cost = linkEnvironment.DocumentationFiles.Count; } // Check if need to generate metadata file if (linkEnvironment.GenerateWindowsMetadata) { var configFile = Path.Combine(options.IntermediateFolder, Path.GetFileNameWithoutExtension(outputFilePath) + ".priconfig.xml"); var manifestFile = Path.Combine(options.IntermediateFolder, Path.GetFileNameWithoutExtension(outputFilePath) + ".AppxManifest.xml"); var priFile = Path.ChangeExtension(outputFilePath, "pri"); // Generate pri config file var priConfigTask = graph.Add <Task>(); priConfigTask.WorkingDirectory = options.WorkingDirectory; priConfigTask.CommandPath = _makepriPath; priConfigTask.CommandArguments = string.Format("createconfig /cf \"{0}\" /dq en-US /o", configFile); priConfigTask.Cost = 1; priConfigTask.ProducedFiles.Add(configFile); // Create AppxManifest file { using (var stringWriter = new StringWriterWithEncoding(Encoding.UTF8)) using (var xmlTextWriter = XmlWriter.Create(stringWriter, new XmlWriterSettings { Encoding = Encoding.UTF8, Indent = true, })) { xmlTextWriter.WriteStartDocument(); // Package { xmlTextWriter.WriteStartElement("Package", "http://schemas.microsoft.com/appx/2010/manifest"); // Identity { xmlTextWriter.WriteStartElement("Identity"); xmlTextWriter.WriteAttributeString("Name", "FlaxGame"); xmlTextWriter.WriteAttributeString("Publisher", "CN=Flax, O=Flax, C=Poland"); xmlTextWriter.WriteAttributeString("Version", "1.0.0.0"); // TODO: get Flax version number switch (Architecture) { case TargetArchitecture.AnyCPU: xmlTextWriter.WriteAttributeString("ProcessorArchitecture", "neutral"); break; case TargetArchitecture.x86: xmlTextWriter.WriteAttributeString("ProcessorArchitecture", "x86"); break; case TargetArchitecture.x64: xmlTextWriter.WriteAttributeString("ProcessorArchitecture", "x64"); break; case TargetArchitecture.ARM: case TargetArchitecture.ARM64: xmlTextWriter.WriteAttributeString("ProcessorArchitecture", "arm"); break; default: throw new InvalidArchitectureException(Architecture); } xmlTextWriter.WriteEndElement(); } // Properties { xmlTextWriter.WriteStartElement("Properties"); // TODO: better logo handling var logoSrcPath = Path.Combine(Globals.EngineRoot, "Source", "Logo.png"); var logoDstPath = Path.Combine(options.IntermediateFolder, "Logo.png"); if (!File.Exists(logoDstPath)) { Utilities.FileCopy(logoSrcPath, logoDstPath); } xmlTextWriter.WriteElementString("DisplayName", "FlaxGame"); xmlTextWriter.WriteElementString("PublisherDisplayName", "Flax"); xmlTextWriter.WriteElementString("Logo", "Logo.png"); xmlTextWriter.WriteEndElement(); } // Resources { xmlTextWriter.WriteStartElement("Resources"); xmlTextWriter.WriteStartElement("Resource"); xmlTextWriter.WriteAttributeString("Language", "en-us"); xmlTextWriter.WriteEndElement(); xmlTextWriter.WriteEndElement(); } // Prerequisites { xmlTextWriter.WriteStartElement("Prerequisites"); xmlTextWriter.WriteElementString("OSMinVersion", "6.2"); xmlTextWriter.WriteElementString("OSMaxVersionTested", "6.2"); xmlTextWriter.WriteEndElement(); } } xmlTextWriter.WriteEndDocument(); xmlTextWriter.Flush(); // Save manifest to file var contents = stringWriter.GetStringBuilder().ToString(); Utilities.WriteFileIfChanged(manifestFile, contents); } } var dummyWorkspace = Path.Combine(options.IntermediateFolder, "Dummy"); if (!Directory.Exists(dummyWorkspace)) { Directory.CreateDirectory(dummyWorkspace); } // Generate pri file var priNewFile = graph.Add <Task>(); priNewFile.WorkingDirectory = options.WorkingDirectory; priNewFile.CommandPath = _makepriPath; priNewFile.CommandArguments = string.Format("new /cf \"{0}\" /pr \"{1}\" /of \"{2}\" /mn \"{3}\" /o", configFile, dummyWorkspace, priFile, manifestFile); priNewFile.Cost = 1; priNewFile.PrerequisiteFiles.Add(configFile); priNewFile.ProducedFiles.Add(priFile); } }
private UploadModResult UploadMod(Action <double> progressCallback = null, Action <TaskbarItemProgressState> setTaskbarProgressState = null) { #region online fetch //Fetch current production manifest for mod (it may not exist) setTaskbarProgressState?.Invoke(TaskbarItemProgressState.Indeterminate); using var wc = new System.Net.WebClient(); try { CurrentActionText = M3L.GetString(M3L.string_checkingIfUpdaterServiceIsConfiguredForMod); string validationUrl = $@"{UpdaterServiceCodeValidationEndpoint}?updatecode={mod.ModClassicUpdateCode}&updatexmlname={mod.UpdaterServiceServerFolderShortname}.xml"; string isBeingServed = wc.DownloadStringAwareOfEncoding(validationUrl); if (string.IsNullOrWhiteSpace(isBeingServed) || isBeingServed != @"true") //we don't parse for bool because it might have a different text that is not specifically true or false. It might // have an error for example { //Not being served Log.Error(@"This mod is not configured for serving on the Updater Service. Please contact Mgamerz."); CurrentActionText = M3L.GetString(M3L.string_serverNotConfiguredForModContactMgamerz); HideChangelogArea(); return(UploadModResult.NOT_BEING_SERVED); } } catch (Exception ex) { Log.Error(@"Error validating mod is configured on updater service: " + ex.Message); CurrentActionText = M3L.GetString(M3L.string_interp_errorCheckingUpdaterServiceConfiguration, ex.Message); HideChangelogArea(); return(UploadModResult.ERROR_VALIDATING_MOD_IS_CONFIGURED); } #endregion #region get current production version to see if we should prompt user var latestVersionOnServer = OnlineContent.GetLatestVersionOfModOnUpdaterService(mod.ModClassicUpdateCode); if (latestVersionOnServer != null) { if (latestVersionOnServer >= mod.ParsedModVersion) { bool cancel = false; setTaskbarProgressState?.Invoke(TaskbarItemProgressState.Paused); Application.Current.Dispatcher.Invoke(delegate { // server is newer or same as version we are pushing var response = M3L.ShowDialog(mainwindow, M3L.GetString(M3L.string_interp_dialog_serverVersionSameOrNewerThanLocal, mod.ParsedModVersion, latestVersionOnServer), M3L.GetString(M3L.string_serverVersionSameOrNewerThanLocal), MessageBoxButton.YesNo, MessageBoxImage.Warning); if (response == MessageBoxResult.No) { CurrentActionText = M3L.GetString(M3L.string_uploadAbortedModOnServerIsSameOrNewerThanLocalOneBeingUploaded); HideChangelogArea(); cancel = true; return; } }); setTaskbarProgressState?.Invoke(TaskbarItemProgressState.Indeterminate); if (cancel) { return(UploadModResult.ABORTED_BY_USER_SAME_VERSION_UPLOADED); } } } #endregion #region mod variables //get refs var files = mod.GetAllRelativeReferences(true); files = files.OrderByDescending(x => new FileInfo(Path.Combine(mod.ModPath, x)).Length).ToList(); long totalModSizeUncompressed = files.Sum(x => new FileInfo(Path.Combine(mod.ModPath, x)).Length); #endregion #region compress and stage mod void updateCurrentTextCallback(string newText) { CurrentActionText = newText; } bool?canceledCheckCallback() => CancelOperations; CurrentActionText = M3L.GetString(M3L.string_compressingModForUpdaterService); progressCallback?.Invoke(0); setTaskbarProgressState?.Invoke(TaskbarItemProgressState.Normal); var lzmaStagingPath = OnlineContent.StageModForUploadToUpdaterService(mod, files, totalModSizeUncompressed, canceledCheckCallback, updateCurrentTextCallback, progressCallback); #endregion if (CancelOperations) { AbortUpload(); return(UploadModResult.ABORTED_BY_USER); } setTaskbarProgressState?.Invoke(TaskbarItemProgressState.Indeterminate); #region hash mod and build server manifest CurrentActionText = M3L.GetString(M3L.string_buildingServerManifest); long amountHashed = 0; ConcurrentDictionary <string, SourceFile> manifestFiles = new ConcurrentDictionary <string, SourceFile>(); Parallel.ForEach(files, new ParallelOptions() { MaxDegreeOfParallelism = Math.Max(1, Environment.ProcessorCount - 1) }, x => { if (CancelOperations) { return; } SourceFile sf = new SourceFile(); var sFile = Path.Combine(mod.ModPath, x); var lFile = Path.Combine(lzmaStagingPath, x + @".lzma"); sf.hash = Utilities.CalculateMD5(sFile); sf.lzmahash = Utilities.CalculateMD5(lFile); var fileInfo = new FileInfo(sFile); sf.size = fileInfo.Length; sf.timestamp = fileInfo.LastWriteTimeUtc.Ticks; sf.relativefilepath = x; sf.lzmasize = new FileInfo(lFile).Length; manifestFiles.TryAdd(x, sf); var done = Interlocked.Add(ref amountHashed, sf.size); CurrentActionText = M3L.GetString(M3L.string_buildingServerManifest) + $@" {Math.Round(done * 100.0 / totalModSizeUncompressed)}%"; }); if (CancelOperations) { AbortUpload(); return(UploadModResult.ABORTED_BY_USER); } //Build document XmlDocument xmlDoc = new XmlDocument(); XmlNode rootNode = xmlDoc.CreateElement(@"mod"); xmlDoc.AppendChild(rootNode); foreach (var mf in manifestFiles) { if (CancelOperations) { AbortUpload(); return(UploadModResult.ABORTED_BY_USER); } XmlNode sourceNode = xmlDoc.CreateElement(@"sourcefile"); var size = xmlDoc.CreateAttribute(@"size"); size.InnerText = mf.Value.size.ToString(); var hash = xmlDoc.CreateAttribute(@"hash"); hash.InnerText = mf.Value.hash; var lzmasize = xmlDoc.CreateAttribute(@"lzmasize"); lzmasize.InnerText = mf.Value.lzmasize.ToString(); var lzmahash = xmlDoc.CreateAttribute(@"lzmahash"); lzmahash.InnerText = mf.Value.lzmahash; var timestamp = xmlDoc.CreateAttribute(@"timestamp"); timestamp.InnerText = mf.Value.timestamp.ToString(); sourceNode.InnerText = mf.Key; sourceNode.Attributes.Append(size); sourceNode.Attributes.Append(hash); sourceNode.Attributes.Append(lzmasize); sourceNode.Attributes.Append(lzmahash); sourceNode.Attributes.Append(timestamp); rootNode.AppendChild(sourceNode); } if (CancelOperations) { AbortUpload(); return(UploadModResult.ABORTED_BY_USER); } foreach (var bf in mod.UpdaterServiceBlacklistedFiles) { if (CancelOperations) { AbortUpload(); return(UploadModResult.ABORTED_BY_USER); } var bfn = xmlDoc.CreateElement(@"blacklistedfile"); bfn.InnerText = bf; rootNode.AppendChild(bfn); } if (CancelOperations) { AbortUpload(); return(UploadModResult.ABORTED_BY_USER); } var updatecode = xmlDoc.CreateAttribute(@"updatecode"); updatecode.InnerText = mod.ModClassicUpdateCode.ToString(); rootNode.Attributes.Append(updatecode); var version = xmlDoc.CreateAttribute(@"version"); version.InnerText = mod.ParsedModVersion.ToString(); rootNode.Attributes.Append(version); var serverfolder = xmlDoc.CreateAttribute(@"folder"); serverfolder.InnerText = mod.UpdaterServiceServerFolder; rootNode.Attributes.Append(serverfolder); setTaskbarProgressState?.Invoke(TaskbarItemProgressState.Indeterminate); #endregion //wait to ensure changelog is set. while (ChangelogNotYetSet) { setTaskbarProgressState?.Invoke(TaskbarItemProgressState.Paused); if (CancelOperations) { AbortUpload(); return(UploadModResult.ABORTED_BY_USER); } CurrentActionText = M3L.GetString(M3L.string_waitingForChangelogToBeSet); Thread.Sleep(250); //wait for changelog to be set. } setTaskbarProgressState?.Invoke(TaskbarItemProgressState.Indeterminate); #region Finish building manifest var changelog = xmlDoc.CreateAttribute(@"changelog"); changelog.InnerText = ChangelogText; rootNode.Attributes.Append(changelog); using var stringWriter = new StringWriterWithEncoding(Encoding.UTF8); XmlWriterSettings settings = new XmlWriterSettings(); settings.Indent = true; settings.IndentChars = @" "; settings.Encoding = Encoding.UTF8; using var xmlTextWriter = XmlWriter.Create(stringWriter, settings); xmlDoc.WriteTo(xmlTextWriter); xmlTextWriter.Flush(); #endregion var finalManifestText = stringWriter.GetStringBuilder().ToString(); #region Connect to ME3Tweaks CurrentActionText = M3L.GetString(M3L.string_connectingToME3TweaksUpdaterService); Log.Information(@"Connecting to ME3Tweaks as " + Username); string host = @"ftp.me3tweaks.com"; string username = Username; string password = Settings.DecryptUpdaterServicePassword(); using SftpClient sftp = new SftpClient(host, username, password); sftp.Connect(); Log.Information(@"Connected to ME3Tweaks over SSH (SFTP)"); CurrentActionText = M3L.GetString(M3L.string_connectedToME3TweaksUpdaterService); var serverFolderName = mod.UpdaterServiceServerFolderShortname; //sftp.ChangeDirectory(LZMAStoragePath); //Log.Information(@"Listing files/folders for " + LZMAStoragePath); //var lzmaStorageDirectoryItems = sftp.ListDirectory(LZMAStoragePath); var serverModPath = LZMAStoragePath + @"/" + serverFolderName; bool justMadeFolder = false; if (!sftp.Exists(serverModPath)) { CurrentActionText = M3L.GetString(M3L.string_creatingServerFolderForMod); Log.Information(@"Creating server folder for mod: " + serverModPath); sftp.CreateDirectory(serverModPath); justMadeFolder = true; } var dirContents = sftp.ListDirectory(serverModPath).ToList(); Dictionary <string, string> serverHashes = new Dictionary <string, string>(); //Open SSH connection as we will need to hash files out afterwards. Log.Information(@"Connecting to ME3Tweaks Updater Service over SSH (SSH Shell)"); using SshClient sshClient = new SshClient(host, username, password); sshClient.Connect(); Log.Information(@"Connected to ME3Tweaks Updater Service over SSH (SSH Shell)"); if (!justMadeFolder && dirContents.Any(x => x.Name != @"." && x.Name != @"..")) { CurrentActionText = M3L.GetString(M3L.string_hashingFilesOnServerForDelta); Log.Information(@"Hashing existing files on server to compare for delta"); serverHashes = getServerHashes(sshClient, serverFolderName, serverModPath); } //Calculate what needs to be updated or removed from server List <string> filesToUploadToServer = new List <string>(); List <string> filesToDeleteOffServer = new List <string>(); //Files to upload foreach (var sourceFile in manifestFiles) { //find matching server file if (serverHashes.TryGetValue(sourceFile.Key.Replace('\\', '/') + @".lzma", out var matchingHash)) { //exists on server, compare hash if (matchingHash != sourceFile.Value.lzmahash) { //server hash is different! Upload new file. Log.Information(@"Server version of file is different from local: " + sourceFile.Key); filesToUploadToServer.Add(sourceFile.Key); } else { Log.Information(@"Server version of file is same as local: " + sourceFile.Key); } } else { Log.Information(@"Server does not have file: " + sourceFile.Key); filesToUploadToServer.Add(sourceFile.Key); } } //Files to remove from server foreach (var serverfile in serverHashes.Keys) { if (!manifestFiles.Any(x => (x.Key + @".lzma") == serverfile.Replace('/', '\\'))) { Log.Information(@"File exists on server but not locally: " + serverfile); filesToDeleteOffServer.Add(serverfile); } } #endregion long amountUploaded = 0, amountToUpload = 1; //Confirm changes if (filesToDeleteOffServer.Any() || filesToUploadToServer.Any()) { var text = M3L.GetString(M3L.string_interp_updaterServiceDeltaConfirmationHeader, mod.ModName); if (filesToUploadToServer.Any()) { text += M3L.GetString(M3L.string_nnFilesToUploadToServern) + @" " + string.Join('\n' + @" - ", filesToUploadToServer); //weird stuff to deal with localizer } if (filesToDeleteOffServer.Any()) { text += M3L.GetString(M3L.string_nnFilesToDeleteOffServern) + @" " + string.Join('\n' + @" - ", filesToDeleteOffServer); //weird stuff to deal with localizer } text += M3L.GetString(M3L.string_interp_updaterServiceDeltaConfirmationFooter); bool performUpload = false; Log.Information(@"Prompting user to accept server delta"); setTaskbarProgressState?.Invoke(TaskbarItemProgressState.Paused); Application.Current.Dispatcher.Invoke(delegate { performUpload = M3L.ShowDialog(mainwindow, text, M3L.GetString(M3L.string_confirmChanges), MessageBoxButton.OKCancel, MessageBoxImage.Exclamation) == MessageBoxResult.OK; }); setTaskbarProgressState?.Invoke(TaskbarItemProgressState.Indeterminate); if (performUpload) { Log.Information(@"User has accepted the delta, applying delta to server"); #region upload files //Create directories SortedSet <string> directoriesToCreate = new SortedSet <string>(); foreach (var f in filesToUploadToServer) { string foldername = f; var lastIndex = foldername.LastIndexOf(@"\"); while (lastIndex > 0) { foldername = foldername.Substring(0, lastIndex); directoriesToCreate.Add(foldername.Replace('\\', '/')); lastIndex = foldername.LastIndexOf(@"\"); } } #endregion //UploadDirectory(sftp, lzmaStagingPath, serverModPath, (ucb) => Debug.WriteLine("UCB: " + ucb)); var dirsToCreateOnServerSorted = directoriesToCreate.ToList(); dirsToCreateOnServerSorted.Sort((a, b) => a.Length.CompareTo(b.Length)); //short to longest so we create top levels first! int numFoldersToCreate = dirsToCreateOnServerSorted.Count(); int numDone = 0; if (dirsToCreateOnServerSorted.Count > 0) { CurrentActionText = M3L.GetString(M3L.string_creatingModDirectoriesOnServer); foreach (var f in dirsToCreateOnServerSorted) { var serverFolderStr = serverModPath + @"/" + f; if (!sftp.Exists(serverFolderStr)) { Log.Information(@"Creating directory on server: " + serverFolderStr); sftp.CreateDirectory(serverFolderStr); } else { Log.Information(@"Server folder already exists, skipping: " + serverFolderStr); } numDone++; CurrentActionText = M3L.GetString(M3L.string_creatingModDirectoriesOnServer) + @" " + Math.Round(numDone * 100.0 / numFoldersToCreate) + @"%"; } } //Upload files progressCallback?.Invoke(0); setTaskbarProgressState?.Invoke(TaskbarItemProgressState.Normal); amountToUpload = filesToUploadToServer.Sum(x => new FileInfo(Path.Combine(lzmaStagingPath, x + @".lzma")).Length); foreach (var file in filesToUploadToServer) { if (CancelOperations) { AbortUpload(); return(UploadModResult.ABORTED_BY_USER); } var fullPath = Path.Combine(lzmaStagingPath, file + @".lzma"); var serverFilePath = serverModPath + @"/" + file.Replace(@"\", @"/") + @".lzma"; Log.Information(@"Uploading file " + fullPath + @" to " + serverFilePath); long amountUploadedBeforeChunk = amountUploaded; using Stream fileStream = new FileStream(fullPath, FileMode.Open); sftp.UploadFile(fileStream, serverFilePath, true, (x) => { if (CancelOperations) { CurrentActionText = M3L.GetString(M3L.string_abortingUpload); return; } amountUploaded = amountUploadedBeforeChunk + (long)x; var uploadedHR = ByteSize.FromBytes(amountUploaded).ToString(@"0.00"); var totalUploadHR = ByteSize.FromBytes(amountToUpload).ToString(@"0.00"); if (amountToUpload > 0) { progressCallback?.Invoke(amountUploaded * 1.0 / amountToUpload); } CurrentActionText = M3L.GetString(M3L.string_interp_uploadingFilesToServerXY, uploadedHR, totalUploadHR); }); } setTaskbarProgressState?.Invoke(TaskbarItemProgressState.Indeterminate); if (CancelOperations) { AbortUpload(); return(UploadModResult.ABORTED_BY_USER); } //delete extra files int numdone = 0; foreach (var file in filesToDeleteOffServer) { CurrentActionText = M3L.GetString(M3L.string_interp_deletingObsoleteFiles, numdone, filesToDeleteOffServer.Count); var fullPath = $@"{LZMAStoragePath}/{serverFolderName}/{file}"; Log.Information(@"Deleting unused file off server: " + fullPath); sftp.DeleteFile(fullPath); numdone++; } //Upload manifest using var manifestStream = finalManifestText.ToStream(); var serverManifestPath = $@"{ManifestStoragePath}/{serverFolderName}.xml"; Log.Information(@"Uploading manifest to server: " + serverManifestPath); sftp.UploadFile(manifestStream, serverManifestPath, true, (x) => { var uploadedAmountHR = ByteSize.FromBytes(amountUploaded).ToString(@"0.00"); var uploadAmountTotalHR = ByteSize.FromBytes(amountToUpload).ToString(@"0.00"); CurrentActionText = M3L.GetString(M3L.string_uploadingUpdateManifestToServer) + $@"{uploadedAmountHR}/{uploadAmountTotalHR}"; }); } else { Log.Warning(@"User has declined uploading the delta. We will not change anything on the server."); CancelOperations = true; AbortUpload(); return(UploadModResult.ABORTED_BY_USER); } CurrentActionText = M3L.GetString(M3L.string_validatingModOnServer); Log.Information(@"Verifying hashes on server for new files"); var newServerhashes = getServerHashes(sshClient, serverFolderName, serverModPath); var badHashes = verifyHashes(manifestFiles, newServerhashes); if (badHashes.Any()) { CurrentActionText = M3L.GetString(M3L.string_someHashesOnServerAreIncorrectContactMgamerz); return(UploadModResult.BAD_SERVER_HASHES_AFTER_VALIDATION); } else { CurrentActionText = M3L.GetString(M3L.string_modUploadedToUpdaterService); return(UploadModResult.UPLOAD_OK); } } return(UploadModResult.ABORTED_BY_USER); }