/* * 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; }