components/visual-panels/core/src/cmd/rad/mod/panels/mod_panels.c
changeset 901 19b502ccabc8
parent 827 0944d8c0158b
child 1410 ca9946e5736c
equal deleted inserted replaced
900:63d3bf696d85 901:19b502ccabc8
    43 /*
    43 /*
    44  * Function prototypes
    44  * Function prototypes
    45  */
    45  */
    46 
    46 
    47 static int md5_file(const char *fname, unsigned char *hash);
    47 static int md5_file(const char *fname, unsigned char *hash);
    48 static data_t *get_text(xmlDoc *doc, xmlNode *node);
    48 static adr_data_t *get_text(xmlDoc *doc, xmlNode *node);
    49 static char *get_text_str(xmlDoc *doc, xmlNode *node);
    49 static char *get_text_str(xmlDoc *doc, xmlNode *node);
    50 static data_t *get_prop(xmlNode *node, const char *name);
    50 static adr_data_t *get_prop(xmlNode *node, const char *name);
    51 static data_t *file_to_token(rad_locale_t *rlocale, const char *pname,
    51 static adr_data_t *file_to_token(rad_locale_t *rlocale, const char *pname,
    52     char *file);
    52     char *file);
    53 static conerr_t token_to_file(data_t *t, char **f);
    53 static conerr_t token_to_file(adr_data_t *t, char **f);
    54 static data_t *create_resource(rad_locale_t *rlocale, const char *pname,
    54 static adr_data_t *create_resource(rad_locale_t *rlocale, const char *pname,
    55     char *file);
    55     char *file);
    56 static void add_localized(rad_locale_t *rlocale, const char *pname,
    56 static void add_localized(rad_locale_t *rlocale, const char *pname,
    57     data_t *farray, char *file);
    57     adr_data_t *farray, char *file);
    58 static data_t *read_panel_path(rad_locale_t *rlocale, const char *path);
    58 static adr_data_t *read_panel_path(rad_locale_t *rlocale, const char *path);
    59 static data_t *read_panel(const char *locale, const char *pname);
    59 static adr_data_t *read_panel(const char *locale, const char *pname);
    60 
    60 
    61 /*
    61 /*
    62  * Static data
    62  * Static data
    63  */
    63  */
    64 
    64 
   103 
   103 
   104 /*
   104 /*
   105  * Seems like overkill, but it's better than mixing xml-allocated
   105  * Seems like overkill, but it's better than mixing xml-allocated
   106  * and other strings.
   106  * and other strings.
   107  */
   107  */
   108 static data_t *
   108 static adr_data_t *
   109 get_text(xmlDoc *doc, xmlNode *node)
   109 get_text(xmlDoc *doc, xmlNode *node)
   110 {
   110 {
   111 	data_t *result;
   111 	adr_data_t *result;
   112 	xmlChar *d = xmlNodeListGetString(doc, node, 1);
   112 	xmlChar *d = xmlNodeListGetString(doc, node, 1);
   113 	if (d == NULL)
   113 	if (d == NULL)
   114 		return (NULL);
   114 		return (NULL);
   115 
   115 
   116 	result = data_new_string((char *)d, lt_copy);
   116 	result = adr_data_new_string((char *)d, LT_COPY);
   117 	xmlFree(d);
   117 	xmlFree(d);
   118 	return (result);
   118 	return (result);
   119 }
   119 }
   120 
   120 
   121 static char *
   121 static char *
   129 	result = strdup((char *)d);
   129 	result = strdup((char *)d);
   130 	xmlFree(d);
   130 	xmlFree(d);
   131 	return (result);
   131 	return (result);
   132 }
   132 }
   133 
   133 
   134 static data_t *
   134 static adr_data_t *
   135 get_prop(xmlNode *node, const char *name)
   135 get_prop(xmlNode *node, const char *name)
   136 {
   136 {
   137 	data_t *result;
   137 	adr_data_t *result;
   138 	xmlChar *d = xmlGetProp(node, (xmlChar *)name);
   138 	xmlChar *d = xmlGetProp(node, (xmlChar *)name);
   139 	if (d == NULL)
   139 	if (d == NULL)
   140 		return (NULL);
   140 		return (NULL);
   141 
   141 
   142 	result = data_new_string((char *)d, lt_copy);
   142 	result = adr_data_new_string((char *)d, LT_COPY);
   143 	xmlFree(d);
   143 	xmlFree(d);
   144 	return (result);
   144 	return (result);
   145 }
   145 }
   146 
   146 
   147 static data_t *
   147 static adr_data_t *
   148 file_to_token(rad_locale_t *rlocale, const char *pname, char *file)
   148 file_to_token(rad_locale_t *rlocale, const char *pname, char *file)
   149 {
   149 {
   150 	int llen = strlen(rlocale->locale);
   150 	int llen = strlen(rlocale->locale);
   151 	int plen = strlen(pname);
   151 	int plen = strlen(pname);
   152 	int flen = strlen(file);
   152 	int flen = strlen(file);
   162 	p += llen + 1;
   162 	p += llen + 1;
   163 	(void) strcpy(p, pname);
   163 	(void) strcpy(p, pname);
   164 	p += plen + 1;
   164 	p += plen + 1;
   165 	(void) strcpy(p, file);
   165 	(void) strcpy(p, file);
   166 
   166 
   167 	return (data_new_opaque(token, tokenlen, lt_free));
   167 	return (adr_data_new_opaque(token, tokenlen, LT_FREE));
   168 }
   168 }
   169 
   169 
   170 static conerr_t
   170 static conerr_t
   171 token_to_file(data_t *t, char **f)
   171 token_to_file(adr_data_t *t, char **f)
   172 {
   172 {
   173 	char *token = data_to_opaque(t);
   173 	char *token = adr_data_to_opaque(t);
   174 	char tokenlen = opaque_size(t);
   174 	char tokenlen = adr_opaque_size(t);
   175 
   175 
   176 	/* Cursory validation */
   176 	/* Cursory validation */
   177 	int nullcnt = 0;
   177 	int nullcnt = 0;
   178 	for (int i = 0; i < tokenlen; i++) {
   178 	for (int i = 0; i < tokenlen; i++) {
   179 		if (token[i] == '\0') {
   179 		if (token[i] == '\0') {
   187 
   187 
   188 	char *locale = token;
   188 	char *locale = token;
   189 	char *pname = locale + strlen(locale) + 1;
   189 	char *pname = locale + strlen(locale) + 1;
   190 	char *file = pname + strlen(pname) + 1;
   190 	char *file = pname + strlen(pname) + 1;
   191 
   191 
   192 	data_t *panel = read_panel(locale, pname);
   192 	adr_data_t *panel = read_panel(locale, pname);
   193 	if (panel == NULL) {
   193 	if (panel == NULL) {
   194 		/* Bad panel */
   194 		/* Bad panel */
   195 		return (ce_object);
   195 		return (ce_object);
   196 	}
   196 	}
   197 
   197 
   198 	data_t *resources = struct_get(panel, "resourceDescriptors");
   198 	adr_data_t *resources = adr_struct_get(panel, "resourceDescriptors");
   199 	static const char * const path[] = { "file", NULL };
   199 	static const char * const path[] = { "file", NULL };
   200 	int index = array_search(resources, file, path);
   200 	int index = adr_array_search(resources, file, path);
   201 	data_free(panel);
   201 	adr_data_free(panel);
   202 	if (index == -1) {
   202 	if (index == -1) {
   203 		/* Bad file */
   203 		/* Bad file */
   204 		return (ce_object);
   204 		return (ce_object);
   205 	}
   205 	}
   206 
   206 
   210 	}
   210 	}
   211 
   211 
   212 	return (ce_ok);
   212 	return (ce_ok);
   213 }
   213 }
   214 
   214 
   215 static data_t *
   215 static adr_data_t *
   216 create_resource(rad_locale_t *rlocale, const char *pname, char *file)
   216 create_resource(rad_locale_t *rlocale, const char *pname, char *file)
   217 {
   217 {
   218 	unsigned char hbuf[MD5_DIGEST_LENGTH];
   218 	unsigned char hbuf[MD5_DIGEST_LENGTH];
   219 	if (md5_file(file, hbuf) != 0) {
   219 	if (md5_file(file, hbuf) != 0) {
   220 		return (NULL);
   220 		return (NULL);
   221 	}
   221 	}
   222 
   222 
   223 	data_t *result = data_new_struct(&t__ResourceDescriptor);
   223 	adr_data_t *result = adr_data_new_struct(&t__ResourceDescriptor);
   224 	struct_set(result, "token", file_to_token(rlocale, pname, file));
   224 	adr_struct_set(result, "token", file_to_token(rlocale, pname, file));
   225 	struct_set(result, "file", data_new_string(file, lt_copy));
   225 	adr_struct_set(result, "file", adr_data_new_string(file, LT_COPY));
   226 	struct_set(result, "hashAlgorithm", data_new_string("MD5", lt_const));
   226 	adr_struct_set(result, "hashAlgorithm",
   227 	struct_set(result, "hash", data_new_opaque(hbuf, MD5_DIGEST_LENGTH,
   227 	    adr_data_new_string("MD5", LT_CONST));
   228 	    lt_copy));
   228 	adr_struct_set(result, "hash",
       
   229 	    adr_data_new_opaque(hbuf, MD5_DIGEST_LENGTH, LT_COPY));
   229 
   230 
   230 	return (result);
   231 	return (result);
   231 }
   232 }
   232 
   233 
   233 static void
   234 static void
   234 add_localized(rad_locale_t *rlocale, const char *pname, data_t *farray,
   235 add_localized(rad_locale_t *rlocale, const char *pname, adr_data_t *farray,
   235     char *file)
   236     char *file)
   236 {
   237 {
   237 	if (rlocale != NULL && rlocale->language != NULL &&
   238 	if (rlocale != NULL && rlocale->language != NULL &&
   238 	    strlen(rlocale->language)) {
   239 	    strlen(rlocale->language)) {
   239 		char path[PATH_MAX + 1];
   240 		char path[PATH_MAX + 1];
   273 				(void) snprintf(l10njar, RAD_COUNT(l10njar),
   274 				(void) snprintf(l10njar, RAD_COUNT(l10njar),
   274 				    fmt[i], path, rlocale->language,
   275 				    fmt[i], path, rlocale->language,
   275 				    rlocale->territory, rlocale->modifier,
   276 				    rlocale->territory, rlocale->modifier,
   276 				    base);
   277 				    base);
   277 				if (access(l10njar, F_OK) == 0) {
   278 				if (access(l10njar, F_OK) == 0) {
   278 					(void) array_add(farray,
   279 					(void) adr_array_add(farray,
   279 					    create_resource(rlocale, pname,
   280 					    create_resource(rlocale, pname,
   280 					    l10njar));
   281 					    l10njar));
   281 				}
   282 				}
   282 			}
   283 			}
   283 		}
   284 		}
   284 	}
   285 	}
   285 	(void) array_add(farray, create_resource(rlocale, pname, file));
   286 	(void) adr_array_add(farray, create_resource(rlocale, pname, file));
   286 }
   287 }
   287 
   288 
   288 static data_t *
   289 static adr_data_t *
   289 read_panel_path(rad_locale_t *rlocale, const char *path)
   290 read_panel_path(rad_locale_t *rlocale, const char *path)
   290 {
   291 {
   291 	xmlParserCtxt *ctx;
   292 	xmlParserCtxt *ctx;
   292 	xmlValidCtxt *vctx;
   293 	xmlValidCtxt *vctx;
   293 	xmlDoc *doc;
   294 	xmlDoc *doc;
   294 	data_t *panel = NULL;
   295 	adr_data_t *panel = NULL;
   295 
   296 
   296 	ctx = xmlNewParserCtxt();
   297 	ctx = xmlNewParserCtxt();
   297 	vctx = xmlNewValidCtxt();
   298 	vctx = xmlNewValidCtxt();
   298 	if (vctx == NULL || ctx == NULL)
   299 	if (vctx == NULL || ctx == NULL)
   299 		return (NULL);
   300 		return (NULL);
   318 	if (root == NULL || strcmp((const char *)root->name, "panel") != 0) {
   319 	if (root == NULL || strcmp((const char *)root->name, "panel") != 0) {
   319 		rad_log(RL_WARN, "Not a panel definition: %s\n", path);
   320 		rad_log(RL_WARN, "Not a panel definition: %s\n", path);
   320 		goto out;
   321 		goto out;
   321 	}
   322 	}
   322 
   323 
   323 	panel = data_new_struct(&t__CustomPanel);
   324 	panel = adr_data_new_struct(&t__CustomPanel);
   324 	struct_set(panel, "locale", data_new_string(rlocale->locale, lt_copy));
   325 	adr_struct_set(panel, "locale",
   325 
   326 	    adr_data_new_string(rlocale->locale, LT_COPY));
   326 	data_t *pname = get_prop(root, "name");
   327 
   327 	struct_set(panel, "name", pname);
   328 	adr_data_t *pname = get_prop(root, "name");
   328 
   329 	adr_struct_set(panel, "name", pname);
   329 	data_t *farray = data_new_array(&t_array__ResourceDescriptor, 1);
   330 
   330 	struct_set(panel, "resourceDescriptors", farray);
   331 	adr_data_t *farray =
       
   332 	    adr_data_new_array(&t_array__ResourceDescriptor, 1);
       
   333 	adr_struct_set(panel, "resourceDescriptors", farray);
   331 
   334 
   332 	char *aroot = NULL;
   335 	char *aroot = NULL;
   333 	for (xmlNode *np = root->children; np != NULL; np = np->next) {
   336 	for (xmlNode *np = root->children; np != NULL; np = np->next) {
   334 		if (np->type != XML_ELEMENT_NODE)
   337 		if (np->type != XML_ELEMENT_NODE)
   335 			continue;
   338 			continue;
   336 		if (strcmp((const char *)np->name, "mainclass") == 0) {
   339 		if (strcmp((const char *)np->name, "mainclass") == 0) {
   337 			data_t *mc = get_text(doc, np->children);
   340 			adr_data_t *mc = get_text(doc, np->children);
   338 			struct_set(panel, "panelDescriptorClassName", mc);
   341 			adr_struct_set(panel, "panelDescriptorClassName", mc);
   339 		} else if (strcmp((const char *)np->name, "approot") == 0) {
   342 		} else if (strcmp((const char *)np->name, "approot") == 0) {
   340 			if (aroot != NULL)
   343 			if (aroot != NULL)
   341 				continue;	/* schema violation */
   344 				continue;	/* schema violation */
   342 			aroot = get_text_str(doc, np->children);
   345 			aroot = get_text_str(doc, np->children);
   343 		} else if (strcmp((const char *)np->name, "file") == 0) {
   346 		} else if (strcmp((const char *)np->name, "file") == 0) {
   357 			char full[PATH_MAX];
   360 			char full[PATH_MAX];
   358 			(void) snprintf(full, RAD_COUNT(full), "%s/%s", aroot,
   361 			(void) snprintf(full, RAD_COUNT(full), "%s/%s", aroot,
   359 			    file);
   362 			    file);
   360 			free(file);
   363 			free(file);
   361 
   364 
   362 			add_localized(rlocale, data_to_string(pname), farray,
   365 			add_localized(rlocale, adr_data_to_string(pname),
   363 			    full);
   366 			    farray, full);
   364 		}
   367 		}
   365 	}
   368 	}
   366 	if (aroot != NULL)
   369 	if (aroot != NULL)
   367 		free(aroot);
   370 		free(aroot);
   368 out:
   371 out:
   369 	xmlFreeValidCtxt(vctx);
   372 	xmlFreeValidCtxt(vctx);
   370 	xmlFreeDoc(doc);
   373 	xmlFreeDoc(doc);
   371 	xmlFreeParserCtxt(ctx);
   374 	xmlFreeParserCtxt(ctx);
   372 
   375 
   373 	return (data_purify_deep(panel));
   376 	return (adr_data_purify_deep(panel));
   374 }
   377 }
   375 
   378 
   376 static data_t *
   379 static adr_data_t *
   377 read_panel(const char *locale, const char *pname)
   380 read_panel(const char *locale, const char *pname)
   378 {
   381 {
   379 	rad_locale_t *rlocale;
   382 	rad_locale_t *rlocale;
   380 	if (rad_locale_parse(locale, &rlocale) != 0) {
   383 	if (rad_locale_parse(locale, &rlocale) != 0) {
   381 		return (NULL);
   384 		return (NULL);
   382 	}
   385 	}
   383 
   386 
   384 	char path[PATH_MAX];
   387 	char path[PATH_MAX];
   385 	(void) snprintf(path, RAD_COUNT(path), "%s/%s.xml", PANELDESCDIR,
   388 	(void) snprintf(path, RAD_COUNT(path), "%s/%s.xml", PANELDESCDIR,
   386 	    pname);
   389 	    pname);
   387 	data_t *panel = read_panel_path(rlocale, path);
   390 	adr_data_t *panel = read_panel_path(rlocale, path);
   388 
   391 
   389 	if (panel != NULL) {
   392 	if (panel != NULL) {
   390 		/* Sanity check - ensure panel @name matches file name */
   393 		/* Sanity check - ensure panel @name matches file name */
   391 		data_t *nameattr = struct_get(panel, "name");
   394 		adr_data_t *nameattr = adr_struct_get(panel, "name");
   392 		if (strcmp(data_to_string(nameattr), pname) != 0) {
   395 		if (strcmp(adr_data_to_string(nameattr), pname) != 0) {
   393 			data_free(panel);
   396 			adr_data_free(panel);
   394 			panel = NULL;
   397 			panel = NULL;
   395 		}
   398 		}
   396 	}
   399 	}
   397 
   400 
   398 	rad_locale_free(rlocale);
   401 	rad_locale_free(rlocale);
   421 }
   424 }
   422 
   425 
   423 /* ARGSUSED */
   426 /* ARGSUSED */
   424 conerr_t
   427 conerr_t
   425 interface_Panel_invoke_getPanel(rad_instance_t *inst, adr_method_t *meth,
   428 interface_Panel_invoke_getPanel(rad_instance_t *inst, adr_method_t *meth,
   426     data_t **ret, data_t **args, int count, data_t **error)
   429     adr_data_t **ret, adr_data_t **args, int count, adr_data_t **error)
   427 {
   430 {
   428 	const char *pname = data_to_string(args[0]);
   431 	const char *pname = adr_data_to_string(args[0]);
   429 	const char *locale = args[1] == NULL ? NULL : data_to_string(args[1]);
   432 	const char *locale = args[1] == NULL ? NULL :
   430 
   433 	    adr_data_to_string(args[1]);
   431 	data_t *panel = read_panel(locale, pname);
   434 
       
   435 	adr_data_t *panel = read_panel(locale, pname);
   432 	if (panel == NULL) {
   436 	if (panel == NULL) {
   433 		/*
   437 		/*
   434 		 * Could be a memory or system error, but more likely an invalid
   438 		 * Could be a memory or system error, but more likely an invalid
   435 		 * name was specified.
   439 		 * name was specified.
   436 		 */
   440 		 */
   442 }
   446 }
   443 
   447 
   444 /* ARGSUSED */
   448 /* ARGSUSED */
   445 conerr_t
   449 conerr_t
   446 interface_Panel_read_panelNames(rad_instance_t *inst, adr_attribute_t *attr,
   450 interface_Panel_read_panelNames(rad_instance_t *inst, adr_attribute_t *attr,
   447     data_t **data, data_t **error)
   451     adr_data_t **data, adr_data_t **error)
   448 {
   452 {
   449 	data_t *array = data_new_array(&t_array_string, 0);
   453 	adr_data_t *array = adr_data_new_array(&adr_t_array_string, 0);
   450 	if (array == NULL) {
   454 	if (array == NULL) {
   451 		return (ce_nomem);
   455 		return (ce_nomem);
   452 	}
   456 	}
   453 
   457 
   454 	DIR *d;
   458 	DIR *d;
   464 		char *ext = ".xml";
   468 		char *ext = ".xml";
   465 		size_t len = strlen(ent->d_name) - strlen(ext);
   469 		size_t len = strlen(ent->d_name) - strlen(ext);
   466 		if (len < 1 || strcmp(ent->d_name + len, ext) != 0) {
   470 		if (len < 1 || strcmp(ent->d_name + len, ext) != 0) {
   467 			continue;
   471 			continue;
   468 		}
   472 		}
   469 		(void) array_add(array, data_new_nstring(ent->d_name, len));
   473 		(void) adr_array_add(array,
       
   474 		    adr_data_new_nstring(ent->d_name, len));
   470 	}
   475 	}
   471 
   476 
   472 	(void) closedir(d);
   477 	(void) closedir(d);
   473 	*data = data_purify(array);
   478 	*data = adr_data_purify(array);
   474 
   479 
   475 	return (*data == NULL ? ce_nomem : ce_ok);
   480 	return (*data == NULL ? ce_nomem : ce_ok);
   476 }
   481 }
   477 
   482 
   478 /* ARGSUSED */
   483 /* ARGSUSED */
   479 conerr_t
   484 conerr_t
   480 interface_Panel_invoke_getResource(rad_instance_t *inst, adr_method_t *meth,
   485 interface_Panel_invoke_getResource(rad_instance_t *inst, adr_method_t *meth,
   481     data_t **ret, data_t **args, int count, data_t **error)
   486     adr_data_t **ret, adr_data_t **args, int count, adr_data_t **error)
   482 {
   487 {
   483 	char *file;
   488 	char *file;
   484 	conerr_t result = token_to_file(args[0], &file);
   489 	conerr_t result = token_to_file(args[0], &file);
   485 	if (result != ce_ok) {
   490 	if (result != ce_ok) {
   486 		return (result);
   491 		return (result);
   511 		return (ce_system);
   516 		return (ce_system);
   512 	}
   517 	}
   513 
   518 
   514 	(void) close(fd);
   519 	(void) close(fd);
   515 
   520 
   516 	*ret = data_new_opaque(buffer, st.st_size, lt_free);
   521 	*ret = adr_data_new_opaque(buffer, st.st_size, LT_FREE);
   517 	return (*ret == NULL ? ce_nomem : ce_ok);
   522 	return (*ret == NULL ? ce_nomem : ce_ok);
   518 }
   523 }