~ubuntu-branches/debian/sid/openchange/sid

« back to all changes in this revision

Viewing changes to libmapi/fxparser.c

  • Committer: Package Import Robot
  • Author(s): Jelmer Vernooij
  • Date: 2012-04-12 20:07:57 UTC
  • mfrom: (11 sid)
  • mto: This revision was merged to the branch mainline in revision 12.
  • Revision ID: package-import@ubuntu.com-20120412200757-k933d9trljmxj1l4
Tags: 1:1.0-4
* openchangeserver: Add dependency on openchangeproxy.
* Rebuild against newer version of Samba 4.
* Use dpkg-buildflags.
* Migrate to Git, update Vcs-Git header.
* Switch to debhelper 9.

Show diffs side-by-side

added added

removed removed

Lines of Context:
37
37
static bool pull_uint8_t(struct fx_parser_context *parser, uint8_t *val)
38
38
{
39
39
        if ((parser->idx) + 1 > parser->data.length) {
40
 
                val = 0;
 
40
                *val = 0;
41
41
                return false;
42
42
        }
43
43
        *val = parser->data.data[parser->idx];
48
48
static bool pull_uint16_t(struct fx_parser_context *parser, uint16_t *val)
49
49
{
50
50
        if ((parser->idx) + 2 > parser->data.length) {
51
 
                val = 0;
 
51
                *val = 0;
52
52
                return false;
53
53
        }
54
54
        *val = parser->data.data[parser->idx];
61
61
static bool pull_uint32_t(struct fx_parser_context *parser, uint32_t *val)
62
62
{
63
63
        if ((parser->idx) + 4 > parser->data.length) {
64
 
                val = 0;
 
64
                *val = 0;
65
65
                return false;
66
66
        }
67
67
        *val = parser->data.data[parser->idx];
77
77
 
78
78
static bool pull_tag(struct fx_parser_context *parser)
79
79
{
80
 
        bool result;
81
 
        result = pull_uint32_t(parser, &(parser->tag));
82
 
        if (!result) {
83
 
                printf("bad pull of tag\n");
84
 
        }
85
 
        return result;
 
80
        return pull_uint32_t(parser, &(parser->tag));
86
81
}
87
82
 
88
 
static bool pull_uint8_data(struct fx_parser_context *parser, uint8_t **data_read)
 
83
static bool pull_uint8_data(struct fx_parser_context *parser, uint32_t read_len, uint8_t **data_read)
89
84
{
90
 
        for (; parser->offset < parser->length; ++(parser->offset)) {
91
 
                /* printf("parser %i of %i\n", parser->offset, parser->length); */
92
 
                if (!pull_uint8_t(parser, (uint8_t*)&((*data_read)[parser->offset]))) {
 
85
        uint32_t i;
 
86
        for (i = 0; i < read_len; i++) {
 
87
                if (!pull_uint8_t(parser, (uint8_t*)&((*data_read)[i]))) {
93
88
                        return false;
94
89
                }
95
90
        }
150
145
                GUID_all_zero(guid);
151
146
                return false;
152
147
        }
153
 
        pull_uint32_t(parser, &(guid->time_low));
154
 
        pull_uint16_t(parser, &(guid->time_mid));
155
 
        pull_uint16_t(parser, &(guid->time_hi_and_version));
156
 
        pull_uint8_t(parser, &(guid->clock_seq[0]));
157
 
        pull_uint8_t(parser, &(guid->clock_seq[1]));
 
148
        if (!pull_uint32_t(parser, &(guid->time_low)))
 
149
                return false;
 
150
        if (!pull_uint16_t(parser, &(guid->time_mid)))
 
151
                return false;
 
152
        if (!pull_uint16_t(parser, &(guid->time_hi_and_version)))
 
153
                return false;
 
154
        if (!pull_uint8_t(parser, &(guid->clock_seq[0])))
 
155
                return false;
 
156
        if (!pull_uint8_t(parser, &(guid->clock_seq[1])))
 
157
                return false;
158
158
        for (i = 0; i < 6; ++i) {
159
 
                pull_uint8_t(parser, &(guid->node[i]));
160
 
        }
 
159
                if (!pull_uint8_t(parser, &(guid->node[i])))
 
160
                        return false;
 
161
        }
 
162
        return true;
 
163
}
 
164
 
 
165
static bool pull_systime(struct fx_parser_context *parser, struct FILETIME *ft)
 
166
{
 
167
        struct FILETIME filetime = {0,0};
 
168
 
 
169
        if (parser->idx + 8 > parser->data.length ||
 
170
            !pull_uint32_t(parser, &(filetime.dwLowDateTime)) ||
 
171
            !pull_uint32_t(parser, &(filetime.dwHighDateTime)))
 
172
                return false;
 
173
 
 
174
        *ft = filetime;
 
175
 
 
176
        return true;
 
177
}
 
178
 
 
179
static bool pull_clsid(struct fx_parser_context *parser, struct FlatUID_r **pclsid)
 
180
{
 
181
        struct FlatUID_r *clsid;
 
182
        int i = 0;
 
183
 
 
184
        if (parser->idx + 16 > parser->data.length)
 
185
                return false;
 
186
 
 
187
        clsid = talloc_zero(parser->mem_ctx, struct FlatUID_r);
 
188
        for (i = 0; i < 16; ++i) {
 
189
                if (!pull_uint8_t(parser, &(clsid->ab[i])))
 
190
                        return false;
 
191
        }
 
192
 
 
193
        *pclsid = clsid;
 
194
 
 
195
        return true;
 
196
}
 
197
 
 
198
static bool pull_string8(struct fx_parser_context *parser, char **pstr)
 
199
{
 
200
        char *str;
 
201
        uint32_t i, length;
 
202
 
 
203
        if (!pull_uint32_t(parser, &length) ||
 
204
            parser->idx + length > parser->data.length)
 
205
                return false;
 
206
 
 
207
        str = talloc_array(parser->mem_ctx, char, length + 1);
 
208
        for (i = 0; i < length; i++) {
 
209
                if (!pull_uint8_t(parser, (uint8_t*)&(str[i]))) {
 
210
                        return false;
 
211
                }
 
212
        }
 
213
        str[length] = '\0';
 
214
 
 
215
        *pstr = str;
 
216
 
161
217
        return true;
162
218
}
163
219
 
168
224
                return false;
169
225
        }
170
226
 
171
 
        *data_read = talloc_array(parser->mem_ctx, smb_ucs2_t, numbytes/2);
 
227
        *data_read = talloc_zero_array(parser->mem_ctx, smb_ucs2_t, (numbytes/2) + 1);
172
228
        memcpy(*data_read, &(parser->data.data[parser->idx]), numbytes);
173
229
        parser->idx += numbytes;
174
230
        return true;
177
233
static bool fetch_ucs2_nullterminated(struct fx_parser_context *parser, smb_ucs2_t **data_read)
178
234
{
179
235
        uint32_t idx_local = parser->idx;
 
236
        bool found = false;
180
237
        while (idx_local < parser->data.length -1) {
181
238
                smb_ucs2_t val = 0x0000;
182
239
                val += parser->data.data[idx_local];
184
241
                val += parser->data.data[idx_local] << 8;
185
242
                idx_local++;
186
243
                if (val == 0x0000) {
 
244
                        found = true;
187
245
                        break;
188
246
                }
189
247
        }
 
248
        if (!found)
 
249
                return false;
190
250
        return fetch_ucs2_data(parser, idx_local-(parser->idx), data_read); 
191
251
}
192
252
 
 
253
static bool pull_unicode(struct fx_parser_context *parser, char **pstr)
 
254
{
 
255
        smb_ucs2_t *ucs2_data = NULL;
 
256
        char *utf8_data = NULL;
 
257
        size_t utf8_len;
 
258
        uint32_t length;
 
259
 
 
260
        if (!pull_uint32_t(parser, &length) ||
 
261
            parser->idx + length > parser->data.length)
 
262
                return false;
 
263
 
 
264
        ucs2_data = talloc_zero_array(parser->mem_ctx, smb_ucs2_t, (length/2) + 1);
 
265
 
 
266
        if (!fetch_ucs2_data(parser, length, &ucs2_data)) {
 
267
                return false;
 
268
        }
 
269
        pull_ucs2_talloc(parser->mem_ctx, &utf8_data, ucs2_data, &utf8_len);
 
270
 
 
271
        *pstr = utf8_data;
 
272
 
 
273
        return true;
 
274
}
 
275
 
 
276
static bool pull_binary(struct fx_parser_context *parser, struct Binary_r *bin)
 
277
{
 
278
        if (!pull_uint32_t(parser, &(bin->cb)) ||
 
279
            parser->idx + bin->cb > parser->data.length)
 
280
                return false;
 
281
 
 
282
        bin->lpb = talloc_array(parser->mem_ctx, uint8_t, bin->cb + 1);
 
283
 
 
284
        return pull_uint8_data(parser, bin->cb, &(bin->lpb));
 
285
}
 
286
 
193
287
/*
194
288
 pull a property value from the blob, starting at position idx
195
289
*/
196
 
static bool fetch_property_value(struct fx_parser_context *parser, DATA_BLOB *buf, struct SPropValue *prop, uint32_t *len)
 
290
static bool fetch_property_value(struct fx_parser_context *parser, DATA_BLOB *buf, struct SPropValue *prop)
197
291
{
198
292
        switch(prop->ulPropTag & 0xFFFF) {
 
293
        case PT_NULL:
 
294
        {
 
295
                if (!pull_uint32_t(parser, &(prop->value.null)))
 
296
                        return false;
 
297
                break; 
 
298
        }
199
299
        case PT_SHORT:
200
300
        {
201
 
                pull_uint16_t(parser, &(prop->value.i));
 
301
                if (!pull_uint16_t(parser, &(prop->value.i)))
 
302
                        return false;
202
303
                break;
203
304
        }
204
305
        case PT_LONG:
205
306
        {
206
 
                pull_uint32_t(parser, &(prop->value.l));
 
307
                if (!pull_uint32_t(parser, &(prop->value.l)))
 
308
                        return false;
207
309
                break;
208
310
        }
209
311
        case PT_DOUBLE:
210
312
        {
211
 
                pull_double(parser, (double *)&(prop->value.dbl));
 
313
                if (!pull_double(parser, (double *)&(prop->value.dbl)))
 
314
                        return false;
212
315
                break;
213
316
        }
214
317
        case PT_BOOLEAN:
215
318
        {
216
 
                pull_uint8_t(parser, &(prop->value.b));
 
319
                if (parser->idx + 2 > parser->data.length ||
 
320
                    !pull_uint8_t(parser, &(prop->value.b)))
 
321
                        return false;
 
322
 
217
323
                /* special case for fast transfer, 2 bytes instead of one */
218
324
                (parser->idx)++;
219
325
                break;
221
327
        case PT_I8:
222
328
        {
223
329
                int64_t val;
224
 
                pull_int64_t(parser, &(val));
 
330
                if (!pull_int64_t(parser, &(val)))
 
331
                        return false;
225
332
                prop->value.d = val;
226
333
                break;
227
334
        }
228
335
        case PT_STRING8:
229
336
        {
230
 
                char *ptr = 0;
231
 
                if (parser->length == 0) {
232
 
                        pull_uint32_t(parser, &(parser->length));
233
 
                        parser->offset = 0;
234
 
                        prop->value.lpszA = talloc_array(parser->mem_ctx, char, parser->length + 1);
235
 
                }
236
 
                for (; parser->offset < parser->length; ++(parser->offset)) {
237
 
                        if (!pull_uint8_t(parser, (uint8_t*)&(prop->value.lpszA[parser->offset]))) {
238
 
                                return false;
239
 
                        }
240
 
                }
241
 
                ptr = (char*)prop->value.lpszA;
242
 
                ptr += parser->length;
243
 
                *ptr = '\0';
 
337
                char *str = NULL;
 
338
                if (!pull_string8(parser, &str))
 
339
                        return false;
 
340
                prop->value.lpszA = str;
244
341
                break;
245
342
        }
246
343
        case PT_UNICODE:
247
344
        {
248
 
                /* TODO: rethink this to handle split buffers */
249
 
                smb_ucs2_t *ucs2_data = NULL;
250
 
                if (parser->length == 0) {
251
 
                        pull_uint32_t(parser, &(parser->length));
252
 
                        ucs2_data = talloc_array(parser->mem_ctx, smb_ucs2_t, parser->length/2);
253
 
                        parser->offset = 0;
254
 
                }
255
 
                char *utf8_data = NULL;
256
 
                size_t utf8_len;
257
 
                if (!fetch_ucs2_data(parser, parser->length, &ucs2_data)) {
 
345
                char *str = NULL;
 
346
                if (!pull_unicode (parser, &str))
258
347
                        return false;
259
 
                }
260
 
                pull_ucs2_talloc(parser->mem_ctx, &utf8_data, ucs2_data, &utf8_len);
261
 
                prop->value.lpszW = utf8_data;
 
348
                prop->value.lpszW = str;
262
349
                break;
263
350
        }
264
351
        case PT_SYSTIME:
265
352
        {
266
 
                struct FILETIME filetime = {0,0};
267
 
                pull_uint32_t(parser, &(filetime.dwLowDateTime));
268
 
                pull_uint32_t(parser, &(filetime.dwHighDateTime));
269
 
                prop->value.ft = filetime;
 
353
                if (!pull_systime(parser, &prop->value.ft))
 
354
                        return false;
270
355
                break;
271
356
        }
272
357
        case PT_CLSID:
273
358
        {
274
 
                int i = 0;
275
 
                prop->value.lpguid = talloc_zero(parser->mem_ctx, struct FlatUID_r);
276
 
                for (i = 0; i < 16; ++i) {
277
 
                        pull_uint8_t(parser, &(prop->value.lpguid->ab[i]));
278
 
                }
 
359
                if (!pull_clsid(parser, &prop->value.lpguid))
 
360
                        return false;
279
361
                break;
280
362
        }
281
363
        case PT_SVREID:
282
364
        case PT_BINARY:
283
365
        {
284
 
                if (parser->length == 0) {
285
 
                          pull_uint32_t(parser, &(prop->value.bin.cb));
286
 
                          parser->length = prop->value.bin.cb;
287
 
                          prop->value.bin.lpb = talloc_array(parser->mem_ctx, uint8_t, parser->length + 1);
288
 
                          parser->offset = 0;
289
 
                }
290
 
                if (!pull_uint8_data(parser, &(prop->value.bin.lpb))) {
 
366
                if (!pull_binary(parser, &prop->value.bin))
291
367
                        return false;
292
 
                }
293
368
                break;
294
369
        }
295
370
        case PT_OBJECT:
296
371
        {
297
 
                pull_uint32_t(parser, &(prop->value.object));
 
372
                /* the object itself is sent too, thus download it as a binary,
 
373
                   not as a meaningless number, which is length of the object here */
 
374
                if (!pull_binary(parser, &prop->value.bin))
 
375
                        return false;
 
376
                break;
 
377
        }
 
378
        case PT_ERROR:
 
379
        {
 
380
                uint32_t num;
 
381
                if (!pull_uint32_t(parser, &num))
 
382
                        return false;
 
383
                prop->value.err = num;
298
384
                break;
299
385
        }
300
386
        case PT_MV_BINARY:
301
387
        {
302
 
                /* TODO: handle partial count / length */
303
 
                uint32_t        i;
304
 
                pull_uint32_t(parser, &(prop->value.MVbin.cValues));
 
388
                uint32_t i;
 
389
                if (!pull_uint32_t(parser, &(prop->value.MVbin.cValues)) ||
 
390
                    parser->idx + prop->value.MVbin.cValues * 4 > parser->data.length)
 
391
                        return false;
305
392
                prop->value.MVbin.lpbin = talloc_array(parser->mem_ctx, struct Binary_r, prop->value.MVbin.cValues);
306
393
                for (i = 0; i < prop->value.MVbin.cValues; i++) {
307
 
                        pull_uint32_t(parser, &(prop->value.MVbin.lpbin[i].cb));
308
 
                        parser->length = prop->value.MVbin.lpbin[i].cb;
309
 
                        prop->value.MVbin.lpbin[i].lpb = talloc_array(parser->mem_ctx, uint8_t, parser->length + 1);
310
 
                        parser->offset = 0;
311
 
                        if (!pull_uint8_data(parser, &(prop->value.MVbin.lpbin[i].lpb))) {
312
 
                                return false;
313
 
                        }
 
394
                        if (!pull_binary(parser, &(prop->value.MVbin.lpbin[i])))
 
395
                                return false;
 
396
                }
 
397
                break;
 
398
        }
 
399
        case PT_MV_SHORT:
 
400
        {
 
401
                uint32_t i;
 
402
                if (!pull_uint32_t(parser, &(prop->value.MVi.cValues)) ||
 
403
                    parser->idx + prop->value.MVi.cValues * 2 > parser->data.length)
 
404
                        return false;
 
405
                prop->value.MVi.lpi = talloc_array(parser->mem_ctx, uint16_t, prop->value.MVi.cValues);
 
406
                for (i = 0; i < prop->value.MVi.cValues; i++) {
 
407
                        if (!pull_uint16_t(parser, &(prop->value.MVi.lpi[i])))
 
408
                                return false;
 
409
                }
 
410
                break;
 
411
        }
 
412
        case PT_MV_LONG:
 
413
        {
 
414
                uint32_t i;
 
415
                if (!pull_uint32_t(parser, &(prop->value.MVl.cValues)) ||
 
416
                    parser->idx + prop->value.MVl.cValues * 4 > parser->data.length)
 
417
                        return false;
 
418
                prop->value.MVl.lpl = talloc_array(parser->mem_ctx, uint32_t, prop->value.MVl.cValues);
 
419
                for (i = 0; i < prop->value.MVl.cValues; i++) {
 
420
                        if (!pull_uint32_t(parser, &(prop->value.MVl.lpl[i])))
 
421
                                return false;
 
422
                }
 
423
                break;
 
424
        }
 
425
        case PT_MV_STRING8:
 
426
        {
 
427
                uint32_t i;
 
428
                char *str;
 
429
                if (!pull_uint32_t(parser, &(prop->value.MVszA.cValues)) ||
 
430
                    parser->idx + prop->value.MVszA.cValues * 4 > parser->data.length)
 
431
                        return false;
 
432
                prop->value.MVszA.lppszA = (const char **) talloc_array(parser->mem_ctx, char *, prop->value.MVszA.cValues);
 
433
                for (i = 0; i < prop->value.MVszA.cValues; i++) {
 
434
                        str = NULL;
 
435
                        if (!pull_string8(parser, &str))
 
436
                                return false;
 
437
                        prop->value.MVszA.lppszA[i] = str;
 
438
                }
 
439
                break;
 
440
        }
 
441
        case PT_MV_CLSID:
 
442
        {
 
443
                uint32_t i;
 
444
                if (!pull_uint32_t(parser, &(prop->value.MVguid.cValues)) ||
 
445
                    parser->idx + prop->value.MVguid.cValues * 16 > parser->data.length)
 
446
                        return false;
 
447
                prop->value.MVguid.lpguid = talloc_array(parser->mem_ctx, struct FlatUID_r *, prop->value.MVguid.cValues);
 
448
                for (i = 0; i < prop->value.MVguid.cValues; i++) {
 
449
                        if (!pull_clsid(parser, &(prop->value.MVguid.lpguid[i])))
 
450
                                return false;
 
451
                }
 
452
                break;
 
453
        }
 
454
        case PT_MV_UNICODE:
 
455
        {
 
456
                uint32_t i;
 
457
                char *str;
 
458
 
 
459
                if (!pull_uint32_t(parser, &(prop->value.MVszW.cValues)) ||
 
460
                    parser->idx + prop->value.MVszW.cValues * 4 > parser->data.length)
 
461
                        return false;
 
462
                prop->value.MVszW.lppszW = (const char **)  talloc_array(parser->mem_ctx, char *, prop->value.MVszW.cValues);
 
463
                for (i = 0; i < prop->value.MVszW.cValues; i++) {
 
464
                        str = NULL;
 
465
                        if (!pull_unicode(parser, &str))
 
466
                                return false;
 
467
                        prop->value.MVszW.lppszW[i] = str;
 
468
                }
 
469
                break;
 
470
        }
 
471
        case PT_MV_SYSTIME:
 
472
        {
 
473
                uint32_t i;
 
474
                if (!pull_uint32_t(parser, &(prop->value.MVft.cValues)) ||
 
475
                    parser->idx + prop->value.MVft.cValues * 8 > parser->data.length)
 
476
                        return false;
 
477
                prop->value.MVft.lpft = talloc_array(parser->mem_ctx, struct FILETIME, prop->value.MVft.cValues);
 
478
                for (i = 0; i < prop->value.MVft.cValues; i++) {
 
479
                        if (!pull_systime(parser, &(prop->value.MVft.lpft[i])))
 
480
                                return false;
314
481
                }
315
482
                break;
316
483
        }
317
484
        default:
318
 
                printf("unhandled conversion case in fetch_property_value(): 0x%x\n", (prop->ulPropTag & 0xFFFF));
 
485
                printf("unhandled conversion case in fetch_property_value(): 0x%x\n", prop->ulPropTag);
319
486
                OPENCHANGE_ASSERT();
320
487
        }
321
488
        return true;
322
489
}
323
490
 
324
 
static void pull_named_property(struct fx_parser_context *parser)
 
491
static bool pull_named_property(struct fx_parser_context *parser, enum MAPISTATUS *ms)
325
492
{
326
493
        uint8_t type = 0;
327
 
        pull_guid(parser, &(parser->namedprop.lpguid));
 
494
        if (!pull_guid(parser, &(parser->namedprop.lpguid)))
 
495
                return false;
328
496
        /* printf("guid       : %s\n", GUID_string(parser->mem_ctx, &(parser->namedprop.lpguid))); */
329
 
        pull_uint8_t(parser, &type);
 
497
        if (!pull_uint8_t(parser, &type))
 
498
                return false;
330
499
        if (type == 0) {
331
500
                parser->namedprop.ulKind = MNID_ID;
332
 
                pull_uint32_t(parser, &(parser->namedprop.kind.lid));
 
501
                if (!pull_uint32_t(parser, &(parser->namedprop.kind.lid)))
 
502
                        return false;
333
503
                /* printf("LID dispid: 0x%08x\n", parser->namedprop.kind.lid); */
334
504
        } else if (type == 1) {
335
505
                smb_ucs2_t *ucs2_data = NULL;
336
506
                size_t utf8_len;
337
507
                parser->namedprop.ulKind = MNID_STRING;
338
 
                fetch_ucs2_nullterminated(parser, &ucs2_data);
 
508
                if (!fetch_ucs2_nullterminated(parser, &ucs2_data))
 
509
                        return false;
339
510
                pull_ucs2_talloc(parser->mem_ctx, (char**)&(parser->namedprop.kind.lpwstr.Name), ucs2_data, &(utf8_len));
340
511
                parser->namedprop.kind.lpwstr.NameSize = utf8_len;
341
512
                /* printf("named: %s\n", parser->namedprop.kind.lpwstr.Name); */
344
515
                OPENCHANGE_ASSERT();
345
516
        }
346
517
        if (parser->op_namedprop) {
347
 
                parser->op_namedprop(parser->lpProp.ulPropTag, parser->namedprop, parser->priv);
 
518
                *ms = parser->op_namedprop(parser->lpProp.ulPropTag, parser->namedprop, parser->priv);
348
519
        }
 
520
 
 
521
        return true;
349
522
}
350
523
 
351
524
/**
394
567
        parser->lpProp.ulPropTag = (enum MAPITAGS) 0;
395
568
        parser->lpProp.dwAlignPad = 0;
396
569
        parser->lpProp.value.l = 0;
397
 
        parser->length = 0;
398
570
        parser->priv = priv;
399
571
 
400
572
        return parser;
403
575
/**
404
576
  \details parse a fast transfer buffer
405
577
*/
406
 
_PUBLIC_ void fxparser_parse(struct fx_parser_context *parser, DATA_BLOB *fxbuf)
 
578
_PUBLIC_ enum MAPISTATUS fxparser_parse(struct fx_parser_context *parser, DATA_BLOB *fxbuf)
407
579
{
 
580
        enum MAPISTATUS ms = MAPI_E_SUCCESS;
 
581
 
408
582
        data_blob_append(parser->mem_ctx, &(parser->data), fxbuf->data, fxbuf->length);
409
583
        parser->enough_data = true;
410
 
        while((parser->idx < parser->data.length) && parser->enough_data) {
 
584
        while(ms == MAPI_E_SUCCESS && (parser->idx < parser->data.length) && parser->enough_data) {
 
585
                uint32_t idx = parser->idx;
 
586
 
411
587
                switch(parser->state) {
412
588
                        case ParserState_Entry:
413
589
                        {
414
 
                                pull_tag(parser);
415
 
                                /* printf("tag: 0x%08x\n", parser->tag); */
416
 
                                parser->state = ParserState_HaveTag;
 
590
                                if (pull_tag(parser)) {
 
591
                                        /* printf("tag: 0x%08x\n", parser->tag); */
 
592
                                        parser->state = ParserState_HaveTag;
 
593
                                } else {
 
594
                                        parser->enough_data = false;
 
595
                                        parser->idx = idx;
 
596
                                }
417
597
                                break;
418
598
                        }
419
599
                        case ParserState_HaveTag:
432
612
                                        case PidTagStartEmbed:
433
613
                                        case PidTagEndEmbed:
434
614
                                                if (parser->op_marker) {
435
 
                                                        parser->op_marker(parser->tag, parser->priv);
 
615
                                                        ms = parser->op_marker(parser->tag, parser->priv);
436
616
                                                }
437
617
                                                parser->state = ParserState_Entry;
438
618
                                                break;
441
621
                                                uint32_t tag;
442
622
                                                if (pull_uint32_t(parser, &tag)) {
443
623
                                                        if (parser->op_delprop) {
444
 
                                                                parser->op_delprop(tag, parser->priv);
 
624
                                                                ms = parser->op_delprop(tag, parser->priv);
445
625
                                                        }
446
626
                                                        parser->state = ParserState_Entry;
447
627
                                                } else {
448
628
                                                        parser->enough_data = false;
 
629
                                                        parser->idx = idx;
449
630
                                                }
450
631
                                                break;
451
632
                                        }
452
633
                                        default:
453
634
                                        {
454
635
                                                /* standard property thing */
455
 
                                          parser->lpProp.ulPropTag = (enum MAPITAGS) parser->tag;
 
636
                                                parser->lpProp.ulPropTag = (enum MAPITAGS) parser->tag;
456
637
                                                parser->lpProp.dwAlignPad = 0;
457
638
                                                if ((parser->lpProp.ulPropTag >> 16) & 0x8000) {
458
639
                                                        /* this is a named property */
459
640
                                                        // printf("tag: 0x%08x\n", parser->tag);
460
641
                                                        // TODO: this should probably be a separate parser state
461
642
                                                        // TODO: this needs to return the named property
462
 
                                                        pull_named_property(parser);
 
643
                                                        if (pull_named_property(parser, &ms)) {
 
644
                                                                parser->state = ParserState_HavePropTag;
 
645
                                                        } else {
 
646
                                                                parser->enough_data = false;
 
647
                                                                parser->idx = idx;
 
648
                                                        }
 
649
                                                } else {
 
650
                                                        parser->state = ParserState_HavePropTag;
463
651
                                                }
464
 
                                                parser->state = ParserState_HavePropTag;
465
652
                                        }
466
653
                                }
467
654
                                break;
468
655
                        }
469
656
                        case ParserState_HavePropTag:
470
657
                        {
471
 
                                if (fetch_property_value(parser, &(parser->data), &(parser->lpProp), &(parser->length))) {
 
658
                                if (fetch_property_value(parser, &(parser->data), &(parser->lpProp))) {
472
659
                                        // printf("position %i of %zi\n", parser->idx, parser->data.length);
473
660
                                        if (parser->op_property) {
474
 
                                                parser->op_property(parser->lpProp, parser->priv);
 
661
                                                ms = parser->op_property(parser->lpProp, parser->priv);
475
662
                                        }
476
663
                                        parser->state = ParserState_Entry;
477
 
                                        parser->length = 0;
478
664
                                } else {
479
665
                                        parser->enough_data = false;
 
666
                                        parser->idx = idx;
480
667
                                }
481
668
                                break;
482
669
                        }
490
677
                parser->data = remainder;
491
678
                parser->idx = 0;
492
679
        }
 
680
 
 
681
        return ms;
493
682
}