@@ -13,7 +13,7 @@ | |||||
<description>MQTTnet is a high performance .NET library for MQTT based communication. It provides a MQTT client and a MQTT server (broker) and supports v3.1.0, v3.1.1 and v5.0.0 of the MQTT protocol.</description> | <description>MQTTnet is a high performance .NET library for MQTT based communication. It provides a MQTT client and a MQTT server (broker) and supports v3.1.0, v3.1.1 and v5.0.0 of the MQTT protocol.</description> | ||||
<releaseNotes> | <releaseNotes> | ||||
* [MQTTnet.Server] Moved server project to a dedicated GitHub repository. | * [MQTTnet.Server] Moved server project to a dedicated GitHub repository. | ||||
* [MQTTnet, MQTTnet.Extensions.ManagedClient] Fixed bug that allowed invalid subscriptions (Thanks to @marcelwinh). | |||||
Git commit: $gitCommit | Git commit: $gitCommit | ||||
</releaseNotes> | </releaseNotes> | ||||
<copyright>Copyright Christian Kratky 2016-2020</copyright> | <copyright>Copyright Christian Kratky 2016-2020</copyright> | ||||
@@ -215,6 +215,11 @@ namespace MQTTnet.Extensions.ManagedClient | |||||
if (topicFilters == null) throw new ArgumentNullException(nameof(topicFilters)); | if (topicFilters == null) throw new ArgumentNullException(nameof(topicFilters)); | ||||
foreach (var topicFilter in topicFilters) | |||||
{ | |||||
MqttTopicValidator.ThrowIfInvalidSubscribe(topicFilter.Topic); | |||||
} | |||||
lock (_subscriptions) | lock (_subscriptions) | ||||
{ | { | ||||
foreach (var topicFilter in topicFilters) | foreach (var topicFilter in topicFilters) | ||||
@@ -194,6 +194,11 @@ namespace MQTTnet.Client | |||||
{ | { | ||||
if (options == null) throw new ArgumentNullException(nameof(options)); | if (options == null) throw new ArgumentNullException(nameof(options)); | ||||
foreach (var topicFilter in options.TopicFilters) | |||||
{ | |||||
MqttTopicValidator.ThrowIfInvalidSubscribe(topicFilter.Topic); | |||||
} | |||||
ThrowIfDisposed(); | ThrowIfDisposed(); | ||||
ThrowIfNotConnected(); | ThrowIfNotConnected(); | ||||
@@ -42,5 +42,15 @@ namespace MQTTnet.Protocol | |||||
} | } | ||||
} | } | ||||
} | } | ||||
public static void ThrowIfInvalidSubscribe(string topic) | |||||
{ | |||||
if (string.IsNullOrEmpty(topic)) | |||||
{ | |||||
throw new MqttProtocolViolationException("Topic should not be empty."); | |||||
} | |||||
if (topic.IndexOf("#") != -1 && topic.IndexOf("#") != topic.Length - 1) throw new MqttProtocolViolationException("The character '#' is only allowed as last character"); | |||||
} | |||||
} | } | ||||
} | } |
@@ -113,7 +113,12 @@ namespace MQTTnet.Server | |||||
{ | { | ||||
if (clientId == null) throw new ArgumentNullException(nameof(clientId)); | if (clientId == null) throw new ArgumentNullException(nameof(clientId)); | ||||
if (topicFilters == null) throw new ArgumentNullException(nameof(topicFilters)); | if (topicFilters == null) throw new ArgumentNullException(nameof(topicFilters)); | ||||
foreach (var topicFilter in topicFilters) | |||||
{ | |||||
MqttTopicValidator.ThrowIfInvalidSubscribe(topicFilter.Topic); | |||||
} | |||||
ThrowIfDisposed(); | ThrowIfDisposed(); | ||||
ThrowIfNotStarted(); | ThrowIfNotStarted(); | ||||
@@ -0,0 +1,54 @@ | |||||
using Microsoft.VisualStudio.TestTools.UnitTesting; | |||||
using MQTTnet.Exceptions; | |||||
using MQTTnet.Protocol; | |||||
namespace MQTTnet.Tests | |||||
{ | |||||
[TestClass] | |||||
public class MqttTopicValidatorSubscribe_Tests | |||||
{ | |||||
[TestMethod] | |||||
public void Valid_Topic() | |||||
{ | |||||
MqttTopicValidator.ThrowIfInvalidSubscribe("/a/b/c"); | |||||
} | |||||
[TestMethod] | |||||
public void Valid_Topic_Plus_In_Between() | |||||
{ | |||||
MqttTopicValidator.ThrowIfInvalidSubscribe("/a/+/c"); | |||||
} | |||||
[TestMethod] | |||||
public void Valid_Topic_Plus_Last_Char() | |||||
{ | |||||
MqttTopicValidator.ThrowIfInvalidSubscribe("/a/+"); | |||||
} | |||||
[TestMethod] | |||||
public void Valid_Topic_Hash_Last_Char() | |||||
{ | |||||
MqttTopicValidator.ThrowIfInvalidSubscribe("/a/#"); | |||||
} | |||||
[TestMethod] | |||||
public void Valid_Topic_Only_Hash() | |||||
{ | |||||
MqttTopicValidator.ThrowIfInvalidSubscribe("#"); | |||||
} | |||||
[TestMethod] | |||||
[ExpectedException(typeof(MqttProtocolViolationException))] | |||||
public void Invalid_Topic_Hash_In_Between() | |||||
{ | |||||
MqttTopicValidator.ThrowIfInvalidSubscribe("/a/#/c"); | |||||
} | |||||
[TestMethod] | |||||
[ExpectedException(typeof(MqttProtocolViolationException))] | |||||
public void Invalid_Topic_Empty() | |||||
{ | |||||
MqttTopicValidator.ThrowIfInvalidSubscribe(string.Empty); | |||||
} | |||||
} | |||||
} |