Ejemplo n.º 1
0
int settings_parse(JsonNode *root) {
    int have_error = 0;

#ifdef WEBSERVER
    int web_port = 0;
    int own_port = 0;

    char *webgui_tpl = malloc(strlen(WEBGUI_TEMPLATE)+1);
    if(!webgui_tpl) {
        logprintf(LOG_ERR, "out of memory");
        exit(EXIT_FAILURE);
    }
    strcpy(webgui_tpl, WEBGUI_TEMPLATE);
    char *webgui_root = malloc(strlen(WEBSERVER_ROOT)+1);
    if(!webgui_root) {
        logprintf(LOG_ERR, "out of memory");
        exit(EXIT_FAILURE);
    }
    strcpy(webgui_root, WEBSERVER_ROOT);
#endif

#ifndef __FreeBSD__
    regex_t regex;
    int reti;
#endif

    JsonNode *jsettings = json_first_child(root);

    while(jsettings) {
        if(strcmp(jsettings->key, "port") == 0
                || strcmp(jsettings->key, "send-repeats") == 0
                || strcmp(jsettings->key, "receive-repeats") == 0) {
            if((int)jsettings->number_ == 0) {
                logprintf(LOG_ERR, "setting \"%s\" must contain a number larger than 0", jsettings->key);
                have_error = 1;
                goto clear;
            } else {
#ifdef WEBSERVER
                if(strcmp(jsettings->key, "port") == 0) {
                    own_port = (int)jsettings->number_;
                }
#endif
                settings_add_number(jsettings->key, (int)jsettings->number_);
            }
        } else if(strcmp(jsettings->key, "standalone") == 0) {
            if(jsettings->number_ < 0 || jsettings->number_ > 1) {
                logprintf(LOG_ERR, "setting \"%s\" must be either 0 or 1", jsettings->key);
                have_error = 1;
                goto clear;
            } else {
                settings_add_number(jsettings->key, (int)jsettings->number_);
            }
        }  else if(strcmp(jsettings->key, "firmware-update") == 0) {
            if(jsettings->number_ < 0 || jsettings->number_ > 1) {
                logprintf(LOG_ERR, "setting \"%s\" must be either 0 or 1", jsettings->key);
                have_error = 1;
                goto clear;
            } else {
                settings_add_number(jsettings->key, (int)jsettings->number_);
            }
        } else if(strcmp(jsettings->key, "log-level") == 0) {
            if((int)jsettings->number_ < 0 || (int)jsettings->number_ > 5) {
                logprintf(LOG_ERR, "setting \"%s\" must contain a number from 0 till 5", jsettings->key);
                have_error = 1;
                goto clear;
            } else {
                settings_add_number(jsettings->key, (int)jsettings->number_);
            }
        } else if(strcmp(jsettings->key, "pid-file") == 0 || strcmp(jsettings->key, "log-file") == 0) {
            if(!jsettings->string_) {
                logprintf(LOG_ERR, "setting \"%s\" must contain an existing file path", jsettings->key);
                have_error = 1;
                goto clear;
            } else {
                if(path_exists(jsettings->string_) != EXIT_SUCCESS) {
                    logprintf(LOG_ERR, "setting \"%s\" must point to an existing folder", jsettings->key);
                    have_error = 1;
                    goto clear;
                } else {
                    settings_add_string(jsettings->key, jsettings->string_);
                }
            }
        } else if(strcmp(jsettings->key, "config-file") == 0 || strcmp(jsettings->key, "hardware-file") == 0) {
            if(!jsettings->string_) {
                logprintf(LOG_ERR, "setting \"%s\" must contain an existing file path", jsettings->key);
                have_error = 1;
                goto clear;
            } else if(strlen(jsettings->string_) > 0) {
                if(settings_file_exists(jsettings->string_) == EXIT_SUCCESS) {
                    settings_add_string(jsettings->key, jsettings->string_);
                } else {
                    logprintf(LOG_ERR, "setting \"%s\" must point to an existing file", jsettings->key);
                    have_error = 1;
                    goto clear;
                }
            }
        } else if(strcmp(jsettings->key, "whitelist") == 0) {
            if(!jsettings->string_) {
                logprintf(LOG_ERR, "setting \"%s\" must contain valid ip addresses", jsettings->key);
                have_error = 1;
                goto clear;
            } else if(strlen(jsettings->string_) > 0) {
#ifndef __FreeBSD__
                char validate[] = "^((\\*|[0-9]|[1-9][0-9]|1[0-9][0-9]|2([0-4][0-9]|5[0-5]))\\.(\\*|[0-9]|[1-9][0-9]|1[0-9][0-9]|2([0-4][0-9]|5[0-5]))\\.(\\*|[0-9]|[1-9][0-9]|1[0-9][0-9]|2([0-4][0-9]|5[0-5]))\\.(\\*|[0-9]|[1-9][0-9]|1[0-9][0-9]|2([0-4][0-9]|5[0-5]))(,[\\ ]|,|$))+$";
                reti = regcomp(&regex, validate, REG_EXTENDED);
                if(reti) {
                    logprintf(LOG_ERR, "could not compile regex");
                    have_error = 1;
                    goto clear;
                }
                reti = regexec(&regex, jsettings->string_, 0, NULL, 0);
                if(reti == REG_NOMATCH || reti != 0) {
                    logprintf(LOG_ERR, "setting \"%s\" must contain valid ip addresses", jsettings->key);
                    have_error = 1;
                    regfree(&regex);
                    goto clear;
                }
                regfree(&regex);
#endif
                int l = (int)strlen(jsettings->string_)-1;
                if(jsettings->string_[l] == ' ' || jsettings->string_[l] == ',') {
                    logprintf(LOG_ERR, "setting \"%s\" must contain valid ip addresses", jsettings->key);
                    have_error = 1;
                    goto clear;
                }
                settings_add_string(jsettings->key, jsettings->string_);
            }
#ifdef WEBSERVER
        } else if(strcmp(jsettings->key, "webserver-port") == 0) {
            if(jsettings->number_ < 0) {
                logprintf(LOG_ERR, "setting \"%s\" must contain a number larger than 0", jsettings->key);
                have_error = 1;
                goto clear;
            } else {
                web_port = (int)jsettings->number_;
                settings_add_number(jsettings->key, (int)jsettings->number_);
            }
        } else if(strcmp(jsettings->key, "webserver-root") == 0) {
            if(!jsettings->string_ || path_exists(jsettings->string_) != 0) {
                logprintf(LOG_ERR, "setting \"%s\" must contain a valid path", jsettings->key);
                have_error = 1;
                goto clear;
            } else {
                webgui_root = realloc(webgui_root, strlen(jsettings->string_)+1);
                if(!webgui_root) {
                    logprintf(LOG_ERR, "out of memory");
                    exit(EXIT_FAILURE);
                }
                strcpy(webgui_root, jsettings->string_);
                settings_add_string(jsettings->key, jsettings->string_);
            }
        } else if(strcmp(jsettings->key, "webserver-enable") == 0) {
            if(jsettings->number_ < 0 || jsettings->number_ > 1) {
                logprintf(LOG_ERR, "setting \"%s\" must be either 0 or 1", jsettings->key);
                have_error = 1;
                goto clear;
            } else {
                settings_add_number(jsettings->key, (int)jsettings->number_);
            }
        } else if(strcmp(jsettings->key, "webserver-cache") == 0) {
            if(jsettings->number_ < 0 || jsettings->number_ > 1) {
                logprintf(LOG_ERR, "setting \"%s\" must be either 0 or 1", jsettings->key);
                have_error = 1;
                goto clear;
            } else {
                settings_add_number(jsettings->key, (int)jsettings->number_);
            }
        } else if(strcmp(jsettings->key, "webserver-user") == 0) {
            if(jsettings->string_ || strlen(jsettings->string_) > 0) {
                if(name2uid(jsettings->string_) == -1) {
                    logprintf(LOG_ERR, "setting \"%s\" must contain a valid system user", jsettings->key);
                    have_error = 1;
                    goto clear;
                } else {
                    settings_add_string(jsettings->key, jsettings->string_);
                }
            }
        } else if(strcmp(jsettings->key, "webserver-authentication") == 0 && jsettings->tag == JSON_ARRAY) {
            JsonNode *jtmp = json_first_child(jsettings);
            unsigned short i = 0;
            while(jtmp) {
                i++;
                if(jtmp->tag == JSON_STRING) {
                    if(i == 1) {
                        settings_add_string("webserver-authentication-username", jtmp->string_);
                    } else if(i == 2) {
                        settings_add_string("webserver-authentication-password", jtmp->string_);
                    }
                } else {
                    have_error = 1;
                    break;
                }
                if(i > 2) {
                    have_error = 1;
                    break;
                }
                jtmp = jtmp->next;
            }
            if(i != 2 || have_error == 1) {
                logprintf(LOG_ERR, "setting \"%s\" must be in the format of [ \"username\", \"password\" ]", jsettings->key);
                have_error = 1;
                goto clear;
            }
        }  else if(strcmp(jsettings->key, "webgui-template") == 0) {
            if(!jsettings->string_) {
                logprintf(LOG_ERR, "setting \"%s\" must be a valid template", jsettings->key);
                have_error = 1;
                goto clear;
            } else {
                webgui_tpl = realloc(webgui_tpl, strlen(jsettings->string_)+1);
                if(!webgui_tpl) {
                    logprintf(LOG_ERR, "out of memory");
                    exit(EXIT_FAILURE);
                }
                strcpy(webgui_tpl, jsettings->string_);
                settings_add_string(jsettings->key, jsettings->string_);
            }
#endif
#ifdef UPDATE
        } else if(strcmp(jsettings->key, "update-check") == 0) {
            if(jsettings->number_ < 0 || jsettings->number_ > 1) {
                logprintf(LOG_ERR, "setting \"%s\" must be either 0 or 1", jsettings->key);
                have_error = 1;
                goto clear;
            } else {
                settings_add_number(jsettings->key, (int)jsettings->number_);
            }
        } else if(strcmp(jsettings->key, "update-development") == 0) {
            if(jsettings->number_ < 0 || jsettings->number_ > 1) {
                logprintf(LOG_ERR, "setting \"%s\" must be either 0 or 1", jsettings->key);
                have_error = 1;
                goto clear;
            } else {
                settings_add_number(jsettings->key, (int)jsettings->number_);
            }
        } else if(strcmp(jsettings->key, "update-mirror") == 0) {
            char *filename = NULL;
            char *url = NULL;
            char *data = NULL;
            int lg = 0;
            char typebuf[70];

            if(jsettings->string_) {
                url = malloc(strlen(jsettings->string_)+1);
                if(!url) {
                    logprintf(LOG_ERR, "out of memory");
                    exit(EXIT_FAILURE);
                }
                strcpy(url, jsettings->string_);
                http_parse_url(url, &filename);
            }
            if(!jsettings->string_ || http_get(filename, &data, &lg, typebuf) != 200) {
                logprintf(LOG_ERR, "setting \"%s\" must be point to a valid (online) file", jsettings->key);
                /* clean-up http_lib global */
                if(http_server) sfree((void *)&http_server);
                if(filename) sfree((void *)&filename);
                if(url) sfree((void *)&url);
                if(data) sfree((void *)&data);
                have_error = 1;
                goto clear;
            } else {
                settings_add_string(jsettings->key, jsettings->string_);
                /* clean-up http_lib global */
                if(http_server) sfree((void *)&http_server);
                if(filename) sfree((void *)&filename);
                if(url) sfree((void *)&url);
                if(data) sfree((void *)&data);
            }
#endif
        } else {
            logprintf(LOG_ERR, "setting \"%s\" is invalid", jsettings->key);
            have_error = 1;
            goto clear;
        }
        jsettings = jsettings->next;
    }
    json_delete(jsettings);
#ifdef WEBSERVER
    if(webgui_tpl) {
        char *tmp = malloc(strlen(webgui_root)+strlen(webgui_tpl)+13);
        if(!tmp) {
            logprintf(LOG_ERR, "out of memory");
            exit(EXIT_FAILURE);
        }
        sprintf(tmp, "%s/%s/index.html", webgui_root, webgui_tpl);
        if(path_exists(tmp) != EXIT_SUCCESS) {
            logprintf(LOG_ERR, "setting \"webgui-template\", template does not exists");
            have_error = 1;
            sfree((void *)&tmp);
            goto clear;
        }
        sfree((void *)&tmp);
    }

    if(web_port == own_port) {
        logprintf(LOG_ERR, "setting \"port\" and \"webserver-port\" cannot be the same");
        have_error = 1;
        goto clear;
    }
#endif
clear:
#ifdef WEBSERVER
    if(webgui_tpl) {
        sfree((void *)&webgui_tpl);
    }
    if(webgui_root) {
        sfree((void *)&webgui_root);
    }
#endif
    return have_error;
}
Ejemplo n.º 2
0
int settings_parse(JsonNode *root) {
	int have_error = 0;
	int is_node = 0;
	char *server_ip = NULL;
	int server_port = 0;
	int web_port = 0;
	int own_port = 0;
	int has_config = 0;
	int has_lirc = 0;
	int has_socket = 0;
	int gpio_in = -1;
	int gpio_out = -1;

	JsonNode *jsettings = json_first_child(root);

	while(jsettings) {
		if(strcmp(jsettings->key, "port") == 0 || strcmp(jsettings->key, "send-repeats") == 0 || strcmp(jsettings->key, "receive-repeats") == 0) {
			if((int)jsettings->number_ == 0) {
				logprintf(LOG_ERR, "setting \"%s\" must contain a number larger than 0", jsettings->key);
				have_error = 1;
				goto clear;
			} else {
				if(strcmp(jsettings->key, "port") == 0) {
					own_port = (int)jsettings->number_;
				}
				settings_add_number_node(jsettings->key, (int)jsettings->number_);
			}
		} else if(strcmp(jsettings->key, "mode") == 0) {
			if(jsettings->string_ == NULL) {
				logprintf(LOG_ERR, "setting \"%s\" must be \"server\" or \"client\"", jsettings->key);
				have_error = 1;
				goto clear;
			} else {
				if(strcmp(jsettings->string_, "client") == 0) {
					is_node = 1;
				}
				if(strcmp(jsettings->string_, "server") == 0 || strcmp(jsettings->string_, "client") == 0) {
					settings_add_string_node(jsettings->key, jsettings->string_);
				} else {
					logprintf(LOG_ERR, "setting \"%s\" must be \"server\" or \"client\"", jsettings->key);
					have_error = 1;
					goto clear;
				}
			}
		} else if(strcmp(jsettings->key, "log-level") == 0) {
			if((int)jsettings->number_ == 0 || (int)jsettings->number_ > 5) {
				logprintf(LOG_ERR, "setting \"%s\" must contain a number from 0 till 5", jsettings->key);
				have_error = 1;
				goto clear;
			} else {
				settings_add_number_node(jsettings->key, (int)jsettings->number_);
			}
		} else if(strcmp(jsettings->key, "pid-file") == 0 || strcmp(jsettings->key, "log-file") == 0) {
			if(jsettings->string_ == NULL) {
				logprintf(LOG_ERR, "setting \"%s\" must contain an existing file path", jsettings->key);
				have_error = 1;
				goto clear;
			} else {
				if(settings_path_exists(jsettings->string_) != 0) {
					logprintf(LOG_ERR, "setting \"%s\" must point to an existing folder", jsettings->key);
					have_error = 1;
					goto clear;				
				} else {
					settings_add_string_node(jsettings->key, jsettings->string_);
				}
			}
		} else if(strcmp(jsettings->key, "config-file") == 0 || strcmp(jsettings->key, "process-file") == 0) {
			if(jsettings->string_ == NULL) {
				logprintf(LOG_ERR, "setting \"%s\" must contain an existing file path", jsettings->key);
				have_error = 1;
				goto clear;
			} else if(strlen(jsettings->string_) > 0) {
				if(settings_file_exists(jsettings->string_) == 0) {
					has_config = 1;
					settings_add_string_node(jsettings->key, jsettings->string_);
				} else {
					logprintf(LOG_ERR, "setting \"%s\" must point to an existing file", jsettings->key);
					have_error = 1;
					goto clear;
				}
			}
		} else if(strcmp(jsettings->key, "socket") == 0) {
			if(jsettings->string_ == NULL) {
				logprintf(LOG_ERR, "setting \"%s\" must point an existing socket", jsettings->key);
				have_error = 1;
				goto clear;
			} else {
				has_socket = 1;
				settings_add_string_node(jsettings->key, jsettings->string_);
			}
		} else if(strcmp(jsettings->key, "use-lirc") == 0) {
			if(jsettings->number_ < 0 || jsettings->number_ > 1) {
				logprintf(LOG_ERR, "setting \"%s\" must be either 0 or 1", jsettings->key);
				have_error = 1;
				goto clear;
			} else {
				if((int)jsettings->number_ == 1) {
					has_lirc = 1;
				}
				settings_add_number_node(jsettings->key, (int)jsettings->number_);
			}
		} else if(strcmp(jsettings->key, "webserver-port") == 0) {
			if(jsettings->number_ < 0) {
				logprintf(LOG_ERR, "setting \"%s\" must contain a number larger than 0", jsettings->key);
				have_error = 1;
				goto clear;
			} else {
				web_port = (int)jsettings->number_;
				settings_add_number_node(jsettings->key, (int)jsettings->number_);
			}
		} else if(strcmp(jsettings->key, "webserver-root") == 0) {
			if(jsettings->string_ == NULL) {
				logprintf(LOG_ERR, "setting \"%s\" must contain a valid path", jsettings->key);
				have_error = 1;
				goto clear;
			} else {
				settings_add_string_node(jsettings->key, jsettings->string_);
			}
		} else if(strcmp(jsettings->key, "webserver-enable") == 0) {
			if(jsettings->number_ < 0 || jsettings->number_ > 1) {
				logprintf(LOG_ERR, "setting \"%s\" must be either 0 or 1", jsettings->key);
				have_error = 1;
				goto clear;
			} else {
				settings_add_number_node(jsettings->key, (int)jsettings->number_);
			}
		} else if(strcmp(jsettings->key, "gpio-receiver") == 0) {
			if(jsettings->number_ < 0 || jsettings->number_ > 7) {
				logprintf(LOG_ERR, "setting \"%s\" must be between 0 and 7", jsettings->key);
				have_error = 1;
				goto clear;
			} else {
				gpio_out = (int)jsettings->number_;
				settings_add_number_node(jsettings->key, (int)jsettings->number_);
			}			
		} else if(strcmp(jsettings->key, "gpio-sender") == 0) {
			if(jsettings->number_ < 0 || jsettings->number_ > 7) {
				logprintf(LOG_ERR, "setting \"%s\" must be between 0 and 7", jsettings->key);
				have_error = 1;
				goto clear;
			} else {
				gpio_in = (int)jsettings->number_;
				settings_add_number_node(jsettings->key, (int)jsettings->number_);
			}			
		} else if(strcmp(jsettings->key, "server") == 0) {
			JsonNode *jserver = json_find_member(root, "server");
			JsonNode *jtmp = json_first_child(jserver);
			int i = 0;
			while(jtmp != NULL) {
				i++;
				if(jtmp->tag == JSON_STRING) {
					server_ip = strdup(jtmp->string_);
				} else if(jtmp->tag == JSON_NUMBER) {
					server_port = (int)jtmp->number_;
				}
				if(i > 2) {
					i++;
					break;
				}
				jtmp = jtmp->next;
			}
			if(i > 2) {
				logprintf(LOG_ERR, "setting \"%s\" must be in the format of [ \"x.x.x.x\", xxxx ]", jsettings->key);
				have_error = 1;
				goto clear;
			} else if(server_ip != NULL && server_port > 0 && is_node == 1) {
				settings_add_string_node("server-ip", server_ip);
				settings_add_number_node("server-port", server_port);
			} else {	
				logprintf(LOG_ERR, "setting \"%s\" must be in the format of [ \"x.x.x.x\", xxxx ]", jsettings->key);
				have_error = 1;
				goto clear;
			}
		} else {
			logprintf(LOG_ERR, "setting \"%s\" is invalid", jsettings->key);
			have_error = 1;
			goto clear;
		}
		jsettings = jsettings->next;
	}
	json_delete(jsettings);
	if(has_lirc == 1 && gpio_in > -1) {
		logprintf(LOG_ERR, "setting \"gpio-receiver\" and use-lirc cannot be combined");
		have_error = 1;
		goto clear;
	}
	if(has_lirc == 1 && gpio_out > -1) {
		logprintf(LOG_ERR, "setting \"gpio-sender\" and use-lirc cannot be combined");
		have_error = 1;
		goto clear;
	}	
	if(has_lirc == 0 && has_socket == 1) {
		logprintf(LOG_ERR, "setting \"socket\" must be combined with use-lirc");
		have_error = 1;
		goto clear;
	}
	if(server_port > 0 && server_port == own_port && is_node == 1) {
		logprintf(LOG_ERR, "setting \"port\" and \"server port\" cannot be the same");
		have_error = 1;
		goto clear;
	}
	if(web_port == own_port) {
		logprintf(LOG_ERR, "setting \"port\" and \"webserver-port\" cannot be the same");
		have_error = 1;
		goto clear;
	}
	if(is_node == 1 && has_config == 1) {
		logprintf(LOG_ERR, "a daemon running as client cannot have a config file defined");
		have_error = 1;
		goto clear;		
	}
clear:
	return have_error;
}