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