1 /* This file is part of the YAZ toolkit.
2 * Copyright (C) 1995-2011 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)))) return 0;
30 p->indirect_reference = 0;
32 p->direct_reference = odr_oiddup(o, yaz_oid_negot_charset_id);
34 p->which = Z_External_octet;
35 if (!(p->u.octet_aligned = (Odr_oct *)odr_malloc(o, sizeof(Odr_oct)))) {
38 if (!(p->u.octet_aligned->buf = (unsigned char *)odr_malloc(o, len))) {
41 p->u.octet_aligned->len = p->u.octet_aligned->size = len;
42 memcpy(p->u.octet_aligned->buf, buf, len);
47 static int get_form(const char *charset)
52 if (!yaz_matchstr(charset, "UCS-2"))
54 if (!yaz_matchstr(charset, "UCS-4"))
56 if (!yaz_matchstr(charset, "UTF-16"))
58 if (!yaz_matchstr(charset, "UTF-8"))
64 static char *set_form (Odr_oid *encoding)
66 static char *charset = 0;
67 if ( oid_oidlen(encoding) != 6)
80 static Z_OriginProposal_0 *z_get_OriginProposal_0(ODR o, const char *charset)
82 int form = get_form (charset);
83 Z_OriginProposal_0 *p0 =
84 (Z_OriginProposal_0*)odr_malloc(o, sizeof(*p0));
86 memset(p0, 0, sizeof(*p0));
89 { /* ISO 10646 (UNICODE) */
92 Z_Iso10646 *is = (Z_Iso10646 *) odr_malloc (o, sizeof(*is));
93 p0->which = Z_OriginProposal_0_iso10646;
96 sprintf (oidname, "1.0.10646.1.0.%d", form);
97 is->encodingLevel = odr_getoidbystr (o, oidname);
101 Z_PrivateCharacterSet *pc =
102 (Z_PrivateCharacterSet *)odr_malloc(o, sizeof(*pc));
104 memset(pc, 0, sizeof(*pc));
106 p0->which = Z_OriginProposal_0_private;
109 pc->which = Z_PrivateCharacterSet_externallySpecified;
110 pc->u.externallySpecified = z_ext_record2(o, charset);
115 static Z_OriginProposal *z_get_OriginProposal(
116 ODR o, const char **charsets, int num_charsets,
117 const char **langs, int num_langs, int selected)
120 Z_OriginProposal *p = (Z_OriginProposal *) odr_malloc(o, sizeof(*p));
122 memset(p, 0, sizeof(*p));
124 p->recordsInSelectedCharSets = (bool_t *)odr_malloc(o, sizeof(bool_t));
125 *p->recordsInSelectedCharSets = (selected) ? 1:0;
127 if (charsets && num_charsets) {
129 p->num_proposedCharSets = num_charsets;
130 p->proposedCharSets =
131 (Z_OriginProposal_0**)
132 odr_malloc(o, num_charsets*sizeof(Z_OriginProposal_0*));
134 for (i = 0; i<num_charsets; i++)
135 p->proposedCharSets[i] =
136 z_get_OriginProposal_0(o, charsets[i]);
138 if (langs && num_langs) {
140 p->num_proposedlanguages = num_langs;
142 p->proposedlanguages =
143 (char **) odr_malloc(o, num_langs*sizeof(char *));
145 for (i = 0; i<num_langs; i++) {
147 p->proposedlanguages[i] = (char *)langs[i];
154 static Z_CharSetandLanguageNegotiation *z_get_CharSetandLanguageNegotiation(
157 Z_CharSetandLanguageNegotiation *p =
158 (Z_CharSetandLanguageNegotiation *) odr_malloc(o, sizeof(*p));
160 memset(p, 0, sizeof(*p));
165 /* Create EXTERNAL for negotation proposal. Client side */
166 Z_External *yaz_set_proposal_charneg(ODR o,
167 const char **charsets, int num_charsets,
168 const char **langs, int num_langs,
171 Z_External *p = (Z_External *)odr_malloc(o, sizeof(*p));
174 p->indirect_reference = 0;
176 p->direct_reference = odr_oiddup(o, yaz_oid_negot_charset_3);
178 p->which = Z_External_charSetandLanguageNegotiation;
179 p->u.charNeg3 = z_get_CharSetandLanguageNegotiation(o);
180 p->u.charNeg3->which = Z_CharSetandLanguageNegotiation_proposal;
181 p->u.charNeg3->u.proposal =
182 z_get_OriginProposal(o, charsets, num_charsets,
183 langs, num_langs, selected);
188 Z_External *yaz_set_proposal_charneg_list(ODR o,
190 const char *charset_list,
191 const char *lang_list,
194 char **charsets_addresses = 0;
195 char **langs_addresses = 0;
196 int charsets_count = 0;
200 nmem_strsplit(odr_getmem(o), delim, charset_list,
201 &charsets_addresses, &charsets_count);
203 nmem_strsplit(odr_getmem(o), delim, lang_list,
204 &langs_addresses, &langs_count);
205 return yaz_set_proposal_charneg(o,
206 (const char **) charsets_addresses,
208 (const char **) langs_addresses,
214 /* used by yaz_set_response_charneg */
215 static Z_TargetResponse *z_get_TargetResponse(ODR o, const char *charset,
216 const char *lang, int selected)
218 Z_TargetResponse *p = (Z_TargetResponse *) odr_malloc(o, sizeof(*p));
219 int form = get_form(charset);
221 memset(p, 0, sizeof(*p));
227 Z_Iso10646 *is = (Z_Iso10646 *) odr_malloc (o, sizeof(*is));
228 p->which = Z_TargetResponse_iso10646;
231 sprintf (oidname, "1.0.10646.1.0.%d", form);
232 is->encodingLevel = odr_getoidbystr (o, oidname);
236 Z_PrivateCharacterSet *pc =
237 (Z_PrivateCharacterSet *)odr_malloc(o, sizeof(*pc));
239 memset(pc, 0, sizeof(*pc));
241 p->which = Z_TargetResponse_private;
244 pc->which = Z_PrivateCharacterSet_externallySpecified;
245 pc->u.externallySpecified =
246 z_ext_record2(o, charset);
248 p->recordsInSelectedCharSets = (bool_t *)odr_malloc(o, sizeof(bool_t));
249 *p->recordsInSelectedCharSets = (selected) ? 1:0;
251 p->selectedLanguage = lang ? (char *)odr_strdup(o, lang) : 0;
255 /* Create charset response. Server side */
256 Z_External *yaz_set_response_charneg(ODR o, const char *charset,
257 const char *lang, int selected)
259 Z_External *p = (Z_External *)odr_malloc(o, sizeof(*p));
262 p->indirect_reference = 0;
264 p->direct_reference = odr_oiddup(o, yaz_oid_negot_charset_3);
266 p->which = Z_External_charSetandLanguageNegotiation;
267 p->u.charNeg3 = z_get_CharSetandLanguageNegotiation(o);
268 p->u.charNeg3->which = Z_CharSetandLanguageNegotiation_response;
269 p->u.charNeg3->u.response = z_get_TargetResponse(o, charset, lang, selected);
274 /* Get negotiation from OtherInformation. Client&Server side */
275 Z_CharSetandLanguageNegotiation *yaz_get_charneg_record(Z_OtherInformation *p)
282 for (i = 0; i < p->num_elements; i++) {
284 if ((p->list[i]->which == Z_OtherInfo_externallyDefinedInfo) &&
285 (pext = p->list[i]->information.externallyDefinedInfo)) {
287 if (!oid_oidcmp(pext->direct_reference, yaz_oid_negot_charset_3)
288 && pext->which == Z_External_charSetandLanguageNegotiation)
290 return pext->u.charNeg3;
297 /* Delete negotiation from OtherInformation. Client&Server side */
298 int yaz_del_charneg_record(Z_OtherInformation **p)
305 for (i = 0; i < (*p)->num_elements; i++) {
307 if (((*p)->list[i]->which == Z_OtherInfo_externallyDefinedInfo) &&
308 (pext = (*p)->list[i]->information.externallyDefinedInfo))
310 if (!oid_oidcmp(pext->direct_reference, yaz_oid_negot_charset_3)
311 && pext->which == Z_External_charSetandLanguageNegotiation)
313 if ((*p)->num_elements <= 1)
317 --((*p)->num_elements);
318 for(; i < (*p)->num_elements; i++)
319 (*p)->list[i] = (*p)->list[i+1];
329 /* Get charsets, langs, selected from negotiation.. Server side */
330 void yaz_get_proposal_charneg(NMEM mem, Z_CharSetandLanguageNegotiation *p,
331 char ***charsets, int *num_charsets,
332 char ***langs, int *num_langs, int *selected)
335 Z_OriginProposal *pro = p->u.proposal;
337 if (num_charsets && charsets)
339 if (pro->num_proposedCharSets)
341 *num_charsets = pro->num_proposedCharSets;
343 (*charsets) = (char **)
344 nmem_malloc(mem, pro->num_proposedCharSets * sizeof(char *));
346 for (i=0; i<pro->num_proposedCharSets; i++)
350 if (pro->proposedCharSets[i]->which ==
351 Z_OriginProposal_0_private &&
352 pro->proposedCharSets[i]->u.zprivate->which ==
353 Z_PrivateCharacterSet_externallySpecified) {
356 pro->proposedCharSets[i]->u.zprivate->u.externallySpecified;
358 if (pext->which == Z_External_octet) {
360 (*charsets)[i] = (char *)
361 nmem_malloc(mem, (1+pext->u.octet_aligned->len) *
364 memcpy ((*charsets)[i], pext->u.octet_aligned->buf,
365 pext->u.octet_aligned->len);
366 (*charsets)[i][pext->u.octet_aligned->len] = 0;
370 else if (pro->proposedCharSets[i]->which ==
371 Z_OriginProposal_0_iso10646)
372 (*charsets)[i] = set_form (
373 pro->proposedCharSets[i]->u.iso10646->encodingLevel);
380 if (langs && num_langs)
382 if (pro->num_proposedlanguages)
384 *num_langs = pro->num_proposedlanguages;
387 nmem_malloc(mem, pro->num_proposedlanguages * sizeof(char *));
389 for (i=0; i<pro->num_proposedlanguages; i++)
390 (*langs)[i] = nmem_strdup(mem, pro->proposedlanguages[i]);
396 if(pro->recordsInSelectedCharSets && selected)
397 *selected = *pro->recordsInSelectedCharSets;
400 /* Return charset, lang, selected from negotiation.. Client side */
401 void yaz_get_response_charneg(NMEM mem, Z_CharSetandLanguageNegotiation *p,
402 char **charset, char **lang, int *selected)
404 Z_TargetResponse *res = p->u.response;
406 if (charset && res->which == Z_TargetResponse_private &&
407 res->u.zprivate->which == Z_PrivateCharacterSet_externallySpecified) {
409 Z_External *pext = res->u.zprivate->u.externallySpecified;
411 if (pext->which == Z_External_octet) {
414 nmem_malloc(mem, (1+pext->u.octet_aligned->len)*sizeof(char));
415 memcpy (*charset, pext->u.octet_aligned->buf,
416 pext->u.octet_aligned->len);
417 (*charset)[pext->u.octet_aligned->len] = 0;
420 if (charset && res->which == Z_TargetResponse_iso10646)
421 *charset = set_form (res->u.iso10646->encodingLevel);
422 if (lang && res->selectedLanguage)
423 *lang = nmem_strdup (mem, res->selectedLanguage);
425 if(selected && res->recordsInSelectedCharSets)
426 *selected = *res->recordsInSelectedCharSets;
431 * c-file-style: "Stroustrup"
432 * indent-tabs-mode: nil
434 * vim: shiftwidth=4 tabstop=8 expandtab