Line data Source code
1 : /*
2 : * Window Search Service
3 : *
4 : * Copyright (c) Noel Power
5 : *
6 : * This program is free software; you can redistribute it and/or modify
7 : * it under the terms of the GNU General Public License as published by
8 : * the Free Software Foundation; either version 3 of the License, or
9 : * (at your option) any later version.
10 : *
11 : * This program is distributed in the hope that it will be useful,
12 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 : * GNU General Public License for more details.
15 : *
16 : * You should have received a copy of the GNU General Public License
17 : * along with this program; if not, see <http://www.gnu.org/licenses/>.
18 : */
19 :
20 : #include "includes.h"
21 : #include "libcli/wsp/wsp_aqs.h"
22 : #include "libcli/wsp/wsp_aqs_parser.tab.h"
23 : #include "libcli/wsp/wsp_aqs_lexer.h"
24 : #include "librpc/wsp/wsp_util.h"
25 : #include "librpc/gen_ndr/ndr_wsp.h"
26 : #include <stdio.h>
27 : #include <stdbool.h>
28 :
29 : int yyparse(t_select_stmt **select, yyscan_t scanner);
30 :
31 24 : static void reverse_cols(t_select_stmt *select)
32 : {
33 24 : int num_elems, fwd, rev;
34 24 : char **cols;
35 :
36 :
37 24 : if (!select->cols) {
38 : return;
39 : }
40 1 : num_elems = select->cols->num_cols;
41 1 : cols = select->cols->cols;
42 :
43 3 : for(fwd = 0, rev = num_elems - 1; fwd <= rev; fwd++, rev--) {
44 2 : char * tmp = cols[rev];
45 2 : cols[rev] = cols[fwd];
46 2 : cols[fwd] = tmp;
47 : }
48 :
49 : }
50 :
51 24 : t_select_stmt *get_wsp_sql_tree(const char *expr)
52 : {
53 24 : t_select_stmt *select = NULL;
54 24 : yyscan_t scanner;
55 24 : YY_BUFFER_STATE state;
56 :
57 24 : if (yylex_init(&scanner)) {
58 0 : DBG_ERR("couldn't initialize\n");
59 0 : return NULL;
60 : }
61 :
62 24 : state = yy_scan_string(expr, scanner);
63 :
64 24 : if (yyparse(&select, scanner)) {
65 0 : DBG_ERR("some parse error\n");
66 0 : return NULL;
67 : }
68 : /*
69 : * parsed columns are in reverse order to how they are specified
70 : * in the AQS like statement, reverse them again to correct this.
71 : */
72 24 : reverse_cols(select);
73 :
74 24 : yy_delete_buffer(state, scanner);
75 :
76 24 : yylex_destroy(scanner);
77 :
78 24 : return select;
79 : }
80 :
81 :
82 3 : t_col_list *create_cols(TALLOC_CTX *ctx, const char *col, t_col_list *append_list)
83 : {
84 3 : t_col_list *cols = append_list;
85 3 : if (!get_prop_info(col)) {
86 0 : DBG_ERR("Unknown property %s\n", col);
87 0 : return NULL;
88 : }
89 3 : if (cols == NULL) {
90 1 : cols = talloc_zero(ctx, t_col_list);
91 1 : if (cols == NULL) {
92 0 : DBG_ERR("out of memory\n");
93 0 : return NULL;
94 : }
95 1 : cols->num_cols = 0;
96 1 : cols->cols = NULL;
97 1 : DBG_INFO("returning new cols %p with item %s\n", cols, col);
98 : }
99 3 : if (col) {
100 3 : int old_index = cols->num_cols;
101 3 : if (old_index == 0) {
102 1 : cols->cols = talloc_array(cols, char*, 1);
103 : } else {
104 2 : cols->cols = (char **)talloc_realloc(cols, cols->cols, char*, old_index + 1);
105 : }
106 3 : if (!cols->cols) {
107 : return NULL; /* can we create a parser error here */
108 : }
109 3 : cols->num_cols++;
110 3 : cols->cols[old_index] = talloc_strdup(cols, col);
111 3 : if (cols->cols[old_index] == NULL) {
112 0 : DBG_ERR("out of memory\n");
113 0 : return NULL;
114 : }
115 :
116 : }
117 : return cols;
118 : }
119 :
120 24 : t_select_stmt *create_select(TALLOC_CTX *ctx, t_col_list *cols, t_query *where)
121 : {
122 24 : t_select_stmt *result = talloc_zero(ctx, t_select_stmt);
123 24 : if (result == NULL) {
124 0 : DBG_ERR("out of memory\n");
125 0 : return NULL;
126 : }
127 24 : result->cols = cols;
128 24 : result->where = where;
129 24 : return result;
130 : }
131 :
132 43 : t_basic_restr *create_basic_restr(TALLOC_CTX *ctx,
133 : uint32_t prop_type,
134 : t_optype op,
135 : t_value_holder *values)
136 : {
137 43 : t_basic_restr *result = talloc_zero(ctx, t_basic_restr);
138 43 : if (result == NULL) {
139 0 : DBG_ERR("out of memory\n");
140 0 : return NULL;
141 : }
142 43 : result->prop_type = prop_type;
143 43 : result->op = op;
144 43 : if (values->type == VALUE_RANGE) {
145 2 : t_restr *left_node;
146 2 : t_restr *right_node;
147 2 : t_basic_restr *left_val;
148 2 : t_basic_restr *right_val;
149 2 : if (op != eEQ) {
150 0 : DBG_ERR("Unsupported operation %d\n", op);
151 0 : TALLOC_FREE(result);
152 0 : goto out;
153 : }
154 :
155 2 : if (values->value.value_range->lower == NULL) {
156 0 : DBG_ERR("range lower limit doesn't exist\n");
157 0 : TALLOC_FREE(result);
158 0 : goto out;
159 : }
160 : /*
161 : * detect special case where upper range doesn't exist
162 : * and convert to a property value. (this won't happen from
163 : * the cmdline directly but only as a result of a range
164 : * created 'specially' in code, e.g. special gigantic size
165 : * range.
166 : */
167 2 : if (values->value.value_range->upper == NULL) {
168 0 : result->op = eGE;
169 0 : result->values = values->value.value_range->lower;
170 0 : goto out;
171 : }
172 2 : result->values = talloc_zero(result, t_value_holder);
173 2 : if (result->values == NULL) {
174 0 : DBG_ERR("out of memory\n");
175 0 : TALLOC_FREE(result);
176 0 : goto out;
177 : }
178 : /*
179 : * try create a restriction tree (>=lower AND <upper) to
180 : * represent the range
181 : */
182 4 : left_val = create_basic_restr(result->values,
183 : prop_type,
184 : eGE,
185 2 : values->value.value_range->lower);
186 :
187 4 : right_val = create_basic_restr(result->values,
188 : prop_type,
189 : eLT,
190 2 : values->value.value_range->upper);
191 :
192 2 : if (!left_val || !right_val) {
193 0 : DBG_ERR("Failed creating basic_restriction values "
194 : "for range\n");
195 0 : TALLOC_FREE(result);
196 0 : goto out;
197 : }
198 :
199 2 : left_node = create_restr(result->values, eVALUE, NULL, NULL, left_val);
200 2 : right_node = create_restr(result->values, eVALUE, NULL, NULL, right_val);
201 :
202 :
203 2 : if (!left_node || !right_node) {
204 0 : DBG_ERR("Failed creating restr nodes for range\n");
205 0 : TALLOC_FREE(result);
206 0 : goto out;
207 : }
208 2 : result->values->type = RESTR;
209 2 : result->values->value.restr_tree = create_restr(result->values,
210 : eAND,
211 : left_node,
212 : right_node,
213 : NULL);
214 2 : if (!result->values->value.restr_tree) {
215 0 : DBG_ERR("Failed creating restr tree for range\n");
216 0 : TALLOC_FREE(result);
217 0 : goto out;
218 : }
219 : } else {
220 41 : result->values = values;
221 : }
222 : out:
223 : return result;
224 : }
225 :
226 : /*
227 : * The parser reads numbers as VT_UI8, booleans as VT_BOOL and strings as
228 : * VT_LPWSTR
229 : */
230 : typedef bool (*conv_func) (TALLOC_CTX *ctx, t_value_holder *src,
231 : struct wsp_cbasestoragevariant *dest,
232 : uint16_t dest_type);
233 :
234 : /*
235 : * default converter #TODO probably should cater for detecting over/underrun
236 : * depending on the dest_type we are narrowing to
237 : */
238 17 : static bool default_convertor(TALLOC_CTX *ctx,
239 : t_value_holder *src,
240 : struct wsp_cbasestoragevariant *dest,
241 : uint16_t dest_type)
242 : {
243 17 : if (src->type != NUMBER) {
244 : return false;
245 : }
246 17 : dest->vvalue.vt_ui8 = src->value.number;
247 17 : dest->vtype = dest_type;
248 17 : return true;
249 : }
250 :
251 9 : static bool convert_string_to_lpwstr_v(TALLOC_CTX *ctx,
252 : t_value_holder *src,
253 : struct wsp_cbasestoragevariant *dest,
254 : uint16_t dest_type)
255 : {
256 9 : const char *str = src->value.string;
257 9 : set_variant_lpwstr_vector(ctx, dest, &str, 1);
258 9 : return true;
259 : }
260 :
261 4 : static bool convert_string_to_lpwstr(TALLOC_CTX *ctx,
262 : t_value_holder *src,
263 : struct wsp_cbasestoragevariant *dest,
264 : uint16_t dest_type)
265 : {
266 4 : const char *str = src->value.string;
267 4 : set_variant_lpwstr(ctx, dest, str);
268 4 : return true;
269 : }
270 :
271 0 : static bool convert_bool_to_lpwstr(TALLOC_CTX *ctx,
272 : t_value_holder *src,
273 : struct wsp_cbasestoragevariant *dest,
274 : uint16_t dest_type)
275 : {
276 0 : set_variant_lpwstr(
277 : ctx,
278 : dest,
279 0 : src->value.boolean ? "true": "false");
280 0 : return true;
281 : }
282 :
283 0 : static bool convert_string_to_filetime(TALLOC_CTX *ctx,
284 : t_value_holder *src,
285 : struct wsp_cbasestoragevariant *dest,
286 : uint16_t dest_type)
287 : {
288 :
289 0 : static const char *fmts[] = {
290 : "%FT%TZ",
291 : "%FT%T",
292 : "%F %T",
293 : "%F %R",
294 : "%F",
295 : };
296 0 : struct tm tm;
297 0 : time_t timeval = 0;
298 0 : int i;
299 0 : ZERO_STRUCT(tm);
300 :
301 0 : for (i = 0; i < ARRAY_SIZE(fmts); i++) {
302 0 : if (strptime(src->value.string, fmts[i], &tm)) {
303 0 : timeval = timegm(&tm);
304 0 : break;
305 : }
306 : }
307 :
308 0 : if (timeval) {
309 0 : NTTIME nt;
310 0 : unix_to_nt_time(&nt, timeval);
311 0 : dest->vtype = VT_FILETIME;
312 0 : dest->vvalue.vt_filetime = nt;
313 0 : return true;
314 : }
315 : return false;
316 : }
317 :
318 : const struct {
319 : uint16_t src_vtype;
320 : uint16_t dest_vtype;
321 : conv_func convert_type;
322 : } type_conv_map[] = {
323 : {NUMBER, VT_I8, default_convertor},
324 : {NUMBER, VT_UI8, default_convertor},
325 : {NUMBER, VT_INT, default_convertor},
326 : {NUMBER, VT_UINT, default_convertor},
327 : {NUMBER, VT_I4, default_convertor},
328 : {NUMBER, VT_UI4, default_convertor},
329 : {NUMBER, VT_I2, default_convertor},
330 : {NUMBER, VT_UI2, default_convertor},
331 : {NUMBER, VT_BOOL, default_convertor},
332 : {NUMBER, VT_FILETIME, default_convertor},
333 : {NUMBER, VT_BOOL, default_convertor},
334 : {BOOL, VT_LPWSTR, convert_bool_to_lpwstr},
335 : {STRING, VT_LPWSTR, convert_string_to_lpwstr},
336 : {STRING, VT_LPWSTR | VT_VECTOR, convert_string_to_lpwstr_v},
337 : {STRING, VT_FILETIME, convert_string_to_filetime},
338 : };
339 :
340 30 : static bool process_prop_value(TALLOC_CTX *ctx,
341 : const struct full_propset_info *prop_info,
342 : t_value_holder *node_value,
343 : struct wsp_cbasestoragevariant *prop_value)
344 : {
345 30 : int i;
346 :
347 : /* coerce type as required */
348 212 : for (i = 0; i < ARRAY_SIZE(type_conv_map); i++ ) {
349 212 : if (type_conv_map[i].src_vtype == node_value->type &&
350 56 : type_conv_map[i].dest_vtype == prop_info->vtype) {
351 30 : type_conv_map[i].convert_type(ctx,
352 : node_value,
353 : prop_value,
354 : prop_info->vtype);
355 30 : return true;
356 : }
357 : }
358 : return false;
359 : }
360 :
361 43 : t_basic_query *create_basic_query(TALLOC_CTX *ctx, const char *propname, t_basic_restr *restr)
362 : {
363 43 : t_basic_query *result = talloc_zero(ctx, t_basic_query);
364 43 : if (result == NULL) {
365 0 : DBG_ERR("out of memory\n");
366 0 : goto out;
367 : }
368 43 : result->prop = talloc_strdup(result, propname);
369 43 : result->prop_info = get_propset_info_with_guid(propname, &result->guid);
370 :
371 43 : if (!result->prop_info) {
372 0 : DBG_ERR("Unknown property %s\n",propname);
373 0 : TALLOC_FREE(result);
374 0 : goto out;
375 : }
376 43 : result->basic_restriction = restr;
377 43 : out:
378 43 : return result;
379 : }
380 :
381 32 : static struct wsp_crestriction *create_restriction(TALLOC_CTX *ctx,
382 : t_basic_query *query)
383 : {
384 32 : struct wsp_crestriction *crestriction = NULL;
385 32 : struct wsp_cfullpropspec *prop = NULL;
386 32 : t_basic_restr *restr = NULL;
387 32 : t_value_holder *src = NULL;
388 32 : crestriction = talloc_zero(ctx, struct wsp_crestriction);
389 32 : if (crestriction == NULL) {
390 0 : DBG_ERR("out of memory\n");
391 0 : goto done;
392 : }
393 :
394 32 : restr = query->basic_restriction;
395 32 : src = restr->values;
396 :
397 32 : if (restr->prop_type == RTNONE) {
398 : /* shouldn't end up here */
399 0 : DBG_ERR("Unexpected t_basic_restr type\n");
400 0 : TALLOC_FREE(crestriction);
401 0 : goto done;
402 : }
403 :
404 32 : crestriction->weight = 1000;
405 :
406 32 : if (restr->prop_type == RTCONTENT) {
407 2 : struct wsp_ccontentrestriction *content = NULL;
408 2 : crestriction->ultype = RTCONTENT;
409 2 : if (src->type != STRING) {
410 0 : DBG_ERR("expected string value for %s\n",
411 : query->prop);
412 0 : TALLOC_FREE(crestriction);
413 0 : goto done;
414 : }
415 2 : content = &crestriction->restriction.ccontentrestriction;
416 2 : content->pwcsphrase = src->value.string;
417 2 : content->cc = strlen(src->value.string);
418 : /*
419 : * In the future we might generate the lcid from
420 : * environ (or config)
421 : */
422 2 : content->lcid = WSP_DEFAULT_LCID;
423 2 : if (restr->op == eEQUALS) {
424 1 : content->ulgeneratemethod = 0;
425 : } else {
426 1 : content->ulgeneratemethod = 1;
427 : }
428 :
429 2 : prop = &content->property;
430 30 : } else if (restr->prop_type == RTPROPERTY) {
431 30 : struct wsp_cbasestoragevariant *dest =
432 : &crestriction->restriction.cpropertyrestriction.prval;
433 30 : crestriction->ultype = RTPROPERTY;
434 30 : if (!process_prop_value(ctx, query->prop_info, src, dest)) {
435 0 : DBG_ERR("Failed to process value for property %s\n",
436 : query->prop);
437 0 : TALLOC_FREE(crestriction);
438 0 : goto done;
439 : }
440 30 : crestriction->restriction.cpropertyrestriction.relop =
441 30 : restr->op;
442 30 : prop = &crestriction->restriction.cpropertyrestriction.property;
443 : } else {
444 0 : TALLOC_FREE(crestriction);
445 0 : goto done;
446 : }
447 32 : prop->guidpropset = query->guid;
448 32 : prop->ulkind = PRSPEC_PROPID;
449 32 : prop->name_or_id.prspec = query->prop_info->id;
450 32 : done:
451 32 : return crestriction;
452 : }
453 :
454 : /* expands restr_node into a tree of t_query nodes */
455 15 : static void build_query(TALLOC_CTX *ctx, t_query *node, t_restr *restr_node,
456 : const char* prop)
457 : {
458 15 : if (!node) {
459 : return;
460 : }
461 15 : if (!restr_node) {
462 : return;
463 : }
464 :
465 15 : node->type = restr_node->type;
466 :
467 15 : if (restr_node->left) {
468 2 : node->left = talloc_zero(ctx, t_query);
469 2 : SMB_ASSERT(node->left != NULL);
470 2 : build_query(ctx, node->left, restr_node->left, prop);
471 : }
472 :
473 15 : if (restr_node->right) {
474 2 : node->right = talloc_zero(ctx, t_query);
475 2 : SMB_ASSERT(node->right != NULL);
476 2 : build_query(ctx, node->right, restr_node->right, prop);
477 : }
478 :
479 15 : if (restr_node->type == eVALUE) {
480 13 : node->restriction =
481 13 : create_restriction(ctx,
482 : create_basic_query(ctx,
483 : prop,
484 : restr_node->basic_restr));
485 : }
486 : }
487 :
488 39 : t_query *create_query_node(TALLOC_CTX *ctx, t_nodetype op, t_query *left, t_query *right, t_basic_query *value)
489 : {
490 39 : t_query *result = talloc_zero(ctx, t_query);
491 39 : if (result == NULL) {
492 : return result;
493 : }
494 39 : result->type = op;
495 39 : result->left = left;
496 39 : result->right = right;
497 39 : if (op == eVALUE) {
498 30 : t_basic_restr *restr = value->basic_restriction;
499 : /* expand restr node */
500 30 : if (restr->values->type == RESTR) {
501 11 : build_query(ctx,
502 : result,
503 11 : restr->values->value.restr_tree,
504 11 : value->prop);
505 : } else {
506 38 : result->restriction =
507 19 : create_restriction(ctx, value);
508 19 : if (!result->restriction) {
509 0 : TALLOC_FREE(result);
510 : }
511 : }
512 : }
513 : return result;
514 : }
515 :
516 15 : t_restr *create_restr(TALLOC_CTX *ctx, t_nodetype op, t_restr *left, t_restr *right, t_basic_restr *value)
517 : {
518 15 : t_restr *result = talloc_zero(ctx, t_restr);
519 15 : if (result == NULL) {
520 : return result;
521 : }
522 15 : result->type = op;
523 15 : result->right = right;
524 15 : result->left = left;
525 15 : result->basic_restr = value;
526 15 : return result;
527 : }
528 :
529 15 : t_value_holder *create_string_val(TALLOC_CTX* ctx, const char *text)
530 : {
531 15 : t_value_holder *result =
532 15 : talloc_zero(ctx, t_value_holder);
533 15 : if (result == NULL) {
534 0 : DBG_ERR("out of memory\n");
535 0 : return NULL;
536 : }
537 15 : result->value.string = text;
538 15 : result->type = STRING;
539 15 : return result;
540 : }
541 :
542 15 : t_value_holder *create_num_val(TALLOC_CTX* ctx, int64_t val)
543 : {
544 15 : t_value_holder *result =
545 15 : talloc_zero(ctx, t_value_holder);
546 :
547 15 : if (result == NULL) {
548 0 : DBG_ERR("out of memory\n");
549 0 : return NULL;
550 : }
551 :
552 15 : result->type = NUMBER;
553 15 : result->value.number = val;
554 15 : return result;
555 : }
556 :
557 0 : t_value_holder *create_bool_val(TALLOC_CTX* ctx, bool val)
558 : {
559 0 : t_value_holder *result =
560 0 : talloc_zero(ctx, t_value_holder);
561 :
562 0 : if (result == NULL) {
563 0 : DBG_ERR("out of memory\n");
564 0 : return NULL;
565 : }
566 :
567 0 : result->type = BOOL;
568 0 : result->value.boolean = val;
569 0 : return result;
570 : }
571 :
572 2 : t_value_holder *create_value_range(TALLOC_CTX* ctx,
573 : t_value_holder *left,
574 : t_value_holder *right)
575 : {
576 2 : t_value_holder *result =
577 2 : talloc_zero(ctx, t_value_holder);
578 :
579 2 : if (result == NULL) {
580 0 : DBG_ERR("out of memory\n");
581 0 : return NULL;
582 : }
583 :
584 2 : result->type = VALUE_RANGE;
585 2 : result->value.value_range = talloc_zero(result, struct value_range);
586 2 : if (!result->value.value_range) {
587 0 : TALLOC_FREE(result);
588 0 : goto out;
589 : }
590 2 : result->value.value_range->lower = left;
591 2 : result->value.value_range->upper = right;
592 : out:
593 : return result;
594 : }
595 :
596 0 : static void zero_time(struct tm *tm)
597 : {
598 0 : tm->tm_hour = 0;
599 0 : tm->tm_min = 0;
600 0 : tm->tm_sec = 0;
601 : }
602 :
603 : typedef bool (*daterange_func) (TALLOC_CTX *ctx, uint64_t *date1,
604 : uint64_t *date2);
605 :
606 :
607 0 : static bool create_date_range(TALLOC_CTX *ctx, uint64_t *date1,
608 : uint64_t *date2,
609 : int32_t lower_mday_adj,
610 : int32_t lower_mon_adj,
611 : int32_t upper_mday_adj,
612 : int32_t upper_mon_adj)
613 : {
614 0 : struct tm tm_now;
615 0 : time_t now;
616 :
617 0 : struct tm tm_tmp;
618 0 : time_t lower;
619 0 : time_t upper;
620 :
621 0 : time(&now);
622 0 : gmtime_r(&now, &tm_now);
623 :
624 0 : tm_tmp = tm_now;
625 0 : zero_time(&tm_tmp);
626 0 : tm_tmp.tm_mday += lower_mday_adj;
627 0 : tm_tmp.tm_mon += lower_mon_adj;
628 0 : lower = mktime(&tm_tmp);
629 0 : tm_tmp = tm_now;
630 0 : zero_time(&tm_tmp);
631 0 : tm_tmp.tm_mday += upper_mday_adj;
632 0 : tm_tmp.tm_mon += upper_mon_adj;
633 0 : upper = mktime(&tm_tmp);
634 0 : unix_to_nt_time(date1, lower);
635 0 : unix_to_nt_time(date2, upper);
636 0 : return true;
637 : }
638 :
639 0 : static void get_now_tm(struct tm *tm_now)
640 : {
641 0 : time_t now;
642 0 : time(&now);
643 0 : gmtime_r(&now, tm_now);
644 : }
645 :
646 0 : static bool create_thismonth_range(TALLOC_CTX *ctx, uint64_t *date1,
647 : uint64_t *date2)
648 : {
649 0 : struct tm tm_now;
650 0 : int32_t firstofmonth_adj;
651 :
652 0 : get_now_tm(&tm_now);
653 0 : firstofmonth_adj = 1 - tm_now.tm_mday;
654 0 : return create_date_range(ctx, date1,
655 : date2, firstofmonth_adj,
656 : 0, firstofmonth_adj, 1);
657 : }
658 :
659 0 : static bool create_lastyear_range(TALLOC_CTX *ctx, uint64_t *date1,
660 : uint64_t *date2)
661 : {
662 0 : struct tm tm_now;
663 0 : int32_t firstofmonth_adj;
664 0 : int32_t january_adj;
665 0 : get_now_tm(&tm_now);
666 :
667 0 : firstofmonth_adj = 1 - tm_now.tm_mday;
668 0 : january_adj = -tm_now.tm_mon;
669 0 : return create_date_range(ctx, date1,
670 : date2, firstofmonth_adj,
671 : january_adj - 12, firstofmonth_adj, january_adj);
672 : }
673 :
674 0 : static bool create_thisyear_range(TALLOC_CTX *ctx, uint64_t *date1,
675 : uint64_t *date2)
676 : {
677 0 : struct tm tm_now;
678 0 : int32_t firstofmonth_adj;
679 0 : int32_t january_adj;
680 :
681 0 : get_now_tm(&tm_now);
682 :
683 0 : firstofmonth_adj = 1 - tm_now.tm_mday;
684 0 : january_adj = -tm_now.tm_mon;
685 0 : return create_date_range(ctx, date1,
686 : date2, firstofmonth_adj,
687 : january_adj, firstofmonth_adj, january_adj + 12);
688 : }
689 :
690 0 : static bool create_lastmonth_range(TALLOC_CTX *ctx, uint64_t *date1,
691 : uint64_t *date2)
692 : {
693 0 : struct tm tm_now;
694 0 : int32_t firstofmonth_adj;
695 0 : get_now_tm(&tm_now);
696 :
697 0 : firstofmonth_adj = 1 - tm_now.tm_mday;
698 0 : return create_date_range(ctx, date1,
699 : date2, firstofmonth_adj,
700 : -1, firstofmonth_adj, 0);
701 : }
702 :
703 0 : static bool create_today_range(TALLOC_CTX *ctx, uint64_t *date1,
704 : uint64_t *date2)
705 : {
706 0 : return create_date_range(ctx, date1,
707 : date2, 0, 0, 1, 0);
708 : }
709 :
710 0 : static bool create_yesterday_range(TALLOC_CTX *ctx, uint64_t *date1,
711 : uint64_t *date2)
712 : {
713 0 : return create_date_range(ctx, date1,
714 : date2, -1, 0, 0, 0);
715 : }
716 :
717 0 : static bool create_thisweek_range(TALLOC_CTX *ctx, uint64_t *date1,
718 : uint64_t *date2)
719 : {
720 0 : struct tm tm_now;
721 0 : time_t now;
722 0 : int32_t startofweek_adj;
723 0 : time(&now);
724 0 : gmtime_r(&now, &tm_now);
725 0 : if (tm_now.tm_wday) {
726 0 : startofweek_adj = 1 - tm_now.tm_wday;
727 : } else {
728 : startofweek_adj = -6;
729 : }
730 : /* lower will be the start of this week */
731 0 : return create_date_range(ctx, date1,
732 : date2, startofweek_adj,
733 : 0, startofweek_adj + 7, 0);
734 : }
735 :
736 0 : static bool create_lastweek_range(TALLOC_CTX *ctx, uint64_t *date1,
737 : uint64_t *date2)
738 : {
739 0 : struct tm tm_now;
740 0 : time_t now;
741 0 : int32_t startofweek_adj;
742 0 : time(&now);
743 0 : gmtime_r(&now, &tm_now);
744 0 : if (tm_now.tm_wday) {
745 0 : startofweek_adj = 1 - tm_now.tm_wday;
746 : } else {
747 : startofweek_adj = -6;
748 : }
749 : /* upper will be the start of this week */
750 0 : return create_date_range(ctx, date1,
751 : date2, startofweek_adj - 7,
752 : 0,startofweek_adj, 0);
753 : }
754 :
755 0 : t_value_holder *create_date_range_shortcut(TALLOC_CTX *ctx,
756 : daterange_type daterange)
757 : {
758 0 : int i;
759 0 : static const struct {
760 : daterange_type range;
761 : daterange_func create_fn;
762 : } date_conv_map[] = {
763 : {eYESTERDAY, create_yesterday_range},
764 : {eTODAY, create_today_range},
765 : {eTHISMONTH, create_thismonth_range},
766 : {eLASTMONTH, create_lastmonth_range},
767 : {eTHISWEEK, create_thisweek_range},
768 : {eLASTWEEK, create_lastweek_range},
769 : {eTHISYEAR, create_thisyear_range},
770 : {eLASTYEAR, create_lastyear_range},
771 : };
772 0 : t_value_holder *result = NULL;
773 0 : t_value_holder *lower = NULL;
774 0 : t_value_holder *upper = NULL;
775 :
776 0 : lower = talloc_zero(ctx, t_value_holder);
777 0 : if (lower == NULL) {
778 0 : DBG_ERR("out of memory\n");
779 0 : goto out;
780 : }
781 :
782 0 : upper = talloc_zero(ctx, t_value_holder);
783 0 : if (upper == NULL) {
784 0 : DBG_ERR("out of memory\n");
785 0 : goto out;
786 : }
787 :
788 0 : result = create_value_range(result, lower, upper);
789 :
790 0 : if (result == NULL) {
791 0 : TALLOC_FREE(result);
792 0 : goto out;
793 : }
794 :
795 0 : lower->type = NUMBER;
796 0 : upper->type = NUMBER;
797 :
798 0 : result->value.value_range->lower = lower;
799 0 : result->value.value_range->upper = upper;
800 :
801 0 : for (i = 0; i < ARRAY_SIZE(date_conv_map); i++) {
802 0 : if (date_conv_map[i].range == daterange) {
803 0 : if (!date_conv_map[i].create_fn(result,
804 : &lower->value.number,
805 : &upper->value.number)) {
806 0 : TALLOC_FREE(result);
807 : break;
808 : }
809 : break;
810 : }
811 : }
812 0 : out:
813 0 : return result;
814 : }
815 :
816 1 : t_value_holder *create_size_range_shortcut(TALLOC_CTX *ctx,
817 : sizerange_type sizerange)
818 : {
819 1 : static const struct {
820 : sizerange_type range;
821 : uint32_t lower;
822 : uint32_t upper;
823 : } sizes[] = {
824 : {eEMPTY, 0x0, 0x1},
825 : {eTINY, 0x1, 0x2801},
826 : {eSMALL, 0x2801, 0x19001},
827 : {eMEDIUM, 0x19001, 0x100001},
828 : {eLARGE, 0x100001, 0x10000001},
829 : {eHUGE, 0x10000001, 0x80000001},
830 : {eGIGANTIC, 0x80000001, 0} /* special case not a range */
831 : };
832 1 : int i;
833 1 : t_value_holder *result = NULL;
834 1 : uint32_t lower_size;
835 1 : uint32_t upper_size;
836 1 : bool rangefound = false;
837 1 : t_value_holder *left = NULL;
838 1 : t_value_holder *right = NULL;
839 3 : for (i = 0; i < ARRAY_SIZE(sizes); i++) {
840 3 : if (sizes[i].range == sizerange) {
841 1 : result = talloc_zero(ctx, t_value_holder);
842 1 : if (result == NULL) {
843 0 : DBG_ERR("out of memory\n");
844 0 : return NULL;
845 : }
846 1 : lower_size = sizes[i].lower;
847 1 : upper_size = sizes[i].upper;
848 1 : rangefound = true;
849 1 : break;
850 : }
851 : }
852 :
853 1 : if (!rangefound) {
854 : return NULL;
855 : }
856 :
857 1 : left = talloc_zero(ctx, t_value_holder);
858 :
859 1 : if (left == NULL) {
860 : return NULL;
861 : }
862 :
863 1 : left->type = NUMBER;
864 1 : left->value.number = lower_size;
865 :
866 1 : if (upper_size) {
867 1 : right = talloc_zero(ctx, t_value_holder);
868 1 : if (right == NULL) {
869 : return NULL;
870 : }
871 1 : right->type = NUMBER;
872 1 : right->value.number = upper_size;
873 : }
874 :
875 1 : result = create_value_range(ctx, left, right);
876 1 : return result;
877 : }
|