removed useless empty line
[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 <log.h>
28 #include "note.h"
29 #include "tw.h"
30
31 static int has_taskrc()
32 {
33         char *home, *path;
34         int ret;
35         struct stat st;
36
37         home = getenv("HOME");
38
39         if (!home) {
40                 log_err("HOME environment variable not defined");
41                 return 0;
42         }
43
44         path = malloc(strlen(home) + 1 + strlen(".taskrc") + 1);
45         sprintf(path, "%s/%s", home, ".taskrc");
46
47         ret = lstat(path, &st);
48
49         free(path);
50
51         return ret == 0;
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         log_debug("execute: %s", 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                 log_err("pclose fails");
92
93  exit_free:
94         free(cmd);
95
96         return str;
97 }
98
99 static struct json_object *task_exec_json(char *opts)
100 {
101         struct json_object *o;
102         char *str;
103
104         str = task_exec(opts);
105
106         if (str) {
107                 o = json_tokener_parse(str);
108                 free(str);
109                 return o;
110         }
111
112         return NULL;
113 }
114
115 struct task **tw_get_all_tasks(const char *status)
116 {
117         int i, n;
118         struct json_object *jtasks, *jtask, *json;
119         struct task **tasks;
120         char *opts;
121
122         opts = malloc(strlen("export status:") + strlen(status) + 1);
123         sprintf(opts, "export status:%s", status);
124
125         jtasks = task_exec_json(opts);
126         free(opts);
127
128         if (!jtasks)
129                 return NULL;
130
131         n = json_object_array_length(jtasks);
132
133         tasks = malloc((n + 1) * sizeof(struct task *));
134
135         for (i = 0; i < n; i++) {
136                 jtask = json_object_array_get_idx(jtasks, i);
137
138                 tasks[i] = malloc(sizeof(struct task));
139
140                 json = json_object_object_get(jtask, "id");
141                 tasks[i]->id = json_object_get_int(json);
142
143                 json = json_object_object_get(jtask, "description");
144                 tasks[i]->description = strdup(json_object_get_string(json));
145
146                 json = json_object_object_get(jtask, "status");
147                 tasks[i]->status = strdup(json_object_get_string(json));
148
149                 json = json_object_object_get(jtask, "project");
150                 if (json)
151                         tasks[i]->project
152                                 = strdup(json_object_get_string(json));
153                 else
154                         tasks[i]->project = NULL;
155
156                 json = json_object_object_get(jtask, "priority");
157                 if (json)
158                         tasks[i]->priority
159                                 = strdup(json_object_get_string(json));
160                 else
161                         tasks[i]->priority = strdup("");
162
163                 json = json_object_object_get(jtask, "uuid");
164                 tasks[i]->uuid = strdup(json_object_get_string(json));
165
166                 tasks[i]->note = note_get(tasks[i]->uuid);
167         }
168
169         tasks[n] = NULL;
170
171         json_object_put(jtasks);
172
173         return tasks;
174 }
175
176 static char *escape(const char *txt)
177 {
178         char *result;
179         char *c;
180
181         result = malloc(2*strlen(txt)+1);
182         c = result;
183
184         while (*txt) {
185                 switch (*txt) {
186                 case '"':
187                         *c = '\\'; c++;
188                         *c = '"';
189                         break;
190                 case '$':
191                         *c = '\\'; c++;
192                         *c = '$';
193                         break;
194                 case '&':
195                         *c = '\\'; c++;
196                         *c = '&';
197                         break;
198                 default:
199                         *c = *txt;
200                 }
201                 c++;
202                 txt++;
203         }
204
205         *c = '\0';
206
207         return result;
208 }
209
210 void tw_modify_description(const char *uuid, const char *newdesc)
211 {
212         char *str;
213         char *opts;
214
215         str = escape(newdesc);
216
217         opts = malloc(1
218                       + strlen(uuid)
219                       + strlen(" modify :\"")
220                       + strlen(str)
221                       + strlen("\"")
222                       + 1);
223         sprintf(opts, " %s modify \"%s\"", uuid, str);
224
225         task_exec(opts);
226
227         free(str);
228         free(opts);
229 }
230
231 void tw_modify_project(const char *uuid, const char *newproject)
232 {
233         char *str;
234         char *opts;
235
236         str = escape(newproject);
237
238         opts = malloc(1
239                       + strlen(uuid)
240                       + strlen(" modify project:\"")
241                       + strlen(str)
242                       + strlen("\"")
243                       + 1);
244         sprintf(opts, " %s modify project:\"%s\"", uuid, str);
245
246         task_exec(opts);
247
248         free(str);
249         free(opts);
250 }
251
252 void tw_modify_priority(const char *uuid, const char *priority)
253 {
254         char *str;
255         char *opts;
256
257         str = escape(priority);
258
259         opts = malloc(1
260                       + strlen(uuid)
261                       + strlen(" modify priority:\"")
262                       + strlen(str)
263                       + strlen("\"")
264                       + 1);
265         sprintf(opts, " %s modify priority:\"%s\"", uuid, str);
266
267         task_exec(opts);
268
269         free(str);
270         free(opts);
271 }
272
273 void tw_add(const char *newdesc)
274 {
275         char *str;
276         char *opts;
277
278         str = escape(newdesc);
279
280         opts = malloc(1
281                       + strlen(" add \"")
282                       + strlen(str)
283                       + strlen("\"")
284                       + 1);
285         sprintf(opts, " add \"%s\"", str);
286
287         task_exec(opts);
288
289         free(str);
290         free(opts);
291 }
292
293 void tw_done(const char *uuid)
294 {
295         char *opts;
296
297         opts = malloc(1
298                       + strlen(uuid)
299                       + strlen(" done")
300                       + 1);
301         sprintf(opts, " %s done", uuid);
302
303         task_exec(opts);
304
305         free(opts);
306 }
307
308 static void task_free(struct task *task)
309 {
310         if (!task)
311                 return ;
312
313         free(task->description);
314         free(task->status);
315         free(task->uuid);
316         free(task->note);
317         free(task->project);
318         free(task->priority);
319
320         free(task);
321 }
322
323 void tw_task_list_free(struct task **tasks)
324 {
325         struct task **cur;
326
327         if (!tasks)
328                 return ;
329
330         for (cur = tasks; *cur; cur++)
331                 task_free(*cur);
332
333         free(tasks);
334 }