Statistics
| Revision:

root / trunk / base / nzbcreator.c @ 1834

History | View | Annotate | Download (21.1 KB)

1
/* 
2
    Copyright (C) 2005-2010  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 
24
#include 
25
#include 
26
#ifdef HAVE_SOUP
27
#include 
28
#endif
29
#ifdef HAVE_SOUP_GNOME
30
#include 
31
#endif
32
#include "nntpgrab_utils.h"
33
#include "nntpgrab_types.h"
34

                
35
#define URI "https://www.nntpgrab.nl/onlinesearch/search.php"
36

                
37
#ifdef HAVE_SOUP
38
static void authenticate_cb(SoupSession *session, SoupMessage *msg, SoupAuth *auth, gboolean retrying, gpointer user_data)
39
{
40
    soup_auth_authenticate(auth, "guest", "guest");
41
}
42
#endif
43

                
44
ngboolean
45
nntpgrab_utils_nzbcreator_check_api_version(ngboolean *api_okay, char **errmsg)
46
{
47
#ifdef HAVE_SOUP
48
    int result = 0;
49
    SoupSession *session;
50
    SoupMessage *msg;
51
    GError *err = NULL;
52
    NGList *list;
53

                
54
    g_return_val_if_fail(api_okay != NULL, FALSE);
55

                
56
    session = soup_session_sync_new();
57

                
58
#ifdef HAVE_SOUP_GNOME
59
    /* Enable proxy support when using GNOME 2.26.0 or higher */
60
    soup_session_add_feature_by_type(session, SOUP_TYPE_GNOME_FEATURES_2_26);
61
#endif
62

                
63
#ifdef HAVE_SOUP_GZIP
64
    /* Enable gzip compression */
65
    soup_session_add_feature_by_type(session, SOUP_TYPE_CONTENT_DECODER);
66
#endif
67

                
68
    g_signal_connect (session, "authenticate", G_CALLBACK(authenticate_cb), NULL);
69

                
70
    msg = soup_xmlrpc_request_new(URI, "getProtocolVersion", G_TYPE_INVALID);
71
    soup_session_send_message(session, msg);
72

                
73
    if (!SOUP_STATUS_IS_SUCCESSFUL (msg->status_code)) {
74
        if (errmsg) {
75
            *errmsg = g_strdup(msg->reason_phrase);
76
        }
77

                
78
        g_object_unref(msg);
79
        g_object_unref(session);
80
        return FALSE;
81
    }
82

                
83
    if (!soup_xmlrpc_extract_method_response(msg->response_body->data, msg->response_body->length, &err, G_TYPE_INT, &result)) {
84
        if (err) {
85
            if (errmsg) {
86
                *errmsg = g_strdup(err->message);
87
            }
88

                
89
            g_error_free(err);
90
        }
91

                
92
        g_object_unref(msg);
93
        g_object_unref(session);
94

                
95
        return FALSE;
96
    }
97

                
98
    g_object_unref(msg);
99
    g_object_unref(session);
100

                
101
    if (result == 20110613) {
102
        *api_okay = TRUE;
103
    } else {
104
        *api_okay = FALSE;
105
    }
106

                
107
    return TRUE;
108
#else
109
    if (errmsg) {
110
        *errmsg = g_strdup(_("Support for the Online Search hasn't been enabled in this build. Please rebuild NNTPGrab to enable this feature"));
111
    }
112
    return FALSE;
113
#endif
114
}
115

                
116
void
117
nntpgrab_utils_nzbcreator_free_groups(NGList *groups)
118
{
119
    NGList *list = groups;
120
    while (list) {
121
        g_slice_free(NZBCreatorGroup, list->data);
122
        list = ng_list_next(list);
123
    }
124
    ng_list_free(groups);
125
}
126

                
127
NGList *
128
nntpgrab_utils_nzbcreator_get_all_groups(char **errmsg)
129
{
130
    NGList *ret = NULL;
131

                
132
#ifndef HAVE_SOUP
133
    if (errmsg) {
134
        *errmsg = g_strdup(_("Support for the Online Search hasn't been enabled in this build. Please rebuild NNTPGrab to enable this feature"));
135
    }
136
#else
137
    SoupSession *session = soup_session_sync_new();
138
    SoupMessage *msg = soup_xmlrpc_request_new(URI, "getListOfAvailableGroups", G_TYPE_INVALID);
139
    GError *err = NULL;
140
    int i;
141
    GValueArray *result = NULL;
142
    GHashTable *group_arr = NULL;
143

                
144
#ifdef SOUP_TYPE_GNOME_FEATURES_2_26
145
    /* Enable proxy support when using GNOME 2.26.0 or higher */
146
    soup_session_add_feature_by_type(session, SOUP_TYPE_GNOME_FEATURES_2_26);
147
#endif
148

                
149
#ifdef HAVE_SOUP_GZIP
150
    /* Enable gzip compression */
151
    soup_session_add_feature_by_type(session, SOUP_TYPE_CONTENT_DECODER);
152
#endif
153

                
154
    g_signal_connect (session, "authenticate", G_CALLBACK(authenticate_cb), NULL);
155

                
156
    soup_session_send_message(session, msg);
157
    if (!SOUP_STATUS_IS_SUCCESSFUL (msg->status_code)) {
158
        if (errmsg) {
159
            *errmsg = g_strdup_printf("Server returned unknown error: %s (%i)", msg->reason_phrase, msg->status_code);
160
        }
161
        g_object_unref(msg);
162
        g_object_unref(session);
163
        return NULL;
164
    }
165

                
166
    if (!soup_xmlrpc_extract_method_response(msg->response_body->data, msg->response_body->length, &err, G_TYPE_VALUE_ARRAY, &result)) {
167
        if (errmsg) {
168
            if (err) {
169
                *errmsg = g_strdup_printf("Unable to parse reply: %s", err->message);
170
            } else {
171
                *errmsg = g_strdup_printf(__FILE__ ":%i Unable to parse reply from server. See the console for more details", __LINE__);
172
            }
173
        }
174

                
175
        if (err) {
176
            g_error_free(err);
177
        }
178

                
179
        g_object_unref(msg);
180
        g_object_unref(session);
181

                
182
        return NULL;
183
    }
184

                
185
    for (i = 0; i < result->n_values; i++) {
186
        NZBCreatorGroup *group;
187
        char *groupname = NULL;
188
        int group_id = -1;
189

                
190
        if (!soup_value_array_get_nth(result, i, G_TYPE_HASH_TABLE, &group_arr)) {
191
            g_warning(__FILE__ ":%i Unable to parse values", __LINE__);
192
            continue;
193
        }
194

                
195
        if (!soup_value_hash_lookup_vals(group_arr, "group_id", G_TYPE_INT, &group_id, "newsgroup", G_TYPE_STRING, &groupname, NULL)) {
196
            g_warning(__FILE__ ":%i Unable to parse values", __LINE__);
197
            g_hash_table_destroy(group_arr);
198
            continue;
199
        }
200

                
201
        group = g_slice_new0(NZBCreatorGroup);
202
        strncpy(group->newsgroup, groupname, sizeof(group->newsgroup) - 1);
203
        group->group_id = group_id;
204

                
205
        ret = ng_list_append(ret, group);
206
    }
207

                
208
    g_value_array_free(result);
209

                
210
    g_object_unref(msg);
211
    g_object_unref(session);
212
#endif
213

                
214
    return ret;
215
}
216

                
217
void
218
nntpgrab_utils_nzbcreator_free_result(NZBCreatorSearchResult *result)
219
{
220
    NGList *list;
221

                
222
    list = result->collections;
223
    while (list) {
224
        g_slice_free(NZBCreatorCollection, list->data);
225
        list = ng_list_next(list);
226
    }
227

                
228
    g_list_free((GList*) result->collections);
229
    g_slice_free(NZBCreatorSearchResult, result);
230
}
231

                
232
NZBCreatorSearchResult *
233
nntpgrab_utils_nzbcreator_perform_search(NZBCreatorSearchOpts opts, char **errmsg)
234
{
235
    NZBCreatorSearchResult *result = NULL;
236

                
237
#ifndef HAVE_SOUP
238
    if (errmsg) {
239
        *errmsg = g_strdup(_("Support for the Online Search hasn't been enabled in this build. Please rebuild NNTPGrab to enable this feature"));
240
    }
241
#else
242
    SoupSession *session;
243
    SoupMessage *msg;
244
    GHashTable *args;
245
    GError *err = NULL;
246
    GHashTable *rpc_result = NULL;
247
    GValueArray *matches = NULL;
248
    int i;
249

                
250
    g_return_val_if_fail(strlen(opts.query) > 0, FALSE);
251
    g_return_val_if_fail(opts.max_age <= 150, FALSE);
252
    g_return_val_if_fail(opts.percentage_complete <= 100, FALSE);
253

                
254
    session = soup_session_sync_new();
255

                
256
#ifdef SOUP_TYPE_GNOME_FEATURES_2_26
257
    /* Enable proxy support when using GNOME 2.26.0 or higher */
258
    soup_session_add_feature_by_type(session, SOUP_TYPE_GNOME_FEATURES_2_26);
259
#endif
260

                
261
#ifdef HAVE_SOUP_GZIP
262
    /* Enable gzip compression */
263
    soup_session_add_feature_by_type(session, SOUP_TYPE_CONTENT_DECODER);
264
#endif
265

                
266
    g_signal_connect (session, "authenticate", G_CALLBACK(authenticate_cb), NULL);
267

                
268
    args = soup_value_hash_new_with_vals(   "query", G_TYPE_STRING, opts.query,
269
                                            "search_only_in", G_TYPE_INT, opts.search_only_in,
270
                                            "max_age", G_TYPE_INT, opts.max_age,
271
                                            NULL);
272

                
273
    if (strlen(opts.username) > 0 && strlen(opts.password) > 0) {
274
        soup_value_hash_insert(args, "username", G_TYPE_STRING, opts.username);
275
        soup_value_hash_insert(args, "password", G_TYPE_STRING, opts.password);
276
    }
277

                
278
    if (opts.minimal_file_size > 0) {
279
        /* Libsoup doesn't support 64bit integers as XML-RPC parameters */
280
        char *tmp = g_strdup_printf("%"G_GUINT64_FORMAT, opts.minimal_file_size);
281
        soup_value_hash_insert(args, "minimal_file_size", G_TYPE_STRING, tmp);
282
        g_free(tmp);
283
    }
284
    if (opts.maximal_file_size > 0) {
285
        char *tmp = g_strdup_printf("%"G_GUINT64_FORMAT, opts.maximal_file_size);
286
        soup_value_hash_insert(args, "maximal_file_size", G_TYPE_STRING, tmp);
287
        g_free(tmp);
288
    }
289
    if (opts.percentage_complete > 0) {
290
        soup_value_hash_insert(args, "percentage_complete", G_TYPE_INT, opts.percentage_complete);
291
    }
292
    if (opts.group_to_search > 0) {
293
        soup_value_hash_insert(args, "group_to_search", G_TYPE_INT, opts.group_to_search);
294
    }
295
    if (opts.file_type != NNTP_FILE_TYPE_UNKNOWN) {
296
        soup_value_hash_insert(args, "file_type", G_TYPE_INT, opts.file_type);
297
    }
298

                
299
    msg = soup_xmlrpc_request_new(URI, "performSearch", G_TYPE_HASH_TABLE, args, G_TYPE_INVALID);
300

                
301
    soup_session_send_message(session, msg);
302

                
303
    g_hash_table_destroy(args);
304

                
305
    if (!SOUP_STATUS_IS_SUCCESSFUL (msg->status_code)) {
306
        if (errmsg) {
307
            *errmsg = g_strdup_printf("Server returned unknown error: %s (%i)", msg->reason_phrase, msg->status_code);
308
        }
309
        g_object_unref(msg);
310
        g_object_unref(session);
311
        return NULL;
312
    }
313

                
314
    if (!soup_xmlrpc_extract_method_response(msg->response_body->data, msg->response_body->length, &err, G_TYPE_HASH_TABLE, &rpc_result)) {
315
        if (errmsg) {
316
            if (err) {
317
                *errmsg = g_strdup_printf("Unable to parse reply: %s", err->message);
318
            } else {
319
                *errmsg = g_strdup_printf(__FILE__ ":%i Unable to parse reply from server. See the console for more details", __LINE__);
320
            }
321
        }
322

                
323
        if (err) {
324
            g_error_free(err);
325
        }
326

                
327
        g_object_unref(msg);
328
        g_object_unref(session);
329

                
330
        return NULL;
331
    }
332

                
333
    result = g_slice_new0(NZBCreatorSearchResult);
334
    if (!soup_value_hash_lookup_vals(rpc_result,    "number_of_hits", G_TYPE_INT, &result->number_of_hits,
335
                                                    "number_of_results", G_TYPE_INT, &result->number_of_results,
336
                                                    "matches", G_TYPE_VALUE_ARRAY, &matches,
337
                                                    NULL)) {
338
        g_warning(__FILE__ ":%i Unable to parse values", __LINE__);
339
        g_slice_free(NZBCreatorSearchResult, result);
340
        g_hash_table_destroy(rpc_result);
341
        g_object_unref(msg);
342
        g_object_unref(session);
343
        return NULL;
344
    }
345

                
346
    for (i = 0; i < matches->n_values; i++) {
347
        NZBCreatorCollection *collection;
348
        GHashTable *hash_collection = NULL;
349
        int collection_id = 0;
350
        char *collection_name;
351
        char *short_collection_name;
352
        char *poster;
353
        char *newsgroup;
354
        int stamp = 0;
355
        int num_parts_found = -1;
356
        int num_parts_expected = -1;
357
        /* gint64 */guint total_size = -1;
358
        int complete_percentage = 0;
359
        int num_regular_files = 0;
360
        int num_par2_files = 0;
361
        int first_file_id = -1;
362

                
363
        if (!soup_value_array_get_nth(matches, i, G_TYPE_HASH_TABLE, &hash_collection)) {
364
            g_warning(__FILE__ ":%i Unable to parse values", __LINE__);
365
            continue;
366
        }
367

                
368
        if (!soup_value_hash_lookup_vals(hash_collection,   "collection_id", G_TYPE_INT, &collection_id,
369
                                                            "collection_name", G_TYPE_STRING, &collection_name,
370
                                                            "short_collection_name", G_TYPE_STRING, &short_collection_name,
371
                                                            "poster", G_TYPE_STRING, &poster,
372
                                                            "total_size", G_TYPE_INT, &total_size,       // FIXME: possible overflow!
373
                                                            "newsgroup", G_TYPE_STRING, &newsgroup,
374
                                                            "stamp", G_TYPE_INT, &stamp,
375
                                                            "num_parts_found", G_TYPE_INT, &num_parts_found,
376
                                                            "num_parts_expected", G_TYPE_INT, &num_parts_expected,
377
                                                            "complete_percentage", G_TYPE_INT, &complete_percentage,
378
                                                            "num_regular_files", G_TYPE_INT, &num_regular_files,
379
                                                            "num_par2_files", G_TYPE_INT, &num_par2_files,
380
                                                            "first_file_id", G_TYPE_INT, &first_file_id,
381
                                                            NULL)) {
382
            g_warning(__FILE__ ":%i Unable to parse values", __LINE__);
383
            g_hash_table_destroy(hash_collection);
384
            continue;
385
        }
386

                
387
        collection = g_slice_new0(NZBCreatorCollection);
388
        collection->collection_id = collection_id;
389
        strncpy(collection->collection_name, collection_name, sizeof(collection->collection_name) - 1);
390
        strncpy(collection->short_collection_name, short_collection_name, sizeof(collection->short_collection_name) - 1);
391
        strncpy(collection->poster, poster, sizeof(collection->poster) - 1);
392
        collection->total_size = total_size;
393
        strncpy(collection->newsgroup, newsgroup, sizeof(collection->newsgroup) - 1);
394
        collection->stamp = (time_t) stamp;
395
        collection->num_parts_found = num_parts_found;
396
        collection->num_parts_expected = num_parts_expected;
397
        collection->complete_percentage = complete_percentage;
398
        collection->num_regular_files = num_regular_files;
399
        collection->num_par2_files = num_par2_files;
400
        collection->first_file_id = first_file_id;
401

                
402
        result->collections = ng_list_append(result->collections, collection);
403
    }
404

                
405
    g_hash_table_destroy(rpc_result);
406
    g_object_unref(msg);
407
    g_object_unref(session);
408
#endif
409

                
410
    return result;
411
}
412

                
413
NGList *
414
nntpgrab_utils_nzbcreator_retrieve_collection_details(ngint64 collection_id, time_t stamp, char **errmsg)
415
{
416
    NGList *result = NULL;
417

                
418
#ifndef HAVE_SOUP
419
    if (errmsg) {
420
        *errmsg = g_strdup(_("Support for the Online Search hasn't been enabled in this build. Please rebuild NNTPGrab to enable this feature"));
421
    }
422
#else
423
    SoupSession *session;
424
    SoupMessage *msg;
425
    GHashTable *args;
426
    GError *err = NULL;
427
    GHashTable *rpc_result = NULL;
428
    GValueArray *matches = NULL;
429
    int i;
430

                
431
    g_return_val_if_fail(collection_id > 0, FALSE);
432

                
433
    session = soup_session_sync_new();
434

                
435
#ifdef SOUP_TYPE_GNOME_FEATURES_2_26
436
    /* Enable proxy support when using GNOME 2.26.0 or higher */
437
    soup_session_add_feature_by_type(session, SOUP_TYPE_GNOME_FEATURES_2_26);
438
#endif
439

                
440
#ifdef HAVE_SOUP_GZIP
441
    /* Enable gzip compression */
442
    soup_session_add_feature_by_type(session, SOUP_TYPE_CONTENT_DECODER);
443
#endif
444

                
445
    g_signal_connect (session, "authenticate", G_CALLBACK(authenticate_cb), NULL);
446

                
447
    args = soup_value_hash_new_with_vals("collection_id", G_TYPE_INT, (int) collection_id,
448
                                         "stamp", G_TYPE_INT, (int) stamp,
449
                                         NULL);
450
    msg = soup_xmlrpc_request_new(URI, "retrieveCollectionDetails", G_TYPE_HASH_TABLE, args, G_TYPE_INVALID);
451

                
452
    soup_session_send_message(session, msg);
453

                
454
    g_hash_table_destroy(args);
455

                
456
    if (!SOUP_STATUS_IS_SUCCESSFUL (msg->status_code)) {
457
        if (errmsg) {
458
            *errmsg = g_strdup_printf("Server returned unknown error: %s (%i)", msg->reason_phrase, msg->status_code);
459
        }
460
        g_object_unref(msg);
461
        g_object_unref(session);
462
        return NULL;
463
    }
464

                
465
    if (!soup_xmlrpc_extract_method_response(msg->response_body->data, msg->response_body->length, &err, G_TYPE_VALUE_ARRAY, &matches)) {
466
        if (errmsg) {
467
            if (err) {
468
                *errmsg = g_strdup_printf("Unable to parse reply: %s", err->message);
469
            } else {
470
                *errmsg = g_strdup_printf(__FILE__ ":%i Unable to parse reply from server:\n%s", __LINE__, msg->response_body->data);
471
            }
472
        }
473

                
474
        if (err) {
475
            g_error_free(err);
476
        }
477

                
478
        g_object_unref(msg);
479
        g_object_unref(session);
480

                
481
        return NULL;
482
    }
483

                
484
    for (i = 0; i < matches->n_values; i++) {
485
        NZBCreatorFile *file;
486
        GHashTable *hash_file = NULL;
487
        /* gint64 */gint file_id = -1;
488
        char *subject = NULL;
489
        char *poster = NULL;
490
        int num_parts_found = -1;
491
        int num_parts_expected = -1;
492
        int file_type = NNTP_FILE_TYPE_UNKNOWN;
493
        /* gint64 */gint file_size = -1;
494
        int complete_percentage = 0;
495
        int stamp;
496

                
497
        if (!soup_value_array_get_nth(matches, i, G_TYPE_HASH_TABLE, &hash_file)) {
498
            g_warning(__FILE__ ":%i Unable to parse values", __LINE__);
499
            continue;
500
        }
501

                
502
        if (!soup_value_hash_lookup_vals(hash_file, "file_id", G_TYPE_INT, &file_id,            // FIXME: possible overflow!
503
                                                    "subject", G_TYPE_STRING, &subject,
504
                                                    "poster", G_TYPE_STRING, &poster,
505
                                                    "num_parts_found", G_TYPE_INT, &num_parts_found,
506
                                                    "num_parts_expected", G_TYPE_INT, &num_parts_expected,
507
                                                    "file_type", G_TYPE_INT, &file_type,
508
                                                    "file_size", G_TYPE_INT, &file_size,        // FIXME: possible overflow!
509
                                                    "stamp", G_TYPE_INT, &stamp,
510
                                                    "complete_percentage", G_TYPE_INT, &complete_percentage,
511
                                                    NULL)) {
512
            g_warning(__FILE__ ":%i Unable to parse values", __LINE__);
513
            continue;
514
        }
515

                
516
        file = g_slice_new0(NZBCreatorFile);
517
        file->file_id = file_id;
518
        strncpy(file->subject, subject, sizeof(file->subject) - 1);
519
        strncpy(file->poster, poster, sizeof(file->poster) - 1);
520
        file->num_parts_found = num_parts_found;
521
        file->num_parts_expected = num_parts_expected;
522
        file->file_type = (NNTPFileType) file_type;
523
        file->file_size = file_size;
524
        file->stamp = (time_t) stamp;
525
        file->complete_percentage = complete_percentage;
526

                
527
        result = ng_list_append(result, file);
528
    }
529

                
530
    g_object_unref(msg);
531
    g_object_unref(session);
532
#endif
533

                
534
    return result;
535
}
536

                
537
void nntpgrab_utils_nzbcreator_free_collection_details(NGList *files)
538
{
539
    NGList *list;
540

                
541
    list = files;
542
    while (list) {
543
        g_slice_free(NZBCreatorFile, list->data);
544
        list = ng_list_next(list);
545
    }
546

                
547
    g_list_free((GList*) files);
548
}
549

                
550
char *
551
nntpgrab_utils_nzbcreator_generate_NZB(NGList *file_ids, char **errmsg)
552
{
553
    char *result = NULL;
554

                
555
#ifndef HAVE_SOUP
556
    if (errmsg) {
557
        *errmsg = g_strdup(_("Support for the Online Search hasn't been enabled in this build. Please rebuild NNTPGrab to enable this feature"));
558
    }
559
#else
560
    SoupSession *session;
561
    SoupMessage *msg;
562
    GError *err = NULL;
563
    GValueArray *args = NULL;
564
    NGList *list;
565

                
566
    args = soup_value_array_new();
567
    list = file_ids;
568
    while (list) {
569
        soup_value_array_append(args, G_TYPE_INT, GPOINTER_TO_INT(list->data));
570
        list = ng_list_next(list);
571
    }
572

                
573
    session = soup_session_sync_new();
574

                
575
#ifdef HAVE_SOUP_GNOME
576
    /* Enable proxy support when using GNOME 2.26.0 or higher */
577
    soup_session_add_feature_by_type(session, SOUP_TYPE_GNOME_FEATURES_2_26);
578
#endif
579

                
580
#ifdef HAVE_SOUP_GZIP
581
    /* Enable gzip compression */
582
    soup_session_add_feature_by_type(session, SOUP_TYPE_CONTENT_DECODER);
583
#endif
584

                
585
    g_signal_connect (session, "authenticate", G_CALLBACK(authenticate_cb), NULL);
586

                
587
    msg = soup_xmlrpc_request_new(URI, "generateNZB", G_TYPE_VALUE_ARRAY, args, G_TYPE_INVALID);
588
    soup_session_send_message(session, msg);
589

                
590
    g_value_array_free(args);
591

                
592
    if (!SOUP_STATUS_IS_SUCCESSFUL (msg->status_code)) {
593
        if (errmsg) {
594
            *errmsg = g_strdup_printf("Server returned unknown error: %s (%i)", msg->reason_phrase, msg->status_code);
595
        }
596
        g_object_unref(msg);
597
        g_object_unref(session);
598
        return NULL;
599
    }
600

                
601
    if (!soup_xmlrpc_extract_method_response(msg->response_body->data, msg->response_body->length, &err, G_TYPE_STRING, &result)) {
602
        if (errmsg) {
603
            if (err) {
604
                *errmsg = g_strdup_printf("Unable to parse reply: %s", err->message);
605
            } else {
606
                *errmsg = g_strdup_printf(__FILE__ ":%i Unable to parse reply from server. See the console for more details", __LINE__);
607
            }
608
        }
609

                
610
        if (err) {
611
            g_error_free(err);
612
        }
613

                
614
        g_object_unref(msg);
615
        g_object_unref(session);
616

                
617
        return NULL;
618
    }
619

                
620
    g_object_unref(msg);
621
    g_object_unref(session);
622
#endif
623

                
624
    return result;
625
}
626