~ubuntu-branches/ubuntu/utopic/evolution-data-server/utopic-proposed

« back to all changes in this revision

Viewing changes to camel/camel-imapx-search.c

  • Committer: Package Import Robot
  • Author(s): Iain Lane
  • Date: 2014-06-13 12:02:14 UTC
  • mfrom: (1.1.116) (1.2.35 sid)
  • Revision ID: package-import@ubuntu.com-20140613120214-1zx93d8jxwt093aw
Tags: 3.12.2-1ubuntu1
* Merge with Debian, remaining changes:
  - debian/control: build depend on hardening-wrapper
  - Add build-depends and pass configure flag to enable Ubuntu Online
    Accounts support.
  - Filter out -Bsymbolic-functions from LDFLAGS (for future people
    wondering about this change, see e.g. BGO #594473 and duplicates).
  - Enable Ubuntu Online Accounts and split it and GOA into a separate
    package

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 * camel-imapx-search.c
3
 
 *
4
 
 * This program is free software; you can redistribute it and/or
5
 
 * modify it under the terms of the GNU Lesser General Public
6
 
 * License as published by the Free Software Foundation; either
7
 
 * version 2 of the License, or (at your option) version 3.
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 GNU
12
 
 * Lesser General Public License for more details.
13
 
 *
14
 
 * You should have received a copy of the GNU Lesser General Public
15
 
 * License along with the program; if not, see <http://www.gnu.org/licenses/>
16
 
 *
17
 
 */
18
 
 
19
 
#include "camel-imapx-search.h"
20
 
 
21
 
#include "camel-offline-store.h"
22
 
#include "camel-search-private.h"
23
 
 
24
 
#define CAMEL_IMAPX_SEARCH_GET_PRIVATE(obj) \
25
 
        (G_TYPE_INSTANCE_GET_PRIVATE \
26
 
        ((obj), CAMEL_TYPE_IMAPX_SEARCH, CamelIMAPXSearchPrivate))
27
 
 
28
 
struct _CamelIMAPXSearchPrivate {
29
 
        GWeakRef server;
30
 
        gint *local_data_search; /* not NULL, if testing whether all used headers are all locally available */
31
 
};
32
 
 
33
 
enum {
34
 
        PROP_0,
35
 
        PROP_SERVER
36
 
};
37
 
 
38
 
G_DEFINE_TYPE (
39
 
        CamelIMAPXSearch,
40
 
        camel_imapx_search,
41
 
        CAMEL_TYPE_FOLDER_SEARCH)
42
 
 
43
 
static void
44
 
imapx_search_set_property (GObject *object,
45
 
                           guint property_id,
46
 
                           const GValue *value,
47
 
                           GParamSpec *pspec)
48
 
{
49
 
        switch (property_id) {
50
 
                case PROP_SERVER:
51
 
                        camel_imapx_search_set_server (
52
 
                                CAMEL_IMAPX_SEARCH (object),
53
 
                                g_value_get_object (value));
54
 
                        return;
55
 
        }
56
 
 
57
 
        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
58
 
}
59
 
 
60
 
static void
61
 
imapx_search_get_property (GObject *object,
62
 
                           guint property_id,
63
 
                           GValue *value,
64
 
                           GParamSpec *pspec)
65
 
{
66
 
        switch (property_id) {
67
 
                case PROP_SERVER:
68
 
                        g_value_take_object (
69
 
                                value,
70
 
                                camel_imapx_search_ref_server (
71
 
                                CAMEL_IMAPX_SEARCH (object)));
72
 
                        return;
73
 
        }
74
 
 
75
 
        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
76
 
}
77
 
 
78
 
static void
79
 
imapx_search_dispose (GObject *object)
80
 
{
81
 
        CamelIMAPXSearchPrivate *priv;
82
 
 
83
 
        priv = CAMEL_IMAPX_SEARCH_GET_PRIVATE (object);
84
 
 
85
 
        g_weak_ref_set (&priv->server, NULL);
86
 
 
87
 
        /* Chain up to parent's dispose() method. */
88
 
        G_OBJECT_CLASS (camel_imapx_search_parent_class)->dispose (object);
89
 
}
90
 
 
91
 
static CamelSExpResult *
92
 
imapx_search_result_match_all (CamelSExp *sexp,
93
 
                               CamelFolderSearch *search)
94
 
{
95
 
        CamelSExpResult *result;
96
 
 
97
 
        g_return_val_if_fail (search != NULL, NULL);
98
 
 
99
 
        if (search->current != NULL) {
100
 
                result = camel_sexp_result_new (sexp, CAMEL_SEXP_RES_BOOL);
101
 
                result->value.boolean = TRUE;
102
 
        } else {
103
 
                gint ii;
104
 
 
105
 
                result = camel_sexp_result_new (sexp, CAMEL_SEXP_RES_ARRAY_PTR);
106
 
                result->value.ptrarray = g_ptr_array_new ();
107
 
 
108
 
                for (ii = 0; ii < search->summary->len; ii++)
109
 
                        g_ptr_array_add (
110
 
                                result->value.ptrarray,
111
 
                                (gpointer) search->summary->pdata[ii]);
112
 
        }
113
 
 
114
 
        return result;
115
 
}
116
 
 
117
 
static CamelSExpResult *
118
 
imapx_search_result_match_none (CamelSExp *sexp,
119
 
                                CamelFolderSearch *search)
120
 
{
121
 
        CamelSExpResult *result;
122
 
 
123
 
        g_return_val_if_fail (search != NULL, NULL);
124
 
 
125
 
        if (search->current != NULL) {
126
 
                result = camel_sexp_result_new (sexp, CAMEL_SEXP_RES_BOOL);
127
 
                result->value.boolean = FALSE;
128
 
        } else {
129
 
                result = camel_sexp_result_new (sexp, CAMEL_SEXP_RES_ARRAY_PTR);
130
 
                result->value.ptrarray = g_ptr_array_new ();
131
 
        }
132
 
 
133
 
        return result;
134
 
}
135
 
 
136
 
static CamelSExpResult *
137
 
imapx_search_process_criteria (CamelSExp *sexp,
138
 
                               CamelFolderSearch *search,
139
 
                               CamelIMAPXServer *server,
140
 
                               const GString *criteria,
141
 
                               const gchar *from_function)
142
 
{
143
 
        CamelSExpResult *result;
144
 
        GPtrArray *uids = NULL;
145
 
        GError *error = NULL;
146
 
 
147
 
        uids = camel_imapx_server_uid_search (
148
 
                server, search->folder, criteria->str, NULL, &error);
149
 
 
150
 
        /* Sanity check. */
151
 
        g_return_val_if_fail (
152
 
                ((uids != NULL) && (error == NULL)) ||
153
 
                ((uids == NULL) && (error != NULL)), NULL);
154
 
 
155
 
        /* XXX No allowance for errors in CamelSExp callbacks!
156
 
         *     Dump the error to the console and make like we
157
 
         *     got an empty result. */
158
 
        if (error != NULL) {
159
 
                g_warning (
160
 
                        "%s: (UID SEARCH %s): %s",
161
 
                        from_function, criteria->str, error->message);
162
 
                uids = g_ptr_array_new ();
163
 
                g_error_free (error);
164
 
        }
165
 
 
166
 
        if (search->current != NULL) {
167
 
                result = camel_sexp_result_new (sexp, CAMEL_SEXP_RES_BOOL);
168
 
                result->value.boolean = (uids && uids->len > 0);
169
 
        } else {
170
 
                result = camel_sexp_result_new (sexp, CAMEL_SEXP_RES_ARRAY_PTR);
171
 
                result->value.ptrarray = g_ptr_array_ref (uids);
172
 
        }
173
 
 
174
 
        g_ptr_array_unref (uids);
175
 
 
176
 
        return result;
177
 
}
178
 
 
179
 
static CamelSExpResult *
180
 
imapx_search_match_all (CamelSExp *sexp,
181
 
                        gint argc,
182
 
                        CamelSExpTerm **argv,
183
 
                        CamelFolderSearch *search)
184
 
{
185
 
        CamelIMAPXSearch *imapx_search = CAMEL_IMAPX_SEARCH (search);
186
 
        CamelIMAPXServer *server;
187
 
        CamelSExpResult *result;
188
 
        GPtrArray *summary;
189
 
        gint local_data_search = 0, *prev_local_data_search, ii;
190
 
 
191
 
        if (argc != 1)
192
 
                return imapx_search_result_match_none (sexp, search);
193
 
 
194
 
        server = camel_imapx_search_ref_server (CAMEL_IMAPX_SEARCH (search));
195
 
        if (!server || search->current || !search->summary) {
196
 
                g_clear_object (&server);
197
 
 
198
 
                /* Chain up to parent's method. */
199
 
                return CAMEL_FOLDER_SEARCH_CLASS (camel_imapx_search_parent_class)->
200
 
                        match_all (sexp, argc, argv, search);
201
 
        }
202
 
 
203
 
        /* First try to see whether all used headers are available locally - if
204
 
           they are, then do not use server-side filtering at all. */
205
 
        prev_local_data_search = imapx_search->priv->local_data_search;
206
 
        imapx_search->priv->local_data_search = &local_data_search;
207
 
 
208
 
        summary = search->summary_set ? search->summary_set : search->summary;
209
 
 
210
 
        if (!CAMEL_IS_VEE_FOLDER (search->folder)) {
211
 
                camel_folder_summary_prepare_fetch_all (search->folder->summary, NULL);
212
 
        }
213
 
 
214
 
        for (ii = 0; ii < summary->len; ii++) {
215
 
                search->current = camel_folder_summary_get (search->folder->summary, summary->pdata[ii]);
216
 
                if (search->current) {
217
 
                        result = camel_sexp_term_eval (sexp, argv[0]);
218
 
                        camel_sexp_result_free (sexp, result);
219
 
                        camel_message_info_free (search->current);
220
 
                        search->current = NULL;
221
 
                        break;
222
 
                }
223
 
        }
224
 
        imapx_search->priv->local_data_search = prev_local_data_search;
225
 
 
226
 
        if (local_data_search >= 0) {
227
 
                g_clear_object (&server);
228
 
 
229
 
                /* Chain up to parent's method. */
230
 
                return CAMEL_FOLDER_SEARCH_CLASS (camel_imapx_search_parent_class)->
231
 
                        match_all (sexp, argc, argv, search);
232
 
        }
233
 
 
234
 
        /* let's change the requirements a bit, the parent class expects as a result boolean,
235
 
           but here is expected GPtrArray of matched UIDs */
236
 
        result = camel_sexp_term_eval (sexp, argv[0]);
237
 
 
238
 
        g_object_unref (server);
239
 
 
240
 
        g_return_val_if_fail (result != NULL, result);
241
 
        g_return_val_if_fail (result->type == CAMEL_SEXP_RES_ARRAY_PTR, result);
242
 
 
243
 
        return result;
244
 
}
245
 
 
246
 
static CamelSExpResult *
247
 
imapx_search_body_contains (CamelSExp *sexp,
248
 
                            gint argc,
249
 
                            CamelSExpResult **argv,
250
 
                            CamelFolderSearch *search)
251
 
{
252
 
        CamelIMAPXSearch *imapx_search = CAMEL_IMAPX_SEARCH (search);
253
 
        CamelIMAPXServer *server;
254
 
        CamelSExpResult *result;
255
 
        GString *criteria;
256
 
        gint ii, jj;
257
 
 
258
 
        /* Always do body-search server-side */
259
 
        if (imapx_search->priv->local_data_search) {
260
 
                *imapx_search->priv->local_data_search = -1;
261
 
                return imapx_search_result_match_none (sexp, search);
262
 
        }
263
 
 
264
 
        /* Match everything if argv = [""] */
265
 
        if (argc == 1 && argv[0]->value.string[0] == '\0')
266
 
                return imapx_search_result_match_all (sexp, search);
267
 
 
268
 
        /* Match nothing if empty argv or empty summary. */
269
 
        if (argc == 0 || search->summary->len == 0)
270
 
                return imapx_search_result_match_none (sexp, search);
271
 
 
272
 
        server = camel_imapx_search_ref_server (CAMEL_IMAPX_SEARCH (search));
273
 
 
274
 
        /* This will be NULL if we're offline.  Search from cache. */
275
 
        if (server == NULL) {
276
 
                /* Chain up to parent's method. */
277
 
                return CAMEL_FOLDER_SEARCH_CLASS (camel_imapx_search_parent_class)->
278
 
                        body_contains (sexp, argc, argv, search);
279
 
        }
280
 
 
281
 
        /* Build the IMAP search criteria. */
282
 
 
283
 
        criteria = g_string_sized_new (128);
284
 
 
285
 
        if (search->current != NULL) {
286
 
                const gchar *uid;
287
 
 
288
 
                /* Limit the search to a single UID. */
289
 
                uid = camel_message_info_uid (search->current);
290
 
                g_string_append_printf (criteria, "UID %s", uid);
291
 
        }
292
 
 
293
 
        for (ii = 0; ii < argc; ii++) {
294
 
                struct _camel_search_words *words;
295
 
                const guchar *term;
296
 
 
297
 
                if (argv[ii]->type != CAMEL_SEXP_RES_STRING)
298
 
                        continue;
299
 
 
300
 
                /* Handle multiple search words within a single term. */
301
 
                term = (const guchar *) argv[ii]->value.string;
302
 
                words = camel_search_words_split (term);
303
 
 
304
 
                for (jj = 0; jj < words->len; jj++) {
305
 
                        gchar *cp;
306
 
 
307
 
                        if (criteria->len > 0)
308
 
                                g_string_append_c (criteria, ' ');
309
 
 
310
 
                        g_string_append (criteria, "BODY \"");
311
 
 
312
 
                        cp = words->words[jj]->word;
313
 
                        for (; *cp != '\0'; cp++) {
314
 
                                if (*cp == '\\' || *cp == '"')
315
 
                                        g_string_append_c (criteria, '\\');
316
 
                                g_string_append_c (criteria, *cp);
317
 
                        }
318
 
 
319
 
                        g_string_append_c (criteria, '"');
320
 
                }
321
 
        }
322
 
 
323
 
        result = imapx_search_process_criteria (sexp, search, server, criteria, G_STRFUNC);
324
 
 
325
 
        g_string_free (criteria, TRUE);
326
 
        g_object_unref (server);
327
 
 
328
 
        return result;
329
 
}
330
 
 
331
 
static gboolean
332
 
imapx_search_is_header_from_summary (const gchar *header_name)
333
 
{
334
 
        return  g_ascii_strcasecmp (header_name, "From") == 0 ||
335
 
                g_ascii_strcasecmp (header_name, "To") == 0 ||
336
 
                g_ascii_strcasecmp (header_name, "CC") == 0 ||
337
 
                g_ascii_strcasecmp (header_name, "Subject") == 0;
338
 
}
339
 
 
340
 
static CamelSExpResult *
341
 
imapx_search_header_contains (CamelSExp *sexp,
342
 
                              gint argc,
343
 
                              CamelSExpResult **argv,
344
 
                              CamelFolderSearch *search)
345
 
{
346
 
        CamelIMAPXSearch *imapx_search = CAMEL_IMAPX_SEARCH (search);
347
 
        CamelIMAPXServer *server;
348
 
        CamelSExpResult *result;
349
 
        const gchar *headername, *command = NULL;
350
 
        GString *criteria;
351
 
        gint ii, jj;
352
 
 
353
 
        /* Match nothing if empty argv or empty summary. */
354
 
        if (argc <= 1 ||
355
 
            argv[0]->type != CAMEL_SEXP_RES_STRING ||
356
 
            search->summary->len == 0)
357
 
                return imapx_search_result_match_none (sexp, search);
358
 
 
359
 
        headername = argv[0]->value.string;
360
 
 
361
 
        if (imapx_search_is_header_from_summary (headername)) {
362
 
                if (imapx_search->priv->local_data_search) {
363
 
                        if (*imapx_search->priv->local_data_search >= 0)
364
 
                                *imapx_search->priv->local_data_search = (*imapx_search->priv->local_data_search) + 1;
365
 
                        return imapx_search_result_match_all (sexp, search);
366
 
                }
367
 
 
368
 
                /* Chain up to parent's method. */
369
 
                return CAMEL_FOLDER_SEARCH_CLASS (camel_imapx_search_parent_class)->
370
 
                        header_contains (sexp, argc, argv, search);
371
 
        } else if (imapx_search->priv->local_data_search) {
372
 
                *imapx_search->priv->local_data_search = -1;
373
 
                return imapx_search_result_match_none (sexp, search);
374
 
        }
375
 
 
376
 
        server = camel_imapx_search_ref_server (CAMEL_IMAPX_SEARCH (search));
377
 
 
378
 
        /* This will be NULL if we're offline.  Search from cache. */
379
 
        if (server == NULL) {
380
 
                /* Chain up to parent's method. */
381
 
                return CAMEL_FOLDER_SEARCH_CLASS (camel_imapx_search_parent_class)->
382
 
                        header_contains (sexp, argc, argv, search);
383
 
        }
384
 
 
385
 
        /* Build the IMAP search criteria. */
386
 
 
387
 
        criteria = g_string_sized_new (128);
388
 
 
389
 
        if (search->current != NULL) {
390
 
                const gchar *uid;
391
 
 
392
 
                /* Limit the search to a single UID. */
393
 
                uid = camel_message_info_uid (search->current);
394
 
                g_string_append_printf (criteria, "UID %s", uid);
395
 
        }
396
 
 
397
 
        if (g_ascii_strcasecmp (headername, "From") == 0)
398
 
                command = "FROM";
399
 
        else if (g_ascii_strcasecmp (headername, "To") == 0)
400
 
                command = "TO";
401
 
        else if (g_ascii_strcasecmp (headername, "CC") == 0)
402
 
                command = "CC";
403
 
        else if (g_ascii_strcasecmp (headername, "Bcc") == 0)
404
 
                command = "BCC";
405
 
        else if (g_ascii_strcasecmp (headername, "Subject") == 0)
406
 
                command = "SUBJECT";
407
 
 
408
 
        for (ii = 1; ii < argc; ii++) {
409
 
                struct _camel_search_words *words;
410
 
                const guchar *term;
411
 
 
412
 
                if (argv[ii]->type != CAMEL_SEXP_RES_STRING)
413
 
                        continue;
414
 
 
415
 
                /* Handle multiple search words within a single term. */
416
 
                term = (const guchar *) argv[ii]->value.string;
417
 
                words = camel_search_words_split (term);
418
 
 
419
 
                for (jj = 0; jj < words->len; jj++) {
420
 
                        gchar *cp;
421
 
 
422
 
                        if (criteria->len > 0)
423
 
                                g_string_append_c (criteria, ' ');
424
 
 
425
 
                        if (command)
426
 
                                g_string_append (criteria, command);
427
 
                        else
428
 
                                g_string_append_printf (criteria, "HEADER \"%s\"", headername);
429
 
 
430
 
                        g_string_append (criteria, " \"");
431
 
 
432
 
                        cp = words->words[jj]->word;
433
 
                        for (; *cp != '\0'; cp++) {
434
 
                                if (*cp == '\\' || *cp == '"')
435
 
                                        g_string_append_c (criteria, '\\');
436
 
                                g_string_append_c (criteria, *cp);
437
 
                        }
438
 
 
439
 
                        g_string_append_c (criteria, '"');
440
 
                }
441
 
        }
442
 
 
443
 
        result = imapx_search_process_criteria (sexp, search, server, criteria, G_STRFUNC);
444
 
 
445
 
        g_string_free (criteria, TRUE);
446
 
        g_object_unref (server);
447
 
 
448
 
        return result;
449
 
}
450
 
 
451
 
static CamelSExpResult *
452
 
imapx_search_header_exists (CamelSExp *sexp,
453
 
                            gint argc,
454
 
                            CamelSExpResult **argv,
455
 
                            CamelFolderSearch *search)
456
 
{
457
 
        CamelIMAPXSearch *imapx_search = CAMEL_IMAPX_SEARCH (search);
458
 
        CamelIMAPXServer *server;
459
 
        CamelSExpResult *result;
460
 
        GString *criteria;
461
 
        gint ii;
462
 
 
463
 
        /* Match nothing if empty argv or empty summary. */
464
 
        if (argc == 0 || search->summary->len == 0)
465
 
                return imapx_search_result_match_none (sexp, search);
466
 
 
467
 
        /* Check if asking for locally stored headers only */
468
 
        for (ii = 0; ii < argc; ii++) {
469
 
                if (argv[ii]->type != CAMEL_SEXP_RES_STRING)
470
 
                        continue;
471
 
 
472
 
                if (!imapx_search_is_header_from_summary (argv[ii]->value.string))
473
 
                        break;
474
 
        }
475
 
 
476
 
        /* All headers are from summary */
477
 
        if (ii == argc) {
478
 
                if (imapx_search->priv->local_data_search) {
479
 
                        if (*imapx_search->priv->local_data_search >= 0)
480
 
                                *imapx_search->priv->local_data_search = (*imapx_search->priv->local_data_search) + 1;
481
 
 
482
 
                        return imapx_search_result_match_all (sexp, search);
483
 
                }
484
 
 
485
 
                /* Chain up to parent's method. */
486
 
                return CAMEL_FOLDER_SEARCH_CLASS (camel_imapx_search_parent_class)->
487
 
                        header_exists (sexp, argc, argv, search);
488
 
        } else if (imapx_search->priv->local_data_search) {
489
 
                *imapx_search->priv->local_data_search = -1;
490
 
                return imapx_search_result_match_none (sexp, search);
491
 
        }
492
 
 
493
 
        server = camel_imapx_search_ref_server (CAMEL_IMAPX_SEARCH (search));
494
 
 
495
 
        /* This will be NULL if we're offline.  Search from cache. */
496
 
        if (server == NULL) {
497
 
                /* Chain up to parent's method. */
498
 
                return CAMEL_FOLDER_SEARCH_CLASS (camel_imapx_search_parent_class)->
499
 
                        header_exists (sexp, argc, argv, search);
500
 
        }
501
 
 
502
 
        /* Build the IMAP search criteria. */
503
 
 
504
 
        criteria = g_string_sized_new (128);
505
 
 
506
 
        if (search->current != NULL) {
507
 
                const gchar *uid;
508
 
 
509
 
                /* Limit the search to a single UID. */
510
 
                uid = camel_message_info_uid (search->current);
511
 
                g_string_append_printf (criteria, "UID %s", uid);
512
 
        }
513
 
 
514
 
        for (ii = 0; ii < argc; ii++) {
515
 
                const gchar *headername;
516
 
 
517
 
                if (argv[ii]->type != CAMEL_SEXP_RES_STRING)
518
 
                        continue;
519
 
 
520
 
                headername = argv[ii]->value.string;
521
 
 
522
 
                if (criteria->len > 0)
523
 
                        g_string_append_c (criteria, ' ');
524
 
 
525
 
                g_string_append_printf (criteria, "HEADER \"%s\" \"\"", headername);
526
 
        }
527
 
 
528
 
        result = imapx_search_process_criteria (sexp, search, server, criteria, G_STRFUNC);
529
 
 
530
 
        g_string_free (criteria, TRUE);
531
 
        g_object_unref (server);
532
 
 
533
 
        return result;
534
 
}
535
 
 
536
 
static void
537
 
camel_imapx_search_class_init (CamelIMAPXSearchClass *class)
538
 
{
539
 
        GObjectClass *object_class;
540
 
        CamelFolderSearchClass *search_class;
541
 
 
542
 
        g_type_class_add_private (class, sizeof (CamelIMAPXSearchPrivate));
543
 
 
544
 
        object_class = G_OBJECT_CLASS (class);
545
 
        object_class->set_property = imapx_search_set_property;
546
 
        object_class->get_property = imapx_search_get_property;
547
 
        object_class->dispose = imapx_search_dispose;
548
 
 
549
 
        search_class = CAMEL_FOLDER_SEARCH_CLASS (class);
550
 
        search_class->match_all = imapx_search_match_all;
551
 
        search_class->body_contains = imapx_search_body_contains;
552
 
        search_class->header_contains = imapx_search_header_contains;
553
 
        search_class->header_exists = imapx_search_header_exists;
554
 
 
555
 
        g_object_class_install_property (
556
 
                object_class,
557
 
                PROP_SERVER,
558
 
                g_param_spec_object (
559
 
                        "server",
560
 
                        "Server",
561
 
                        "Server proxy for server-side searches",
562
 
                        CAMEL_TYPE_IMAPX_SERVER,
563
 
                        G_PARAM_READWRITE |
564
 
                        G_PARAM_STATIC_STRINGS));
565
 
}
566
 
 
567
 
static void
568
 
camel_imapx_search_init (CamelIMAPXSearch *search)
569
 
{
570
 
        search->priv = CAMEL_IMAPX_SEARCH_GET_PRIVATE (search);
571
 
        search->priv->local_data_search = NULL;
572
 
}
573
 
 
574
 
/**
575
 
 * camel_imapx_search_new:
576
 
 *
577
 
 * Returns a new #CamelIMAPXSearch instance.
578
 
 *
579
 
 * The #CamelIMAPXSearch must be given a #CamelIMAPXSearch:server before
580
 
 * it can issue server-side search requests.  Otherwise it will fallback
581
 
 * to the default #CamelFolderSearch behavior.
582
 
 *
583
 
 * Returns: a new #CamelIMAPXSearch
584
 
 *
585
 
 * Since: 3.8
586
 
 **/
587
 
CamelFolderSearch *
588
 
camel_imapx_search_new (void)
589
 
{
590
 
        return g_object_new (CAMEL_TYPE_IMAPX_SEARCH, NULL);
591
 
}
592
 
 
593
 
/**
594
 
 * camel_imapx_search_ref_server:
595
 
 * @search: a #CamelIMAPXSearch
596
 
 *
597
 
 * Returns a #CamelIMAPXServer to use for server-side searches,
598
 
 * or %NULL when the corresponding #CamelIMAPXStore is offline.
599
 
 *
600
 
 * The returned #CamelIMAPXSearch is referenced for thread-safety and
601
 
 * must be unreferenced with g_object_unref() when finished with it.
602
 
 *
603
 
 * Returns: a #CamelIMAPXServer, or %NULL
604
 
 *
605
 
 * Since: 3.8
606
 
 **/
607
 
CamelIMAPXServer *
608
 
camel_imapx_search_ref_server (CamelIMAPXSearch *search)
609
 
{
610
 
        g_return_val_if_fail (CAMEL_IS_IMAPX_SEARCH (search), NULL);
611
 
 
612
 
        return g_weak_ref_get (&search->priv->server);
613
 
}
614
 
 
615
 
/**
616
 
 * camel_imapx_search_set_server:
617
 
 * @search: a #CamelIMAPXSearch
618
 
 * @server: a #CamelIMAPXServer, or %NULL
619
 
 *
620
 
 * Sets a #CamelIMAPXServer to use for server-side searches.  Generally
621
 
 * this is set for the duration of a single search when online, and then
622
 
 * reset to %NULL.
623
 
 *
624
 
 * Since: 3.8
625
 
 **/
626
 
void
627
 
camel_imapx_search_set_server (CamelIMAPXSearch *search,
628
 
                               CamelIMAPXServer *server)
629
 
{
630
 
        g_return_if_fail (CAMEL_IS_IMAPX_SEARCH (search));
631
 
 
632
 
        if (server != NULL)
633
 
                g_return_if_fail (CAMEL_IS_IMAPX_SERVER (server));
634
 
 
635
 
        g_weak_ref_set (&search->priv->server, server);
636
 
 
637
 
        g_object_notify (G_OBJECT (search), "server");
638
 
}
639