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., 51 Franklin Street, Fifth Floor,
17 * Boston, MA 02110-1301, 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);