X-Git-Url: http://git.datanom.net/caldav.git/blobdiff_plain/7f587903cb1680dc6d9a70603a9db396dc645627..e1b22e2b5b944589477889b759029f8fe104a731:/test-app/cmdline-parser.c diff --git a/test-app/cmdline-parser.c b/test-app/cmdline-parser.c new file mode 100644 index 0000000..747e3d7 --- /dev/null +++ b/test-app/cmdline-parser.c @@ -0,0 +1,305 @@ +/* + * cmdline-parser.c + * + * Copyright 2017 Michael Rasmussen + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "cmdline-parser.h" +#include "caldav.h" + +static const gchar* help[] = { + "Usage: test-app [Options] -o operation -p password -u username URL", + "", + "a|data Use this option to insert calendar data from file.", + " As an alternative use redirect IO with <.", + "d|debug Print a lot of debug information to STDOUT", + "e|etag ETag to use for update and delete", + "f|finish End time interval in ISO 8601 local time. 2017-01-13T13:13:13", + "h|help Show this help info.", + "r|href HREFs to use for getobjects. Each href on a separate line.", + " As an alternative use redirect IO with <.", + "s|start Start time interval in ISO 8601 local time. 2017-01-13T13:13:13", + NULL +}; + +static void show_help() { + for (int i = 0; help[i]; i++) { + printf("%s\n", help[i]); + } +} + +static void get_operation(const gchar* op, Operation* o) { + if (o) { + if (g_strcmp0("CALENDARINFO", op) == 0) { + *o = CALENDARINFO; + } else if (g_strcmp0("GETOBJECTS", op) == 0) { + *o = GETOBJECTS; + } else if (g_strcmp0("GETALLOBJECTS", op) == 0) { + *o = GETALLOBJECTS; + } else if (g_strcmp0("SIMPLEGET", op) == 0) { + *o = SIMPLEGET; + } else if (g_strcmp0("CHANGEINFO", op) == 0) { + *o = CHANGEINFO; + } else if (g_strcmp0("UPDATEOBJECTS", op) == 0) { + *o = UPDATEOBJECTS; + } else if (g_strcmp0("ADDOBJECTS", op) == 0) { + *o = ADDOBJECTS; + } else if (g_strcmp0("DELETEOBJECTS", op) == 0) { + *o = DELETEOBJECTS; + } else if (g_strcmp0("DISCOVER", op) == 0) { + *o = DISCOVER; + } else if (g_strcmp0("OPTIONSINFO", op) == 0) { + *o = OPTIONSINFO; + } else if (g_strcmp0("FREEBUSY", op) == 0) { + *o = FREEBUSY; + } else { + *o = UNKNOWN; + } + } +} + +static gboolean invalid_test_case(Runtime* test) { + gboolean invalid = TRUE; + gboolean error = FALSE; + + if (test) { + if (!test->username) { + printf("Missing username\n"); + error = TRUE; + } + if (!test->password) { + printf("Missing password\n"); + error = TRUE; + } + if (!test->url) { + printf("Missing URL\n"); + error = TRUE; + } + if (!test->operation) { + printf("Missing operation\n"); + error = TRUE; + } + invalid = (error) ? TRUE : FALSE; + } + + return invalid; +} + +#define BUF_SIZE 1024 +static gchar* read_stream(FILE* stream) { + gchar buffer[BUF_SIZE]; + size_t size = 1; + gchar* content = g_malloc0(sizeof(gchar) * BUF_SIZE); + + while (fgets(buffer, BUF_SIZE, stream) != NULL) { + size += strlen(buffer); + content = g_realloc(content, size); + g_strlcat(content, buffer, size); + } + + return content; +} + +static GSList* parse_input(const gchar* input) { + GSList* list = NULL; + + gchar** strings = g_strsplit(input, "\n", 0); + for (gchar** h = strings; *h; ++h) { + if (g_strcmp0(*h, "") != 0) { + HrefData* hd = href_data_new(*h, NULL); + list = g_slist_append(list, hd); + } + } + g_strfreev(strings); + + return list; +} + +Runtime* parse_cmdline(int argc, char **argv) { + int opt = 0; + int debug_flag = 0; + Runtime* test = runtime_new(); + Operation* op = g_new(Operation, 1); + FILE* stream = NULL; + + struct option long_options[] = { + {"data", required_argument, 0, 'a'}, + {"etag", required_argument, 0, 'e'}, + {"finish", required_argument, 0, 'f'}, + {"debug", no_argument, &debug_flag, 1 }, + {"help", no_argument, 0, 'h'}, + {"operation", required_argument, 0, 'o'}, + {"password", required_argument, 0, 'p'}, + {"href", required_argument, 0, 'r'}, + {"start", required_argument, 0, 's'}, + {"username", required_argument, 0, 'u'}, + {0, 0, 0, 0 } + }; + + int option_index = 0; + while ((opt = getopt_long(argc, argv, "a:de:f:h:o:p:rs:u:", + long_options, &option_index)) != -1) { + switch (opt) { + case 'a': { + stream = fopen(optarg, "r"); + if (!stream) { + perror("File"); + runtime_free(test); + exit(EXIT_FAILURE); + } + break; + } + + case 'd': + debug_flag = 1; + break; + + case 'e': + test->etag = g_strdup(optarg); + break; + + case 'f': + test->finish = get_date_time_from_string(optarg); + break; + + case 'h': + runtime_free(test); + show_help(); + exit(EXIT_SUCCESS); + + case 'o': + get_operation(optarg, op); + if (op && *op != UNKNOWN) { + test->operation = op; + } else { + runtime_free(test); + fprintf(stderr, "%s: Invalid operation\n", optarg); + show_help(); + exit(EXIT_FAILURE); + } + break; + + case 'p': + test->password = g_strdup(optarg); + break; + + case 'r': { + stream = fopen(optarg, "r"); + if (!stream) { + perror("File"); + runtime_free(test); + exit(EXIT_FAILURE); + } + break; + } + + case 's': + test->start = get_date_time_from_string(optarg); + break; + + case 'u': + test->username = g_strdup(optarg); + break; + + case ':': + /* missing option argument */ + runtime_free(test); + printf("%s: option '-%c' requires an argument\n", argv[0], optopt); + show_help(); + exit(EXIT_FAILURE); + + case '?': + default: + /* invalid option */ + runtime_free(test); + fprintf(stderr, "%s: option '-%c' is invalid: ignored\n", argv[0], optopt); + show_help(); + exit(EXIT_FAILURE); + } + } + + if (optind + 1 < argc) { + runtime_free(test); + printf("Only one URL allowed\n"); + show_help(); + exit(EXIT_FAILURE); + } + + test->url= g_strdup(argv[optind]); + + if (invalid_test_case(test)) { + runtime_free(test); + show_help(); + exit(EXIT_FAILURE); + } + + if (*test->operation == ADDOBJECTS || *test->operation == UPDATEOBJECTS) { + struct stat sb; + if (fstat(fileno(stdin), &sb) == -1) { + if (!stream) { + perror("Stat"); + runtime_free(test); + exit(EXIT_FAILURE); + } + } else { + if (stream && sb.st_size > 0) { + fprintf(stderr, "Error: Option --data or --href active. Cannot redirect STDIN\n"); + runtime_free(test); + exit(EXIT_FAILURE); + } else { + stream = (stream) ? stream : stdin; + } + } + + gchar* text = read_stream(stream); + + switch (*test->operation) { + case GETOBJECTS: + test->hrefs = parse_input(text); + g_free(text); + break; + case UPDATEOBJECTS: + case ADDOBJECTS: + test->component = text; + break; + default: + fprintf(stderr, "%i: Input not allowed\n", *test->operation); + runtime_free(test); + g_free(text); + exit(EXIT_FAILURE); + } + } + + test->debug = (debug_flag) ? TRUE : FALSE; + + return test; +} +