1
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
3
/* Copyright (C) 2003, 2004 Novell, Inc.
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.
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.
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.
27
#include "e2k-action.h"
28
#include "e2k-properties.h"
29
#include "e2k-propnames.h"
30
#include "e2k-utils.h"
34
* @prop: an #E2kRuleProp
35
* @propname: a MAPI property name
37
* This is a convenience function to set both the %name and %proptag
41
e2k_rule_prop_set (E2kRuleProp *prop, const char *propname)
43
prop->name = propname;
44
prop->proptag = e2k_prop_proptag (propname);
48
* e2k_rule_write_uint32:
49
* @ptr: pointer into a binary rule
50
* @val: a uint32 value
52
* Writes @val into the rule at @ptr
55
e2k_rule_write_uint32 (guint8 *ptr, guint32 val)
57
*ptr++ = ( val & 0xFF);
58
*ptr++ = ((val >> 8) & 0xFF);
59
*ptr++ = ((val >> 16) & 0xFF);
60
*ptr++ = ((val >> 24) & 0xFF);
64
* e2k_rule_append_uint32:
65
* @ba: a byte array containing a binary rule
66
* @val: a uint32 value
68
* Appends @val to the rule in @ba
71
e2k_rule_append_uint32 (GByteArray *ba, guint32 val)
73
g_byte_array_set_size (ba, ba->len + 4);
74
e2k_rule_write_uint32 (ba->data + ba->len - 4, val);
78
* e2k_rule_read_uint32:
79
* @ptr: pointer into a binary rule
81
* Reads a uint32 value from the rule at @ptr
83
* Return value: the uint32 value
86
e2k_rule_read_uint32 (guint8 *ptr)
88
return ptr[0] | (ptr[1] << 8) | (ptr[2] << 16) | (ptr[3] << 24);
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
97
* Reads a uint32 value from the rule at **@ptr into *@val and updates
98
* *@ptr and *@len accordingly.
100
* Return value: success or failure
103
e2k_rule_extract_uint32 (guint8 **ptr, int *len, guint32 *val)
108
*val = e2k_rule_read_uint32 (*ptr);
116
* e2k_rule_write_uint16:
117
* @ptr: pointer into a binary rule
118
* @val: a uint16 value
120
* Writes @val into the rule at @ptr
123
e2k_rule_write_uint16 (guint8 *ptr, guint16 val)
125
*ptr++ = ( val & 0xFF);
126
*ptr++ = ((val >> 8) & 0xFF);
130
* e2k_rule_append_uint16:
131
* @ba: a byte array containing a binary rule
132
* @val: a uint16 value
134
* Appends @val to the rule in @ba
137
e2k_rule_append_uint16 (GByteArray *ba, guint16 val)
139
g_byte_array_set_size (ba, ba->len + 2);
140
e2k_rule_write_uint16 (ba->data + ba->len - 2, val);
144
* e2k_rule_read_uint16:
145
* @ptr: pointer into a binary rule
147
* Reads a uint16 value from the rule at @ptr
149
* Return value: the uint16 value
152
e2k_rule_read_uint16 (guint8 *ptr)
154
return ptr[0] | (ptr[1] << 8);
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
163
* Reads a uint16 value from the rule at **@ptr into *@val and updates
164
* *@ptr and *@len accordingly.
166
* Return value: success or failure
169
e2k_rule_extract_uint16 (guint8 **ptr, int *len, guint16 *val)
174
*val = e2k_rule_read_uint16 (*ptr);
182
* e2k_rule_append_byte:
183
* @ba: a byte array containing a binary rule
186
* Appends @val to the rule in @ba
189
e2k_rule_append_byte (GByteArray *ba, guint8 val)
191
g_byte_array_append (ba, &val, 1);
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
200
* Reads a byte value from the rule at **@ptr into *@val and updates
201
* *@ptr and *@len accordingly.
203
* Return value: success or failure
206
e2k_rule_extract_byte (guint8 **ptr, int *len, guint8 *val)
219
* e2k_rule_append_string:
220
* @ba: a byte array containing a binary rule
221
* @str: a (Windows) locale-encoded string
223
* Appends @str to the rule in @ba
226
e2k_rule_append_string (GByteArray *ba, const char *str)
228
/* FIXME: verify encoding */
229
g_byte_array_append (ba, str, strlen (str) + 1);
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
238
* Reads a (Windows) locale-encoded string from the rule at **@ptr
239
* into *@str and updates *@ptr and *@len accordingly.
241
* Return value: success or failure
244
e2k_rule_extract_string (guint8 **ptr, int *len, char **str)
248
for (slen = 0; slen < *len; slen++) {
249
if ((*ptr)[slen] == '\0') {
250
*str = g_strdup (*ptr);
261
* e2k_rule_append_unicode:
262
* @ba: a byte array containing a binary rule
263
* @str: a UTF-8 string
265
* Appends @str to the rule in @ba
268
e2k_rule_append_unicode (GByteArray *ba, const char *str)
273
utf16 = g_utf8_to_utf16 (str, -1, NULL, NULL, NULL);
274
g_return_if_fail (utf16 != NULL);
276
for (i = 0; utf16[i]; i++)
277
e2k_rule_append_uint16 (ba, utf16[i]);
278
e2k_rule_append_uint16 (ba, 0);
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
288
* Reads a Unicode-encoded string from the rule at **@ptr into *@str
289
* and updates *@ptr and *@len accordingly.
291
* Return value: success or failure
294
e2k_rule_extract_unicode (guint8 **ptr, int *len, char **str)
302
for (; *ptr < end - 1; (*ptr) += 2) {
303
if ((*ptr)[0] == '\0' && (*ptr)[1] == '\0') {
305
*len -= *ptr - start;
307
utf16 = g_memdup (start, *ptr - start);
308
*str = g_utf16_to_utf8 (utf16, -1, NULL, NULL, NULL);
317
* e2k_rule_append_binary:
318
* @ba: a byte array containing a binary rule
321
* Appends @data (with a 2-byte length prefix) to the rule in @ba
324
e2k_rule_append_binary (GByteArray *ba, GByteArray *data)
326
e2k_rule_append_uint16 (ba, data->len);
327
g_byte_array_append (ba, data->data, data->len);
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
336
* Reads binary data (preceded by a 2-byte length) from the rule at
337
* **@ptr into *@data and updates *@ptr and *@len accordingly.
339
* Return value: success or failure
342
e2k_rule_extract_binary (guint8 **ptr, int *len, GByteArray **data)
346
if (!e2k_rule_extract_uint16 (ptr, len, &datalen))
351
*data = g_byte_array_sized_new (datalen);
352
memcpy ((*data)->data, *ptr, datalen);
353
(*data)->len = datalen;
360
#define E2K_PT_UNICODE_RULE 0x84b0
363
* e2k_rule_append_proptag:
364
* @ba: a byte array containing a binary rule
365
* @prop: an #E2kRuleProp
367
* Appends a representation of @prop to the rule in @ba
370
e2k_rule_append_proptag (GByteArray *ba, E2kRuleProp *prop)
372
guint32 proptag = prop->proptag;
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;
378
e2k_rule_append_uint32 (ba, proptag);
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
387
* Reads a proptag from the rule at **@ptr into *@prop and updates
388
* *@ptr and *@len accordingly.
390
* Return value: success or failure
393
e2k_rule_extract_proptag (guint8 **ptr, int *len, E2kRuleProp *prop)
395
if (!e2k_rule_extract_uint32 (ptr, len, &prop->proptag))
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);
407
* e2k_rule_append_propvalue:
408
* @ba: a byte array containing a binary rule
409
* @pv: an #E2kPropValue
411
* Appends a representation of @pv (the proptag and its value) to the
415
e2k_rule_append_propvalue (GByteArray *ba, E2kPropValue *pv)
417
g_return_if_fail (pv->prop.proptag != 0);
419
e2k_rule_append_proptag (ba, &pv->prop);
421
switch (E2K_PROPTAG_TYPE (pv->prop.proptag)) {
424
e2k_rule_append_unicode (ba, pv->value);
428
e2k_rule_append_binary (ba, pv->value);
432
e2k_rule_append_uint32 (ba, GPOINTER_TO_UINT (pv->value));
436
e2k_rule_append_byte (ba, GPOINTER_TO_UINT (pv->value));
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
451
* Reads a representation of an #E2kPropValue from the rule at **@ptr
452
* into *@pv and updates *@ptr and *@len accordingly.
454
* Return value: success or failure
457
e2k_rule_extract_propvalue (guint8 **ptr, int *len, E2kPropValue *pv)
459
if (!e2k_rule_extract_proptag (ptr, len, &pv->prop))
462
switch (E2K_PROPTAG_TYPE (pv->prop.proptag)) {
465
pv->type = E2K_PROP_TYPE_STRING;
466
return e2k_rule_extract_unicode (ptr, len, (char **)&pv->value);
469
pv->type = E2K_PROP_TYPE_BINARY;
470
return e2k_rule_extract_binary (ptr, len, (GByteArray **)&pv->value);
479
memcpy (&temp, *ptr, 8);
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));
493
if (!e2k_rule_extract_uint32 (ptr, len, &temp))
495
pv->type = E2K_PROP_TYPE_INT;
496
pv->value = GUINT_TO_POINTER (temp);
504
if (!e2k_rule_extract_byte (ptr, len, &temp))
506
pv->type = E2K_PROP_TYPE_BOOL;
507
pv->value = GUINT_TO_POINTER ((guint)temp);
518
* e2k_rule_free_propvalue:
519
* @pv: an #E2kPropValue
524
e2k_rule_free_propvalue (E2kPropValue *pv)
526
if (pv->type == E2K_PROP_TYPE_STRING ||
527
pv->type == E2K_PROP_TYPE_DATE)
529
else if (pv->type == E2K_PROP_TYPE_BINARY && pv->value)
530
g_byte_array_free (pv->value, TRUE);
541
e2k_rule_free (E2kRule *rule)
546
e2k_restriction_unref (rule->condition);
548
e2k_actions_free (rule->actions);
550
g_free (rule->provider);
551
if (rule->provider_data)
552
g_byte_array_free (rule->provider_data, TRUE);
557
* @rules: an #E2kRules structure
559
* Frees @rules and the rules it contains
562
e2k_rules_free (E2kRules *rules)
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);
573
* e2k_rules_from_binary:
574
* @rules_data: binary-encoded rules data
576
* Extract rules from @rules_data and returns them in an #E2kRules
579
* Return value: the rules, or %NULL on error.
582
e2k_rules_from_binary (GByteArray *rules_data)
586
guint32 nrules, pdlen;
590
data = rules_data->data;
591
len = rules_data->len;
600
rules = g_new0 (E2kRules, 1);
603
if (!e2k_rule_extract_uint32 (&data, &len, &nrules) ||
604
!e2k_rule_extract_uint32 (&data, &len, &rules->codepage)) {
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);
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))
625
/* The provider data has a 4-byte length, unlike the
626
* binary fields in a condition or rule.
628
if (!e2k_rule_extract_uint32 (&data, &len, &pdlen))
632
rule->provider_data = g_byte_array_sized_new (pdlen);
633
rule->provider_data->len = pdlen;
634
memcpy (rule->provider_data->data, data, pdlen);
642
e2k_rules_free (rules);
647
* e2k_rules_to_binary:
648
* @rules: an #E2kRules structure
650
* Encodes @rules into binary form
652
* Return value: the binary-encoded rules
655
e2k_rules_to_binary (E2kRules *rules)
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);
666
for (i = 0; i < rules->rules->len; i++) {
667
rule = rules->rules->pdata[i];
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);
679
/* The provider data has a 4-byte length, unlike the
680
* binary fields in a condition or rule.
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);