2 * Copyright (C) 1995-2007, Index Data ApS
3 * See the file LICENSE for details.
5 * $Id: charneg.c,v 1.8 2007-04-12 13:52:57 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>
19 #include <yaz/oid_db.h>
21 static Z_External* z_ext_record2(ODR o, const char *buf)
24 int len = strlen(buf);
26 if (!(p = (Z_External *)odr_malloc(o, sizeof(*p)))) return 0;
29 p->indirect_reference = 0;
31 p->direct_reference = yaz_string_to_oid_odr(yaz_oid_std(),
36 p->which = Z_External_octet;
37 if (!(p->u.octet_aligned = (Odr_oct *)odr_malloc(o, sizeof(Odr_oct)))) {
40 if (!(p->u.octet_aligned->buf = (unsigned char *)odr_malloc(o, len))) {
43 p->u.octet_aligned->len = p->u.octet_aligned->size = len;
44 memcpy(p->u.octet_aligned->buf, buf, len);
49 static int get_form(const char *charset)
54 if (!yaz_matchstr(charset, "UCS-2"))
56 if (!yaz_matchstr(charset, "UCS-4"))
58 if (!yaz_matchstr(charset, "UTF-16"))
60 if (!yaz_matchstr(charset, "UTF-8"))
66 static char *set_form (Odr_oid *encoding)
68 static char *charset = 0;
69 if ( oid_oidlen(encoding) != 6)
82 static Z_OriginProposal_0 *z_get_OriginProposal_0(ODR o, const char *charset)
84 int form = get_form (charset);
85 Z_OriginProposal_0 *p0 =
86 (Z_OriginProposal_0*)odr_malloc(o, sizeof(*p0));
88 memset(p0, 0, sizeof(*p0));
91 { /* ISO 10646 (UNICODE) */
94 Z_Iso10646 *is = (Z_Iso10646 *) odr_malloc (o, sizeof(*is));
95 p0->which = Z_OriginProposal_0_iso10646;
98 sprintf (oidname, "1.0.10646.1.0.%d", form);
99 is->encodingLevel = odr_getoidbystr (o, oidname);
103 Z_PrivateCharacterSet *pc =
104 (Z_PrivateCharacterSet *)odr_malloc(o, sizeof(*pc));
106 memset(pc, 0, sizeof(*pc));
108 p0->which = Z_OriginProposal_0_private;
111 pc->which = Z_PrivateCharacterSet_externallySpecified;
112 pc->u.externallySpecified = z_ext_record2(o, charset);
117 static Z_OriginProposal *z_get_OriginProposal(
118 ODR o, const char **charsets, int num_charsets,
119 const char **langs, int num_langs, int selected)
122 Z_OriginProposal *p = (Z_OriginProposal *) odr_malloc(o, sizeof(*p));
124 memset(p, 0, sizeof(*p));
126 p->recordsInSelectedCharSets = (bool_t *)odr_malloc(o, sizeof(bool_t));
127 *p->recordsInSelectedCharSets = (selected) ? 1:0;
129 if (charsets && num_charsets) {
131 p->num_proposedCharSets = num_charsets;
132 p->proposedCharSets =
133 (Z_OriginProposal_0**)
134 odr_malloc(o, num_charsets*sizeof(Z_OriginProposal_0*));
136 for (i = 0; i<num_charsets; i++)
137 p->proposedCharSets[i] =
138 z_get_OriginProposal_0(o, charsets[i]);
140 if (langs && num_langs) {
142 p->num_proposedlanguages = num_langs;
144 p->proposedlanguages =
145 (char **) odr_malloc(o, num_langs*sizeof(char *));
147 for (i = 0; i<num_langs; i++) {
149 p->proposedlanguages[i] = (char *)langs[i];
156 static Z_CharSetandLanguageNegotiation *z_get_CharSetandLanguageNegotiation(
159 Z_CharSetandLanguageNegotiation *p =
160 (Z_CharSetandLanguageNegotiation *) odr_malloc(o, sizeof(*p));
162 memset(p, 0, sizeof(*p));
167 /* Create EXTERNAL for negotation proposal. Client side */
168 Z_External *yaz_set_proposal_charneg(ODR o,
169 const char **charsets, int num_charsets,
170 const char **langs, int num_langs,
173 Z_External *p = (Z_External *)odr_malloc(o, sizeof(*p));
176 p->indirect_reference = 0;
178 p->direct_reference = yaz_string_to_oid_odr(yaz_oid_std(),
183 p->which = Z_External_charSetandLanguageNegotiation;
184 p->u.charNeg3 = z_get_CharSetandLanguageNegotiation(o);
185 p->u.charNeg3->which = Z_CharSetandLanguageNegotiation_proposal;
186 p->u.charNeg3->u.proposal =
187 z_get_OriginProposal(o, charsets, num_charsets,
188 langs, num_langs, selected);
193 Z_External *yaz_set_proposal_charneg_list(ODR o,
195 const char *charset_list,
196 const char *lang_list,
199 char **charsets_addresses = 0;
200 char **langs_addresses = 0;
201 int charsets_count = 0;
205 nmem_strsplit(odr_getmem(o), delim, charset_list,
206 &charsets_addresses, &charsets_count);
208 nmem_strsplit(odr_getmem(o), delim, lang_list,
209 &langs_addresses, &langs_count);
210 return yaz_set_proposal_charneg(o,
211 (const char **) charsets_addresses,
213 (const char **) langs_addresses,
219 /* used by yaz_set_response_charneg */
220 static Z_TargetResponse *z_get_TargetResponse(ODR o, const char *charset,
221 const char *lang, int selected)
223 Z_TargetResponse *p = (Z_TargetResponse *) odr_malloc(o, sizeof(*p));
224 int form = get_form(charset);
226 memset(p, 0, sizeof(*p));
232 Z_Iso10646 *is = (Z_Iso10646 *) odr_malloc (o, sizeof(*is));
233 p->which = Z_TargetResponse_iso10646;
236 sprintf (oidname, "1.0.10646.1.0.%d", form);
237 is->encodingLevel = odr_getoidbystr (o, oidname);
241 Z_PrivateCharacterSet *pc =
242 (Z_PrivateCharacterSet *)odr_malloc(o, sizeof(*pc));
244 memset(pc, 0, sizeof(*pc));
246 p->which = Z_TargetResponse_private;
249 pc->which = Z_PrivateCharacterSet_externallySpecified;
250 pc->u.externallySpecified =
251 z_ext_record2(o, charset);
253 p->recordsInSelectedCharSets = (bool_t *)odr_malloc(o, sizeof(bool_t));
254 *p->recordsInSelectedCharSets = (selected) ? 1:0;
256 p->selectedLanguage = lang ? (char *)odr_strdup(o, lang) : 0;
260 /* Create charset response. Server side */
261 Z_External *yaz_set_response_charneg(ODR o, const char *charset,
262 const char *lang, int selected)
264 Z_External *p = (Z_External *)odr_malloc(o, sizeof(*p));
267 p->indirect_reference = 0;
269 p->direct_reference = yaz_string_to_oid_odr(yaz_oid_std(),
274 p->which = Z_External_charSetandLanguageNegotiation;
275 p->u.charNeg3 = z_get_CharSetandLanguageNegotiation(o);
276 p->u.charNeg3->which = Z_CharSetandLanguageNegotiation_response;
277 p->u.charNeg3->u.response = z_get_TargetResponse(o, charset, lang, selected);
282 /* Get negotiation from OtherInformation. Client&Server side */
283 Z_CharSetandLanguageNegotiation *yaz_get_charneg_record(Z_OtherInformation *p)
290 for (i = 0; i < p->num_elements; i++) {
292 if ((p->list[i]->which == Z_OtherInfo_externallyDefinedInfo) &&
293 (pext = p->list[i]->information.externallyDefinedInfo)) {
296 const char *name = yaz_oid_to_string(yaz_oid_std(),
297 pext->direct_reference,
300 if (oclass == CLASS_NEGOT
301 && name && !strcmp(name, OID_STR_CHARNEG_3)
302 && pext->which == Z_External_charSetandLanguageNegotiation)
304 return pext->u.charNeg3;
311 /* Delete negotiation from OtherInformation. Client&Server side */
312 int yaz_del_charneg_record(Z_OtherInformation **p)
319 for (i = 0; i < (*p)->num_elements; i++) {
321 if (((*p)->list[i]->which == Z_OtherInfo_externallyDefinedInfo) &&
322 (pext = (*p)->list[i]->information.externallyDefinedInfo))
325 const char *name = yaz_oid_to_string(yaz_oid_std(),
326 pext->direct_reference,
329 if (oclass == CLASS_NEGOT
330 && name && !strcmp(name, OID_STR_CHARNEG_3)
331 && pext->which == Z_External_charSetandLanguageNegotiation)
333 if ((*p)->num_elements <= 1)
337 --((*p)->num_elements);
338 for(; i < (*p)->num_elements; i++)
339 (*p)->list[i] = (*p)->list[i+1];
349 /* Get charsets, langs, selected from negotiation.. Server side */
350 void yaz_get_proposal_charneg(NMEM mem, Z_CharSetandLanguageNegotiation *p,
351 char ***charsets, int *num_charsets,
352 char ***langs, int *num_langs, int *selected)
355 Z_OriginProposal *pro = p->u.proposal;
357 if (num_charsets && charsets)
359 if (pro->num_proposedCharSets)
361 *num_charsets = pro->num_proposedCharSets;
363 (*charsets) = (char **)
364 nmem_malloc(mem, pro->num_proposedCharSets * sizeof(char *));
366 for (i=0; i<pro->num_proposedCharSets; i++)
370 if (pro->proposedCharSets[i]->which ==
371 Z_OriginProposal_0_private &&
372 pro->proposedCharSets[i]->u.zprivate->which ==
373 Z_PrivateCharacterSet_externallySpecified) {
376 pro->proposedCharSets[i]->u.zprivate->u.externallySpecified;
378 if (pext->which == Z_External_octet) {
380 (*charsets)[i] = (char *)
381 nmem_malloc(mem, (1+pext->u.octet_aligned->len) *
384 memcpy ((*charsets)[i], pext->u.octet_aligned->buf,
385 pext->u.octet_aligned->len);
386 (*charsets)[i][pext->u.octet_aligned->len] = 0;
390 else if (pro->proposedCharSets[i]->which ==
391 Z_OriginProposal_0_iso10646)
392 (*charsets)[i] = set_form (
393 pro->proposedCharSets[i]->u.iso10646->encodingLevel);
400 if (langs && num_langs)
402 if (pro->num_proposedlanguages)
404 *num_langs = pro->num_proposedlanguages;
407 nmem_malloc(mem, pro->num_proposedlanguages * sizeof(char *));
409 for (i=0; i<pro->num_proposedlanguages; i++)
410 (*langs)[i] = nmem_strdup(mem, pro->proposedlanguages[i]);
416 if(pro->recordsInSelectedCharSets && selected)
417 *selected = *pro->recordsInSelectedCharSets;
420 /* Return charset, lang, selected from negotiation.. Client side */
421 void yaz_get_response_charneg(NMEM mem, Z_CharSetandLanguageNegotiation *p,
422 char **charset, char **lang, int *selected)
424 Z_TargetResponse *res = p->u.response;
426 if (charset && res->which == Z_TargetResponse_private &&
427 res->u.zprivate->which == Z_PrivateCharacterSet_externallySpecified) {
429 Z_External *pext = res->u.zprivate->u.externallySpecified;
431 if (pext->which == Z_External_octet) {
434 nmem_malloc(mem, (1+pext->u.octet_aligned->len)*sizeof(char));
435 memcpy (*charset, pext->u.octet_aligned->buf,
436 pext->u.octet_aligned->len);
437 (*charset)[pext->u.octet_aligned->len] = 0;
440 if (charset && res->which == Z_TargetResponse_iso10646)
441 *charset = set_form (res->u.iso10646->encodingLevel);
442 if (lang && res->selectedLanguage)
443 *lang = nmem_strdup (mem, res->selectedLanguage);
445 if(selected && res->recordsInSelectedCharSets)
446 *selected = *res->recordsInSelectedCharSets;
451 * indent-tabs-mode: nil
453 * vim: shiftwidth=4 tabstop=8 expandtab