1 /*
2   LibRCC - module responsible for library initialization
3 
4   Copyright (C) 2005-2008 Suren A. Chilingaryan <csa@dside.dyndns.org>
5 
6   This library is free software; you can redistribute it and/or modify it
7   under the terms of the GNU Lesser General Public License version 2.1 or later
8   as published by the Free Software Foundation.
9 
10   This library is distributed in the hope that it will be useful, but WITHOUT
11   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
13   for more details.
14 
15   You should have received a copy of the GNU Lesser General Public License
16   along with this program; if not, write to the Free Software Foundation, Inc.,
17   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 */
19 
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <time.h>
23 #include <errno.h>
24 
25 #include <string.h>
26 #ifdef HAVE_STRINGS_H
27 # include <strings.h>
28 #endif /* HAVE_STRINGS_H */
29 
30 
31 #include "../config.h"
32 
33 #ifdef HAVE_UNISTD_H
34 # include <unistd.h>
35 #endif /* HAVE_UNISTD_H */
36 
37 #ifdef HAVE_SYS_TYPES_H
38 # include <sys/types.h>
39 #endif /* HAVE_SYS_TYPES_H */
40 #ifdef HAVE_SYS_STAT_H
41 # include <sys/stat.h>
42 #endif /* HAVE_SYS_STAT_H */
43 
44 #ifdef HAVE_PWD_H
45 # include <pwd.h>
46 #endif /* HAVE_PWD_H */
47 
48 #ifdef HAVE_SYS_FILE_H
49 # include <sys/file.h>
50 #endif /* HAVE_SYS_FILE_H */
51 
52 
53 #include "internal.h"
54 #include "rccconfig.h"
55 #include "rccenca.h"
56 #include "rcclist.h"
57 #include "plugin.h"
58 #include "engine.h"
59 #include "rccxml.h"
60 #include "rccexternal.h"
61 #include "rcctranslate.h"
62 #include "rcclock.h"
63 #include "rcchome.h"
64 
65 static int initialized = 0;
66 rcc_context rcc_default_ctx = NULL;
67 static rcc_compiled_configuration_s compiled_configuration;
68 
rccGetCompiledConfiguration()69 rcc_compiled_configuration rccGetCompiledConfiguration() {
70     compiled_configuration.flags = 0;
71 #ifdef HAVE_RCD
72     compiled_configuration.flags|=RCC_CC_FLAG_HAVE_RCD;
73 #endif /* HAVE_RCD */
74 #ifdef HAVE_ENCA
75     compiled_configuration.flags|=RCC_CC_FLAG_HAVE_ENCA;
76 #endif /* HAVE_ENCA */
77 #ifdef HAVE_DLOPEN
78     compiled_configuration.flags|=RCC_CC_FLAG_HAVE_DYNAMIC_ENGINES;
79 #endif /* HAVE_DLOPEN */
80 #ifdef HAVE_DB_H
81     compiled_configuration.flags|=RCC_CC_FLAG_HAVE_BERKLEY_DB;
82 #endif /* HAVE_DB_H */
83 #ifdef HAVE_LIBTRANSLATE
84     compiled_configuration.flags|=RCC_CC_FLAG_HAVE_LIBTRANSLATE;
85 #endif /* HAVE_LIBTRANSLATE */
86 
87     return &compiled_configuration;
88 }
89 
rccInit(void)90 int rccInit(void) {
91     int err;
92     unsigned long i, rpos;
93 
94     if (initialized) return 0;
95 
96     rccHomeSet();
97 
98     memcpy(rcc_default_languages, rcc_default_languages_embeded, (RCC_MAX_LANGUAGES + 1)*sizeof(rcc_language));
99     memcpy(rcc_default_aliases, rcc_default_aliases_embeded, (RCC_MAX_ALIASES + 1)*sizeof(rcc_language_alias));
100     memcpy(rcc_default_relations, rcc_default_relations_embeded, (RCC_MAX_RELATIONS + 1)*sizeof(rcc_language_relation));
101     memcpy(rcc_option_descriptions, rcc_option_descriptions_embeded, (RCC_MAX_OPTIONS + 1)*sizeof(rcc_option_description));
102 
103 #ifdef HAVE_LIBTRANSLATE
104     rccExternalInit();
105 #endif /* HAVE_LIBTRANSLATE */
106 
107     for (rpos=0;rcc_default_relations[rpos].lang;rpos++);
108     for (i=0;rcc_default_languages[i].sn;i++) {
109 	if (!strcasecmp(rcc_default_languages[i].sn, rcc_default_language_sn)) continue;
110 	if (!strcasecmp(rcc_default_languages[i].sn, rcc_disabled_language_sn)) continue;
111 	if (!strcasecmp(rcc_default_languages[i].sn, rcc_english_language_sn)) continue;
112 
113 	rcc_default_relations[rpos].lang = rcc_default_languages[i].sn;
114 	rcc_default_relations[rpos++].parent = rcc_english_language_sn;
115     }
116     rcc_default_relations[rpos].lang = NULL;
117     rcc_default_relations[rpos].parent = NULL;
118 
119     err = rccPluginInit();
120     if (!err) err = rccTranslateInit();
121     if (!err) err = rccXmlInit(1);
122     if (!err) err = rccEngineInit();
123 
124     if (err) {
125 	rccFree();
126 	return err;
127     }
128 
129     initialized = 1;
130 
131     return 0;
132 }
133 
rccFree(void)134 void rccFree(void) {
135     if (rcc_default_ctx) {
136 	rccFreeContext(rcc_default_ctx);
137 	rcc_default_ctx = NULL;
138     }
139 
140     rccEngineFree();
141     rccXmlFree();
142     rccTranslateFree();
143     rccPluginFree();
144 
145     rccExternalFree();
146 
147     rccHomeFree();
148 
149     initialized = 0;
150 }
151 
rccCreateContext(const char * locale_variable,unsigned int max_languages,unsigned int max_classes,rcc_class_ptr defclasses,rcc_init_flags flags)152 rcc_context rccCreateContext(const char *locale_variable, unsigned int max_languages, unsigned int max_classes, rcc_class_ptr defclasses, rcc_init_flags flags) {
153     unsigned int i;
154 
155     rcc_context ctx;
156     rcc_language_ptr *languages;
157     rcc_language_internal *ilang;
158     rcc_class_ptr *classes;
159     rcc_class_internal *iclass;
160     rcc_language_config configs;
161     rcc_iconv *from;
162     rcc_mutex mutex;
163 
164     if (!initialized) return NULL;
165 
166     if (!max_languages) {
167 	if (flags&RCC_FLAG_NO_DEFAULT_CONFIGURATION) max_languages = RCC_MAX_LANGUAGES;
168 	else {
169 	    for (i=0;rcc_default_languages[i].sn;i++);
170 	    max_languages = i;
171 	}
172     }
173 
174     if (!max_classes) {
175 	if (defclasses) {
176 	    for (i=0;defclasses[i].name;i++);
177 	    max_classes = i;
178 	} else max_classes = RCC_MAX_CLASSES;
179     }
180 
181     ctx = (rcc_context)malloc(sizeof(struct rcc_context_t));
182     languages = (rcc_language_ptr*)malloc((max_languages+1)*sizeof(rcc_language_ptr));
183     classes = (rcc_class_ptr*)malloc((max_classes+1)*sizeof(rcc_class_ptr));
184     from = (rcc_iconv*)malloc((max_classes)*sizeof(rcc_iconv));
185     ilang = (rcc_language_internal*)malloc((max_languages+1)*sizeof(rcc_language_internal));
186     iclass = (rcc_class_internal*)malloc((max_classes+1)*sizeof(rcc_class_internal));
187     mutex = rccMutexCreate();
188 
189     configs = (rcc_language_config)malloc((max_languages)*sizeof(struct rcc_language_config_t));
190 
191     if ((!ctx)||(!languages)||(!classes)||(!mutex)||(!from)||(!ilang)||(!iclass)||(!mutex)) {
192 	if (mutex) rccMutexFree(mutex);
193 	if (from) free(from);
194 	if (configs) free(configs);
195 	if (classes) free(classes);
196 	if (languages) free(languages);
197 	if (ilang) free(ilang);
198 	if (iclass) free(iclass);
199 	if (ctx) free(ctx);
200 	return NULL;
201     }
202 
203     ctx->configuration_lock = 0;
204 
205     ctx->mutex = mutex;
206 
207     ctx->db4ctx = NULL;
208 
209     ctx->aliases[0] = NULL;
210     for (i=0;rcc_default_aliases[i].alias;i++)
211 	rccRegisterLanguageAlias(ctx, rcc_default_aliases + i);
212 
213     ctx->ilang = ilang;
214     ctx->iclass = iclass;
215 
216     ctx->languages = languages;
217     ctx->max_languages = max_languages;
218     ctx->n_languages = 0;
219     languages[0] = NULL;
220 
221     ctx->classes = classes;
222     ctx->max_classes = max_classes;
223     ctx->n_classes = 0;
224     classes[0] = NULL;
225 
226     ctx->lastprefix[0] = 0;
227 
228     ctx->iconv_from = from;
229     for (i=0;i<max_classes;i++) from[i] = NULL;
230     for (i=0;i<RCC_MAX_CHARSETS;i++) ctx->iconv_auto[i] = NULL;
231 
232     ctx->configs = configs;
233     for (i=0;i<max_languages;i++)
234 	configs[i].charset = NULL;
235 
236     ctx->current_language = 0;
237     ctx->default_language = 0;
238 
239     if (locale_variable) {
240 	if (strlen(locale_variable)>=RCC_MAX_VARIABLE_CHARS) {
241 	    rccFreeContext(ctx);
242 	    return NULL;
243 	}
244 	strcpy(ctx->locale_variable, locale_variable);
245     } else {
246 	strcpy(ctx->locale_variable, RCC_LOCALE_VARIABLE);
247     }
248 
249     for (i=0;i<RCC_MAX_OPTIONS;i++) rccOptionSetDefault(ctx, (rcc_option)i);
250 
251     if (flags&RCC_FLAG_NO_DEFAULT_CONFIGURATION) {
252 	rccRegisterLanguage(ctx, rcc_default_languages);
253 	ctx->current_config = NULL;
254     } else {
255 	for (i=0;rcc_default_languages[i].sn;i++)
256 	    rccRegisterLanguage(ctx, rcc_default_languages+i);
257 
258 	if (max_languages < i) {
259 	    rccFreeContext(ctx);
260 	    return NULL;
261 	}
262 
263 	for (i=0;rcc_default_relations[i].lang;i++)
264 	    rccRegisterLanguageRelation(ctx, rcc_default_relations+i);
265 
266 	ctx->current_config = rccGetCurrentConfig(ctx);
267     }
268 
269     if (defclasses) {
270 	for (i=0;defclasses[i].name;i++)
271 	    rccRegisterClass(ctx, defclasses+i);
272 
273 	if (max_classes < i) {
274 	    rccFreeContext(ctx);
275 	    return NULL;
276 	}
277     }
278 
279     ctx->configure = 1;
280 
281     return ctx;
282 }
283 
rccInitDefaultContext(const char * locale_variable,unsigned int max_languages,unsigned int max_classes,rcc_class_ptr defclasses,rcc_init_flags flags)284 int rccInitDefaultContext(const char *locale_variable, unsigned int max_languages, unsigned int max_classes, rcc_class_ptr defclasses, rcc_init_flags flags) {
285     if (!initialized) return -1;
286     if (rcc_default_ctx) rccFreeContext(rcc_default_ctx);
287     rcc_default_ctx = rccCreateContext(locale_variable, max_languages, max_classes, defclasses, flags);
288     if (rcc_default_ctx) return 0;
289     return -1;
290 }
291 
292 
rccFreeIConv(rcc_context ctx)293 static void rccFreeIConv(rcc_context ctx) {
294     unsigned int i;
295 
296     if ((!ctx)||(!ctx->iconv_from)) return;
297 
298     for (i=0;i<ctx->n_classes;i++) {
299 	if (ctx->iconv_from[i]) {
300 	    rccIConvClose(ctx->iconv_from[i]);
301 	    ctx->iconv_from[i] = NULL;
302 	}
303     }
304     for (i=0;i<RCC_MAX_CHARSETS;i++) {
305 	if (ctx->iconv_auto[i]) {
306 	    rccIConvClose(ctx->iconv_auto[i]);
307 	    ctx->iconv_auto[i] = NULL;
308 	}
309     }
310 }
311 
rccFreeContext(rcc_context ctx)312 void rccFreeContext(rcc_context ctx) {
313     unsigned int i;
314 
315     if (ctx) {
316 	if (ctx->db4ctx) rccDb4FreeContext(ctx->db4ctx);
317 	rccFreeIConv(ctx);
318 	if (ctx->iconv_from) free(ctx->iconv_from);
319 
320 	if (ctx->configs) {
321 	    for (i=0;i<ctx->max_languages;i++)
322 		rccConfigClear(ctx->configs+i);
323 	    free(ctx->configs);
324 	}
325 	if (ctx->iclass) free(ctx->iclass);
326 	if (ctx->classes) free(ctx->classes);
327 	if (ctx->ilang) free(ctx->ilang);
328 	if (ctx->languages) free(ctx->languages);
329 	if (ctx->mutex) rccMutexFree(ctx->mutex);
330 	free(ctx);
331     }
332 }
333 
rccInitDb4(rcc_context ctx,const char * name,rcc_db4_flags flags)334 int rccInitDb4(rcc_context ctx, const char *name, rcc_db4_flags flags) {
335     size_t size;
336     char *dbname;
337 
338     if (!ctx) {
339 	if (rcc_default_ctx) ctx = rcc_default_ctx;
340 	else return -1;
341     }
342 
343     if (!name) name = "default";
344 
345     size = strlen(rcc_home_dir) + strlen(name) + 32;
346     dbname = (char*)malloc(size*sizeof(char));
347     if (!dbname) return -1;
348 
349     sprintf(dbname,"%s/.rcc/",rcc_home_dir);
350     mkdir(dbname, 00755);
351 
352     sprintf(dbname,"%s/.rcc/%s.db/",rcc_home_dir,name);
353     mkdir(dbname, 00755);
354 
355     ctx->db4ctx = rccDb4CreateContext(dbname, flags);
356     free(dbname);
357 
358     if (!ctx->db4ctx) return -1;
359 
360     return 0;
361 }
362 
rccLockConfiguration(rcc_context ctx,unsigned int lock_code)363 int rccLockConfiguration(rcc_context ctx, unsigned int lock_code) {
364     if (!ctx) {
365 	if (rcc_default_ctx) ctx = rcc_default_ctx;
366 	else return -1;
367     }
368 
369     if (ctx->configuration_lock) return -1;
370     ctx->configuration_lock = lock_code;
371     return 0;
372 }
373 
rccUnlockConfiguration(rcc_context ctx,unsigned int lock_code)374 int rccUnlockConfiguration(rcc_context ctx, unsigned int lock_code) {
375     if (!ctx) {
376 	if (rcc_default_ctx) ctx = rcc_default_ctx;
377 	else return -1;
378     }
379 
380     if (ctx->configuration_lock != lock_code) return -1;
381     ctx->configuration_lock = 0;
382     return 0;
383 }
384 
rccRegisterLanguage(rcc_context ctx,rcc_language * language)385 rcc_language_id rccRegisterLanguage(rcc_context ctx, rcc_language *language) {
386     unsigned int i;
387     if (!ctx) {
388 	if (rcc_default_ctx) ctx = rcc_default_ctx;
389 	else return (rcc_language_id)-1;
390     }
391     if (!language) return (rcc_language_id)-1;
392     if (ctx->configuration_lock) return (rcc_language_id)-1;
393 
394     if (ctx->n_languages == ctx->max_languages) return (rcc_language_id)-1;
395 
396     memcpy(ctx->ilang + ctx->n_languages, language, sizeof(rcc_language));
397     ctx->ilang[ctx->n_languages].parents[0] = (rcc_language_id)-1;
398     ctx->ilang[ctx->n_languages].latin = 0;
399 
400     for (i=0;language->charsets[i];i++)
401 	if ((strstr(language->charsets[i],"8859"))&&(language->charsets[i][strlen(language->charsets[i])-1]=='1')) {
402 	    ctx->ilang[ctx->n_languages].latin = 1;
403 	    break;
404 	}
405 
406     if ((i==1)&&(!language->charsets[1])&&(rccIsUTF8(language->charsets[0])))
407 	    ctx->ilang[ctx->n_languages].latin = 1;
408 
409     ctx->languages[ctx->n_languages] = (rcc_language_ptr)(ctx->ilang + ctx->n_languages);
410     ctx->languages[++ctx->n_languages] = NULL;
411 
412     if (!ctx->current_language)
413 	ctx->current_config = rccGetCurrentConfig(ctx);
414 
415     return ctx->n_languages-1;
416 }
417 
rccLanguageRegisterCharset(rcc_language * language,rcc_charset charset)418 rcc_charset_id rccLanguageRegisterCharset(rcc_language *language, rcc_charset charset) {
419     unsigned int i;
420 
421     if ((!language)||(!charset)) return (rcc_charset_id)-1;
422     for (i=0;language->charsets[i];i++);
423     if (i>=RCC_MAX_CHARSETS) return (rcc_charset_id)-1;
424 
425     if ((strstr(charset,"8859"))&&(charset[strlen(charset)-1]=='1'))
426 	((rcc_language_internal*)language)->latin = 1;
427 
428     language->charsets[i++] = charset;
429     language->charsets[i] = NULL;
430     return i-1;
431 }
432 
rccLanguageRegisterEngine(rcc_language * language,rcc_engine * engine)433 rcc_engine_id rccLanguageRegisterEngine(rcc_language *language, rcc_engine *engine) {
434     unsigned int i;
435 
436     if ((!language)||(!engine)) return (rcc_engine_id)-1;
437     for (i=0;language->engines[i];i++);
438     if (i>=RCC_MAX_ENGINES) return (rcc_engine_id)-1;
439     language->engines[i++] = engine;
440     language->engines[i] = NULL;
441     return i-1;
442 }
443 
rccRegisterLanguageAlias(rcc_context ctx,rcc_language_alias * alias)444 rcc_alias_id rccRegisterLanguageAlias(rcc_context ctx, rcc_language_alias *alias) {
445     unsigned int i;
446 
447     if (!ctx) {
448 	if (rcc_default_ctx) ctx = rcc_default_ctx;
449 	else return (rcc_alias_id)-1;
450     }
451     if (!alias) return (rcc_alias_id)-1;
452 
453     for (i=0;ctx->aliases[i];i++)
454     if (i>=RCC_MAX_ALIASES) return (rcc_alias_id)-1;
455 
456     ctx->aliases[i++] = alias;
457     ctx->aliases[i] = NULL;
458 
459     return i-1;
460 }
461 
rccRegisterLanguageRelation(rcc_context ctx,rcc_language_relation * relation)462 rcc_relation_id rccRegisterLanguageRelation(rcc_context ctx, rcc_language_relation *relation) {
463     unsigned int i;
464     rcc_language_id language_id;
465     const char *lang;
466     const char *parent;
467     rcc_language_id *list;
468 
469     if (!ctx) {
470 	if (rcc_default_ctx) ctx = rcc_default_ctx;
471 	else return (rcc_alias_id)-1;
472     }
473     if (!relation) return (rcc_relation_id)-1;
474 
475     lang = relation->lang;
476     parent = relation->parent;
477     if ((!lang)||(!parent)||(!strcasecmp(lang,parent))) return (rcc_relation_id)-1;
478 
479     language_id = rccGetLanguageByName(ctx, lang);
480     if (language_id == (rcc_language_id)-1) return (rcc_relation_id)-1;
481 
482 
483     list = ((rcc_language_internal*)ctx->languages[language_id])->parents;
484 
485     language_id = rccGetLanguageByName(ctx, parent);
486     if (language_id == (rcc_language_id)-1) return (rcc_relation_id)0;
487 
488     for (i=0;list[i]!=(rcc_language_id)-1;i++)
489 	if (list[i] == language_id) return (rcc_relation_id)0;
490 
491     if (i<RCC_MAX_LANGUAGE_PARENTS) {
492 	list[i++] = language_id;
493     	list[i] = (rcc_language_id)-1;
494     } else return (rcc_relation_id)-1;
495 
496 
497     return (rcc_relation_id)0;
498 }
499 
500 
rccRegisterClass(rcc_context ctx,rcc_class * cl)501 rcc_class_id rccRegisterClass(rcc_context ctx, rcc_class *cl) {
502     if (!ctx) {
503 	if (rcc_default_ctx) ctx = rcc_default_ctx;
504 	else return (rcc_class_id)-1;
505     }
506     if (!cl) return (rcc_class_id)-1;
507     if (ctx->configuration_lock) return (rcc_class_id)-1;
508     if (ctx->n_classes == ctx->max_classes) return (rcc_class_id)-1;
509 
510     ctx->configure = 1;
511 
512     memcpy(ctx->iclass + ctx->n_classes, cl, sizeof(rcc_class));
513     ctx->iclass[ctx->n_classes].disabled = NULL;
514     ctx->iclass[ctx->n_classes].additional = NULL;
515 
516     ctx->classes[ctx->n_classes] = (rcc_class_ptr)(ctx->iclass + ctx->n_classes);
517     ctx->classes[++ctx->n_classes] = NULL;
518 
519     if (!strcasecmp(cl->name, "id3")) {
520 	rccRegisterDisabledCharsets(ctx, ctx->n_classes - 1, rcc_default_disabled_id3_charsets);
521     } else if (!strcasecmp(cl->name, "id3v2")) {
522 	rccRegisterAdditionalCharsets(ctx, ctx->n_classes - 1, rcc_default_additional_id3v2_charsets);
523     }
524 
525     return ctx->n_classes-1;
526 }
527 
rccRegisterDisabledCharsets(rcc_context ctx,rcc_class_id class_id,rcc_charset * charsets)528 int rccRegisterDisabledCharsets(rcc_context ctx, rcc_class_id class_id, rcc_charset *charsets) {
529     if (!ctx) {
530 	if (rcc_default_ctx) ctx = rcc_default_ctx;
531 	else return -1;
532     }
533     if (ctx->configuration_lock) return -1;
534     if ((class_id == (rcc_class_id)-1)||(class_id >= ctx->n_classes)) return -1;
535 
536     ctx->iclass[class_id].disabled = charsets;
537     return 0;
538 }
539 
rccRegisterAdditionalCharsets(rcc_context ctx,rcc_class_id class_id,rcc_charset * charsets)540 int rccRegisterAdditionalCharsets(rcc_context ctx, rcc_class_id class_id, rcc_charset *charsets) {
541     if (!ctx) {
542 	if (rcc_default_ctx) ctx = rcc_default_ctx;
543 	else return -1;
544     }
545     if (ctx->configuration_lock) return -1;
546     if ((class_id == (rcc_class_id)-1)||(class_id >= ctx->n_classes)) return -1;
547 
548     ctx->iclass[class_id].additional = charsets;
549     return 0;
550 }
551 
rccGetClassType(rcc_context ctx,rcc_class_id class_id)552 rcc_class_type rccGetClassType(rcc_context ctx, rcc_class_id class_id) {
553     rcc_class_type clt;
554 
555     if (!ctx) {
556 	if (rcc_default_ctx) ctx = rcc_default_ctx;
557 	else return RCC_CLASS_INVALID;
558     }
559 
560     if ((class_id<0)||(class_id>=ctx->n_classes)) return RCC_CLASS_INVALID;
561 
562     /*DS: temporary solution */
563 
564     clt = ctx->classes[class_id]->class_type;
565 
566     if ((!strcasecmp(ctx->classes[class_id]->name, "out"))&&(clt == RCC_CLASS_STANDARD))
567 	clt = RCC_CLASS_TRANSLATE_LOCALE;
568 
569     return clt;
570 }
571 
rccGetClassName(rcc_context ctx,rcc_class_id class_id)572 const char *rccGetClassName(rcc_context ctx, rcc_class_id class_id) {
573     if ((class_id<0)||(class_id>=ctx->n_classes)) return NULL;
574 
575     if (!ctx) {
576 	if (rcc_default_ctx) ctx = rcc_default_ctx;
577 	else return NULL;
578     }
579 
580     return ctx->classes[class_id]->name;
581 }
582 
rccGetClassFullName(rcc_context ctx,rcc_class_id class_id)583 const char *rccGetClassFullName(rcc_context ctx, rcc_class_id class_id) {
584     if ((class_id<0)||(class_id>=ctx->n_classes)) return NULL;
585 
586     if (!ctx) {
587 	if (rcc_default_ctx) ctx = rcc_default_ctx;
588 	else return NULL;
589     }
590 
591     return ctx->classes[class_id]->fullname;
592 }
593 
594 
rccIsDisabledCharsetName(rcc_context ctx,rcc_class_id class_id,const char * charset)595 int rccIsDisabledCharsetName(rcc_context ctx, rcc_class_id class_id, const char *charset) {
596     unsigned int i;
597     rcc_charset *charsets;
598 
599     if (!ctx) {
600 	if (rcc_default_ctx) ctx = rcc_default_ctx;
601 	else return RCC_CLASS_INVALID;
602     }
603 
604     if ((!charset)||(class_id<0)||(class_id>=ctx->n_classes)) return -1;
605 
606     charsets = ctx->iclass[class_id].disabled;
607     if (!charsets) return 0;
608 
609     for (i=0;charsets[i];i++) {
610 	if (!strcasecmp(charsets[i], charset)) return 1;
611 	else if (!strcasecmp(charsets[i], rcc_default_unicode_charsets)) {
612 	    if (rccIsUnicode(charset)) return 1;
613 	}
614 	else if (!strcasecmp(charsets[i], rcc_default_nonunicode_charsets)) {
615 	    if (!rccIsUnicode(charset)) return 1;
616 	}
617     }
618     return 0;
619 }
620 
621 
rccConfigure(rcc_context ctx)622 int rccConfigure(rcc_context ctx) {
623     unsigned int i;
624     rcc_charset *charsets;
625     const char *charset;
626     rcc_language_config cfg;
627 
628     if (!ctx) return -1;
629     if (!ctx->configure) return 0;
630 
631 
632 
633     cfg = rccGetCurrentConfig(ctx);
634     if (!cfg) return -1;
635 
636     rccMutexLock(ctx->mutex);
637     rccMutexLock(cfg->mutex);
638 
639     rccFreeIConv(ctx);
640     for (i=0;i<ctx->n_classes;i++) {
641 	charset = rccConfigGetCurrentCharsetName(cfg, (rcc_class_id)i);
642 	if ((!charset)||(rccIsUTF8(charset))) continue;
643 	ctx->iconv_from[i] = rccIConvOpen("UTF-8", charset);
644     }
645 
646     charsets = rccGetCurrentAutoCharsetList(ctx);
647     if (charsets) {
648 	for (i=0;charsets[i];i++) {
649 	    charset = charsets[i];
650 	    if ((!charset)||(rccIsUTF8(charset))) continue;
651 	    ctx->iconv_auto[i] = rccIConvOpen("UTF-8", charset);
652 	}
653     }
654 
655     ctx->configure = 0;
656 
657     rccMutexUnLock(cfg->mutex);
658     rccMutexUnLock(ctx->mutex);
659 
660     return 0;
661 }
662 
rccCreateResult(rcc_context ctx,size_t len)663 char *rccCreateResult(rcc_context ctx, size_t len) {
664     char *res;
665 
666     if (!len) len = strlen(ctx->tmpbuffer);
667 
668     res = (char*)malloc(len+1);
669     if (!res) return NULL;
670 
671     memcpy(res, ctx->tmpbuffer, len);
672     res[len] = 0;
673 
674     return res;
675 }
676