a345310e05ea55ab31374c2d497b70a24fe0dd07
[yazproxy-moved-to-github.git] / src / yaz-proxy-config.cpp
1 /* $Id: yaz-proxy-config.cpp,v 1.3 2004-04-11 12:25:01 adam Exp $
2    Copyright (c) 1998-2004, Index Data.
3
4 This file is part of the yaz-proxy.
5
6 Zebra is free software; you can redistribute it and/or modify it under
7 the terms of the GNU General Public License as published by the Free
8 Software Foundation; either version 2, or (at your option) any later
9 version.
10
11 Zebra is distributed in the hope that it will be useful, but WITHOUT ANY
12 WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14 for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with YAZ proxy; see the file LICENSE.  If not, write to the
18 Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
19 02111-1307, USA.
20  */
21
22 #include <ctype.h>
23 #include <yaz/log.h>
24 #include <yazproxy/proxy.h>
25
26 Yaz_ProxyConfig::Yaz_ProxyConfig()
27 {
28     m_copy = 0;
29 #if HAVE_XSLT
30     m_docPtr = 0;
31     m_proxyPtr = 0;
32 #endif
33 }
34
35 Yaz_ProxyConfig::~Yaz_ProxyConfig()
36 {
37 #if HAVE_XSLT
38     if (!m_copy && m_docPtr)
39         xmlFreeDoc(m_docPtr);
40 #endif
41 }
42
43 int Yaz_ProxyConfig::read_xml(const char *fname)
44 {
45 #if HAVE_XSLT
46     xmlDocPtr ndoc = xmlParseFile(fname);
47
48     if (!ndoc)
49     {
50         yaz_log(LOG_WARN, "Config file %s not found or parse error", fname);
51         return -1;  // no good
52     }
53     xmlNodePtr proxyPtr = xmlDocGetRootElement(ndoc);
54     if (!proxyPtr || proxyPtr->type != XML_ELEMENT_NODE ||
55         strcmp((const char *) proxyPtr->name, "proxy"))
56     {
57         yaz_log(LOG_WARN, "No proxy element in %s", fname);
58         xmlFreeDoc(ndoc);
59         return -1;
60     }
61     m_proxyPtr = proxyPtr;
62
63     // OK: release previous and make it the current one.
64     if (m_docPtr)
65         xmlFreeDoc(m_docPtr);
66     m_docPtr = ndoc;
67     return 0;
68 #else
69     return -2;
70 #endif
71 }
72
73 #if HAVE_XSLT
74 const char *Yaz_ProxyConfig::get_text(xmlNodePtr ptr)
75 {
76     for(ptr = ptr->children; ptr; ptr = ptr->next)
77         if (ptr->type == XML_TEXT_NODE)
78         {
79             xmlChar *t = ptr->content;
80             if (t)
81             {
82                 while (*t == ' ')
83                     t++;
84                 return (const char *) t;
85             }
86         }
87     return 0;
88 }
89 #endif
90
91 #if HAVE_XSLT
92 void Yaz_ProxyConfig::return_limit(xmlNodePtr ptr,
93                                    int *limit_bw,
94                                    int *limit_pdu,
95                                    int *limit_req)
96 {
97     for (ptr = ptr->children; ptr; ptr = ptr->next)
98     {
99         if (ptr->type == XML_ELEMENT_NODE 
100             && !strcmp((const char *) ptr->name, "bandwidth"))
101         {
102             const char *t = get_text(ptr);
103             if (t)
104                 *limit_bw = atoi(t);
105         }
106         if (ptr->type == XML_ELEMENT_NODE 
107             && !strcmp((const char *) ptr->name, "retrieve"))
108         {
109             const char *t = get_text(ptr);
110             if (t)
111                 *limit_req = atoi(t);
112         }
113         if (ptr->type == XML_ELEMENT_NODE 
114             && !strcmp((const char *) ptr->name, "pdu"))
115         {
116             const char *t = get_text(ptr);
117             if (t)
118                 *limit_pdu = atoi(t);
119         }
120     }
121 }
122 #endif
123
124 #if HAVE_XSLT
125 void Yaz_ProxyConfig::return_target_info(xmlNodePtr ptr,
126                                          const char **url,
127                                          int *limit_bw,
128                                          int *limit_pdu,
129                                          int *limit_req,
130                                          int *target_idletime,
131                                          int *client_idletime,
132                                          int *keepalive_limit_bw,
133                                          int *keepalive_limit_pdu,
134                                          int *pre_init,
135                                          const char **cql2rpn)
136 {
137     *pre_init = 0;
138     int no_url = 0;
139     ptr = ptr->children;
140     for (; ptr; ptr = ptr->next)
141     {
142         if (ptr->type == XML_ELEMENT_NODE 
143             && !strcmp((const char *) ptr->name, "preinit"))
144         {
145             const char *v = get_text(ptr);
146             *pre_init = v ? atoi(v) : 1;
147         }
148         if (ptr->type == XML_ELEMENT_NODE 
149             && !strcmp((const char *) ptr->name, "url"))
150         {
151             const char *t = get_text(ptr);
152             if (t && no_url < MAX_ZURL_PLEX)
153             {
154                 url[no_url++] = t;
155                 url[no_url] = 0;
156             }
157         }
158         if (ptr->type == XML_ELEMENT_NODE 
159             && !strcmp((const char *) ptr->name, "keepalive"))
160         {
161             int dummy;
162             *keepalive_limit_bw = 500000;
163             *keepalive_limit_pdu = 1000;
164             return_limit(ptr, keepalive_limit_bw, keepalive_limit_pdu,
165                          &dummy);
166         }
167         if (ptr->type == XML_ELEMENT_NODE 
168             && !strcmp((const char *) ptr->name, "limit"))
169             return_limit(ptr, limit_bw, limit_pdu, limit_req);
170         if (ptr->type == XML_ELEMENT_NODE 
171             && !strcmp((const char *) ptr->name, "target-timeout"))
172         {
173             const char *t = get_text(ptr);
174             if (t)
175             {
176                 *target_idletime = atoi(t);
177                 if (*target_idletime < 0)
178                     *target_idletime = 0;
179             }
180         }
181         if (ptr->type == XML_ELEMENT_NODE 
182             && !strcmp((const char *) ptr->name, "client-timeout"))
183         {
184             const char *t = get_text(ptr);
185             if (t)
186             {
187                 *client_idletime = atoi(t);
188                 if (*client_idletime < 0)
189                     *client_idletime = 0;
190             }
191         }
192         if (ptr->type == XML_ELEMENT_NODE 
193             && !strcmp((const char *) ptr->name, "cql2rpn"))
194         {
195             const char *t = get_text(ptr);
196             if (t)
197                 *cql2rpn = t;
198         }
199     }
200 }
201 #endif
202
203 int Yaz_ProxyConfig::atoi_l(const char **cp)
204 {
205     int v = 0;
206     while (**cp && isdigit(**cp))
207     {
208         v = v*10 + (**cp - '0');
209         (*cp)++;
210     }
211     return v;
212 }
213
214 int Yaz_ProxyConfig::match_list(int v, const char *m)
215 {
216   while(m && *m)
217   {
218       while(*m && isspace(*m))
219           m++;
220       if (*m == '*')
221           return 1;
222       int l = atoi_l(&m);
223       int h = l;
224       if (*m == '-')
225       {
226           ++m;
227           h = atoi_l(&m);
228       }
229       if (v >= l && v <= h)
230           return 1;
231       if (*m == ',')
232           m++;
233   }
234   return 0;
235 }
236
237 #if HAVE_XSLT
238 int Yaz_ProxyConfig::check_type_1_attributes(ODR odr, xmlNodePtr ptrl,
239                                              Z_AttributeList *attrs,
240                                              char **addinfo)
241 {
242     int i;
243     for (i = 0; i<attrs->num_attributes; i++)
244     {
245         Z_AttributeElement *el = attrs->attributes[i];
246         
247         if (!el->attributeType)
248             continue;
249         int type = *el->attributeType;
250         int *value = 0;
251         
252         if (el->which == Z_AttributeValue_numeric && el->value.numeric)
253             value = el->value.numeric;
254         
255         xmlNodePtr ptr;
256         for(ptr = ptrl->children; ptr; ptr = ptr->next)
257         {
258             if (ptr->type == XML_ELEMENT_NODE &&
259                 !strcmp((const char *) ptr->name, "attribute"))
260             {
261                 const char *match_type = 0;
262                 const char *match_value = 0;
263                 const char *match_error = 0;
264                 struct _xmlAttr *attr;
265                 for (attr = ptr->properties; attr; attr = attr->next)
266                 {
267                     if (!strcmp((const char *) attr->name, "type") &&
268                         attr->children && attr->children->type == XML_TEXT_NODE)
269                         match_type = (const char *) attr->children->content;
270                     if (!strcmp((const char *) attr->name, "value") &&
271                         attr->children && attr->children->type == XML_TEXT_NODE)
272                         match_value = (const char *) attr->children->content;
273                     if (!strcmp((const char *) attr->name, "error") &&
274                         attr->children && attr->children->type == XML_TEXT_NODE)
275                         match_error = (const char *) attr->children->content;
276                 }
277                 if (match_type && match_value)
278                 {
279                     char addinfo_str[20];
280                     if (!match_list(type, match_type))
281                         continue;
282                     
283                     *addinfo_str = '\0';
284                     if (!strcmp(match_type, "*"))
285                         sprintf (addinfo_str, "%d", type);
286                     else if (value)
287                     {
288                         if (!match_list(*value, match_value))
289                             continue;
290                         sprintf (addinfo_str, "%d", *value);
291                     }
292                     else
293                         continue;
294                     
295                     if (match_error)
296                     {
297                         if (*addinfo_str)
298                             *addinfo = odr_strdup(odr, addinfo_str);
299                         return atoi(match_error);
300                     }
301                     break;
302                 }
303             }
304         }
305     }
306     return 0;
307 }
308 #endif
309
310 #if HAVE_XSLT
311 int Yaz_ProxyConfig::check_type_1_structure(ODR odr, xmlNodePtr ptr,
312                                             Z_RPNStructure *q,
313                                             char **addinfo)
314 {
315     if (q->which == Z_RPNStructure_complex)
316     {
317         int e = check_type_1_structure(odr, ptr, q->u.complex->s1, addinfo);
318         if (e)
319             return e;
320         e = check_type_1_structure(odr, ptr, q->u.complex->s2, addinfo);
321         return e;
322     }
323     else if (q->which == Z_RPNStructure_simple)
324     {
325         if (q->u.simple->which == Z_Operand_APT)
326         {
327             return check_type_1_attributes(
328                 odr, ptr, q->u.simple->u.attributesPlusTerm->attributes,
329                 addinfo);
330         }
331     }
332     return 0;
333 }
334 #endif
335
336 #if HAVE_XSLT
337 int Yaz_ProxyConfig::check_type_1(ODR odr, xmlNodePtr ptr, Z_RPNQuery *query,
338                                   char **addinfo)
339 {
340     // possibly check for Bib-1
341     return check_type_1_structure(odr, ptr, query->RPNStructure, addinfo);
342 }
343 #endif
344
345 int Yaz_ProxyConfig::check_query(ODR odr, const char *name, Z_Query *query,
346                                  char **addinfo)
347 {
348 #if HAVE_XSLT
349     xmlNodePtr ptr;
350     
351     ptr = find_target_node(name, 0);
352     if (ptr)
353     {
354         if (query->which == Z_Query_type_1 || query->which == Z_Query_type_101)
355             return check_type_1(odr, ptr, query->u.type_1, addinfo);
356     }
357 #endif
358     return 0;
359 }
360
361 #if HAVE_XSLT
362 int Yaz_ProxyConfig::check_schema(xmlNodePtr ptr, Z_RecordComposition *comp,
363                                   const char *schema_identifier)
364 {
365     char *esn = 0;
366     int default_match = 1;
367     if (comp && comp->which == Z_RecordComp_simple &&
368         comp->u.simple && comp->u.simple->which == Z_ElementSetNames_generic)
369     {
370         esn = comp->u.simple->u.generic;
371     }
372     // if no ESN/schema was given accept..
373     if (!esn)
374         return 1;
375     // check if schema identifier match
376     if (schema_identifier && !strcmp(esn, schema_identifier))
377         return 1;
378     // Check each name element
379     for (; ptr; ptr = ptr->next)
380     {
381         if (ptr->type == XML_ELEMENT_NODE 
382             && !strcmp((const char *) ptr->name, "name"))
383         {
384             xmlNodePtr tptr = ptr->children;
385             default_match = 0;
386             for (; tptr; tptr = tptr->next)
387                 if (tptr->type == XML_TEXT_NODE && tptr->content)
388                 {
389                     xmlChar *t = tptr->content;
390                     while (*t && isspace(*t))
391                         t++;
392                     int i = 0;
393                     while (esn[i] && esn[i] == t[i])
394                         i++;
395                     if (!esn[i] && (!t[i] || isspace(t[i])))
396                         return 1;
397                 }
398         }
399     }
400     return default_match;
401 }
402 #endif
403
404 int Yaz_ProxyConfig::check_syntax(ODR odr, const char *name,
405                                   Odr_oid *syntax, Z_RecordComposition *comp,
406                                   char **addinfo,
407                                   char **stylesheet, char **schema)
408 {
409     if (stylesheet)
410     {
411         xfree (*stylesheet);
412         *stylesheet = 0;
413     }
414     if (schema)
415     {
416         xfree (*schema);
417         *schema = 0;
418     }
419 #if HAVE_XSLT
420     int syntax_has_matched = 0;
421     xmlNodePtr ptr;
422     
423     ptr = find_target_node(name, 0);
424     if (!ptr)
425         return 0;
426     for(ptr = ptr->children; ptr; ptr = ptr->next)
427     {
428         if (ptr->type == XML_ELEMENT_NODE &&
429             !strcmp((const char *) ptr->name, "syntax"))
430         {
431             int match = 0;  // if we match record syntax
432             const char *match_type = 0;
433             const char *match_error = 0;
434             const char *match_marcxml = 0;
435             const char *match_stylesheet = 0;
436             const char *match_identifier = 0;
437             struct _xmlAttr *attr;
438             for (attr = ptr->properties; attr; attr = attr->next)
439             {
440                 if (!strcmp((const char *) attr->name, "type") &&
441                     attr->children && attr->children->type == XML_TEXT_NODE)
442                     match_type = (const char *) attr->children->content;
443                 if (!strcmp((const char *) attr->name, "error") &&
444                     attr->children && attr->children->type == XML_TEXT_NODE)
445                     match_error = (const char *) attr->children->content;
446                 if (!strcmp((const char *) attr->name, "marcxml") &&
447                     attr->children && attr->children->type == XML_TEXT_NODE)
448                     match_marcxml = (const char *) attr->children->content;
449                 if (!strcmp((const char *) attr->name, "stylesheet") &&
450                     attr->children && attr->children->type == XML_TEXT_NODE)
451                     match_stylesheet = (const char *) attr->children->content;
452                 if (!strcmp((const char *) attr->name, "identifier") &&
453                     attr->children && attr->children->type == XML_TEXT_NODE)
454                     match_identifier = (const char *) attr->children->content;
455             }
456             if (match_type)
457             {
458                 if (!strcmp(match_type, "*"))
459                     match = 1;
460                 else if (!strcmp(match_type, "none"))
461                 {
462                     if (syntax == 0)
463                         match = 1;
464                 }
465                 else if (syntax)
466                 {
467                     int match_oid[OID_SIZE];
468                     oid_name_to_oid(CLASS_RECSYN, match_type, match_oid);
469                     if (oid_oidcmp(match_oid, syntax) == 0)
470                         match = 1;
471                 }
472             }
473             if (match)
474             {
475                 if (!match_error)
476                     syntax_has_matched = 1;
477                 match = check_schema(ptr->children, comp, match_identifier);
478             }
479             if (match)
480             {
481                 if (stylesheet && match_stylesheet)
482                 {
483                     xfree(*stylesheet);
484                     *stylesheet = xstrdup(match_stylesheet);
485                 }
486                 if (schema && match_identifier)
487                 {
488                     xfree(*schema);
489                     *schema = xstrdup(match_identifier);
490                 }
491                 if (match_marcxml)
492                 {
493                     return -1;
494                 }
495                 if (match_error)
496                 {
497                     if (syntax_has_matched)  // if syntax OK, bad schema/ESN
498                         return 25;
499                     if (syntax)
500                     {
501                         char dotoid_str[100];
502                         oid_to_dotstring(syntax, dotoid_str);
503                         *addinfo = odr_strdup(odr, dotoid_str);
504                     }
505                     return atoi(match_error);
506                 }
507                 return 0;
508             }
509         }
510     }
511 #endif
512     return 0;
513 }
514
515 #if HAVE_XSLT
516 xmlNodePtr Yaz_ProxyConfig::find_target_db(xmlNodePtr ptr, const char *db)
517 {
518     xmlNodePtr dptr;
519     if (!db)
520         return ptr;
521     if (!ptr)
522         return 0;
523     for (dptr = ptr->children; dptr; dptr = dptr->next)
524         if (dptr->type == XML_ELEMENT_NODE &&
525             !strcmp((const char *) dptr->name, "database"))
526         {
527             struct _xmlAttr *attr;
528             for (attr = dptr->properties; attr; attr = attr->next)
529                 if (!strcmp((const char *) attr->name, "name"))
530                 {
531                     if (attr->children
532                         && attr->children->type==XML_TEXT_NODE
533                         && attr->children->content 
534                         && (!strcmp((const char *) attr->children->content, db)
535                             || !strcmp((const char *) attr->children->content,
536                                        "*")))
537                         return dptr;
538                 }
539         }
540     return ptr;
541 }
542     
543 xmlNodePtr Yaz_ProxyConfig::find_target_node(const char *name, const char *db)
544 {
545     xmlNodePtr ptr;
546     if (!m_proxyPtr)
547         return 0;
548     for (ptr = m_proxyPtr->children; ptr; ptr = ptr->next)
549     {
550         if (ptr->type == XML_ELEMENT_NODE &&
551             !strcmp((const char *) ptr->name, "target"))
552         {
553             // default one ? 
554             if (!name)
555             {
556                 // <target default="1"> ?
557                 struct _xmlAttr *attr;
558                 for (attr = ptr->properties; attr; attr = attr->next)
559                     if (!strcmp((const char *) attr->name, "default") &&
560                         attr->children && attr->children->type == XML_TEXT_NODE)
561                     {
562                         xmlChar *t = attr->children->content;
563                         if (!t || *t == '1')
564                         {
565                             return find_target_db(ptr, db);
566                         }
567                     }
568             }
569             else
570             {
571                 // <target name="name"> ?
572                 struct _xmlAttr *attr;
573                 for (attr = ptr->properties; attr; attr = attr->next)
574                     if (!strcmp((const char *) attr->name, "name"))
575                     {
576                         if (attr->children
577                             && attr->children->type==XML_TEXT_NODE
578                             && attr->children->content 
579                             && (!strcmp((const char *) attr->children->content,
580                                         name)
581                                 || !strcmp((const char *) attr->children->content,
582                                            "*")))
583                         {
584                             return find_target_db(ptr, db);
585                         }
586                     }
587             }
588         }
589     }
590     return 0;
591 }
592 #endif
593
594 int Yaz_ProxyConfig::get_target_no(int no,
595                                    const char **name,
596                                    const char **url,
597                                    int *limit_bw,
598                                    int *limit_pdu,
599                                    int *limit_req,
600                                    int *target_idletime,
601                                    int *client_idletime,
602                                    int *max_clients,
603                                    int *keepalive_limit_bw,
604                                    int *keepalive_limit_pdu,
605                                    int *pre_init,
606                                    const char **cql2rpn)
607 {
608 #if HAVE_XSLT
609     xmlNodePtr ptr;
610     if (!m_proxyPtr)
611         return 0;
612     int i = 0;
613     for (ptr = m_proxyPtr->children; ptr; ptr = ptr->next)
614         if (ptr->type == XML_ELEMENT_NODE &&
615             !strcmp((const char *) ptr->name, "target"))
616         {
617             if (i == no)
618             {
619                 struct _xmlAttr *attr;
620                 for (attr = ptr->properties; attr; attr = attr->next)
621                     if (!strcmp((const char *) attr->name, "name"))
622                     {
623                         if (attr->children
624                             && attr->children->type==XML_TEXT_NODE
625                             && attr->children->content)
626                             *name = (const char *) attr->children->content;
627                     }
628                 return_target_info(ptr, url, limit_bw, limit_pdu, limit_req,
629                                    target_idletime, client_idletime,
630                                    keepalive_limit_bw, keepalive_limit_pdu,
631                                    pre_init, cql2rpn);
632                 return 1;
633             }
634             i++;
635         }
636 #endif
637     return 0;
638 }
639
640 int Yaz_ProxyConfig::mycmp(const char *hay, const char *item, size_t len)
641 {
642     if (len == strlen(item) && memcmp(hay, item, len) == 0)
643         return 1;
644     return 0;
645 }
646
647 void Yaz_ProxyConfig::get_generic_info(int *log_mask,
648                                        int *max_clients)
649 {
650 #if HAVE_XSLT
651     xmlNodePtr ptr;
652     if (!m_proxyPtr)
653         return;
654     for (ptr = m_proxyPtr->children; ptr; ptr = ptr->next)
655     {
656         if (ptr->type == XML_ELEMENT_NODE 
657             && !strcmp((const char *) ptr->name, "log"))
658         {
659             const char *v = get_text(ptr);
660             *log_mask = 0;
661             while (v && *v)
662             {
663                 const char *cp = v;
664                 while (*cp && *cp != ',' && !isspace(*cp))
665                     cp++;
666                 size_t len = cp - v;
667                 if (mycmp(v, "client-apdu", len))
668                     *log_mask |= PROXY_LOG_APDU_CLIENT;
669                 if (mycmp(v, "server-apdu", len))
670                     *log_mask |= PROXY_LOG_APDU_SERVER;
671                 if (mycmp(v, "client-requests", len))
672                     *log_mask |= PROXY_LOG_REQ_CLIENT;
673                 if (mycmp(v, "server-requests", len))
674                     *log_mask |= PROXY_LOG_REQ_SERVER;
675                 if (isdigit(*v))
676                     *log_mask |= atoi(v);
677                 if (*cp == ',')
678                     cp++;
679                 while (*cp && isspace(*cp))
680                     cp++;
681                 v = cp;
682             }
683         }
684         if (ptr->type == XML_ELEMENT_NODE &&
685             !strcmp((const char *) ptr->name, "max-clients"))
686         {
687             const char *t = get_text(ptr);
688             if (t)
689             {
690                 *max_clients = atoi(t);
691                 if (*max_clients  < 1)
692                     *max_clients = 1;
693             }
694         }
695     }
696 #endif
697 }
698
699 char *Yaz_ProxyConfig::get_explain(ODR odr, const char *name, const char *db,
700                                    int *len)
701 {
702 #if HAVE_XSLT
703     xmlNodePtr ptr = find_target_node(name, db);
704     if (ptr)
705     {
706         ptr = ptr->children;
707         for (; ptr; ptr = ptr->next)
708             if (ptr->type == XML_ELEMENT_NODE &&
709                 !strcmp((const char *) ptr->name, "explain"))
710             {
711                 xmlNodePtr ptr1 = ptr->children;
712                 if (db)
713                 {
714                     for (; ptr1; ptr1 = ptr1->next)
715                         if (ptr1->type == XML_ELEMENT_NODE &&
716                             !strcmp((const char *) ptr1->name, "serverInfo"))
717                             break;
718                     if (!ptr1)
719                         continue;
720                     for (ptr1 = ptr1->children; ptr1; ptr1 = ptr1->next)
721                         if (ptr1->type == XML_ELEMENT_NODE &&
722                             !strcmp((const char *) ptr1->name, "database"))
723                             break;
724                     
725                     if (!ptr1)
726                         continue;
727                     for (ptr1 = ptr1->children; ptr1; ptr1 = ptr1->next)
728                         if (ptr1->type == XML_TEXT_NODE &&
729                             ptr1->content &&
730                             !strcmp((const char *) ptr1->content, db))
731                             break;
732                     if (!ptr1)
733                         continue;
734                 }
735                 xmlNodePtr ptr2 = xmlCopyNode(ptr, 1);
736
737                 xmlDocPtr doc = xmlNewDoc((const xmlChar *) "1.0");
738                 
739                 xmlDocSetRootElement(doc, ptr2);
740                 
741                 xmlChar *buf_out;
742                 xmlDocDumpMemory(doc, &buf_out, len);
743                 char *content = (char*) odr_malloc(odr, *len);
744                 memcpy(content, buf_out, *len);
745                 
746                 xmlFree(buf_out);
747                 xmlFreeDoc(doc);
748                 return content;
749             }
750     }
751 #endif
752     return 0;
753 }
754
755 void Yaz_ProxyConfig::get_target_info(const char *name,
756                                       const char **url,
757                                       int *limit_bw,
758                                       int *limit_pdu,
759                                       int *limit_req,
760                                       int *target_idletime,
761                                       int *client_idletime,
762                                       int *max_clients,
763                                       int *keepalive_limit_bw,
764                                       int *keepalive_limit_pdu,
765                                       int *pre_init,
766                                       const char **cql2rpn)
767 {
768 #if HAVE_XSLT
769     xmlNodePtr ptr;
770     if (!m_proxyPtr)
771     {
772         url[0] = name;
773         url[1] = 0;
774         return;
775     }
776     url[0] = 0;
777     for (ptr = m_proxyPtr->children; ptr; ptr = ptr->next)
778     {
779         if (ptr->type == XML_ELEMENT_NODE &&
780             !strcmp((const char *) ptr->name, "max-clients"))
781         {
782             const char *t = get_text(ptr);
783             if (t)
784             {
785                 *max_clients = atoi(t);
786                 if (*max_clients  < 1)
787                     *max_clients = 1;
788             }
789         }
790     }
791     ptr = find_target_node(name, 0);
792     if (ptr)
793     {
794         if (name)
795         {
796             url[0] = name;
797             url[1] = 0;
798         }
799         return_target_info(ptr, url, limit_bw, limit_pdu, limit_req,
800                            target_idletime, client_idletime,
801                            keepalive_limit_bw, keepalive_limit_pdu,
802                            pre_init, cql2rpn);
803     }
804 #else
805     *url = name;
806     return;
807 #endif
808 }
809
810