diff --git a/lib/linker.version b/lib/linker.version index ceebab2a..74030e95 100644 --- a/lib/linker.version +++ b/lib/linker.version @@ -73,4 +73,6 @@ MOSQ_1.3 { MOSQ_1.4 { global: mosquitto_threaded_set; + mosquitto_pub_topic_check; + mosquitto_sub_topic_check; } MOSQ_1.3; diff --git a/lib/mosquitto.c b/lib/mosquitto.c index 8172a1f3..8e5117e1 100644 --- a/lib/mosquitto.c +++ b/lib/mosquitto.c @@ -526,7 +526,7 @@ int mosquitto_publish(struct mosquitto *mosq, int *mid, const char *topic, int p if(strlen(topic) == 0) return MOSQ_ERR_INVAL; if(payloadlen < 0 || payloadlen > MQTT_MAX_PAYLOAD) return MOSQ_ERR_PAYLOAD_SIZE; - if(_mosquitto_pub_topic_check(topic) != MOSQ_ERR_SUCCESS){ + if(mosquitto_pub_topic_check(topic) != MOSQ_ERR_SUCCESS){ return MOSQ_ERR_INVAL; } @@ -589,7 +589,7 @@ int mosquitto_subscribe(struct mosquitto *mosq, int *mid, const char *sub, int q if(!mosq) return MOSQ_ERR_INVAL; if(mosq->sock == INVALID_SOCKET) return MOSQ_ERR_NO_CONN; - if(_mosquitto_sub_topic_check(sub)) return MOSQ_ERR_INVAL; + if(mosquitto_sub_topic_check(sub)) return MOSQ_ERR_INVAL; return _mosquitto_send_subscribe(mosq, mid, false, sub, qos); } @@ -599,7 +599,7 @@ int mosquitto_unsubscribe(struct mosquitto *mosq, int *mid, const char *sub) if(!mosq) return MOSQ_ERR_INVAL; if(mosq->sock == INVALID_SOCKET) return MOSQ_ERR_NO_CONN; - if(_mosquitto_sub_topic_check(sub)) return MOSQ_ERR_INVAL; + if(mosquitto_sub_topic_check(sub)) return MOSQ_ERR_INVAL; return _mosquitto_send_unsubscribe(mosq, mid, false, sub); } diff --git a/lib/mosquitto.h b/lib/mosquitto.h index 6c78d7c0..2819e65f 100644 --- a/lib/mosquitto.h +++ b/lib/mosquitto.h @@ -1424,6 +1424,57 @@ libmosq_EXPORT int mosquitto_sub_topic_tokens_free(char ***topics, int count); */ libmosq_EXPORT int mosquitto_topic_matches_sub(const char *sub, const char *topic, bool *result); +/* + * Function: mosquitto_pub_topic_check + * + * Check whether a topic to be used for publishing is valid. + * + * This searches for + or # in a topic and checks its length. + * + * This check is already carried out in and + * , there is no need to call it directly before them. It + * may be useful if you wish to check the validity of a topic in advance of + * making a connection for example. + * + * Parameters: + * topic - the topic to check + * + * Returns: + * MOSQ_ERR_SUCCESS - for a valid topic + * MOSQ_ERR_INVAL - if the topic contains a + or a #, or if it is too long. + * + * See Also: + * + */ +libmosq_EXPORT int mosquitto_pub_topic_check(const char *topic); + +/* + * Function: mosquitto_sub_topic_check + * + * Check whether a topic to be used for subscribing is valid. + * + * This searches for + or # in a topic and checks that they aren't in invalid + * positions, such as with foo/#/bar, foo/+bar or foo/bar#, and checks its + * length. + * + * This check is already carried out in and + * , there is no need to call it directly before them. + * It may be useful if you wish to check the validity of a topic in advance of + * making a connection for example. + * + * Parameters: + * topic - the topic to check + * + * Returns: + * MOSQ_ERR_SUCCESS - for a valid topic + * MOSQ_ERR_INVAL - if the topic contains a + or a # that is in an invalid + * position, or if it is too long. + * + * See Also: + * + */ +libmosq_EXPORT int mosquitto_sub_topic_check(const char *topic); + #ifdef __cplusplus } #endif diff --git a/lib/util_mosq.c b/lib/util_mosq.c index 3a076924..16105635 100644 --- a/lib/util_mosq.c +++ b/lib/util_mosq.c @@ -160,7 +160,7 @@ uint16_t _mosquitto_mid_generate(struct mosquitto *mosq) * Also returns MOSQ_ERR_INVAL if the topic string is too long. * Returns MOSQ_ERR_SUCCESS if everything is fine. */ -int _mosquitto_pub_topic_check(const char *str) +int mosquitto_pub_topic_check(const char *str) { int len = 0; while(str && str[0]){ @@ -182,7 +182,7 @@ int _mosquitto_pub_topic_check(const char *str) * Also returns MOSQ_ERR_INVAL if the topic string is too long. * Returns MOSQ_ERR_SUCCESS if everything is fine. */ -int _mosquitto_sub_topic_check(const char *str) +int mosquitto_sub_topic_check(const char *str) { char c = '\0'; int len = 0; diff --git a/lib/util_mosq.h b/lib/util_mosq.h index b737514b..7b8ac485 100644 --- a/lib/util_mosq.h +++ b/lib/util_mosq.h @@ -28,8 +28,6 @@ void _mosquitto_check_keepalive(struct mosquitto_db *db, struct mosquitto *mosq) void _mosquitto_check_keepalive(struct mosquitto *mosq); #endif uint16_t _mosquitto_mid_generate(struct mosquitto *mosq); -int _mosquitto_pub_topic_check(const char *str); -int _mosquitto_sub_topic_check(const char *str); FILE *_mosquitto_fopen(const char *path, const char *mode); #ifdef REAL_WITH_TLS_PSK diff --git a/lib/will_mosq.c b/lib/will_mosq.c index 60f519d3..2756a626 100644 --- a/lib/will_mosq.c +++ b/lib/will_mosq.c @@ -45,7 +45,7 @@ int _mosquitto_will_set(struct mosquitto *mosq, const char *topic, int payloadle if(payloadlen < 0 || payloadlen > MQTT_MAX_PAYLOAD) return MOSQ_ERR_PAYLOAD_SIZE; if(payloadlen > 0 && !payload) return MOSQ_ERR_INVAL; - if(_mosquitto_pub_topic_check(topic)) return MOSQ_ERR_INVAL; + if(mosquitto_pub_topic_check(topic)) return MOSQ_ERR_INVAL; if(mosq->will){ if(mosq->will->topic){ diff --git a/src/conf.c b/src/conf.c index e1a956d1..122404c2 100644 --- a/src/conf.c +++ b/src/conf.c @@ -1352,7 +1352,7 @@ int _config_read_file_core(struct mqtt3_config *config, bool reload, const char return MOSQ_ERR_INVAL; } if(_conf_parse_string(&token, "mount_point", &cur_listener->mount_point, saveptr)) return MOSQ_ERR_INVAL; - if(_mosquitto_pub_topic_check(cur_listener->mount_point) != MOSQ_ERR_SUCCESS){ + if(mosquitto_pub_topic_check(cur_listener->mount_point) != MOSQ_ERR_SUCCESS){ _mosquitto_log_printf(NULL, MOSQ_LOG_ERR, "Error: Invalid mount_point '%s'. Does it contain a wildcard character?", cur_listener->mount_point); @@ -1667,7 +1667,7 @@ int _config_read_file_core(struct mqtt3_config *config, bool reload, const char if(!strcmp(token, "\"\"")){ cur_topic->local_prefix = NULL; }else{ - if(_mosquitto_pub_topic_check(token) != MOSQ_ERR_SUCCESS){ + if(mosquitto_pub_topic_check(token) != MOSQ_ERR_SUCCESS){ _mosquitto_log_printf(NULL, MOSQ_LOG_ERR, "Error: Invalid bridge topic local prefix '%s'.", token); return MOSQ_ERR_INVAL; } @@ -1683,7 +1683,7 @@ int _config_read_file_core(struct mqtt3_config *config, bool reload, const char if(!strcmp(token, "\"\"")){ cur_topic->remote_prefix = NULL; }else{ - if(_mosquitto_pub_topic_check(token) != MOSQ_ERR_SUCCESS){ + if(mosquitto_pub_topic_check(token) != MOSQ_ERR_SUCCESS){ _mosquitto_log_printf(NULL, MOSQ_LOG_ERR, "Error: Invalid bridge topic remote prefix '%s'.", token); return MOSQ_ERR_INVAL; } diff --git a/src/read_handle.c b/src/read_handle.c index 16af8cae..76c9372e 100644 --- a/src/read_handle.c +++ b/src/read_handle.c @@ -157,7 +157,7 @@ int mqtt3_handle_publish(struct mosquitto_db *db, struct mosquitto *context) } } #endif - if(_mosquitto_pub_topic_check(topic) != MOSQ_ERR_SUCCESS){ + if(mosquitto_pub_topic_check(topic) != MOSQ_ERR_SUCCESS){ /* Invalid publish topic, just swallow it. */ _mosquitto_free(topic); return 1; diff --git a/src/read_handle_server.c b/src/read_handle_server.c index 8480883c..a4a3ecb3 100644 --- a/src/read_handle_server.c +++ b/src/read_handle_server.c @@ -242,7 +242,7 @@ int mqtt3_handle_connect(struct mosquitto_db *db, struct mosquitto *context) rc = 1; goto handle_connect_error; } - if(_mosquitto_pub_topic_check(will_topic)){ + if(mosquitto_pub_topic_check(will_topic)){ rc = 1; goto handle_connect_error; } @@ -696,7 +696,7 @@ int mqtt3_handle_subscribe(struct mosquitto_db *db, struct mosquitto *context) if(payload) _mosquitto_free(payload); return 1; } - if(_mosquitto_sub_topic_check(sub)){ + if(mosquitto_sub_topic_check(sub)){ _mosquitto_log_printf(NULL, MOSQ_LOG_INFO, "Invalid subscription string from %s, disconnecting.", context->address); _mosquitto_free(sub); @@ -806,7 +806,7 @@ int mqtt3_handle_unsubscribe(struct mosquitto_db *db, struct mosquitto *context) _mosquitto_free(sub); return 1; } - if(_mosquitto_sub_topic_check(sub)){ + if(mosquitto_sub_topic_check(sub)){ _mosquitto_log_printf(NULL, MOSQ_LOG_INFO, "Invalid unsubscription string from %s, disconnecting.", context->id); _mosquitto_free(sub);