Statistics
| Branch: | Tag: | Revision:

root / glue / glue_json.c @ master

History | View | Annotate | Download (71.2 KB)

1
/* 
2
    Copyright (C) 2005-2012  Erik van Pienbroek
3

                
4
    This program is free software; you can redistribute it and/or modify
5
    it under the terms of the GNU General Public License as published by
6
    the Free Software Foundation; either version 2 of the License, or
7
    (at your option) any later version.
8

                
9
    This program is distributed in the hope that it will be useful,
10
    but WITHOUT ANY WARRANTY; without even the implied warranty of
11
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
    GNU 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17
*/
18

                
19
#ifdef HAVE_CONFIG_H
20
#include "config.h"
21
#endif
22

                
23
#include <stdio.h>
24
#include <stdlib.h>
25
#include <string.h>
26

                
27
#include <glib.h>
28
#include <glib-object.h>
29

                
30
#include "nntpgrab.h"
31
#include "nntpgrab_utils.h"
32
#include "nntpgrab_internal.h"
33
#include "nntpgrab_glue.h"
34
#include "nntpgrab_glue_internal.h"
35

                
36
#include "json_object.h"
37
#include "json.h"
38
#include "jsonrpc.h"
39

                
40
static void process_foreach_collection_event(const char *msg, struct json_object *params);
41
static void process_foreach_file_event(const char *msg, struct json_object *params);
42
static void process_foreach_group_event(const char *msg, struct json_object *params);
43

                
44
static struct json_object *
45
get_json_param(const char *msg, struct json_object *params, const char *field, const char *event_name, enum json_type type)
46
{
47
    struct json_object *obj;
48

                
49
    obj = json_object_object_get(params, (char*) field);
50
    if (!obj) {
51
        g_print(__FILE__ ":%i field '%s' is missing for event or method '%s', msg = %s\n", __LINE__, field, event_name, msg);
52
        return NULL;
53
    }
54

                
55
    if (json_object_get_type(obj) != type) {
56
        g_print(__FILE__ ":%i field '%s' is of invalid type for event or method '%s', msg = %s\n", __LINE__, field, event_name, msg);
57
        return NULL;
58
    }
59

                
60
    return obj;
61
}
62

                
63
#define get_param(msg, params, field, event_name, type, dest)                                           \
64
    {                                                                                                   \
65
        struct json_object *obj = get_json_param(msg, params, field, event_name, json_type_ ## type);   \
66
        if (!obj) {                                                                                     \
67
            return;                                                                                     \
68
        }                                                                                               \
69
        dest = json_object_get_ ## type (obj);                                                          \
70
    }
71

                
72
static void
73
emit_part_download_start(const char *msg, struct json_object *params)
74
{
75
    char *servername;
76
    int conn_id;
77
    char *collection_name;
78
    char *subject;
79
    int part_num;
80

                
81
    get_param(msg, params, "servername", "part_download_start", string, servername);
82
    get_param(msg, params, "conn_id", "part_download_start", int, conn_id);
83
    get_param(msg, params, "collection_name", "part_download_start", string, collection_name);
84
    get_param(msg, params, "subject", "part_download_start", string, subject);
85
    get_param(msg, params, "part_num", "part_download_start", int, part_num);
86

                
87
    nntpgrab_core_emit_part_download_start(FALSE, servername, conn_id, collection_name, subject, part_num);
88
}
89

                
90
static void
91
emit_part_done(const char *msg, struct json_object *params)
92
{
93
    char *servername;
94
    int conn_id;
95
    char *collection_name;
96
    char *subject;
97
    int part_num;
98
    int size;
99

                
100
    get_param(msg, params, "servername", "part_done", string, servername);
101
    get_param(msg, params, "conn_id", "part_done", int, conn_id);
102
    get_param(msg, params, "collection_name", "part_done", string, collection_name);
103
    get_param(msg, params, "subject", "part_done", string, subject);
104
    get_param(msg, params, "part_num", "part_done", int, part_num);
105
    get_param(msg, params, "size", "part_done", int, size);
106

                
107
    nntpgrab_core_emit_part_done(FALSE, servername, conn_id, collection_name, subject, part_num, size);
108
}
109

                
110
static void
111
emit_part_failed(const char *msg, struct json_object *params)
112
{
113
    char *servername;
114
    int conn_id;
115
    char *collection_name;
116
    char *subject;
117
    int part_num;
118
    int size;
119
    gboolean all_servers_tried;
120

                
121
    get_param(msg, params, "servername", "part_done", string, servername);
122
    get_param(msg, params, "conn_id", "part_done", int, conn_id);
123
    get_param(msg, params, "collection_name", "part_done", string, collection_name);
124
    get_param(msg, params, "subject", "part_done", string, subject);
125
    get_param(msg, params, "part_num", "part_done", int, part_num);
126
    get_param(msg, params, "size", "part_done", int, size);
127
    get_param(msg, params, "all_servers_tried", "part_done", boolean, all_servers_tried);
128

                
129
    nntpgrab_core_emit_part_failed(FALSE, servername, conn_id, collection_name, subject, part_num, size, all_servers_tried);
130
}
131

                
132
static void
133
emit_traffic_monitor_update(const char *msg, struct json_object *params)
134
{
135
    int bytes_received[10];
136
    int stamp;
137

                
138
    get_param(msg, params, "bytes_received1",  "traffic_monitor_update", int, bytes_received[0]);
139
    get_param(msg, params, "bytes_received2",  "traffic_monitor_update", int, bytes_received[1]);
140
    get_param(msg, params, "bytes_received3",  "traffic_monitor_update", int, bytes_received[2]);
141
    get_param(msg, params, "bytes_received4",  "traffic_monitor_update", int, bytes_received[3]);
142
    get_param(msg, params, "bytes_received5",  "traffic_monitor_update", int, bytes_received[4]);
143
    get_param(msg, params, "bytes_received6",  "traffic_monitor_update", int, bytes_received[5]);
144
    get_param(msg, params, "bytes_received7",  "traffic_monitor_update", int, bytes_received[6]);
145
    get_param(msg, params, "bytes_received8",  "traffic_monitor_update", int, bytes_received[7]);
146
    get_param(msg, params, "bytes_received9",  "traffic_monitor_update", int, bytes_received[8]);
147
    get_param(msg, params, "bytes_received10", "traffic_monitor_update", int, bytes_received[9]);
148
    get_param(msg, params, "stamp", "traffic_monitor_update", int, stamp);
149

                
150
    nntpgrab_core_emit_traffic_monitor_update(FALSE, bytes_received, stamp);
151
}
152

                
153
static void
154
emit_part_progress_update(const char *msg, struct json_object *params)
155
{
156
    char *servername;
157
    int conn_id;
158
    char *collection_name;
159
    char *subject;
160
    int part_num;
161
    int bytes_downloaded;
162
    int bytes_total;
163

                
164
    get_param(msg, params, "servername", "part_progress_update", string, servername);
165
    get_param(msg, params, "conn_id", "part_progress_update", int, conn_id);
166
    get_param(msg, params, "collection_name", "part_progress_update", string, collection_name);
167
    get_param(msg, params, "subject", "part_progress_update", string, subject);
168
    get_param(msg, params, "part_num", "part_progress_update", int, part_num);
169
    get_param(msg, params, "bytes_downloaded", "part_progress_update", int, bytes_downloaded);
170
    get_param(msg, params, "bytes_total", "part_progress_update", int, bytes_total);
171

                
172
    nntpgrab_core_emit_part_progress_update(FALSE, servername, conn_id, collection_name, subject, part_num, bytes_downloaded, bytes_total);
173
}
174

                
175
static void
176
emit_collection_added(const char *msg, struct json_object *params)
177
{
178
    char *collection_name;
179
    char *poster;
180

                
181
    get_param(msg, params, "collection_name", "collection_added", string, collection_name);
182
    get_param(msg, params, "poster", "collection_added", string, poster);
183

                
184
    nntpgrab_core_emit_collection_added(FALSE, collection_name, poster);
185
}
186

                
187
static void
188
emit_collection_removed(const char *msg, struct json_object *params)
189
{
190
    char *collection_name;
191

                
192
    get_param(msg, params, "collection_name", "collection_removed", string, collection_name);
193

                
194
    nntpgrab_core_emit_collection_removed(FALSE, collection_name);
195
}
196

                
197
static void
198
emit_collection_modified(const char *msg, struct json_object *params)
199
{
200
    char *collection_name;
201
    char *poster;
202

                
203
    get_param(msg, params, "collection_name", "collection_modified", string, collection_name);
204
    get_param(msg, params, "poster", "collection_modified", string, poster);
205

                
206
    nntpgrab_core_emit_collection_modified(FALSE, collection_name, poster);
207
}
208

                
209
static void
210
emit_file_added(const char *msg, struct json_object *params)
211
{
212
    struct json_object *obj;
213
    int len;
214
    int i;
215
    char *collection_name;
216
    char *subject;
217
    char *poster;
218
    int stamp;
219
    guint64 file_size;
220
    guint64 total_size;
221
    guint64 total_size_remaining;
222
    NGTaskState status;
223
    int num_parts;
224
    GList *groups;
225

                
226
    get_param(msg, params, "collection_name", "file_added", string, collection_name);
227
    get_param(msg, params, "subject", "file_added", string, subject);
228
    get_param(msg, params, "poster", "file_added", string, poster);
229
    get_param(msg, params, "stamp", "file_added", int, stamp);
230
    get_param(msg, params, "file_size", "file_added", int, file_size);
231
    get_param(msg, params, "total_size", "file_added", int, total_size);
232
    get_param(msg, params, "total_size_remaining", "file_added", int, total_size_remaining);
233
    get_param(msg, params, "status", "file_added", int, status);
234
    get_param(msg, params, "num_parts", "file_added", int, num_parts);
235

                
236
    obj = get_json_param(msg, params, "groups", "file_added", json_type_array);
237
    if (!obj) {
238
        return;
239
    }
240

                
241
    groups = NULL;
242
    len = json_object_array_length(obj);
243
    for (i = 0; i < len; i++) {
244
        struct json_object *group = json_object_array_get_idx(obj, i);
245
        char *groupname;
246

                
247
        g_return_if_fail(group != NULL);
248

                
249
        groupname = json_object_get_string(group);
250

                
251
        g_return_if_fail(groupname != NULL);
252

                
253
        groups = g_list_append(groups, groupname);
254
    }
255

                
256
    nntpgrab_core_emit_file_added(FALSE, collection_name, subject, poster, stamp, file_size * 1024, total_size * 1024, total_size_remaining * 1024, status, num_parts, groups);
257

                
258
    g_list_free(groups);
259
}
260

                
261
static void
262
emit_file_removed(const char *msg, struct json_object *params)
263
{
264
    char *collection_name;
265
    char *subject;
266
    guint64 total_size;
267
    guint64 total_size_remaining;
268

                
269
    get_param(msg, params, "collection_name", "file_removed", string, collection_name);
270
    get_param(msg, params, "subject", "file_removed", string, subject);
271
    get_param(msg, params, "total_size", "file_removed", int, total_size);
272
    get_param(msg, params, "total_size_remaining", "file_removed", int, total_size_remaining);
273

                
274
    nntpgrab_core_emit_file_removed(FALSE, collection_name, subject, total_size * 1024, total_size_remaining * 1024);
275
}
276

                
277
static void
278
emit_file_download_state_update(const char *msg, struct json_object *params)
279
{
280
    char *collection_name;
281
    char *subject;
282
    int num_parts_total;
283
    int num_parts_done;
284
    int num_parts_failed;
285
    guint64 file_size;
286
    guint64 file_size_remaining;
287
    guint64 total_size;
288
    guint64 total_size_remaining;
289

                
290
    get_param(msg, params, "collection_name", "file_download_state_update", string, collection_name);
291
    get_param(msg, params, "subject", "file_download_state_update", string, subject);
292
    get_param(msg, params, "num_parts_total", "file_download_state_update", int, num_parts_total);
293
    get_param(msg, params, "num_parts_done", "file_download_state_update", int, num_parts_done);
294
    get_param(msg, params, "num_parts_failed", "file_download_state_update", int, num_parts_failed);
295
    get_param(msg, params, "file_size", "file_download_state_update", int, file_size);
296
    get_param(msg, params, "file_size_remaining", "file_download_state_update", int, file_size_remaining);
297
    get_param(msg, params, "total_size", "file_download_state_update", int, total_size);
298
    get_param(msg, params, "total_size_remaining", "file_download_state_update", int, total_size_remaining);
299

                
300
    nntpgrab_core_emit_file_download_state_update(FALSE, collection_name, subject, num_parts_total, num_parts_done, num_parts_failed, file_size * 1024, file_size_remaining * 1024, total_size * 1024, total_size_remaining * 1024);
301
}
302

                
303
static void
304
emit_file_state_changed(const char *msg, struct json_object *params)
305
{
306
    char *collection_name;
307
    char *subject;
308
    char *real_filename;
309
    int old_state;
310
    int new_state;
311
    guint64 file_size_remaining;
312
    guint64 total_size;
313
    guint64 total_size_remaining;
314

                
315
    get_param(msg, params, "collection_name", "file_state_changed", string, collection_name);
316
    get_param(msg, params, "subject", "file_state_changed", string, subject);
317
    get_param(msg, params, "real_filename", "file_state_changed", string, real_filename);
318
    get_param(msg, params, "old_state", "file_state_changed", int, old_state);
319
    get_param(msg, params, "new_state", "file_state_changed", int, new_state);
320
    get_param(msg, params, "file_size_remaining", "file_state_changed", int, file_size_remaining);
321
    get_param(msg, params, "total_size", "file_state_changed", int, total_size);
322
    get_param(msg, params, "total_size_remaining", "file_state_changed", int, total_size_remaining);
323

                
324
    nntpgrab_core_emit_file_state_changed(FALSE, collection_name, subject, real_filename, old_state, new_state, file_size_remaining * 1024, total_size * 1024, total_size_remaining * 1024);
325
}
326

                
327
static void
328
emit_connection_connecting(const char *msg, struct json_object *params)
329
{
330
    char *servername;
331
    int conn_id;
332

                
333
    get_param(msg, params, "servername", "connection_connecting", string, servername);
334
    get_param(msg, params, "conn_id", "connection_connecting", int, conn_id);
335

                
336
    nntpgrab_core_emit_connecting(FALSE, servername, conn_id);
337
}
338

                
339
static void
340
emit_connection_connected(const char *msg, struct json_object *params)
341
{
342
    char *servername;
343
    int conn_id;
344
    char *welcome_msg;
345

                
346
    get_param(msg, params, "servername", "connection_connected", string, servername);
347
    get_param(msg, params, "conn_id", "connection_connected", int, conn_id);
348
    get_param(msg, params, "welcome_msg", "connection_connected", string, welcome_msg);
349

                
350
    nntpgrab_core_emit_connected(FALSE, servername, conn_id, welcome_msg);
351
}
352

                
353
static void
354
emit_connection_disconnect(const char *msg, struct json_object *params)
355
{
356
    char *servername;
357
    int conn_id;
358
    NNTPDisconnectType disconnect_type;
359
    char *reason;
360

                
361
    get_param(msg, params, "servername", "connection_disconnect", string, servername);
362
    get_param(msg, params, "conn_id", "connection_disconnect", int, conn_id);
363
    get_param(msg, params, "disconnect_type", "connection_disconnect", int, disconnect_type);
364
    get_param(msg, params, "reason", "connection_disconnect", string, reason);
365

                
366
    nntpgrab_core_emit_disconnect(FALSE, servername, conn_id, disconnect_type, reason);
367
}
368

                
369
static void
370
emit_schedular_state_changed(const char *msg, struct json_object *params)
371
{
372
    NGSchedularState new_state;
373
    char *reason;
374

                
375
    get_param(msg, params, "new_state", "schedular_state_changed", int, new_state);
376
    get_param(msg, params, "reason", "schedular_state_changed", string, reason);
377

                
378
    nntpgrab_core_emit_schedular_state_changed(FALSE, new_state, (strlen(reason) > 0 ? reason : NULL));
379
}
380

                
381
static void
382
emit_log_message(const char *msg, struct json_object *params)
383
{
384
    char *component;
385
    NGLogLevel log_level;
386
    char *message;
387

                
388
    get_param(msg, params, "component", "log_message", string, component);
389
    get_param(msg, params, "log_level", "log_message", int, log_level);
390
    get_param(msg, params, "msg", "log_message", string, message);
391

                
392
    nntpgrab_core_emit_log_message(FALSE, component, log_level, message, TRUE, FALSE);
393
}
394

                
395
static void
396
emit_task_moved(const char *msg, struct json_object *params)
397
{
398
    char *orig_collection_name;
399
    char *subject;
400
    char *new_collection_name;
401
    int old_position;
402
    int new_position;
403

                
404
    get_param(msg, params, "orig_collection_name", "task_moved", string, orig_collection_name);
405
    get_param(msg, params, "subject", "task_moved", string, subject);
406
    get_param(msg, params, "new_collection_name", "task_moved", string, new_collection_name);
407
    get_param(msg, params, "old_position", "task_moved", int, old_position);
408
    get_param(msg, params, "new_position", "task_moved", int, new_position);
409

                
410
    nntpgrab_core_emit_file_moved(FALSE, orig_collection_name, subject, new_collection_name, old_position, new_position);
411
}
412

                
413
static void
414
emit_collection_moved(const char *msg, struct json_object *params)
415
{
416
    char *collection_name;
417
    int old_position;
418
    int new_position;
419

                
420
    get_param(msg, params, "collection_name", "collection_moved", string, collection_name);
421
    get_param(msg, params, "old_position", "collection_moved", int, old_position);
422
    get_param(msg, params, "new_position", "collection_moved", int, new_position);
423

                
424
    nntpgrab_core_emit_collection_moved(FALSE, collection_name, old_position, new_position);
425
}
426

                
427
static void
428
emit_plugin_loaded(const char *msg, struct json_object *params)
429
{
430
    char *plugin_name;
431
    gboolean is_persistent;
432

                
433
    get_param(msg, params, "plugin_name", "plugin_loaded", string, plugin_name);
434
    get_param(msg, params, "is_persistent", "plugin_loaded", boolean, is_persistent);
435

                
436
    nntpgrab_core_emit_plugin_loaded(FALSE, plugin_name, is_persistent);
437
}
438

                
439
static void
440
emit_plugin_unloaded(const char *msg, struct json_object *params)
441
{
442
    char *plugin_name;
443

                
444
    get_param(msg, params, "plugin_name", "plugin_unloaded", string, plugin_name);
445

                
446
    nntpgrab_core_emit_plugin_unloaded(FALSE, plugin_name);
447
}
448

                
449
static void
450
emit_plugin_event(const char *msg, struct json_object *params)
451
{
452
    int i;
453
    int len;
454
    struct json_object *obj;
455
    char *plugin_name;
456
    char *event_name;
457
    char **values;
458

                
459
    get_param(msg, params, "plugin_name", "plugin_event", string, plugin_name);
460
    get_param(msg, params, "event_name", "plugin_event", string, event_name);
461

                
462
    obj = get_json_param(msg, params, "values", "plugin_event", json_type_array);
463
    if (!obj) {
464
        return;
465
    }
466

                
467
    len = json_object_array_length(obj);
468
    values = g_slice_alloc0(sizeof(char*) * (len + 1));
469

                
470
    for (i = 0; i < len; i++) {
471
        struct json_object *val_obj = json_object_array_get_idx(obj, i);
472
        char *val;
473

                
474
        g_return_if_fail(val_obj != NULL);
475

                
476
        val = json_object_get_string(val_obj);
477

                
478
        g_return_if_fail(val != NULL);
479

                
480
        values[i] = val;
481
    }
482

                
483
    nntpgrab_core_emit_plugin_event(FALSE, plugin_name, event_name, (const char **) values);
484

                
485
    g_slice_free1(sizeof(char*) * (len + 1), values);
486
}
487

                
488
/* This function used to be part of GLib, but because it behaviour got 
489
 * changed in GLib 2.27.4 we can't rely on it's value anymore for
490
 * hardcoded hash comparisons. This is the g_str_hash implementation
491
 * of before GLib 2.27.4 */
492
static guint
493
ng_str_hash (gconstpointer v)
494
{
495
    const signed char *p;
496
    guint32 h = 0;
497

                
498
    for (p = v; *p != '\0'; p++)
499
        h = (h << 5) - h + *p;
500

                
501
    return h;
502
}
503

                
504
static void
505
glue_process_jsonrpc_notification(const char *msg, struct json_object *obj)
506
{
507
    struct json_object *params;
508
    struct json_object *method;
509
    char *event_name;
510
    guint hash;
511

                
512
    params = json_object_object_get(obj, "params");
513
    if (!params) {
514
        g_print(__FILE__ ":%i JSON message lacks a 'params' field, ignoring: %s\n", __LINE__, msg);
515
        return;
516
    }
517

                
518
    if (json_object_get_type(params) != json_type_object) {
519
        g_print(__FILE__ ":%i JSON parameter is of invalid type, ignoring: %s\n", __LINE__, msg);
520
        return;
521
    }
522

                
523
    method = json_object_object_get(obj, "method");
524
    if (!method) {
525
        g_print(__FILE__ ":%i JSON message lacks a 'method' field, ignoring: %s\n", __LINE__, msg);
526
        return;
527
    }
528

                
529
    event_name = json_object_get_string(method);
530
    hash = ng_str_hash(event_name);
531

                
532
    switch (hash) {
533
        case 4148964023U:       /* config_changed */
534
            if (has_signal_handler_pending(CONFIG_CHANGED_SIGNAL)) {
535
                nntpgrab_core_emit_config_changed(FALSE);
536
            }
537
            break;
538
        case 718712759U:        /* part_download_start */
539
            if (has_signal_handler_pending(PART_DOWNLOAD_START_SIGNAL)) {
540
                emit_part_download_start(msg, params);
541
            }
542
            break;
543
        case 2485450830U:       /* part_done */
544
            if (has_signal_handler_pending(PART_DONE_SIGNAL)) {
545
                emit_part_done(msg, params);
546
            }
547
            break;
548
        case 560621065U:        /* part_failed */
549
            if (has_signal_handler_pending(PART_FAILED_SIGNAL)) {
550
                emit_part_failed(msg, params);
551
            }
552
            break;
553
        case 3851882960U:       /* traffic_monitor_update */
554
            if (has_signal_handler_pending(TRAFFIC_MONITOR_UPDATE_SIGNAL)) {
555
                emit_traffic_monitor_update(msg, params);
556
            }
557
            break;
558
        case 3667888847U:       /* part_progress_update */
559
            if (has_signal_handler_pending(PART_PROGRESS_UPDATE_SIGNAL)) {
560
                emit_part_progress_update(msg, params);
561
            }
562
            break;
563
        case 2792752159U:       /* collection_added */
564
            if (has_signal_handler_pending(COLLECTION_ADDED_SIGNAL)) {
565
                emit_collection_added(msg, params);
566
            }
567
            break;
568
        case 1720184767U:       /* collection_removed */
569
            if (has_signal_handler_pending(COLLECTION_REMOVED_SIGNAL)) {
570
                emit_collection_removed(msg, params);
571
            }
572
            break;
573
        case 1683429194U:       /* collection_modified */
574
            if (has_signal_handler_pending(COLLECTION_MODIFIED_SIGNAL)) {
575
                emit_collection_modified(msg, params);
576
            }
577
            break;
578
        case 2127244413U:       /* file_added */
579
            if (has_signal_handler_pending(FILE_ADDED_SIGNAL)) {
580
                emit_file_added(msg, params);
581
            }
582
            break;
583
        case 2117367965U:       /* file_removed */
584
            if (has_signal_handler_pending(FILE_REMOVED_SIGNAL)) {
585
                emit_file_removed(msg, params);
586
            }
587
            break;
588
        case 2548616203U:       /* file_download_state_update */
589
            if (has_signal_handler_pending(FILE_DOWNLOAD_STATE_UPDATE_SIGNAL)) {
590
                emit_file_download_state_update(msg, params);
591
            }
592
            break;
593
        case 3407424387U:       /* file_state_changed */
594
            if (has_signal_handler_pending(FILE_STATE_CHANGED_SIGNAL)) {
595
                emit_file_state_changed(msg, params);
596
            }
597
            break;
598
        case 1506868921U:       /* connection_connecting */
599
            if (has_signal_handler_pending(CONNECTION_CONNECTING_SIGNAL)) {
600
                emit_connection_connecting(msg, params);
601
            }
602
            break;
603
        case 2681007848U:       /* connection_connected */
604
            if (has_signal_handler_pending(CONNECTION_CONNECTED_SIGNAL)) {
605
                emit_connection_connected(msg, params);
606
            }
607
            break;
608
        case 2812926109U:       /* connection_disconnect */
609
            if (has_signal_handler_pending(CONNECTION_DISCONNECT_SIGNAL)) {
610
                emit_connection_disconnect(msg, params);
611
            }
612
            break;
613
        case 1376609542U:       /* schedular_state_changed */
614
            if (has_signal_handler_pending(SCHEDULAR_STATE_CHANGED_SIGNAL)) {
615
                emit_schedular_state_changed(msg, params);
616
            }
617
            break;
618
        case 843068174U:        /* foreach_collection_event */
619
            process_foreach_collection_event(msg, params);
620
            break;
621
        case 3826728748U:       /* foreach_file_event */
622
            process_foreach_file_event(msg, params);
623
            break;
624
        case 2102350437U:       /* foreach_group_event */
625
            process_foreach_group_event(msg, params);
626
            break;
627
        case 693552652U:        /* log_message */
628
            if (has_signal_handler_pending(LOG_MESSAGE_SIGNAL)) {
629
                emit_log_message(msg, params);
630
            }
631
            break;
632
        case 1307041657U:       /* task_moved */
633
            if (has_signal_handler_pending(TASK_MOVED_SIGNAL)) {
634
                emit_task_moved(msg, params);
635
            }
636
            break;
637
        case 2804179410U:       /* collection_moved */
638
            if (has_signal_handler_pending(COLLECTION_MOVED_SIGNAL)) {
639
                emit_collection_moved(msg, params);
640
            }
641
            break;
642
        case 2405579865U:       /* all_downloads_completed */
643
            if (has_signal_handler_pending(ALL_DOWNLOADS_COMPLETED_SIGNAL)) {
644
                nntpgrab_core_emit_all_downloads_completed(FALSE);
645
            }
646
            break;
647
        case 3241070225U:       /* plugin_loaded */
648
            if (has_signal_handler_pending(PLUGIN_LOADED_SIGNAL)) {
649
                emit_plugin_loaded(msg, params);
650
            }
651
            break;
652
        case 3055047530U:       /* plugin_unloaded */
653
            if (has_signal_handler_pending(PLUGIN_UNLOADED_SIGNAL)) {
654
                emit_plugin_unloaded(msg, params);
655
            }
656
            break;
657
        case 2037961358U:       /* plugin_event */
658
            if (has_signal_handler_pending(PLUGIN_EVENT_SIGNAL)) {
659
                emit_plugin_event(msg, params);
660
            }
661
            break;
662

                
663
        default:
664
            g_print(__FILE__ ":%i JSON notification with unknown event name received, event_name = %s, hash = %u, msg = %s\n", __LINE__, event_name, hash, msg);
665
            break;
666
    }
667
}
668

                
669
static GAsyncQueue *command_queue = NULL;
670
static GStaticMutex command_mutex = G_STATIC_MUTEX_INIT;
671
static GStaticMutex init_mutex = G_STATIC_MUTEX_INIT;
672

                
673
void
674
glue_process_jsonrpc_msg(const char *msg)
675
{
676
    struct json_object *obj;
677
    struct json_object *id;
678

                
679
    g_return_if_fail(msg != NULL);
680

                
681
    obj = json_tokener_parse((char*)msg);
682
    if (!obj) {
683
        g_print(__FILE__ ":%i Invalid message received from server, ignoring: %s\n", __LINE__, msg);
684
        return;
685
    }
686

                
687
    id = json_object_object_get(obj, "id");
688
    if (!id) {
689
        /* Notification received! */
690
        glue_process_jsonrpc_notification(msg, obj);
691
        json_object_put(obj);
692
        return;
693
    }
694

                
695
    g_print(__FILE__ ":%i JSON response received for msg: %s\n", __LINE__, msg);
696

                
697
    g_static_mutex_lock(&init_mutex);
698
    if (command_queue == NULL) {
699
        command_queue = g_async_queue_new();
700
    }
701
    g_static_mutex_unlock(&init_mutex);
702

                
703
    g_async_queue_push(command_queue, obj);
704

                
705
    /* No need to unref here as it should be done by the thread who pop's the queue */
706
}
707

                
708
/*************************************************************************************/
709
/* JSON-RPC methods */
710
/*************************************************************************************/
711
#define get_method_param(params, field, method_name, type, dest)                                        \
712
    {                                                                                                   \
713
        char *msg = json_object_get_string(params);                                                     \
714
        struct json_object *obj = get_json_param(msg, params, field, method_name, json_type_ ## type);  \
715
        if (!obj) {                                                                                     \
716
            json_object_put(params) ;                                                                   \
717
            return FALSE;                                                                               \
718
        }                                                                                               \
719
        dest = json_object_get_ ## type (obj);                                                          \
720
    }
721

                
722
static struct json_object *
723
create_new_json_request(const char *method, struct json_object *request_params)
724
{
725
    struct json_object *request;
726
    static int id = 0;
727

                
728
    if (!request_params) {
729
        request_params = json_object_new_array();
730
    }
731

                
732
    request = json_object_new_object();
733
    json_object_object_add(request, "method", json_object_new_string((char*) method));
734
    json_object_object_add(request, "id", json_object_new_int(++id));
735
    json_object_object_add(request, "params", request_params);
736

                
737
    return request;
738
}
739

                
740
static struct json_object *
741
send_request_and_wait_for_response(NntpgrabGlue *glue, struct json_object *request, char **errmsg)
742
{
743
    struct json_object *response;
744
    struct json_object *result;
745
    struct json_object *error;
746
    GTimeVal tv;
747
    int count;
748

                
749
    g_return_val_if_fail(glue != NULL, NULL);
750
    g_return_val_if_fail(request != NULL, NULL);
751
    g_return_val_if_fail(errmsg != NULL, NULL);
752

                
753
    g_static_mutex_lock(&command_mutex);
754

                
755
    if (!write_line(&glue->socket, "%s\r\n", json_object_to_json_string(request))) {
756
        g_static_mutex_unlock(&command_mutex);
757
        return NULL;
758
    }
759

                
760
    g_static_mutex_lock(&init_mutex);
761
    if (command_queue == NULL) {
762
        command_queue = g_async_queue_new();
763
    }
764
    g_static_mutex_unlock(&init_mutex);
765

                
766
    count = 0;
767
    while (count < READ_TIMEOUT_VALUE) {
768
        g_get_current_time(&tv);
769
        tv.tv_sec++;
770

                
771
        response = g_async_queue_timed_pop(command_queue, &tv);
772
        if (response) {
773
            break;
774
        } else if (glue->socket.socket_id <= 0) {
775
            *errmsg = g_strdup_printf(__FILE__ ":%i Connection got disconnected\n", __LINE__);
776

                
777
            nntpgrab_core_emit_log_message(FALSE, "Glue layer", NG_LOG_LEVEL_WARNING, *errmsg, TRUE, FALSE);
778

                
779
            g_static_mutex_unlock(&command_mutex);
780

                
781
            return NULL;
782
        }
783
        count++;
784
    }
785

                
786
    g_static_mutex_unlock(&command_mutex);
787

                
788
    if (!response) {
789
        *errmsg = g_strdup_printf(__FILE__ ":%i Timed out waiting for response from server, request = %s\n", __LINE__, json_object_to_json_string(request));
790

                
791
        nntpgrab_core_emit_log_message(FALSE, "Glue layer", NG_LOG_LEVEL_WARNING, *errmsg, TRUE, FALSE);
792

                
793
        return NULL;
794
    }
795

                
796
    error = json_object_object_get(response, "error");
797
    if (error) {
798
        *errmsg = g_strdup(json_object_get_string(error));
799

                
800
        json_object_put(response);
801

                
802
        return NULL;
803
    }
804

                
805
    result = json_object_object_get(response, "result");
806
    if (!result) {
807
        *errmsg = g_strdup_printf(__FILE__ ":%i Response from server lacks a 'result' field, request = %s, response = %s\n", __LINE__, json_object_to_json_string(request), json_object_to_json_string(response));
808

                
809
        nntpgrab_core_emit_log_message(FALSE, "Glue layer", NG_LOG_LEVEL_WARNING, *errmsg, TRUE, FALSE);
810

                
811
        json_object_put(response);
812

                
813
        return NULL;
814
    }
815

                
816
    /* We're only interested in the result, so we add a reference to that and unref the response */
817
    json_object_get(result);
818
    json_object_put(response);
819

                
820
    return result;
821
}
822

                
823
void
824
nntpgrab_glue_internal_kill_server(NntpgrabGlue *obj)
825
{
826
    NntpgrabGlue *glue = NNTPGRAB_GLUE(obj);
827
    struct json_object *request;
828
    struct json_object *response_result;
829
    char *errmsg = NULL;
830

                
831
    request = create_new_json_request("nntpgrab_server_request_quit", NULL);
832

                
833
    if (!(response_result = send_request_and_wait_for_response(glue, request, &errmsg))) {
834
        g_print(__FILE__ ":%i nntpgrab_server_request_quit FAILED: %s\n", __LINE__, errmsg);
835
        g_free(errmsg);
836
        json_object_put(request);
837
        return;
838
    }
839

                
840
    json_object_put(response_result);
841
    json_object_put(request);
842
}
843

                
844
NGList *
845
nntpgrab_glue_internal_config_get_avail_servers(NntpgrabGlue *obj)
846
{
847
    NntpgrabGlue *glue = NNTPGRAB_GLUE(obj);
848
    struct json_object *request;
849
    struct json_object *response_result;
850
    NGList *ret = NULL;
851
    char *errmsg = NULL;
852
    int i;
853
    int len;
854

                
855
    request = create_new_json_request("nntpgrab_config_get_avail_servers", NULL);
856

                
857
    if (!(response_result = send_request_and_wait_for_response(glue, request, &errmsg))) {
858
        g_print(__FILE__ ":%i nntpgrab_config_get_avail_servers FAILED: %s\n", __LINE__, errmsg);
859
        g_free(errmsg);
860
        json_object_put(request);
861
        return NULL;
862
    }
863

                
864
    len = json_object_array_length(response_result);
865
    for (i = 0; i < len; i++) {
866
        struct json_object *obj = json_object_array_get_idx(response_result, i);
867
        char *servername;
868

                
869
        g_return_val_if_fail(obj != NULL, NULL);
870

                
871
        servername = json_object_get_string(obj);
872

                
873
        g_return_val_if_fail(servername != NULL, NULL);
874

                
875
        ret = ng_list_append(ret, g_strdup(servername));
876
    }
877

                
878
    json_object_put(request);
879
    json_object_put(response_result);
880

                
881
    return ret;
882
}
883

                
884
gboolean
885
nntpgrab_glue_internal_config_get_server_info(NntpgrabGlue *obj, const char *servername, NGConfigServer *ret)
886
{
887
    NntpgrabGlue *glue = NNTPGRAB_GLUE(obj);
888
    struct json_object *request;
889
    struct json_object *request_params;
890
    struct json_object *response_result;
891
    char *errmsg = NULL;
892
    char *servername_received;
893
    char *hostname;
894
    int port;
895
    char *username;
896
    char *password;
897
    int max_threads;
898
    NGServerPriority priority;
899
    ngboolean send_group_command;
900
    ngboolean use_ssl;
901
    ngboolean enabled;
902

                
903
    g_return_val_if_fail(servername != NULL, FALSE);
904
    g_return_val_if_fail(ret != NULL, FALSE);
905

                
906
    request_params = json_object_new_array();
907
    json_object_array_add(request_params, json_object_new_string((char*) servername));
908
    request = create_new_json_request("nntpgrab_config_get_server_info", request_params);
909

                
910
    if (!(response_result = send_request_and_wait_for_response(glue, request, &errmsg))) {
911
        g_print(__FILE__ ":%i nntpgrab_config_get_server_info FAILED: %s\n", __LINE__, errmsg);
912
        g_free(errmsg);
913
        json_object_put(request);
914
        return FALSE;
915
    }
916

                
917
    get_method_param(response_result, "servername", "config_get_server_info", string, servername_received);
918
    get_method_param(response_result, "hostname", "config_get_server_info", string, hostname);
919
    get_method_param(response_result, "port", "config_get_server_info", int, port);
920
    get_method_param(response_result, "username", "config_get_server_info", string, username);
921
    get_method_param(response_result, "password", "config_get_server_info", string, password);
922
    get_method_param(response_result, "max_threads", "config_get_server_info", int, max_threads);
923
    get_method_param(response_result, "priority", "config_get_server_info", int, priority);
924
    get_method_param(response_result, "send_group_command", "config_get_server_info", boolean, send_group_command);
925
    get_method_param(response_result, "use_ssl", "config_get_server_info", boolean, use_ssl);
926
    get_method_param(response_result, "enabled", "config_get_server_info", boolean, enabled);
927

                
928
    memset(ret, 0, sizeof(NGConfigServer));
929

                
930
    strncpy(ret->servername, servername_received, sizeof(ret->servername));
931
    strncpy(ret->hostname, hostname, sizeof(ret->hostname));
932
    ret->port = port;
933
    strncpy(ret->username, username, sizeof(ret->username));
934
    strncpy(ret->password, password, sizeof(ret->password));
935
    ret->max_threads = max_threads;
936
    ret->priority = priority;
937
    ret->send_group_command = send_group_command;
938
    ret->use_ssl = use_ssl;
939
    ret->enabled = enabled;
940

                
941
    json_object_put(request);
942
    json_object_put(response_result);
943

                
944
    return TRUE;
945
}
946

                
947
gboolean
948
nntpgrab_glue_internal_config_add_server(NntpgrabGlue *obj, NGConfigServer new_server, char **errmsg)
949
{
950
    NntpgrabGlue *glue = NNTPGRAB_GLUE(obj);
951
    struct json_object *request;
952
    struct json_object *request_params;
953
    struct json_object *server;
954
    struct json_object *response_result;
955

                
956
    request_params = json_object_new_array();
957
    server = json_object_new_object();
958
    json_object_object_add(server, "servername", json_object_new_string((char*) new_server.servername));
959
    json_object_object_add(server, "hostname", json_object_new_string((char*) new_server.hostname));
960
    json_object_object_add(server, "port", json_object_new_int(new_server.port));
961
    json_object_object_add(server, "username", json_object_new_string((char*) new_server.username));
962
    json_object_object_add(server, "password", json_object_new_string((char*) new_server.password));
963
    json_object_object_add(server, "max_threads", json_object_new_int(new_server.max_threads));
964
    json_object_object_add(server, "priority", json_object_new_int(new_server.priority));
965
    json_object_object_add(server, "send_group_command", json_object_new_boolean(new_server.send_group_command));
966
    json_object_object_add(server, "use_ssl", json_object_new_boolean(new_server.use_ssl));
967
    json_object_object_add(server, "enabled", json_object_new_boolean(new_server.enabled));
968
    json_object_array_add(request_params, server);
969
    request = create_new_json_request("nntpgrab_config_add_server", request_params);
970

                
971
    if (!(response_result = send_request_and_wait_for_response(glue, request, errmsg))) {
972
        json_object_put(request);
973
        return FALSE;
974
    }
975

                
976
    json_object_put(request);
977
    json_object_put(response_result);
978

                
979
    return TRUE;
980
}
981

                
982
gboolean
983
nntpgrab_glue_internal_config_del_server(NntpgrabGlue *obj, const char *servername, char **errmsg)
984
{
985
    NntpgrabGlue *glue = NNTPGRAB_GLUE(obj);
986
    struct json_object *request;
987
    struct json_object *request_params;
988
    struct json_object *response_result;
989

                
990
    request_params = json_object_new_array();
991
    json_object_array_add(request_params, json_object_new_string((char*) servername));
992
    request = create_new_json_request("nntpgrab_config_del_server", request_params);
993

                
994
    if (!(response_result = send_request_and_wait_for_response(glue, request, errmsg))) {
995
        json_object_put(request);
996
        return FALSE;
997
    }
998

                
999
    json_object_put(request);
1000
    json_object_put(response_result);
1001

                
1002
    return TRUE;
1003
}
1004

                
1005
gboolean
1006
nntpgrab_glue_internal_config_edit_server(NntpgrabGlue *obj, const char *servername, NGConfigServer new_server, char **errmsg)
1007
{
1008
    NntpgrabGlue *glue = NNTPGRAB_GLUE(obj);
1009
    struct json_object *request;
1010
    struct json_object *request_params;
1011
    struct json_object *server;
1012
    struct json_object *response_result;
1013

                
1014
    request_params = json_object_new_array();
1015
    server = json_object_new_object();
1016
    json_object_object_add(server, "servername", json_object_new_string((char*) new_server.servername));
1017
    json_object_object_add(server, "hostname", json_object_new_string((char*) new_server.hostname));
1018
    json_object_object_add(server, "port", json_object_new_int(new_server.port));
1019
    json_object_object_add(server, "username", json_object_new_string((char*) new_server.username));
1020
    json_object_object_add(server, "password", json_object_new_string((char*) new_server.password));
1021
    json_object_object_add(server, "max_threads", json_object_new_int(new_server.max_threads));
1022
    json_object_object_add(server, "priority", json_object_new_int(new_server.priority));
1023
    json_object_object_add(server, "send_group_command", json_object_new_boolean(new_server.send_group_command));
1024
    json_object_object_add(server, "use_ssl", json_object_new_boolean(new_server.use_ssl));
1025
    json_object_object_add(server, "enabled", json_object_new_boolean(new_server.enabled));
1026
    json_object_array_add(request_params, json_object_new_string((char*) servername));
1027
    json_object_array_add(request_params, server);
1028
    request = create_new_json_request("nntpgrab_config_edit_server", request_params);
1029

                
1030
    if (!(response_result = send_request_and_wait_for_response(glue, request, errmsg))) {
1031
        json_object_put(request);
1032
        return FALSE;
1033
    }
1034

                
1035
    json_object_put(request);
1036
    json_object_put(response_result);
1037

                
1038
    return TRUE;
1039
}
1040

                
1041
gboolean
1042
nntpgrab_glue_internal_config_get_opts(NntpgrabGlue *obj, NGConfigOpts *opts)
1043
{
1044
    NntpgrabGlue *glue = NNTPGRAB_GLUE(obj);
1045
    struct json_object *request;
1046
    struct json_object *response_result;
1047
    char *errmsg = NULL;
1048
    char *download_directory;
1049
    char *temp_directory;
1050
    gboolean enable_intelligent_par2_downloading;
1051
    gboolean enable_par2_repair;
1052
    char *auto_import_directory;
1053
    gboolean enable_auto_import;
1054
    gboolean move_file_after_auto_import;
1055
    gboolean enable_auto_unpack;
1056
    gboolean enable_bandwidth_shaping;
1057
    int max_bandwidth;
1058
    gboolean enable_webserver;
1059
    int webserver_port;
1060
    gboolean enable_logger;
1061
    gboolean auto_remove_files_after_repair;
1062
    gboolean auto_remove_files_after_unpack;
1063
    gboolean auto_remove_collections_after_download;
1064

                
1065
    memset(opts, 0, sizeof(NGConfigOpts));
1066

                
1067
    request = create_new_json_request("nntpgrab_config_get_opts", NULL);
1068

                
1069
    if (!(response_result = send_request_and_wait_for_response(glue, request, &errmsg))) {
1070
        g_print(__FILE__ ":%i nntpgrab_config_get_opts FAILED: %s\n", __LINE__, errmsg);
1071
        g_free(errmsg);
1072
        json_object_put(request);
1073
        return FALSE;
1074
    }
1075

                
1076
    get_method_param(response_result, "download_directory", "config_get_opts", string, download_directory);
1077
    get_method_param(response_result, "temp_directory", "config_get_opts", string, temp_directory);
1078
    get_method_param(response_result, "enable_intelligent_par2_downloading", "config_get_opts", boolean, enable_intelligent_par2_downloading);
1079
    get_method_param(response_result, "enable_par2_repair", "config_get_opts", boolean, enable_par2_repair);
1080
    get_method_param(response_result, "auto_import_directory", "config_get_opts", string, auto_import_directory);
1081
    get_method_param(response_result, "enable_auto_import", "config_get_opts", boolean, enable_auto_import);
1082
    get_method_param(response_result, "move_file_after_auto_import", "config_get_opts", boolean, move_file_after_auto_import);
1083
    get_method_param(response_result, "enable_auto_unpack", "config_get_opts", boolean, enable_auto_unpack);
1084
    get_method_param(response_result, "enable_bandwidth_shaping", "config_get_opts", boolean, enable_bandwidth_shaping);
1085
    get_method_param(response_result, "max_bandwidth", "config_get_opts", int, max_bandwidth);
1086
    get_method_param(response_result, "enable_webserver", "config_get_opts", boolean, enable_webserver);
1087
    get_method_param(response_result, "webserver_port", "config_get_opts", int, webserver_port);
1088
    get_method_param(response_result, "enable_logger", "config_get_opts", boolean, enable_logger);
1089
    get_method_param(response_result, "auto_remove_files_after_repair", "config_get_opts", boolean, auto_remove_files_after_repair);
1090
    get_method_param(response_result, "auto_remove_files_after_unpack", "config_get_opts", boolean, auto_remove_files_after_unpack);
1091
    get_method_param(response_result, "auto_remove_collections_after_download", "config_get_opts", boolean, auto_remove_collections_after_download);
1092

                
1093
    strncpy(opts->download_directory, download_directory, sizeof(opts->download_directory) - 1);
1094
    strncpy(opts->temp_directory, temp_directory, sizeof(opts->temp_directory) - 1);
1095
    opts->enable_intelligent_par2_downloading = enable_intelligent_par2_downloading;
1096
    opts->enable_par2_repair = enable_par2_repair;
1097
    strncpy(opts->auto_import_directory, auto_import_directory, sizeof(opts->auto_import_directory) - 1);
1098
    opts->enable_auto_import = enable_auto_import;
1099
    opts->move_file_after_auto_import = move_file_after_auto_import;
1100
    opts->enable_auto_unpack = enable_auto_unpack;
1101
    opts->enable_bandwidth_shaping = enable_bandwidth_shaping;
1102
    opts->max_bandwidth = max_bandwidth;
1103
    opts->enable_webserver = enable_webserver;
1104
    opts->webserver_port = webserver_port;
1105
    opts->enable_logger = enable_logger;
1106
    opts->auto_remove_files_after_repair = auto_remove_files_after_repair;
1107
    opts->auto_remove_files_after_unpack = auto_remove_files_after_unpack;
1108
    opts->auto_remove_collections_after_download = auto_remove_collections_after_download;
1109

                
1110
    json_object_put(request);
1111
    json_object_put(response_result);
1112

                
1113
    return TRUE;
1114
}
1115

                
1116
gboolean
1117
nntpgrab_glue_internal_config_set_opts(NntpgrabGlue *obj, NGConfigOpts opts)
1118
{
1119
    NntpgrabGlue *glue = NNTPGRAB_GLUE(obj);
1120
    struct json_object *request;
1121
    struct json_object *request_params;
1122
    struct json_object *param;
1123
    struct json_object *response_result;
1124
    char *errmsg = NULL;
1125

                
1126
    request_params = json_object_new_array();
1127
    param = json_object_new_object();
1128
    json_object_object_add(param, "download_directory", json_object_new_string((char*) opts.download_directory));
1129
    json_object_object_add(param, "temp_directory", json_object_new_string((char*) opts.temp_directory));
1130
    json_object_object_add(param, "enable_intelligent_par2_downloading", json_object_new_boolean(opts.enable_intelligent_par2_downloading));
1131
    json_object_object_add(param, "enable_par2_repair", json_object_new_boolean(opts.enable_par2_repair));
1132
    json_object_object_add(param, "auto_import_directory", json_object_new_string((char*) opts.auto_import_directory));
1133
    json_object_object_add(param, "enable_auto_import", json_object_new_boolean(opts.enable_auto_import));
1134
    json_object_object_add(param, "move_file_after_auto_import", json_object_new_boolean(opts.move_file_after_auto_import));
1135
    json_object_object_add(param, "enable_auto_unpack", json_object_new_boolean(opts.enable_auto_unpack));
1136
    json_object_object_add(param, "enable_bandwidth_shaping", json_object_new_boolean(opts.enable_bandwidth_shaping));
1137
    json_object_object_add(param, "max_bandwidth", json_object_new_int(opts.max_bandwidth));
1138
    json_object_object_add(param, "enable_webserver", json_object_new_boolean(opts.enable_webserver));
1139
    json_object_object_add(param, "webserver_port", json_object_new_int(opts.webserver_port));
1140
    json_object_object_add(param, "enable_logger", json_object_new_boolean(opts.enable_logger));
1141
    json_object_object_add(param, "auto_remove_files_after_repair", json_object_new_boolean(opts.auto_remove_files_after_repair));
1142
    json_object_object_add(param, "auto_remove_files_after_unpack", json_object_new_boolean(opts.auto_remove_files_after_unpack));
1143
    json_object_object_add(param, "auto_remove_collections_after_download", json_object_new_boolean(opts.auto_remove_collections_after_download));
1144
    json_object_array_add(request_params, param);
1145
    request = create_new_json_request("nntpgrab_config_set_opts", request_params);
1146

                
1147
    if (!(response_result = send_request_and_wait_for_response(glue, request, &errmsg))) {
1148
        g_print(__FILE__ ":%i nntpgrab_config_set_opts FAILED: %s\n", __LINE__, errmsg);
1149
        g_free(errmsg);
1150
        json_object_put(request);
1151
        return FALSE;
1152
    }
1153

                
1154
    json_object_put(request);
1155
    json_object_put(response_result);
1156

                
1157
    return TRUE;
1158
}
1159

                
1160
gboolean
1161
nntpgrab_glue_internal_config_get_folder_listing(NntpgrabGlue *obj, const char *parent, NGList **folders)
1162
{
1163
    NntpgrabGlue *glue = NNTPGRAB_GLUE(obj);
1164
    struct json_object *request;
1165
    struct json_object *request_params;
1166
    struct json_object *response_result;
1167
    char *errmsg = NULL;
1168
    int i;
1169
    int len;
1170

                
1171
    request_params = json_object_new_array();
1172
    if (parent) {
1173
        json_object_array_add(request_params, json_object_new_string((char*) parent));
1174
    } else {
1175
        json_object_array_add(request_params, NULL);
1176
    }
1177
    request = create_new_json_request("nntpgrab_utils_get_folder_listing", request_params);
1178

                
1179
    if (!(response_result = send_request_and_wait_for_response(glue, request, &errmsg))) {
1180
        g_print(__FILE__ ":%i nntpgrab_utils_get_folder_listing FAILED: %s\n", __LINE__, errmsg);
1181
        g_free(errmsg);
1182
        json_object_put(request);
1183
        return FALSE;
1184
    }
1185

                
1186
    if (json_object_get_type(response_result) != json_type_array) {
1187
        g_print(__FILE__ ":%i nntpgrab_utils_get_folder_listing FAILED: response_result is of invalid type, type = %i\n", __LINE__, json_object_get_type(response_result));
1188
        json_object_put(request);
1189
        json_object_put(response_result);
1190

                
1191
        return FALSE;
1192
    }
1193

                
1194
    len = json_object_array_length(response_result);
1195
    *folders = NULL;
1196
    for (i = 0; i < len; i++) {
1197
        struct json_object *param = json_object_array_get_idx(response_result, i);
1198
        NNTPGrabFolder *folder;
1199
        char *folder_str;
1200

                
1201
        g_return_val_if_fail(obj != NULL, FALSE);
1202

                
1203
        folder = g_slice_new0(NNTPGrabFolder);
1204

                
1205
        get_method_param(param, "folder", "nntpgrab_utils_get_folder_listing", string, folder_str);
1206
        get_method_param(param, "has_subfolders", "nntpgrab_utils_get_folder_listing", boolean, folder->has_subfolders);
1207
        strncpy(folder->folder, folder_str, sizeof(folder->folder) - 1);
1208

                
1209
        *folders = ng_list_append(*folders, folder);
1210
    }
1211

                
1212
    json_object_put(request);
1213
    json_object_put(response_result);
1214

                
1215
    return TRUE;
1216
}
1217

                
1218
gboolean
1219
nntpgrab_glue_internal_schedular_start(NntpgrabGlue *obj)
1220
{
1221
    NntpgrabGlue *glue = NNTPGRAB_GLUE(obj);
1222
    struct json_object *request;
1223
    struct json_object *response_result;
1224
    char *errmsg = NULL;
1225

                
1226
    request = create_new_json_request("nntpgrab_schedular_start", NULL);
1227

                
1228
    if (!(response_result = send_request_and_wait_for_response(glue, request, &errmsg))) {
1229
        g_print(__FILE__ ":%i nntpgrab_schedular_start FAILED: %s\n", __LINE__, errmsg);
1230
        g_free(errmsg);
1231
        json_object_put(request);
1232
        return FALSE;
1233
    }
1234

                
1235
    json_object_put(request);
1236
    json_object_put(response_result);
1237

                
1238
    return TRUE;
1239
}
1240

                
1241
gboolean
1242
nntpgrab_glue_internal_schedular_stop(NntpgrabGlue *obj, gboolean wait)
1243
{
1244
    NntpgrabGlue *glue = NNTPGRAB_GLUE(obj);
1245
    struct json_object *request;
1246
    struct json_object *request_params;
1247
    struct json_object *response_result;
1248
    char *errmsg = NULL;
1249

                
1250
    request_params = json_object_new_array();
1251
    json_object_array_add(request_params, json_object_new_boolean(wait));
1252
    request = create_new_json_request("nntpgrab_schedular_stop", request_params);
1253

                
1254
    if (!(response_result = send_request_and_wait_for_response(glue, request, &errmsg))) {
1255
        g_print(__FILE__ ":%i nntpgrab_schedular_stop FAILED: %s\n", __LINE__, errmsg);
1256
        g_free(errmsg);
1257
        json_object_put(request);
1258
        return FALSE;
1259
    }
1260

                
1261
    json_object_put(request);
1262
    json_object_put(response_result);
1263

                
1264
    return TRUE;
1265
}
1266

                
1267
NGSchedularState
1268
nntpgrab_glue_internal_schedular_get_state(NntpgrabGlue *obj)
1269
{
1270
    NntpgrabGlue *glue = NNTPGRAB_GLUE(obj);
1271
    struct json_object *request;
1272
    struct json_object *response_result;
1273
    char *errmsg = NULL;
1274
    NGSchedularState ret;
1275

                
1276
    request = create_new_json_request("nntpgrab_schedular_get_state", NULL);
1277

                
1278
    if (!(response_result = send_request_and_wait_for_response(glue, request, &errmsg))) {
1279
        g_print(__FILE__ ":%i nntpgrab_schedular_get_state FAILED: %s\n", __LINE__, errmsg);
1280
        g_free(errmsg);
1281
        json_object_put(request);
1282
        return SCHEDULAR_STATE_STOPPED;
1283
    }
1284

                
1285
    if (json_object_get_type(response_result) != json_type_int) {
1286
        g_print(__FILE__ ":%i nntpgrab_schedular_get_state FAILED: response_result is of invalid type, type = %i\n", __LINE__, json_object_get_type(response_result));
1287
        json_object_put(request);
1288
        json_object_put(response_result);
1289

                
1290
        return SCHEDULAR_STATE_STOPPED;
1291
    }
1292

                
1293
    ret = json_object_get_int(response_result);
1294

                
1295
    json_object_put(request);
1296
    json_object_put(response_result);
1297

                
1298
    return ret;
1299
}
1300

                
1301
gboolean
1302
nntpgrab_glue_internal_schedular_add_task_to_queue(NntpgrabGlue *obj, const char *collection_name, const char *subject, const char *poster, time_t stamp, nguint64 file_size, NGList *groups, NGList *parts, char **errmsg)
1303
{
1304
    NntpgrabGlue *glue = NNTPGRAB_GLUE(obj);
1305
    struct json_object *request;
1306
    struct json_object *request_params;
1307
    struct json_object *response_result;
1308
    struct json_object *json_obj;
1309
    NGList *list;
1310

                
1311
    request_params = json_object_new_array();
1312
    json_object_array_add(request_params, json_object_new_string((char*) collection_name));
1313
    json_object_array_add(request_params, json_object_new_string((char*) subject));
1314
    json_object_array_add(request_params, json_object_new_string((char*) poster));
1315
    json_object_array_add(request_params, json_object_new_int(stamp));
1316
    json_object_array_add(request_params, json_object_new_int(file_size / 1024));
1317

                
1318
    json_obj = json_object_new_array();
1319
    json_object_array_add(request_params, json_obj);
1320
    list = groups;
1321
    while (list) {
1322
        char *groupname = list->data;
1323

                
1324
        json_object_array_add(json_obj, json_object_new_string(groupname));
1325

                
1326
        list = ng_list_next(list);
1327
    }
1328

                
1329
    json_obj = json_object_new_array();
1330
    json_object_array_add(request_params, json_obj);
1331
    list = parts;
1332
    while (list) {
1333
        NNTPGrabPart *part = list->data;
1334
        struct json_object *part_obj = json_object_new_object();
1335

                
1336
        json_object_object_add(part_obj, "message_id", json_object_new_string((char*) part->message_id));
1337
        json_object_object_add(part_obj, "part_num", json_object_new_int(part->part_num));
1338
        json_object_object_add(part_obj, "size", json_object_new_int(part->size));
1339
        json_object_array_add(json_obj, part_obj);
1340

                
1341
        list = ng_list_next(list);
1342
    }
1343

                
1344
    request = create_new_json_request("nntpgrab_schedular_add_file_to_queue", request_params);
1345

                
1346
    if (!(response_result = send_request_and_wait_for_response(glue, request, errmsg))) {
1347
        json_object_put(request);
1348
        return FALSE;
1349
    }
1350

                
1351
    json_object_put(request);
1352
    json_object_put(response_result);
1353

                
1354
    return TRUE;
1355
}
1356

                
1357
gboolean
1358
nntpgrab_glue_internal_schedular_del_task_from_queue(NntpgrabGlue *obj, const char *collection_name, const char *subject, char **errmsg)
1359
{
1360
    NntpgrabGlue *glue = NNTPGRAB_GLUE(obj);
1361
    struct json_object *request;
1362
    struct json_object *request_params;
1363
    struct json_object *response_result;
1364

                
1365
    request_params = json_object_new_array();
1366
    json_object_array_add(request_params, json_object_new_string((char*) collection_name));
1367
    if (subject) {
1368
        json_object_array_add(request_params, json_object_new_string((char*) subject));
1369
    } else {
1370
        json_object_array_add(request_params, NULL);
1371
    }
1372
    request = create_new_json_request("nntpgrab_schedular_del_file_from_queue", request_params);
1373

                
1374
    if (!(response_result = send_request_and_wait_for_response(glue, request, errmsg))) {
1375
        json_object_put(request);
1376
        return FALSE;
1377
    }
1378

                
1379
    json_object_put(request);
1380
    json_object_put(response_result);
1381

                
1382
    return TRUE;
1383
}
1384

                
1385
gboolean
1386
nntpgrab_glue_internal_schedular_restart_task(NntpgrabGlue *obj, const char *collection_name, const char *subject, char **errmsg)
1387
{
1388
    NntpgrabGlue *glue = NNTPGRAB_GLUE(obj);
1389
    struct json_object *request;
1390
    struct json_object *request_params;
1391
    struct json_object *response_result;
1392

                
1393
    g_return_val_if_fail(collection_name != NULL, FALSE);
1394
    /* NOTE: subject CAN be NULL */
1395

                
1396
    request_params = json_object_new_array();
1397
    json_object_array_add(request_params, json_object_new_string((char*) collection_name));
1398
    if (subject) {
1399
        json_object_array_add(request_params, json_object_new_string((char*) subject));
1400
    } else {
1401
        json_object_array_add(request_params, NULL);
1402
    }
1403
    request = create_new_json_request("nntpgrab_schedular_restart_file", request_params);
1404

                
1405
    if (!(response_result = send_request_and_wait_for_response(glue, request, errmsg))) {
1406
        json_object_put(request);
1407
        return FALSE;
1408
    }
1409

                
1410
    json_object_put(request);
1411
    json_object_put(response_result);
1412

                
1413
    return TRUE;
1414
}
1415

                
1416
gboolean
1417
nntpgrab_glue_internal_schedular_save_queue(NntpgrabGlue *obj, char **errmsg)
1418
{
1419
    NntpgrabGlue *glue = NNTPGRAB_GLUE(obj);
1420
    struct json_object *request;
1421
    struct json_object *response_result;
1422

                
1423
    request = create_new_json_request("nntpgrab_schedular_save_queue", NULL);
1424

                
1425
    if (!(response_result = send_request_and_wait_for_response(glue, request, errmsg))) {
1426
        json_object_put(request);
1427
        return FALSE;
1428
    }
1429

                
1430
    json_object_put(request);
1431
    json_object_put(response_result);
1432

                
1433
    return TRUE;
1434
}
1435

                
1436
static ForeachCollectionFunc collection_func_global = NULL;
1437
static ForeachFileFunc file_func_global = NULL;
1438
static ForeachGroupFunc group_func_global = NULL;
1439
static void *foreach_task_user_data_global = NULL;
1440

                
1441
static void
1442
process_foreach_collection_event(const char *msg, struct json_object *params)
1443
{
1444
    char *collection_name = NULL;
1445
    char *poster = NULL;
1446
    guint64 total_size = 0;
1447
    guint64 total_size_remaining = 0;
1448
    int position = 0;
1449

                
1450
    if (!collection_func_global) {
1451
        return;
1452
    }
1453

                
1454
    get_param(msg, params, "collection_name", "foreach_collection_event", string, collection_name);
1455
    get_param(msg, params, "poster", "foreach_collection_event", string, poster);
1456
    get_param(msg, params, "total_size", "foreach_collection_event", int, total_size);
1457
    get_param(msg, params, "total_size_remaining", "foreach_collection_event", int, total_size_remaining);
1458
    get_param(msg, params, "position", "foreach_collection_event", int, position);
1459

                
1460
    /* JSON doesn't support 64bit integers so all file sizes are in KB instead of bytes */
1461
    total_size *= 1024;
1462
    total_size_remaining *= 1024;
1463

                
1464
    collection_func_global(collection_name, poster, total_size, total_size_remaining, position, foreach_task_user_data_global);
1465
}
1466

                
1467
static void
1468
process_foreach_file_event(const char *msg, struct json_object *params)
1469
{
1470
    char *collection_name = NULL;
1471
    char *subject = NULL;
1472
    char *poster;
1473
    int stamp;
1474
    guint64 file_size;
1475
    guint64 file_size_remaining;
1476
    int num_parts_total;
1477
    int num_parts_downloaded;
1478
    int num_parts_failed;
1479
    NGTaskState status;
1480
    char *filename;
1481
    int position;
1482

                
1483
    if (!file_func_global) {
1484
        return;
1485
    }
1486

                
1487
    get_param(msg, params, "collection_name", "foreach_file_event", string, collection_name);
1488
    get_param(msg, params, "subject", "foreach_file_event", string, subject);
1489
    get_param(msg, params, "poster", "foreach_file_event", string, poster);
1490
    get_param(msg, params, "stamp", "foreach_file_event", int, stamp);
1491
    get_param(msg, params, "file_size", "foreach_file_event", int, file_size);
1492
    get_param(msg, params, "file_size_remaining", "foreach_file_event", int, file_size_remaining);
1493
    get_param(msg, params, "num_parts_total", "foreach_file_event", int, num_parts_total);
1494
    get_param(msg, params, "num_parts_downloaded", "foreach_file_event", int, num_parts_downloaded);
1495
    get_param(msg, params, "num_parts_failed", "foreach_file_event", int, num_parts_failed);
1496
    get_param(msg, params, "status", "foreach_file_event", int, status);
1497
    get_param(msg, params, "filename", "foreach_file_event", string, filename);
1498
    get_param(msg, params, "position", "foreach_file_event", int, position);
1499

                
1500
    /* JSON doesn't support 64bit integers so all file sizes are in KB instead of bytes */
1501
    file_size *= 1024;
1502
    file_size_remaining *= 1024;
1503

                
1504
    file_func_global(collection_name, subject, poster, stamp, file_size, file_size_remaining, position, num_parts_total, num_parts_downloaded, num_parts_failed, status, filename, foreach_task_user_data_global);
1505
}
1506

                
1507
static void
1508
process_foreach_group_event(const char *msg, struct json_object *params)
1509
{
1510
    char *collection_name = NULL;
1511
    char *subject = NULL;
1512
    char *group = NULL;
1513

                
1514
    if (!group_func_global) {
1515
        return;
1516
    }
1517

                
1518
    get_param(msg, params, "collection_name", "foreach_group_event", string, collection_name);
1519
    get_param(msg, params, "subject", "foreach_group_event", string, subject);
1520
    get_param(msg, params, "group", "foreach_group_event", string, group);
1521

                
1522
    group_func_global(collection_name, subject, group, foreach_task_user_data_global);
1523
}
1524

                
1525
gboolean
1526
nntpgrab_glue_internal_schedular_foreach_task(NntpgrabGlue *obj, ForeachCollectionFunc collection_func, ForeachFileFunc file_func, ForeachGroupFunc group_func, void *data)
1527
{
1528
    NntpgrabGlue *glue = NNTPGRAB_GLUE(obj);
1529
    struct json_object *request;
1530
    struct json_object *response_result;
1531
    char *errmsg = NULL;
1532
    gboolean ret;
1533

                
1534
    g_return_val_if_fail(obj != NULL, FALSE);
1535
    g_return_val_if_fail(collection_func != NULL || file_func != NULL || group_func != NULL, FALSE);
1536

                
1537
    request = create_new_json_request("nntpgrab_schedular_foreach_task", NULL);
1538

                
1539
    collection_func_global = collection_func;
1540
    file_func_global = file_func;
1541
    group_func_global = group_func;
1542
    foreach_task_user_data_global = data;
1543

                
1544
    if (!(response_result = send_request_and_wait_for_response(glue, request, &errmsg))) {
1545
        g_free(errmsg);
1546
        json_object_put(request);
1547
        collection_func_global = NULL;
1548
        file_func_global = NULL;
1549
        group_func_global = NULL;
1550
        foreach_task_user_data_global = NULL;
1551
        return FALSE;
1552
    }
1553

                
1554
    collection_func_global = NULL;
1555
    file_func_global = NULL;
1556
    group_func_global = NULL;
1557
    foreach_task_user_data_global = NULL;
1558

                
1559
    if (json_object_get_type(response_result) != json_type_boolean) {
1560
        // invalid type
1561
        g_print(__FILE__ ":%i response is of invalid type for method 'schedular_foreach_task', response = %s\n", __LINE__, json_object_get_string(response_result));
1562
        json_object_put(request);
1563
        json_object_put(response_result);
1564
        return FALSE;
1565
    }
1566

                
1567
    ret = json_object_get_boolean(response_result);
1568

                
1569
    json_object_put(request);
1570
    json_object_put(response_result);
1571

                
1572
    return ret;
1573
}
1574

                
1575
gboolean
1576
nntpgrab_glue_internal_schedular_move_task(NntpgrabGlue *obj, const char *collection_name_src, const char *subject_src, const char *collection_name_dest, int position_dest)
1577
{
1578
    NntpgrabGlue *glue = NNTPGRAB_GLUE(obj);
1579
    struct json_object *request;
1580
    struct json_object *request_params;
1581
    struct json_object *response_result;
1582
    char *errmsg = NULL;
1583

                
1584
    request_params = json_object_new_array();
1585
    json_object_array_add(request_params, json_object_new_string((char*) collection_name_src));
1586
    json_object_array_add(request_params, json_object_new_string((char*) subject_src));
1587
    json_object_array_add(request_params, json_object_new_string((char*) collection_name_dest));
1588
    json_object_array_add(request_params, json_object_new_int(position_dest));
1589
    request = create_new_json_request("nntpgrab_schedular_move_file", request_params);
1590

                
1591
    if (!(response_result = send_request_and_wait_for_response(glue, request, &errmsg))) {
1592
        g_print(__FILE__ ":%i nntpgrab_schedular_move_file FAILED: %s\n", __LINE__, errmsg);
1593
        g_free(errmsg);
1594
        json_object_put(request);
1595
        return FALSE;
1596
    }
1597

                
1598
    json_object_put(request);
1599
    json_object_put(response_result);
1600

                
1601
    return TRUE;
1602
}
1603

                
1604
gboolean
1605
nntpgrab_glue_internal_schedular_move_collection(NntpgrabGlue *obj, const char *collection_name, int new_position)
1606
{
1607
    NntpgrabGlue *glue = NNTPGRAB_GLUE(obj);
1608
    struct json_object *request;
1609
    struct json_object *request_params;
1610
    struct json_object *response_result;
1611
    char *errmsg = NULL;
1612

                
1613
    request_params = json_object_new_array();
1614
    json_object_array_add(request_params, json_object_new_string((char*) collection_name));
1615
    json_object_array_add(request_params, json_object_new_int(new_position));
1616
    request = create_new_json_request("nntpgrab_schedular_move_collection", request_params);
1617

                
1618
    if (!(response_result = send_request_and_wait_for_response(glue, request, &errmsg))) {
1619
        g_print(__FILE__ ":%i nntpgrab_schedular_move_collection FAILED: %s\n", __LINE__, errmsg);
1620
        g_free(errmsg);
1621
        json_object_put(request);
1622
        return FALSE;
1623
    }
1624

                
1625
    json_object_put(request);
1626
    json_object_put(response_result);
1627

                
1628
    return TRUE;
1629
}
1630

                
1631
gboolean
1632
nntpgrab_glue_internal_schedular_mark_task_optional(NntpgrabGlue *obj, const char *collection_name, const char *subject, ngboolean is_optional)
1633
{
1634
    NntpgrabGlue *glue = NNTPGRAB_GLUE(obj);
1635
    struct json_object *request;
1636
    struct json_object *request_params;
1637
    struct json_object *response_result;
1638
    char *errmsg = NULL;
1639

                
1640
    request_params = json_object_new_array();
1641
    json_object_array_add(request_params, json_object_new_string((char*) collection_name));
1642
    json_object_array_add(request_params, json_object_new_string((char*) subject));
1643
    json_object_array_add(request_params, json_object_new_boolean(is_optional));
1644
    request = create_new_json_request("nntpgrab_schedular_mark_task_optional", request_params);
1645

                
1646
    if (!(response_result = send_request_and_wait_for_response(glue, request, &errmsg))) {
1647
        g_print(__FILE__ ":%i nntpgrab_schedular_mark_task_optional FAILED: %s\n", __LINE__, errmsg);
1648
        g_free(errmsg);
1649
        json_object_put(request);
1650
        return FALSE;
1651
    }
1652

                
1653
    json_object_put(request);
1654
    json_object_put(response_result);
1655

                
1656
    return TRUE;
1657
}
1658

                
1659
NGList *
1660
nntpgrab_glue_internal_plugins_get_avail_plugins(NntpgrabGlue *obj)
1661
{
1662
    NntpgrabGlue *glue = NNTPGRAB_GLUE(obj);
1663
    struct json_object *request;
1664
    struct json_object *response_result;
1665
    NGList *ret = NULL;
1666
    char *errmsg = NULL;
1667
    int i;
1668
    int len;
1669

                
1670
    request = create_new_json_request("nntpgrab_plugins_get_avail_plugins", NULL);
1671

                
1672
    if (!(response_result = send_request_and_wait_for_response(glue, request, &errmsg))) {
1673
        g_print(__FILE__ ":%i nntpgrab_plugins_get_avail_plugins FAILED: %s\n", __LINE__, errmsg);
1674
        g_free(errmsg);
1675
        json_object_put(request);
1676
        return NULL;
1677
    }
1678

                
1679
    len = json_object_array_length(response_result);
1680
    for (i = 0; i < len; i++) {
1681
        struct json_object *obj = json_object_array_get_idx(response_result, i);
1682
        char *servername;
1683

                
1684
        g_return_val_if_fail(obj != NULL, NULL);
1685

                
1686
        servername = json_object_get_string(obj);
1687

                
1688
        g_return_val_if_fail(servername != NULL, NULL);
1689

                
1690
        ret = ng_list_append(ret, g_strdup(servername));
1691
    }
1692

                
1693
    json_object_put(request);
1694
    json_object_put(response_result);
1695

                
1696
    return ret;
1697
}
1698

                
1699
gboolean
1700
nntpgrab_glue_internal_plugins_get_plugin_info(NntpgrabGlue *obj, const char *plugin_name, NNTPGrabPluginInfo *plugin_info)
1701
{
1702
    NntpgrabGlue *glue = NNTPGRAB_GLUE(obj);
1703
    struct json_object *request;
1704
    struct json_object *request_params;
1705
    struct json_object *response_result;
1706
    char *errmsg = NULL;
1707
    char *name;
1708
    char *version;
1709
    char *author;
1710
    char *url;
1711
    char *description;
1712
    gboolean is_loaded;
1713
    gboolean is_persistent;
1714

                
1715
    g_return_val_if_fail(plugin_name != NULL, FALSE);
1716
    g_return_val_if_fail(plugin_info != NULL, FALSE);
1717

                
1718
    request_params = json_object_new_array();
1719
    json_object_array_add(request_params, json_object_new_string((char*) plugin_name));
1720
    request = create_new_json_request("nntpgrab_plugins_get_plugin_info", request_params);
1721

                
1722
    if (!(response_result = send_request_and_wait_for_response(glue, request, &errmsg))) {
1723
        g_print(__FILE__ ":%i nntpgrab_plugins_get_plugin_info FAILED: %s\n", __LINE__, errmsg);
1724
        g_free(errmsg);
1725
        json_object_put(request);
1726
        return FALSE;
1727
    }
1728

                
1729
    get_method_param(response_result, "name", "plugins_get_plugin_info", string, name);
1730
    get_method_param(response_result, "version", "plugins_get_plugin_info", string, version);
1731
    get_method_param(response_result, "author", "plugins_get_plugin_info", string, author);
1732
    get_method_param(response_result, "url", "plugins_get_plugin_info", string, url);
1733
    get_method_param(response_result, "description", "plugins_get_plugin_info", string, description);
1734
    get_method_param(response_result, "is_loaded", "plugins_get_plugin_info", boolean, is_loaded);
1735
    get_method_param(response_result, "is_persistent", "plugins_get_plugin_info", boolean, is_persistent);
1736

                
1737
    memset(plugin_info, 0, sizeof(NNTPGrabPluginInfo));
1738

                
1739
    strncpy(plugin_info->name, name, sizeof(plugin_info->name));
1740
    strncpy(plugin_info->version, version, sizeof(plugin_info->version));
1741
    strncpy(plugin_info->author, author, sizeof(plugin_info->author));
1742
    strncpy(plugin_info->url, url, sizeof(plugin_info->url));
1743
    strncpy(plugin_info->description, description, sizeof(plugin_info->description));
1744
    plugin_info->is_loaded = is_loaded;
1745
    plugin_info->is_persistent = is_persistent;
1746

                
1747
    json_object_put(request);
1748
    json_object_put(response_result);
1749

                
1750
    return TRUE;
1751
}
1752

                
1753
gboolean
1754
nntpgrab_glue_internal_plugins_load_plugin(NntpgrabGlue *obj, const char *plugin_name, char **errmsg)
1755
{
1756
    NntpgrabGlue *glue = NNTPGRAB_GLUE(obj);
1757
    struct json_object *request;
1758
    struct json_object *request_params;
1759
    struct json_object *response_result;
1760

                
1761
    request_params = json_object_new_array();
1762
    json_object_array_add(request_params, json_object_new_string((char*) plugin_name));
1763
    request = create_new_json_request("nntpgrab_plugins_load_plugin", request_params);
1764

                
1765
    if (!(response_result = send_request_and_wait_for_response(glue, request, errmsg))) {
1766
        json_object_put(request);
1767
        return FALSE;
1768
    }
1769

                
1770
    json_object_put(request);
1771
    json_object_put(response_result);
1772

                
1773
    return TRUE;
1774
}
1775

                
1776
gboolean
1777
nntpgrab_glue_internal_plugins_unload_plugin(NntpgrabGlue *obj, const char *plugin_name, char **errmsg)
1778
{
1779
    NntpgrabGlue *glue = NNTPGRAB_GLUE(obj);
1780
    struct json_object *request;
1781
    struct json_object *request_params;
1782
    struct json_object *response_result;
1783

                
1784
    request_params = json_object_new_array();
1785
    json_object_array_add(request_params, json_object_new_string((char*) plugin_name));
1786
    request = create_new_json_request("nntpgrab_plugins_unload_plugin", request_params);
1787

                
1788
    if (!(response_result = send_request_and_wait_for_response(glue, request, errmsg))) {
1789
        json_object_put(request);
1790
        return FALSE;
1791
    }
1792

                
1793
    json_object_put(request);
1794
    json_object_put(response_result);
1795

                
1796
    return TRUE;
1797
}
1798

                
1799
gboolean
1800
nntpgrab_glue_internal_plugins_set_persistent(NntpgrabGlue *obj, const char *plugin_name, ngboolean persistent)
1801
{
1802
    NntpgrabGlue *glue = NNTPGRAB_GLUE(obj);
1803
    struct json_object *request;
1804
    struct json_object *request_params;
1805
    struct json_object *response_result;
1806
    char *errmsg = NULL;
1807

                
1808
    request_params = json_object_new_array();
1809
    json_object_array_add(request_params, json_object_new_string((char*) plugin_name));
1810
    json_object_array_add(request_params, json_object_new_boolean(persistent));
1811
    request = create_new_json_request("nntpgrab_plugins_set_persistent", request_params);
1812

                
1813
    if (!(response_result = send_request_and_wait_for_response(glue, request, &errmsg))) {
1814
        g_print(__FILE__ ":%i nntpgrab_plugins_set_persistent FAILED: %s\n", __LINE__, errmsg);
1815
        g_free(errmsg);
1816
        json_object_put(request);
1817
        return FALSE;
1818
    }
1819

                
1820
    json_object_put(request);
1821
    json_object_put(response_result);
1822

                
1823
    return TRUE;
1824
}
1825

                
1826
NGVariant *
1827
nntpgrab_glue_internal_plugins_call_plugin_method(NntpgrabGlue *obj, const char *plugin_name, const char *method, NGVariant *parameters, char **errmsg)
1828
{
1829
    NntpgrabGlue *glue = NNTPGRAB_GLUE(obj);
1830
    struct json_object *request;
1831
    struct json_object *request_params;
1832
    struct json_object *response_result;
1833
    char *params_str;
1834
    GVariant *ret;
1835
    GError *error = NULL;
1836

                
1837
    g_return_val_if_fail(glue != NULL, NULL);
1838
    g_return_val_if_fail(plugin_name != NULL, NULL);
1839
    g_return_val_if_fail(method != NULL, NULL);
1840
    g_return_val_if_fail(parameters != NULL, NULL);
1841

                
1842
    params_str = g_variant_print((GVariant*) parameters, TRUE);
1843

                
1844
    request_params = json_object_new_array();
1845
    json_object_array_add(request_params, json_object_new_string((char*) plugin_name));
1846
    json_object_array_add(request_params, json_object_new_string((char*) method));
1847
    json_object_array_add(request_params, json_object_new_string((char*) params_str));
1848
    request = create_new_json_request("nntpgrab_plugins_call_plugin_method", request_params);
1849

                
1850
    if (!(response_result = send_request_and_wait_for_response(glue, request, errmsg))) {
1851
        json_object_put(request);
1852
        g_free(params_str);
1853
        return NULL;
1854
    }
1855

                
1856
    ret = g_variant_parse(NULL, json_object_get_string(response_result), NULL, NULL, &error);
1857
    if (!ret) {
1858
        if (errmsg) {
1859
            *errmsg = g_strdup(error->message);
1860
        }
1861
        g_error_free(error);
1862
    }
1863

                
1864
    json_object_put(request);
1865
    json_object_put(response_result);
1866

                
1867
    g_free(params_str);
1868

                
1869
    return (NGVariant*) ret;
1870
}
1871

                
1872
void
1873
nntpgrab_glue_internal_set_emit_log_messages(NntpgrabGlue *obj, ngboolean val)
1874
{
1875
    NntpgrabGlue *glue = NNTPGRAB_GLUE(obj);
1876
    struct json_object *request;
1877
    struct json_object *request_params;
1878
    struct json_object *response_result;
1879
    char *errmsg = NULL;
1880

                
1881
    request_params = json_object_new_array();
1882
    json_object_array_add(request_params, json_object_new_boolean(val));
1883
    request = create_new_json_request("nntpgrab_set_emit_log_messages", request_params);
1884

                
1885
    if (!(response_result = send_request_and_wait_for_response(glue, request, &errmsg))) {
1886
        g_print(__FILE__ ":%i nntpgrab_set_emit_log_messages FAILED: %s\n", __LINE__, errmsg);
1887
        g_free(errmsg);
1888
        json_object_put(request);
1889
        return;
1890
    }
1891

                
1892
    json_object_put(response_result);
1893
    json_object_put(request);
1894
}