diff --git a/Duplicati/Library/Modules/Builtin/ReportHelper.cs b/Duplicati/Library/Modules/Builtin/ReportHelper.cs index b83c81d3f..4f5f145c3 100644 --- a/Duplicati/Library/Modules/Builtin/ReportHelper.cs +++ b/Duplicati/Library/Modules/Builtin/ReportHelper.cs @@ -294,29 +294,61 @@ namespace Duplicati.Library.Modules.Builtin /// The result object. /// If set to true, the result is intended for a subject or title line. protected virtual string ReplaceTemplate(string input, object result, bool subjectline) - { - input = Regex.Replace(input, "\\%OPERATIONNAME\\%", m_operationname ?? "", RegexOptions.IgnoreCase | RegexOptions.CultureInvariant); - input = Regex.Replace(input, "\\%REMOTEURL\\%", m_remoteurl ?? "", RegexOptions.IgnoreCase | RegexOptions.CultureInvariant); - input = Regex.Replace(input, "\\%LOCALPATH\\%", m_localpath == null ? "" : string.Join(System.IO.Path.PathSeparator.ToString(), m_localpath), RegexOptions.IgnoreCase | RegexOptions.CultureInvariant); - input = Regex.Replace(input, "\\%PARSEDRESULT\\%", m_parsedresultlevel ?? "", RegexOptions.IgnoreCase | RegexOptions.CultureInvariant); - if (subjectline) - { - input = Regex.Replace(input, "\\%RESULT\\%", m_parsedresultlevel ?? "", RegexOptions.IgnoreCase | RegexOptions.CultureInvariant); - } - else + { + // For JSON, ignore the template and just use the contents + if (ExportFormat == ResultExportFormat.Json) { - if (input.IndexOf("%RESULT%", StringComparison.OrdinalIgnoreCase) >= 0) - input = Regex.Replace(input, "\\%RESULT\\%", m_resultFormatSerializer.Serialize(result, LogLines), RegexOptions.IgnoreCase | RegexOptions.CultureInvariant); + var extra = new Dictionary(); + + if (input.IndexOf("%OPERATIONNAME%", StringComparison.OrdinalIgnoreCase) >= 0) + extra["OperationName"] = m_operationname; + if (input.IndexOf("%REMOTEURL%", StringComparison.OrdinalIgnoreCase) >= 0) + extra["RemoteUrl"] = m_remoteurl; + if (input.IndexOf("%LOCALPATH%", StringComparison.OrdinalIgnoreCase) >= 0 && m_localpath != null) + extra["LocalPath"] = string.Join(System.IO.Path.PathSeparator.ToString(), m_localpath); + if (input.IndexOf("%PARSEDRESULT%", StringComparison.OrdinalIgnoreCase) >= 0) + extra["ParsedResult"] = m_parsedresultlevel; + + if (input.IndexOf("%backup-name%", StringComparison.OrdinalIgnoreCase) >= 0) + { + if (m_options.ContainsKey("backup-name")) + extra["backup-name"] = m_options["backup-name"]; + else + extra["backup-name"] = System.IO.Path.GetFileNameWithoutExtension(Duplicati.Library.Utility.Utility.getEntryAssembly().Location); + } + + foreach (KeyValuePair kv in m_options) + if (input.IndexOf($"%{kv.Key}%", StringComparison.OrdinalIgnoreCase) >= 0) + extra[kv.Key] = kv.Value; + + return m_resultFormatSerializer.Serialize(result, LogLines, extra); + } + else + { + + input = Regex.Replace(input, "\\%OPERATIONNAME\\%", m_operationname ?? "", RegexOptions.IgnoreCase | RegexOptions.CultureInvariant); + input = Regex.Replace(input, "\\%REMOTEURL\\%", m_remoteurl ?? "", RegexOptions.IgnoreCase | RegexOptions.CultureInvariant); + input = Regex.Replace(input, "\\%LOCALPATH\\%", m_localpath == null ? "" : string.Join(System.IO.Path.PathSeparator.ToString(), m_localpath), RegexOptions.IgnoreCase | RegexOptions.CultureInvariant); + input = Regex.Replace(input, "\\%PARSEDRESULT\\%", m_parsedresultlevel ?? "", RegexOptions.IgnoreCase | RegexOptions.CultureInvariant); + if (subjectline) + { + input = Regex.Replace(input, "\\%RESULT\\%", m_parsedresultlevel ?? "", RegexOptions.IgnoreCase | RegexOptions.CultureInvariant); + } + else + { + if (input.IndexOf("%RESULT%", StringComparison.OrdinalIgnoreCase) >= 0) + input = Regex.Replace(input, "\\%RESULT\\%", m_resultFormatSerializer.Serialize(result, LogLines, null), RegexOptions.IgnoreCase | RegexOptions.CultureInvariant); + } + + foreach (KeyValuePair kv in m_options) + input = Regex.Replace(input, "\\%" + kv.Key + "\\%", kv.Value ?? "", RegexOptions.IgnoreCase | RegexOptions.CultureInvariant); + + if (!m_options.ContainsKey("backup-name")) + input = Regex.Replace(input, "\\%backup-name\\%", System.IO.Path.GetFileNameWithoutExtension(Duplicati.Library.Utility.Utility.getEntryAssembly().Location) ?? "", RegexOptions.IgnoreCase | RegexOptions.CultureInvariant); + + input = Regex.Replace(input, "\\%[^\\%]+\\%", ""); + return input; } - - foreach (KeyValuePair kv in m_options) - input = Regex.Replace(input, "\\%" + kv.Key + "\\%", kv.Value ?? "", RegexOptions.IgnoreCase | RegexOptions.CultureInvariant); - - if (!m_options.ContainsKey("backup-name")) - input = Regex.Replace(input, "\\%backup-name\\%", System.IO.Path.GetFileNameWithoutExtension(Duplicati.Library.Utility.Utility.getEntryAssembly().Location) ?? "", RegexOptions.IgnoreCase | RegexOptions.CultureInvariant); - - input = Regex.Replace(input, "\\%[^\\%]+\\%", ""); - return input; } /// diff --git a/Duplicati/Library/Modules/Builtin/ResultSerialization/DuplicatiFormatSerializer.cs b/Duplicati/Library/Modules/Builtin/ResultSerialization/DuplicatiFormatSerializer.cs index a066e370f..a88cf21d6 100644 --- a/Duplicati/Library/Modules/Builtin/ResultSerialization/DuplicatiFormatSerializer.cs +++ b/Duplicati/Library/Modules/Builtin/ResultSerialization/DuplicatiFormatSerializer.cs @@ -17,7 +17,8 @@ namespace Duplicati.Library.Modules.Builtin.ResultSerialization /// The serialized result string. /// The result to serialize. /// The log lines to serialize. - public string Serialize(object result, IEnumerable loglines) + /// Additional parameters to include + public string Serialize(object result, IEnumerable loglines, Dictionary additional) { StringBuilder sb = new StringBuilder(); @@ -88,6 +89,9 @@ namespace Duplicati.Library.Modules.Builtin.ResultSerialization Utility.Utility.PrintSerializeObject(result, sb); } + if (additional != null && additional.Count > 0) + sb.AppendLine(Serialize(additional, null, null)); + if (loglines != null && loglines.Any()) { sb.AppendLine(); diff --git a/Duplicati/Library/Modules/Builtin/ResultSerialization/IResultFormatSerializer.cs b/Duplicati/Library/Modules/Builtin/ResultSerialization/IResultFormatSerializer.cs index 4fbfdf3fb..2df6776dc 100644 --- a/Duplicati/Library/Modules/Builtin/ResultSerialization/IResultFormatSerializer.cs +++ b/Duplicati/Library/Modules/Builtin/ResultSerialization/IResultFormatSerializer.cs @@ -13,7 +13,8 @@ namespace Duplicati.Library.Modules.Builtin /// The serialized result string. /// The result to serialize. /// The log lines to serialize. - string Serialize(object result, IEnumerable loglines); + /// Additional parameters to include + string Serialize(object result, IEnumerable loglines, Dictionary additional); /// /// Returns the format that the serializer represents diff --git a/Duplicati/Library/Modules/Builtin/ResultSerialization/JsonFormatSerializer.cs b/Duplicati/Library/Modules/Builtin/ResultSerialization/JsonFormatSerializer.cs index 1d1bdee49..f15516fca 100644 --- a/Duplicati/Library/Modules/Builtin/ResultSerialization/JsonFormatSerializer.cs +++ b/Duplicati/Library/Modules/Builtin/ResultSerialization/JsonFormatSerializer.cs @@ -53,12 +53,14 @@ namespace Duplicati.Library.Modules.Builtin.ResultSerialization /// The serialized result string. /// The result to serialize. /// The log lines to serialize. - public string Serialize(object result, IEnumerable loglines) - { + /// Additional parameters to include + public string Serialize(object result, IEnumerable loglines, Dictionary additional) + { return JsonConvert.SerializeObject( new { - Data = result, + Data = result, + Extra = additional, LogLines = loglines }, diff --git a/Duplicati/Library/Modules/Builtin/RunScript.cs b/Duplicati/Library/Modules/Builtin/RunScript.cs index 4c33a44a1..25db9a530 100644 --- a/Duplicati/Library/Modules/Builtin/RunScript.cs +++ b/Duplicati/Library/Modules/Builtin/RunScript.cs @@ -188,7 +188,7 @@ namespace Duplicati.Library.Modules.Builtin using (TempFile tmpfile = new TempFile()) { using (var streamWriter = new StreamWriter(tmpfile)) - streamWriter.Write(resultFormatSerializer.Serialize(result, m_logstorage)); + streamWriter.Write(resultFormatSerializer.Serialize(result, m_logstorage, null)); Execute(m_finishScript, "AFTER", m_operationName, ref m_remoteurl, ref m_localpath, m_timeout, false, m_options, tmpfile, level); } diff --git a/Duplicati/Library/Modules/Builtin/SendHttpMessage.cs b/Duplicati/Library/Modules/Builtin/SendHttpMessage.cs index e0dc9fdb8..ec1363c1f 100644 --- a/Duplicati/Library/Modules/Builtin/SendHttpMessage.cs +++ b/Duplicati/Library/Modules/Builtin/SendHttpMessage.cs @@ -191,6 +191,7 @@ namespace Duplicati.Library.Modules.Builtin { // No need to do the expansion as we throw away the result if (subjectline) return string.Empty; + return base.ReplaceTemplate(input, result, subjectline); }