diff options
-rw-r--r-- | src/config.c | 74 | ||||
-rw-r--r-- | src/config.h | 5 | ||||
-rw-r--r-- | tests/fixtures/normal.ini | 2 | ||||
-rw-r--r-- | tests/test_config.c | 2 |
4 files changed, 77 insertions, 6 deletions
diff --git a/src/config.c b/src/config.c index 7f610a6..f143f55 100644 --- a/src/config.c +++ b/src/config.c @@ -10,6 +10,7 @@ #include <stdio.h> #include <stdlib.h> #include <string.h> +#include <sys/errno.h> #include <sys/mman.h> #include <sys/stat.h> #include <unistd.h> @@ -80,6 +81,70 @@ static char *trim(char *start, char *end) return start; } +/** + * Parse a token value from the config file. + * If the token is a file path, read the file and set the token to its contents. + * If not a file path, the raw token value is checked for validity. + * It then checks that the token starts with: + * - "ghp_" + * - "gho_" + * - "ghu_" + * - "ghs_" + * - "ghf_" + * @param value token value + * @param cfg config struct + * @return 0 on success, -1 on error + */ +static int parse_token(char *value, struct config *cfg) +{ + char *token = value; + + // Open the file to check if it is a file + const int fd = open(value, O_RDONLY); + if (fd == -1) { + if (errno != ENOENT) { + perror("Error opening token file"); + return -1; + } + // Not a file, token check + cfg->token_owned = 0; + goto token_check; + } + + // Read the file + token = malloc(64); + if (!token) { + perror("Error allocating token buffer"); + close(fd); + return -1; + } + + // Read the file contents + const ssize_t bytes_read = read(fd, token, 64); + if (bytes_read < 0) { + perror("Error reading token file"); + free(token); + close(fd); + return -1; + } + token[bytes_read] = '\0'; + + cfg->token_owned = 1; + close(fd); + +token_check: + if (!strncmp(token, "ghp_", 4) || !strncmp(token, "gho_", 4) || + !strncmp(token, "ghu_", 4) || !strncmp(token, "ghs_", 4) || + !strncmp(token, "ghf_", 4)) { + cfg->token = token; + } else { + fprintf(stderr, "Error: invalid token format: %s\n", token); + free(token); + return -1; + } + return 0; +} + static int parse_line_inner(struct config *cfg, enum config_section section, char *key, char *value) { @@ -92,9 +157,10 @@ static int parse_line_inner(struct config *cfg, enum config_section section, case section_github: if (!strcmp(key, "endpoint")) cfg->endpoint = value; - else if (!strcmp(key, "token")) - cfg->token = value; - else if (!strcmp(key, "user_agent")) + else if (!strcmp(key, "token")) { + if (parse_token(value, cfg) < 0) + return -1; + } else if (!strcmp(key, "user_agent")) cfg->user_agent = value; else if (!strcmp(key, "owner")) cfg->owner = value; @@ -264,5 +330,7 @@ void config_free(struct config *config) if (!config || !config->contents) return; munmap(config->contents, config->contents_len); + if (config->token_owned) + free((char *) config->token); free(config); } diff --git a/src/config.h b/src/config.h index 2fa32d2..ece19d9 100644 --- a/src/config.h +++ b/src/config.h @@ -17,8 +17,11 @@ struct config { char *contents; size_t contents_len; - const char *endpoint; const char *token; + /// Whether the token's memory is owned or borrowed from contents + int token_owned; + + const char *endpoint; const char *user_agent; /// The owner of the repositories diff --git a/tests/fixtures/normal.ini b/tests/fixtures/normal.ini index ad3f9e2..2f2bf4d 100644 --- a/tests/fixtures/normal.ini +++ b/tests/fixtures/normal.ini @@ -1,6 +1,6 @@ [github] endpoint = https://api.github.com/graphql -token = token +token = ghp_1234567890abcdef user_agent = user-agent owner = my-org diff --git a/tests/test_config.c b/tests/test_config.c index 9b4ecbf..5e052a3 100644 --- a/tests/test_config.c +++ b/tests/test_config.c @@ -26,7 +26,7 @@ static void config_read_normal(void **state) struct config *cfg = config_read(path); assert_non_null(cfg); assert_string_equal(cfg->endpoint, "https://api.github.com/graphql"); - assert_string_equal(cfg->token, "token"); + assert_string_equal(cfg->token, "ghp_1234567890abcdef"); assert_string_equal(cfg->user_agent, "user-agent"); assert_string_equal(cfg->owner, "my-org"); assert_string_equal(cfg->git_base, "/srv/git"); |