Fix non-libxml2 compilation
[yazpp-moved-to-github.git] / src / yaz-proxy-config.cpp
1 /*
2  * Copyright (c) 1998-2003, Index Data.
3  * See the file LICENSE for details.
4  * 
5  * $Id: yaz-proxy-config.cpp,v 1.3 2003-10-04 06:44:16 adam Exp $
6  */
7
8 #include <yaz/log.h>
9 #include <yaz++/proxy.h>
10
11 Yaz_ProxyConfig::Yaz_ProxyConfig()
12 {
13     m_copy = 0;
14 #if HAVE_XML2
15     m_docPtr = 0;
16     m_proxyPtr = 0;
17 #endif
18 }
19
20 Yaz_ProxyConfig::~Yaz_ProxyConfig()
21 {
22 #if HAVE_XML2
23     if (!m_copy && m_docPtr)
24         xmlFreeDoc(m_docPtr);
25 #endif
26 }
27
28 void Yaz_ProxyConfig::operator=(const Yaz_ProxyConfig &conf)
29 {
30 #if HAVE_XML2
31     m_docPtr = conf.m_docPtr;
32     m_proxyPtr = conf.m_proxyPtr;
33 #endif
34     m_copy = 1;
35 }
36
37 int Yaz_ProxyConfig::read_xml(const char *fname)
38 {
39 #if HAVE_XML2
40     xmlDocPtr ndoc = xmlParseFile(fname);
41
42     if (!ndoc)
43     {
44         yaz_log(LOG_WARN, "Config file %s not found or parse error", fname);
45         return -1;  // no good
46     }
47     xmlNodePtr proxyPtr = xmlDocGetRootElement(ndoc);
48     if (!proxyPtr || proxyPtr->type != XML_ELEMENT_NODE ||
49         strcmp((const char *) proxyPtr->name, "proxy"))
50     {
51         yaz_log(LOG_WARN, "No proxy element in %s", fname);
52         xmlFreeDoc(ndoc);
53         return -1;
54     }
55     m_proxyPtr = proxyPtr;
56
57     // OK: release previous and make it the current one.
58     if (m_docPtr)
59         xmlFreeDoc(m_docPtr);
60     m_docPtr = ndoc;
61     return 0;
62 #else
63     return -2;
64 #endif
65 }
66
67 #if HAVE_XML2
68 const char *Yaz_ProxyConfig::get_text(xmlNodePtr ptr)
69 {
70     for(ptr = ptr->children; ptr; ptr = ptr->next)
71         if (ptr->type == XML_TEXT_NODE)
72         {
73             xmlChar *t = ptr->content;
74             if (t)
75             {
76                 while (*t == ' ')
77                     t++;
78                 return (const char *) t;
79             }
80         }
81     return 0;
82 }
83 #endif
84
85 #if HAVE_XML2
86 void Yaz_ProxyConfig::return_limit(xmlNodePtr ptr,
87                                    int *limit_bw,
88                                    int *limit_pdu,
89                                    int *limit_req)
90 {
91     for (ptr = ptr->children; ptr; ptr = ptr->next)
92     {
93         if (ptr->type == XML_ELEMENT_NODE 
94             && !strcmp((const char *) ptr->name, "bandwidth"))
95         {
96             const char *t = get_text(ptr);
97             if (t)
98                 *limit_bw = atoi(t);
99         }
100         if (ptr->type == XML_ELEMENT_NODE 
101             && !strcmp((const char *) ptr->name, "retrieve"))
102         {
103             const char *t = get_text(ptr);
104             if (t)
105                 *limit_req = atoi(t);
106         }
107         if (ptr->type == XML_ELEMENT_NODE 
108             && !strcmp((const char *) ptr->name, "pdu"))
109         {
110             const char *t = get_text(ptr);
111             if (t)
112                 *limit_pdu = atoi(t);
113         }
114     }
115 }
116 #endif
117
118 #if HAVE_XML2
119 void Yaz_ProxyConfig::return_target_info(xmlNodePtr ptr,
120                                          const char **url,
121                                          int *keepalive,
122                                          int *limit_bw,
123                                          int *limit_pdu,
124                                          int *limit_req,
125                                          int *target_idletime,
126                                          int *client_idletime)
127 {
128     ptr = ptr->children;
129     for (; ptr; ptr = ptr->next)
130     {
131         if (ptr->type == XML_ELEMENT_NODE 
132             && !strcmp((const char *) ptr->name, "url"))
133         {
134             const char *t = get_text(ptr);
135             if (t)
136                 *url = t;
137         }
138         if (ptr->type == XML_ELEMENT_NODE 
139             && !strcmp((const char *) ptr->name, "keepalive"))
140         {
141             const char *t = get_text(ptr);
142             if (!t || *t == '1')
143                 *keepalive = 1;
144             else
145                 *keepalive = 0;
146         }
147         if (ptr->type == XML_ELEMENT_NODE 
148             && !strcmp((const char *) ptr->name, "limit"))
149             return_limit(ptr, limit_bw, limit_pdu, limit_req);
150         if (ptr->type == XML_ELEMENT_NODE 
151             && !strcmp((const char *) ptr->name, "target-timeout"))
152         {
153             const char *t = get_text(ptr);
154             if (t)
155             {
156                 *target_idletime = atoi(t);
157                 if (*target_idletime < 0)
158                     *target_idletime = 0;
159             }
160         }
161         if (ptr->type == XML_ELEMENT_NODE 
162             && !strcmp((const char *) ptr->name, "client-timeout"))
163         {
164             const char *t = get_text(ptr);
165             if (t)
166             {
167                 *client_idletime = atoi(t);
168                 if (*client_idletime < 0)
169                     *client_idletime = 0;
170             }
171         }
172     }
173 }
174 #endif
175
176 #if HAVE_XML2
177 int Yaz_ProxyConfig::check_type_1_attributes(ODR odr, xmlNodePtr ptr,
178                                              Z_AttributeList *attrs,
179                                              char **addinfo)
180 {
181     for(ptr = ptr->children; ptr; ptr = ptr->next)
182     {
183         if (ptr->type == XML_ELEMENT_NODE &&
184             !strcmp((const char *) ptr->name, "query"))
185         {
186             const char *match_type = 0;
187             const char *match_value = 0;
188             const char *match_error = 0;
189             struct _xmlAttr *attr;
190             for (attr = ptr->properties; attr; attr = attr->next)
191             {
192                 if (!strcmp((const char *) attr->name, "type") &&
193                     attr->children && attr->children->type == XML_TEXT_NODE)
194                     match_type = (const char *) attr->children->content;
195                 if (!strcmp((const char *) attr->name, "value") &&
196                     attr->children && attr->children->type == XML_TEXT_NODE)
197                     match_value = (const char *) attr->children->content;
198                 if (!strcmp((const char *) attr->name, "error") &&
199                     attr->children && attr->children->type == XML_TEXT_NODE)
200                     match_error = (const char *) attr->children->content;
201             }
202             int i;
203
204             if (match_type && match_value)
205             {
206                 for (i = 0; i<attrs->num_attributes; i++)
207                 {
208                     Z_AttributeElement *el = attrs->attributes[i];
209                     char value_str[20];
210                     
211                     value_str[0] = '\0';
212                     if (!el->attributeType)
213                         continue;
214                     int type = *el->attributeType;
215
216                     if (strcmp(match_type, "*")) {
217                         if (type != atoi(match_type))
218                             continue;  // no match on type
219                     }
220                     if (el->which == Z_AttributeValue_numeric && 
221                         el->value.numeric)
222                     {
223                         int value = *el->value.numeric;
224                         if (strcmp(match_value, "*")) {
225                             if (value != atoi(match_value))
226                                 continue;  // no match on value
227                         }
228                         sprintf(value_str, "%d", value);
229                     }
230                     else
231                         continue;
232                     if (match_error)
233                     {
234                         if (*value_str)
235                             *addinfo = odr_strdup(odr, value_str);
236                         return atoi(match_error);
237                     }
238                     return 0;
239                 }
240             }
241         }
242     }
243     return 0;
244 }
245 #endif
246
247 #if HAVE_XML2
248 int Yaz_ProxyConfig::check_type_1_structure(ODR odr, xmlNodePtr ptr,
249                                             Z_RPNStructure *q,
250                                             char **addinfo)
251 {
252     int c;
253     if (q->which == Z_RPNStructure_complex)
254     {
255         int e = check_type_1_structure(odr, ptr, q->u.complex->s1, addinfo);
256         if (e)
257             return e;
258         e = check_type_1_structure(odr, ptr, q->u.complex->s2, addinfo);
259         return e;
260     }
261     else if (q->which == Z_RPNStructure_simple)
262     {
263         if (q->u.simple->which == Z_Operand_APT)
264         {
265             return check_type_1_attributes(
266                 odr, ptr, q->u.simple->u.attributesPlusTerm->attributes,
267                 addinfo);
268         }
269     }
270     return 0;
271 }
272 #endif
273
274 #if HAVE_XML2
275 int Yaz_ProxyConfig::check_type_1(ODR odr, xmlNodePtr ptr, Z_RPNQuery *query,
276                                   char **addinfo)
277 {
278     // possibly check for Bib-1
279     return check_type_1_structure(odr, ptr, query->RPNStructure, addinfo);
280 }
281 #endif
282
283 int Yaz_ProxyConfig::check_query(ODR odr, const char *name, Z_Query *query,
284                                  char **addinfo)
285 {
286 #if HAVE_XML2
287     xmlNodePtr ptr;
288     
289     ptr = find_target_node(name);
290     if (ptr)
291     {
292         if (query->which == Z_Query_type_1 || query->which == Z_Query_type_101)
293             return check_type_1(odr, ptr, query->u.type_1, addinfo);
294     }
295 #endif
296     return 0;
297 }
298
299 #if HAVE_XML2
300 xmlNodePtr Yaz_ProxyConfig::find_target_node(const char *name)
301 {
302     xmlNodePtr ptr;
303     for (ptr = m_proxyPtr->children; ptr; ptr = ptr->next)
304     {
305         if (ptr->type == XML_ELEMENT_NODE &&
306             !strcmp((const char *) ptr->name, "target"))
307         {
308             // default one ? 
309             if (!name)
310             {
311                 // <target default="1"> ?
312                 struct _xmlAttr *attr;
313                 for (attr = ptr->properties; attr; attr = attr->next)
314                     if (!strcmp((const char *) attr->name, "default") &&
315                         attr->children && attr->children->type == XML_TEXT_NODE)
316                     {
317                         xmlChar *t = attr->children->content;
318                         if (!t || *t == '1')
319                             return ptr;
320                     }
321             }
322             else
323             {
324                 // <target name="name"> ?
325                 struct _xmlAttr *attr;
326                 for (attr = ptr->properties; attr; attr = attr->next)
327                     if (!strcmp((const char *) attr->name, "name"))
328                     {
329                         if (attr->children
330                             && attr->children->type==XML_TEXT_NODE
331                             && attr->children->content 
332                             && (!strcmp((const char *) attr->children->content,
333                                         name)
334                                 || !strcmp((const char *) attr->children->content,
335                                            "*")))
336                         {
337                             return ptr;
338                         }
339                     }
340             }
341         }
342     }
343     return 0;
344 }
345 #endif
346
347 void Yaz_ProxyConfig::get_target_info(const char *name,
348                                       const char **url,
349                                       int *keepalive,
350                                       int *limit_bw,
351                                       int *limit_pdu,
352                                       int *limit_req,
353                                       int *target_idletime,
354                                       int *client_idletime,
355                                       int *max_clients)
356 {
357 #if HAVE_XML2
358     xmlNodePtr ptr;
359     if (!m_proxyPtr)
360     {
361         *url = name;
362         return;
363     }
364     for (ptr = m_proxyPtr->children; ptr; ptr = ptr->next)
365     {
366         if (ptr->type == XML_ELEMENT_NODE &&
367             !strcmp((const char *) ptr->name, "max-clients"))
368         {
369             const char *t = get_text(ptr);
370             if (t)
371             {
372                 *max_clients = atoi(t);
373                 if (*max_clients  < 1)
374                     *max_clients = 1;
375             }
376         }
377     }
378     ptr = find_target_node(name);
379     if (ptr)
380     {
381         if (name)
382             *url = name;
383         return_target_info(ptr, url, keepalive, limit_bw, limit_pdu, limit_req,
384                            target_idletime, client_idletime);
385     }
386 #else
387     *url = name;
388     return;
389 #endif
390 }
391
392