1 /* This file is part of the YAZ toolkit.
2 * Copyright (C) 1995-2013 Index Data
3 * See the file LICENSE for details.
7 * \brief Implements Z39.50 Charset negotiation utilities
9 * Helper functions for Character Set and Language Negotiation - 3
16 #include <yaz/otherinfo.h>
17 #include <yaz/z-charneg.h>
18 #include <yaz/charneg.h>
19 #include <yaz/yaz-util.h>
20 #include <yaz/oid_db.h>
22 static Z_External* z_ext_record2(ODR o, const char *buf)
25 int len = strlen(buf);
27 if (!(p = (Z_External *)odr_malloc(o, sizeof(*p))))
30 p->indirect_reference = 0;
31 p->direct_reference = odr_oiddup(o, yaz_oid_negot_charset_id);
32 p->which = Z_External_octet;
34 odr_create_Odr_oct(o, buf, len);
38 static int get_form(const char *charset)
42 if (!yaz_matchstr(charset, "UCS-2"))
44 if (!yaz_matchstr(charset, "UCS-4"))
46 if (!yaz_matchstr(charset, "UTF-16"))
48 if (!yaz_matchstr(charset, "UTF-8"))
54 static char *set_form(Odr_oid *encoding)
56 static char *charset = 0;
57 if ( oid_oidlen(encoding) != 6)
70 static Z_OriginProposal_0 *z_get_OriginProposal_0(ODR o, const char *charset)
72 int form = get_form(charset);
73 Z_OriginProposal_0 *p0 =
74 (Z_OriginProposal_0*)odr_malloc(o, sizeof(*p0));
76 memset(p0, 0, sizeof(*p0));
79 { /* ISO 10646 (UNICODE) */
82 Z_Iso10646 *is = (Z_Iso10646 *) odr_malloc(o, sizeof(*is));
83 p0->which = Z_OriginProposal_0_iso10646;
86 sprintf(oidname, "1.0.10646.1.0.%d", form);
87 is->encodingLevel = odr_getoidbystr(o, oidname);
91 Z_PrivateCharacterSet *pc =
92 (Z_PrivateCharacterSet *)odr_malloc(o, sizeof(*pc));
94 memset(pc, 0, sizeof(*pc));
96 p0->which = Z_OriginProposal_0_private;
99 pc->which = Z_PrivateCharacterSet_externallySpecified;
100 pc->u.externallySpecified = z_ext_record2(o, charset);
105 static Z_OriginProposal *z_get_OriginProposal(
106 ODR o, const char **charsets, int num_charsets,
107 const char **langs, int num_langs, int selected)
110 Z_OriginProposal *p = (Z_OriginProposal *) odr_malloc(o, sizeof(*p));
112 memset(p, 0, sizeof(*p));
114 p->recordsInSelectedCharSets = (bool_t *)odr_malloc(o, sizeof(bool_t));
115 *p->recordsInSelectedCharSets = (selected) ? 1 : 0;
117 if (charsets && num_charsets)
119 p->num_proposedCharSets = num_charsets;
120 p->proposedCharSets =
121 (Z_OriginProposal_0**)
122 odr_malloc(o, num_charsets*sizeof(Z_OriginProposal_0*));
124 for (i = 0; i < num_charsets; i++)
125 p->proposedCharSets[i] =
126 z_get_OriginProposal_0(o, charsets[i]);
128 if (langs && num_langs)
130 p->num_proposedlanguages = num_langs;
131 p->proposedlanguages =
132 (char **) odr_malloc(o, num_langs*sizeof(char *));
134 for (i = 0; i < num_langs; i++)
135 p->proposedlanguages[i] = (char *)langs[i];
140 static Z_CharSetandLanguageNegotiation *z_get_CharSetandLanguageNegotiation(
143 Z_CharSetandLanguageNegotiation *p =
144 (Z_CharSetandLanguageNegotiation *) odr_malloc(o, sizeof(*p));
146 memset(p, 0, sizeof(*p));
151 /* Create EXTERNAL for negotation proposal. Client side */
152 Z_External *yaz_set_proposal_charneg(ODR o,
153 const char **charsets, int num_charsets,
154 const char **langs, int num_langs,
157 Z_External *p = (Z_External *)odr_malloc(o, sizeof(*p));
160 p->indirect_reference = 0;
162 p->direct_reference = odr_oiddup(o, yaz_oid_negot_charset_3);
164 p->which = Z_External_charSetandLanguageNegotiation;
165 p->u.charNeg3 = z_get_CharSetandLanguageNegotiation(o);
166 p->u.charNeg3->which = Z_CharSetandLanguageNegotiation_proposal;
167 p->u.charNeg3->u.proposal =
168 z_get_OriginProposal(o, charsets, num_charsets,
169 langs, num_langs, selected);
174 Z_External *yaz_set_proposal_charneg_list(ODR o,
176 const char *charset_list,
177 const char *lang_list,
180 char **charsets_addresses = 0;
181 char **langs_addresses = 0;
182 int charsets_count = 0;
186 nmem_strsplit(odr_getmem(o), delim, charset_list,
187 &charsets_addresses, &charsets_count);
189 nmem_strsplit(odr_getmem(o), delim, lang_list,
190 &langs_addresses, &langs_count);
191 return yaz_set_proposal_charneg(o,
192 (const char **) charsets_addresses,
194 (const char **) langs_addresses,
200 /* used by yaz_set_response_charneg */
201 static Z_TargetResponse *z_get_TargetResponse(ODR o, const char *charset,
202 const char *lang, int selected)
204 Z_TargetResponse *p = (Z_TargetResponse *) odr_malloc(o, sizeof(*p));
205 int form = get_form(charset);
207 memset(p, 0, sizeof(*p));
212 Z_Iso10646 *is = (Z_Iso10646 *) odr_malloc (o, sizeof(*is));
213 p->which = Z_TargetResponse_iso10646;
216 sprintf(oidname, "1.0.10646.1.0.%d", form);
217 is->encodingLevel = odr_getoidbystr (o, oidname);
221 Z_PrivateCharacterSet *pc =
222 (Z_PrivateCharacterSet *)odr_malloc(o, sizeof(*pc));
224 memset(pc, 0, sizeof(*pc));
226 p->which = Z_TargetResponse_private;
229 pc->which = Z_PrivateCharacterSet_externallySpecified;
230 pc->u.externallySpecified =
231 z_ext_record2(o, charset);
233 p->recordsInSelectedCharSets = (bool_t *)odr_malloc(o, sizeof(bool_t));
234 *p->recordsInSelectedCharSets = (selected) ? 1 : 0;
236 p->selectedLanguage = lang ? (char *) odr_strdup(o, lang) : 0;
240 /* Create charset response. Server side */
241 Z_External *yaz_set_response_charneg(ODR o, const char *charset,
242 const char *lang, int selected)
244 Z_External *p = (Z_External *)odr_malloc(o, sizeof(*p));
247 p->indirect_reference = 0;
249 p->direct_reference = odr_oiddup(o, yaz_oid_negot_charset_3);
251 p->which = Z_External_charSetandLanguageNegotiation;
252 p->u.charNeg3 = z_get_CharSetandLanguageNegotiation(o);
253 p->u.charNeg3->which = Z_CharSetandLanguageNegotiation_response;
254 p->u.charNeg3->u.response = z_get_TargetResponse(o, charset, lang, selected);
259 /* Get negotiation from OtherInformation. Client&Server side */
260 Z_CharSetandLanguageNegotiation *yaz_get_charneg_record(Z_OtherInformation *p)
267 for (i = 0; i < p->num_elements; i++)
270 if ((p->list[i]->which == Z_OtherInfo_externallyDefinedInfo) &&
271 (pext = p->list[i]->information.externallyDefinedInfo))
273 if (!oid_oidcmp(pext->direct_reference, yaz_oid_negot_charset_3)
274 && pext->which == Z_External_charSetandLanguageNegotiation)
276 return pext->u.charNeg3;
283 /* Delete negotiation from OtherInformation. Client&Server side */
284 int yaz_del_charneg_record(Z_OtherInformation **p)
291 for (i = 0; i < (*p)->num_elements; i++)
294 if (((*p)->list[i]->which == Z_OtherInfo_externallyDefinedInfo) &&
295 (pext = (*p)->list[i]->information.externallyDefinedInfo))
297 if (!oid_oidcmp(pext->direct_reference, yaz_oid_negot_charset_3)
298 && pext->which == Z_External_charSetandLanguageNegotiation)
300 if ((*p)->num_elements <= 1)
304 --((*p)->num_elements);
305 for (; i < (*p)->num_elements; i++)
306 (*p)->list[i] = (*p)->list[i+1];
316 /* Get charsets, langs, selected from negotiation.. Server side */
317 void yaz_get_proposal_charneg(NMEM mem, Z_CharSetandLanguageNegotiation *p,
318 char ***charsets, int *num_charsets,
319 char ***langs, int *num_langs, int *selected)
322 Z_OriginProposal *pro = p->u.proposal;
324 if (num_charsets && charsets)
326 if (pro->num_proposedCharSets)
328 *num_charsets = pro->num_proposedCharSets;
330 (*charsets) = (char **)
331 nmem_malloc(mem, pro->num_proposedCharSets * sizeof(char *));
333 for (i = 0; i < pro->num_proposedCharSets; i++)
337 if (pro->proposedCharSets[i]->which ==
338 Z_OriginProposal_0_private &&
339 pro->proposedCharSets[i]->u.zprivate->which ==
340 Z_PrivateCharacterSet_externallySpecified)
343 pro->proposedCharSets[i]->u.zprivate->u.externallySpecified;
345 if (pext->which == Z_External_octet)
347 (*charsets)[i] = (char *)
348 nmem_malloc(mem, (1+pext->u.octet_aligned->len) *
351 memcpy((*charsets)[i], pext->u.octet_aligned->buf,
352 pext->u.octet_aligned->len);
353 (*charsets)[i][pext->u.octet_aligned->len] = 0;
356 else if (pro->proposedCharSets[i]->which ==
357 Z_OriginProposal_0_iso10646)
358 (*charsets)[i] = set_form(
359 pro->proposedCharSets[i]->u.iso10646->encodingLevel);
366 if (langs && num_langs)
368 if (pro->num_proposedlanguages)
370 *num_langs = pro->num_proposedlanguages;
373 nmem_malloc(mem, pro->num_proposedlanguages * sizeof(char *));
375 for (i = 0; i < pro->num_proposedlanguages; i++)
376 (*langs)[i] = nmem_strdup(mem, pro->proposedlanguages[i]);
382 if (pro->recordsInSelectedCharSets && selected)
383 *selected = *pro->recordsInSelectedCharSets;
386 /* Return charset, lang, selected from negotiation.. Client side */
387 void yaz_get_response_charneg(NMEM mem, Z_CharSetandLanguageNegotiation *p,
388 char **charset, char **lang, int *selected)
390 Z_TargetResponse *res = p->u.response;
392 if (charset && res->which == Z_TargetResponse_private &&
393 res->u.zprivate->which == Z_PrivateCharacterSet_externallySpecified)
395 Z_External *pext = res->u.zprivate->u.externallySpecified;
397 if (pext->which == Z_External_octet)
400 nmem_malloc(mem, (1+pext->u.octet_aligned->len)*sizeof(char));
401 memcpy(*charset, pext->u.octet_aligned->buf,
402 pext->u.octet_aligned->len);
403 (*charset)[pext->u.octet_aligned->len] = 0;
406 if (charset && res->which == Z_TargetResponse_iso10646)
407 *charset = set_form(res->u.iso10646->encodingLevel);
408 if (lang && res->selectedLanguage)
409 *lang = nmem_strdup(mem, res->selectedLanguage);
411 if (selected && res->recordsInSelectedCharSets)
412 *selected = *res->recordsInSelectedCharSets;
417 * c-file-style: "Stroustrup"
418 * indent-tabs-mode: nil
420 * vim: shiftwidth=4 tabstop=8 expandtab