2 * Copyright (C) 1995-2005, Index Data ApS
3 * See the file LICENSE for details.
5 * $Id: charneg.c,v 1.6 2006-03-31 09:51:22 adam Exp $
10 * \brief Implements Z39.50 Charset negotiation utilities
12 * Helper functions for Character Set and Language Negotiation - 3
15 #include <yaz/otherinfo.h>
16 #include <yaz/z-charneg.h>
17 #include <yaz/charneg.h>
18 #include <yaz/yaz-util.h>
20 static Z_External* z_ext_record2(ODR o, int oid_class, int oid_value,
25 int len = strlen(buf);
27 if (!(p = (Z_External *)odr_malloc(o, sizeof(*p)))) return 0;
30 p->indirect_reference = 0;
32 oid.proto = PROTO_Z3950;
33 oid.oclass = (enum oid_class) oid_class;
34 oid.value = (enum oid_value) oid_value;
35 p->direct_reference = odr_oiddup(o, oid_getoidbyent(&oid));
37 p->which = Z_External_octet;
38 if (!(p->u.octet_aligned = (Odr_oct *)odr_malloc(o, sizeof(Odr_oct)))) {
41 if (!(p->u.octet_aligned->buf = (unsigned char *)odr_malloc(o, len))) {
44 p->u.octet_aligned->len = p->u.octet_aligned->size = len;
45 memcpy(p->u.octet_aligned->buf, buf, len);
50 static int get_form(const char *charset)
55 if (!yaz_matchstr(charset, "UCS-2"))
57 if (!yaz_matchstr(charset, "UCS-4"))
59 if (!yaz_matchstr(charset, "UTF-16"))
61 if (!yaz_matchstr(charset, "UTF-8"))
67 static char *set_form (Odr_oid *encoding)
69 static char *charset = 0;
70 if ( oid_oidlen(encoding) != 6)
83 static Z_OriginProposal_0 *z_get_OriginProposal_0(ODR o, const char *charset)
85 int form = get_form (charset);
86 Z_OriginProposal_0 *p0 =
87 (Z_OriginProposal_0*)odr_malloc(o, sizeof(*p0));
89 memset(p0, 0, sizeof(*p0));
92 { /* ISO 10646 (UNICODE) */
95 Z_Iso10646 *is = (Z_Iso10646 *) odr_malloc (o, sizeof(*is));
96 p0->which = Z_OriginProposal_0_iso10646;
99 sprintf (oidname, "1.0.10646.1.0.%d", form);
100 is->encodingLevel = odr_getoidbystr (o, oidname);
104 Z_PrivateCharacterSet *pc =
105 (Z_PrivateCharacterSet *)odr_malloc(o, sizeof(*pc));
107 memset(pc, 0, sizeof(*pc));
109 p0->which = Z_OriginProposal_0_private;
112 pc->which = Z_PrivateCharacterSet_externallySpecified;
113 pc->u.externallySpecified =
114 z_ext_record2(o, CLASS_NEGOT, VAL_ID_CHARSET, charset);
119 static Z_OriginProposal *z_get_OriginProposal(
120 ODR o, const char **charsets, int num_charsets,
121 const char **langs, int num_langs, int selected)
124 Z_OriginProposal *p = (Z_OriginProposal *) odr_malloc(o, sizeof(*p));
126 memset(p, 0, sizeof(*p));
128 p->recordsInSelectedCharSets = (bool_t *)odr_malloc(o, sizeof(bool_t));
129 *p->recordsInSelectedCharSets = (selected) ? 1:0;
131 if (charsets && num_charsets) {
133 p->num_proposedCharSets = num_charsets;
134 p->proposedCharSets =
135 (Z_OriginProposal_0**)
136 odr_malloc(o, num_charsets*sizeof(Z_OriginProposal_0*));
138 for (i = 0; i<num_charsets; i++)
139 p->proposedCharSets[i] =
140 z_get_OriginProposal_0(o, charsets[i]);
142 if (langs && num_langs) {
144 p->num_proposedlanguages = num_langs;
146 p->proposedlanguages =
147 (char **) odr_malloc(o, num_langs*sizeof(char *));
149 for (i = 0; i<num_langs; i++) {
151 p->proposedlanguages[i] = (char *)langs[i];
158 static Z_CharSetandLanguageNegotiation *z_get_CharSetandLanguageNegotiation(
161 Z_CharSetandLanguageNegotiation *p =
162 (Z_CharSetandLanguageNegotiation *) odr_malloc(o, sizeof(*p));
164 memset(p, 0, sizeof(*p));
169 /* Create EXTERNAL for negotation proposal. Client side */
170 Z_External *yaz_set_proposal_charneg(ODR o,
171 const char **charsets, int num_charsets,
172 const char **langs, int num_langs,
175 Z_External *p = (Z_External *)odr_malloc(o, sizeof(*p));
179 p->indirect_reference = 0;
181 oid.proto = PROTO_Z3950;
182 oid.oclass = CLASS_NEGOT;
183 oid.value = VAL_CHARNEG3;
184 p->direct_reference = odr_oiddup(o, oid_getoidbyent(&oid));
186 p->which = Z_External_charSetandLanguageNegotiation;
187 p->u.charNeg3 = z_get_CharSetandLanguageNegotiation(o);
188 p->u.charNeg3->which = Z_CharSetandLanguageNegotiation_proposal;
189 p->u.charNeg3->u.proposal =
190 z_get_OriginProposal(o, charsets, num_charsets,
191 langs, num_langs, selected);
196 Z_External *yaz_set_proposal_charneg_list(ODR o,
198 const char *charset_list,
199 const char *lang_list,
202 char **charsets_addresses = 0;
203 char **langs_addresses = 0;
204 int charsets_count = 0;
208 nmem_strsplit(o->mem, delim, charset_list,
209 &charsets_addresses, &charsets_count);
211 nmem_strsplit(o->mem, delim, lang_list,
212 &langs_addresses, &langs_count);
213 return yaz_set_proposal_charneg(o,
214 (const char **) charsets_addresses,
216 (const char **) langs_addresses,
222 /* used by yaz_set_response_charneg */
223 static Z_TargetResponse *z_get_TargetResponse(ODR o, const char *charset,
224 const char *lang, int selected)
226 Z_TargetResponse *p = (Z_TargetResponse *) odr_malloc(o, sizeof(*p));
227 int form = get_form(charset);
229 memset(p, 0, sizeof(*p));
235 Z_Iso10646 *is = (Z_Iso10646 *) odr_malloc (o, sizeof(*is));
236 p->which = Z_TargetResponse_iso10646;
239 sprintf (oidname, "1.0.10646.1.0.%d", form);
240 is->encodingLevel = odr_getoidbystr (o, oidname);
244 Z_PrivateCharacterSet *pc =
245 (Z_PrivateCharacterSet *)odr_malloc(o, sizeof(*pc));
247 memset(pc, 0, sizeof(*pc));
249 p->which = Z_TargetResponse_private;
252 pc->which = Z_PrivateCharacterSet_externallySpecified;
253 pc->u.externallySpecified =
254 z_ext_record2(o, CLASS_NEGOT, VAL_ID_CHARSET, charset);
256 p->recordsInSelectedCharSets = (bool_t *)odr_malloc(o, sizeof(bool_t));
257 *p->recordsInSelectedCharSets = (selected) ? 1:0;
259 p->selectedLanguage = lang ? (char *)odr_strdup(o, lang) : 0;
263 /* Create charset response. Server side */
264 Z_External *yaz_set_response_charneg(ODR o, const char *charset,
265 const char *lang, int selected)
267 Z_External *p = (Z_External *)odr_malloc(o, sizeof(*p));
271 p->indirect_reference = 0;
273 oid.proto = PROTO_Z3950;
274 oid.oclass = CLASS_NEGOT;
275 oid.value = VAL_CHARNEG3;
276 p->direct_reference = odr_oiddup(o, oid_getoidbyent(&oid));
278 p->which = Z_External_charSetandLanguageNegotiation;
279 p->u.charNeg3 = z_get_CharSetandLanguageNegotiation(o);
280 p->u.charNeg3->which = Z_CharSetandLanguageNegotiation_response;
281 p->u.charNeg3->u.response = z_get_TargetResponse(o, charset, lang, selected);
286 /* Get negotiation from OtherInformation. Client&Server side */
287 Z_CharSetandLanguageNegotiation *yaz_get_charneg_record(Z_OtherInformation *p)
294 for (i = 0; i < p->num_elements; i++) {
296 if ((p->list[i]->which == Z_OtherInfo_externallyDefinedInfo) &&
297 (pext = p->list[i]->information.externallyDefinedInfo)) {
299 oident *ent = oid_getentbyoid(pext->direct_reference);
301 if (ent && ent->value == VAL_CHARNEG3
302 && ent->oclass == CLASS_NEGOT
303 && pext->which == Z_External_charSetandLanguageNegotiation)
305 return pext->u.charNeg3;
312 /* Delete negotiation from OtherInformation. Client&Server side */
313 int yaz_del_charneg_record(Z_OtherInformation **p)
320 for (i = 0; i < (*p)->num_elements; i++) {
322 if (((*p)->list[i]->which == Z_OtherInfo_externallyDefinedInfo) &&
323 (pext = (*p)->list[i]->information.externallyDefinedInfo)) {
325 oident *ent = oid_getentbyoid(pext->direct_reference);
327 if (ent && ent->value == VAL_CHARNEG3
328 && ent->oclass == CLASS_NEGOT
329 && pext->which == Z_External_charSetandLanguageNegotiation)
331 --((*p)->num_elements);
332 if ((*p)->num_elements == 0)
336 for(; i < (*p)->num_elements; i++)
337 (*p)->list[i] = (*p)->list[i+1];
347 /* Get charsets, langs, selected from negotiation.. Server side */
348 void yaz_get_proposal_charneg(NMEM mem, Z_CharSetandLanguageNegotiation *p,
349 char ***charsets, int *num_charsets,
350 char ***langs, int *num_langs, int *selected)
353 Z_OriginProposal *pro = p->u.proposal;
355 if (num_charsets && charsets)
357 if (pro->num_proposedCharSets)
359 *num_charsets = pro->num_proposedCharSets;
361 (*charsets) = (char **)
362 nmem_malloc(mem, pro->num_proposedCharSets * sizeof(char *));
364 for (i=0; i<pro->num_proposedCharSets; i++)
368 if (pro->proposedCharSets[i]->which ==
369 Z_OriginProposal_0_private &&
370 pro->proposedCharSets[i]->u.zprivate->which ==
371 Z_PrivateCharacterSet_externallySpecified) {
374 pro->proposedCharSets[i]->u.zprivate->u.externallySpecified;
376 if (pext->which == Z_External_octet) {
378 (*charsets)[i] = (char *)
379 nmem_malloc(mem, (1+pext->u.octet_aligned->len) *
382 memcpy ((*charsets)[i], pext->u.octet_aligned->buf,
383 pext->u.octet_aligned->len);
384 (*charsets)[i][pext->u.octet_aligned->len] = 0;
388 else if (pro->proposedCharSets[i]->which ==
389 Z_OriginProposal_0_iso10646)
390 (*charsets)[i] = set_form (
391 pro->proposedCharSets[i]->u.iso10646->encodingLevel);
398 if (langs && num_langs)
400 if (pro->num_proposedlanguages)
402 *num_langs = pro->num_proposedlanguages;
405 nmem_malloc(mem, pro->num_proposedlanguages * sizeof(char *));
407 for (i=0; i<pro->num_proposedlanguages; i++)
408 (*langs)[i] = nmem_strdup(mem, pro->proposedlanguages[i]);
414 if(pro->recordsInSelectedCharSets && selected)
415 *selected = *pro->recordsInSelectedCharSets;
418 /* Return charset, lang, selected from negotiation.. Client side */
419 void yaz_get_response_charneg(NMEM mem, Z_CharSetandLanguageNegotiation *p,
420 char **charset, char **lang, int *selected)
422 Z_TargetResponse *res = p->u.response;
424 if (charset && res->which == Z_TargetResponse_private &&
425 res->u.zprivate->which == Z_PrivateCharacterSet_externallySpecified) {
427 Z_External *pext = res->u.zprivate->u.externallySpecified;
429 if (pext->which == Z_External_octet) {
432 nmem_malloc(mem, (1+pext->u.octet_aligned->len)*sizeof(char));
433 memcpy (*charset, pext->u.octet_aligned->buf,
434 pext->u.octet_aligned->len);
435 (*charset)[pext->u.octet_aligned->len] = 0;
438 if (charset && res->which == Z_TargetResponse_iso10646)
439 *charset = set_form (res->u.iso10646->encodingLevel);
440 if (lang && res->selectedLanguage)
441 *lang = nmem_strdup (mem, res->selectedLanguage);
443 if(selected && res->recordsInSelectedCharSets)
444 *selected = *res->recordsInSelectedCharSets;
449 * indent-tabs-mode: nil
451 * vim: shiftwidth=4 tabstop=8 expandtab