1
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
3
/* Copyright (C) 2001-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.
20
/* e2k-restriction.c: message restrictions (WHERE clauses / Rule conditions) */
26
#include "e2k-restriction.h"
27
#include "e2k-properties.h"
33
static E2kRestriction *
34
conjoin (E2kRestrictionType type, gint nrns, E2kRestriction **rns, gboolean unref)
36
E2kRestriction *ret = g_new0 (E2kRestriction, 1);
40
ret->res.and.nrns = nrns;
41
ret->res.and.rns = g_new (E2kRestriction *, nrns);
42
for (i = 0; i < nrns; i++) {
43
ret->res.and.rns[i] = rns[i];
45
e2k_restriction_ref (rns[i]);
52
* e2k_restriction_and:
53
* @nrns: length of @rns
54
* @rns: an array of #E2kRestriction
55
* @unref: whether or not to unref the restrictions when it is done
57
* Creates a new restriction which is true if all of the restrictions
60
* If @unref is %TRUE, then e2k_restriction_and() is essentially
61
* stealing the caller's references on the restrictions. If it is
62
* %FALSE, then e2k_restriction_and() will acquire its own references
63
* to each of the restrictions.
65
* Return value: the new restriction
68
e2k_restriction_and (gint nrns, E2kRestriction **rns, gboolean unref)
70
return conjoin (E2K_RESTRICTION_AND, nrns, rns, unref);
75
* @nrns: length of @rns
76
* @rns: an array of #E2kRestriction
77
* @unref: see e2k_restriction_and()
79
* Creates a new restriction which is true if any of the restrictions
82
* Return value: the new restriction
85
e2k_restriction_or (gint nrns, E2kRestriction **rns, gboolean unref)
87
return conjoin (E2K_RESTRICTION_OR, nrns, rns, unref);
90
static E2kRestriction *
91
conjoinv (E2kRestrictionType type, E2kRestriction *rn, va_list ap)
93
E2kRestriction *ret = g_new0 (E2kRestriction, 1);
96
rns = g_ptr_array_new ();
98
g_ptr_array_add (rns, rn);
99
rn = va_arg (ap, E2kRestriction *);
104
ret->res.and.nrns = rns->len;
105
ret->res.and.rns = (E2kRestriction **)rns->pdata;
106
g_ptr_array_free (rns, FALSE);
112
* e2k_restriction_andv:
113
* @rn: an #E2kRestriction
114
* @...: a %NULL-terminated list of additional #E2kRestrictions
116
* Creates a new restriction which is true if all of the passed-in
117
* restrictions are true. e2k_restriction_andv() steals the caller's
118
* reference on each of the passed-in restrictions.
120
* Return value: the new restriction
123
e2k_restriction_andv (E2kRestriction *rn, ...)
128
return conjoinv (E2K_RESTRICTION_AND, rn, ap);
132
* e2k_restriction_orv:
133
* @rn: an #E2kRestriction
134
* @...: a %NULL-terminated list of additional #E2kRestrictions
136
* Creates a new restriction which is true if any of the passed-in
137
* restrictions are true. e2k_restriction_orv() steals the caller's
138
* reference on each of the passed-in restrictions.
140
* Return value: the new restriction
143
e2k_restriction_orv (E2kRestriction *rn, ...)
148
return conjoinv (E2K_RESTRICTION_OR, rn, ap);
152
* e2k_restriction_not:
153
* @rn: an #E2kRestriction
154
* @unref: see e2k_restriction_and()
156
* Creates a new restriction which is true if @rn is false.
158
* Return value: the new restriction
161
e2k_restriction_not (E2kRestriction *rn, gboolean unref)
163
E2kRestriction *ret = g_new0 (E2kRestriction, 1);
165
ret->type = E2K_RESTRICTION_NOT;
166
ret->res.not.rn = rn;
168
e2k_restriction_ref (rn);
174
* e2k_restriction_content:
175
* @propname: text property to compare against
176
* @fuzzy_level: how to compare
177
* @value: value to compare against
179
* Creates a new restriction that is true for objects where the
180
* indicated property's value matches @value according to @fuzzy_level.
182
* For a WebDAV SEARCH, @fuzzy_level should be %E2K_FL_FULLSTRING,
183
* %E2K_FL_SUBSTRING, %E2K_FL_PREFIX, or %E2K_FL_SUFFIX.
185
* For a MAPI restriction, @fuzzy_level may not be %E2K_FL_SUFFIX, but
186
* may be ORed with any of the additional values %E2K_FL_IGNORECASE,
187
* %E2K_FL_IGNORENONSPACE, or %E2K_FL_LOOSE.
189
* To compare a property's sort order to another string, use
190
* e2k_restriction_prop_string().
192
* Return value: the new restriction
195
e2k_restriction_content (const gchar *propname,
196
E2kRestrictionFuzzyLevel fuzzy_level,
199
E2kRestriction *ret = g_new0 (E2kRestriction, 1);
201
ret->type = E2K_RESTRICTION_CONTENT;
202
ret->res.content.fuzzy_level = fuzzy_level;
203
e2k_rule_prop_set (&ret->res.content.pv.prop, propname);
204
ret->res.content.pv.type = E2K_PROP_TYPE_STRING;
205
ret->res.content.pv.value = g_strdup (value);
211
* e2k_restriction_prop_bool:
212
* @propname: boolean property to compare against
213
* @relop: %E2K_RELOP_EQ or %E2K_RELOP_NE
214
* @value: %TRUE or %FALSE
216
* Creates a new restriction that is true for objects where the
217
* indicated property matches @relop and @value.
219
* Return value: the new restriction
222
e2k_restriction_prop_bool (const gchar *propname, E2kRestrictionRelop relop,
225
E2kRestriction *ret = g_new0 (E2kRestriction, 1);
227
ret->type = E2K_RESTRICTION_PROPERTY;
228
ret->res.property.relop = relop;
229
e2k_rule_prop_set (&ret->res.property.pv.prop, propname);
230
ret->res.property.pv.type = E2K_PROP_TYPE_BOOL;
231
ret->res.property.pv.value = GUINT_TO_POINTER (value);
237
* e2k_restriction_prop_int:
238
* @propname: integer property to compare against
239
* @relop: an #E2kRestrictionRelop
240
* @value: number to compare against
242
* Creates a new restriction that is true for objects where the
243
* indicated property matches @value according to @relop.
245
* Return value: the new restriction
248
e2k_restriction_prop_int (const gchar *propname, E2kRestrictionRelop relop,
251
E2kRestriction *ret = g_new0 (E2kRestriction, 1);
253
ret->type = E2K_RESTRICTION_PROPERTY;
254
ret->res.property.relop = relop;
255
e2k_rule_prop_set (&ret->res.property.pv.prop, propname);
256
ret->res.property.pv.type = E2K_PROP_TYPE_INT;
257
ret->res.property.pv.value = GINT_TO_POINTER (value);
263
* e2k_restriction_prop_date:
264
* @propname: date/time property to compare against
265
* @relop: an #E2kRestrictionRelop
266
* @value: date/time to compare against (as returned by e2k_make_timestamp())
268
* Creates a new restriction that is true for objects where the
269
* indicated property matches @value according to @relop.
271
* Return value: the new restriction
274
e2k_restriction_prop_date (const gchar *propname, E2kRestrictionRelop relop,
277
E2kRestriction *ret = g_new0 (E2kRestriction, 1);
279
ret->type = E2K_RESTRICTION_PROPERTY;
280
ret->res.property.relop = relop;
281
e2k_rule_prop_set (&ret->res.property.pv.prop, propname);
282
ret->res.property.pv.type = E2K_PROP_TYPE_DATE;
283
ret->res.property.pv.value = g_strdup (value);
289
* e2k_restriction_prop_string:
290
* @propname: text property to compare against
291
* @relop: an #E2kRestrictionRelop
292
* @value: text to compare against
294
* Creates a new restriction that is true for objects where the
295
* indicated property matches @value according to @relop.
297
* To do a substring match, use e2k_restriction_content().
299
* Return value: the new restriction
302
e2k_restriction_prop_string (const gchar *propname, E2kRestrictionRelop relop,
305
E2kRestriction *ret = g_new0 (E2kRestriction, 1);
307
ret->type = E2K_RESTRICTION_PROPERTY;
308
ret->res.property.relop = relop;
309
e2k_rule_prop_set (&ret->res.property.pv.prop, propname);
310
ret->res.property.pv.type = E2K_PROP_TYPE_STRING;
311
ret->res.property.pv.value = g_strdup (value);
317
* e2k_restriction_prop_binary:
318
* @propname: binary property to compare against
319
* @relop: %E2K_RELOP_EQ or %E2K_RELOP_NE
320
* @data: data to compare against
321
* @len: length of @data
323
* Creates a new restriction that is true for objects where the
324
* indicated property matches @value according to @relop.
326
* Return value: the new restriction
329
e2k_restriction_prop_binary (const gchar *propname, E2kRestrictionRelop relop,
330
gconstpointer data, gint len)
332
E2kRestriction *ret = g_new0 (E2kRestriction, 1);
334
ret->type = E2K_RESTRICTION_PROPERTY;
335
ret->res.property.relop = relop;
336
e2k_rule_prop_set (&ret->res.property.pv.prop, propname);
337
ret->res.property.pv.type = E2K_PROP_TYPE_BINARY;
338
ret->res.property.pv.value = g_byte_array_new ();
339
g_byte_array_append (ret->res.property.pv.value, data, len);
345
* e2k_restriction_compare:
346
* @propname1: first property
347
* @relop: an #E2kRestrictionRelop
348
* @propname2: second property
350
* Creates a new restriction which is true for objects where
351
* @propname1 and @propname2 have the relationship described by
354
* Return value: the new restriction
357
e2k_restriction_compare (const gchar *propname1, E2kRestrictionRelop relop,
358
const gchar *propname2)
360
E2kRestriction *ret = g_new0 (E2kRestriction, 1);
362
ret->type = E2K_RESTRICTION_COMPAREPROPS;
363
ret->res.compare.relop = relop;
364
e2k_rule_prop_set (&ret->res.compare.prop1, propname1);
365
e2k_rule_prop_set (&ret->res.compare.prop2, propname2);
371
* e2k_restriction_bitmask:
372
* @propname: integer property to compare
373
* @bitop: an #E2kRestrictionBitop
374
* @mask: mask of bits to compare against
376
* Creates a new restriction that is true for objects where the
377
* indicated bits of the value of @propname either are or aren't zero,
378
* as indicated by @bitop.
380
* This cannot be used for WebDAV SEARCH restrictions.
382
* Return value: the new restriction
385
e2k_restriction_bitmask (const gchar *propname, E2kRestrictionBitop bitop,
388
E2kRestriction *ret = g_new0 (E2kRestriction, 1);
390
ret->type = E2K_RESTRICTION_BITMASK;
391
ret->res.bitmask.bitop = bitop;
392
e2k_rule_prop_set (&ret->res.bitmask.prop, propname);
393
ret->res.bitmask.mask = mask;
399
* e2k_restriction_size:
400
* @propname: property to compare
401
* @relop: an #E2kRestrictionRelop
402
* @size: the size to compare @propname to
404
* Creates a new restriction which is true for objects where the size
405
* of the value of @propname matches @size according to @relop.
407
* This cannot be used for WebDAV SEARCH restrictions.
409
* You probably do not want to use this. The standard idiom for
410
* checking the size of a message is to use e2k_restriction_prop_int()
411
* on its %PR_MESSAGE_SIZE property, not to use e2k_restriction_size()
414
* Return value: the new restriction
417
e2k_restriction_size (const gchar *propname, E2kRestrictionRelop relop,
420
E2kRestriction *ret = g_new0 (E2kRestriction, 1);
422
ret->type = E2K_RESTRICTION_SIZE;
423
ret->res.size.relop = relop;
424
e2k_rule_prop_set (&ret->res.size.prop, propname);
425
ret->res.size.size = size;
431
* e2k_restriction_exist:
432
* @propname: property to check
434
* Creates a new restriction which is true for objects that have
435
* a @propname property.
437
* This cannot be used for WebDAV SEARCH restrictions.
439
* Return value: the new restriction
442
e2k_restriction_exist (const gchar *propname)
444
E2kRestriction *ret = g_new0 (E2kRestriction, 1);
446
ret->type = E2K_RESTRICTION_EXIST;
447
e2k_rule_prop_set (&ret->res.exist.prop, propname);
453
* e2k_restriction_sub:
454
* @subtable: the WebDAV name of a MAPI property of type PT_OBJECT
455
* @rn: the restriction to apply against the values of @subtable
456
* @unref: see e2k_restriction_and()
458
* Creates a new restriction that is true for objects where @rn is
459
* true when applied to the value of @subtable on that object.
461
* @subtable is generally %PR_MESSAGE_RECIPIENTS (for finding messages
462
* whose recipients match a given restriction) or
463
* %PR_MESSAGE_ATTACHMENTS (for finding messages whose attachments
464
* match a given restriction).
466
* This cannot be used for WebDAV SEARCH restrictions.
468
* Return value: the new restriction
471
e2k_restriction_sub (const gchar *subtable, E2kRestriction *rn, gboolean unref)
473
E2kRestriction *ret = g_new0 (E2kRestriction, 1);
475
ret->type = E2K_RESTRICTION_SUBRESTRICTION;
476
e2k_rule_prop_set (&ret->res.sub.subtable, subtable);
477
ret->res.sub.rn = rn;
479
e2k_restriction_ref (rn);
485
* e2k_restriction_unref:
488
* Unrefs @rn. If there are no more references to @rn, it is freed.
491
e2k_restriction_unref (E2kRestriction *rn)
499
case E2K_RESTRICTION_AND:
500
case E2K_RESTRICTION_OR:
501
for (i = 0; i < rn->res.and.nrns; i++)
502
e2k_restriction_unref (rn->res.and.rns[i]);
503
g_free (rn->res.and.rns);
506
case E2K_RESTRICTION_NOT:
507
e2k_restriction_unref (rn->res.not.rn);
510
case E2K_RESTRICTION_CONTENT:
511
e2k_rule_free_propvalue (&rn->res.content.pv);
514
case E2K_RESTRICTION_PROPERTY:
515
e2k_rule_free_propvalue (&rn->res.property.pv);
526
* e2k_restriction_ref:
532
e2k_restriction_ref (E2kRestriction *rn)
539
static gboolean rn_to_sql (E2kRestriction *rn, GString *sql, E2kRestrictionType inside);
541
static const gchar *sql_relops[] = { "<", "<=", ">", ">=", "=", "!=" };
542
static const gint n_sql_relops = G_N_ELEMENTS (sql_relops);
545
rns_to_sql (E2kRestrictionType type, E2kRestriction **rns, gint nrns, GString *sql)
548
gboolean need_op = FALSE;
551
for (i = 0; i < nrns; i++) {
553
g_string_append (sql, type == E2K_RESTRICTION_AND ?
557
if (rn_to_sql (rns[i], sql, type)) {
566
append_sql_quoted (GString *sql, const gchar *string)
570
g_string_append (sql, "''");
572
g_string_append_c (sql, *string);
578
rn_to_sql (E2kRestriction *rn, GString *sql, E2kRestrictionType inside)
583
case E2K_RESTRICTION_AND:
584
case E2K_RESTRICTION_OR: {
585
GString *subsql = g_string_new ("");
587
if ((rv = rns_to_sql (rn->type, rn->res.and.rns, rn->res.and.nrns, subsql))) {
588
if (rn->type != inside)
589
g_string_append (sql, "(");
590
g_string_append (sql, subsql->str);
591
if (rn->type != inside)
592
g_string_append (sql, ")");
594
g_string_free (subsql, TRUE);
599
case E2K_RESTRICTION_NOT: {
600
GString *subsql = g_string_new ("");
602
if ((rv = rn_to_sql (rn->res.not.rn, subsql, rn->type))) {
603
g_string_append (sql, "NOT (");
604
g_string_append (sql, subsql->str);
605
g_string_append (sql, ")");
607
g_string_free (subsql, TRUE);
612
case E2K_RESTRICTION_CONTENT:
613
pv = &rn->res.content.pv;
614
g_string_append_printf (sql, "\"%s\" ", pv->prop.name);
616
switch (E2K_FL_MATCH_TYPE (rn->res.content.fuzzy_level)) {
618
/* make suffix same as substring; it'll be checked for suffixes only later */
619
case E2K_FL_SUBSTRING:
620
g_string_append (sql, "LIKE '%");
621
append_sql_quoted (sql, pv->value);
622
g_string_append (sql, "%'");
626
g_string_append (sql, "LIKE '");
627
append_sql_quoted (sql, pv->value);
628
g_string_append (sql, "%'");
631
case E2K_FL_FULLSTRING:
633
g_string_append (sql, "= '");
634
append_sql_quoted (sql, pv->value);
635
g_string_append_c (sql, '\'');
640
case E2K_RESTRICTION_PROPERTY:
641
if (rn->res.property.relop >= n_sql_relops)
644
pv = &rn->res.property.pv;
645
g_string_append_printf (sql, "\"%s\" %s ", pv->prop.name,
646
sql_relops[rn->res.property.relop]);
649
case E2K_PROP_TYPE_INT:
650
g_string_append_printf (sql, "%d",
651
GPOINTER_TO_UINT (pv->value));
654
case E2K_PROP_TYPE_BOOL:
655
g_string_append (sql, pv->value ? "True" : "False");
658
case E2K_PROP_TYPE_DATE:
659
g_string_append_printf (sql,
660
"cast (\"%s\" as 'dateTime.tz')",
665
g_string_append_c (sql, '\'');
666
append_sql_quoted (sql, pv->value);
667
g_string_append_c (sql, '\'');
672
case E2K_RESTRICTION_COMPAREPROPS:
673
if (rn->res.compare.relop >= n_sql_relops)
676
g_string_append_printf (sql, "\"%s\" %s \"%s\"",
677
rn->res.compare.prop1.name,
678
sql_relops[rn->res.compare.relop],
679
rn->res.compare.prop2.name);
682
case E2K_RESTRICTION_COMMENT:
685
case E2K_RESTRICTION_BITMASK:
686
case E2K_RESTRICTION_EXIST:
687
case E2K_RESTRICTION_SIZE:
688
case E2K_RESTRICTION_SUBRESTRICTION:
696
* e2k_restriction_to_sql:
699
* Converts @rn to an SQL WHERE clause to be used with the WebDAV
700
* SEARCH method. Note that certain restriction types cannot be used
701
* in SQL, as mentioned in their descriptions above.
703
* If the restriction matches all objects, the return value will
704
* be the empty string. Otherwise it will start with "WHERE ".
706
* Return value: the SQL WHERE clause, which the caller must free,
707
* or %NULL if @rn could not be converted to SQL.
710
e2k_restriction_to_sql (E2kRestriction *rn)
715
sql = g_string_new (NULL);
716
if (!rn_to_sql (rn, sql, E2K_RESTRICTION_AND)) {
717
g_string_free (sql, TRUE);
722
g_string_prepend (sql, "WHERE ");
725
g_string_free (sql, FALSE);
729
/* Binary import/export */
732
extract_restriction (guint8 **data, gint *len, E2kRestriction **rn)
743
case E2K_RESTRICTION_AND:
744
case E2K_RESTRICTION_OR:
746
E2kRestriction **rns;
750
if (!e2k_rule_extract_uint16 (data, len, &nrns))
752
rns = g_new0 (E2kRestriction *, nrns);
753
for (i = 0; i < nrns; i++) {
754
if (!extract_restriction (data, len, &rns[i])) {
756
e2k_restriction_unref (rns[i]);
762
*rn = conjoin (type, nrns, rns, TRUE);
766
case E2K_RESTRICTION_NOT:
768
E2kRestriction *subrn;
770
if (!extract_restriction (data, len, &subrn))
772
*rn = e2k_restriction_not (subrn, TRUE);
776
case E2K_RESTRICTION_CONTENT:
782
if (!e2k_rule_extract_uint32 (data, len, &fuzzy_level) ||
783
!e2k_rule_extract_proptag (data, len, &prop) ||
784
!e2k_rule_extract_propvalue (data, len, &pv))
789
*rn = g_new0 (E2kRestriction, 1);
791
(*rn)->res.content.fuzzy_level = fuzzy_level;
792
(*rn)->res.content.pv = pv;
796
case E2K_RESTRICTION_PROPERTY:
802
if (!e2k_rule_extract_byte (data, len, &relop) ||
803
!e2k_rule_extract_proptag (data, len, &prop) ||
804
!e2k_rule_extract_propvalue (data, len, &pv))
809
*rn = g_new0 (E2kRestriction, 1);
811
(*rn)->res.property.relop = relop;
812
(*rn)->res.property.pv = pv;
816
case E2K_RESTRICTION_COMPAREPROPS:
822
case E2K_RESTRICTION_BITMASK:
828
if (!e2k_rule_extract_byte (data, len, &bitop) ||
829
!e2k_rule_extract_proptag (data, len, &prop) ||
830
!e2k_rule_extract_uint32 (data, len, &mask))
833
*rn = g_new0 (E2kRestriction, 1);
835
(*rn)->res.bitmask.bitop = bitop;
836
(*rn)->res.bitmask.prop = prop;
837
(*rn)->res.bitmask.mask = mask;
841
case E2K_RESTRICTION_SIZE:
847
case E2K_RESTRICTION_EXIST:
851
if (!e2k_rule_extract_proptag (data, len, &prop))
854
*rn = g_new0 (E2kRestriction, 1);
856
(*rn)->res.exist.prop = prop;
860
case E2K_RESTRICTION_SUBRESTRICTION:
862
E2kRuleProp subtable;
863
E2kRestriction *subrn;
865
if (!e2k_rule_extract_proptag (data, len, &subtable) ||
866
!extract_restriction (data, len, &subrn))
869
*rn = g_new0 (E2kRestriction, 1);
871
(*rn)->res.sub.subtable = subtable;
872
(*rn)->res.sub.rn = subrn;
876
case E2K_RESTRICTION_COMMENT:
878
guint8 nprops, dummy;
882
if (!e2k_rule_extract_byte (data, len, &nprops))
885
props = g_new0 (E2kPropValue, nprops);
886
for (i = 0; i < nprops; i++) {
887
if (!e2k_rule_extract_propvalue (data, len, &props[i])) {
889
e2k_rule_free_propvalue (&props[i]);
895
*rn = g_new0 (E2kRestriction, 1);
897
(*rn)->res.comment.nprops = nprops;
898
(*rn)->res.comment.props = props;
900
/* FIXME: There is always a "1" byte here, but I don't
903
if (!e2k_rule_extract_byte (data, len, &dummy) || dummy != 1) {
904
e2k_restriction_unref (*rn);
908
if (!extract_restriction (data, len, &(*rn)->res.comment.rn)) {
909
e2k_restriction_unref (*rn);
922
* e2k_restriction_extract:
923
* @data: pointer to data pointer
924
* @len: pointer to data length
925
* @rn: pointer to variable to store the extracted restriction in
927
* Attempts to extract a restriction from *@data, which contains
928
* a binary-encoded restriction from a server-side rule.
930
* On success, *@rn will contain the extracted restriction, *@data
931
* will be advanced past the end of the restriction data, and *@len
932
* will be decremented accordingly.
934
* Return value: success or failure
937
e2k_restriction_extract (guint8 **data, gint *len, E2kRestriction **rn)
941
if (!e2k_rule_extract_uint32 (data, len, &rnlen))
946
if (rnlen == 1 && (*data)[0] == 0xFF) {
955
if ((*data)[0] != 0 || (*data)[1] != 0)
960
return extract_restriction (data, len, rn);
964
append_restriction (GByteArray *ba, E2kRestriction *rn)
968
e2k_rule_append_byte (ba, rn->type);
971
case E2K_RESTRICTION_AND:
972
case E2K_RESTRICTION_OR:
973
e2k_rule_append_uint16 (ba, rn->res.and.nrns);
974
for (i = 0; i < rn->res.and.nrns; i++)
975
append_restriction (ba, rn->res.and.rns[i]);
978
case E2K_RESTRICTION_NOT:
979
append_restriction (ba, rn->res.not.rn);
982
case E2K_RESTRICTION_CONTENT:
983
e2k_rule_append_uint32 (ba, rn->res.content.fuzzy_level);
984
e2k_rule_append_proptag (ba, &rn->res.content.pv.prop);
985
e2k_rule_append_propvalue (ba, &rn->res.content.pv);
988
case E2K_RESTRICTION_PROPERTY:
989
e2k_rule_append_byte (ba, rn->res.property.relop);
990
e2k_rule_append_proptag (ba, &rn->res.property.pv.prop);
991
e2k_rule_append_propvalue (ba, &rn->res.property.pv);
994
case E2K_RESTRICTION_COMPAREPROPS:
998
case E2K_RESTRICTION_BITMASK:
999
e2k_rule_append_byte (ba, rn->res.bitmask.bitop);
1000
e2k_rule_append_proptag (ba, &rn->res.bitmask.prop);
1001
e2k_rule_append_uint32 (ba, rn->res.bitmask.mask);
1004
case E2K_RESTRICTION_SIZE:
1007
case E2K_RESTRICTION_EXIST:
1008
e2k_rule_append_proptag (ba, &rn->res.exist.prop);
1011
case E2K_RESTRICTION_SUBRESTRICTION:
1012
e2k_rule_append_proptag (ba, &rn->res.sub.subtable);
1013
append_restriction (ba, rn->res.sub.rn);
1016
case E2K_RESTRICTION_COMMENT:
1017
e2k_rule_append_byte (ba, rn->res.comment.nprops);
1019
for (i = 0; i < rn->res.comment.nprops; i++)
1020
e2k_rule_append_propvalue (ba, &rn->res.comment.props[i]);
1022
/* FIXME: There is always a "1" byte here, but I don't
1025
e2k_rule_append_byte (ba, 1);
1027
append_restriction (ba, rn->res.comment.rn);
1036
* e2k_restriction_append:
1037
* @ba: a buffer into which a server-side rule is being constructed
1038
* @rn: the restriction to append to @ba
1040
* Appends @rn to @ba as part of a server-side rule.
1043
e2k_restriction_append (GByteArray *ba, E2kRestriction *rn)
1045
gint rnlen_offset, rnlen;
1048
e2k_rule_append_uint32 (ba, 1);
1049
e2k_rule_append_byte (ba, 0xFF);
1053
/* Save space for the length field */
1054
rnlen_offset = ba->len;
1055
e2k_rule_append_uint32 (ba, 0);
1058
e2k_rule_append_uint16 (ba, 0);
1060
append_restriction (ba, rn);
1062
rnlen = ba->len - rnlen_offset - 4;
1063
e2k_rule_write_uint32 (ba->data + rnlen_offset, rnlen);