Added ASC.Notify.Textile

This commit is contained in:
pavelbannov 2019-08-19 16:51:36 +03:00
parent 451bcaea1a
commit 8c8b844a70
14 changed files with 1030 additions and 37 deletions

View File

@ -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

View File

@ -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<Match>().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('/');
}
}
}

View File

@ -0,0 +1,7 @@
namespace ASC.Core.Common.WhiteLabel
{
public class BaseWhiteLabelSettings
{
public const string DefaultLogoText = "ONLYOFFICE";
}
}

View File

@ -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";
}
}

View File

@ -0,0 +1,30 @@
<Project Sdk="Microsoft.NET.Sdk.Web" ToolsVersion="Current">
<PropertyGroup>
<ProductVersion>9.0.30729</ProductVersion>
<TargetFramework>netcoreapp3.0</TargetFramework>
<FileUpgradeFlags>
</FileUpgradeFlags>
<UpgradeBackupLocation>
</UpgradeBackupLocation>
<AssemblyTitle>ASC.Notify.Textile</AssemblyTitle>
<Company>Ascensio System SIA</Company>
<Product>ASC.Notify.Textile</Product>
<Copyright>(c) Ascensio System SIA. All rights reserved</Copyright>
<AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
<ApplicationIcon />
<OutputType>Library</OutputType>
<StartupObject />
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugType>full</DebugType>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>none</DebugType>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\ASC.Common\ASC.Common.csproj" />
<ProjectReference Include="..\ASC.Core.Common\ASC.Core.Common.csproj" />
<ProjectReference Include="..\ASC.Textile\ASC.Textile.csproj" />
</ItemGroup>
</Project>

View File

@ -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 + "(?<arg>.*?)" + NVelocityPatternFormatter.NoStyleSuffix, RegexOptions.IgnoreCase | RegexOptions.Singleline | RegexOptions.Compiled);
static readonly Regex LinkReplacer = new Regex(@"""(?<text>[\w\W]+?)"":""(?<link>[^""]+)""", RegexOptions.Singleline | RegexOptions.Compiled);
static readonly Regex TextileReplacer = new Regex(@"(h1\.|h2\.|\*|h3\.|\^)", RegexOptions.Singleline | RegexOptions.Compiled);
static readonly Regex BrReplacer = new Regex(@"<br\s*\/*>", RegexOptions.IgnoreCase | RegexOptions.CultureInvariant | RegexOptions.IgnorePatternWhitespace | RegexOptions.Compiled | RegexOptions.Singleline);
static readonly Regex ClosedTagsReplacer = new Regex(@"</(p|div)>", 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}");
}
}
}

View File

@ -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();
}
}
}
}

View File

@ -0,0 +1,138 @@
//------------------------------------------------------------------------------
// <auto-generated>
// 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.
// </auto-generated>
//------------------------------------------------------------------------------
namespace ASC.Notify.Textile.Resources {
using System;
/// <summary>
/// A strongly-typed resource class, for looking up localized strings, etc.
/// </summary>
// 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() {
}
/// <summary>
/// Returns the cached ResourceManager instance used by this class.
/// </summary>
[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;
}
}
/// <summary>
/// Overrides the current thread's CurrentUICulture property for all
/// resource lookups using this strongly typed resource class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
public static global::System.Globalization.CultureInfo Culture {
get {
return resourceCulture;
}
set {
resourceCulture = value;
}
}
/// <summary>
/// Looks up a localized string similar to &lt;tr border=&quot;0&quot; cellspacing=&quot;0&quot; cellpadding=&quot;0&quot;&gt;&lt;td colspan=&quot;3&quot; style=&quot;height: 10px; line-height: 10px; background: #fff; padding: 0; margin: 0;&quot;&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
/// &lt;tr border=&quot;0&quot; cellspacing=&quot;0&quot; cellpadding=&quot;0&quot;&gt;
/// &lt;td style=&quot;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;&quot;&gt;
/// &lt;img src=&quot;https://static.onlyoffice.com/media/news [rest of string was truncated]&quot;;.
/// </summary>
public static string FooterCommon {
get {
return ResourceManager.GetString("FooterCommon", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to &lt;tr border=&quot;0&quot; cellspacing=&quot;0&quot; cellpadding=&quot;0&quot;&gt;&lt;td colspan=&quot;3&quot; style=&quot;height: 10px; line-height: 10px; background: #fff; padding: 0; margin: 0;&quot;&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
/// &lt;tr border=&quot;0&quot; cellspacing=&quot;0&quot; cellpadding=&quot;0&quot;&gt;
/// &lt;td style=&quot;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;&quot;&gt;
/// &lt;img src=&quot;https://static.onlyoffice.com/media/news [rest of string was truncated]&quot;;.
/// </summary>
public static string FooterOpensource {
get {
return ResourceManager.GetString("FooterOpensource", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to &lt;body style=&quot;margin: 0; padding: 0; text-align: center; width: 100%; font-family: Arial, sans-serif; font-size: 14px; color: #333;&quot;&gt;
///%ANALYTICS%
///&lt;div style=&quot;background-color: #fff; width: 600px; margin: 0 auto; text-align: left;&quot;&gt;
/// &lt;table cellspacing=&quot;0&quot; cellpadding=&quot;0&quot; style=&quot;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;&quot;&gt;
/// &lt;tbody&gt;
/// [rest of string was truncated]&quot;;.
/// </summary>
public static string HtmlMaster {
get {
return ResourceManager.GetString("HtmlMaster", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to &lt;body style=&quot;margin: 0; padding: 0; text-align: center; width: 100%; font-family: Arial, sans-serif; font-size: 14px; color: #333;&quot;&gt;
///%ANALYTICS%
///&lt;div style=&quot;background-color: #fff; width: 600px; margin: 0 auto; text-align: left;&quot;&gt;
/// &lt;table cellspacing=&quot;0&quot; cellpadding=&quot;0&quot; style=&quot;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;&quot;&gt;
/// &lt;tbody&gt;
/// [rest of string was truncated]&quot;;.
/// </summary>
public static string HtmlMasterPersonal {
get {
return ResourceManager.GetString("HtmlMasterPersonal", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to &lt;tr border=&quot;0&quot; cellspacing=&quot;0&quot; cellpadding=&quot;0&quot;&gt;
/// &lt;td style=&quot;width: 40px; vertical-align: top; margin: 0; padding: 22px 5px 0 155px;&quot;&gt;
/// &lt;a href=&quot;https://www.facebook.com/pages/OnlyOffice/833032526736775&quot; style=&quot;width: 40px; height: 40px; display: block; margin: 0; padding: 0;&quot; target=&quot;_blank&quot;&gt;
/// &lt;img src=&quot;https://static.onlyoffice.com/media/newsletters/images-v10/social-fb-40.png&quot; alt=&quot;Facebook&quot; style=&quot;width: 40px; height: 40px;&quot; /&gt;
/// &lt;/a&gt;
/// &lt;/td [rest of string was truncated]&quot;;.
/// </summary>
public static string SocialNetworksFooter {
get {
return ResourceManager.GetString("SocialNetworksFooter", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to You received this message because you are a registered user of the &lt;a href=&quot;{0}&quot; style=&quot;color: #7b7b7b;&quot; target=&quot;_blank&quot;&gt;{0}&lt;/a&gt;. &lt;a href=&quot;{1}&quot; style=&quot;color: #7b7b7b;&quot; target=&quot;_blank&quot;&gt;Unsubscribe&lt;/a&gt;.
/// </summary>
public static string TextForFooterWithUnsubscribeLink {
get {
return ResourceManager.GetString("TextForFooterWithUnsubscribeLink", resourceCulture);
}
}
}
}

View File

@ -0,0 +1,300 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="FooterCommon" xml:space="preserve">
<value>&lt;tr border="0" cellspacing="0" cellpadding="0"&gt;&lt;td colspan="3" style="height: 10px; line-height: 10px; background: #fff; padding: 0; margin: 0;"&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
&lt;tr border="0" cellspacing="0" cellpadding="0"&gt;
&lt;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;"&gt;
&lt;img src="https://static.onlyoffice.com/media/newsletters/images-v10/tech-100.png" style="width: 100px; height: 100px;margin: 0 auto;" /&gt;
&lt;/td&gt;
&lt;td style="vertical-align: top; margin: 0; padding: 34px 0 0 0; width: 180px; height: 108px; background: #f6f6f6;"&gt;
&lt;img src="https://static.onlyoffice.com/media/newsletters/images-v10/mailus-100.png" style="width: 100px; height: 100px;margin: 0 auto;" /&gt;
&lt;/td&gt;
&lt;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;"&gt;
&lt;img src="https://static.onlyoffice.com/media/newsletters/images-v10/demo-100.png" style="width: 100px; height: 100px;margin: 0 auto;" /&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr border="0" cellspacing="0" cellpadding="0"&gt;
&lt;td style="vertical-align: top; margin: 0; padding: 0; width: 210px; height: 16px; background: #f6f6f6;"&gt;Need tech help?&lt;/td&gt;
&lt;td style="vertical-align: top; margin: 0; padding: 0; width: 180px; height: 16px; background: #f6f6f6;"&gt;Sales Questions&lt;/td&gt;
&lt;td style="vertical-align: top; margin: 0; padding: 0; width: 210px; height: 16px; background: #f6f6f6;"&gt;Order Demo&lt;/td&gt;
&lt;/tr&gt;
&lt;tr border="0" cellspacing="0" cellpadding="0"&gt;
&lt;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;"&gt;
&lt;a href="%SUPPORTURL%" target="_blank" style="color: #333;"&gt;Send your question&lt;/a&gt;
&lt;/td&gt;
&lt;td style="vertical-align: top; margin: 0; padding: 0 0 30px; width: 180px; background: #f6f6f6;"&gt;
&lt;a href="mailto:%SALESEMAIL%" style="color: #333;"&gt;Email us&lt;/a&gt;
&lt;/td&gt;
&lt;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;"&gt;
&lt;a href="%DEMOURL%" target="_blank" style="color: #333;"&gt;Send a request&lt;/a&gt;
&lt;/td&gt;
&lt;/tr&gt;</value>
</data>
<data name="FooterOpensource" xml:space="preserve">
<value>&lt;tr border="0" cellspacing="0" cellpadding="0"&gt;&lt;td colspan="3" style="height: 10px; line-height: 10px; background: #fff; padding: 0; margin: 0;"&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
&lt;tr border="0" cellspacing="0" cellpadding="0"&gt;
&lt;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;"&gt;
&lt;img src="https://static.onlyoffice.com/media/newsletters/images-v10/tech-100.png" style="width: 100px; height: 100px;margin: 0 auto;" /&gt;
&lt;/td&gt;
&lt;td style="vertical-align: top; margin: 0; padding: 34px 0 0 0; width: 180px; height: 108px; background: #f6f6f6;"&gt;
&lt;img src="https://static.onlyoffice.com/media/newsletters/images-v10/mailus-100.png" style="width: 100px; height: 100px;margin: 0 auto;" /&gt;
&lt;/td&gt;
&lt;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;"&gt;
&lt;img src="https://static.onlyoffice.com/media/newsletters/images-v10/demo-100.png" style="width: 100px; height: 100px;margin: 0 auto;" /&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr border="0" cellspacing="0" cellpadding="0"&gt;
&lt;td style="vertical-align: top; margin: 0; padding: 0; width: 210px; height: 16px; background: #f6f6f6;"&gt;Need tech help?&lt;/td&gt;
&lt;td style="vertical-align: top; margin: 0; padding: 0; width: 180px; height: 16px; background: #f6f6f6;"&gt;Sales Questions&lt;/td&gt;
&lt;td style="vertical-align: top; margin: 0; padding: 0; width: 210px; height: 16px; background: #f6f6f6;"&gt;Order Demo&lt;/td&gt;
&lt;/tr&gt;
&lt;tr border="0" cellspacing="0" cellpadding="0"&gt;
&lt;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;"&gt;
&lt;a href="http://dev.onlyoffice.org/" target="_blank" style="color: #333;"&gt;Ask the Community&lt;/a&gt;
&lt;/td&gt;
&lt;td style="vertical-align: top; margin: 0; padding: 0 0 30px; width: 180px; background: #f6f6f6;"&gt;
&lt;a href="mailto:sales@onlyoffice.com" style="color: #333;"&gt;Email us&lt;/a&gt;
&lt;/td&gt;
&lt;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;"&gt;
&lt;a href="http://www.onlyoffice.com/demo-order.aspx" target="_blank" style="color: #333;"&gt;Send a request&lt;/a&gt;
&lt;/td&gt;
&lt;/tr&gt;</value>
</data>
<data name="HtmlMaster" xml:space="preserve">
<value>&lt;body style="margin: 0; padding: 0; text-align: center; width: 100%; font-family: Arial, sans-serif; font-size: 14px; color: #333;"&gt;
%ANALYTICS%
&lt;div style="background-color: #fff; width: 600px; margin: 0 auto; text-align: left;"&gt;
&lt;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;"&gt;
&lt;tbody&gt;
&lt;tr border="0" cellspacing="0" cellpadding="0"&gt;
&lt;td colspan="3" style="margin: 0; padding: 0; background-color: #fff; height: 65px; padding: 20px 0 0 30px;"&gt;
&lt;div style="text-align: left; height: 65px; width: 570px; margin: 0; padding: 0;"&gt;
&lt;a href="%SITEURL%" style="text-decoration: none; display: inline-block; width: 216px; height: 35px; margin: 0; padding: 0;" target="_blank"&gt;
&lt;img src="%LOGO%" style="border: 0px none; width: 216px; height: 35px; margin: 0; padding: 0;" alt="%LOGOTEXT%" /&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr border="0" cellspacing="0" cellpadding="0"&gt;
&lt;td colspan="3" style="margin: 0; padding: 15px 30px 15px; background-color: #f6f6f6; -moz-border-radius: 6px; -webkit-border-radius: 6px; border-radius: 6px;"&gt;
&lt;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;"&gt;
%CONTENT%
&lt;/div&gt;
&lt;/td&gt;
&lt;/tr&gt;
%FOOTER%
&lt;/tbody&gt;
&lt;/table&gt;
&lt;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; "&gt;
&lt;tbody&gt;
%FOOTERSOCIAL%
&lt;tr border="0" cellspacing="0" cellpadding="0"&gt;
&lt;td colspan="6" style="width: 600px; vertical-align: top; margin: 0; padding: 20px 30px 15px;"&gt;
&lt;p style="color: #7b7b7b; font-family: Arial, Tahoma; font-size: 12px; margin: 0; padding: 0; text-align: center; width: 540px;"&gt;
%TEXTFOOTER%
&lt;/p&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;/body&gt;</value>
</data>
<data name="HtmlMasterPersonal" xml:space="preserve">
<value>&lt;body style="margin: 0; padding: 0; text-align: center; width: 100%; font-family: Arial, sans-serif; font-size: 14px; color: #333;"&gt;
%ANALYTICS%
&lt;div style="background-color: #fff; width: 600px; margin: 0 auto; text-align: left;"&gt;
&lt;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;"&gt;
&lt;tbody&gt;
&lt;tr border="0" cellspacing="0" cellpadding="0"&gt;
&lt;td colspan="3" style="margin: 0; padding: 0; background-color: #fff; height: 65px; padding: 20px 0 0 30px;"&gt;
&lt;div style="text-align: left; height: 65px; width: 570px; margin: 0; padding: 0;"&gt;
&lt;a href="%SITEURL%" style="text-decoration: none; display: inline-block; width: 216px; height: 35px; margin: 0; padding: 0;" target="_blank"&gt;
&lt;img src="%LOGO%" style="border: 0px none; width: 216px; height: 35px; margin: 0; padding: 0;" alt="%LOGOTEXT%" /&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr border="0" cellspacing="0" cellpadding="0"&gt;
&lt;td colspan="3" style="margin: 0; padding: 0; background-color: #f6f6f6; -moz-border-radius: 6px; -webkit-border-radius: 6px; border-radius: 6px;"&gt;
&lt;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;"&gt;&lt;/div&gt;
&lt;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;"&gt;
%CONTENT%
&lt;/div&gt;
&lt;/td&gt;
&lt;/tr&gt;
%FOOTER%
&lt;/tbody&gt;
&lt;/table&gt;
&lt;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; "&gt;
&lt;tbody&gt;
%FOOTERSOCIAL%
&lt;tr border="0" cellspacing="0" cellpadding="0"&gt;
&lt;td colspan="6" style="width: 600px; vertical-align: top; margin: 0; padding: 20px 30px 15px;"&gt;
&lt;p style="color: #7b7b7b; font-family: Arial, Tahoma; font-size: 12px; margin: 0; padding: 0; text-align: center; width: 540px;"&gt;
%TEXTFOOTER%
&lt;/p&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;/body&gt;</value>
</data>
<data name="SocialNetworksFooter" xml:space="preserve">
<value>&lt;tr border="0" cellspacing="0" cellpadding="0"&gt;
&lt;td style="width: 40px; vertical-align: top; margin: 0; padding: 22px 5px 0 155px;"&gt;
&lt;a href="https://www.facebook.com/pages/OnlyOffice/833032526736775" style="width: 40px; height: 40px; display: block; margin: 0; padding: 0;" target="_blank"&gt;
&lt;img src="https://static.onlyoffice.com/media/newsletters/images-v10/social-fb-40.png" alt="Facebook" style="width: 40px; height: 40px;" /&gt;
&lt;/a&gt;
&lt;/td&gt;
&lt;td style="width: 40px; vertical-align: top; margin: 0; padding: 22px 5px 0 5px;"&gt;
&lt;a href="https://twitter.com/ONLY_OFFICE" style="width: 40px; height: 40px; display: block; margin: 0; padding: 0;" target="_blank"&gt;
&lt;img src="https://static.onlyoffice.com/media/newsletters/images-v10/social-tw-40.png" alt="Twitter" style="width: 40px; height: 40px;" /&gt;
&lt;/a&gt;
&lt;/td&gt;
&lt;td style="width: 40px; vertical-align: top; margin: 0; padding: 22px 5px 0 5px;"&gt;
&lt;a href="https://www.onlyoffice.com/blog" style="width: 40px; height: 40px; display: block; margin: 0; padding: 0;" target="_blank"&gt;
&lt;img src="https://static.onlyoffice.com/media/newsletters/images-v10/social-blog-40.png" alt="ONLYOFFICE" style="width: 40px; height: 40px;" /&gt;
&lt;/a&gt;
&lt;/td&gt;
&lt;td style="width: 40px; vertical-align: top; margin: 0; padding: 22px 5px 0 5px;"&gt;
&lt;a href="https://www.youtube.com/user/onlyofficeTV" style="width: 40px; height: 40px; display: block; margin: 0; padding: 0;" target="_blank"&gt;
&lt;img src="https://static.onlyoffice.com/media/newsletters/images-v10/social-youtube-40.png" alt="YouTube" style="width: 40px; height: 40x;" /&gt;
&lt;/a&gt;
&lt;/td&gt;
&lt;td style="width: 40px; vertical-align: top; margin: 0; padding: 22px 5px 0 5px;"&gt;
&lt;a href="https://vk.com/onlyoffice" style="width: 40px; height: 40px; display: block; margin: 0; padding: 0;" target="_blank"&gt;
&lt;img src="https://static.onlyoffice.com/media/newsletters/images-v10/social-vk-40.png" alt="VK" style="width: 40px; height: 40px;" /&gt;
&lt;/a&gt;
&lt;/td&gt;
&lt;td style="width: 40px; vertical-align: top; margin: 0; padding: 22px 155px 0 5px;"&gt;
&lt;a href="https://www.instagram.com/the_onlyoffice" style="width: 40px; height: 40px; display: block; margin: 0; padding: 0;" target="_blank"&gt;
&lt;img src="https://static.onlyoffice.com/media/newsletters/images-v10/social-inst-40.png" alt="Instagram" style="width: 40px; height: 40px;" /&gt;
&lt;/a&gt;
&lt;/td&gt;
&lt;/tr&gt;</value>
</data>
<data name="TextForFooterWithUnsubscribeLink" xml:space="preserve">
<value>You received this message because you are a registered user of the &lt;a href="{0}" style="color: #7b7b7b;" target="_blank"&gt;{0}&lt;/a&gt;. &lt;a href="{1}" style="color: #7b7b7b;" target="_blank"&gt;Unsubscribe&lt;/a&gt;</value>
</data>
</root>

View File

@ -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 +
"==<b>- The text!&nbsp;</b>==" + 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

View File

@ -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 + "(?<arg>.*?)" + 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()))));
}
}
}

View File

@ -22,6 +22,7 @@
<ProjectReference Include="..\..\common\ASC.Feed\ASC.Feed.csproj" />
<ProjectReference Include="..\..\common\ASC.IPSecurity\ASC.IPSecurity.csproj" />
<ProjectReference Include="..\..\common\ASC.MessagingSystem\ASC.MessagingSystem.csproj" />
<ProjectReference Include="..\..\common\ASC.Notify.Textile\ASC.Notify.Textile.csproj" />
<ProjectReference Include="..\..\common\ASC.VoipService\ASC.VoipService.csproj" />
</ItemGroup>

View File

@ -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<Match>().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

View File

@ -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<TenantWhiteLabelSettings>
{
public const string DefaultLogoText = "ONLYOFFICE";
public const string DefaultLogoText = BaseWhiteLabelSettings.DefaultLogoText;
#region Logos information: extension, isDefault, text for img auto generating