@@ -228,33 +228,56 @@ static int mqtt_is_topic_equals(const char *topic_filter, const char *topic)
228228 return 0 ;
229229}
230230
231- static char mqtt_topic_is_matched (char * topic_filter , MQTTString * topic_name )
231+ static char mqtt_topic_is_matched (const char * topic_filter , MQTTString * topic_name )
232232{
233- char * curf = topic_filter ;
234- char * curn = topic_name -> lenstring .data ;
235- char * curn_end = curn + topic_name -> lenstring .len ;
236-
237- while (* curf && curn < curn_end )
238- {
239- if (* curn == '/' && * curf != '/' )
240- break ;
241-
242- /* support wildcards for MQTT topics, such as '#' '+' */
243- if (* curf != '+' && * curf != '#' && * curf != * curn )
244- break ;
245-
246- if (* curf == '+' ) {
247- char * nextpos = curn + 1 ;
248- while (nextpos < curn_end && * nextpos != '/' )
249- nextpos = ++ curn + 1 ;
233+ const char * filter = topic_filter ;
234+ const char * topic = topic_name -> lenstring .data ;
235+ int topic_len = topic_name != NULL && topic != NULL ? strnlen (topic , topic_name -> lenstring .len ) : 0 ;
236+ int filter_len = strlen (filter );
237+ int i = 0 , j = 0 ;
238+ while (i < filter_len && j < topic_len ) {
239+ if (filter [i ] == '#' ) {
240+ // '#' must be at the end and must be preceded by '/' or be the first character
241+ if ((i == filter_len - 1 ) && (i == 0 || filter [i - 1 ] == '/' )) {
242+ return 1 ;
243+ }
244+ else {
245+ return 0 ;
246+ }
247+ }
248+ if (filter [i ] == '+' ) {
249+ // '+' must occupy an entire level
250+ if ((i > 0 && filter [i - 1 ] != '/' ) || (i < filter_len - 1 && filter [i + 1 ] != '/' && filter [i + 1 ] != '\0' )) {
251+ return 0 ;
252+ }
253+ // Skip one level in the topic
254+ while (j < topic_len && topic [j ] != '/' ) j ++ ;
255+ i ++ ;
250256 }
251- else if (* curf == '#' )
252- curn = curn_end - 1 ;
253- curf ++ ;
254- curn ++ ;
255- };
257+ else {
258+ // Ordinary characters match one by one
259+ if (filter [i ] != topic [j ]) {
260+ return 0 ;
261+ }
262+ i ++ ;
263+ j ++ ;
264+ }
265+ // Skip '/'
266+ if (i < filter_len && filter [i ] == '/' && j < topic_len && topic [j ] == '/' ) {
267+ i ++ ;
268+ j ++ ;
269+ }
270+ }
256271
257- return (curn == curn_end ) && (* curf == '\0' );
272+ // Process ending
273+ if (i == filter_len && j == topic_len ) {
274+ return 1 ;
275+ }
276+ // Allow ending with "/#" and topic is entirely consumed
277+ if ((i == filter_len - 2 ) && filter [i ] == '/' && filter [i + 1 ] == '#' && j == topic_len ) {
278+ return 1 ;
279+ }
280+ return 0 ;
258281}
259282
260283static void mqtt_new_message_data (message_data_t * md , MQTTString * topic_name , mqtt_message_t * message )
0 commit comments