2 * Unix SMB/CIFS implementation.
4 * Window Search Service
6 * Copyright (c) Noel Power
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.
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.
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/>.
22 #include "librpc/wsp/wsp_util.h"
23 #include "librpc/gen_ndr/wsp.h"
24 #include "librpc/gen_ndr/ndr_wsp.h"
25 #include "lib/util/strv_util.h"
26 #include "lib/util/strv.h"
27 #include "lib/util/util_str_hex.h"
28 #include "source3/param/param_proto.h"
29 #include "lib/util/dlinklist.h"
31 #define BUFFER_SIZE 1024000
32 struct guidtopropmap_holder
34 struct guidtopropmap
*guidtopropmaploc
;
37 struct full_propset_info_list
{
38 struct full_propset_info_list
*prev
, *next
;
39 struct full_propset_info info
;
42 struct guidtopropmap
{
43 struct guidtopropmap
*prev
, *next
;
45 struct full_propset_info_list
*propset
;
48 static struct guidtopropmap
*find_guid_props(
49 struct guidtopropmap_holder
*holder
,
50 const struct GUID
*guid
)
52 struct guidtopropmap
*mapitem
;
53 for (mapitem
= holder
->guidtopropmaploc
; mapitem
; mapitem
= mapitem
->next
) {
54 if (GUID_equal(guid
, &mapitem
->guid
)) {
61 static bool getbool(char *str
)
63 char *cpy
= talloc_strdup(NULL
, str
);
66 trim_string(cpy
, " ", " ");
67 if (strequal("TRUE", cpy
)) {
81 {"String", VT_LPWSTR
},
84 {"Buffer", VT_BLOB_OBJECT
},
92 {"DateTime", VT_FILETIME
},
96 static uint16_t getvtype(char *str
, bool isvec
)
98 uint16_t result
= UINT16_MAX
;
100 for (i
= 0; i
< ARRAY_SIZE(vtype_map
); i
++) {
101 if (strequal(vtype_map
[i
].typename
, str
)) {
102 result
= vtype_map
[i
].type
;
112 static bool parse_csv_line(TALLOC_CTX
*ctx
,
113 char **csvs
, size_t num_values
,
114 struct guidtopropmap_holder
*propmap_holder
)
116 struct guidtopropmap
*mapitem
= NULL
;
117 struct full_propset_info_list
*item
= NULL
;
119 char *guid_str
= NULL
;
123 item
= talloc_zero(ctx
,
124 struct full_propset_info_list
);
129 item
->info
.in_inverted_index
= false;
130 item
->info
.is_column
= true;
131 item
->info
.can_col_be_indexed
= true;
133 if (strlen(csvs
[1])) {
134 guid_str
= talloc_strdup(ctx
, csvs
[1]);
138 DBG_ERR("out of memory\n");
142 if (!trim_string(guid_str
, "{", "}")) {
146 if (strlen(csvs
[0])) {
147 char *tmp
= talloc_strdup(item
, csvs
[0]);
148 trim_string(tmp
, " ", " ");
149 item
->info
.name
= tmp
;
152 if (strlen(csvs
[2])) {
153 item
->info
.id
= atoi(csvs
[2]);
156 if (strlen(csvs
[3])) {
157 item
->info
.in_inverted_index
= getbool(csvs
[3]);
160 if (strlen(csvs
[4])) {
161 item
->info
.is_column
= getbool(csvs
[4]);
164 if (strlen(csvs
[5])) {
165 item
->info
.can_col_be_indexed
= getbool(csvs
[5]);
168 if (strlen(csvs
[6])) {
171 if (strlen(csvs
[0])) {
172 isvec
= getbool(csvs
[8]);
174 type
= getvtype(csvs
[6], isvec
);
175 if (type
== UINT16_MAX
) {
176 DBG_ERR("failed to parse type\n");
179 item
->info
.vtype
= type
;
182 ok
= parse_guid_string(guid_str
, &guid
);
187 mapitem
= find_guid_props(propmap_holder
, &guid
);
189 mapitem
= talloc_zero(propmap_holder
,
190 struct guidtopropmap
);
194 mapitem
->guid
= guid
;
195 DLIST_ADD_END(propmap_holder
->guidtopropmaploc
, mapitem
);
198 talloc_steal(mapitem
, item
);
199 DLIST_ADD_END(mapitem
->propset
, item
);
203 static bool parse_properties_line(TALLOC_CTX
*ctx
,
205 struct guidtopropmap_holder
*propmap_holder
)
210 char** csv_line
= NULL
;
214 ret
= strv_split(ctx
,
220 DBG_ERR("failed to split line\n");
224 len
= strv_count(strv
);
227 DBG_WARNING("skipping line as it doesn't have "
232 csv_line
= talloc_zero_array(ctx
,
237 DBG_ERR("out of memory\n");
240 for (pos
= 0; pos
< talloc_array_length(csv_line
); pos
++) {
241 t
= strv_next(strv
, t
);
242 /* the scraped property file can have a non ascii char */
243 if (strlen(t
) == 1 && *t
== 0xa0) {
244 csv_line
[pos
] = talloc_strdup(csv_line
,
247 csv_line
[pos
] = talloc_strdup(csv_line
,
250 trim_string(csv_line
[pos
], " ", " ");
253 if (!parse_csv_line(csv_line
, csv_line
, len
, propmap_holder
)) {
254 DBG_ERR("failed to parse line\n");
255 TALLOC_FREE(csv_line
);
258 TALLOC_FREE(csv_line
);
262 static bool parse_properties_csvfile(TALLOC_CTX
*ctx
,
263 struct guidtopropmap_holder
*propmap_holder
,
264 const char* filename
)
270 if (filename
== NULL
|| strlen(filename
) == 0) {
274 lines
= file_lines_load(filename
,
279 DBG_ERR("Failed to load %s\n", filename
);
282 DBG_ERR("parsed %d lines\n", numlines
);
284 for (i
= 0; i
< numlines
; i
++) {
285 TALLOC_CTX
*line_ctx
= talloc_init("line context");
287 DBG_ERR("out of memory\n");
291 trim_string(lines
[i
], " ", " ");
292 if (lines
[i
][0] == '#') {
293 DBG_WARNING("skipping comment at line %d.\n)", i
);
294 TALLOC_FREE(line_ctx
);
298 if (!parse_properties_line(line_ctx
,
301 DBG_ERR("Failed to parse line %d\n", i
);
303 TALLOC_FREE(line_ctx
);
308 static bool populate_map(struct guidtopropmap_holder
*propmap_holder
)
310 const char * path
= NULL
;
311 path
= lp_wsp_property_file();
313 /* first populate the map from property file */
315 parse_properties_csvfile(propmap_holder
, propmap_holder
, path
);
321 static struct guidtopropmap_holder
*propmap(void)
323 static struct guidtopropmap_holder
*holder
= NULL
;
326 holder
= talloc_zero(NULL
, struct guidtopropmap_holder
);
328 populate_map(holder
);
335 const struct full_propset_info
*get_propset_info_with_guid(
336 const char *prop_name
,
337 struct GUID
*propset_guid
)
339 const struct full_propset_info
*result
= NULL
;
340 struct guidtopropmap_holder
*holder
= NULL
;
341 struct guidtopropmap
*mapitem
= NULL
;
344 const struct full_guid_propset
*guid_propset
= NULL
;
346 /* search builtin props first */
347 for (i
= 0; full_propertyset
[i
].prop_info
!= NULL
; i
++) {
348 const struct full_propset_info
*item
= NULL
;
349 guid_propset
= &full_propertyset
[i
];
350 item
= guid_propset
->prop_info
;
352 if (strequal(prop_name
, item
->name
)) {
353 *propset_guid
= guid_propset
->guid
;
368 /* if we didn't find a match in builtin props try the extra props */
370 for (mapitem
= holder
->guidtopropmaploc
; mapitem
;
371 mapitem
= mapitem
->next
) {
372 struct full_propset_info_list
*propitem
;
373 for (propitem
= mapitem
->propset
; propitem
;
374 propitem
= propitem
->next
) {
375 if (strequal(prop_name
, propitem
->info
.name
)) {
376 *propset_guid
= mapitem
->guid
;
377 result
= &propitem
->info
;
385 const struct full_propset_info
*get_prop_info(const char *prop_name
)
387 const struct full_propset_info
*result
= NULL
;
389 result
= get_propset_info_with_guid(prop_name
, &guid
);
393 char *prop_from_fullprop(TALLOC_CTX
*ctx
, struct wsp_cfullpropspec
*fullprop
)
397 const struct full_propset_info
*item
= NULL
;
398 const struct full_propset_info_list
*prop_item
= NULL
;
399 bool search_by_id
= (fullprop
->ulkind
== PRSPEC_PROPID
);
400 struct guidtopropmap_holder
*holder
= NULL
;
401 struct guidtopropmap
*mapitem
= NULL
;
403 /* check builtin properties */
404 for (i
= 0; full_propertyset
[i
].prop_info
!= NULL
; i
++) {
406 if (GUID_equal(&fullprop
->guidpropset
,
407 &full_propertyset
[i
].guid
)) {
408 item
= full_propertyset
[i
].prop_info
;
415 if( fullprop
->name_or_id
.prspec
== item
->id
) {
416 result
= talloc_strdup(ctx
, item
->name
);
419 } else if (strcmp(item
->name
,
420 fullprop
->name_or_id
.propname
.vstring
)
422 result
= talloc_strdup(ctx
, item
->name
);
429 /* not found, search the extra props */
433 for (mapitem
= holder
->guidtopropmaploc
; mapitem
;
434 mapitem
= mapitem
->next
) {
435 if (GUID_equal(&fullprop
->guidpropset
,
437 prop_item
= mapitem
->propset
;
442 for (;prop_item
; prop_item
= prop_item
->next
) {
444 if(fullprop
->name_or_id
.prspec
==
445 prop_item
->info
.id
) {
446 result
= talloc_strdup(ctx
,
447 prop_item
->info
.name
);
450 } else if (strcmp(prop_item
->info
.name
,
451 fullprop
->name_or_id
.propname
.vstring
) == 0) {
452 result
= talloc_strdup(ctx
,
453 prop_item
->info
.name
);
460 result
= GUID_string(ctx
, &fullprop
->guidpropset
);
463 result
= talloc_asprintf(result
, "%s/%d", result
,
464 fullprop
->name_or_id
.prspec
);
466 result
= talloc_asprintf(result
, "%s/%s", result
,
467 fullprop
->name_or_id
.propname
.vstring
);
473 struct wsp_cfullpropspec
*get_full_prop(struct wsp_crestriction
*restriction
)
475 struct wsp_cfullpropspec
*result
;
476 switch (restriction
->ultype
) {
478 result
= &restriction
->restriction
.cpropertyrestriction
.property
;
481 result
= &restriction
->restriction
.ccontentrestriction
.property
;
484 result
= &restriction
->restriction
.cnatlanguagerestriction
.property
;