LCOV - code coverage report
Current view: top level - librpc/wsp - wsp_util.c (source / functions) Hit Total Coverage
Test: coverage report for master 2f515e9b Lines: 120 457 26.3 %
Date: 2024-04-21 15:09:00 Functions: 10 29 34.5 %

          Line data    Source code
       1             : /*
       2             :  *  Unix SMB/CIFS implementation.
       3             :  *
       4             :  *  Window Search Service
       5             :  *
       6             :  *  Copyright (c) Noel Power
       7             :  *
       8             :  *  This program is free software; you can redistribute it and/or modify
       9             :  *  it under the terms of the GNU General Public License as published by
      10             :  *  the Free Software Foundation; either version 3 of the License, or
      11             :  *  (at your option) any later version.
      12             :  *
      13             :  *  This program is distributed in the hope that it will be useful,
      14             :  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
      15             :  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      16             :  *  GNU General Public License for more details.
      17             :  *
      18             :  *  You should have received a copy of the GNU General Public License
      19             :  *  along with this program; if not, see <http://www.gnu.org/licenses/>.
      20             :  */
      21             : #include "includes.h"
      22             : #include "lib/util/util_file.h"
      23             : #include "librpc/wsp/wsp_util.h"
      24             : #include "librpc/gen_ndr/wsp.h"
      25             : #include "librpc/gen_ndr/ndr_wsp.h"
      26             : #include "lib/util/strv_util.h"
      27             : #include "lib/util/strv.h"
      28             : #include "lib/util/util_str_hex.h"
      29             : #include "source3/param/param_proto.h"
      30             : #include "lib/util/dlinklist.h"
      31             : 
      32             : #define BUFFER_SIZE  1024000
      33             : struct guidtopropmap_holder
      34             : {
      35             :         struct guidtopropmap *guidtopropmaploc;
      36             : };
      37             : 
      38             : struct full_propset_info_list {
      39             :         struct full_propset_info_list *prev, *next;
      40             :         struct full_propset_info info;
      41             : };
      42             : 
      43             : struct guidtopropmap {
      44             :         struct guidtopropmap *prev, *next;
      45             :         struct GUID guid;
      46             :         struct full_propset_info_list *propset;
      47             : };
      48             : 
      49           0 : static struct guidtopropmap *find_guid_props(
      50             :                 struct guidtopropmap_holder *holder,
      51             :                 const struct GUID *guid)
      52             : {
      53           0 :         struct guidtopropmap *mapitem;
      54           0 :         for (mapitem = holder->guidtopropmaploc; mapitem; mapitem = mapitem->next) {
      55           0 :                 if (GUID_equal(guid, &mapitem->guid)) {
      56             :                         return mapitem;
      57             :                 }
      58             :         }
      59             :         return NULL;
      60             : }
      61             : 
      62           0 : static bool getbool(char *str)
      63             : {
      64           0 :         char *cpy = talloc_strdup(NULL, str);
      65           0 :         bool result;
      66             : 
      67           0 :         trim_string(cpy, " ", " ");
      68           0 :         if (strequal("TRUE", cpy)) {
      69             :                 result = true;
      70             :         } else {
      71           0 :                 result = false;
      72             :         }
      73           0 :         TALLOC_FREE(cpy);
      74           0 :         return result;
      75             : }
      76             : 
      77             : struct {
      78             :         const char* typename;
      79             :         uint16_t type;
      80             : } vtype_map[]  = {
      81             :         {"GUID", VT_CLSID},
      82             :         {"String", VT_LPWSTR},
      83             :         {"BString", VT_BSTR},
      84             :         {"Double", VT_R8},
      85             :         {"Buffer", VT_BLOB_OBJECT},
      86             :         {"Byte", VT_UI1},
      87             :         {"UInt64", VT_UI8},
      88             :         {"Int64", VT_I8},
      89             :         {"UInt32", VT_UI4},
      90             :         {"Int32", VT_I4},
      91             :         {"UInt16", VT_UI2},
      92             :         {"Int16", VT_I2},
      93             :         {"DateTime", VT_FILETIME},
      94             :         {"Boolean", VT_BOOL}
      95             : };
      96             : 
      97           0 : static uint16_t getvtype(char *str, bool isvec)
      98             : {
      99           0 :         uint16_t result = UINT16_MAX;
     100           0 :         int i;
     101           0 :         for (i = 0; i < ARRAY_SIZE(vtype_map); i++) {
     102           0 :                 if (strequal(vtype_map[i].typename, str)) {
     103           0 :                         result = vtype_map[i].type;
     104           0 :                         if (isvec) {
     105           0 :                                 result |= VT_VECTOR;
     106             :                         }
     107             :                         break;
     108             :                 }
     109             :         }
     110           0 :         return result;
     111             : }
     112             : 
     113           0 : static bool parse_csv_line(TALLOC_CTX *ctx,
     114             :                 char **csvs, size_t num_values,
     115             :                 struct guidtopropmap_holder *propmap_holder)
     116             : {
     117           0 :         struct guidtopropmap *mapitem = NULL;
     118           0 :         struct full_propset_info_list *item = NULL;
     119             : 
     120           0 :         char *guid_str = NULL;
     121           0 :         struct GUID guid;
     122           0 :         bool ok;
     123             : 
     124           0 :         item = talloc_zero(ctx,
     125             :                         struct full_propset_info_list);
     126           0 :         if (!item) {
     127             :                 return false;
     128             :         }
     129             : 
     130           0 :         item->info.in_inverted_index = false;
     131           0 :         item->info.is_column = true;
     132           0 :         item->info.can_col_be_indexed = true;
     133             : 
     134           0 :         if (strlen(csvs[1])) {
     135           0 :                 guid_str = talloc_strdup(ctx, csvs[1]);
     136             :         }
     137             : 
     138           0 :         if (!guid_str) {
     139           0 :                 DBG_ERR("out of memory\n");
     140           0 :                 return false;
     141             :         }
     142             : 
     143           0 :         if (!trim_string(guid_str, "{", "}")) {
     144             :                 return false;
     145             :         }
     146             : 
     147           0 :         if (strlen(csvs[0])) {
     148           0 :                 char *tmp = talloc_strdup(item, csvs[0]);
     149           0 :                 trim_string(tmp, " ", " ");
     150           0 :                 item->info.name = tmp;
     151             :         }
     152             : 
     153           0 :         if (strlen(csvs[2])) {
     154           0 :                 item->info.id = atoi(csvs[2]);
     155             :         }
     156             : 
     157           0 :         if (strlen(csvs[3])) {
     158           0 :                 item->info.in_inverted_index = getbool(csvs[3]);
     159             :         }
     160             : 
     161           0 :         if (strlen(csvs[4])) {
     162           0 :                 item->info.is_column = getbool(csvs[4]);
     163             :         }
     164             : 
     165           0 :         if (strlen(csvs[5])) {
     166           0 :                 item->info.can_col_be_indexed = getbool(csvs[5]);
     167             :         }
     168             : 
     169           0 :         if (strlen(csvs[6])) {
     170           0 :                 bool isvec = false;
     171           0 :                 uint16_t type;
     172           0 :                 if (strlen(csvs[0])) {
     173           0 :                         isvec = getbool(csvs[8]);
     174             :                 }
     175           0 :                 type = getvtype(csvs[6], isvec);
     176           0 :                 if (type == UINT16_MAX) {
     177           0 :                         DBG_ERR("failed to parse type\n");
     178           0 :                         return false;
     179             :                 }
     180           0 :                 item->info.vtype = type;
     181             :         }
     182             : 
     183           0 :         ok = parse_guid_string(guid_str, &guid);
     184           0 :         if (!ok) {
     185             :                 return false;
     186             :         }
     187             : 
     188           0 :         mapitem = find_guid_props(propmap_holder, &guid);
     189           0 :         if (!mapitem) {
     190           0 :                 mapitem = talloc_zero(propmap_holder,
     191             :                         struct guidtopropmap);
     192           0 :                 if (!mapitem) {
     193             :                         return false;
     194             :                 }
     195           0 :                 mapitem->guid = guid;
     196           0 :                 DLIST_ADD_END(propmap_holder->guidtopropmaploc, mapitem);
     197             :         }
     198             : 
     199           0 :         talloc_steal(mapitem, item);
     200           0 :         DLIST_ADD_END(mapitem->propset, item);
     201             :         return true;
     202             : }
     203             : 
     204           0 : static bool parse_properties_line(TALLOC_CTX *ctx,
     205             :                 const char* line,
     206             :                 struct guidtopropmap_holder *propmap_holder)
     207             : {
     208           0 :         int ret;
     209           0 :         int pos;
     210           0 :         char* strv = NULL;
     211           0 :         char** csv_line = NULL;
     212           0 :         char* t = NULL;
     213           0 :         size_t len;
     214             : 
     215           0 :         ret = strv_split(ctx,
     216             :                         &strv,
     217             :                         line,
     218             :                         ",");
     219             : 
     220           0 :         if (ret != 0) {
     221           0 :                 DBG_ERR("failed to split line\n");
     222           0 :                 return false;
     223             :         }
     224             : 
     225           0 :         len = strv_count(strv);
     226             : 
     227           0 :         if (len < 9) {
     228           0 :                 DBG_WARNING("skipping line as it doesn't have "
     229             :                             "enough fields\n");
     230           0 :                 return true;
     231             :         }
     232             : 
     233           0 :         csv_line = talloc_zero_array(ctx,
     234             :                         char *,
     235             :                         len);
     236             : 
     237           0 :         if (!csv_line) {
     238           0 :                 DBG_ERR("out of memory\n");
     239           0 :                 return false;
     240             :         }
     241           0 :         for (pos = 0; pos < talloc_array_length(csv_line); pos++) {
     242           0 :                 t = strv_next(strv, t);
     243             :                 /* the scraped property file can have a non ascii char */
     244           0 :                 if (strlen(t) == 1 && *t == 0xa0) {
     245             :                         csv_line[pos] = talloc_strdup(csv_line,
     246             :                                         "");
     247             :                 } else {
     248           0 :                         csv_line[pos] = talloc_strdup(csv_line,
     249             :                                                 t);
     250             :                 }
     251           0 :                 trim_string(csv_line[pos], " ", " ");
     252             :         }
     253             : 
     254           0 :         if (!parse_csv_line(csv_line, csv_line, len, propmap_holder)) {
     255           0 :                 DBG_ERR("failed to parse line\n");
     256           0 :                 TALLOC_FREE(csv_line);
     257           0 :                 return false;
     258             :         }
     259           0 :         TALLOC_FREE(csv_line);
     260           0 :         return true;
     261             : }
     262             : 
     263           0 : static bool parse_properties_csvfile(TALLOC_CTX *ctx,
     264             :                 struct guidtopropmap_holder *propmap_holder,
     265             :                 const char* filename)
     266             : {
     267           0 :         char **lines = NULL;
     268           0 :         int numlines;
     269           0 :         int i;
     270             : 
     271           0 :         if (filename == NULL || strlen(filename) == 0) {
     272             :                 return false;
     273             :         }
     274             : 
     275           0 :         lines = file_lines_load(filename,
     276             :                         &numlines,
     277             :                         BUFFER_SIZE,
     278             :                         ctx);
     279           0 :         if (!lines) {
     280           0 :                 DBG_ERR("Failed to load %s\n", filename);
     281           0 :                 return false;
     282             :         }
     283           0 :         DBG_ERR("parsed %d lines\n", numlines);
     284             : 
     285           0 :         for (i = 0; i < numlines; i++) {
     286           0 :                 TALLOC_CTX *line_ctx = talloc_init("line context");
     287           0 :                 if (!line_ctx) {
     288           0 :                         DBG_ERR("out of memory\n");
     289           0 :                         return false;
     290             :                 }
     291             : 
     292           0 :                 trim_string(lines[i], " ", " ");
     293           0 :                 if (lines[i][0] == '#') {
     294           0 :                         DBG_WARNING("skipping comment at line %d.\n)", i);
     295           0 :                         TALLOC_FREE(line_ctx);
     296           0 :                         continue;
     297             :                 }
     298             : 
     299           0 :                 if (!parse_properties_line(line_ctx,
     300             :                                         lines[i],
     301             :                                         propmap_holder)) {
     302           0 :                         DBG_ERR("Failed to parse line %d\n", i);
     303             :                 }
     304           0 :                 TALLOC_FREE(line_ctx);
     305             :         }
     306             :         return true;
     307             : }
     308             : 
     309           0 : static bool populate_map(struct guidtopropmap_holder *propmap_holder)
     310             : {
     311           0 :         const char * path = NULL;
     312           0 :         path = lp_wsp_property_file();
     313             : 
     314             :         /* first populate the map from property file */
     315           0 :         if (path) {
     316           0 :                 parse_properties_csvfile(propmap_holder, propmap_holder, path);
     317             :         }
     318             : 
     319           0 :         return true;
     320             : }
     321             : 
     322           0 : static struct guidtopropmap_holder *propmap(void)
     323             : {
     324           0 :         static struct guidtopropmap_holder *holder = NULL;
     325             : 
     326           0 :         if (!holder) {
     327           0 :                 holder = talloc_zero(NULL, struct guidtopropmap_holder);
     328           0 :                 if (holder) {
     329           0 :                         populate_map(holder);
     330             :                 }
     331             :         }
     332             : 
     333           0 :         return holder;
     334             : }
     335             : 
     336          46 : const struct full_propset_info *get_propset_info_with_guid(
     337             :                                                 const char *prop_name,
     338             :                                                 struct GUID *propset_guid)
     339             : {
     340          46 :         const struct full_propset_info *result = NULL;
     341          46 :         struct guidtopropmap_holder *holder = NULL;
     342          46 :         struct guidtopropmap *mapitem = NULL;
     343             : 
     344          46 :         size_t i;
     345          46 :         const struct full_guid_propset *guid_propset = NULL;
     346             : 
     347             :         /* search builtin props first */
     348        4561 :         for (i = 0; full_propertyset[i].prop_info != NULL; i++) {
     349             :                 const struct full_propset_info *item = NULL;
     350       14442 :                 guid_propset = &full_propertyset[i];
     351             :                 item = guid_propset->prop_info;
     352       14442 :                 while (item->id) {
     353        9927 :                         if (strequal(prop_name, item->name)) {
     354          46 :                                 *propset_guid = guid_propset->guid;
     355          46 :                                 result = item;
     356          46 :                                 break;
     357             :                         }
     358        9881 :                         item++;
     359             :                 }
     360        4561 :                 if (result) {
     361             :                         break;
     362             :                 }
     363             :         }
     364             : 
     365          46 :         if (result) {
     366             :                 return result;
     367             :         }
     368             : 
     369             :         /* if we didn't find a match in builtin props try the extra props */
     370           0 :         holder = propmap();
     371           0 :         for (mapitem = holder->guidtopropmaploc; mapitem;
     372           0 :                         mapitem = mapitem->next) {
     373           0 :                 struct full_propset_info_list *propitem;
     374           0 :                 for (propitem = mapitem->propset; propitem;
     375           0 :                                 propitem = propitem->next) {
     376           0 :                         if (strequal(prop_name, propitem->info.name)) {
     377           0 :                                 *propset_guid = mapitem->guid;
     378           0 :                                 result = &propitem->info;
     379           0 :                                 break;
     380             :                         }
     381             :                 }
     382             :         }
     383             :         return result;
     384             : }
     385             : 
     386           3 : const struct full_propset_info *get_prop_info(const char *prop_name)
     387             : {
     388           3 :         const struct full_propset_info *result = NULL;
     389           3 :         struct GUID guid;
     390           3 :         result = get_propset_info_with_guid(prop_name, &guid);
     391           3 :         return result;
     392             : }
     393             : 
     394          32 : char *prop_from_fullprop(TALLOC_CTX *ctx, struct wsp_cfullpropspec *fullprop)
     395             : {
     396          32 :         size_t i;
     397          32 :         char *result = NULL;
     398          32 :         const struct full_propset_info *item = NULL;
     399          32 :         const struct full_propset_info_list *prop_item = NULL;
     400          32 :         bool search_by_id = (fullprop->ulkind == PRSPEC_PROPID);
     401          32 :         struct guidtopropmap_holder *holder = NULL;
     402          32 :         struct guidtopropmap *mapitem = NULL;
     403             : 
     404             :         /* check builtin properties */
     405        3260 :         for (i = 0; full_propertyset[i].prop_info != NULL; i++) {
     406             :                 /* find propset */
     407        3260 :                 if (GUID_equal(&fullprop->guidpropset,
     408             :                                &full_propertyset[i].guid)) {
     409             :                         item = full_propertyset[i].prop_info;
     410             :                         break;
     411             :                 }
     412             :         }
     413          32 :         if (item) {
     414         227 :                 while (item->id) {
     415         227 :                         if (search_by_id) {
     416         227 :                                 if( fullprop->name_or_id.prspec == item->id) {
     417          32 :                                         result = talloc_strdup(ctx, item->name);
     418          32 :                                         break;
     419             :                                 }
     420           0 :                         } else if (strcmp(item->name,
     421             :                                         fullprop->name_or_id.propname.vstring)
     422             :                                         == 0) {
     423           0 :                                 result = talloc_strdup(ctx, item->name);
     424           0 :                                 break;
     425             :                         }
     426         195 :                         item++;
     427             :                 }
     428             :         }
     429             : 
     430             :         /* not found, search the extra props */
     431          32 :         if (!result) {
     432           0 :                 holder = propmap();
     433             : 
     434           0 :                 for (mapitem = holder->guidtopropmaploc; mapitem;
     435           0 :                                 mapitem = mapitem->next) {
     436           0 :                         if (GUID_equal(&fullprop->guidpropset,
     437           0 :                                        &mapitem->guid)) {
     438           0 :                                 prop_item = mapitem->propset;
     439           0 :                                 break;
     440             :                         }
     441             :                 }
     442             : 
     443           0 :                 for (;prop_item; prop_item = prop_item->next) {
     444           0 :                         if (search_by_id) {
     445           0 :                                 if(fullprop->name_or_id.prspec ==
     446           0 :                                                 prop_item->info.id) {
     447           0 :                                         result = talloc_strdup(ctx,
     448           0 :                                                         prop_item->info.name);
     449           0 :                                         break;
     450             :                                 }
     451           0 :                         } else if (strcmp(prop_item->info.name,
     452             :                                 fullprop->name_or_id.propname.vstring) == 0) {
     453           0 :                                         result = talloc_strdup(ctx,
     454             :                                                         prop_item->info.name);
     455           0 :                                         break;
     456             :                         }
     457             :                 }
     458             :         }
     459             : 
     460          32 :         if (!result) {
     461           0 :                 result = GUID_string(ctx, &fullprop->guidpropset);
     462             : 
     463           0 :                 if (search_by_id) {
     464           0 :                         result = talloc_asprintf(result, "%s/%d", result,
     465             :                                                  fullprop->name_or_id.prspec);
     466             :                 } else {
     467           0 :                         result = talloc_asprintf(result, "%s/%s", result,
     468             :                                         fullprop->name_or_id.propname.vstring);
     469             :                 }
     470             :         }
     471          32 :         return result;
     472             : }
     473             : 
     474           2 : const char *genmeth_to_string(uint32_t genmethod)
     475             : {
     476           2 :         const char *result = NULL;
     477           2 :         switch (genmethod) {
     478             :                 case 0:
     479             :                         result = "equals";
     480             :                         break;
     481           1 :                 case 1:
     482           1 :                         result = "starts with";
     483           1 :                         break;
     484           0 :                 case 2:
     485           0 :                         result = "matches inflection";
     486           0 :                         break;
     487           0 :                 default:
     488           0 :                         result = NULL;
     489           0 :                         break;
     490             :         }
     491           2 :         return result;
     492             : }
     493             : 
     494          32 : bool is_operator(struct wsp_crestriction *restriction) {
     495          32 :         bool result;
     496          32 :         switch(restriction->ultype) {
     497             :                 case RTAND:
     498             :                 case RTOR:
     499             :                 case RTNOT:
     500             :                         result = true;
     501             :                         break;
     502          32 :                 default:
     503          32 :                         result = false;
     504          32 :                         break;
     505             :         }
     506          32 :         return result;
     507             : }
     508             : 
     509          32 : const char *op_as_string(struct wsp_crestriction *restriction)
     510             : {
     511          32 :         const char *op = NULL;
     512          32 :         if (is_operator(restriction)) {
     513           0 :                 switch(restriction->ultype) {
     514           0 :                         case RTAND:
     515           0 :                                 op = " && ";
     516           0 :                                 break;
     517           0 :                         case RTOR:
     518           0 :                                 op = " || ";
     519           0 :                                 break;
     520           0 :                         case RTNOT:
     521           0 :                                 op = "!";
     522           0 :                                 break;
     523             :                 }
     524          32 :         } else if (restriction->ultype == RTPROPERTY) {
     525          30 :                 struct wsp_cpropertyrestriction *prop_restr =
     526             :                         &restriction->restriction.cpropertyrestriction;
     527          30 :                 switch (prop_restr->relop & 0XF) {
     528          15 :                         case PREQ:
     529          15 :                                 op = "=";
     530          15 :                                 break;
     531           2 :                         case PRNE:
     532           2 :                                 op = "!=";
     533           2 :                                 break;
     534           5 :                         case PRGE:
     535           5 :                                 op = ">=";
     536           5 :                                 break;
     537           2 :                         case PRLE:
     538           2 :                                 op = "<=";
     539           2 :                                 break;
     540           4 :                         case PRLT:
     541           4 :                                 op = "<";
     542           4 :                                 break;
     543           2 :                         case PRGT:
     544           2 :                                 op = ">";
     545           2 :                                 break;
     546             :                         default:
     547             :                                 break;
     548             :                 }
     549           2 :         } else if (restriction->ultype == RTCONTENT) {
     550           2 :                 struct wsp_ccontentrestriction *content = NULL;
     551           2 :                 content = &restriction->restriction.ccontentrestriction;
     552           2 :                 op = genmeth_to_string(content->ulgeneratemethod);
     553           0 :         } else if (restriction->ultype == RTNATLANGUAGE) {
     554           0 :                 op = "=";
     555             :         }
     556          32 :         return op;
     557             : }
     558             : 
     559           0 : struct wsp_cfullpropspec *get_full_prop(struct wsp_crestriction *restriction)
     560             : {
     561           0 :         struct wsp_cfullpropspec *result;
     562           0 :         switch (restriction->ultype) {
     563           0 :                 case RTPROPERTY:
     564           0 :                         result = &restriction->restriction.cpropertyrestriction.property;
     565           0 :                         break;
     566           0 :                 case RTCONTENT:
     567           0 :                         result = &restriction->restriction.ccontentrestriction.property;
     568           0 :                         break;
     569           0 :                 case RTNATLANGUAGE:
     570           0 :                         result = &restriction->restriction.cnatlanguagerestriction.property;
     571           0 :                         break;
     572             :                 default:
     573             :                         result = NULL;
     574             :                         break;
     575             :         }
     576           0 :         return result;
     577             : }
     578             : 
     579          30 : const char *variant_as_string(TALLOC_CTX *ctx,
     580             :                         struct wsp_cbasestoragevariant *value, bool quote)
     581             : {
     582          30 :         const char* result = NULL;
     583          30 :         switch(value->vtype) {
     584           0 :                 case VT_UI1:
     585           0 :                         result = talloc_asprintf(ctx, "%u",
     586           0 :                                                  value->vvalue.vt_ui1);
     587           0 :                         break;
     588           0 :                 case VT_INT:
     589             :                 case VT_I4:
     590           0 :                         result = talloc_asprintf(ctx, "%d",
     591             :                                                  value->vvalue.vt_i4);
     592           0 :                         break;
     593           0 :                 case VT_ERROR:
     594             :                 case VT_UINT:
     595             :                 case VT_UI4:
     596           0 :                         result = talloc_asprintf(ctx, "%u",
     597             :                                                  value->vvalue.vt_ui4);
     598           0 :                         break;
     599           0 :                 case VT_UI2:
     600             :                 case VT_I2:
     601           0 :                         result = talloc_asprintf(ctx, "%u",
     602           0 :                                                  value->vvalue.vt_ui2);
     603           0 :                         break;
     604           0 :                 case VT_BOOL:
     605           0 :                         result = talloc_asprintf(ctx, "%s",
     606           0 :                                         value->vvalue.vt_ui2 == 0xFFFF ?
     607             :                                                 "true" : "false");
     608           0 :                         break;
     609           0 :                 case VT_DATE:
     610             :                 case VT_FILETIME: {
     611           0 :                         NTTIME filetime = value->vvalue.vt_ui8;
     612           0 :                         time_t unixtime;
     613           0 :                         struct tm *tm = NULL;
     614           0 :                         char datestring[256];
     615           0 :                         unixtime = nt_time_to_unix(filetime);
     616           0 :                         tm = gmtime(&unixtime);
     617           0 :                         strftime(datestring, sizeof(datestring), "%FT%TZ", tm);
     618           0 :                         result = talloc_strdup(ctx, datestring);
     619           0 :                         break;
     620             :                 }
     621             :                 case VT_R4: {
     622           0 :                         float f;
     623           0 :                         if (sizeof(f) != sizeof(value->vvalue.vt_ui4)) {
     624             :                                 DBG_ERR("can't convert float\n");
     625             :                                 break;
     626             :                         }
     627           0 :                         memcpy((void*)&f,
     628           0 :                                 (void*)&value->vvalue.vt_ui4,
     629             :                                 sizeof(value->vvalue.vt_ui4));
     630           0 :                         result = talloc_asprintf(ctx, "%f",
     631             :                                                  f);
     632           0 :                         break;
     633             :                 }
     634             :                 case VT_R8: {
     635             :                         /* should this really be unsigned ? */
     636           0 :                         double dval;
     637           0 :                         if (sizeof(dval) != sizeof(value->vvalue.vt_i8)) {
     638             :                                 DBG_ERR("can't convert double\n");
     639             :                                 break;
     640             :                         }
     641           0 :                         memcpy((void*)&dval,
     642           0 :                                 (void*)&value->vvalue.vt_i8,
     643             :                                 sizeof(dval));
     644           0 :                         result = talloc_asprintf(ctx, "%f",
     645             :                                                  dval);
     646           0 :                         break;
     647             :                 }
     648           0 :                 case VT_I8: {
     649           0 :                         result = talloc_asprintf(ctx, "%" PRIi64,
     650             :                                                  value->vvalue.vt_i8);
     651           0 :                         break;
     652             :                 }
     653          17 :                 case VT_UI8: {
     654          17 :                         result = talloc_asprintf(ctx, "%" PRIu64,
     655             :                                                  value->vvalue.vt_ui8);
     656          17 :                         break;
     657             :                 }
     658           4 :                 case VT_LPWSTR:
     659           4 :                         result = talloc_asprintf(ctx, "%s%s%s",
     660             :                                                 quote ? "\'" : "",
     661             :                                                 value->vvalue.vt_lpwstr.value,
     662             :                                                 quote ? "\'" : "");
     663           4 :                         break;
     664           9 :                 case VT_LPWSTR | VT_VECTOR: {
     665           9 :                         int num_elems =
     666           9 :                         value->vvalue.vt_lpwstr_v.vvector_elements;
     667           9 :                         int i;
     668          18 :                         for(i = 0; i < num_elems; i++) {
     669           9 :                                 struct vt_lpwstr_vec *vec;
     670           9 :                                 const char *val;
     671           9 :                                 vec = &value->vvalue.vt_lpwstr_v;
     672           9 :                                 val = vec->vvector_data[i].value;
     673           9 :                                 result =
     674          27 :                                         talloc_asprintf(ctx,
     675             :                                                         "%s%s%s%s%s",
     676             :                                                         result ? result : "",
     677             :                                                         i ? "," : "",
     678             :                                                         quote ? "\'" : "",
     679             :                                                         val,
     680             :                                                         quote ? "\'" : "");
     681             :                         }
     682             :                         break;
     683             :                 }
     684           0 :                 default:
     685           0 :                         DBG_INFO("can't represent unsupported vtype 0x%x as string\n",
     686             :                                 value->vtype);
     687             :                         break;
     688             :         }
     689          30 :         return result;
     690             : }
     691             : 
     692             : static const struct {
     693             :         uint32_t id;
     694             :         const char *name;
     695             : } typename_map[] = {
     696             :         {VT_EMPTY, "Empty"},
     697             :         {VT_NULL, "Null"},
     698             :         {VT_I2, "VT_I2"},
     699             :         {VT_I4, "VT_I4"},
     700             :         {VT_I4, "VT_I4"},
     701             :         {VT_R4, "VT_R4"},
     702             :         {VT_R8, "VT_R8"},
     703             :         {VT_CY, "VT_CY"},
     704             :         {VT_DATE, "VT_DATE"},
     705             :         {VT_BSTR, "VT_BSTR"},
     706             :         {VT_I1, "VT_I1"},
     707             :         {VT_UI1, "VT_UI1"},
     708             :         {VT_UI2, "VT_UI2"},
     709             :         {VT_UI4, "VT_UI4"},
     710             :         {VT_I8, "VT_I8"},
     711             :         {VT_UI8, "VT_UI8"},
     712             :         {VT_INT, "VT_INT"},
     713             :         {VT_UINT, "VT_UINT"},
     714             :         {VT_ERROR, "VT_ERROR"},
     715             :         {VT_BOOL, "VT_BOOL"},
     716             :         {VT_VARIANT, "VT_VARIANT"},
     717             :         {VT_DECIMAL, "VT_DECIMAL"},
     718             :         {VT_FILETIME, "VT_FILETIME"},
     719             :         {VT_BLOB, "VT_BLOB"},
     720             :         {VT_BLOB_OBJECT, "VT_BLOB_OBJECT"},
     721             :         {VT_CLSID, "VT_CLSID"},
     722             :         {VT_LPSTR, "VT_LPSTR"},
     723             :         {VT_LPWSTR, "VT_LPWSTR"},
     724             :         {VT_COMPRESSED_LPWSTR, "VT_COMPRESSED_LPWSTR"},
     725             : };
     726             : 
     727           0 : const char *get_vtype_name(uint32_t type)
     728             : {
     729           0 :         const char *type_name = NULL;
     730           0 :         static char result_buf[255];
     731           0 :         int i;
     732           0 :         uint32_t temp = type & ~(VT_VECTOR | VT_ARRAY);
     733           0 :         for (i = 0; i < ARRAY_SIZE(typename_map); i++) {
     734           0 :                 if (temp == typename_map[i].id) {
     735           0 :                         type_name = typename_map[i].name;
     736           0 :                         break;
     737             :                 }
     738             :         }
     739           0 :         if (type & VT_VECTOR) {
     740           0 :                 snprintf(result_buf, sizeof(result_buf), "Vector | %s", type_name);
     741           0 :         } else if (type & VT_ARRAY) {
     742           0 :                 snprintf(result_buf, sizeof(result_buf), "Array | %s", type_name);
     743             :         } else {
     744           0 :                 snprintf(result_buf, sizeof(result_buf), "%s", type_name);
     745             :         }
     746           0 :         return result_buf;
     747             : }
     748             : 
     749           0 : bool is_variable_size(uint16_t vtype)
     750             : {
     751           0 :         bool result;
     752           0 :         switch(vtype) {
     753             :                 case VT_LPWSTR:
     754             :                 case VT_COMPRESSED_LPWSTR:
     755             :                 case VT_BSTR:
     756             :                 case VT_BLOB:
     757             :                 case VT_BLOB_OBJECT:
     758             :                 case VT_VARIANT:
     759             :                         result = true;
     760             :                         break;
     761           0 :                 default:
     762           0 :                         result = false;
     763           0 :                         break;
     764             :         }
     765           0 :         return result;
     766             : }
     767             : 
     768           0 : const char *get_store_status(uint8_t status_byte)
     769             : {
     770           0 :         const char *result;
     771           0 :         switch(status_byte) {
     772             :                 case 0:
     773             :                         result = "StoreStatusOk";
     774             :                         break;
     775           0 :                 case 1:
     776           0 :                         result = "StoreStatusDeferred";
     777           0 :                         break;
     778           0 :                 case 2:
     779           0 :                         result = "StoreStatusNull";
     780           0 :                         break;
     781           0 :                 default:
     782           0 :                         result = "Unknown Status";
     783           0 :                         break;
     784             :         }
     785           0 :         return result;
     786             : }
     787             : 
     788           4 : void set_variant_lpwstr(TALLOC_CTX *ctx,
     789             :                         struct wsp_cbasestoragevariant *vvalue,
     790             :                         const char *string_val)
     791             : {
     792           4 :         vvalue->vtype = VT_LPWSTR;
     793           4 :         vvalue->vvalue.vt_lpwstr.value = talloc_strdup(ctx, string_val);
     794           4 : }
     795             : 
     796           0 : void set_variant_i4(TALLOC_CTX *ctx,
     797             :                     struct wsp_cbasestoragevariant *vvalue,
     798             :                     uint32_t val)
     799             : {
     800           0 :         vvalue->vtype = VT_I4;
     801           0 :         vvalue->vvalue.vt_i4 = val;
     802           0 : }
     803             : 
     804           0 : void set_variant_vt_bool(TALLOC_CTX *ctx,
     805             :                         struct wsp_cbasestoragevariant *variant,
     806             :                         bool bval)
     807             : {
     808           0 :         variant->vtype = VT_BOOL;
     809           0 :         variant->vvalue.vt_bool = bval;
     810           0 : }
     811             : 
     812           0 : static void fill_int32_vec(TALLOC_CTX* ctx,
     813             :                             int32_t **pdest,
     814             :                             int32_t* ivector, uint32_t elems)
     815             : {
     816           0 :         int i;
     817           0 :         int32_t *dest = talloc_zero_array(ctx, int32_t, elems);
     818           0 :         for ( i = 0; i < elems; i++ ) {
     819           0 :                 dest[ i ] = ivector[ i ];
     820             :         }
     821           0 :         *pdest = dest;
     822           0 : }
     823             : 
     824           0 : void set_variant_i4_vector(TALLOC_CTX *ctx,
     825             :                            struct wsp_cbasestoragevariant *variant,
     826             :                            int32_t* ivector, uint32_t elems)
     827             : {
     828           0 :         variant->vtype = VT_VECTOR | VT_I4;
     829           0 :         variant->vvalue.vt_i4_vec.vvector_elements = elems;
     830           0 :         fill_int32_vec(ctx, &variant->vvalue.vt_i4_vec.vvector_data, ivector, elems);
     831           0 : }
     832             : 
     833           9 : static void fill_string_vec(TALLOC_CTX* ctx,
     834             :                                 struct wsp_cbasestoragevariant *variant,
     835             :                                 const char **strings, uint16_t elems)
     836             : {
     837           9 :         int i;
     838           9 :         variant->vvalue.vt_lpwstr_v.vvector_elements = elems;
     839           9 :         variant->vvalue.vt_lpwstr_v.vvector_data = talloc_zero_array(ctx,
     840             :                                                         struct vt_lpwstr,
     841             :                                                         elems);
     842             : 
     843          18 :         for( i = 0; i < elems; i++ ) {
     844           9 :                 variant->vvalue.vt_lpwstr_v.vvector_data[ i ].value = talloc_strdup(ctx, strings[ i ]);
     845             :         }
     846           9 : }
     847             : 
     848           0 : static void fill_bstr_vec(TALLOC_CTX *ctx,
     849             :                   struct vt_bstr **pvector,
     850             :                   const char **strings, uint16_t elems)
     851             : {
     852           0 :         int i;
     853           0 :         struct vt_bstr *vdata = talloc_zero_array(ctx, struct vt_bstr, elems);
     854             : 
     855           0 :         for( i = 0; i < elems; i++ ) {
     856           0 :                 vdata [ i ].value = talloc_strdup(ctx, strings[ i ]);
     857             :         }
     858           0 :         *pvector = vdata;
     859           0 : }
     860             : 
     861           0 : void set_variant_bstr(TALLOC_CTX *ctx, struct wsp_cbasestoragevariant *variant,
     862             :                         const char *string_val)
     863             : {
     864           0 :         variant->vtype = VT_BSTR;
     865           0 :         variant->vvalue.vt_bstr.value = talloc_strdup(ctx, string_val);
     866           0 : }
     867             : 
     868           9 : void set_variant_lpwstr_vector(TALLOC_CTX *ctx,
     869             :                               struct wsp_cbasestoragevariant *variant,
     870             :                               const char **string_vals, uint32_t elems)
     871             : {
     872           9 :         variant->vtype = VT_LPWSTR | VT_VECTOR;
     873           9 :         fill_string_vec(ctx, variant, string_vals, elems);
     874           9 : }
     875             : 
     876           0 : void set_variant_array_bstr(TALLOC_CTX *ctx,
     877             :                            struct wsp_cbasestoragevariant *variant,
     878             :                            const char **string_vals, uint16_t elems)
     879             : {
     880           0 :         variant->vtype = VT_BSTR | VT_ARRAY;
     881           0 :         variant->vvalue.vt_bstr_array.cdims = 1;
     882           0 :         variant->vvalue.vt_bstr_array.ffeatures = 0;
     883             : 
     884           0 :         variant->vvalue.vt_bstr_array.rgsabound =
     885           0 :                 talloc_zero_array(ctx, struct safearraybound, 1);
     886             : 
     887           0 :         variant->vvalue.vt_bstr_array.rgsabound[0].celements = elems;
     888           0 :         variant->vvalue.vt_bstr_array.rgsabound[0].ilbound = 0;
     889           0 :         variant->vvalue.vt_bstr_array.cbelements = 0;
     890           0 :         fill_bstr_vec(ctx, &variant->vvalue.vt_bstr_array.vdata,
     891             :                       string_vals, elems);
     892             :         /*
     893             :          * if cbelements is the num bytes per elem it kindof means each
     894             :          * string in the array must be the same size ?
     895             :          */
     896             : 
     897           0 :         if (elems >0) {
     898           0 :                 variant->vvalue.vt_bstr_array.cbelements =
     899           0 :                         strlen_m_term(variant->vvalue.vt_bstr_array.vdata[0].value)*2;
     900             :         }
     901           0 : }
     902             : 
     903             : /* create single dim array of vt_i4 */
     904           0 : void set_variant_array_i4(TALLOC_CTX *ctx,
     905             :                          struct wsp_cbasestoragevariant *variant,
     906             :                          int32_t *vals, uint16_t elems)
     907             : {
     908             :         /* #TODO see if we can combine with other set_variant_array methods */
     909           0 :         variant->vtype = VT_I4 | VT_ARRAY;
     910           0 :         variant->vvalue.vt_i4_array.cdims = 1;
     911           0 :         variant->vvalue.vt_i4_array.ffeatures = 0;
     912             : 
     913           0 :         variant->vvalue.vt_i4_array.rgsabound =
     914           0 :                 talloc_zero_array(ctx, struct safearraybound, 1);
     915             : 
     916           0 :         variant->vvalue.vt_i4_array.rgsabound[0].celements = elems;
     917           0 :         variant->vvalue.vt_i4_array.rgsabound[0].ilbound = 0;
     918           0 :         variant->vvalue.vt_i4_array.cbelements = sizeof(uint32_t);
     919           0 :         fill_int32_vec(ctx, &variant->vvalue.vt_i4_array.vdata, vals, elems);
     920           0 : }

Generated by: LCOV version 1.14