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

« back to all changes in this revision

Viewing changes to servers/exchange/lib/e2k-rule.c

  • Committer: Bazaar Package Importer
  • Author(s): Daniel Holbach
  • Date: 2005-10-10 11:30:56 UTC
  • mfrom: (1.1.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20051010113056-rb4vj4kbs8yxft85
Tags: 1.4.1-0ubuntu3
* debian/patches/camel-imap-store.c.patch:
  - Ubuntu 17465: apply patch from
  http://bugzilla.gnome.org/attachment.cgi?id=53234&action=view
  (additional NULL pointer check)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
 
2
 
 
3
/* Copyright (C) 2003, 2004 Novell, Inc.
 
4
 *
 
5
 * This program is free software; you can redistribute it and/or
 
6
 * modify it under the terms of version 2 of the GNU Lesser General Public
 
7
 * License as published by the Free Software Foundation.
 
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
 * General Public License for more details.
 
13
 *
 
14
 * You should have received a copy of the GNU Lesser General Public
 
15
 * License along with this program; if not, write to the
 
16
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 
17
 * Boston, MA 02111-1307, USA.
 
18
 */
 
19
 
 
20
#ifdef HAVE_CONFIG_H
 
21
#include "config.h"
 
22
#endif
 
23
 
 
24
#include <string.h>
 
25
 
 
26
#include "e2k-rule.h"
 
27
#include "e2k-action.h"
 
28
#include "e2k-properties.h"
 
29
#include "e2k-propnames.h"
 
30
#include "e2k-utils.h"
 
31
 
 
32
/**
 
33
 * e2k_rule_prop_set:
 
34
 * @prop: an #E2kRuleProp
 
35
 * @propname: a MAPI property name
 
36
 *
 
37
 * This is a convenience function to set both the %name and %proptag
 
38
 * fields of @prop.
 
39
 **/
 
40
void
 
41
e2k_rule_prop_set (E2kRuleProp *prop, const char *propname)
 
42
{
 
43
        prop->name = propname;
 
44
        prop->proptag = e2k_prop_proptag (propname);
 
45
}
 
46
 
 
47
/**
 
48
 * e2k_rule_write_uint32:
 
49
 * @ptr: pointer into a binary rule
 
50
 * @val: a uint32 value
 
51
 *
 
52
 * Writes @val into the rule at @ptr
 
53
 **/
 
54
void
 
55
e2k_rule_write_uint32 (guint8 *ptr, guint32 val)
 
56
{
 
57
        *ptr++ = ( val        & 0xFF);
 
58
        *ptr++ = ((val >>  8) & 0xFF);
 
59
        *ptr++ = ((val >> 16) & 0xFF);
 
60
        *ptr++ = ((val >> 24) & 0xFF);
 
61
}
 
62
 
 
63
/**
 
64
 * e2k_rule_append_uint32:
 
65
 * @ba: a byte array containing a binary rule
 
66
 * @val: a uint32 value
 
67
 *
 
68
 * Appends @val to the rule in @ba
 
69
 **/
 
70
void
 
71
e2k_rule_append_uint32 (GByteArray *ba, guint32 val)
 
72
{
 
73
        g_byte_array_set_size (ba, ba->len + 4);
 
74
        e2k_rule_write_uint32 (ba->data + ba->len - 4, val);
 
75
}
 
76
 
 
77
/**
 
78
 * e2k_rule_read_uint32:
 
79
 * @ptr: pointer into a binary rule
 
80
 *
 
81
 * Reads a uint32 value from the rule at @ptr
 
82
 *
 
83
 * Return value: the uint32 value
 
84
 **/
 
85
guint32
 
86
e2k_rule_read_uint32 (guint8 *ptr)
 
87
{
 
88
        return ptr[0] | (ptr[1] << 8) | (ptr[2] << 16) | (ptr[3] << 24);
 
89
}
 
90
 
 
91
/**
 
92
 * e2k_rule_extract_uint32:
 
93
 * @ptr: pointer to a pointer into a binary rule
 
94
 * @len: pointer to the remaining length of *@ptr
 
95
 * @val: pointer to a uint32 value
 
96
 *
 
97
 * Reads a uint32 value from the rule at **@ptr into *@val and updates
 
98
 * *@ptr and *@len accordingly.
 
99
 *
 
100
 * Return value: success or failure
 
101
 **/
 
102
gboolean
 
103
e2k_rule_extract_uint32 (guint8 **ptr, int *len, guint32 *val)
 
104
{
 
105
        if (*len < 4)
 
106
                return FALSE;
 
107
 
 
108
        *val = e2k_rule_read_uint32 (*ptr);
 
109
 
 
110
        *ptr += 4;
 
111
        *len -= 4;
 
112
        return TRUE;
 
113
}
 
114
 
 
115
/**
 
116
 * e2k_rule_write_uint16:
 
117
 * @ptr: pointer into a binary rule
 
118
 * @val: a uint16 value
 
119
 *
 
120
 * Writes @val into the rule at @ptr
 
121
 **/
 
122
void
 
123
e2k_rule_write_uint16 (guint8 *ptr, guint16 val)
 
124
{
 
125
        *ptr++ = ( val        & 0xFF);
 
126
        *ptr++ = ((val >>  8) & 0xFF);
 
127
}
 
128
 
 
129
/**
 
130
 * e2k_rule_append_uint16:
 
131
 * @ba: a byte array containing a binary rule
 
132
 * @val: a uint16 value
 
133
 *
 
134
 * Appends @val to the rule in @ba
 
135
 **/
 
136
void
 
137
e2k_rule_append_uint16 (GByteArray *ba, guint16 val)
 
138
{
 
139
        g_byte_array_set_size (ba, ba->len + 2);
 
140
        e2k_rule_write_uint16 (ba->data + ba->len - 2, val);
 
141
}
 
142
 
 
143
/**
 
144
 * e2k_rule_read_uint16:
 
145
 * @ptr: pointer into a binary rule
 
146
 *
 
147
 * Reads a uint16 value from the rule at @ptr
 
148
 *
 
149
 * Return value: the uint16 value
 
150
 **/
 
151
guint16
 
152
e2k_rule_read_uint16 (guint8 *ptr)
 
153
{
 
154
        return ptr[0] | (ptr[1] << 8);
 
155
}
 
156
 
 
157
/**
 
158
 * e2k_rule_extract_uint16:
 
159
 * @ptr: pointer to a pointer into a binary rule
 
160
 * @len: pointer to the remaining length of *@ptr
 
161
 * @val: pointer to a uint16 value
 
162
 *
 
163
 * Reads a uint16 value from the rule at **@ptr into *@val and updates
 
164
 * *@ptr and *@len accordingly.
 
165
 *
 
166
 * Return value: success or failure
 
167
 **/
 
168
gboolean
 
169
e2k_rule_extract_uint16 (guint8 **ptr, int *len, guint16 *val)
 
170
{
 
171
        if (*len < 2)
 
172
                return FALSE;
 
173
 
 
174
        *val = e2k_rule_read_uint16 (*ptr);
 
175
 
 
176
        *ptr += 2;
 
177
        *len -= 2;
 
178
        return TRUE;
 
179
}
 
180
 
 
181
/**
 
182
 * e2k_rule_append_byte:
 
183
 * @ba: a byte array containing a binary rule
 
184
 * @val: a byte value
 
185
 *
 
186
 * Appends @val to the rule in @ba
 
187
 **/
 
188
void
 
189
e2k_rule_append_byte (GByteArray *ba, guint8 val)
 
190
{
 
191
        g_byte_array_append (ba, &val, 1);
 
192
}
 
193
 
 
194
/**
 
195
 * e2k_rule_extract_byte:
 
196
 * @ptr: pointer to a pointer into a binary rule
 
197
 * @len: pointer to the remaining length of *@ptr
 
198
 * @val: pointer to a byte value
 
199
 *
 
200
 * Reads a byte value from the rule at **@ptr into *@val and updates
 
201
 * *@ptr and *@len accordingly.
 
202
 *
 
203
 * Return value: success or failure
 
204
 **/
 
205
gboolean
 
206
e2k_rule_extract_byte (guint8 **ptr, int *len, guint8 *val)
 
207
{
 
208
        if (*len < 1)
 
209
                return FALSE;
 
210
 
 
211
        *val = **ptr;
 
212
 
 
213
        *ptr += 1;
 
214
        *len -= 1;
 
215
        return TRUE;
 
216
}
 
217
 
 
218
/**
 
219
 * e2k_rule_append_string:
 
220
 * @ba: a byte array containing a binary rule
 
221
 * @str: a (Windows) locale-encoded string
 
222
 *
 
223
 * Appends @str to the rule in @ba
 
224
 **/
 
225
void
 
226
e2k_rule_append_string (GByteArray *ba, const char *str)
 
227
{
 
228
        /* FIXME: verify encoding */
 
229
        g_byte_array_append (ba, str, strlen (str) + 1);
 
230
}
 
231
 
 
232
/**
 
233
 * e2k_rule_extract_string:
 
234
 * @ptr: pointer to a pointer into a binary rule
 
235
 * @len: pointer to the remaining length of *@ptr
 
236
 * @str: pointer to a string pointer
 
237
 *
 
238
 * Reads a (Windows) locale-encoded string from the rule at **@ptr
 
239
 * into *@str and updates *@ptr and *@len accordingly.
 
240
 *
 
241
 * Return value: success or failure
 
242
 **/
 
243
gboolean
 
244
e2k_rule_extract_string (guint8 **ptr, int *len, char **str)
 
245
{
 
246
        int slen;
 
247
 
 
248
        for (slen = 0; slen < *len; slen++) {
 
249
                if ((*ptr)[slen] == '\0') {
 
250
                        *str = g_strdup (*ptr);
 
251
                        *ptr += slen + 1;
 
252
                        *len -= slen + 1;
 
253
                        return TRUE;
 
254
                }
 
255
        }
 
256
 
 
257
        return FALSE;
 
258
}
 
259
 
 
260
/**
 
261
 * e2k_rule_append_unicode:
 
262
 * @ba: a byte array containing a binary rule
 
263
 * @str: a UTF-8 string
 
264
 *
 
265
 * Appends @str to the rule in @ba
 
266
 **/
 
267
void
 
268
e2k_rule_append_unicode (GByteArray *ba, const char *str)
 
269
{
 
270
        gunichar2 *utf16;
 
271
        int i;
 
272
 
 
273
        utf16 = g_utf8_to_utf16 (str, -1, NULL, NULL, NULL);
 
274
        g_return_if_fail (utf16 != NULL);
 
275
 
 
276
        for (i = 0; utf16[i]; i++)
 
277
                e2k_rule_append_uint16 (ba, utf16[i]);
 
278
        e2k_rule_append_uint16 (ba, 0);
 
279
        g_free (utf16);
 
280
}
 
281
 
 
282
/**
 
283
 * e2k_rule_extract_unicode:
 
284
 * @ptr: pointer to a pointer into a binary rule
 
285
 * @len: pointer to the remaining length of *@ptr
 
286
 * @str: pointer to a string pointer
 
287
 *
 
288
 * Reads a Unicode-encoded string from the rule at **@ptr into *@str
 
289
 * and updates *@ptr and *@len accordingly.
 
290
 *
 
291
 * Return value: success or failure
 
292
 **/
 
293
gboolean
 
294
e2k_rule_extract_unicode (guint8 **ptr, int *len, char **str)
 
295
{
 
296
        guint8 *start, *end;
 
297
        gunichar2 *utf16;
 
298
 
 
299
        start = *ptr;
 
300
        end = *ptr + *len;
 
301
 
 
302
        for (; *ptr < end - 1; (*ptr) += 2) {
 
303
                if ((*ptr)[0] == '\0' && (*ptr)[1] == '\0') {
 
304
                        *ptr += 2;
 
305
                        *len -= *ptr - start;
 
306
 
 
307
                        utf16 = g_memdup (start, *ptr - start);
 
308
                        *str = g_utf16_to_utf8 (utf16, -1, NULL, NULL, NULL);
 
309
                        g_free (utf16);
 
310
                        return TRUE;
 
311
                }
 
312
        }
 
313
        return FALSE;
 
314
}
 
315
 
 
316
/**
 
317
 * e2k_rule_append_binary:
 
318
 * @ba: a byte array containing a binary rule
 
319
 * @data: binary data
 
320
 *
 
321
 * Appends @data (with a 2-byte length prefix) to the rule in @ba
 
322
 **/
 
323
void
 
324
e2k_rule_append_binary (GByteArray *ba, GByteArray *data)
 
325
{
 
326
        e2k_rule_append_uint16 (ba, data->len);
 
327
        g_byte_array_append (ba, data->data, data->len);
 
328
}
 
329
 
 
330
/**
 
331
 * e2k_rule_extract_binary:
 
332
 * @ptr: pointer to a pointer into a binary rule
 
333
 * @len: pointer to the remaining length of *@ptr
 
334
 * @data: pointer to a #GByteArray
 
335
 *
 
336
 * Reads binary data (preceded by a 2-byte length) from the rule at
 
337
 * **@ptr into *@data and updates *@ptr and *@len accordingly.
 
338
 *
 
339
 * Return value: success or failure
 
340
 **/
 
341
gboolean
 
342
e2k_rule_extract_binary (guint8 **ptr, int *len, GByteArray **data)
 
343
{
 
344
        guint16 datalen;
 
345
 
 
346
        if (!e2k_rule_extract_uint16 (ptr, len, &datalen))
 
347
                return FALSE;
 
348
        if (*len < datalen)
 
349
                return FALSE;
 
350
 
 
351
        *data = g_byte_array_sized_new (datalen);
 
352
        memcpy ((*data)->data, *ptr, datalen);
 
353
        (*data)->len = datalen;
 
354
 
 
355
        *ptr += datalen;
 
356
        *len -= datalen;
 
357
        return TRUE;
 
358
}
 
359
 
 
360
#define E2K_PT_UNICODE_RULE 0x84b0
 
361
 
 
362
/**
 
363
 * e2k_rule_append_proptag:
 
364
 * @ba: a byte array containing a binary rule
 
365
 * @prop: an #E2kRuleProp
 
366
 *
 
367
 * Appends a representation of @prop to the rule in @ba
 
368
 **/
 
369
void
 
370
e2k_rule_append_proptag (GByteArray *ba, E2kRuleProp *prop)
 
371
{
 
372
        guint32 proptag = prop->proptag;
 
373
 
 
374
        if (E2K_PROPTAG_TYPE (proptag) == E2K_PT_STRING8 ||
 
375
            E2K_PROPTAG_TYPE (proptag) == E2K_PT_UNICODE)
 
376
                proptag = E2K_PROPTAG_ID (proptag) | E2K_PT_UNICODE_RULE;
 
377
 
 
378
        e2k_rule_append_uint32 (ba, proptag);
 
379
}
 
380
 
 
381
/**
 
382
 * e2k_rule_extract_proptag:
 
383
 * @ptr: pointer to a pointer into a binary rule
 
384
 * @len: pointer to the remaining length of *@ptr
 
385
 * @prop: poitner to an #E2kRuleProp
 
386
 *
 
387
 * Reads a proptag from the rule at **@ptr into *@prop and updates
 
388
 * *@ptr and *@len accordingly.
 
389
 *
 
390
 * Return value: success or failure
 
391
 **/
 
392
gboolean
 
393
e2k_rule_extract_proptag (guint8 **ptr, int *len, E2kRuleProp *prop)
 
394
{
 
395
        if (!e2k_rule_extract_uint32 (ptr, len, &prop->proptag))
 
396
                return FALSE;
 
397
 
 
398
        if (E2K_PROPTAG_TYPE (prop->proptag) == E2K_PT_UNICODE_RULE)
 
399
                prop->proptag = E2K_PROPTAG_ID (prop->proptag) | E2K_PT_UNICODE;
 
400
        prop->name = e2k_proptag_prop (prop->proptag);
 
401
 
 
402
        return TRUE;
 
403
}
 
404
 
 
405
 
 
406
/**
 
407
 * e2k_rule_append_propvalue:
 
408
 * @ba: a byte array containing a binary rule
 
409
 * @pv: an #E2kPropValue
 
410
 *
 
411
 * Appends a representation of @pv (the proptag and its value) to the
 
412
 * rule in @ba
 
413
 **/
 
414
void
 
415
e2k_rule_append_propvalue (GByteArray *ba, E2kPropValue *pv)
 
416
{
 
417
        g_return_if_fail (pv->prop.proptag != 0);
 
418
 
 
419
        e2k_rule_append_proptag (ba, &pv->prop);
 
420
 
 
421
        switch (E2K_PROPTAG_TYPE (pv->prop.proptag)) {
 
422
        case E2K_PT_UNICODE:
 
423
        case E2K_PT_STRING8:
 
424
                e2k_rule_append_unicode (ba, pv->value);
 
425
                break;
 
426
 
 
427
        case E2K_PT_BINARY:
 
428
                e2k_rule_append_binary (ba, pv->value);
 
429
                break;
 
430
 
 
431
        case E2K_PT_LONG:
 
432
                e2k_rule_append_uint32 (ba, GPOINTER_TO_UINT (pv->value));
 
433
                break;
 
434
 
 
435
        case E2K_PT_BOOLEAN:
 
436
                e2k_rule_append_byte (ba, GPOINTER_TO_UINT (pv->value));
 
437
                break;
 
438
 
 
439
        default:
 
440
                /* FIXME */
 
441
                break;
 
442
        }
 
443
}
 
444
 
 
445
/**
 
446
 * e2k_rule_extract_propvalue:
 
447
 * @ptr: pointer to a pointer into a binary rule
 
448
 * @len: pointer to the remaining length of *@ptr
 
449
 * @pv: pointer to an #E2kPropValue
 
450
 *
 
451
 * Reads a representation of an #E2kPropValue from the rule at **@ptr
 
452
 * into *@pv and updates *@ptr and *@len accordingly.
 
453
 *
 
454
 * Return value: success or failure
 
455
 **/
 
456
gboolean
 
457
e2k_rule_extract_propvalue (guint8 **ptr, int *len, E2kPropValue *pv)
 
458
{
 
459
        if (!e2k_rule_extract_proptag (ptr, len, &pv->prop))
 
460
                return FALSE;
 
461
 
 
462
        switch (E2K_PROPTAG_TYPE (pv->prop.proptag)) {
 
463
        case E2K_PT_UNICODE:
 
464
        case E2K_PT_STRING8:
 
465
                pv->type = E2K_PROP_TYPE_STRING;
 
466
                return e2k_rule_extract_unicode (ptr, len, (char **)&pv->value);
 
467
 
 
468
        case E2K_PT_BINARY:
 
469
                pv->type = E2K_PROP_TYPE_BINARY;
 
470
                return e2k_rule_extract_binary (ptr, len, (GByteArray **)&pv->value);
 
471
 
 
472
        case E2K_PT_SYSTIME:
 
473
        {
 
474
                guint64 temp;
 
475
 
 
476
                if (*len < 8)
 
477
                        return FALSE;
 
478
 
 
479
                memcpy (&temp, *ptr, 8);
 
480
                *ptr += 8;
 
481
                *len -= 8;
 
482
 
 
483
                temp = GUINT64_FROM_LE (temp);
 
484
                pv->type = E2K_PROP_TYPE_DATE;
 
485
                pv->value = e2k_make_timestamp (e2k_filetime_to_time_t (temp));
 
486
                return TRUE;
 
487
        }
 
488
 
 
489
        case E2K_PT_LONG:
 
490
        {
 
491
                guint32 temp;
 
492
 
 
493
                if (!e2k_rule_extract_uint32 (ptr, len, &temp))
 
494
                        return FALSE;
 
495
                pv->type = E2K_PROP_TYPE_INT;
 
496
                pv->value = GUINT_TO_POINTER (temp);
 
497
                return TRUE;
 
498
        }
 
499
 
 
500
        case E2K_PT_BOOLEAN:
 
501
        {
 
502
                guint8 temp;
 
503
 
 
504
                if (!e2k_rule_extract_byte (ptr, len, &temp))
 
505
                        return FALSE;
 
506
                pv->type = E2K_PROP_TYPE_BOOL;
 
507
                pv->value = GUINT_TO_POINTER ((guint)temp);
 
508
                return TRUE;
 
509
        }
 
510
 
 
511
        default:
 
512
                /* FIXME */
 
513
                return FALSE;
 
514
        }
 
515
}
 
516
 
 
517
/**
 
518
 * e2k_rule_free_propvalue:
 
519
 * @pv: an #E2kPropValue
 
520
 *
 
521
 * Frees @pv
 
522
 **/
 
523
void
 
524
e2k_rule_free_propvalue (E2kPropValue *pv)
 
525
{
 
526
        if (pv->type == E2K_PROP_TYPE_STRING ||
 
527
            pv->type == E2K_PROP_TYPE_DATE)
 
528
                g_free (pv->value);
 
529
        else if (pv->type == E2K_PROP_TYPE_BINARY && pv->value)
 
530
                g_byte_array_free (pv->value, TRUE);
 
531
}
 
532
 
 
533
 
 
534
/**
 
535
 * e2k_rule_free:
 
536
 * @rule: an #E2kRule
 
537
 *
 
538
 * Frees @rule
 
539
 **/
 
540
void
 
541
e2k_rule_free (E2kRule *rule)
 
542
{
 
543
        if (rule->name)
 
544
                g_free (rule->name);
 
545
        if (rule->condition)
 
546
                e2k_restriction_unref (rule->condition);
 
547
        if (rule->actions)
 
548
                e2k_actions_free (rule->actions);
 
549
        if (rule->provider)
 
550
                g_free (rule->provider);
 
551
        if (rule->provider_data)
 
552
                g_byte_array_free (rule->provider_data, TRUE);
 
553
}
 
554
 
 
555
/**
 
556
 * e2k_rules_free:
 
557
 * @rules: an #E2kRules structure
 
558
 *
 
559
 * Frees @rules and the rules it contains
 
560
 **/
 
561
void
 
562
e2k_rules_free (E2kRules *rules)
 
563
{
 
564
        int i;
 
565
 
 
566
        for (i = 0; i < rules->rules->len; i++)
 
567
                e2k_rule_free (rules->rules->pdata[i]);
 
568
        g_ptr_array_free (rules->rules, TRUE);
 
569
        g_free (rules);
 
570
}
 
571
 
 
572
/**
 
573
 * e2k_rules_from_binary:
 
574
 * @rules_data: binary-encoded rules data
 
575
 *
 
576
 * Extract rules from @rules_data and returns them in an #E2kRules
 
577
 * structure.
 
578
 *
 
579
 * Return value: the rules, or %NULL on error.
 
580
 **/
 
581
E2kRules *
 
582
e2k_rules_from_binary (GByteArray *rules_data)
 
583
{
 
584
        guint8 *data;
 
585
        int len, i;
 
586
        guint32 nrules, pdlen;
 
587
        E2kRules *rules;
 
588
        E2kRule *rule;
 
589
 
 
590
        data = rules_data->data;
 
591
        len = rules_data->len;
 
592
 
 
593
        if (len < 9)
 
594
                return NULL;
 
595
        if (*data != 2)
 
596
                return NULL;
 
597
        data++;
 
598
        len--;
 
599
 
 
600
        rules = g_new0 (E2kRules, 1);
 
601
        rules->version = 2;
 
602
 
 
603
        if (!e2k_rule_extract_uint32 (&data, &len, &nrules) ||
 
604
            !e2k_rule_extract_uint32 (&data, &len, &rules->codepage)) {
 
605
                g_free (rules);
 
606
                return NULL;
 
607
        }
 
608
 
 
609
        rules->rules = g_ptr_array_new ();
 
610
        for (i = 0; i < nrules; i++) {
 
611
                rule = g_new0 (E2kRule, 1);
 
612
                g_ptr_array_add (rules->rules, rule);
 
613
 
 
614
                if (!e2k_rule_extract_uint32 (&data, &len, &rule->sequence) ||
 
615
                    !e2k_rule_extract_uint32 (&data, &len, &rule->state) ||
 
616
                    !e2k_rule_extract_uint32 (&data, &len, &rule->user_flags) ||
 
617
                    !e2k_rule_extract_uint32 (&data, &len, &rule->condition_lcid) ||
 
618
                    !e2k_restriction_extract (&data, &len, &rule->condition) ||
 
619
                    !e2k_actions_extract (&data, &len, &rule->actions) ||
 
620
                    !e2k_rule_extract_string (&data, &len, &rule->provider) ||
 
621
                    !e2k_rule_extract_string (&data, &len, &rule->name) ||
 
622
                    !e2k_rule_extract_uint32 (&data, &len, &rule->level))
 
623
                        goto error;
 
624
 
 
625
                /* The provider data has a 4-byte length, unlike the
 
626
                 * binary fields in a condition or rule.
 
627
                 */
 
628
                if (!e2k_rule_extract_uint32 (&data, &len, &pdlen))
 
629
                        goto error;
 
630
                if (len < pdlen)
 
631
                        goto error;
 
632
                rule->provider_data = g_byte_array_sized_new (pdlen);
 
633
                rule->provider_data->len = pdlen;
 
634
                memcpy (rule->provider_data->data, data, pdlen);
 
635
                data += pdlen;
 
636
                len -= pdlen;
 
637
        }
 
638
 
 
639
        return rules;
 
640
 
 
641
 error:
 
642
        e2k_rules_free (rules);
 
643
        return NULL;
 
644
}
 
645
 
 
646
/**
 
647
 * e2k_rules_to_binary:
 
648
 * @rules: an #E2kRules structure
 
649
 *
 
650
 * Encodes @rules into binary form
 
651
 *
 
652
 * Return value: the binary-encoded rules
 
653
 **/
 
654
GByteArray *
 
655
e2k_rules_to_binary (E2kRules *rules)
 
656
{
 
657
        GByteArray *ba;
 
658
        E2kRule *rule;
 
659
        int i;
 
660
 
 
661
        ba = g_byte_array_new ();
 
662
        e2k_rule_append_byte (ba, rules->version);
 
663
        e2k_rule_append_uint32 (ba, rules->rules->len);
 
664
        e2k_rule_append_uint32 (ba, rules->codepage);
 
665
 
 
666
        for (i = 0; i < rules->rules->len; i++) {
 
667
                rule = rules->rules->pdata[i];
 
668
 
 
669
                e2k_rule_append_uint32 (ba, rule->sequence);
 
670
                e2k_rule_append_uint32 (ba, rule->state);
 
671
                e2k_rule_append_uint32 (ba, rule->user_flags);
 
672
                e2k_rule_append_uint32 (ba, rule->condition_lcid);
 
673
                e2k_restriction_append (ba, rule->condition);
 
674
                e2k_actions_append (ba, rule->actions);
 
675
                e2k_rule_append_string (ba, rule->provider);
 
676
                e2k_rule_append_string (ba, rule->name);
 
677
                e2k_rule_append_uint32 (ba, rule->level);
 
678
 
 
679
                /* The provider data has a 4-byte length, unlike the
 
680
                 * binary fields in a condition or rule.
 
681
                 */
 
682
                e2k_rule_append_uint32 (ba, rule->provider_data->len);
 
683
                g_byte_array_append (ba, rule->provider_data->data,
 
684
                                     rule->provider_data->len);
 
685
        }
 
686
 
 
687
        return ba;
 
688
}