components/visual-panels/core/src/cmd/rad/mod/panels/mod_panels.c
changeset 1700 d04a7bb15a5b
parent 1699 152cafe6cd99
child 1701 279ed2832e3f
--- a/components/visual-panels/core/src/cmd/rad/mod/panels/mod_panels.c	Fri Feb 07 08:34:39 2014 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,534 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License (the "License").
- * You may not use this file except in compliance with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-
-/*
- * Copyright (c) 2009, 2013, Oracle and/or its affiliates. All rights reserved.
- */
-
-#include <assert.h>
-#include <dirent.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <libxml/tree.h>
-#include <limits.h>
-#include <openssl/evp.h>
-#include <openssl/md5.h>
-#include <string.h>
-#include <sys/stat.h>
-#include <unistd.h>
-#include "api_panel.h"
-
-#define	PANELDESCDIR	"/usr/share/vpanels/conf"
-
-#define	HASH_BSIZE	65536
-
-/*
- * Function prototypes
- */
-
-static int md5_file(const char *fname, unsigned char *hash);
-static adr_data_t *get_text(xmlDoc *doc, xmlNode *node);
-static char *get_text_str(xmlDoc *doc, xmlNode *node);
-static adr_data_t *get_prop(xmlNode *node, const char *name);
-static adr_data_t *file_to_token(rad_locale_t *rlocale, const char *pname,
-    char *file);
-static conerr_t token_to_file(adr_data_t *t, char **f);
-static adr_data_t *create_resource(rad_locale_t *rlocale, const char *pname,
-    char *file);
-static void add_localized(rad_locale_t *rlocale, const char *pname,
-    adr_data_t *farray, char *file);
-static adr_data_t *read_panel_path(rad_locale_t *rlocale, const char *path);
-static adr_data_t *read_panel(const char *locale, const char *pname);
-
-/*
- * Static data
- */
-
-static xmlDtd *dtd;
-
-/*
- * Static functions
- */
-
-static int
-md5_file(const char *fname, unsigned char *hash)
-{
-	int fd, len = -1;
-	MD5_CTX ctx;
-
-	char *buffer = malloc(HASH_BSIZE);
-	if (buffer == NULL)
-		return (-1);
-
-	if ((fd = open(fname, O_RDONLY)) == -1) {
-		free(buffer);
-		return (-1);
-	}
-
-	if (MD5_Init(&ctx) == 0)
-		goto out;
-
-	while ((len = read(fd, buffer, HASH_BSIZE)) > 0)
-		if (MD5_Update(&ctx, buffer, len) == 0) {
-			len = -1;
-			break;
-		}
-	if (MD5_Final(hash, &ctx) == 0)
-		len = -1;
-
-out:
-	(void) close(fd);
-	free(buffer);
-	return (len);	/* Should be 0 or -1 */
-}
-
-/*
- * Seems like overkill, but it's better than mixing xml-allocated
- * and other strings.
- */
-static adr_data_t *
-get_text(xmlDoc *doc, xmlNode *node)
-{
-	adr_data_t *result;
-	xmlChar *d = xmlNodeListGetString(doc, node, 1);
-	if (d == NULL)
-		return (NULL);
-
-	result = adr_data_new_string((char *)d, LT_COPY);
-	xmlFree(d);
-	return (result);
-}
-
-static char *
-get_text_str(xmlDoc *doc, xmlNode *node)
-{
-	char *result;
-	xmlChar *d = xmlNodeListGetString(doc, node, 1);
-	if (d == NULL)
-		return (NULL);
-
-	result = strdup((char *)d);
-	xmlFree(d);
-	return (result);
-}
-
-static adr_data_t *
-get_prop(xmlNode *node, const char *name)
-{
-	adr_data_t *result;
-	xmlChar *d = xmlGetProp(node, (xmlChar *)name);
-	if (d == NULL)
-		return (NULL);
-
-	result = adr_data_new_string((char *)d, LT_COPY);
-	xmlFree(d);
-	return (result);
-}
-
-static adr_data_t *
-file_to_token(rad_locale_t *rlocale, const char *pname, char *file)
-{
-	int llen = strlen(rlocale->locale);
-	int plen = strlen(pname);
-	int flen = strlen(file);
-	int tokenlen = llen + 1 + plen + 1 + flen + 1;
-
-	char *token = rad_zalloc(tokenlen);
-	if (token == NULL) {
-		return (NULL);
-	}
-
-	char *p = token;
-	(void) strcpy(p, rlocale->locale);
-	p += llen + 1;
-	(void) strcpy(p, pname);
-	p += plen + 1;
-	(void) strcpy(p, file);
-
-	return (adr_data_new_opaque(token, tokenlen, LT_FREE));
-}
-
-static conerr_t
-token_to_file(adr_data_t *t, char **f)
-{
-	char *token = adr_data_to_opaque(t);
-	char tokenlen = adr_opaque_size(t);
-
-	/* Cursory validation */
-	int nullcnt = 0;
-	for (int i = 0; i < tokenlen; i++) {
-		if (token[i] == '\0') {
-			nullcnt++;
-		}
-	}
-	if (nullcnt != 3 || token[tokenlen - 1] != '\0') {
-		/* Bad token */
-		return (CE_OBJECT);
-	}
-
-	char *locale = token;
-	char *pname = locale + strlen(locale) + 1;
-	char *file = pname + strlen(pname) + 1;
-
-	adr_data_t *panel = read_panel(locale, pname);
-	if (panel == NULL) {
-		/* Bad panel */
-		return (CE_OBJECT);
-	}
-
-	adr_data_t *resources = adr_struct_get(panel, "resourceDescriptors");
-	static const char * const path[] = { "file", NULL };
-	int index = adr_array_search(resources, file, path);
-	adr_data_free(panel);
-	if (index == -1) {
-		/* Bad file */
-		return (CE_OBJECT);
-	}
-
-	*f = strdup(file);
-	if (*f == NULL) {
-		return (CE_NOMEM);
-	}
-
-	return (CE_OK);
-}
-
-static adr_data_t *
-create_resource(rad_locale_t *rlocale, const char *pname, char *file)
-{
-	unsigned char hbuf[MD5_DIGEST_LENGTH];
-	if (md5_file(file, hbuf) != 0) {
-		return (NULL);
-	}
-
-	adr_data_t *result = adr_data_new_struct(&t__ResourceDescriptor);
-	adr_struct_set(result, "token", file_to_token(rlocale, pname, file));
-	adr_struct_set(result, "file", adr_data_new_string(file, LT_COPY));
-	adr_struct_set(result, "hashAlgorithm",
-	    adr_data_new_string("MD5", LT_CONST));
-	adr_struct_set(result, "hash",
-	    adr_data_new_opaque(hbuf, MD5_DIGEST_LENGTH, LT_COPY));
-
-	return (result);
-}
-
-static void
-add_localized(rad_locale_t *rlocale, const char *pname, adr_data_t *farray,
-    char *file)
-{
-	if (rlocale != NULL && rlocale->language != NULL &&
-	    strlen(rlocale->language)) {
-		char path[PATH_MAX + 1];
-		(void) strlcpy(path, file, PATH_MAX);
-
-		char *ext = strrchr(path, '.');
-		if (ext != NULL && strcmp(ext, ".jar") == 0) {
-			*ext = '\0';
-			char *base = strrchr(path, '/');
-			if (base == NULL) {
-				return;
-			}
-			*base++ = '\0';
-
-			char *fmt[] = {NULL, NULL, NULL};
-
-			/*
-			 * Use a ResourceBundle.getBundle-like algorithm -
-			 * <language>[_<territory>[@<modifier>]] - and order
-			 * from most- to least-specific.
-			 */
-			fmt[2] = "%s/locale/%s/%5$s_l10n.jar";
-			if (rlocale->territory != NULL) {
-				fmt[1] = "%s/locale/%s_%s/%5$s_l10n.jar";
-				if (rlocale->modifier != NULL) {
-					fmt[0] = "%s/locale/%s_%s@%s/"
-					    "%5$s_l10n.jar";
-				}
-			}
-
-			char l10njar[PATH_MAX];
-			for (int i = 0; i < RAD_COUNT(fmt); i++) {
-				if (fmt[i] == NULL) {
-					continue;
-				}
-				/* LINTED: E_SEC_PRINTF_VAR_FMT */
-				(void) snprintf(l10njar, RAD_COUNT(l10njar),
-				    fmt[i], path, rlocale->language,
-				    rlocale->territory, rlocale->modifier,
-				    base);
-				if (access(l10njar, F_OK) == 0) {
-					(void) adr_array_add(farray,
-					    create_resource(rlocale, pname,
-					    l10njar));
-				}
-			}
-		}
-	}
-	(void) adr_array_add(farray, create_resource(rlocale, pname, file));
-}
-
-static adr_data_t *
-read_panel_path(rad_locale_t *rlocale, const char *path)
-{
-	xmlParserCtxt *ctx;
-	xmlValidCtxt *vctx;
-	xmlDoc *doc;
-	adr_data_t *panel = NULL;
-
-	ctx = xmlNewParserCtxt();
-	vctx = xmlNewValidCtxt();
-	if (vctx == NULL || ctx == NULL)
-		return (NULL);
-
-	doc = xmlCtxtReadFile(ctx, path, NULL, 0);
-	if (doc == NULL) {
-		xmlFreeValidCtxt(vctx);
-		xmlFreeParserCtxt(ctx);
-		rad_log(RL_WARN, "Empty/no such document: %s\n", path);
-		return (NULL);
-	}
-
-	/*
-	 * Validate against *our* DTD.
-	 */
-	if (xmlValidateDtd(vctx, doc, dtd) == 0) {
-		rad_log(RL_WARN, "Invalid document: %s\n", path);
-		goto out;
-	}
-
-	xmlNodePtr root = xmlDocGetRootElement(doc);
-	if (root == NULL || strcmp((const char *)root->name, "panel") != 0) {
-		rad_log(RL_WARN, "Not a panel definition: %s\n", path);
-		goto out;
-	}
-
-	panel = adr_data_new_struct(&t__CustomPanel);
-	adr_struct_set(panel, "locale",
-	    adr_data_new_string(rlocale->locale, LT_COPY));
-
-	adr_data_t *pname = get_prop(root, "name");
-	adr_struct_set(panel, "name", pname);
-
-	adr_data_t *farray =
-	    adr_data_new_array(&t_array__ResourceDescriptor, 1);
-	adr_struct_set(panel, "resourceDescriptors", farray);
-
-	char *aroot = NULL;
-	for (xmlNode *np = root->children; np != NULL; np = np->next) {
-		if (np->type != XML_ELEMENT_NODE)
-			continue;
-		if (strcmp((const char *)np->name, "mainclass") == 0) {
-			adr_data_t *mc = get_text(doc, np->children);
-			adr_struct_set(panel, "panelDescriptorClassName", mc);
-		} else if (strcmp((const char *)np->name, "approot") == 0) {
-			if (aroot != NULL)
-				continue;	/* schema violation */
-			aroot = get_text_str(doc, np->children);
-		} else if (strcmp((const char *)np->name, "file") == 0) {
-			char *file = get_text_str(doc, np->children);
-			if (file == NULL) {
-				rad_log(RL_WARN,
-				    "Empty <file> declaration within %s\n",
-				    path);
-				continue;
-			}
-
-			if (aroot == NULL) {
-				rad_log(RL_WARN, "App root not specified\n");
-				continue;
-			}
-
-			char full[PATH_MAX];
-			(void) snprintf(full, RAD_COUNT(full), "%s/%s", aroot,
-			    file);
-			free(file);
-
-			add_localized(rlocale, adr_data_to_string(pname),
-			    farray, full);
-		}
-	}
-	if (aroot != NULL)
-		free(aroot);
-out:
-	xmlFreeValidCtxt(vctx);
-	xmlFreeDoc(doc);
-	xmlFreeParserCtxt(ctx);
-
-	return (adr_data_purify_deep(panel));
-}
-
-static adr_data_t *
-read_panel(const char *locale, const char *pname)
-{
-	rad_locale_t *rlocale;
-	if (rad_locale_parse(locale, &rlocale) != 0) {
-		return (NULL);
-	}
-
-	char path[PATH_MAX];
-	(void) snprintf(path, RAD_COUNT(path), "%s/%s.xml", PANELDESCDIR,
-	    pname);
-	adr_data_t *panel = read_panel_path(rlocale, path);
-
-	if (panel != NULL) {
-		/* Sanity check - ensure panel @name matches file name */
-		adr_data_t *nameattr = adr_struct_get(panel, "name");
-		if (strcmp(adr_data_to_string(nameattr), pname) != 0) {
-			adr_data_free(panel);
-			panel = NULL;
-		}
-	}
-
-	rad_locale_free(rlocale);
-
-	return (panel);
-}
-
-/*
- * Extern functions
- */
-
-int
-_rad_init(void)
-{
-	dtd = xmlParseDTD(NULL,
-	    (xmlChar *)"/usr/share/lib/xml/dtd/vpanel.dtd.1");
-
-	adr_name_t *aname = adr_name_vcreate(MOD_DOMAIN, 1, "type", "Panel");
-	conerr_t cerr =  rad_cont_insert_singleton(rad_container, aname,
-	    &modinfo, &interface_Panel_svr);
-	adr_name_rele(aname);
-	if (cerr != CE_OK) {
-		rad_log(RL_ERROR, "(mod_panels) failed to insert Panel");
-		return (-1);
-	}
-
-	return (0);
-}
-
-/*
- * _rad_fini is called by the RAD daemon when the module is unloaded. Any
- * module finalisation is completed here.
- */
-/*ARGSUSED*/
-void
-_rad_fini(void *unused)
-{
-}
-
-/* ARGSUSED */
-conerr_t
-interface_Panel_invoke_getPanel(rad_instance_t *inst, adr_method_t *meth,
-    adr_data_t **ret, adr_data_t **args, int count, adr_data_t **error)
-{
-	const char *pname = adr_data_to_string(args[0]);
-	const char *locale = args[1] == NULL ? NULL :
-	    adr_data_to_string(args[1]);
-
-	adr_data_t *panel = read_panel(locale, pname);
-	if (panel == NULL) {
-		/*
-		 * Could be a memory or system error, but more likely an invalid
-		 * name was specified.
-		 */
-		return (CE_OBJECT);
-	}
-	*ret = panel;
-
-	return (CE_OK);
-}
-
-/* ARGSUSED */
-conerr_t
-interface_Panel_read_panelNames(rad_instance_t *inst, adr_attribute_t *attr,
-    adr_data_t **data, adr_data_t **error)
-{
-	adr_data_t *array = adr_data_new_array(&adr_t_array_string, 0);
-	if (array == NULL) {
-		return (CE_NOMEM);
-	}
-
-	DIR *d;
-	if ((d = opendir(PANELDESCDIR)) == NULL) {
-		if (errno == ENOENT) {
-			return (CE_OK);
-		}
-		return (CE_SYSTEM);
-	}
-
-	struct dirent *ent;
-	while ((ent = readdir(d)) != NULL) {
-		char *ext = ".xml";
-		size_t len = strlen(ent->d_name) - strlen(ext);
-		if (len < 1 || strcmp(ent->d_name + len, ext) != 0) {
-			continue;
-		}
-		(void) adr_array_add(array,
-		    adr_data_new_nstring(ent->d_name, len));
-	}
-
-	(void) closedir(d);
-	*data = adr_data_purify(array);
-
-	return (*data == NULL ? CE_NOMEM : CE_OK);
-}
-
-/* ARGSUSED */
-conerr_t
-interface_Panel_invoke_getResource(rad_instance_t *inst, adr_method_t *meth,
-    adr_data_t **ret, adr_data_t **args, int count, adr_data_t **error)
-{
-	char *file;
-	conerr_t result = token_to_file(args[0], &file);
-	if (result != CE_OK) {
-		return (result);
-	}
-
-	struct stat st;
-	if (stat(file, &st) != 0) {
-		free(file);
-		return (CE_OBJECT);
-	}
-
-	char *buffer = malloc(st.st_size);
-	if (buffer == NULL) {
-		free(file);
-		return (CE_NOMEM);
-	}
-
-	int fd = open(file, O_RDONLY);
-	free(file);
-	if (fd == -1) {
-		free(buffer);
-		return (CE_PRIV);
-	}
-
-	if (read(fd, buffer, st.st_size) != st.st_size) {
-		(void) close(fd);
-		free(buffer);
-		return (CE_SYSTEM);
-	}
-
-	(void) close(fd);
-
-	*ret = adr_data_new_opaque(buffer, st.st_size, LT_FREE);
-	return (*ret == NULL ? CE_NOMEM : CE_OK);
-}