#include "config.h"
#include <assert.h>
#include <string.h>
#ifdef WIN32
# include <winsock2.h>
# include <aclapi.h>
# include <io.h>
# include <lmcons.h>
#else
# include <sys/stat.h>
#endif
#ifdef WITH_BROKER
#include "mosquitto_broker_internal.h"
#endif
#include "mosquitto.h"
#include "memory_mosq.h"
#include "net_mosq.h"
#include "send_mosq.h"
#include "time_mosq.h"
#include "tls_mosq.h"
#include "util_mosq.h"
int mosquitto_pub_topic_check(const char *str)
{
int len = 0;
#ifdef WITH_BROKER
int hier_count = 0;
#endif
if(str == NULL){
return MOSQ_ERR_INVAL;
}
while(str && str[0]){
if(str[0] == '+' || str[0] == '#'){
return MOSQ_ERR_INVAL;
}
#ifdef WITH_BROKER
else if(str[0] == '/'){
hier_count++;
}
#endif
len++;
str = &str[1];
}
if(len > 65535) return MOSQ_ERR_INVAL;
#ifdef WITH_BROKER
if(hier_count > TOPIC_HIERARCHY_LIMIT) return MOSQ_ERR_INVAL;
#endif
return MOSQ_ERR_SUCCESS;
}
int mosquitto_pub_topic_check2(const char *str, size_t len)
{
size_t i;
#ifdef WITH_BROKER
int hier_count = 0;
#endif
if(str == NULL || len > 65535){
return MOSQ_ERR_INVAL;
}
for(i=0; i<len; i++){
if(str[i] == '+' || str[i] == '#'){
return MOSQ_ERR_INVAL;
}
#ifdef WITH_BROKER
else if(str[i] == '/'){
hier_count++;
}
#endif
}
#ifdef WITH_BROKER
if(hier_count > TOPIC_HIERARCHY_LIMIT) return MOSQ_ERR_INVAL;
#endif
return MOSQ_ERR_SUCCESS;
}
int mosquitto_sub_topic_check(const char *str)
{
char c = '\0';
int len = 0;
#ifdef WITH_BROKER
int hier_count = 0;
#endif
if(str == NULL){
return MOSQ_ERR_INVAL;
}
while(str[0]){
if(str[0] == '+'){
if((c != '\0' && c != '/') || (str[1] != '\0' && str[1] != '/')){
return MOSQ_ERR_INVAL;
}
}else if(str[0] == '#'){
if((c != '\0' && c != '/') || str[1] != '\0'){
return MOSQ_ERR_INVAL;
}
}
#ifdef WITH_BROKER
else if(str[0] == '/'){
hier_count++;
}
#endif
len++;
c = str[0];
str = &str[1];
}
if(len > 65535) return MOSQ_ERR_INVAL;
#ifdef WITH_BROKER
if(hier_count > TOPIC_HIERARCHY_LIMIT) return MOSQ_ERR_INVAL;
#endif
return MOSQ_ERR_SUCCESS;
}
int mosquitto_sub_topic_check2(const char *str, size_t len)
{
char c = '\0';
size_t i;
#ifdef WITH_BROKER
int hier_count = 0;
#endif
if(str == NULL || len > 65535){
return MOSQ_ERR_INVAL;
}
for(i=0; i<len; i++){
if(str[i] == '+'){
if((c != '\0' && c != '/') || (i<len-1 && str[i+1] != '/')){
return MOSQ_ERR_INVAL;
}
}else if(str[i] == '#'){
if((c != '\0' && c != '/') || i<len-1){
return MOSQ_ERR_INVAL;
}
}
#ifdef WITH_BROKER
else if(str[i] == '/'){
hier_count++;
}
#endif
c = str[i];
}
#ifdef WITH_BROKER
if(hier_count > TOPIC_HIERARCHY_LIMIT) return MOSQ_ERR_INVAL;
#endif
return MOSQ_ERR_SUCCESS;
}
int mosquitto_topic_matches_sub(const char *sub, const char *topic, bool *result)
{
return mosquitto_topic_matches_sub2(sub, 0, topic, 0, result);
}
int mosquitto_topic_matches_sub2(const char *sub, size_t sublen, const char *topic, size_t topiclen, bool *result)
{
size_t spos;
UNUSED(sublen);
UNUSED(topiclen);
if(!result) return MOSQ_ERR_INVAL;
*result = false;
if(!sub || !topic || sub[0] == 0 || topic[0] == 0){
return MOSQ_ERR_INVAL;
}
if((sub[0] == '$' && topic[0] != '$')
|| (topic[0] == '$' && sub[0] != '$')){
return MOSQ_ERR_SUCCESS;
}
spos = 0;
while(sub[0] != 0){
if(topic[0] == '+' || topic[0] == '#'){
return MOSQ_ERR_INVAL;
}
if(sub[0] != topic[0] || topic[0] == 0){
if(sub[0] == '+'){
if(spos > 0 && sub[-1] != '/'){
return MOSQ_ERR_INVAL;
}
if(sub[1] != 0 && sub[1] != '/'){
return MOSQ_ERR_INVAL;
}
spos++;
sub++;
while(topic[0] != 0 && topic[0] != '/'){
if(topic[0] == '+' || topic[0] == '#'){
return MOSQ_ERR_INVAL;
}
topic++;
}
if(topic[0] == 0 && sub[0] == 0){
*result = true;
return MOSQ_ERR_SUCCESS;
}
}else if(sub[0] == '#'){
if(spos > 0 && sub[-1] != '/'){
return MOSQ_ERR_INVAL;
}
if(sub[1] != 0){
return MOSQ_ERR_INVAL;
}else{
while(topic[0] != 0){
if(topic[0] == '+' || topic[0] == '#'){
return MOSQ_ERR_INVAL;
}
topic++;
}
*result = true;
return MOSQ_ERR_SUCCESS;
}
}else{
if(topic[0] == 0
&& spos > 0
&& sub[-1] == '+'
&& sub[0] == '/'
&& sub[1] == '#')
{
*result = true;
return MOSQ_ERR_SUCCESS;
}
while(sub[0] != 0){
if(sub[0] == '#' && sub[1] != 0){
return MOSQ_ERR_INVAL;
}
spos++;
sub++;
}
return MOSQ_ERR_SUCCESS;
}
}else{
if(topic[1] == 0){
if(sub[1] == '/'
&& sub[2] == '#'
&& sub[3] == 0){
*result = true;
return MOSQ_ERR_SUCCESS;
}
}
spos++;
sub++;
topic++;
if(sub[0] == 0 && topic[0] == 0){
*result = true;
return MOSQ_ERR_SUCCESS;
}else if(topic[0] == 0 && sub[0] == '+' && sub[1] == 0){
if(spos > 0 && sub[-1] != '/'){
return MOSQ_ERR_INVAL;
}
spos++;
sub++;
*result = true;
return MOSQ_ERR_SUCCESS;
}
}
}
if((topic[0] != 0 || sub[0] != 0)){
*result = false;
}
while(topic[0] != 0){
if(topic[0] == '+' || topic[0] == '#'){
return MOSQ_ERR_INVAL;
}
topic++;
}
return MOSQ_ERR_SUCCESS;
}