~ubuntu-branches/ubuntu/saucy/evolution-data-server/saucy

« back to all changes in this revision

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

  • Committer: Package Import Robot
  • Author(s): Chris Coulson
  • Date: 2012-10-08 12:58:16 UTC
  • mfrom: (181.1.7 quantal)
  • Revision ID: package-import@ubuntu.com-20121008125816-i3n76e8c0m64e7xp
Tags: 3.6.0-0ubuntu2
* Fix LP: #1038047 part 1 - Don't abort in e_source_registry_new* when a
  problem occurs connecting to the Dbus service
  - add debian/patches/dont-abort-in-e_source_registry_new.patch
  - update debian/patches/series
* Fix LP: #1038047 part 2 - libedataserver depends on
  evolution-data-server-common to ensure that the GSettings schemas are
  present
  - update debian/control

Show diffs side-by-side

added added

removed removed

Lines of Context:
36
36
#include "camel-imapx-utils.h"
37
37
#include "camel-imapx-stream.h"
38
38
 
 
39
#define CAMEL_IMAPX_STREAM_GET_PRIVATE(obj) \
 
40
        (G_TYPE_INSTANCE_GET_PRIVATE \
 
41
        ((obj), CAMEL_TYPE_IMAPX_STREAM, CamelIMAPXStreamPrivate))
 
42
 
39
43
#define t(...) camel_imapx_debug(token, __VA_ARGS__)
40
44
#define io(...) camel_imapx_debug(io, __VA_ARGS__)
41
45
 
 
46
struct _CamelIMAPXStreamPrivate {
 
47
        CamelStream *source;
 
48
 
 
49
        guchar *buf, *ptr, *end;
 
50
        guint literal;
 
51
 
 
52
        guint unget;
 
53
        camel_imapx_token_t unget_tok;
 
54
        guchar *unget_token;
 
55
        guint unget_len;
 
56
 
 
57
        guchar *tokenbuf;
 
58
        guint bufsize;
 
59
};
 
60
 
 
61
enum {
 
62
        PROP_0,
 
63
        PROP_SOURCE
 
64
};
 
65
 
42
66
G_DEFINE_TYPE (CamelIMAPXStream, camel_imapx_stream, CAMEL_TYPE_STREAM)
43
67
 
44
68
static gint
48
72
{
49
73
        gint left = 0;
50
74
 
51
 
        if (is->source) {
52
 
                left = is->end - is->ptr;
53
 
                memcpy (is->buf, is->ptr, left);
54
 
                is->end = is->buf + left;
55
 
                is->ptr = is->buf;
 
75
        if (is->priv->source != NULL) {
 
76
                left = is->priv->end - is->priv->ptr;
 
77
                memcpy (is->priv->buf, is->priv->ptr, left);
 
78
                is->priv->end = is->priv->buf + left;
 
79
                is->priv->ptr = is->priv->buf;
56
80
                left = camel_stream_read (
57
 
                        is->source, (gchar *) is->end,
58
 
                        is->bufsize - (is->end - is->buf),
 
81
                        is->priv->source,
 
82
                        (gchar *) is->priv->end,
 
83
                        is->priv->bufsize - (is->priv->end - is->priv->buf),
59
84
                        cancellable, error);
60
85
                if (left > 0) {
61
 
                        is->end += left;
62
 
                        io(is->tagprefix, "camel_imapx_read: buffer is '%.*s'\n", (gint)(is->end - is->ptr), is->ptr);
63
 
                        return is->end - is->ptr;
 
86
                        is->priv->end += left;
 
87
                        io (is->tagprefix, "camel_imapx_read: buffer is '%.*s'\n", (gint)(is->priv->end - is->priv->ptr), is->priv->ptr);
 
88
                        return is->priv->end - is->priv->ptr;
64
89
                } else {
65
 
                        io(is->tagprefix, "camel_imapx_read: -1\n");
 
90
                        io (is->tagprefix, "camel_imapx_read: -1\n");
66
91
                        /* If returning zero, camel_stream_read() doesn't consider
67
92
                         * that to be an error. But we do -- we should only be here
68
93
                         * if we *know* there are data to receive. So set the error
74
99
                }
75
100
        }
76
101
 
77
 
        io(is->tagprefix, "camel_imapx_read: -1\n");
 
102
        io (is->tagprefix, "camel_imapx_read: -1\n");
78
103
 
79
104
        g_set_error (
80
105
                error, CAMEL_ERROR, CAMEL_ERROR_GENERIC,
84
109
}
85
110
 
86
111
static void
 
112
imapx_stream_set_source (CamelIMAPXStream *stream,
 
113
                         CamelStream *source)
 
114
{
 
115
        g_return_if_fail (CAMEL_IS_STREAM (source));
 
116
        g_return_if_fail (stream->priv->source == NULL);
 
117
 
 
118
        stream->priv->source = g_object_ref (source);
 
119
}
 
120
 
 
121
static void
 
122
imapx_stream_set_property (GObject *object,
 
123
                           guint property_id,
 
124
                           const GValue *value,
 
125
                           GParamSpec *pspec)
 
126
{
 
127
        switch (property_id) {
 
128
                case PROP_SOURCE:
 
129
                        imapx_stream_set_source (
 
130
                                CAMEL_IMAPX_STREAM (object),
 
131
                                g_value_get_object (value));
 
132
                        return;
 
133
        }
 
134
 
 
135
        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
 
136
}
 
137
 
 
138
static void
 
139
imapx_stream_get_property (GObject *object,
 
140
                           guint property_id,
 
141
                           GValue *value,
 
142
                           GParamSpec *pspec)
 
143
{
 
144
        switch (property_id) {
 
145
                case PROP_SOURCE:
 
146
                        g_value_take_object (
 
147
                                value,
 
148
                                camel_imapx_stream_ref_source (
 
149
                                CAMEL_IMAPX_STREAM (object)));
 
150
                        return;
 
151
        }
 
152
 
 
153
        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
 
154
}
 
155
 
 
156
static void
87
157
imapx_stream_dispose (GObject *object)
88
158
{
89
159
        CamelIMAPXStream *stream = CAMEL_IMAPX_STREAM (object);
90
160
 
91
 
        if (stream->source != NULL) {
92
 
                g_object_unref (stream->source);
93
 
                stream->source = NULL;
 
161
        if (stream->priv->source != NULL) {
 
162
                g_object_unref (stream->priv->source);
 
163
                stream->priv->source = NULL;
94
164
        }
95
165
 
96
166
        /* Chain up to parent's dispose() method. */
102
172
{
103
173
        CamelIMAPXStream *stream = CAMEL_IMAPX_STREAM (object);
104
174
 
105
 
        g_free (stream->buf);
106
 
        g_free (stream->tokenbuf);
 
175
        g_free (stream->priv->buf);
 
176
        g_free (stream->priv->tokenbuf);
107
177
 
108
178
        /* Chain up to parent's finalize() method. */
109
179
        G_OBJECT_CLASS (camel_imapx_stream_parent_class)->finalize (object);
119
189
        CamelIMAPXStream *is = (CamelIMAPXStream *) stream;
120
190
        gssize max;
121
191
 
122
 
        if (is->literal == 0 || n == 0)
 
192
        if (is->priv->literal == 0 || n == 0)
123
193
                return 0;
124
194
 
125
 
        max = is->end - is->ptr;
 
195
        max = is->priv->end - is->priv->ptr;
126
196
        if (max > 0) {
127
 
                max = MIN (max, is->literal);
 
197
                max = MIN (max, is->priv->literal);
128
198
                max = MIN (max, n);
129
 
                memcpy (buffer, is->ptr, max);
130
 
                is->ptr += max;
 
199
                memcpy (buffer, is->priv->ptr, max);
 
200
                is->priv->ptr += max;
131
201
        } else {
132
 
                max = MIN (is->literal, n);
133
 
                max = camel_stream_read (is->source, buffer, max, cancellable, error);
 
202
                max = MIN (is->priv->literal, n);
 
203
                max = camel_stream_read (
 
204
                        is->priv->source,
 
205
                        buffer, max, cancellable, error);
134
206
                if (max <= 0)
135
207
                        return max;
136
208
        }
137
209
 
138
 
        io(is->tagprefix, "camel_imapx_read(literal): '%.*s'\n", (gint)max, buffer);
 
210
        io (is->tagprefix, "camel_imapx_read(literal): '%.*s'\n", (gint) max, buffer);
139
211
 
140
 
        is->literal -= max;
 
212
        is->priv->literal -= max;
141
213
 
142
214
        return max;
143
215
}
152
224
        CamelIMAPXStream *is = (CamelIMAPXStream *) stream;
153
225
 
154
226
        if (g_strstr_len (buffer, n, "LOGIN")) {
155
 
                io(is->tagprefix, "camel_imapx_write: 'LOGIN...'\n");
 
227
                io (is->tagprefix, "camel_imapx_write: 'LOGIN...'\n");
156
228
        } else {
157
 
                io(is->tagprefix, "camel_imapx_write: '%.*s'\n", (gint)n, buffer);
 
229
                io (is->tagprefix, "camel_imapx_write: '%.*s'\n", (gint) n, buffer);
158
230
        }
159
231
 
160
 
        return camel_stream_write (is->source, buffer, n, cancellable, error);
 
232
        return camel_stream_write (
 
233
                is->priv->source,
 
234
                buffer, n, cancellable, error);
161
235
}
162
236
 
163
237
static gint
165
239
                    GCancellable *cancellable,
166
240
                    GError **error)
167
241
{
168
 
        /* nop? */
169
 
        return 0;
 
242
        CamelIMAPXStream *is = (CamelIMAPXStream *) stream;
 
243
 
 
244
        return camel_stream_close (is->priv->source, cancellable, error);
170
245
}
171
246
 
172
247
static gint
183
258
{
184
259
        CamelIMAPXStream *is = (CamelIMAPXStream *) stream;
185
260
 
186
 
        return is->literal == 0;
 
261
        return is->priv->literal == 0;
187
262
}
188
263
 
189
264
static void
192
267
        GObjectClass *object_class;
193
268
        CamelStreamClass *stream_class;
194
269
 
 
270
        g_type_class_add_private (class, sizeof (CamelIMAPXStreamPrivate));
 
271
 
195
272
        object_class = G_OBJECT_CLASS (class);
 
273
        object_class->set_property = imapx_stream_set_property;
 
274
        object_class->get_property = imapx_stream_get_property;
196
275
        object_class->dispose = imapx_stream_dispose;
197
276
        object_class->finalize = imapx_stream_finalize;
198
277
 
202
281
        stream_class->close = imapx_stream_close;
203
282
        stream_class->flush = imapx_stream_flush;
204
283
        stream_class->eos = imapx_stream_eos;
 
284
 
 
285
        g_object_class_install_property (
 
286
                object_class,
 
287
                PROP_SOURCE,
 
288
                g_param_spec_object (
 
289
                        "source",
 
290
                        "Source",
 
291
                        "Source stream",
 
292
                        CAMEL_TYPE_STREAM,
 
293
                        G_PARAM_READWRITE |
 
294
                        G_PARAM_CONSTRUCT_ONLY |
 
295
                        G_PARAM_STATIC_STRINGS));
205
296
}
206
297
 
207
298
static void
208
299
camel_imapx_stream_init (CamelIMAPXStream *is)
209
300
{
 
301
        is->priv = CAMEL_IMAPX_STREAM_GET_PRIVATE (is);
 
302
 
210
303
        /* +1 is room for appending a 0 if we need to for a token */
211
 
        is->bufsize = 4096;
212
 
        is->ptr = is->end = is->buf = g_malloc (is->bufsize + 1);
213
 
        is->tokenbuf = g_malloc (is->bufsize + 1);
 
304
        is->priv->bufsize = 4096;
 
305
        is->priv->buf = g_malloc (is->priv->bufsize + 1);
 
306
        is->priv->ptr = is->priv->end = is->priv->buf;
 
307
        is->priv->tokenbuf = g_malloc (is->priv->bufsize + 1);
214
308
}
215
309
 
216
 
static void camel_imapx_stream_grow (CamelIMAPXStream *is, guint len, guchar **bufptr, guchar **tokptr)
 
310
static void
 
311
camel_imapx_stream_grow (CamelIMAPXStream *is,
 
312
                         guint len,
 
313
                         guchar **bufptr,
 
314
                         guchar **tokptr)
217
315
{
218
 
        guchar *oldtok = is->tokenbuf;
219
 
        guchar *oldbuf = is->buf;
 
316
        guchar *oldtok = is->priv->tokenbuf;
 
317
        guchar *oldbuf = is->priv->buf;
220
318
 
221
319
        do {
222
 
                is->bufsize <<= 1;
223
 
        } while (is->bufsize <= len);
224
 
 
225
 
        io(is->tagprefix, "Grow imapx buffers to %d bytes\n", is->bufsize);
226
 
 
227
 
        is->tokenbuf = g_realloc (is->tokenbuf, is->bufsize + 1);
 
320
                is->priv->bufsize <<= 1;
 
321
        } while (is->priv->bufsize <= len);
 
322
 
 
323
        io (is->tagprefix, "Grow imapx buffers to %d bytes\n", is->priv->bufsize);
 
324
 
 
325
        is->priv->tokenbuf = g_realloc (
 
326
                is->priv->tokenbuf,
 
327
                is->priv->bufsize + 1);
228
328
        if (tokptr)
229
 
                *tokptr = is->tokenbuf + (*tokptr - oldtok);
230
 
        if (is->unget)
231
 
                is->unget_token = is->tokenbuf + (is->unget_token - oldtok);
 
329
                *tokptr = is->priv->tokenbuf + (*tokptr - oldtok);
 
330
        if (is->priv->unget)
 
331
                is->priv->unget_token =
 
332
                        is->priv->tokenbuf +
 
333
                        (is->priv->unget_token - oldtok);
232
334
 
233
 
        //io(is->tagprefix, "buf was %p, ptr %p end %p\n", is->buf, is->ptr, is->end);
234
 
        is->buf = g_realloc (is->buf, is->bufsize + 1);
235
 
        is->ptr = is->buf + (is->ptr - oldbuf);
236
 
        is->end = is->buf + (is->end - oldbuf);
237
 
        //io(is->tagprefix, "buf now %p, ptr %p end %p\n", is->buf, is->ptr, is->end);
 
335
        is->priv->buf = g_realloc (is->priv->buf, is->priv->bufsize + 1);
 
336
        is->priv->ptr = is->priv->buf + (is->priv->ptr - oldbuf);
 
337
        is->priv->end = is->priv->buf + (is->priv->end - oldbuf);
238
338
        if (bufptr)
239
 
                *bufptr = is->buf + (*bufptr - oldbuf);
 
339
                *bufptr = is->priv->buf + (*bufptr - oldbuf);
 
340
}
 
341
 
 
342
GQuark
 
343
camel_imapx_error_quark (void)
 
344
{
 
345
        static GQuark quark = 0;
 
346
 
 
347
        if (G_UNLIKELY (quark == 0)) {
 
348
                const gchar *string = "camel-imapx-error-quark";
 
349
                quark = g_quark_from_static_string (string);
 
350
        }
 
351
 
 
352
        return quark;
240
353
}
241
354
 
242
355
/**
250
363
CamelStream *
251
364
camel_imapx_stream_new (CamelStream *source)
252
365
{
253
 
        CamelIMAPXStream *is;
254
 
 
255
 
        is = g_object_new (CAMEL_TYPE_IMAPX_STREAM, NULL);
256
 
        is->source = g_object_ref (source);
257
 
 
258
 
        return (CamelStream *) is;
 
366
        g_return_val_if_fail (CAMEL_IS_STREAM (source), NULL);
 
367
 
 
368
        return g_object_new (
 
369
                CAMEL_TYPE_IMAPX_STREAM,
 
370
                "source", source, NULL);
259
371
}
260
372
 
261
 
GQuark
262
 
camel_imapx_error_quark (void)
 
373
CamelStream *
 
374
camel_imapx_stream_ref_source (CamelIMAPXStream *is)
263
375
{
264
 
        static GQuark quark = 0;
265
 
 
266
 
        if (G_UNLIKELY (quark == 0)) {
267
 
                const gchar *string = "camel-imapx-error-quark";
268
 
                quark = g_quark_from_static_string (string);
269
 
        }
270
 
 
271
 
        return quark;
 
376
        g_return_val_if_fail (CAMEL_IS_IMAPX_STREAM (is), NULL);
 
377
 
 
378
        return g_object_ref (is->priv->source);
272
379
}
273
380
 
274
381
/* Returns if there is any data buffered that is ready for processing */
275
382
gint
276
383
camel_imapx_stream_buffered (CamelIMAPXStream *is)
277
384
{
278
 
        return is->end - is->ptr;
279
 
}
280
 
 
281
 
#if 0
282
 
 
283
 
static gint
284
 
skip_ws (CamelIMAPXStream *is,
285
 
         guchar *pp,
286
 
         guchar *pe)
287
 
{
288
 
        register guchar c, *p;
289
 
        guchar *e;
290
 
 
291
 
        p = is->ptr;
292
 
        e = is->end;
293
 
 
294
 
        do {
295
 
                while (p >= e ) {
296
 
                        is->ptr = p;
297
 
                        if (imapx_stream_fill (is, NULL) == IMAPX_TOK_ERROR)
298
 
                                return IMAPX_TOK_ERROR;
299
 
                        p = is->ptr;
300
 
                        e = is->end;
301
 
                }
302
 
                c = *p++;
303
 
        } while (c == ' ' || c == '\r');
304
 
 
305
 
        is->ptr = p;
306
 
        is->end = e;
307
 
 
308
 
        return c;
309
 
}
310
 
#endif
 
385
        g_return_val_if_fail (CAMEL_IS_IMAPX_STREAM (is), 0);
 
386
 
 
387
        return is->priv->end - is->priv->ptr;
 
388
}
311
389
 
312
390
/* FIXME: these should probably handle it themselves,
313
391
 * and get rid of the token interface? */
321
399
        guchar *p, c;
322
400
        GError *local_error = NULL;
323
401
 
 
402
        g_return_val_if_fail (CAMEL_IS_IMAPX_STREAM (is), IMAPX_TOK_ERROR);
 
403
        g_return_val_if_fail (data != NULL, IMAPX_TOK_ERROR);
 
404
        g_return_val_if_fail (lenp != NULL, IMAPX_TOK_ERROR);
 
405
 
324
406
        /* this is only 'approximate' atom */
325
407
        switch (camel_imapx_stream_token (is, data, lenp, cancellable, &local_error)) {
326
408
        case IMAPX_TOK_TOKEN:
338
420
                        g_set_error (error, CAMEL_IMAPX_ERROR, 1, "expecting atom");
339
421
                else
340
422
                        g_propagate_error (error, local_error);
341
 
                io(is->tagprefix, "expecting atom!\n");
 
423
                io (is->tagprefix, "expecting atom!\n");
342
424
                return IMAPX_TOK_PROTOCOL;
343
425
        }
344
426
}
355
437
        gint ret;
356
438
        GError *local_error = NULL;
357
439
 
 
440
        g_return_val_if_fail (CAMEL_IMAPX_STREAM (is), IMAPX_TOK_ERROR);
 
441
        g_return_val_if_fail (data != NULL, IMAPX_TOK_ERROR);
 
442
 
358
443
        switch (camel_imapx_stream_token (is, data, &len, cancellable, &local_error)) {
359
444
        case IMAPX_TOK_TOKEN:
360
445
        case IMAPX_TOK_INT:
361
446
        case IMAPX_TOK_STRING:
362
447
                return 0;
363
448
        case IMAPX_TOK_LITERAL:
364
 
                if (len >= is->bufsize)
 
449
                if (len >= is->priv->bufsize)
365
450
                        camel_imapx_stream_grow (is, len, NULL, NULL);
366
 
                p = is->tokenbuf;
 
451
                p = is->priv->tokenbuf;
367
452
                camel_imapx_stream_set_literal (is, len);
368
453
                do {
369
454
                        ret = camel_imapx_stream_getl (is, &start, &inlen, cancellable, error);
373
458
                        p += inlen;
374
459
                } while (ret > 0);
375
460
                *p = 0;
376
 
                *data = is->tokenbuf;
 
461
                *data = is->priv->tokenbuf;
377
462
                return 0;
378
463
        case IMAPX_TOK_ERROR:
379
464
                /* wont get unless no exception hanlder*/
385
470
                        g_set_error (error, CAMEL_IMAPX_ERROR, 1, "expecting astring");
386
471
                else
387
472
                        g_propagate_error (error, local_error);
388
 
                io(is->tagprefix, "expecting astring!\n");
 
473
                io (is->tagprefix, "expecting astring!\n");
389
474
                return IMAPX_TOK_PROTOCOL;
390
475
        }
391
476
}
402
487
        gint ret;
403
488
        GError *local_error = NULL;
404
489
 
 
490
        g_return_val_if_fail (CAMEL_IS_IMAPX_STREAM (is), IMAPX_TOK_ERROR);
 
491
        g_return_val_if_fail (data != NULL, IMAPX_TOK_ERROR);
 
492
 
405
493
        switch (camel_imapx_stream_token (is, data, &len, cancellable, &local_error)) {
406
494
        case IMAPX_TOK_STRING:
407
495
                return 0;
408
496
        case IMAPX_TOK_LITERAL:
409
 
                if (len >= is->bufsize)
 
497
                if (len >= is->priv->bufsize)
410
498
                        camel_imapx_stream_grow (is, len, NULL, NULL);
411
 
                p = is->tokenbuf;
 
499
                p = is->priv->tokenbuf;
412
500
                camel_imapx_stream_set_literal (is, len);
413
501
                do {
414
502
                        ret = camel_imapx_stream_getl (is, &start, &inlen, cancellable, error);
418
506
                        p += inlen;
419
507
                } while (ret > 0);
420
508
                *p = 0;
421
 
                *data = is->tokenbuf;
 
509
                *data = is->priv->tokenbuf;
422
510
                return 0;
423
511
        case IMAPX_TOK_TOKEN:
424
512
                p = *data;
447
535
                                   CamelStream **stream,
448
536
                                   GCancellable *cancellable,
449
537
                                   GError **error)
450
 
/* throws IO,PARSE exception */
451
538
{
452
539
        guchar *token;
453
540
        guint len;
455
542
        CamelStream * mem = NULL;
456
543
        GError *local_error = NULL;
457
544
 
 
545
        g_return_val_if_fail (CAMEL_IS_IMAPX_STREAM (is), -1);
 
546
        g_return_val_if_fail (stream != NULL, -1);
 
547
 
458
548
        *stream = NULL;
459
549
 
460
550
        switch (camel_imapx_stream_token (is, &token, &len, cancellable, &local_error)) {
503
593
        guint len;
504
594
        GError *local_error = NULL;
505
595
 
 
596
        g_return_val_if_fail (CAMEL_IS_IMAPX_STREAM (is), 0);
 
597
 
506
598
        if (camel_imapx_stream_token (is, &token, &len, cancellable, &local_error) != IMAPX_TOK_INT) {
507
599
                if (local_error == NULL)
508
600
                        g_set_error (error, CAMEL_IMAPX_ERROR, 1, "expecting number");
525
617
        guint len;
526
618
        gint tok;
527
619
 
528
 
        while (is->unget > 0) {
529
 
                switch (is->unget_tok) {
 
620
        g_return_val_if_fail (CAMEL_IS_IMAPX_STREAM (is), -1);
 
621
        g_return_val_if_fail (text != NULL, -1);
 
622
 
 
623
        while (is->priv->unget > 0) {
 
624
                switch (is->priv->unget_tok) {
530
625
                        case IMAPX_TOK_TOKEN:
531
626
                        case IMAPX_TOK_STRING:
532
627
                        case IMAPX_TOK_INT:
533
 
                                g_byte_array_append (build, (guint8 *) is->unget_token, is->unget_len);
534
 
                                g_byte_array_append(build, (guint8 *) " ", 1);
 
628
                                g_byte_array_append (
 
629
                                        build, (guint8 *)
 
630
                                        is->priv->unget_token,
 
631
                                        is->priv->unget_len);
 
632
                                g_byte_array_append (
 
633
                                        build, (guint8 *) " ", 1);
535
634
                        default: /* invalid, but we'll ignore */
536
635
                                break;
537
636
                }
538
 
                is->unget--;
 
637
                is->priv->unget--;
539
638
        }
540
639
 
541
640
        do {
549
648
                        g_byte_array_append (build, token, len);
550
649
        } while (tok > 0);
551
650
 
552
 
        g_byte_array_append(build, (guint8 *) "", 1);
 
651
        g_byte_array_append (build, (guint8 *) "", 1);
553
652
        *text = build->data;
554
653
        g_byte_array_free (build, FALSE);
555
654
 
558
657
 
559
658
/* Get one token from the imap stream */
560
659
camel_imapx_token_t
561
 
/* throws IO,PARSE exception */
562
660
camel_imapx_stream_token (CamelIMAPXStream *is,
563
661
                          guchar **data,
564
662
                          guint *len,
570
668
        guint literal;
571
669
        gint digits;
572
670
 
573
 
        if (is->unget > 0) {
574
 
                is->unget--;
575
 
                *data = is->unget_token;
576
 
                *len = is->unget_len;
577
 
                /*printf("token UNGET '%c' %s\n", is->unget_tok, is->unget_token);*/
578
 
                return is->unget_tok;
 
671
        g_return_val_if_fail (CAMEL_IS_IMAPX_STREAM (is), IMAPX_TOK_ERROR);
 
672
        g_return_val_if_fail (data != NULL, IMAPX_TOK_ERROR);
 
673
        g_return_val_if_fail (len != NULL, IMAPX_TOK_ERROR);
 
674
 
 
675
        if (is->priv->unget > 0) {
 
676
                is->priv->unget--;
 
677
                *data = is->priv->unget_token;
 
678
                *len = is->priv->unget_len;
 
679
                return is->priv->unget_tok;
579
680
        }
580
681
 
581
 
        if (is->literal > 0)
582
 
                g_warning("stream_token called with literal %d", is->literal);
 
682
        if (is->priv->literal > 0)
 
683
                g_warning (
 
684
                        "stream_token called with literal %d",
 
685
                        is->priv->literal);
583
686
 
584
 
        p = is->ptr;
585
 
        e = is->end;
 
687
        p = is->priv->ptr;
 
688
        e = is->priv->end;
586
689
 
587
690
        /* skip whitespace/prefill buffer */
588
691
        do {
589
692
                while (p >= e ) {
590
 
                        is->ptr = p;
 
693
                        is->priv->ptr = p;
591
694
                        if (imapx_stream_fill (is, cancellable, error) == IMAPX_TOK_ERROR)
592
695
                                return IMAPX_TOK_ERROR;
593
 
                        p = is->ptr;
594
 
                        e = is->end;
 
696
                        p = is->priv->ptr;
 
697
                        e = is->priv->end;
595
698
                }
596
699
                c = *p++;
597
700
        } while (c == ' ' || c == '\r');
598
701
 
599
702
        /*strchr("\n*()[]+", c)*/
600
703
        if (imapx_is_token_char (c)) {
601
 
                is->ptr = p;
602
 
                t(is->tagprefix, "token '%c'\n", c);
 
704
                is->priv->ptr = p;
 
705
                t (is->tagprefix, "token '%c'\n", c);
603
706
                return c;
604
707
        } else if (c == '{') {
605
708
                literal = 0;
615
718
                                                        c = *p++;
616
719
                                                        if (c == '\n') {
617
720
                                                                *len = literal;
618
 
                                                                is->ptr = p;
619
 
                                                                is->literal = literal;
620
 
                                                                t(is->tagprefix, "token LITERAL %d\n", literal);
 
721
                                                                is->priv->ptr = p;
 
722
                                                                is->priv->literal = literal;
 
723
                                                                t (is->tagprefix, "token LITERAL %d\n", literal);
621
724
                                                                return IMAPX_TOK_LITERAL;
622
725
                                                        }
623
726
                                                }
624
 
                                                is->ptr = p;
 
727
                                                is->priv->ptr = p;
625
728
                                                if (imapx_stream_fill (is, cancellable, error) == IMAPX_TOK_ERROR)
626
729
                                                        return IMAPX_TOK_ERROR;
627
 
                                                p = is->ptr;
628
 
                                                e = is->end;
 
730
                                                p = is->priv->ptr;
 
731
                                                e = is->priv->end;
629
732
                                        }
630
733
                                } else {
631
734
                                        if (isdigit (c)) {
632
 
                                                io(is->tagprefix, "Protocol error: literal too big\n");
 
735
                                                io (is->tagprefix, "Protocol error: literal too big\n");
633
736
                                        } else {
634
 
                                                io(is->tagprefix, "Protocol error: literal contains invalid gchar %02x '%c'\n", c, isprint(c)?c:c);
 
737
                                                io (is->tagprefix, "Protocol error: literal contains invalid gchar %02x '%c'\n", c, isprint (c) ? c : c);
635
738
                                        }
636
739
                                        goto protocol_error;
637
740
                                }
638
741
                        }
639
 
                        is->ptr = p;
 
742
                        is->priv->ptr = p;
640
743
                        if (imapx_stream_fill (is, cancellable, error) == IMAPX_TOK_ERROR)
641
744
                                return IMAPX_TOK_ERROR;
642
 
                        p = is->ptr;
643
 
                        e = is->end;
 
745
                        p = is->priv->ptr;
 
746
                        e = is->priv->end;
644
747
                }
645
748
        } else if (c == '"') {
646
 
                o = is->tokenbuf;
647
 
                oe = is->tokenbuf + is->bufsize - 1;
 
749
                o = is->priv->tokenbuf;
 
750
                oe = is->priv->tokenbuf + is->priv->bufsize - 1;
648
751
                while (1) {
649
752
                        while (p < e) {
650
753
                                c = *p++;
651
754
                                if (c == '\\') {
652
755
                                        while (p >= e) {
653
 
                                                is->ptr = p;
 
756
                                                is->priv->ptr = p;
654
757
                                                if (imapx_stream_fill (is, cancellable, error) == IMAPX_TOK_ERROR)
655
758
                                                        return IMAPX_TOK_ERROR;
656
 
                                                p = is->ptr;
657
 
                                                e = is->end;
 
759
                                                p = is->priv->ptr;
 
760
                                                e = is->priv->end;
658
761
                                        }
659
762
                                        c = *p++;
660
763
                                } else if (c == '\"') {
661
 
                                        is->ptr = p;
 
764
                                        is->priv->ptr = p;
662
765
                                        *o = 0;
663
 
                                        *data = is->tokenbuf;
664
 
                                        *len = o - is->tokenbuf;
665
 
                                        t(is->tagprefix, "token STRING '%s'\n", is->tokenbuf);
 
766
                                        *data = is->priv->tokenbuf;
 
767
                                        *len = o - is->priv->tokenbuf;
 
768
                                        t (is->tagprefix, "token STRING '%s'\n", is->priv->tokenbuf);
666
769
                                        return IMAPX_TOK_STRING;
667
770
                                }
668
771
                                if (c == '\n' || c == '\r') {
669
 
                                        io(is->tagprefix, "Protocol error: truncated string\n");
 
772
                                        io (is->tagprefix, "Protocol error: truncated string\n");
670
773
                                        goto protocol_error;
671
774
                                }
672
775
                                if (o >= oe) {
673
776
                                        camel_imapx_stream_grow (is, 0, &p, &o);
674
 
                                        oe = is->tokenbuf + is->bufsize - 1;
675
 
                                        e = is->end;
 
777
                                        oe = is->priv->tokenbuf + is->priv->bufsize - 1;
 
778
                                        e = is->priv->end;
676
779
                                }
677
780
                                *o++ = c;
678
781
                        }
679
 
                        is->ptr = p;
 
782
                        is->priv->ptr = p;
680
783
                        if (imapx_stream_fill (is, cancellable, error) == IMAPX_TOK_ERROR)
681
784
                                return IMAPX_TOK_ERROR;
682
 
                        p = is->ptr;
683
 
                        e = is->end;
 
785
                        p = is->priv->ptr;
 
786
                        e = is->priv->end;
684
787
                }
685
788
        } else {
686
 
                o = is->tokenbuf;
687
 
                oe = is->tokenbuf + is->bufsize - 1;
 
789
                o = is->priv->tokenbuf;
 
790
                oe = is->priv->tokenbuf + is->priv->bufsize - 1;
688
791
                digits = isdigit (c);
689
792
                *o++ = c;
690
793
                while (1) {
693
796
                                /*if (strchr(" \r\n*()[]+", c) != NULL) {*/
694
797
                                if (imapx_is_notid_char (c)) {
695
798
                                        if (c == ' ' || c == '\r')
696
 
                                                is->ptr = p;
 
799
                                                is->priv->ptr = p;
697
800
                                        else
698
 
                                                is->ptr = p - 1;
 
801
                                                is->priv->ptr = p - 1;
699
802
                                        *o = 0;
700
 
                                        *data = is->tokenbuf;
701
 
                                        *len = o - is->tokenbuf;
702
 
                                        t(is->tagprefix, "token TOKEN '%s'\n", is->tokenbuf);
 
803
                                        *data = is->priv->tokenbuf;
 
804
                                        *len = o - is->priv->tokenbuf;
 
805
                                        t (is->tagprefix, "token TOKEN '%s'\n", is->priv->tokenbuf);
703
806
                                        return digits ? IMAPX_TOK_INT : IMAPX_TOK_TOKEN;
704
807
                                }
705
808
 
706
809
                                if (o >= oe) {
707
810
                                        camel_imapx_stream_grow (is, 0, &p, &o);
708
 
                                        oe = is->tokenbuf + is->bufsize - 1;
709
 
                                        e = is->end;
 
811
                                        oe = is->priv->tokenbuf + is->priv->bufsize - 1;
 
812
                                        e = is->priv->end;
710
813
                                }
711
814
                                digits &= isdigit (c);
712
815
                                *o++ = c;
713
816
                        }
714
 
                        is->ptr = p;
 
817
                        is->priv->ptr = p;
715
818
                        if (imapx_stream_fill (is, cancellable, error) == IMAPX_TOK_ERROR)
716
819
                                return IMAPX_TOK_ERROR;
717
 
                        p = is->ptr;
718
 
                        e = is->end;
 
820
                        p = is->priv->ptr;
 
821
                        e = is->priv->end;
719
822
                }
720
823
        }
721
824
 
722
825
        /* Protocol error, skip until next lf? */
723
826
protocol_error:
724
 
        io(is->tagprefix, "Got protocol error\n");
 
827
        io (is->tagprefix, "Got protocol error\n");
725
828
 
726
829
        if (c == '\n')
727
 
                is->ptr = p - 1;
 
830
                is->priv->ptr = p - 1;
728
831
        else
729
 
                is->ptr = p;
 
832
                is->priv->ptr = p;
730
833
 
731
834
        g_set_error (error, CAMEL_IMAPX_ERROR, 1, "protocol error");
732
835
        return IMAPX_TOK_PROTOCOL;
738
841
                               guchar *token,
739
842
                               guint len)
740
843
{
741
 
        /*printf("ungettoken: '%c' '%s'\n", tok, token);*/
742
 
        is->unget_tok = tok;
743
 
        is->unget_token = token;
744
 
        is->unget_len = len;
745
 
        is->unget++;
 
844
        g_return_if_fail (CAMEL_IS_IMAPX_STREAM (is));
 
845
 
 
846
        is->priv->unget_tok = tok;
 
847
        is->priv->unget_token = token;
 
848
        is->priv->unget_len = len;
 
849
        is->priv->unget++;
746
850
}
747
851
 
748
852
/* returns -1 on error, 0 if last lot of data, >0 if more remaining */
756
860
        gint max;
757
861
        guchar *end;
758
862
 
 
863
        g_return_val_if_fail (CAMEL_IS_IMAPX_STREAM (is), -1);
 
864
        g_return_val_if_fail (start != NULL, -1);
 
865
        g_return_val_if_fail (len != NULL, -1);
 
866
 
759
867
        *len = 0;
760
868
 
761
 
        max = is->end - is->ptr;
 
869
        max = is->priv->end - is->priv->ptr;
762
870
        if (max == 0) {
763
871
                max = imapx_stream_fill (is, cancellable, error);
764
872
                if (max <= 0)
765
873
                        return max;
766
874
        }
767
875
 
768
 
        *start = is->ptr;
769
 
        end = memchr (is->ptr, '\n', max);
 
876
        *start = is->priv->ptr;
 
877
        end = memchr (is->priv->ptr, '\n', max);
770
878
        if (end)
771
 
                max = (end - is->ptr) + 1;
772
 
        *start = is->ptr;
 
879
                max = (end - is->priv->ptr) + 1;
 
880
        *start = is->priv->ptr;
773
881
        *len = max;
774
 
        is->ptr += max;
 
882
        is->priv->ptr += max;
775
883
 
776
884
        return end == NULL ? 1 : 0;
777
885
}
778
886
 
779
 
void camel_imapx_stream_set_literal (CamelIMAPXStream *is, guint literal)
 
887
void
 
888
camel_imapx_stream_set_literal (CamelIMAPXStream *is,
 
889
                                guint literal)
780
890
{
781
 
        is->literal = literal;
 
891
        g_return_if_fail (CAMEL_IS_IMAPX_STREAM (is));
 
892
 
 
893
        is->priv->literal = literal;
782
894
}
783
895
 
784
896
/* returns -1 on erorr, 0 if last data, >0 if more data left */
791
903
{
792
904
        gint max;
793
905
 
 
906
        g_return_val_if_fail (CAMEL_IS_IMAPX_STREAM (is), -1);
 
907
        g_return_val_if_fail (start != NULL, -1);
 
908
        g_return_val_if_fail (len != NULL, -1);
 
909
 
794
910
        *len = 0;
795
911
 
796
 
        if (is->literal > 0) {
797
 
                max = is->end - is->ptr;
 
912
        if (is->priv->literal > 0) {
 
913
                max = is->priv->end - is->priv->ptr;
798
914
                if (max == 0) {
799
915
                        max = imapx_stream_fill (is, cancellable, error);
800
916
                        if (max <= 0)
801
917
                                return max;
802
918
                }
803
919
 
804
 
                max = MIN (max, is->literal);
805
 
                *start = is->ptr;
 
920
                max = MIN (max, is->priv->literal);
 
921
                *start = is->priv->ptr;
806
922
                *len = max;
807
 
                is->ptr += max;
808
 
                is->literal -= max;
 
923
                is->priv->ptr += max;
 
924
                is->priv->literal -= max;
809
925
        }
810
926
 
811
 
        if (is->literal > 0)
 
927
        if (is->priv->literal > 0)
812
928
                return 1;
813
929
 
814
930
        return 0;
824
940
        guchar *token;
825
941
        guint len;
826
942
 
 
943
        g_return_val_if_fail (CAMEL_IS_IMAPX_STREAM (is), -1);
 
944
 
827
945
        do {
828
946
                tok = camel_imapx_stream_token (is, &token, &len, cancellable, error);
829
947
                if (tok == IMAPX_TOK_LITERAL) {
830
948
                        camel_imapx_stream_set_literal (is, len);
831
949
                        while ((tok = camel_imapx_stream_getl (is, &token, &len, cancellable, error)) > 0) {
832
 
                                io(is->tagprefix, "Skip literal data '%.*s'\n", (gint)len, token);
 
950
                                io (is->tagprefix, "Skip literal data '%.*s'\n", (gint) len, token);
833
951
                        }
834
952
                }
835
953
        } while (tok != '\n' && tok >= 0);
839
957
 
840
958
        return 0;
841
959
}
 
960