--- 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);
-}