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 */ |
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); |