diff options
author | Ralph Boehme <slow@samba.org> | 2019-04-09 11:19:43 +0200 |
---|---|---|
committer | Jeremy Allison <jra@samba.org> | 2019-08-08 20:24:31 +0000 |
commit | b5731a94bbc95fa001059d488a2c16a988127619 (patch) | |
tree | d1d0fe22cf691c0c372b9869c609eab053488c7f /source3/rpc_server | |
parent | 1b897df4f7489c6ac7663ca4830dc4c129dd2457 (diff) | |
download | samba-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.c | 92 | ||||
-rw-r--r-- | source3/rpc_server/mdssvc/mdssvc.h | 4 |
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; |