|
|
@ -131,80 +131,59 @@ int mosquitto_sub_topic_check2(const char *str, size_t len)
|
|
|
|
|
|
|
|
|
|
|
|
int mosquitto_topic_matches_sub(const char *sub, const char *topic, bool *result)
|
|
|
|
int mosquitto_topic_matches_sub(const char *sub, const char *topic, bool *result)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
int slen, tlen;
|
|
|
|
return mosquitto_topic_matches_sub2(sub, 0, topic, 0, result);
|
|
|
|
|
|
|
|
|
|
|
|
if(!result) return MOSQ_ERR_INVAL;
|
|
|
|
|
|
|
|
*result = false;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if(!sub || !topic){
|
|
|
|
|
|
|
|
return MOSQ_ERR_INVAL;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
slen = strlen(sub);
|
|
|
|
|
|
|
|
tlen = strlen(topic);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return mosquitto_topic_matches_sub2(sub, slen, topic, tlen, result);
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* Does a topic match a subscription? */
|
|
|
|
/* Does a topic match a subscription? */
|
|
|
|
int mosquitto_topic_matches_sub2(const char *sub, size_t sublen, const char *topic, size_t topiclen, bool *result)
|
|
|
|
int mosquitto_topic_matches_sub2(const char *sub, size_t sublen, const char *topic, size_t topiclen, bool *result)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
size_t i;
|
|
|
|
size_t spos;
|
|
|
|
size_t spos, tpos;
|
|
|
|
|
|
|
|
bool multilevel_wildcard = false;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if(!result) return MOSQ_ERR_INVAL;
|
|
|
|
if(!result) return MOSQ_ERR_INVAL;
|
|
|
|
*result = false;
|
|
|
|
*result = false;
|
|
|
|
|
|
|
|
|
|
|
|
if(!sub || !topic){
|
|
|
|
if(!sub || !topic || sub[0] == 0 || topic[0] == 0){
|
|
|
|
return MOSQ_ERR_INVAL;
|
|
|
|
return MOSQ_ERR_INVAL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if(!sublen || !topiclen){
|
|
|
|
if((sub[0] == '$' && topic[0] != '$')
|
|
|
|
*result = false;
|
|
|
|
|| (topic[0] == '$' && sub[0] != '$')){
|
|
|
|
return MOSQ_ERR_INVAL;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if(sublen && topiclen){
|
|
|
|
|
|
|
|
if((sub[0] == '$' && topic[0] != '$')
|
|
|
|
|
|
|
|
|| (topic[0] == '$' && sub[0] != '$')){
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return MOSQ_ERR_SUCCESS;
|
|
|
|
return MOSQ_ERR_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
spos = 0;
|
|
|
|
spos = 0;
|
|
|
|
tpos = 0;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
while(spos < sublen && tpos <= topiclen){
|
|
|
|
while(sub[0] != 0){
|
|
|
|
if(topic[tpos] == '+' || topic[tpos] == '#'){
|
|
|
|
if(topic[0] == '+' || topic[0] == '#'){
|
|
|
|
return MOSQ_ERR_INVAL;
|
|
|
|
return MOSQ_ERR_INVAL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if(tpos == topiclen || sub[spos] != topic[tpos]){ /* Check for wildcard matches */
|
|
|
|
if(sub[0] != topic[0] || topic[0] == 0){ /* Check for wildcard matches */
|
|
|
|
if(sub[spos] == '+'){
|
|
|
|
if(sub[0] == '+'){
|
|
|
|
/* Check for bad "+foo" or "a/+foo" subscription */
|
|
|
|
/* Check for bad "+foo" or "a/+foo" subscription */
|
|
|
|
if(spos > 0 && sub[spos-1] != '/'){
|
|
|
|
if(spos > 0 && sub[-1] != '/'){
|
|
|
|
return MOSQ_ERR_INVAL;
|
|
|
|
return MOSQ_ERR_INVAL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/* Check for bad "foo+" or "foo+/a" subscription */
|
|
|
|
/* Check for bad "foo+" or "foo+/a" subscription */
|
|
|
|
if(spos < sublen-1 && sub[spos+1] != '/'){
|
|
|
|
if(sub[1] != 0 && sub[1] != '/'){
|
|
|
|
return MOSQ_ERR_INVAL;
|
|
|
|
return MOSQ_ERR_INVAL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
spos++;
|
|
|
|
spos++;
|
|
|
|
while(tpos < topiclen && topic[tpos] != '/'){
|
|
|
|
sub++;
|
|
|
|
tpos++;
|
|
|
|
while(topic[0] != 0 && topic[0] != '/'){
|
|
|
|
|
|
|
|
topic++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if(tpos == topiclen && spos == sublen){
|
|
|
|
if(topic[0] == 0 && sub[0] == 0){
|
|
|
|
*result = true;
|
|
|
|
*result = true;
|
|
|
|
return MOSQ_ERR_SUCCESS;
|
|
|
|
return MOSQ_ERR_SUCCESS;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}else if(sub[spos] == '#'){
|
|
|
|
}else if(sub[0] == '#'){
|
|
|
|
/* Check for bad "foo#" subscription */
|
|
|
|
/* Check for bad "foo#" subscription */
|
|
|
|
if(spos > 0 && sub[spos-1] != '/'){
|
|
|
|
if(spos > 0 && sub[-1] != '/'){
|
|
|
|
return MOSQ_ERR_INVAL;
|
|
|
|
return MOSQ_ERR_INVAL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/* Check for # not the final character of the sub, e.g. "#foo" */
|
|
|
|
/* Check for # not the final character of the sub, e.g. "#foo" */
|
|
|
|
if(spos+1 != sublen){
|
|
|
|
if(sub[1] != 0){
|
|
|
|
return MOSQ_ERR_INVAL;
|
|
|
|
return MOSQ_ERR_INVAL;
|
|
|
|
}else{
|
|
|
|
}else{
|
|
|
|
*result = true;
|
|
|
|
*result = true;
|
|
|
@ -212,23 +191,23 @@ int mosquitto_topic_matches_sub2(const char *sub, size_t sublen, const char *top
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}else{
|
|
|
|
}else{
|
|
|
|
/* Check for e.g. foo/bar matching foo/+/# */
|
|
|
|
/* Check for e.g. foo/bar matching foo/+/# */
|
|
|
|
if(spos > 0
|
|
|
|
if(topic[0] == 0
|
|
|
|
&& spos+2 == sublen
|
|
|
|
&& spos > 0
|
|
|
|
&& tpos == topiclen
|
|
|
|
&& sub[-1] == '+'
|
|
|
|
&& sub[spos-1] == '+'
|
|
|
|
&& sub[0] == '/'
|
|
|
|
&& sub[spos] == '/'
|
|
|
|
&& sub[1] == '#')
|
|
|
|
&& sub[spos+1] == '#')
|
|
|
|
|
|
|
|
{
|
|
|
|
{
|
|
|
|
*result = true;
|
|
|
|
*result = true;
|
|
|
|
multilevel_wildcard = true;
|
|
|
|
|
|
|
|
return MOSQ_ERR_SUCCESS;
|
|
|
|
return MOSQ_ERR_SUCCESS;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* There is no match at this point, but is the sub invalid? */
|
|
|
|
/* There is no match at this point, but is the sub invalid? */
|
|
|
|
for(i=spos; i<sublen; i++){
|
|
|
|
while(sub[0] != 0){
|
|
|
|
if(sub[i] == '#' && i+1 != sublen){
|
|
|
|
if(sub[0] == '#' && sub[1] != 0){
|
|
|
|
return MOSQ_ERR_INVAL;
|
|
|
|
return MOSQ_ERR_INVAL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
spos++;
|
|
|
|
|
|
|
|
sub++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* Valid input, but no match */
|
|
|
|
/* Valid input, but no match */
|
|
|
@ -236,32 +215,33 @@ int mosquitto_topic_matches_sub2(const char *sub, size_t sublen, const char *top
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}else{
|
|
|
|
}else{
|
|
|
|
/* sub[spos] == topic[tpos] */
|
|
|
|
/* sub[spos] == topic[tpos] */
|
|
|
|
if(tpos == topiclen-1){
|
|
|
|
if(topic[1] == 0){
|
|
|
|
/* Check for e.g. foo matching foo/# */
|
|
|
|
/* Check for e.g. foo matching foo/# */
|
|
|
|
if(spos == sublen-3
|
|
|
|
if(sub[1] == '/'
|
|
|
|
&& sub[spos+1] == '/'
|
|
|
|
&& sub[2] == '#'
|
|
|
|
&& sub[spos+2] == '#'){
|
|
|
|
&& sub[3] == 0){
|
|
|
|
*result = true;
|
|
|
|
*result = true;
|
|
|
|
multilevel_wildcard = true;
|
|
|
|
|
|
|
|
return MOSQ_ERR_SUCCESS;
|
|
|
|
return MOSQ_ERR_SUCCESS;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
spos++;
|
|
|
|
spos++;
|
|
|
|
tpos++;
|
|
|
|
sub++;
|
|
|
|
if(spos == sublen && tpos == topiclen){
|
|
|
|
topic++;
|
|
|
|
|
|
|
|
if(sub[0] == 0 && topic[0] == 0){
|
|
|
|
*result = true;
|
|
|
|
*result = true;
|
|
|
|
return MOSQ_ERR_SUCCESS;
|
|
|
|
return MOSQ_ERR_SUCCESS;
|
|
|
|
}else if(tpos == topiclen && spos == sublen-1 && sub[spos] == '+'){
|
|
|
|
}else if(topic[0] == 0 && sub[0] == '+' && sub[1] == 0){
|
|
|
|
if(spos > 0 && sub[spos-1] != '/'){
|
|
|
|
if(spos > 0 && sub[-1] != '/'){
|
|
|
|
return MOSQ_ERR_INVAL;
|
|
|
|
return MOSQ_ERR_INVAL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
spos++;
|
|
|
|
spos++;
|
|
|
|
|
|
|
|
sub++;
|
|
|
|
*result = true;
|
|
|
|
*result = true;
|
|
|
|
return MOSQ_ERR_SUCCESS;
|
|
|
|
return MOSQ_ERR_SUCCESS;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if(multilevel_wildcard == false && (tpos < topiclen || spos < sublen)){
|
|
|
|
if((topic[0] != 0 || sub[0] != 0)){
|
|
|
|
*result = false;
|
|
|
|
*result = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|