LCOV - code coverage report
Current view: top level - libcli/wsp - wsp_aqs.c (source / functions) Hit Total Coverage
Test: coverage report for master 70ed9daf Lines: 226 426 53.1 %
Date: 2024-01-11 09:59:51 Functions: 18 31 58.1 %

          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             : }

Generated by: LCOV version 1.14