v1.c (3206B)
1 #include <time.h>
2 #include <xlocale.h>
3 #include <yajl/yajl_gen.h>
4 #include <yajl/yajl_tree.h>
5 #include <kore/kore.h>
6 #include <kore/http.h>
7 #include <kore/jsonrpc.h>
8
9 int v1(struct http_request *);
10
11 static int
12 write_string(struct jsonrpc_request *req, void *ctx)
13 {
14 const unsigned char *str = (unsigned char *)ctx;
15
16 return yajl_gen_string(req->gen, str, strlen((const char *)str));
17 }
18
19 static int
20 write_string_array_params(struct jsonrpc_request *req, void *ctx)
21 {
22 int status = 0;
23
24 if (!YAJL_GEN_KO(status = yajl_gen_array_open(req->gen))) {
25 for (size_t i = 0; i < req->params->u.array.len; i++) {
26 yajl_val yajl_str = req->params->u.array.values[i];
27 char *str = YAJL_GET_STRING(yajl_str);
28
29 if (YAJL_GEN_KO(status = yajl_gen_string(req->gen,
30 (unsigned char *)str, strlen(str))))
31 break;
32 }
33 if (status == 0)
34 status = yajl_gen_array_close(req->gen);
35 }
36
37 return status;
38 }
39
40 int
41 v1(struct http_request *http_req)
42 {
43 struct jsonrpc_request req;
44 int ret;
45
46 /* We only allow POST/PUT methods. */
47 if (http_req->method != HTTP_METHOD_POST &&
48 http_req->method != HTTP_METHOD_PUT) {
49 http_response_header(http_req, "allow", "POST, PUT");
50 http_response(http_req, HTTP_STATUS_METHOD_NOT_ALLOWED, NULL, 0);
51 return (KORE_RESULT_OK);
52 }
53
54 /* Read JSON-RPC request. */
55 if ((ret = jsonrpc_read_request(http_req, &req)) != 0)
56 return jsonrpc_error(&req, ret, NULL);
57
58 /* Echo command takes and gives back params. */
59 if (strcmp(req.method, "echo") == 0) {
60 if (!YAJL_IS_ARRAY(req.params)) {
61 jsonrpc_log(&req, LOG_ERR,
62 "Echo only accepts positional params");
63 return jsonrpc_error(&req, JSONRPC_INVALID_PARAMS, NULL);
64 }
65 for (size_t i = 0; i < req.params->u.array.len; i++) {
66 yajl_val v = req.params->u.array.values[i];
67 if (!YAJL_IS_STRING(v)) {
68 jsonrpc_log(&req, -3,
69 "Echo only accepts strings");
70 return jsonrpc_error(&req,
71 JSONRPC_INVALID_PARAMS, NULL);
72 }
73 }
74 return jsonrpc_result(&req, write_string_array_params, NULL);
75 }
76
77 /* Date command displays date and time according to parameters. */
78 if (strcmp(req.method, "date") == 0) {
79 time_t time_value;
80 struct tm time_info;
81 char timestamp[33];
82 struct tm *(*gettm)(const time_t *, struct tm *) =
83 localtime_r;
84
85 if (YAJL_IS_OBJECT(req.params)) {
86 const char *path[] = {"local", NULL};
87 yajl_val bf;
88
89 bf = yajl_tree_get(req.params, path, yajl_t_false);
90 if (bf != NULL)
91 gettm = gmtime_r;
92 } else if (req.params != NULL) {
93 jsonrpc_log(&req, LOG_ERR,
94 "Date only accepts named params");
95 return jsonrpc_error(&req, JSONRPC_INVALID_PARAMS, NULL);
96 }
97
98 if ((time_value = time(NULL)) == -1)
99 return jsonrpc_error(&req, -2,
100 "Failed to get date time");
101
102 if (gettm(&time_value, &time_info) == NULL)
103 return jsonrpc_error(&req, -3,
104 "Failed to get date time info");
105
106 memset(timestamp, 0, sizeof(timestamp));
107 if (strftime_l(timestamp, sizeof(timestamp) - 1, "%c",
108 &time_info, LC_GLOBAL_LOCALE) == 0)
109 return jsonrpc_error(&req, -4,
110 "Failed to get printable date time");
111
112 return jsonrpc_result(&req, write_string, timestamp);
113 }
114
115 return jsonrpc_error(&req, JSONRPC_METHOD_NOT_FOUND, NULL);
116 }