Skip to content

Commit 74f6de6

Browse files
authored
Merge commit from fork
Add encoding variants to BaseCustomTokenReplace
2 parents 21f49f5 + 34290ec commit 74f6de6

File tree

14 files changed

+276
-138
lines changed

14 files changed

+276
-138
lines changed

DNN Platform/Library/DotNetNuke.Library.csproj

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -946,10 +946,13 @@
946946
<Compile Include="Services\Tokens\PropertyAccess\AntiForgeryTokenPropertyAccess.cs" />
947947
<Compile Include="Services\Tokens\PropertyAccess\ArrayListPropertyAccess.cs" />
948948
<Compile Include="Services\Tokens\PropertyAccess\CssPropertyAccess.cs" />
949+
<Compile Include="Services\Tokens\PropertyAccess\HtmlEncodingPropertyAccess.cs" />
949950
<Compile Include="Services\Tokens\PropertyAccess\JavaScriptDto.cs" />
951+
<Compile Include="Services\Tokens\PropertyAccess\JavaScriptEncodingPropertyAccess.cs" />
950952
<Compile Include="Services\Tokens\PropertyAccess\JavaScriptPropertyAccess.cs" />
951953
<Compile Include="Services\Tokens\PropertyAccess\JsonPropertyAccess.cs" />
952954
<Compile Include="Services\Tokens\PropertyAccess\StylesheetDto.cs" />
955+
<Compile Include="Services\Tokens\PropertyAccess\UrlEncodingPropertyAccess.cs" />
953956
<Compile Include="Services\Tokens\Scope.cs" />
954957
<Compile Include="Services\Tokens\CoreTokenProvider.cs" />
955958
<Compile Include="Services\Tokens\TokenContext.cs" />

DNN Platform/Library/Services/Tokens/BaseCustomTokenReplace.cs

Lines changed: 37 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -149,18 +149,18 @@ protected override string replacedTokenValue(string objectName, string propertyN
149149
{
150150
result = this.PropertySource[objectName.ToLowerInvariant()].GetProperty(propertyName, format, this.FormatProvider, this.AccessingUser, this.CurrentAccessLevel, ref propertyNotFound);
151151
}
152-
else
152+
else if (this.DebugMessages)
153153
{
154-
if (this.DebugMessages)
154+
string message = Localization.GetString(
155+
"TokenReplaceUnknownObject",
156+
Localization.SharedResourceFile,
157+
this.FormatProvider.ToString());
158+
if (message == string.Empty)
155159
{
156-
string message = Localization.GetString("TokenReplaceUnknownObject", Localization.SharedResourceFile, this.FormatProvider.ToString());
157-
if (message == string.Empty)
158-
{
159-
message = "Error accessing [{0}:{1}], {0} is an unknown datasource";
160-
}
161-
162-
result = string.Format(message, objectName, propertyName);
160+
message = "Error accessing [{0}:{1}], {0} is an unknown datasource";
163161
}
162+
163+
result = string.Format(message, objectName, propertyName);
164164
}
165165

166166
if (this.DebugMessages && propertyNotFound)
@@ -191,5 +191,33 @@ protected override string ReplaceTokens(string sourceText)
191191
{
192192
return this.Provider is CoreTokenProvider ? base.ReplaceTokens(sourceText) : this.Provider.Tokenize(sourceText, this.TokenContext);
193193
}
194+
195+
/// <summary>
196+
/// Adds the <paramref name="properties"/> with the given <paramref name="name"/> as a source for the token replace, by default HTML encoding its results.
197+
/// Additionally, provides derived sources to encode the results in a variety of ways.
198+
/// <list type="bullet">
199+
/// <item>name - HTML encoded output (e.g. <c>"</c> becomes <c>&quot;</c>)</item>
200+
/// <item>name_raw - Raw, unencoded output</item>
201+
/// <item>name_url - URL encoded output (e.g. <c>"</c> becomes <c>%22</c>)</item>
202+
/// <item>name_js - JavaScript string encoded output (e.g. <c>"</c> becomes <c>\"</c>)</item>
203+
/// </list>
204+
/// </summary>
205+
/// <param name="name">The base name of the source.</param>
206+
/// <param name="properties">The <see cref="IPropertyAccess"/> implementation.</param>
207+
protected void AddPropertySource(string name, IPropertyAccess properties)
208+
{
209+
this.PropertySource[name + "_raw"] = properties;
210+
this.PropertySource[name] = new HtmlEncodingPropertyAccess(properties);
211+
this.PropertySource[name + "_url"] = new UrlEncodingPropertyAccess(properties);
212+
this.PropertySource[name + "_js"] = new JavaScriptEncodingPropertyAccess(properties);
213+
}
214+
215+
/// <summary>Adds the <paramref name="properties"/> with the given <paramref name="name"/> as a source for the token replace.</summary>
216+
/// <param name="name">The name of the source.</param>
217+
/// <param name="properties">The <see cref="IPropertyAccess"/> implementation.</param>
218+
protected void AddRawPropertySource(string name, IPropertyAccess properties)
219+
{
220+
this.PropertySource[name] = properties;
221+
}
194222
}
195223
}

DNN Platform/Library/Services/Tokens/BaseTokenReplace.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ namespace DotNetNuke.Services.Tokens
1414

1515
/// <summary>
1616
/// The BaseTokenReplace class provides the tokenization of tokens formatted
17-
/// [object:property] or [object:property|format|ifEmpty] or [custom:no] within a string
17+
/// <c>[object:property]</c> or <c>[object:property|format|ifEmpty]</c> or <c>[custom:no]</c> within a string
1818
/// with the appropriate current property/custom values.
1919
/// </summary>
2020
public abstract class BaseTokenReplace
@@ -102,11 +102,11 @@ protected virtual string ReplaceTokens(string sourceText)
102102

103103
string propertyName = currentMatch.Result("${property}");
104104
string format = currentMatch.Result("${format}");
105-
string ifEmptyReplacment = currentMatch.Result("${ifEmpty}");
105+
string ifEmptyReplacement = currentMatch.Result("${ifEmpty}");
106106
string conversion = this.replacedTokenValue(objectName, propertyName, format);
107-
if (!string.IsNullOrEmpty(ifEmptyReplacment) && string.IsNullOrEmpty(conversion))
107+
if (!string.IsNullOrEmpty(ifEmptyReplacement) && string.IsNullOrEmpty(conversion))
108108
{
109-
conversion = ifEmptyReplacment;
109+
conversion = ifEmptyReplacement;
110110
}
111111

112112
result.Append(conversion);

DNN Platform/Library/Services/Tokens/HtmlTokenReplace.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,10 @@ public class HtmlTokenReplace : TokenReplace
1212
public HtmlTokenReplace(Page page)
1313
: base(Scope.DefaultSettings)
1414
{
15-
this.PropertySource["css"] = new CssPropertyAccess(page);
16-
this.PropertySource["js"] = new JavaScriptPropertyAccess(page);
17-
this.PropertySource["javascript"] = new JavaScriptPropertyAccess(page);
18-
this.PropertySource["antiforgerytoken"] = new AntiForgeryTokenPropertyAccess();
15+
this.AddPropertySource("css", new CssPropertyAccess(page));
16+
this.AddPropertySource("js", new JavaScriptPropertyAccess(page));
17+
this.AddPropertySource("javascript", new JavaScriptPropertyAccess(page));
18+
this.AddPropertySource("antiforgerytoken", new AntiForgeryTokenPropertyAccess());
1919
}
2020
}
2121
}
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
// See the LICENSE file in the project root for more information
4+
5+
namespace DotNetNuke.Services.Tokens;
6+
7+
using System.Globalization;
8+
using System.Net;
9+
10+
using DotNetNuke.Entities.Users;
11+
12+
/// <summary>An <see cref="IPropertyAccess"/> implementation that wraps an existing <see cref="IPropertyAccess"/>, HTML encoding its result.</summary>
13+
/// <param name="implementation">The <see cref="IPropertyAccess"/> implementation that is being wrapped.</param>
14+
public class HtmlEncodingPropertyAccess(IPropertyAccess implementation) : IPropertyAccess
15+
{
16+
/// <inheritdoc />
17+
public CacheLevel Cacheability
18+
{
19+
get => implementation.Cacheability;
20+
}
21+
22+
/// <inheritdoc />
23+
public string GetProperty(
24+
string propertyName,
25+
string format,
26+
CultureInfo formatProvider,
27+
UserInfo accessingUser,
28+
Scope accessLevel,
29+
ref bool propertyNotFound)
30+
{
31+
var result = implementation.GetProperty(
32+
propertyName,
33+
format,
34+
formatProvider,
35+
accessingUser,
36+
accessLevel,
37+
ref propertyNotFound);
38+
39+
return WebUtility.HtmlEncode(result);
40+
}
41+
}
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
// See the LICENSE file in the project root for more information
4+
5+
namespace DotNetNuke.Services.Tokens;
6+
7+
using System.Globalization;
8+
using System.Net;
9+
using System.Web;
10+
using System.Web.Util;
11+
12+
using DotNetNuke.Entities.Users;
13+
14+
/// <summary>An <see cref="IPropertyAccess"/> implementation that wraps an existing <see cref="IPropertyAccess"/>, JavaScript string encoding its result.</summary>
15+
/// <param name="implementation">The <see cref="IPropertyAccess"/> implementation that is being wrapped.</param>
16+
public class JavaScriptEncodingPropertyAccess(IPropertyAccess implementation) : IPropertyAccess
17+
{
18+
/// <inheritdoc />
19+
public CacheLevel Cacheability
20+
{
21+
get => implementation.Cacheability;
22+
}
23+
24+
/// <inheritdoc />
25+
public string GetProperty(
26+
string propertyName,
27+
string format,
28+
CultureInfo formatProvider,
29+
UserInfo accessingUser,
30+
Scope accessLevel,
31+
ref bool propertyNotFound)
32+
{
33+
var result = implementation.GetProperty(
34+
propertyName,
35+
format,
36+
formatProvider,
37+
accessingUser,
38+
accessLevel,
39+
ref propertyNotFound);
40+
41+
return HttpUtility.JavaScriptStringEncode(result);
42+
}
43+
}
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
// See the LICENSE file in the project root for more information
4+
5+
namespace DotNetNuke.Services.Tokens;
6+
7+
using System.Globalization;
8+
using System.Net;
9+
10+
using DotNetNuke.Entities.Users;
11+
12+
/// <summary>An <see cref="IPropertyAccess"/> implementation that wraps an existing <see cref="IPropertyAccess"/>, URL encoding its result.</summary>
13+
/// <param name="implementation">The <see cref="IPropertyAccess"/> implementation that is being wrapped.</param>
14+
public class UrlEncodingPropertyAccess(IPropertyAccess implementation) : IPropertyAccess
15+
{
16+
/// <inheritdoc />
17+
public CacheLevel Cacheability
18+
{
19+
get => implementation.Cacheability;
20+
}
21+
22+
/// <inheritdoc />
23+
public string GetProperty(
24+
string propertyName,
25+
string format,
26+
CultureInfo formatProvider,
27+
UserInfo accessingUser,
28+
Scope accessLevel,
29+
ref bool propertyNotFound)
30+
{
31+
var result = implementation.GetProperty(
32+
propertyName,
33+
format,
34+
formatProvider,
35+
accessingUser,
36+
accessLevel,
37+
ref propertyNotFound);
38+
39+
return WebUtility.UrlEncode(result);
40+
}
41+
}

DNN Platform/Library/Services/Tokens/TokenContext.cs

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,30 @@
11
// Licensed to the .NET Foundation under one or more agreements.
22
// The .NET Foundation licenses this file to you under the MIT license.
33
// See the LICENSE file in the project root for more information
4-
namespace DotNetNuke.Services.Tokens
4+
namespace DotNetNuke.Services.Tokens
55
{
66
using System.Collections.Generic;
77
using System.Globalization;
8-
using System.Threading;
8+
using System.Threading;
99

1010
using DotNetNuke.Entities.Modules;
1111
using DotNetNuke.Entities.Portals;
1212
using DotNetNuke.Entities.Tabs;
1313
using DotNetNuke.Entities.Users;
14-
14+
1515
/// <summary>The context in which tokenization should happen.</summary>
16-
public class TokenContext
16+
public class TokenContext
1717
{
1818
/// <summary>Gets or sets the user object representing the currently accessing user (permission).</summary>
19-
/// <value>UserInfo oject.</value>
19+
/// <value>UserInfo object.</value>
2020
public UserInfo AccessingUser { get; set; }
2121

2222
/// <summary>Gets or sets the user object to use for 'User:' token replacement.</summary>
23-
/// <value>UserInfo oject.</value>
23+
/// <value>UserInfo object.</value>
2424
public UserInfo User { get; set; }
2525

2626
/// <summary>Gets or sets the portal settings object to use for 'Portal:' token replacement.</summary>
27-
/// <value>PortalSettings oject.</value>
27+
/// <value>PortalSettings object.</value>
2828
public PortalSettings Portal { get; set; }
2929

3030
/// <summary>Gets or sets the tab settings object to use for 'Tab:' token replacement.</summary>
@@ -34,11 +34,11 @@ public class TokenContext
3434
public ModuleInfo Module { get; set; }
3535

3636
/// <summary>Gets or sets the Format provider as Culture info from stored language or current culture.</summary>
37-
/// <value>An CultureInfo.</value>
37+
/// <value>An CultureInfo.</value>
3838
public CultureInfo Language { get; set; } = Thread.CurrentThread.CurrentUICulture;
3939

4040
/// <summary>Gets or sets the current Access Level controlling access to critical user settings.</summary>
41-
/// <value>A TokenAccessLevel as defined above.</value>
41+
/// <value>A TokenAccessLevel as defined above.</value>
4242
public Scope CurrentAccessLevel { get; set; }
4343

4444
/// <summary>Gets or sets a value indicating whether if DebugMessages are enabled, unknown Tokens are replaced with Error Messages.</summary>

0 commit comments

Comments
 (0)