Fix PiHelper API to return better int values and add comments

This commit is contained in:
William Brawner 2020-01-01 13:35:06 -06:00
parent 9c4582c4bc
commit 7e599ee5f1
6 changed files with 129 additions and 39 deletions

View file

@ -78,7 +78,7 @@ int main(int argc, char ** argv) {
case 'h': case 'h':
default: default:
print_usage(); print_usage();
return PIHELPER_HELP; return PIHELPER_OPERATION_FAILED;
} }
} }
if (config_path == NULL) { if (config_path == NULL) {
@ -118,25 +118,35 @@ int main(int argc, char ** argv) {
write_log(PIHELPER_LOG_DEBUG, "Reading existing PiHelper config"); write_log(PIHELPER_LOG_DEBUG, "Reading existing PiHelper config");
config = pihelper_read_config(config_path); config = pihelper_read_config(config_path);
} }
int retval; int status;
if (config == NULL) { if (config == NULL) {
write_log(PIHELPER_LOG_ERROR, "Failed to parse Pi-Helper config at %s", config_path); write_log(PIHELPER_LOG_ERROR, "Failed to parse Pi-Helper config at %s", config_path);
retval = 1; status = PIHELPER_OPERATION_FAILED;
} else if (enable && disable != NULL) { } else if (enable && disable != NULL) {
print_usage(); print_usage();
retval = PIHELPER_INVALID_COMMANDS; status = PIHELPER_OPERATION_FAILED;
} else if (enable) { } else if (enable) {
retval = pihelper_enable_pihole(config); status = pihelper_enable_pihole(config);
} else if (disable != NULL) { } else if (disable != NULL) {
retval = pihelper_disable_pihole(config, disable); status = pihelper_disable_pihole(config, disable);
free(disable); free(disable);
} else { } else {
retval = pihelper_get_status(config); status = pihelper_get_status(config);
} }
char * status_message = NULL;
if (status == PIHELPER_ENABLED) {
status_message = "enabled";
} else if (status == PIHELPER_DISABLED) {
status_message = "disabled";
}
if (status_message != NULL) {
write_log(PIHELPER_LOG_INFO, "Pi-hole status: %s", status_message);
}
free(config_path); free(config_path);
pihelper_free_config(config); pihelper_free_config(config);
return retval; return status;
} }
void print_usage() { void print_usage() {

View file

@ -25,8 +25,6 @@
#include <unistd.h> #include <unistd.h>
#include "config.h" #include "config.h"
const int MAX_PIHOLE_API_KEY = 64;
int mkdirs(char * path) { int mkdirs(char * path) {
char * curPos = strstr(path, "/") + 1; char * curPos = strstr(path, "/") + 1;
char parents[strlen(path)]; char parents[strlen(path)];

View file

@ -22,6 +22,8 @@
#include "log.h" #include "log.h"
#include "pihelper.h" #include "pihelper.h"
#define MAX_PIHOLE_API_KEY 64
int save_config(pihole_config * config, char * config_path); int save_config(pihole_config * config, char * config_path);
pihole_config * read_config(char * config_path); pihole_config * read_config(char * config_path);

View file

@ -26,14 +26,6 @@
#include "log.h" #include "log.h"
#include "network.h" #include "network.h"
static char * URL_FORMAT = "http://%s/admin/api.php";
static int URL_FORMAT_LEN = 22;
static char * AUTH_QUERY = "auth";
static char * ENABLE_QUERY = "enable";
static char * DISABLE_QUERY = "disable";
static char * HTTP_SCHEME = "http://";
static char * HTTPS_SCHEME = "https://";
int get_status(pihole_config * config) { int get_status(pihole_config * config) {
write_log(PIHELPER_LOG_DEBUG, "Getting Pi-hole status…"); write_log(PIHELPER_LOG_DEBUG, "Getting Pi-hole status…");
char * formatted_host = prepend_scheme(config->host); char * formatted_host = prepend_scheme(config->host);
@ -41,11 +33,11 @@ int get_status(pihole_config * config) {
free(formatted_host); free(formatted_host);
if (response == NULL) { if (response == NULL) {
write_log(PIHELPER_LOG_ERROR, "Failed to retrieve status for Pi-hole at %s\n", config->host); write_log(PIHELPER_LOG_ERROR, "Failed to retrieve status for Pi-hole at %s\n", config->host);
return 1; return PIHELPER_OPERATION_FAILED;
} else { } else {
parse_status(response); int status = parse_status(response);
free(response); free(response);
return 0; return status;
} }
} }
@ -57,11 +49,11 @@ int enable_pihole(pihole_config * config) {
char * response = get(formatted_host); char * response = get(formatted_host);
free(formatted_host); free(formatted_host);
if (response == NULL) { if (response == NULL) {
return 1; return PIHELPER_OPERATION_FAILED;
} else { } else {
parse_status(response); int status = parse_status(response);
free(response); free(response);
return 0; return status;
} }
} }
@ -77,11 +69,11 @@ int disable_pihole(pihole_config * config, char * duration) {
char * response = get(formatted_host); char * response = get(formatted_host);
free(formatted_host); free(formatted_host);
if (response == NULL) { if (response == NULL) {
return 1; return PIHELPER_OPERATION_FAILED;
} else { } else {
parse_status(response); int status = parse_status(response);
free(response); free(response);
return 0; return status;
} }
} }
@ -145,10 +137,11 @@ static char * prepend_scheme(char * raw_host) {
return formatted_host; return formatted_host;
} }
static void parse_status(char * raw_json) { static int parse_status(char * raw_json) {
json_tokener *tok = json_tokener_new(); json_tokener *tok = json_tokener_new();
json_object *jobj = NULL; json_object *jobj = NULL;
int stringlen = 0; int stringlen = 0;
int retval = PIHELPER_OPERATION_FAILED;
enum json_tokener_error jerr; enum json_tokener_error jerr;
do { do {
stringlen = strlen(raw_json); stringlen = strlen(raw_json);
@ -157,19 +150,24 @@ static void parse_status(char * raw_json) {
if (jerr != json_tokener_success) { if (jerr != json_tokener_success) {
write_log(PIHELPER_LOG_ERROR, "Failed to parse JSON: %s", json_tokener_error_desc(jerr)); write_log(PIHELPER_LOG_ERROR, "Failed to parse JSON: %s", json_tokener_error_desc(jerr));
json_tokener_free(tok); json_tokener_free(tok);
return; return retval;
} }
write_log(PIHELPER_LOG_DEBUG, "%s", json_object_to_json_string_ext(jobj, JSON_C_TO_STRING_PRETTY)); write_log(PIHELPER_LOG_DEBUG, "%s", json_object_to_json_string_ext(jobj, JSON_C_TO_STRING_PRETTY));
json_object *status; json_object *status;
const char * status_string; const char * status_string;
if (json_pointer_get(jobj, "/status", &status) == 0 if (json_pointer_get(jobj, "/status", &status) == 0
&& (status_string = json_object_get_string(status)) != NULL) { && (status_string = json_object_get_string(status)) != NULL) {
printf("Pi-hole status: %s\n", status_string); if (strstr(status_string, "enabled") == status_string) {
retval = PIHELPER_ENABLED;
} else if (strstr(status_string, "disabled") == status_string) {
retval = PIHELPER_DISABLED;
}
} else { } else {
write_log(PIHELPER_LOG_DEBUG, "Unable to parse response: %s", raw_json); write_log(PIHELPER_LOG_DEBUG, "Unable to parse response: %s", raw_json);
} }
json_tokener_free(tok); json_tokener_free(tok);
json_object_put(jobj); json_object_put(jobj);
return retval;
} }
static void append_query_parameter(char ** host, char * key, char * value) { static void append_query_parameter(char ** host, char * key, char * value) {

View file

@ -19,6 +19,14 @@
#ifndef PIHELPER_NETWORK #ifndef PIHELPER_NETWORK
#define PIHELPER_NETWORK #define PIHELPER_NETWORK
#define URL_FORMAT "http://%s/admin/api.php"
#define URL_FORMAT_LEN 22
#define AUTH_QUERY "auth"
#define ENABLE_QUERY "enable"
#define DISABLE_QUERY "disable"
#define HTTP_SCHEME "http://"
#define HTTPS_SCHEME "https://"
typedef struct { typedef struct {
size_t size; size_t size;
char * body; char * body;
@ -51,7 +59,7 @@ int disable_pihole(pihole_config * config, char * duration);
static char * get(char endpoint[]); static char * get(char endpoint[]);
static void parse_status(char * raw_json); static int parse_status(char * raw_json);
static void append_query_parameter(char ** host, char * key, char * value); static void append_query_parameter(char ** host, char * key, char * value);

View file

@ -18,42 +18,116 @@
*/ */
#ifndef PIHELPER #ifndef PIHELPER
#define PIHELPER #define PIHELPER
static int PIHELPER_OK = 0;
static int PIHELPER_HELP = 1;
static int PIHELPER_INVALID_COMMANDS = 2;
static int PIHELPER_LOG_DISABLED = -1; /**
static int PIHELPER_LOG_ERROR = 0; * Use this with pihelper_set_log_level() to disable logging
static int PIHELPER_LOG_WARN = 1; */
static int PIHELPER_LOG_INFO = 2; #define PIHELPER_LOG_DISABLED -1
static int PIHELPER_LOG_DEBUG = 3;
/**
* Use this with pihelper_set_log_level() to only log error messages
*/
#define PIHELPER_LOG_ERROR 0
/**
* Use this with pihelper_set_log_level() to log error and warning messages
*/
#define PIHELPER_LOG_WARN 1
/**
* Use this with pihelper_set_log_level() to log error, warning, and info messages
*/
#define PIHELPER_LOG_INFO 2
/**
* Use this with pihelper_set_log_level() to print all log messages
*/
#define PIHELPER_LOG_DEBUG 3
/**
* The return code used when a Pi-hole operation fails
*/
#define PIHELPER_OPERATION_FAILED -1
/**
* The return code used to denote that the Pi-hole is enabled
*/
#define PIHELPER_ENABLED 0
/**
* The return code used to denote that the Pi-hole is disabled
*/
#define PIHELPER_DISABLED 1
typedef struct { typedef struct {
char * host; char * host;
char * api_key; char * api_key;
} pihole_config; } pihole_config;
/**
* Call this to change the logging level with one of the PIHELPER_LOG_* constants
*/
void pihelper_set_log_level(int level); void pihelper_set_log_level(int level);
/**
* Retrieve the status of the pi-hole. This method does not require an API key to succeed.
* @return PIHELPER_OPERATION_FAILED on failure, or either PIHELPER_ENABLED or PIHELPER_DISABLED
*/
int pihelper_get_status(pihole_config * config); int pihelper_get_status(pihole_config * config);
/**
* Enable the pi-hole. This method requires a valid API key to succeed.
* @return PIHELPER_OPERATION_FAILED on failure, or either PIHELPER_ENABLED or PIHELPER_DISABLED
*/
int pihelper_enable_pihole(pihole_config * config); int pihelper_enable_pihole(pihole_config * config);
/**
* Disable the pi-hole. This method requires a valid API key to succeed.
* @return PIHELPER_OPERATION_FAILED on failure, or either PIHELPER_ENABLED or PIHELPER_DISABLED
*/
int pihelper_disable_pihole(pihole_config * config, char * duration); int pihelper_disable_pihole(pihole_config * config, char * duration);
/**
* Create a new pihole_config object. The pointer returned here should be passed to pihelper_free_config()
* when it is no longer needed;
* @return A pointer to a pihole_config object or NULL if the system doesn't have enough memory
*/
pihole_config * pihelper_new_config(); pihole_config * pihelper_new_config();
/**
* Sets the host for a given config. The memory will be copied, so you can free your copy once it's been
* passed to the config object.
*/
void pihelper_config_set_host(pihole_config * config, char * host); void pihelper_config_set_host(pihole_config * config, char * host);
/**
* Sets the password for a given config. The password will be hashed and converted to an API key. Call this
* if you don't already have the API key, otherwise call pihelper_config_set_api_key(). The memory will be
* copied, so you can free your copy once it's been passed to the config object.
*/
void pihelper_config_set_password(pihole_config * config, char * password); void pihelper_config_set_password(pihole_config * config, char * password);
/**
* Sets the API key for a given config. The API key is a 64-character double SHA256 hash of the password. If
* you don't have this, call pihelper_config_set_password() instead. The memory will be copied, so you can
* free your copy once it's been passed to the config object.
*/
void pihelper_config_set_api_key(pihole_config * config, char * api_key); void pihelper_config_set_api_key(pihole_config * config, char * api_key);
/**
* Read the PiHelper config from a file at the given path.
*/
pihole_config * pihelper_read_config(char * config_path); pihole_config * pihelper_read_config(char * config_path);
/**
* Save the PiHelper config to a file at the given path.
*/
int pihelper_save_config(pihole_config * config, char * config_path); int pihelper_save_config(pihole_config * config, char * config_path);
/**
* Clean up all memory associated with a pihole_config object.
*/
void pihelper_free_config(pihole_config * config); void pihelper_free_config(pihole_config * config);
#endif #endif