]> git.datanom.net - caldav.git/blob - test-app/cmdline-parser.c
Add TODO
[caldav.git] / test-app / cmdline-parser.c
1 /*
2 * cmdline-parser.c
3 *
4 * Copyright 2017 Michael Rasmussen <mir@datanom.net>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19 * MA 02110-1301, USA.
20 */
21
22 #ifdef HAVE_CONFIG_H
23 # include "config.h"
24 #endif
25
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <getopt.h>
29 #include <glib.h>
30 #include <string.h>
31 #include <sys/types.h>
32 #include <sys/stat.h>
33 #include <unistd.h>
34
35 #include "cmdline-parser.h"
36 #include "caldav.h"
37
38 static const gchar* help[] = {
39 "Usage: test-app [Options] -o operation -p password -u username URL",
40 "",
41 "a|data Use this option to insert calendar data from file.",
42 " As an alternative use redirect IO with <.",
43 "d|debug Print a lot of debug information to STDOUT",
44 "e|etag ETag to use for update and delete",
45 "f|finish End time interval in ISO 8601 local time. 2017-01-13T13:13:13",
46 "h|help Show this help info.",
47 "r|href HREFs to use for getobjects. Each href on a separate line.",
48 " As an alternative use redirect IO with <.",
49 "s|start Start time interval in ISO 8601 local time. 2017-01-13T13:13:13",
50 NULL
51 };
52
53 static void show_help() {
54 for (int i = 0; help[i]; i++) {
55 printf("%s\n", help[i]);
56 }
57 }
58
59 static void get_operation(const gchar* op, Operation* o) {
60 if (o) {
61 if (g_strcmp0("CALENDARINFO", op) == 0) {
62 *o = CALENDARINFO;
63 } else if (g_strcmp0("GETOBJECTS", op) == 0) {
64 *o = GETOBJECTS;
65 } else if (g_strcmp0("GETALLOBJECTS", op) == 0) {
66 *o = GETALLOBJECTS;
67 } else if (g_strcmp0("SIMPLEGET", op) == 0) {
68 *o = SIMPLEGET;
69 } else if (g_strcmp0("CHANGEINFO", op) == 0) {
70 *o = CHANGEINFO;
71 } else if (g_strcmp0("UPDATEOBJECTS", op) == 0) {
72 *o = UPDATEOBJECTS;
73 } else if (g_strcmp0("ADDOBJECTS", op) == 0) {
74 *o = ADDOBJECTS;
75 } else if (g_strcmp0("DELETEOBJECTS", op) == 0) {
76 *o = DELETEOBJECTS;
77 } else if (g_strcmp0("DISCOVER", op) == 0) {
78 *o = DISCOVER;
79 } else if (g_strcmp0("OPTIONSINFO", op) == 0) {
80 *o = OPTIONSINFO;
81 } else if (g_strcmp0("FREEBUSY", op) == 0) {
82 *o = FREEBUSY;
83 } else {
84 *o = UNKNOWN;
85 }
86 }
87 }
88
89 static gboolean invalid_test_case(Runtime* test) {
90 gboolean invalid = TRUE;
91 gboolean error = FALSE;
92
93 if (test) {
94 if (!test->username) {
95 printf("Missing username\n");
96 error = TRUE;
97 }
98 if (!test->password) {
99 printf("Missing password\n");
100 error = TRUE;
101 }
102 if (!test->url) {
103 printf("Missing URL\n");
104 error = TRUE;
105 }
106 if (!test->operation) {
107 printf("Missing operation\n");
108 error = TRUE;
109 }
110 invalid = (error) ? TRUE : FALSE;
111 }
112
113 return invalid;
114 }
115
116 #define BUF_SIZE 1024
117 static gchar* read_stream(FILE* stream) {
118 gchar buffer[BUF_SIZE];
119 size_t size = 1;
120 gchar* content = g_malloc0(sizeof(gchar) * BUF_SIZE);
121
122 while (fgets(buffer, BUF_SIZE, stream) != NULL) {
123 size += strlen(buffer);
124 content = g_realloc(content, size);
125 g_strlcat(content, buffer, size);
126 }
127
128 return content;
129 }
130
131 static GSList* parse_input(const gchar* input) {
132 GSList* list = NULL;
133
134 gchar** strings = g_strsplit(input, "\n", 0);
135 for (gchar** h = strings; *h; ++h) {
136 if (g_strcmp0(*h, "") != 0) {
137 HrefData* hd = href_data_new(*h, NULL);
138 list = g_slist_append(list, hd);
139 }
140 }
141 g_strfreev(strings);
142
143 return list;
144 }
145
146 Runtime* parse_cmdline(int argc, char **argv) {
147 int opt = 0;
148 int debug_flag = 0;
149 Runtime* test = runtime_new();
150 Operation* op = g_new(Operation, 1);
151 FILE* stream = NULL;
152
153 struct option long_options[] = {
154 {"data", required_argument, 0, 'a'},
155 {"etag", required_argument, 0, 'e'},
156 {"finish", required_argument, 0, 'f'},
157 {"debug", no_argument, &debug_flag, 1 },
158 {"help", no_argument, 0, 'h'},
159 {"operation", required_argument, 0, 'o'},
160 {"password", required_argument, 0, 'p'},
161 {"href", required_argument, 0, 'r'},
162 {"start", required_argument, 0, 's'},
163 {"username", required_argument, 0, 'u'},
164 {0, 0, 0, 0 }
165 };
166
167 int option_index = 0;
168 while ((opt = getopt_long(argc, argv, "a:de:f:h:o:p:rs:u:",
169 long_options, &option_index)) != -1) {
170 switch (opt) {
171 case 'a': {
172 stream = fopen(optarg, "r");
173 if (!stream) {
174 perror("File");
175 runtime_free(test);
176 exit(EXIT_FAILURE);
177 }
178 break;
179 }
180
181 case 'd':
182 debug_flag = 1;
183 break;
184
185 case 'e':
186 test->etag = g_strdup(optarg);
187 break;
188
189 case 'f':
190 test->finish = get_date_time_from_string(optarg);
191 break;
192
193 case 'h':
194 runtime_free(test);
195 show_help();
196 exit(EXIT_SUCCESS);
197
198 case 'o':
199 get_operation(optarg, op);
200 if (op && *op != UNKNOWN) {
201 test->operation = op;
202 } else {
203 runtime_free(test);
204 fprintf(stderr, "%s: Invalid operation\n", optarg);
205 show_help();
206 exit(EXIT_FAILURE);
207 }
208 break;
209
210 case 'p':
211 test->password = g_strdup(optarg);
212 break;
213
214 case 'r': {
215 stream = fopen(optarg, "r");
216 if (!stream) {
217 perror("File");
218 runtime_free(test);
219 exit(EXIT_FAILURE);
220 }
221 break;
222 }
223
224 case 's':
225 test->start = get_date_time_from_string(optarg);
226 break;
227
228 case 'u':
229 test->username = g_strdup(optarg);
230 break;
231
232 case ':':
233 /* missing option argument */
234 runtime_free(test);
235 printf("%s: option '-%c' requires an argument\n", argv[0], optopt);
236 show_help();
237 exit(EXIT_FAILURE);
238
239 case '?':
240 default:
241 /* invalid option */
242 runtime_free(test);
243 fprintf(stderr, "%s: option '-%c' is invalid: ignored\n", argv[0], optopt);
244 show_help();
245 exit(EXIT_FAILURE);
246 }
247 }
248
249 if (optind + 1 < argc) {
250 runtime_free(test);
251 printf("Only one URL allowed\n");
252 show_help();
253 exit(EXIT_FAILURE);
254 }
255
256 test->url= g_strdup(argv[optind]);
257
258 if (invalid_test_case(test)) {
259 runtime_free(test);
260 show_help();
261 exit(EXIT_FAILURE);
262 }
263
264 if (*test->operation == ADDOBJECTS || *test->operation == UPDATEOBJECTS) {
265 struct stat sb;
266 if (fstat(fileno(stdin), &sb) == -1) {
267 if (!stream) {
268 perror("Stat");
269 runtime_free(test);
270 exit(EXIT_FAILURE);
271 }
272 } else {
273 if (stream && sb.st_size > 0) {
274 fprintf(stderr, "Error: Option --data or --href active. Cannot redirect STDIN\n");
275 runtime_free(test);
276 exit(EXIT_FAILURE);
277 } else {
278 stream = (stream) ? stream : stdin;
279 }
280 }
281
282 gchar* text = read_stream(stream);
283
284 switch (*test->operation) {
285 case GETOBJECTS:
286 test->hrefs = parse_input(text);
287 g_free(text);
288 break;
289 case UPDATEOBJECTS:
290 case ADDOBJECTS:
291 test->component = text;
292 break;
293 default:
294 fprintf(stderr, "%i: Input not allowed\n", *test->operation);
295 runtime_free(test);
296 g_free(text);
297 exit(EXIT_FAILURE);
298 }
299 }
300
301 test->debug = (debug_flag) ? TRUE : FALSE;
302
303 return test;
304 }
305
This page took 0.080634 seconds and 6 git commands to generate.