Fix non-SOAP compile
[yaz-moved-to-github.git] / zutil / charneg.c
1 /* 
2  $ $Id: charneg.c,v 1.7 2002-10-04 19:06:25 adam Exp $
3  * Helper functions for Character Set and Language Negotiation - 3
4  */
5
6 #include <stdio.h>
7 #include <yaz/otherinfo.h>
8 #include <yaz/z-charneg.h>
9 #include <yaz/charneg.h>
10 #include <yaz/yaz-util.h>
11
12 static Z_External* z_ext_record2(ODR o, int oid_class, int oid_value,
13                                  const char *buf, int len)
14 {
15     Z_External *p;
16     oident oid;
17     
18     if (!(p = (Z_External *)odr_malloc(o, sizeof(*p)))) return 0;
19     
20     p->descriptor = 0;
21     p->indirect_reference = 0;
22     
23     oid.proto = PROTO_Z3950;
24     oid.oclass = (enum oid_class) oid_class;
25     oid.value = (enum oid_value) oid_value;
26     p->direct_reference = odr_oiddup(o, oid_getoidbyent(&oid));
27     
28     p->which = Z_External_octet;
29     if (!(p->u.octet_aligned = (Odr_oct *)odr_malloc(o, sizeof(Odr_oct)))) {
30         return 0;
31     }
32     if (!(p->u.octet_aligned->buf = (unsigned char *)odr_malloc(o, len))) {
33         return 0;
34     }
35     p->u.octet_aligned->len = p->u.octet_aligned->size = len;
36     memcpy(p->u.octet_aligned->buf, buf, len);
37         
38     return p;
39 }
40
41 static int get_form(const char *charset)
42 {
43     int form = -1;
44
45
46     if (!yaz_matchstr(charset, "UCS-2"))
47         form = 2;
48     if (!yaz_matchstr(charset, "UCS-4"))
49         form = 4;
50     if (!yaz_matchstr(charset, "UTF-16"))
51         form = 5;
52     if (!yaz_matchstr(charset, "UTF-8"))
53         form = 8;
54
55     return form;
56 }
57
58 static char *set_form (Odr_oid *encoding)
59 {
60     static char *charset = 0;
61     if ( oid_oidlen(encoding) != 6)
62         return 0;
63     if (encoding[5] == 2)
64         charset = "UCS-2";
65     if (encoding[5] == 4)
66         charset = "UCS-4";
67     if (encoding[5] == 5)
68         charset = "UTF-16";
69     if (encoding[5] == 8)
70         charset = "UTF-8";
71     return charset;
72 }
73
74 static Z_OriginProposal_0 *z_get_OriginProposal_0(ODR o, const char *charset)
75 {
76     int form = get_form (charset);
77     Z_OriginProposal_0 *p0 =
78         (Z_OriginProposal_0*)odr_malloc(o, sizeof(*p0));
79
80     memset(p0, 0, sizeof(*p0));
81
82     if (form > 0)
83     {   /* ISO 10646 (UNICODE) */
84         char oidname[20];
85
86         Z_Iso10646 *is = (Z_Iso10646 *) odr_malloc (o, sizeof(*is));
87         p0->which = Z_OriginProposal_0_iso10646;
88         p0->u.iso10646 = is;
89         is->collections = 0;
90         sprintf (oidname, "1.0.10646.1.0.%d", form);
91         is->encodingLevel = odr_getoidbystr (o, oidname);
92     }
93     else
94     {   /* private ones */
95         Z_PrivateCharacterSet *pc =
96             (Z_PrivateCharacterSet *)odr_malloc(o, sizeof(*pc));
97
98         
99         memset(pc, 0, sizeof(*pc));
100         
101         p0->which = Z_OriginProposal_0_private;
102         p0->u.zprivate = pc;
103         
104         pc->which = Z_PrivateCharacterSet_externallySpecified;
105         pc->u.externallySpecified =
106             z_ext_record2(o, CLASS_RECSYN, VAL_NOP, charset, strlen(charset));
107     }
108     return p0;
109 }
110
111 static Z_OriginProposal *z_get_OriginProposal(
112     ODR o, const char **charsets, int num_charsets,
113     const char **langs, int num_langs, int selected)
114 {       
115     int i;
116     Z_OriginProposal *p = (Z_OriginProposal *) odr_malloc(o, sizeof(*p));
117                 
118     memset(p, 0, sizeof(*p));
119
120     p->recordsInSelectedCharSets = (bool_t *)odr_malloc(o, sizeof(bool_t));
121     *p->recordsInSelectedCharSets = (selected) ? 1:0;
122
123     if (charsets && num_charsets) {             
124         
125         p->num_proposedCharSets = num_charsets;
126         p->proposedCharSets = 
127             (Z_OriginProposal_0**)
128             odr_malloc(o, num_charsets*sizeof(Z_OriginProposal_0*));
129
130         for (i = 0; i<num_charsets; i++)
131             p->proposedCharSets[i] =
132                 z_get_OriginProposal_0(o, charsets[i]);
133     }
134     if (langs && num_langs) {
135         
136         p->num_proposedlanguages = num_langs;
137
138         p->proposedlanguages = 
139             (char **) odr_malloc(o, num_langs*sizeof(char *));
140
141         for (i = 0; i<num_langs; i++) {
142
143             p->proposedlanguages[i] = (char *)langs[i];
144                         
145         }
146     }
147     return p;
148 }
149
150 static Z_CharSetandLanguageNegotiation *z_get_CharSetandLanguageNegotiation(
151     ODR o)
152 {
153     Z_CharSetandLanguageNegotiation *p =
154         (Z_CharSetandLanguageNegotiation *) odr_malloc(o, sizeof(*p));
155     
156     memset(p, 0, sizeof(*p));
157         
158     return p;
159 }
160
161 Z_External *yaz_set_proposal_charneg(ODR o,
162                                      const char **charsets, int num_charsets,
163                                      const char **langs, int num_langs,
164                                      int selected)
165 {
166     Z_External *p = (Z_External *)odr_malloc(o, sizeof(*p));
167     oident oid;
168         
169     p->descriptor = 0;
170     p->indirect_reference = 0;  
171
172     oid.proto = PROTO_Z3950;
173     oid.oclass = CLASS_NEGOT;
174     oid.value = VAL_CHARNEG3;
175     p->direct_reference = odr_oiddup(o, oid_getoidbyent(&oid));
176
177     p->which = Z_External_charSetandLanguageNegotiation;
178     p->u.charNeg3 = z_get_CharSetandLanguageNegotiation(o);
179     p->u.charNeg3->which = Z_CharSetandLanguageNegotiation_proposal;
180     p->u.charNeg3->u.proposal =
181         z_get_OriginProposal(o, charsets, num_charsets,
182                              langs, num_langs, selected);
183
184     return p;
185 }
186
187 static Z_TargetResponse *z_get_TargetResponse(ODR o, const char *charset,
188                                               const char *lang, int selected)
189 {       
190     Z_TargetResponse *p = (Z_TargetResponse *) odr_malloc(o, sizeof(*p));
191     int form = get_form(charset);
192
193     memset(p, 0, sizeof(*p));
194
195     if (form > 0)
196     {
197         char oidname[20];
198
199         Z_Iso10646 *is = (Z_Iso10646 *) odr_malloc (o, sizeof(*is));
200         p->which = Z_TargetResponse_iso10646;
201         p->u.iso10646 = is;
202         is->collections = 0;
203         sprintf (oidname, "1.0.10646.1.0.%d", form);
204         is->encodingLevel = odr_getoidbystr (o, oidname);
205     }
206     else
207     {
208         Z_PrivateCharacterSet *pc =
209             (Z_PrivateCharacterSet *)odr_malloc(o, sizeof(*pc));
210         
211         memset(pc, 0, sizeof(*pc));
212         
213         p->which = Z_TargetResponse_private;
214         p->u.zprivate = pc;
215         
216         pc->which = Z_PrivateCharacterSet_externallySpecified;
217         pc->u.externallySpecified =
218         z_ext_record2(o, CLASS_RECSYN, VAL_NOP, charset, strlen(charset));
219     }
220     p->recordsInSelectedCharSets = (bool_t *)odr_malloc(o, sizeof(bool_t));
221     *p->recordsInSelectedCharSets = (selected) ? 1:0;
222     
223     p->selectedLanguage = lang ? (char *)odr_strdup(o, lang) : 0;
224     return p;
225 }
226
227 Z_External *yaz_set_response_charneg(ODR o, const char *charset,
228                                      const char *lang, int selected)
229 {
230     Z_External *p = (Z_External *)odr_malloc(o, sizeof(*p));
231     oident oid;
232         
233     p->descriptor = 0;
234     p->indirect_reference = 0;  
235
236     oid.proto = PROTO_Z3950;
237     oid.oclass = CLASS_NEGOT;
238     oid.value = VAL_CHARNEG3;
239     p->direct_reference = odr_oiddup(o, oid_getoidbyent(&oid));
240
241     p->which = Z_External_charSetandLanguageNegotiation;
242     p->u.charNeg3 = z_get_CharSetandLanguageNegotiation(o);
243     p->u.charNeg3->which = Z_CharSetandLanguageNegotiation_response;
244     p->u.charNeg3->u.response = z_get_TargetResponse(o, charset, lang, selected);
245
246     return p;
247 }
248
249 Z_CharSetandLanguageNegotiation *yaz_get_charneg_record(Z_OtherInformation *p)
250 {
251     Z_External *pext;
252     int i;
253         
254     if(!p)
255         return 0;
256         
257     for (i=0; i<p->num_elements; i++) {
258         
259         if ((p->list[i]->which == Z_OtherInfo_externallyDefinedInfo) &&
260             (pext = p->list[i]->information.externallyDefinedInfo)) {
261                                         
262             oident *ent = oid_getentbyoid(pext->direct_reference);
263                         
264             if (ent && ent->value == VAL_CHARNEG3 && ent->oclass == CLASS_NEGOT &&
265                 pext->which == Z_External_charSetandLanguageNegotiation) {
266                                 
267                 return pext->u.charNeg3;
268             }
269         }
270     }
271         
272     return 0;
273 }
274
275 void yaz_get_proposal_charneg(NMEM mem, Z_CharSetandLanguageNegotiation *p,
276                               char ***charsets, int *num_charsets,
277                               char ***langs, int *num_langs, int *selected)
278 {
279     int i;
280     Z_OriginProposal *pro = p->u.proposal;
281     
282     if (num_charsets && charsets)
283     {
284         if (pro->num_proposedCharSets)
285         {
286             *num_charsets = pro->num_proposedCharSets;
287             
288             (*charsets) = (char **)
289                 nmem_malloc(mem, pro->num_proposedCharSets * sizeof(char *));
290             
291             for (i=0; i<pro->num_proposedCharSets; i++) 
292             {
293                 (*charsets)[i] = 0;
294                 
295                 if (pro->proposedCharSets[i]->which ==
296                     Z_OriginProposal_0_private &&
297                     pro->proposedCharSets[i]->u.zprivate->which ==
298                     Z_PrivateCharacterSet_externallySpecified) {
299                     
300                     Z_External *pext =
301                         pro->proposedCharSets[i]->u.zprivate->u.externallySpecified;
302                     
303                     if (pext->which == Z_External_octet) {
304                         
305                         (*charsets)[i] = (char *)
306                             nmem_malloc(mem, (1+pext->u.octet_aligned->len) *
307                                         sizeof(char));
308                         
309                         memcpy ((*charsets)[i], pext->u.octet_aligned->buf,
310                                 pext->u.octet_aligned->len);
311                         (*charsets)[i][pext->u.octet_aligned->len] = 0;
312                         
313                     }
314                 }
315                 else if (pro->proposedCharSets[i]->which ==
316                          Z_OriginProposal_0_iso10646)
317                     (*charsets)[i] = set_form (
318                         pro->proposedCharSets[i]->u.iso10646->encodingLevel);
319             }
320         }
321         else
322             *num_charsets = 0;
323     }
324     
325     if (langs && num_langs)
326     {
327         if (pro->num_proposedlanguages)
328         {
329             *num_langs = pro->num_proposedlanguages;
330             
331             (*langs) = (char **)
332                 nmem_malloc(mem, pro->num_proposedlanguages * sizeof(char *));
333             
334             for (i=0; i<pro->num_proposedlanguages; i++)
335                 (*langs)[i] = nmem_strdup(mem, pro->proposedlanguages[i]);
336         }
337         else
338             *num_langs = 0;
339     }
340     
341     if(pro->recordsInSelectedCharSets && selected)
342         *selected = *pro->recordsInSelectedCharSets;
343 }
344
345 void yaz_get_response_charneg(NMEM mem, Z_CharSetandLanguageNegotiation *p,
346                               char **charset, char **lang, int *selected)
347 {
348     Z_TargetResponse *res = p->u.response;
349         
350     if (charset && res->which == Z_TargetResponse_private &&
351         res->u.zprivate->which == Z_PrivateCharacterSet_externallySpecified) {
352
353         Z_External *pext = res->u.zprivate->u.externallySpecified;
354         
355         if (pext->which == Z_External_octet) {
356             
357             *charset = (char *)
358                 nmem_malloc(mem, (1+pext->u.octet_aligned->len)*sizeof(char));
359             memcpy (*charset, pext->u.octet_aligned->buf,
360                     pext->u.octet_aligned->len);
361             (*charset)[pext->u.octet_aligned->len] = 0;
362         }       
363     }
364     if (charset && res->which == Z_TargetResponse_iso10646)
365         *charset = set_form (res->u.iso10646->encodingLevel);
366     if (lang && res->selectedLanguage)
367         *lang = nmem_strdup (mem, res->selectedLanguage);
368
369     if(selected && res->recordsInSelectedCharSets)
370         *selected = *res->recordsInSelectedCharSets;
371 }