popup error dialog when .taskrc does not exist
[ptask.git] / src / tw.c
1 /*
2  * Copyright (C) 2012-2013 jeanfi@gmail.com
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License as
6  * published by the Free Software Foundation; either version 2 of the
7  * License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful, but
10  * WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17  * 02110-1301 USA
18  */
19
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <string.h>
23 #include <sys/stat.h>
24
25 #include <json/json.h>
26
27 #include "note.h"
28 #include "tw.h"
29
30 static int has_taskrc()
31 {
32         char *home, *path;
33         int ret;
34         struct stat st;
35
36         home = getenv("HOME");
37
38         if (!home) {
39                 fprintf(stderr, "HOME environment variable not defined\n");
40                 return 0;
41         }
42
43         path = malloc(strlen(home) + 1 + strlen(".taskrc") + 1);
44         sprintf(path, "%s/%s", home, ".taskrc");
45
46         ret = lstat(path, &st);
47
48         free(path);
49
50         return ret == 0;
51
52 }
53
54 static char *task_exec(char *opts)
55 {
56         FILE *f;
57         int ret;
58         size_t s;
59         char *str, *tmp, *cmd, buf[1024];
60
61         if (!has_taskrc())
62                 return NULL;
63
64         cmd = malloc(strlen("task rc.json.array=on ") + strlen(opts) + 1);
65         strcpy(cmd, "task rc.json.array=on ");
66         strcat(cmd, opts);
67
68         printf("execute: %s\n", cmd);
69
70         f = popen(cmd, "r");
71
72         if (!f) {
73                 perror("popen");
74                 str = NULL;
75                 goto exit_free;
76         }
77
78         str = strdup("");
79         while ((s = fread(buf, 1, 1024, f))) {
80                 tmp = malloc(strlen(str) + s + (size_t)1);
81                 memcpy(tmp, str, strlen(str));
82                 memcpy(tmp + strlen(str), buf, s);
83                 tmp[strlen(str) + s] = '\0';
84                 free(str);
85                 str = tmp;
86         }
87
88         ret = pclose(f);
89
90         if (ret == -1) {
91                 printf("pclose fails\n");
92                 perror("pclose");
93         }
94
95  exit_free:
96         free(cmd);
97
98         return str;
99 }
100
101 static struct json_object *task_exec_json(char *opts)
102 {
103         struct json_object *o;
104         char *str;
105
106         str = task_exec(opts);
107
108         if (str) {
109                 o = json_tokener_parse(str);
110                 free(str);
111                 return o;
112         }
113
114         return NULL;
115 }
116
117 struct task **tw_get_all_tasks(const char *status)
118 {
119         int i, n;
120         struct json_object *jtasks, *jtask, *json;
121         struct task **tasks;
122         char *opts;
123
124         opts = malloc(strlen("export status:") + strlen(status) + 1);
125         sprintf(opts, "export status:%s", status);
126
127         jtasks = task_exec_json(opts);
128         free(opts);
129
130         if (!jtasks)
131                 return NULL;
132
133         n = json_object_array_length(jtasks);
134
135         tasks = malloc((n + 1) * sizeof(struct task *));
136
137         for (i = 0; i < n; i++) {
138                 jtask = json_object_array_get_idx(jtasks, i);
139
140                 tasks[i] = malloc(sizeof(struct task));
141
142                 json = json_object_object_get(jtask, "id");
143                 tasks[i]->id = json_object_get_int(json);
144
145                 json = json_object_object_get(jtask, "description");
146                 tasks[i]->description = strdup(json_object_get_string(json));
147
148                 json = json_object_object_get(jtask, "status");
149                 tasks[i]->status = strdup(json_object_get_string(json));
150
151                 json = json_object_object_get(jtask, "project");
152                 if (json)
153                         tasks[i]->project
154                                 = strdup(json_object_get_string(json));
155                 else
156                         tasks[i]->project = NULL;
157
158                 json = json_object_object_get(jtask, "priority");
159                 if (json)
160                         tasks[i]->priority
161                                 = strdup(json_object_get_string(json));
162                 else
163                         tasks[i]->priority = strdup("");
164
165                 json = json_object_object_get(jtask, "uuid");
166                 tasks[i]->uuid = strdup(json_object_get_string(json));
167
168                 tasks[i]->note = note_get(tasks[i]->uuid);
169         }
170
171         tasks[n] = NULL;
172
173         json_object_put(jtasks);
174
175         return tasks;
176 }
177
178 static char *escape(const char *txt)
179 {
180         char *result;
181         char *c;
182
183         result = malloc(2*strlen(txt)+1);
184         c = result;
185
186         while (*txt) {
187                 switch (*txt) {
188                 case '"':
189                         *c = '\\'; c++;
190                         *c = '"';
191                         break;
192                 case '$':
193                         *c = '\\'; c++;
194                         *c = '$';
195                         break;
196                 case '&':
197                         *c = '\\'; c++;
198                         *c = '&';
199                         break;
200                 default:
201                         *c = *txt;
202                 }
203                 c++;
204                 txt++;
205         }
206
207         *c = '\0';
208
209         return result;
210 }
211
212 void tw_modify_description(const char *uuid, const char *newdesc)
213 {
214         char *str;
215         char *opts;
216
217         str = escape(newdesc);
218
219         opts = malloc(1
220                       + strlen(uuid)
221                       + strlen(" modify :\"")
222                       + strlen(str)
223                       + strlen("\"")
224                       + 1);
225         sprintf(opts, " %s modify \"%s\"", uuid, str);
226
227         task_exec(opts);
228
229         free(str);
230         free(opts);
231 }
232
233 void tw_modify_project(const char *uuid, const char *newproject)
234 {
235         char *str;
236         char *opts;
237
238         str = escape(newproject);
239
240         opts = malloc(1
241                       + strlen(uuid)
242                       + strlen(" modify project:\"")
243                       + strlen(str)
244                       + strlen("\"")
245                       + 1);
246         sprintf(opts, " %s modify project:\"%s\"", uuid, str);
247
248         task_exec(opts);
249
250         free(str);
251         free(opts);
252 }
253
254 void tw_modify_priority(const char *uuid, const char *priority)
255 {
256         char *str;
257         char *opts;
258
259         str = escape(priority);
260
261         opts = malloc(1
262                       + strlen(uuid)
263                       + strlen(" modify priority:\"")
264                       + strlen(str)
265                       + strlen("\"")
266                       + 1);
267         sprintf(opts, " %s modify priority:\"%s\"", uuid, str);
268
269         task_exec(opts);
270
271         free(str);
272         free(opts);
273 }
274
275 void tw_add(const char *newdesc)
276 {
277         char *str;
278         char *opts;
279
280         str = escape(newdesc);
281
282         opts = malloc(1
283                       + strlen(" add \"")
284                       + strlen(str)
285                       + strlen("\"")
286                       + 1);
287         sprintf(opts, " add \"%s\"", str);
288
289         task_exec(opts);
290
291         free(str);
292         free(opts);
293 }
294
295 void tw_done(const char *uuid)
296 {
297         char *opts;
298
299         opts = malloc(1
300                       + strlen(uuid)
301                       + strlen(" done")
302                       + 1);
303         sprintf(opts, " %s done", uuid);
304
305         task_exec(opts);
306
307         free(opts);
308 }
309
310 static void task_free(struct task *task)
311 {
312         if (!task)
313                 return ;
314
315         free(task->description);
316         free(task->status);
317         free(task->uuid);
318         free(task->note);
319         free(task->project);
320         free(task->priority);
321
322         free(task);
323 }
324
325 void tw_task_list_free(struct task **tasks)
326 {
327         struct task **cur;
328
329         if (!tasks)
330                 return ;
331
332         for (cur = tasks; *cur; cur++)
333                 task_free(*cur);
334
335         free(tasks);
336 }