From 8c8b844a703101c7559abdcfcd9a29406efbaa5d Mon Sep 17 00:00:00 2001 From: pavelbannov Date: Mon, 19 Aug 2019 16:51:36 +0300 Subject: [PATCH] Added ASC.Notify.Textile --- ASC.Web.sln | 6 + .../ASC.Core.Common/BaseCommonLinkUtility.cs | 36 +++ .../WhiteLabel/BaseWhiteLabelSettings.cs | 7 + .../WhiteLabel/MailWhiteLabelSettings.cs | 12 +- .../ASC.Notify.Textile.csproj | 30 ++ common/ASC.Notify.Textile/JabberStyler.cs | 93 ++++++ common/ASC.Notify.Textile/PushStyler.cs | 53 ++++ .../NotifyTemplateResource.Designer.cs | 138 ++++++++ .../Resources/NotifyTemplateResource.resx | 300 ++++++++++++++++++ common/ASC.Notify.Textile/StylerTests.cs | 59 ++++ common/ASC.Notify.Textile/TextileStyler.cs | 298 +++++++++++++++++ web/ASC.Web.Core/ASC.Web.Core.csproj | 1 + web/ASC.Web.Core/Utility/CommonLinkUtility.cs | 31 +- .../WhiteLabel/TenantWhiteLabelSettings.cs | 3 +- 14 files changed, 1030 insertions(+), 37 deletions(-) create mode 100644 common/ASC.Core.Common/WhiteLabel/BaseWhiteLabelSettings.cs rename {web/ASC.Web.Core => common/ASC.Core.Common}/WhiteLabel/MailWhiteLabelSettings.cs (92%) create mode 100644 common/ASC.Notify.Textile/ASC.Notify.Textile.csproj create mode 100644 common/ASC.Notify.Textile/JabberStyler.cs create mode 100644 common/ASC.Notify.Textile/PushStyler.cs create mode 100644 common/ASC.Notify.Textile/Resources/NotifyTemplateResource.Designer.cs create mode 100644 common/ASC.Notify.Textile/Resources/NotifyTemplateResource.resx create mode 100644 common/ASC.Notify.Textile/StylerTests.cs create mode 100644 common/ASC.Notify.Textile/TextileStyler.cs diff --git a/ASC.Web.sln b/ASC.Web.sln index b737f7141d..4f0d10abf9 100644 --- a/ASC.Web.sln +++ b/ASC.Web.sln @@ -42,6 +42,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ASC.Studio.Notify", "common EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ASC.Textile", "common\ASC.Textile\ASC.Textile.csproj", "{C8F410B4-B83B-47B9-9ECD-07590A8750A7}" EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ASC.Notify.Textile", "common\ASC.Notify.Textile\ASC.Notify.Textile.csproj", "{DB50E2EF-B4D8-493A-8568-29CAC0DF9062}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -120,6 +122,10 @@ Global {C8F410B4-B83B-47B9-9ECD-07590A8750A7}.Debug|Any CPU.Build.0 = Debug|Any CPU {C8F410B4-B83B-47B9-9ECD-07590A8750A7}.Release|Any CPU.ActiveCfg = Release|Any CPU {C8F410B4-B83B-47B9-9ECD-07590A8750A7}.Release|Any CPU.Build.0 = Release|Any CPU + {DB50E2EF-B4D8-493A-8568-29CAC0DF9062}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {DB50E2EF-B4D8-493A-8568-29CAC0DF9062}.Debug|Any CPU.Build.0 = Debug|Any CPU + {DB50E2EF-B4D8-493A-8568-29CAC0DF9062}.Release|Any CPU.ActiveCfg = Release|Any CPU + {DB50E2EF-B4D8-493A-8568-29CAC0DF9062}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/common/ASC.Core.Common/BaseCommonLinkUtility.cs b/common/ASC.Core.Common/BaseCommonLinkUtility.cs index 303853b738..6398b1b07e 100644 --- a/common/ASC.Core.Common/BaseCommonLinkUtility.cs +++ b/common/ASC.Core.Common/BaseCommonLinkUtility.cs @@ -25,6 +25,8 @@ using System; +using System.Linq; +using System.Text.RegularExpressions; using System.Web; using ASC.Common.Logging; using ASC.Common.Web; @@ -152,6 +154,40 @@ namespace ASC.Core.Common return virtualPath; } return (_vpath != "/" ? _vpath : string.Empty) + "/" + virtualPath.TrimStart('~', '/'); + } + + public static string GetRegionalUrl(string url, string lang) + { + if (string.IsNullOrEmpty(url)) + return url; + + //-replace language + var regex = new Regex("{.*?}"); + var matches = regex.Matches(url); + + if (string.IsNullOrEmpty(lang)) + { + url = matches.Cast().Aggregate(url, (current, match) => current.Replace(match.Value, string.Empty)); + } + else + { + foreach (Match match in matches) + { + var values = match.Value.TrimStart('{').TrimEnd('}').Split('|'); + url = url.Replace(match.Value, values.Contains(lang) ? lang : string.Empty); + } + } + //- + + //--remove redundant slashes + var uri = new Uri(url); + var baseUri = new UriBuilder(uri.Scheme, uri.Host, uri.Port).Uri; + baseUri = uri.Segments.Aggregate(baseUri, (current, segment) => new Uri(current, segment)); + //-- + //todo: lost query string!!! + + + return baseUri.ToString().TrimEnd('/'); } } } diff --git a/common/ASC.Core.Common/WhiteLabel/BaseWhiteLabelSettings.cs b/common/ASC.Core.Common/WhiteLabel/BaseWhiteLabelSettings.cs new file mode 100644 index 0000000000..a1314dd754 --- /dev/null +++ b/common/ASC.Core.Common/WhiteLabel/BaseWhiteLabelSettings.cs @@ -0,0 +1,7 @@ +namespace ASC.Core.Common.WhiteLabel +{ + public class BaseWhiteLabelSettings + { + public const string DefaultLogoText = "ONLYOFFICE"; + } +} diff --git a/web/ASC.Web.Core/WhiteLabel/MailWhiteLabelSettings.cs b/common/ASC.Core.Common/WhiteLabel/MailWhiteLabelSettings.cs similarity index 92% rename from web/ASC.Web.Core/WhiteLabel/MailWhiteLabelSettings.cs rename to common/ASC.Core.Common/WhiteLabel/MailWhiteLabelSettings.cs index 966262a07c..823c3ebf90 100644 --- a/web/ASC.Web.Core/WhiteLabel/MailWhiteLabelSettings.cs +++ b/common/ASC.Core.Common/WhiteLabel/MailWhiteLabelSettings.cs @@ -27,8 +27,8 @@ using System; using System.Runtime.Serialization; using ASC.Common.Utils; +using ASC.Core.Common; using ASC.Core.Common.Settings; -using ASC.Web.Studio.Utility; namespace ASC.Web.Core.WhiteLabel { @@ -102,7 +102,7 @@ namespace ASC.Web.Core.WhiteLabel { get { - var url = CommonLinkUtility.GetRegionalUrl(ConfigurationManager.AppSettings["web.support-feedback"] ?? string.Empty, null); + var url = BaseCommonLinkUtility.GetRegionalUrl(ConfigurationManager.AppSettings["web:support-feedback"] ?? string.Empty, null); return !string.IsNullOrEmpty(url) ? url : "http://support.onlyoffice.com"; } } @@ -111,7 +111,7 @@ namespace ASC.Web.Core.WhiteLabel { get { - var email = ConfigurationManager.AppSettings["web.support.email"]; + var email = ConfigurationManager.AppSettings["web:support:email"]; return !string.IsNullOrEmpty(email) ? email : "support@onlyoffice.com"; } } @@ -120,7 +120,7 @@ namespace ASC.Web.Core.WhiteLabel { get { - var email = ConfigurationManager.AppSettings["web.payment.email"]; + var email = ConfigurationManager.AppSettings["web:payment:email"]; return !string.IsNullOrEmpty(email) ? email : "sales@onlyoffice.com"; } } @@ -129,7 +129,7 @@ namespace ASC.Web.Core.WhiteLabel { get { - var url = CommonLinkUtility.GetRegionalUrl(ConfigurationManager.AppSettings["web.demo-order"] ?? string.Empty, null); + var url = BaseCommonLinkUtility.GetRegionalUrl(ConfigurationManager.AppSettings["web:demo-order"] ?? string.Empty, null); return !string.IsNullOrEmpty(url) ? url : "http://www.onlyoffice.com/demo-order.aspx"; } } @@ -138,7 +138,7 @@ namespace ASC.Web.Core.WhiteLabel { get { - var url = ConfigurationManager.AppSettings["web.teamlab-site"]; + var url = ConfigurationManager.AppSettings["web:teamlab-site"]; return !string.IsNullOrEmpty(url) ? url : "http://www.onlyoffice.com"; } } diff --git a/common/ASC.Notify.Textile/ASC.Notify.Textile.csproj b/common/ASC.Notify.Textile/ASC.Notify.Textile.csproj new file mode 100644 index 0000000000..6a9c3641fb --- /dev/null +++ b/common/ASC.Notify.Textile/ASC.Notify.Textile.csproj @@ -0,0 +1,30 @@ + + + 9.0.30729 + netcoreapp3.0 + + + + + ASC.Notify.Textile + Ascensio System SIA + ASC.Notify.Textile + (c) Ascensio System SIA. All rights reserved + false + + Library + + + + full + + + none + true + + + + + + + \ No newline at end of file diff --git a/common/ASC.Notify.Textile/JabberStyler.cs b/common/ASC.Notify.Textile/JabberStyler.cs new file mode 100644 index 0000000000..66f3d66a13 --- /dev/null +++ b/common/ASC.Notify.Textile/JabberStyler.cs @@ -0,0 +1,93 @@ +/* + * + * (c) Copyright Ascensio System Limited 2010-2018 + * + * This program is freeware. You can redistribute it and/or modify it under the terms of the GNU + * General Public License (GPL) version 3 as published by the Free Software Foundation (https://www.gnu.org/copyleft/gpl.html). + * In accordance with Section 7(a) of the GNU GPL its Section 15 shall be amended to the effect that + * Ascensio System SIA expressly excludes the warranty of non-infringement of any third-party rights. + * + * THIS PROGRAM IS DISTRIBUTED WITHOUT ANY WARRANTY; WITHOUT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY OR + * FITNESS FOR A PARTICULAR PURPOSE. For more details, see GNU GPL at https://www.gnu.org/copyleft/gpl.html + * + * You can contact Ascensio System SIA by email at sales@onlyoffice.com + * + * The interactive user interfaces in modified source and object code versions of ONLYOFFICE must display + * Appropriate Legal Notices, as required under Section 5 of the GNU GPL version 3. + * + * Pursuant to Section 7 § 3(b) of the GNU GPL you must retain the original ONLYOFFICE logo which contains + * relevant author attributions when distributing the software. If the display of the logo in its graphic + * form is not reasonably feasible for technical reasons, you must include the words "Powered by ONLYOFFICE" + * in every copy of the program you distribute. + * Pursuant to Section 7 § 3(e) we decline to grant you any rights under trademark law for use of our trademarks. + * +*/ + + +using System; +using System.Text.RegularExpressions; +using System.Web; +using ASC.Common.Notify.Patterns; +using ASC.Notify.Messages; +using ASC.Notify.Patterns; + +namespace ASC.Notify.Textile +{ + public class JabberStyler : IPatternStyler + { + static readonly Regex VelocityArguments = new Regex(NVelocityPatternFormatter.NoStylePreffix + "(?.*?)" + NVelocityPatternFormatter.NoStyleSuffix, RegexOptions.IgnoreCase | RegexOptions.Singleline | RegexOptions.Compiled); + static readonly Regex LinkReplacer = new Regex(@"""(?[\w\W]+?)"":""(?[^""]+)""", RegexOptions.Singleline | RegexOptions.Compiled); + static readonly Regex TextileReplacer = new Regex(@"(h1\.|h2\.|\*|h3\.|\^)", RegexOptions.Singleline | RegexOptions.Compiled); + static readonly Regex BrReplacer = new Regex(@"", RegexOptions.IgnoreCase | RegexOptions.CultureInvariant | RegexOptions.IgnorePatternWhitespace | RegexOptions.Compiled | RegexOptions.Singleline); + static readonly Regex ClosedTagsReplacer = new Regex(@"", RegexOptions.IgnoreCase | RegexOptions.CultureInvariant | RegexOptions.IgnorePatternWhitespace | RegexOptions.Compiled | RegexOptions.Singleline); + static readonly Regex TagReplacer = new Regex(@"<(.|\n)*?>", RegexOptions.IgnoreCase | RegexOptions.CultureInvariant | RegexOptions.IgnorePatternWhitespace | RegexOptions.Compiled | RegexOptions.Singleline); + static readonly Regex MultiLineBreaksReplacer = new Regex(@"(?:\r\n|\r(?!\n)|(?!<\r)\n){3,}", RegexOptions.IgnoreCase | RegexOptions.CultureInvariant); + + public void ApplyFormating(NoticeMessage message) + { + var body = string.Empty; + if (!string.IsNullOrEmpty(message.Subject)) + { + body += VelocityArguments.Replace(message.Subject, ArgMatchReplace) + Environment.NewLine; + message.Subject = string.Empty; + } + if (string.IsNullOrEmpty(message.Body)) return; + var lines = message.Body.Split(new[] { Environment.NewLine, "\n" }, StringSplitOptions.None); + for (var i = 0; i < lines.Length - 1; i++) + { + if (string.IsNullOrEmpty(lines[i])) { body += Environment.NewLine; continue; } + lines[i] = VelocityArguments.Replace(lines[i], ArgMatchReplace); + body += LinkReplacer.Replace(lines[i], EvalLink) + Environment.NewLine; + } + lines[^1] = VelocityArguments.Replace(lines[^1], ArgMatchReplace); + body += LinkReplacer.Replace(lines[^1], EvalLink); + body = TextileReplacer.Replace(HttpUtility.HtmlDecode(body), ""); //Kill textile markup + body = BrReplacer.Replace(body, Environment.NewLine); + body = ClosedTagsReplacer.Replace(body, Environment.NewLine); + body = TagReplacer.Replace(body, ""); + body = MultiLineBreaksReplacer.Replace(body, Environment.NewLine); + message.Body = body; + } + + private static string EvalLink(Match match) + { + if (match.Success) + { + if (match.Groups["text"].Success && match.Groups["link"].Success) + { + if (match.Groups["text"].Value.Equals(match.Groups["link"].Value, StringComparison.OrdinalIgnoreCase)) + { + return " " + match.Groups["text"].Value + " "; + } + return match.Groups["text"].Value + string.Format(" ( {0} )", match.Groups["link"].Value); + } + } + return match.Value; + } + + private static string ArgMatchReplace(Match match) + { + return match.Result("${arg}"); + } + } +} diff --git a/common/ASC.Notify.Textile/PushStyler.cs b/common/ASC.Notify.Textile/PushStyler.cs new file mode 100644 index 0000000000..79b6890bc7 --- /dev/null +++ b/common/ASC.Notify.Textile/PushStyler.cs @@ -0,0 +1,53 @@ +/* + * + * (c) Copyright Ascensio System Limited 2010-2018 + * + * This program is freeware. You can redistribute it and/or modify it under the terms of the GNU + * General Public License (GPL) version 3 as published by the Free Software Foundation (https://www.gnu.org/copyleft/gpl.html). + * In accordance with Section 7(a) of the GNU GPL its Section 15 shall be amended to the effect that + * Ascensio System SIA expressly excludes the warranty of non-infringement of any third-party rights. + * + * THIS PROGRAM IS DISTRIBUTED WITHOUT ANY WARRANTY; WITHOUT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY OR + * FITNESS FOR A PARTICULAR PURPOSE. For more details, see GNU GPL at https://www.gnu.org/copyleft/gpl.html + * + * You can contact Ascensio System SIA by email at sales@onlyoffice.com + * + * The interactive user interfaces in modified source and object code versions of ONLYOFFICE must display + * Appropriate Legal Notices, as required under Section 5 of the GNU GPL version 3. + * + * Pursuant to Section 7 § 3(b) of the GNU GPL you must retain the original ONLYOFFICE logo which contains + * relevant author attributions when distributing the software. If the display of the logo in its graphic + * form is not reasonably feasible for technical reasons, you must include the words "Powered by ONLYOFFICE" + * in every copy of the program you distribute. + * Pursuant to Section 7 § 3(e) we decline to grant you any rights under trademark law for use of our trademarks. + * +*/ + + +using System; +using System.Text.RegularExpressions; +using ASC.Common.Notify.Patterns; +using ASC.Notify.Messages; +using ASC.Notify.Patterns; + +namespace ASC.Notify.Textile +{ + public class PushStyler : IPatternStyler + { + private static readonly Regex VelocityArgumentsRegex = new Regex(NVelocityPatternFormatter.NoStylePreffix + "(?'arg'.*?)" + NVelocityPatternFormatter.NoStyleSuffix, RegexOptions.IgnoreCase | RegexOptions.Singleline | RegexOptions.Compiled); + + public void ApplyFormating(NoticeMessage message) + { + if (!string.IsNullOrEmpty(message.Subject)) + { + message.Subject = VelocityArgumentsRegex.Replace(message.Subject, m => m.Groups["arg"].Value); + message.Subject = message.Subject.Replace(Environment.NewLine, " ").Trim(); + } + if (!string.IsNullOrEmpty(message.Body)) + { + message.Body = VelocityArgumentsRegex.Replace(message.Body, m => m.Groups["arg"].Value); + message.Body = message.Body.Replace(Environment.NewLine, " ").Trim(); + } + } + } +} diff --git a/common/ASC.Notify.Textile/Resources/NotifyTemplateResource.Designer.cs b/common/ASC.Notify.Textile/Resources/NotifyTemplateResource.Designer.cs new file mode 100644 index 0000000000..263aef538c --- /dev/null +++ b/common/ASC.Notify.Textile/Resources/NotifyTemplateResource.Designer.cs @@ -0,0 +1,138 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace ASC.Notify.Textile.Resources { + using System; + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + public class NotifyTemplateResource { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal NotifyTemplateResource() { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + public static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("ASC.Notify.Textile.Resources.NotifyTemplateResource", typeof(NotifyTemplateResource).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + public static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// + /// Looks up a localized string similar to <tr border="0" cellspacing="0" cellpadding="0"><td colspan="3" style="height: 10px; line-height: 10px; background: #fff; padding: 0; margin: 0;">&nbsp;</td></tr> + /// <tr border="0" cellspacing="0" cellpadding="0"> + /// <td style="vertical-align: top; margin: 0; padding: 34px 0 0 0; width: 210px; height: 108px; background: #f6f6f6; -moz-border-radius-topleft: 6px; -webkit-border-top-left-radius: 6px; border-top-left-radius: 6px;"> + /// <img src="https://static.onlyoffice.com/media/news [rest of string was truncated]";. + /// + public static string FooterCommon { + get { + return ResourceManager.GetString("FooterCommon", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to <tr border="0" cellspacing="0" cellpadding="0"><td colspan="3" style="height: 10px; line-height: 10px; background: #fff; padding: 0; margin: 0;">&nbsp;</td></tr> + /// <tr border="0" cellspacing="0" cellpadding="0"> + /// <td style="vertical-align: top; margin: 0; padding: 34px 0 0 0; width: 210px; height: 108px; background: #f6f6f6; -moz-border-radius-topleft: 6px; -webkit-border-top-left-radius: 6px; border-top-left-radius: 6px;"> + /// <img src="https://static.onlyoffice.com/media/news [rest of string was truncated]";. + /// + public static string FooterOpensource { + get { + return ResourceManager.GetString("FooterOpensource", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to <body style="margin: 0; padding: 0; text-align: center; width: 100%; font-family: Arial, sans-serif; font-size: 14px; color: #333;"> + ///%ANALYTICS% + ///<div style="background-color: #fff; width: 600px; margin: 0 auto; text-align: left;"> + /// <table cellspacing="0" cellpadding="0" style="font-family: Arial; font-size: 14px; color: #333; background: #fff; text-align: center; width: 600px; margin: 0; padding: 0; border: 0 none; border-collapse: collapse; empty-cells: show; border-spacing: 0;"> + /// <tbody> + /// [rest of string was truncated]";. + /// + public static string HtmlMaster { + get { + return ResourceManager.GetString("HtmlMaster", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to <body style="margin: 0; padding: 0; text-align: center; width: 100%; font-family: Arial, sans-serif; font-size: 14px; color: #333;"> + ///%ANALYTICS% + ///<div style="background-color: #fff; width: 600px; margin: 0 auto; text-align: left;"> + /// <table cellspacing="0" cellpadding="0" style="font-family: Arial; font-size: 14px; color: #333; background: #fff; text-align: center; width: 600px; margin: 0; padding: 0; border: 0 none; border-collapse: collapse; empty-cells: show; border-spacing: 0;"> + /// <tbody> + /// [rest of string was truncated]";. + /// + public static string HtmlMasterPersonal { + get { + return ResourceManager.GetString("HtmlMasterPersonal", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to <tr border="0" cellspacing="0" cellpadding="0"> + /// <td style="width: 40px; vertical-align: top; margin: 0; padding: 22px 5px 0 155px;"> + /// <a href="https://www.facebook.com/pages/OnlyOffice/833032526736775" style="width: 40px; height: 40px; display: block; margin: 0; padding: 0;" target="_blank"> + /// <img src="https://static.onlyoffice.com/media/newsletters/images-v10/social-fb-40.png" alt="Facebook" style="width: 40px; height: 40px;" /> + /// </a> + /// </td [rest of string was truncated]";. + /// + public static string SocialNetworksFooter { + get { + return ResourceManager.GetString("SocialNetworksFooter", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to You received this message because you are a registered user of the <a href="{0}" style="color: #7b7b7b;" target="_blank">{0}</a>. <a href="{1}" style="color: #7b7b7b;" target="_blank">Unsubscribe</a>. + /// + public static string TextForFooterWithUnsubscribeLink { + get { + return ResourceManager.GetString("TextForFooterWithUnsubscribeLink", resourceCulture); + } + } + } +} diff --git a/common/ASC.Notify.Textile/Resources/NotifyTemplateResource.resx b/common/ASC.Notify.Textile/Resources/NotifyTemplateResource.resx new file mode 100644 index 0000000000..b9a4dc12a7 --- /dev/null +++ b/common/ASC.Notify.Textile/Resources/NotifyTemplateResource.resx @@ -0,0 +1,300 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + <tr border="0" cellspacing="0" cellpadding="0"><td colspan="3" style="height: 10px; line-height: 10px; background: #fff; padding: 0; margin: 0;">&nbsp;</td></tr> + <tr border="0" cellspacing="0" cellpadding="0"> + <td style="vertical-align: top; margin: 0; padding: 34px 0 0 0; width: 210px; height: 108px; background: #f6f6f6; -moz-border-radius-topleft: 6px; -webkit-border-top-left-radius: 6px; border-top-left-radius: 6px;"> + <img src="https://static.onlyoffice.com/media/newsletters/images-v10/tech-100.png" style="width: 100px; height: 100px;margin: 0 auto;" /> + </td> + <td style="vertical-align: top; margin: 0; padding: 34px 0 0 0; width: 180px; height: 108px; background: #f6f6f6;"> + <img src="https://static.onlyoffice.com/media/newsletters/images-v10/mailus-100.png" style="width: 100px; height: 100px;margin: 0 auto;" /> + </td> + <td style="vertical-align: top; margin: 0; padding: 34px 0 0 0; width: 210px; height: 108px; background: #f6f6f6; -moz-border-radius-topright: 6px; -webkit-border-top-right-radius: 6px; border-top-right-radius: 6px;"> + <img src="https://static.onlyoffice.com/media/newsletters/images-v10/demo-100.png" style="width: 100px; height: 100px;margin: 0 auto;" /> + </td> + </tr> + <tr border="0" cellspacing="0" cellpadding="0"> + <td style="vertical-align: top; margin: 0; padding: 0; width: 210px; height: 16px; background: #f6f6f6;">Need tech help?</td> + <td style="vertical-align: top; margin: 0; padding: 0; width: 180px; height: 16px; background: #f6f6f6;">Sales Questions</td> + <td style="vertical-align: top; margin: 0; padding: 0; width: 210px; height: 16px; background: #f6f6f6;">Order Demo</td> + </tr> + <tr border="0" cellspacing="0" cellpadding="0"> + <td style="vertical-align: top; margin: 0; padding: 0 0 30px; width: 210px; background: #f6f6f6;-moz-border-radius-bottomleft: 6px; -webkit-border-bottom-left-radius: 6px; border-bottom-left-radius: 6px;"> + <a href="%SUPPORTURL%" target="_blank" style="color: #333;">Send your question</a> + </td> + <td style="vertical-align: top; margin: 0; padding: 0 0 30px; width: 180px; background: #f6f6f6;"> + <a href="mailto:%SALESEMAIL%" style="color: #333;">Email us</a> + </td> + <td style="vertical-align: top; margin: 0; padding: 0 0 30px; width: 210px; background: #f6f6f6;-moz-border-radius-bottomright: 6px; -webkit-border-bottom-right-radius: 6px; border-bottom-right-radius: 6px;"> + <a href="%DEMOURL%" target="_blank" style="color: #333;">Send a request</a> + </td> + </tr> + + + <tr border="0" cellspacing="0" cellpadding="0"><td colspan="3" style="height: 10px; line-height: 10px; background: #fff; padding: 0; margin: 0;">&nbsp;</td></tr> + <tr border="0" cellspacing="0" cellpadding="0"> + <td style="vertical-align: top; margin: 0; padding: 34px 0 0 0; width: 210px; height: 108px; background: #f6f6f6; -moz-border-radius-topleft: 6px; -webkit-border-top-left-radius: 6px; border-top-left-radius: 6px;"> + <img src="https://static.onlyoffice.com/media/newsletters/images-v10/tech-100.png" style="width: 100px; height: 100px;margin: 0 auto;" /> + </td> + <td style="vertical-align: top; margin: 0; padding: 34px 0 0 0; width: 180px; height: 108px; background: #f6f6f6;"> + <img src="https://static.onlyoffice.com/media/newsletters/images-v10/mailus-100.png" style="width: 100px; height: 100px;margin: 0 auto;" /> + </td> + <td style="vertical-align: top; margin: 0; padding: 34px 0 0 0; width: 210px; height: 108px; background: #f6f6f6; -moz-border-radius-topright: 6px; -webkit-border-top-right-radius: 6px; border-top-right-radius: 6px;"> + <img src="https://static.onlyoffice.com/media/newsletters/images-v10/demo-100.png" style="width: 100px; height: 100px;margin: 0 auto;" /> + </td> + </tr> + <tr border="0" cellspacing="0" cellpadding="0"> + <td style="vertical-align: top; margin: 0; padding: 0; width: 210px; height: 16px; background: #f6f6f6;">Need tech help?</td> + <td style="vertical-align: top; margin: 0; padding: 0; width: 180px; height: 16px; background: #f6f6f6;">Sales Questions</td> + <td style="vertical-align: top; margin: 0; padding: 0; width: 210px; height: 16px; background: #f6f6f6;">Order Demo</td> + </tr> + <tr border="0" cellspacing="0" cellpadding="0"> + <td style="vertical-align: top; margin: 0; padding: 0 0 30px; width: 210px; background: #f6f6f6;-moz-border-radius-bottomleft: 6px; -webkit-border-bottom-left-radius: 6px; border-bottom-left-radius: 6px;"> + <a href="http://dev.onlyoffice.org/" target="_blank" style="color: #333;">Ask the Community</a> + </td> + <td style="vertical-align: top; margin: 0; padding: 0 0 30px; width: 180px; background: #f6f6f6;"> + <a href="mailto:sales@onlyoffice.com" style="color: #333;">Email us</a> + </td> + <td style="vertical-align: top; margin: 0; padding: 0 0 30px; width: 210px; background: #f6f6f6;-moz-border-radius-bottomright: 6px; -webkit-border-bottom-right-radius: 6px; border-bottom-right-radius: 6px;"> + <a href="http://www.onlyoffice.com/demo-order.aspx" target="_blank" style="color: #333;">Send a request</a> + </td> + </tr> + + + <body style="margin: 0; padding: 0; text-align: center; width: 100%; font-family: Arial, sans-serif; font-size: 14px; color: #333;"> +%ANALYTICS% +<div style="background-color: #fff; width: 600px; margin: 0 auto; text-align: left;"> + <table cellspacing="0" cellpadding="0" style="font-family: Arial; font-size: 14px; color: #333; background: #fff; text-align: center; width: 600px; margin: 0; padding: 0; border: 0 none; border-collapse: collapse; empty-cells: show; border-spacing: 0;"> + <tbody> + <tr border="0" cellspacing="0" cellpadding="0"> + <td colspan="3" style="margin: 0; padding: 0; background-color: #fff; height: 65px; padding: 20px 0 0 30px;"> + <div style="text-align: left; height: 65px; width: 570px; margin: 0; padding: 0;"> + <a href="%SITEURL%" style="text-decoration: none; display: inline-block; width: 216px; height: 35px; margin: 0; padding: 0;" target="_blank"> + <img src="%LOGO%" style="border: 0px none; width: 216px; height: 35px; margin: 0; padding: 0;" alt="%LOGOTEXT%" /> + </a> + </div> + </td> + </tr> + <tr border="0" cellspacing="0" cellpadding="0"> + <td colspan="3" style="margin: 0; padding: 15px 30px 15px; background-color: #f6f6f6; -moz-border-radius: 6px; -webkit-border-radius: 6px; border-radius: 6px;"> + <div style="font-family: Arial; font-size: 14px; color: #333; margin: 0; padding: 0; width: 540px; height: auto; overflow: hidden; word-wrap: break-word; vertical-align: top; text-align: left; border: 0 none;"> + %CONTENT% + </div> + </td> + </tr> + %FOOTER% + </tbody> + </table> + + <table cellspacing="0" cellpadding="0" style="font-family: Arial; font-size: 14px; color: #333; text-align: center; vertical-align: top; width: 600px; margin: 0; padding: 0; border-collapse: collapse; border: 0; border-spacing: 0; "> + <tbody> + %FOOTERSOCIAL% + <tr border="0" cellspacing="0" cellpadding="0"> + <td colspan="6" style="width: 600px; vertical-align: top; margin: 0; padding: 20px 30px 15px;"> + <p style="color: #7b7b7b; font-family: Arial, Tahoma; font-size: 12px; margin: 0; padding: 0; text-align: center; width: 540px;"> + %TEXTFOOTER% + </p> + </td> + </tr> + </tbody> + </table> +</div> +</body> + + + <body style="margin: 0; padding: 0; text-align: center; width: 100%; font-family: Arial, sans-serif; font-size: 14px; color: #333;"> +%ANALYTICS% +<div style="background-color: #fff; width: 600px; margin: 0 auto; text-align: left;"> + <table cellspacing="0" cellpadding="0" style="font-family: Arial; font-size: 14px; color: #333; background: #fff; text-align: center; width: 600px; margin: 0; padding: 0; border: 0 none; border-collapse: collapse; empty-cells: show; border-spacing: 0;"> + <tbody> + <tr border="0" cellspacing="0" cellpadding="0"> + <td colspan="3" style="margin: 0; padding: 0; background-color: #fff; height: 65px; padding: 20px 0 0 30px;"> + <div style="text-align: left; height: 65px; width: 570px; margin: 0; padding: 0;"> + <a href="%SITEURL%" style="text-decoration: none; display: inline-block; width: 216px; height: 35px; margin: 0; padding: 0;" target="_blank"> + <img src="%LOGO%" style="border: 0px none; width: 216px; height: 35px; margin: 0; padding: 0;" alt="%LOGOTEXT%" /> + </a> + </div> + </td> + </tr> + <tr border="0" cellspacing="0" cellpadding="0"> + <td colspan="3" style="margin: 0; padding: 0; background-color: #f6f6f6; -moz-border-radius: 6px; -webkit-border-radius: 6px; border-radius: 6px;"> + <div style="width: 600px; height: 340px; background: url('https://d2nlctn12v279m.cloudfront.net/media/newsletters/images/personal-wellcome-bg.png') 0 0 no-repeat; margin: 0; padding: 0; border: 0 none;"></div> +<div style="font-family: Arial; font-size: 14px; color: #333; margin: 0; padding: 15px 30px 15px; width: 540px; height: auto; overflow: hidden; word-wrap: break-word; vertical-align: top; text-align: left; border: 0 none;"> + %CONTENT% + </div> + </td> + </tr> + %FOOTER% + </tbody> + </table> + + <table cellspacing="0" cellpadding="0" style="font-family: Arial; font-size: 14px; color: #333; text-align: center; vertical-align: top; width: 600px; margin: 0; padding: 0; border-collapse: collapse; border: 0; border-spacing: 0; "> + <tbody> + %FOOTERSOCIAL% + <tr border="0" cellspacing="0" cellpadding="0"> + <td colspan="6" style="width: 600px; vertical-align: top; margin: 0; padding: 20px 30px 15px;"> + <p style="color: #7b7b7b; font-family: Arial, Tahoma; font-size: 12px; margin: 0; padding: 0; text-align: center; width: 540px;"> + %TEXTFOOTER% + </p> + </td> + </tr> + </tbody> + </table> +</div> +</body> + + + <tr border="0" cellspacing="0" cellpadding="0"> + <td style="width: 40px; vertical-align: top; margin: 0; padding: 22px 5px 0 155px;"> + <a href="https://www.facebook.com/pages/OnlyOffice/833032526736775" style="width: 40px; height: 40px; display: block; margin: 0; padding: 0;" target="_blank"> + <img src="https://static.onlyoffice.com/media/newsletters/images-v10/social-fb-40.png" alt="Facebook" style="width: 40px; height: 40px;" /> + </a> + </td> + <td style="width: 40px; vertical-align: top; margin: 0; padding: 22px 5px 0 5px;"> + <a href="https://twitter.com/ONLY_OFFICE" style="width: 40px; height: 40px; display: block; margin: 0; padding: 0;" target="_blank"> + <img src="https://static.onlyoffice.com/media/newsletters/images-v10/social-tw-40.png" alt="Twitter" style="width: 40px; height: 40px;" /> + </a> + </td> + <td style="width: 40px; vertical-align: top; margin: 0; padding: 22px 5px 0 5px;"> + <a href="https://www.onlyoffice.com/blog" style="width: 40px; height: 40px; display: block; margin: 0; padding: 0;" target="_blank"> + <img src="https://static.onlyoffice.com/media/newsletters/images-v10/social-blog-40.png" alt="ONLYOFFICE" style="width: 40px; height: 40px;" /> + </a> + </td> + <td style="width: 40px; vertical-align: top; margin: 0; padding: 22px 5px 0 5px;"> + <a href="https://www.youtube.com/user/onlyofficeTV" style="width: 40px; height: 40px; display: block; margin: 0; padding: 0;" target="_blank"> + <img src="https://static.onlyoffice.com/media/newsletters/images-v10/social-youtube-40.png" alt="YouTube" style="width: 40px; height: 40x;" /> + </a> + </td> + <td style="width: 40px; vertical-align: top; margin: 0; padding: 22px 5px 0 5px;"> + <a href="https://vk.com/onlyoffice" style="width: 40px; height: 40px; display: block; margin: 0; padding: 0;" target="_blank"> + <img src="https://static.onlyoffice.com/media/newsletters/images-v10/social-vk-40.png" alt="VK" style="width: 40px; height: 40px;" /> + </a> + </td> + <td style="width: 40px; vertical-align: top; margin: 0; padding: 22px 155px 0 5px;"> + <a href="https://www.instagram.com/the_onlyoffice" style="width: 40px; height: 40px; display: block; margin: 0; padding: 0;" target="_blank"> + <img src="https://static.onlyoffice.com/media/newsletters/images-v10/social-inst-40.png" alt="Instagram" style="width: 40px; height: 40px;" /> + </a> + </td> + </tr> + + + You received this message because you are a registered user of the <a href="{0}" style="color: #7b7b7b;" target="_blank">{0}</a>. <a href="{1}" style="color: #7b7b7b;" target="_blank">Unsubscribe</a> + + \ No newline at end of file diff --git a/common/ASC.Notify.Textile/StylerTests.cs b/common/ASC.Notify.Textile/StylerTests.cs new file mode 100644 index 0000000000..782acddf28 --- /dev/null +++ b/common/ASC.Notify.Textile/StylerTests.cs @@ -0,0 +1,59 @@ +/* + * + * (c) Copyright Ascensio System Limited 2010-2018 + * + * This program is freeware. You can redistribute it and/or modify it under the terms of the GNU + * General Public License (GPL) version 3 as published by the Free Software Foundation (https://www.gnu.org/copyleft/gpl.html). + * In accordance with Section 7(a) of the GNU GPL its Section 15 shall be amended to the effect that + * Ascensio System SIA expressly excludes the warranty of non-infringement of any third-party rights. + * + * THIS PROGRAM IS DISTRIBUTED WITHOUT ANY WARRANTY; WITHOUT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY OR + * FITNESS FOR A PARTICULAR PURPOSE. For more details, see GNU GPL at https://www.gnu.org/copyleft/gpl.html + * + * You can contact Ascensio System SIA by email at sales@onlyoffice.com + * + * The interactive user interfaces in modified source and object code versions of ONLYOFFICE must display + * Appropriate Legal Notices, as required under Section 5 of the GNU GPL version 3. + * + * Pursuant to Section 7 § 3(b) of the GNU GPL you must retain the original ONLYOFFICE logo which contains + * relevant author attributions when distributing the software. If the display of the logo in its graphic + * form is not reasonably feasible for technical reasons, you must include the words "Powered by ONLYOFFICE" + * in every copy of the program you distribute. + * Pursuant to Section 7 § 3(e) we decline to grant you any rights under trademark law for use of our trademarks. + * +*/ + + +#if (DEBUG) +namespace ASC.Notify.Textile +{ + using ASC.Notify.Messages; + using NUnit.Framework; + + [TestFixture] + public class StylerTests + { + private readonly string pattern = "h1.New Post in Forum Topic: \"==Project(%: \"Sample Title\"==\":\"==http://sssp.teamlab.com==\"" + System.Environment.NewLine + + "25/1/2022 \"Jim\":\"http://sssp.teamlab.com/myp.aspx\"" + System.Environment.NewLine + + "has created a new post in topic:" + System.Environment.NewLine + + "==- The text! ==" + System.Environment.NewLine + + "\"Read More\":\"http://sssp.teamlab.com/forum/post?id=4345\"" + System.Environment.NewLine + + "Your portal address: \"http://sssp.teamlab.com\":\"http://teamlab.com\" " + System.Environment.NewLine + + "\"Edit subscription settings\":\"http://sssp.teamlab.com/subscribe.aspx\""; + + [Test] + public void TestJabberStyler() + { + var message = new NoticeMessage() { Body = pattern }; + new JabberStyler().ApplyFormating(message); + } + + [Test] + public void TestTextileStyler() + { + var message = new NoticeMessage() { Body = pattern }; + new TextileStyler().ApplyFormating(message); + } + } +} +#endif \ No newline at end of file diff --git a/common/ASC.Notify.Textile/TextileStyler.cs b/common/ASC.Notify.Textile/TextileStyler.cs new file mode 100644 index 0000000000..05ed516b20 --- /dev/null +++ b/common/ASC.Notify.Textile/TextileStyler.cs @@ -0,0 +1,298 @@ +/* + * + * (c) Copyright Ascensio System Limited 2010-2018 + * + * This program is freeware. You can redistribute it and/or modify it under the terms of the GNU + * General Public License (GPL) version 3 as published by the Free Software Foundation (https://www.gnu.org/copyleft/gpl.html). + * In accordance with Section 7(a) of the GNU GPL its Section 15 shall be amended to the effect that + * Ascensio System SIA expressly excludes the warranty of non-infringement of any third-party rights. + * + * THIS PROGRAM IS DISTRIBUTED WITHOUT ANY WARRANTY; WITHOUT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY OR + * FITNESS FOR A PARTICULAR PURPOSE. For more details, see GNU GPL at https://www.gnu.org/copyleft/gpl.html + * + * You can contact Ascensio System SIA by email at sales@onlyoffice.com + * + * The interactive user interfaces in modified source and object code versions of ONLYOFFICE must display + * Appropriate Legal Notices, as required under Section 5 of the GNU GPL version 3. + * + * Pursuant to Section 7 § 3(b) of the GNU GPL you must retain the original ONLYOFFICE logo which contains + * relevant author attributions when distributing the software. If the display of the logo in its graphic + * form is not reasonably feasible for technical reasons, you must include the words "Powered by ONLYOFFICE" + * in every copy of the program you distribute. + * Pursuant to Section 7 § 3(e) we decline to grant you any rights under trademark law for use of our trademarks. + * +*/ + + +using System.Configuration; +using System.IO; +using System.Linq; +using System.Reflection; +using System.Text; +using System.Text.RegularExpressions; +using ASC.Common.Notify.Patterns; +using ASC.Core; +using ASC.Core.Common.WhiteLabel; +using ASC.Notify.Messages; +using ASC.Notify.Patterns; +using ASC.Notify.Textile.Resources; +using ASC.Web.Core.WhiteLabel; +using Microsoft.AspNetCore.WebUtilities; +using Textile; +using Textile.Blocks; + +namespace ASC.Notify.Textile +{ + public class TextileStyler : IPatternStyler + { + private static readonly Regex VelocityArguments = new Regex(NVelocityPatternFormatter.NoStylePreffix + "(?.*?)" + NVelocityPatternFormatter.NoStyleSuffix, RegexOptions.IgnoreCase | RegexOptions.Singleline | RegexOptions.Compiled); + + static TextileStyler() + { + const string file = "ASC.Notify.Textile.Resources.style.css"; + using var stream = Assembly.GetExecutingAssembly().GetManifestResourceStream(file); + using var reader = new StreamReader(stream); + BlockAttributesParser.Styler = new StyleReader(reader.ReadToEnd().Replace("\n", "").Replace("\r", "")); + } + + public void ApplyFormating(NoticeMessage message) + { + var output = new StringBuilderTextileFormatter(); + var formatter = new TextileFormatter(output); + + if (!string.IsNullOrEmpty(message.Subject)) + { + message.Subject = VelocityArguments.Replace(message.Subject, m => m.Result("${arg}")); + } + + if (string.IsNullOrEmpty(message.Body)) return; + + formatter.Format(message.Body); + + var template = GetTemplate(message); + var analytics = GetAnalytics(message); + var logoImg = GetLogoImg(message); + var logoText = GetLogoText(message); + var mailSettings = GetMailSettings(message); + var unsubscribeText = GetUnsubscribeText(message, mailSettings); + + + InitFooter(message, mailSettings, out var footerContent, out var footerSocialContent); + + message.Body = template.Replace("%ANALYTICS%", analytics) + .Replace("%CONTENT%", output.GetFormattedText()) + .Replace("%LOGO%", logoImg) + .Replace("%LOGOTEXT%", logoText) + .Replace("%SITEURL%", mailSettings == null ? MailWhiteLabelSettings.DefaultMailSiteUrl : mailSettings.SiteUrl) + .Replace("%FOOTER%", footerContent) + .Replace("%FOOTERSOCIAL%", footerSocialContent) + .Replace("%TEXTFOOTER%", unsubscribeText); + } + + private static string GetTemplate(NoticeMessage message) + { + var template = NotifyTemplateResource.HtmlMaster; + + var templateTag = message.GetArgument("MasterTemplate"); + if (templateTag != null) + { + var templateTagValue = templateTag.Value as string; + if (!string.IsNullOrEmpty(templateTagValue)) + { + var templateValue = NotifyTemplateResource.ResourceManager.GetString(templateTagValue); + if (!string.IsNullOrEmpty(templateValue)) + template = templateValue; + } + } + + return template; + } + + private static string GetAnalytics(NoticeMessage message) + { + var analyticsTag = message.GetArgument("Analytics"); + return analyticsTag == null ? string.Empty : (string)analyticsTag.Value; + } + + private static string GetLogoImg(NoticeMessage message) + { + string logoImg; + + if (CoreContext.Configuration.Personal && !CoreContext.Configuration.CustomMode) + { + logoImg = "https://static.onlyoffice.com/media/newsletters/images-v10/mail_logo.png"; + } + else + { + logoImg = ConfigurationManager.AppSettings["web.logo.mail"]; + if (string.IsNullOrEmpty(logoImg)) + { + var logo = message.GetArgument("LetterLogo"); + if (logo != null && (string)logo.Value != "") + { + logoImg = (string)logo.Value; + } + else + { + logoImg = "https://static.onlyoffice.com/media/newsletters/images-v10/mail_logo.png"; + } + } + } + + return logoImg; + } + + private static string GetLogoText(NoticeMessage message) + { + var logoText = ConfigurationManager.AppSettings["web.logotext.mail"]; + + if (string.IsNullOrEmpty(logoText)) + { + var llt = message.GetArgument("LetterLogoText"); + if (llt != null && (string)llt.Value != "") + { + logoText = (string)llt.Value; + } + else + { + logoText = BaseWhiteLabelSettings.DefaultLogoText; + } + } + + return logoText; + } + + private static MailWhiteLabelSettings GetMailSettings(NoticeMessage message) + { + var mailWhiteLabelTag = message.GetArgument("MailWhiteLabelSettings"); + return mailWhiteLabelTag == null ? null : mailWhiteLabelTag.Value as MailWhiteLabelSettings; + } + + private static void InitFooter(NoticeMessage message, MailWhiteLabelSettings settings, out string footerContent, out string footerSocialContent) + { + footerContent = string.Empty; + footerSocialContent = string.Empty; + + var footer = message.GetArgument("Footer"); + + if (footer == null) return; + + var footerValue = (string)footer.Value; + + if (string.IsNullOrEmpty(footerValue)) return; + + switch (footerValue) + { + case "common": + InitCommonFooter(settings, out footerContent, out footerSocialContent); + break; + case "social": + InitSocialFooter(settings, out footerSocialContent); + break; + case "personal": + footerSocialContent = NotifyTemplateResource.SocialNetworksFooter; + break; + case "personalCustomMode": + break; + case "opensource": + footerContent = NotifyTemplateResource.FooterOpensource; + footerSocialContent = NotifyTemplateResource.SocialNetworksFooter; + break; + } + } + + private static void InitCommonFooter(MailWhiteLabelSettings settings, out string footerContent, out string footerSocialContent) + { + footerContent = string.Empty; + footerSocialContent = string.Empty; + + if (settings == null) + { + footerContent = + NotifyTemplateResource.FooterCommon + .Replace("%SUPPORTURL%", MailWhiteLabelSettings.DefaultMailSupportUrl) + .Replace("%SALESEMAIL%", MailWhiteLabelSettings.DefaultMailSalesEmail) + .Replace("%DEMOURL%", MailWhiteLabelSettings.DefaultMailDemotUrl); + footerSocialContent = NotifyTemplateResource.SocialNetworksFooter; + + } + else if (settings.FooterEnabled) + { + footerContent = + NotifyTemplateResource.FooterCommon + .Replace("%SUPPORTURL%", string.IsNullOrEmpty(settings.SupportUrl) ? "mailto:" + settings.SalesEmail : settings.SupportUrl) + .Replace("%SALESEMAIL%", settings.SalesEmail) + .Replace("%DEMOURL%", string.IsNullOrEmpty(settings.DemotUrl) ? "mailto:" + settings.SalesEmail : settings.DemotUrl); + footerSocialContent = settings.FooterSocialEnabled ? NotifyTemplateResource.SocialNetworksFooter : string.Empty; + } + } + + private static void InitSocialFooter(MailWhiteLabelSettings settings, out string footerSocialContent) + { + footerSocialContent = string.Empty; + + if (settings == null || (settings.FooterEnabled && settings.FooterSocialEnabled)) + footerSocialContent = NotifyTemplateResource.SocialNetworksFooter; + } + + private static string GetUnsubscribeText(NoticeMessage message, MailWhiteLabelSettings settings) + { + var withoutUnsubscribe = message.GetArgument("WithoutUnsubscribe"); + + if (withoutUnsubscribe != null && (bool)withoutUnsubscribe.Value) + return string.Empty; + + var rootPathArgument = message.GetArgument("__VirtualRootPath"); + var rootPath = rootPathArgument == null ? string.Empty : (string)rootPathArgument.Value; + + if (string.IsNullOrEmpty(rootPath)) + return string.Empty; + + var unsubscribeLink = CoreContext.Configuration.CustomMode && CoreContext.Configuration.Personal + ? GetSiteUnsubscribeLink(message, settings) + : GetPortalUnsubscribeLink(message, settings); + + if (string.IsNullOrEmpty(unsubscribeLink)) + return string.Empty; + + return string.Format(NotifyTemplateResource.TextForFooterWithUnsubscribeLink, rootPath, unsubscribeLink); + } + + private static string GetPortalUnsubscribeLink(NoticeMessage message, MailWhiteLabelSettings settings) + { + var unsubscribeLinkArgument = message.GetArgument("ProfileUrl"); + + if (unsubscribeLinkArgument != null) + { + var unsubscribeLink = (string)unsubscribeLinkArgument.Value; + + if (!string.IsNullOrEmpty(unsubscribeLink)) + return unsubscribeLink; + } + + return GetSiteUnsubscribeLink(message, settings); + } + + private static string GetSiteUnsubscribeLink(NoticeMessage message, MailWhiteLabelSettings settings) + { + var mail = message.Recipient.Addresses.FirstOrDefault(r => r.Contains("@")); + + if (string.IsNullOrEmpty(mail)) + return string.Empty; + + var format = CoreContext.Configuration.CustomMode + ? "{0}/unsubscribe/{1}" + : "{0}/Unsubscribe.aspx?id={1}"; + + var site = settings == null + ? MailWhiteLabelSettings.DefaultMailSiteUrl + : settings.SiteUrl; + + return string.Format(format, + site, + WebEncoders.Base64UrlEncode( + Security.Cryptography.InstanceCrypto.Encrypt( + Encoding.UTF8.GetBytes(mail.ToLowerInvariant())))); + } + } +} \ No newline at end of file diff --git a/web/ASC.Web.Core/ASC.Web.Core.csproj b/web/ASC.Web.Core/ASC.Web.Core.csproj index 14c0d38163..2b0a3b33a2 100644 --- a/web/ASC.Web.Core/ASC.Web.Core.csproj +++ b/web/ASC.Web.Core/ASC.Web.Core.csproj @@ -22,6 +22,7 @@ + diff --git a/web/ASC.Web.Core/Utility/CommonLinkUtility.cs b/web/ASC.Web.Core/Utility/CommonLinkUtility.cs index b76d19c2d7..6915735fac 100644 --- a/web/ASC.Web.Core/Utility/CommonLinkUtility.cs +++ b/web/ASC.Web.Core/Utility/CommonLinkUtility.cs @@ -480,36 +480,7 @@ namespace ASC.Web.Studio.Utility public static string GetRegionalUrl(string url, string lang) { - if (string.IsNullOrEmpty(url)) - return url; - - //-replace language - var regex = new Regex("{.*?}"); - var matches = regex.Matches(url); - - if (string.IsNullOrEmpty(lang)) - { - url = matches.Cast().Aggregate(url, (current, match) => current.Replace(match.Value, string.Empty)); - } - else - { - foreach (Match match in matches) - { - var values = match.Value.TrimStart('{').TrimEnd('}').Split('|'); - url = url.Replace(match.Value, values.Contains(lang) ? lang : string.Empty); - } - } - //- - - //--remove redundant slashes - var uri = new Uri(url); - var baseUri = new UriBuilder(uri.Scheme, uri.Host, uri.Port).Uri; - baseUri = uri.Segments.Aggregate(baseUri, (current, segment) => new Uri(current, segment)); - //-- - //todo: lost query string!!! - - - return baseUri.ToString().TrimEnd('/'); + return BaseCommonLinkUtility.GetRegionalUrl(url, lang); } #endregion diff --git a/web/ASC.Web.Core/WhiteLabel/TenantWhiteLabelSettings.cs b/web/ASC.Web.Core/WhiteLabel/TenantWhiteLabelSettings.cs index b5a343f74b..68c76f5711 100644 --- a/web/ASC.Web.Core/WhiteLabel/TenantWhiteLabelSettings.cs +++ b/web/ASC.Web.Core/WhiteLabel/TenantWhiteLabelSettings.cs @@ -33,6 +33,7 @@ using System.Linq; using System.Runtime.Serialization; using ASC.Common.Logging; using ASC.Core.Common.Settings; +using ASC.Core.Common.WhiteLabel; using ASC.Data.Storage; using ASC.Web.Core.Users; using ASC.Web.Core.Utility.Skins; @@ -45,7 +46,7 @@ namespace ASC.Web.Core.WhiteLabel [DataContract] public class TenantWhiteLabelSettings : BaseSettings { - public const string DefaultLogoText = "ONLYOFFICE"; + public const string DefaultLogoText = BaseWhiteLabelSettings.DefaultLogoText; #region Logos information: extension, isDefault, text for img auto generating