summaryrefslogtreecommitdiff
path: root/source3/rpc_server
diff options
context:
space:
mode:
authorRalph Boehme <slow@samba.org>2019-04-09 11:19:43 +0200
committerJeremy Allison <jra@samba.org>2019-08-08 20:24:31 +0000
commitb5731a94bbc95fa001059d488a2c16a988127619 (patch)
treed1d0fe22cf691c0c372b9869c609eab053488c7f /source3/rpc_server
parent1b897df4f7489c6ac7663ca4830dc4c129dd2457 (diff)
downloadsamba-b5731a94bbc95fa001059d488a2c16a988127619.tar.gz
s3:mdssvc: add Unicode normalisation
Signed-off-by: Ralph Boehme <slow@samba.org> Reviewed-by: Jeremy Allison <jra@samba.org>
Diffstat (limited to 'source3/rpc_server')
-rw-r--r--source3/rpc_server/mdssvc/mdssvc.c92
-rw-r--r--source3/rpc_server/mdssvc/mdssvc.h4
2 files changed, 83 insertions, 13 deletions
diff --git a/source3/rpc_server/mdssvc/mdssvc.c b/source3/rpc_server/mdssvc/mdssvc.c
index ef567595a4d..2090841d8be 100644
--- a/source3/rpc_server/mdssvc/mdssvc.c
+++ b/source3/rpc_server/mdssvc/mdssvc.c
@@ -254,7 +254,8 @@ char *mds_dalloc_dump(DALLOC_CTX *dd, int nestinglevel)
*
* If path or sp is NULL, simply add nil values for all attributes.
**/
-static bool add_filemeta(sl_array_t *reqinfo,
+static bool add_filemeta(struct mds_ctx *mds_ctx,
+ sl_array_t *reqinfo,
sl_array_t *fm_array,
const char *path,
const struct stat_ex *sp)
@@ -266,6 +267,13 @@ static bool add_filemeta(sl_array_t *reqinfo,
sl_time_t sl_time;
char *p;
const char *attribute;
+ size_t nfc_len;
+ const char *nfc_path = path;
+ size_t nfd_buf_size;
+ char *nfd_path = NULL;
+ char *dest = NULL;
+ size_t dest_remaining;
+ size_t nconv;
metacount = dalloc_size(reqinfo);
if (metacount == 0 || path == NULL || sp == NULL) {
@@ -281,6 +289,28 @@ static bool add_filemeta(sl_array_t *reqinfo,
return false;
}
+ nfc_len = strlen(nfc_path);
+ /*
+ * Simple heuristic, strlen by two should give enough room for NFC to
+ * NFD conversion.
+ */
+ nfd_buf_size = nfc_len * 2;
+ nfd_path = talloc_array(meta, char, nfd_buf_size);
+ if (nfd_path == NULL) {
+ return false;
+ }
+ dest = nfd_path;
+ dest_remaining = talloc_array_length(dest);
+
+ nconv = smb_iconv(mds_ctx->ic_nfc_to_nfd,
+ &nfc_path,
+ &nfc_len,
+ &dest,
+ &dest_remaining);
+ if (nconv == (size_t)-1) {
+ return false;
+ }
+
for (i = 0; i < metacount; i++) {
attribute = dalloc_get_object(reqinfo, i);
if (attribute == NULL) {
@@ -288,7 +318,7 @@ static bool add_filemeta(sl_array_t *reqinfo,
}
if (strcmp(attribute, "kMDItemDisplayName") == 0
|| strcmp(attribute, "kMDItemFSName") == 0) {
- p = strrchr(path, '/');
+ p = strrchr(nfd_path, '/');
if (p) {
result = dalloc_stradd(meta, p + 1);
if (result != 0) {
@@ -296,7 +326,7 @@ static bool add_filemeta(sl_array_t *reqinfo,
}
}
} else if (strcmp(attribute, "kMDItemPath") == 0) {
- result = dalloc_stradd(meta, path);
+ result = dalloc_stradd(meta, nfd_path);
if (result != 0) {
return false;
}
@@ -713,7 +743,8 @@ bool mds_add_result(struct sl_query *slq, const char *path)
slq->state = SLQ_STATE_ERROR;
return false;
}
- ok = add_filemeta(slq->reqinfo,
+ ok = add_filemeta(slq->mds_ctx,
+ slq->reqinfo,
slq->query_results->fm_array,
path,
&sb);
@@ -940,7 +971,11 @@ static bool slrpc_open_query(struct mds_ctx *mds_ctx,
sl_cnids_t *cnids;
struct sl_query *slq = NULL;
int result;
- char *querystring;
+ const char *querystring = NULL;
+ size_t querystring_len;
+ char *dest = NULL;
+ size_t dest_remaining;
+ size_t nconv;
char *scope = NULL;
array = dalloc_zero(reply, sl_array_t);
@@ -979,16 +1014,26 @@ static bool slrpc_open_query(struct mds_ctx *mds_ctx,
DEBUG(1, ("missing kMDQueryString\n"));
goto error;
}
- slq->query_string = talloc_strdup(slq, querystring);
+
+ querystring_len = talloc_array_length(querystring);
+
+ slq->query_string = talloc_array(slq, char, querystring_len);
if (slq->query_string == NULL) {
DEBUG(1, ("out of memory\n"));
goto error;
}
+ dest = slq->query_string;
+ dest_remaining = talloc_array_length(dest);
- /*
- * FIXME: convert spotlight query charset from decomposed UTF8
- * to host charset precomposed UTF8.
- */
+ nconv = smb_iconv(mds_ctx->ic_nfd_to_nfc,
+ &querystring,
+ &querystring_len,
+ &dest,
+ &dest_remaining);
+ if (nconv == (size_t)-1) {
+ DBG_ERR("smb_iconv failed for: %s\n", querystring);
+ return false;
+ }
uint64p = dalloc_get(query, "DALLOC_CTX", 0, "DALLOC_CTX", 0,
"uint64_t", 1);
@@ -1422,7 +1467,7 @@ static bool slrpc_fetch_attributes(struct mds_ctx *mds_ctx,
goto error;
}
- ok = add_filemeta(reqinfo, fm_array, elem->path, &sb);
+ ok = add_filemeta(mds_ctx, reqinfo, fm_array, elem->path, &sb);
if (!ok) {
goto error;
}
@@ -1640,7 +1685,23 @@ struct mds_ctx *mds_init_ctx(TALLOC_CTX *mem_ctx,
default:
DBG_ERR("Unknown backend %d\n", backend);
TALLOC_FREE(mdssvc_ctx);
- return NULL;
+ goto error;
+ }
+
+ mds_ctx->ic_nfc_to_nfd = smb_iconv_open_ex(mds_ctx,
+ "UTF8-NFD",
+ "UTF8-NFC",
+ false);
+ if (mds_ctx->ic_nfc_to_nfd == (smb_iconv_t)-1) {
+ goto error;
+ }
+
+ mds_ctx->ic_nfd_to_nfc = smb_iconv_open_ex(mds_ctx,
+ "UTF8-NFC",
+ "UTF8-NFD",
+ false);
+ if (mds_ctx->ic_nfd_to_nfc == (smb_iconv_t)-1) {
+ goto error;
}
mds_ctx->sharename = talloc_strdup(mds_ctx, sharename);
@@ -1677,6 +1738,13 @@ struct mds_ctx *mds_init_ctx(TALLOC_CTX *mem_ctx,
return mds_ctx;
error:
+ if (mds_ctx->ic_nfc_to_nfd != NULL) {
+ smb_iconv_close(mds_ctx->ic_nfc_to_nfd);
+ }
+ if (mds_ctx->ic_nfd_to_nfc != NULL) {
+ smb_iconv_close(mds_ctx->ic_nfd_to_nfc);
+ }
+
TALLOC_FREE(mds_ctx);
return NULL;
}
diff --git a/source3/rpc_server/mdssvc/mdssvc.h b/source3/rpc_server/mdssvc/mdssvc.h
index bd76476dd32..6836e65ea06 100644
--- a/source3/rpc_server/mdssvc/mdssvc.h
+++ b/source3/rpc_server/mdssvc/mdssvc.h
@@ -88,7 +88,7 @@ struct sl_query {
uint64_t ctx1; /* client context 1 */
uint64_t ctx2; /* client context 2 */
sl_array_t *reqinfo; /* array with requested metadata */
- const char *query_string; /* the Spotlight query string */
+ char *query_string; /* the Spotlight query string */
uint64_t *cnids; /* restrict query to these CNIDs */
size_t cnids_num; /* Size of slq_cnids array */
const char *path_scope; /* path to directory to search */
@@ -122,6 +122,8 @@ struct mds_ctx {
struct auth_session_info *pipe_session_info;
struct dom_sid sid;
uid_t uid;
+ smb_iconv_t ic_nfc_to_nfd;
+ smb_iconv_t ic_nfd_to_nfc;
int snum;
const char *sharename;
const char *spath;