DEBIAN_DIST="wheezy squeeze"
-UBUNTU_DIST="quantal precise oneiric natty lucid"
+UBUNTU_DIST="quantal precise oneiric lucid"
CENTOS_DIST="centos5 centos6"
-VERSION=1.3.55
+VERSION=1.3.58
+--- 1.3.58 2013/06/12
+
+Fix loading of filters cql_rpn and sru_z3950 . Was broken by 1.3.57.
+
+--- 1.3.57 2013/06/12
+
+Make RouterChain and RouterXML part of public API (libmetaproxy).
+
+http_client: honor X-Metaproxy-Proxy as an alternative to
+the "proxy" configuration. Allows proxy to be set per HTTP request.
+
+sru_z3950: For SRU requests recognize x-client prefixes as a way
+to ingest "database parameters".. The suffix of x-client- serves
+as database argument name. Multiple may be given. For example:
+ http://path/db/?operation=searchRetrieve&x-client-user=a&x-client-password=b
+is turned into Z39.50 database
+ db,user=a&password=b
+
+--- 1.3.56 2013/05/27
+
+New filter present_chunk. This filter allows splitting of present requests into smaller chunks.
+
+New filter sd_remove, which replaces surrogate diagnostics with
+SUTRS records. This filter tries to deal with clients that breaks
+when receiving surrogate diagnostics.
+
+new filter http_client. Same role as z3950_client, but just for
+HTTP. Allows Metaproxy to operate as a HTTP proxy.
+
+New filter http_rewrite1, which serves as purpose on how to rewrite
+HTTP content with Metaproxy.
+
+Use libboost-system if available, because newer versions of libboost-threads
+requires libboost-system.
+
+Allow frontend_net to serve SSL/HTTPS, because we can specify a server
+certificate now.
+
--- 1.3.55 2013/04/10
zoom: Torus setting: authenticationMode which may hold values "basic"
AC_MSG_ERROR([YAZ++ development libraries missing])
fi
CPPFLAGS="$YAZPPINC $CPPFLAGS"
-AC_MSG_CHECKING([if YAZ is version 4.2.50 or later])
+AC_MSG_CHECKING([if YAZ is version 4.2.59 or later])
AC_COMPILE_IFELSE(
[AC_LANG_PROGRAM([[#include <yaz/yaz-version.h>]],
[[
-#if YAZ_VERSIONL < 0x40232
+#if YAZ_VERSIONL < 0x4023B
#error too old
#endif
]])],
+metaproxy (1.3.58-1indexdata) unstable; urgency=low
+
+ * Upstream.
+
+ -- Adam Dickmeiss <adam@indexdata.dk> Wed, 12 Jun 2013 21:47:19 +0200
+
+metaproxy (1.3.57-1indexdata) unstable; urgency=low
+
+ * Upstream.
+
+ -- Adam Dickmeiss <adam@indexdata.dk> Wed, 12 Jun 2013 15:01:35 +0200
+
+metaproxy (1.3.56-1indexdata) unstable; urgency=low
+
+ * Upstream.
+
+ -- Adam Dickmeiss <adam@indexdata.dk> Mon, 27 May 2013 13:14:23 +0200
+
metaproxy (1.3.55-1indexdata) unstable; urgency=low
* Upstream.
Maintainer: Adam Dickmeiss <adam@indexdata.dk>
Priority: extra
Build-Depends: debhelper (>= 5),
- libyaz4-dev (>= 4.2.50),
+ libyaz4-dev (>= 4.2.59),
libyazpp5-dev (>= 1.4.1),
libxslt1-dev,
libboost-dev,
<refsect1><title>DESCRIPTION</title>
<para>
- This module implements HTTP client functionality. By default,
- if proxy element is not given, it should be used as an explicit
- proxy (non-transparent mode). If proxy element is set, requests
- will be relayed to the proxy given (transparent mode for HTTP clients
- accessing this module).
+ This module implements HTTP client functionality. Filter rontend_net
+ + http_client in combo - acts as a normal, non-transparent, proxy.
+ </para>
+ <para>
+ The element default-host of configuration specifies the default host
+ in remote URL. If this is set, frontend_net + http_client acts as a
+ transparent HTTP proxy as well.
+ </para>
+ <para>
+ The configuration element, proxy, is optional and enables a remote
+ HTTP proxy to be in use.
</para>
</refsect1>
A typical configuration looks like this:
<screen><![CDATA[
<filter type="http_client">
- <proxy>localhost:9999</proxy>
+ <proxy>localhost:3128</proxy>
</filter>
]]>
</screen>
$(srcdir)/config-cgi.xml \
$(srcdir)/config-solr.xml \
$(srcdir)/config-zoom.xml \
+ $(srcdir)/config-proxy.xml \
$(srcdir)/retrieval-info.xml
config = example.simple-auth example.target-auth pqf2pqf.xsl explain.xml \
+++ /dev/null
-<?xml version="1.0"?>
-<metaproxy xmlns="http://indexdata.com/metaproxy" version="1.0">
- <start route="start"/>
- <!-- sample config which illustrates the use of http_file filter.. -->
- <filters>
- <filter id="frontend" type="frontend_net">
- <threads>20</threads>
- <port>@:9000</port>
- <message>FN</message>
- <stat-req>/fn_stat</stat-req>
- </filter>
- </filters>
- <routes>
- <route id="start">
- <filter refid="frontend"/>
- <filter type="http_file">
- <mimetypes>/etc/mime.types</mimetypes>
- <area>
- <documentroot>.</documentroot>
- <prefix>/etc</prefix>
- </area>
- </filter>
- <filter type="log"><category access="false" line="true" apdu="true" /></filter>
-<!--
- <filter type="http_rewrite1">
- <replace content-type="text/html" pattern="YAZ" replacement="yaz"/>
- </filter>
--->
- <filter type="http_client">
-<!--
- <proxy>localhost:9999</proxy>
--->
- </filter>
- <filter type="bounce"/>
- </route>
- </routes>
-</metaproxy>
-
--- /dev/null
+<?xml version="1.0"?>
+<metaproxy xmlns="http://indexdata.com/metaproxy" version="1.0">
+ <start route="start"/>
+ <!-- sample config which illustrates the use of http_file filter.. -->
+ <routes>
+ <route id="start">
+ <filter type="frontend_net">
+ <threads>10</threads>
+ <port>tcp:@:9000</port>
+ <port cert_fname="ztest.pem">ssl:@:9001</port>
+ </filter>
+ <filter type="log">
+ <message>M</message>
+ <category apdu="true"/>
+ </filter>
+ <filter type="http_client">
+ <!-- <default-host>https://localhost:9999</default-host> -->
+ <!-- <proxy>localhost:3128</proxy> -->
+ </filter>
+ </route>
+ </routes>
+</metaproxy>
+
CONFIG=../metaproxy-config
SO=metaproxy_filter_myfilter.so
-all: $(SO)
+all: $(SO) mytest
$(SO): filter_myfilter.cpp
- echo $(LIBS)
- $(CXX) -shared `$(CONFIG) --cflags` -fPIC -I ../src $< \
- -o $(SO) `$(CONFIG) --libs`
+ $(CXX) -shared `$(CONFIG) --cflags` -fPIC $< \
+ -o $@ `$(CONFIG) --libs`
+
+mytest: mytest.cpp
+ $(CXX) `$(CONFIG) --cflags` $< \
+ -o $@ `$(CONFIG) --libs`
clean:
- rm -f *.so
+ rm -f *.so mytest
run: all
../src/metaproxy -c config.xml
--- /dev/null
+/* This file is part of Metaproxy.
+ Copyright (C) 2005-2013 Index Data
+
+Metaproxy is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 2, or (at your option) any later
+version.
+
+Metaproxy is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+#include <yaz/log.h>
+#include <yaz/diagbib1.h>
+
+#include <metaproxy/router_chain.hpp>
+#include <yaz/test.h>
+
+namespace mp = metaproxy_1;
+
+void tst(void)
+{
+ try {
+ mp::RouterChain router;
+ }
+ catch ( ... ) {
+ YAZ_CHECK(0);
+ }
+
+}
+
+int main(int argc, char **argv)
+{
+ YAZ_CHECK_INIT(argc, argv);
+ tst();
+ YAZ_CHECK_TERM;
+}
+
+/*
+ * Local variables:
+ * c-basic-offset: 4
+ * c-file-style: "Stroustrup"
+ * indent-tabs-mode: nil
+ * End:
+ * vim: shiftwidth=4 tabstop=8 expandtab
+ */
+
## Copyright (C) 2005-2013 Index Data
pkginclude_HEADERS= filter.hpp origin.hpp package.hpp \
- router.hpp session.hpp util.hpp xmlutil.hpp
+ router.hpp router_chain.hpp router_xml.hpp \
+ session.hpp util.hpp xmlutil.hpp
--- /dev/null
+/* This file is part of Metaproxy.
+ Copyright (C) 2005-2013 Index Data
+
+Metaproxy is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 2, or (at your option) any later
+version.
+
+Metaproxy is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+#ifndef ROUTER_CHAIN_HPP
+#define ROUTER_CHAIN_HPP
+
+
+#include <metaproxy/router.hpp>
+
+#include <boost/scoped_ptr.hpp>
+#include <stdexcept>
+
+namespace metaproxy_1 {
+ class RouterChain : public Router {
+ class Rep;
+ class Pos;
+ public:
+ RouterChain();
+ virtual ~RouterChain();
+ virtual RoutePos *createpos() const;
+ RouterChain & append(const filter::Base &filter);
+ void start();
+ void stop();
+ private:
+ boost::scoped_ptr<Rep> m_p;
+ /// disabled because class is singleton
+ RouterChain(const RouterChain &);
+
+ /// disabled because class is singleton
+ RouterChain& operator=(const RouterChain &);
+ };
+}
+
+#endif
+/*
+ * Local variables:
+ * c-basic-offset: 4
+ * c-file-style: "Stroustrup"
+ * indent-tabs-mode: nil
+ * End:
+ * vim: shiftwidth=4 tabstop=8 expandtab
+ */
+
--- /dev/null
+/* This file is part of Metaproxy.
+ Copyright (C) 2005-2013 Index Data
+
+Metaproxy is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 2, or (at your option) any later
+version.
+
+Metaproxy is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+#ifndef ROUTER_XML_HPP
+#define ROUTER_XML_HPP
+
+#include <metaproxy/router.hpp>
+
+#include <libxml/tree.h>
+#include <boost/scoped_ptr.hpp>
+
+namespace metaproxy_1
+{
+ class RouterXML : public metaproxy_1::Router
+ {
+ class Rep;
+ class Route;
+ class Pos;
+ public:
+ RouterXML(xmlDocPtr doc,
+ bool test_only, const char *file_include_path);
+ RouterXML(std::string xmlconf,
+ bool test_only);
+
+ ~RouterXML();
+
+ virtual RoutePos *createpos() const;
+ void start();
+ void stop();
+ private:
+ boost::scoped_ptr<Rep> m_p;
+ };
+
+};
+#endif
+
+/*
+ * Local variables:
+ * c-basic-offset: 4
+ * c-file-style: "Stroustrup"
+ * indent-tabs-mode: nil
+ * End:
+ * vim: shiftwidth=4 tabstop=8 expandtab
+ */
+
void get_default_diag(Z_DefaultDiagFormat *r,
int &error_code, std::string &addinfo);
+ Z_RecordComposition *piggyback_to_RecordComposition(
+ ODR odr, Odr_int result_set_size, Z_SearchRequest *sreq);
+
void piggyback(int smallSetUpperBound,
int largeSetLowerBound,
int mediumSetPresentNumber,
Source: metaproxy-%{version}.tar.gz
BuildRoot: %{_tmppath}/%{name}-%{version}-root
Prefix: %{_prefix} /etc/metaproxy
-BuildRequires: pkgconfig, libyaz4-devel >= 4.2.50, libyazpp5-devel >= 1.4.1
+BuildRequires: pkgconfig, libyaz4-devel >= 4.2.59, libyazpp5-devel >= 1.4.1
BuildRequires: libxslt-devel, boost-devel
Conflicts: cf-engine <= 2.12.5
Packager: Adam Dickmeiss <adam@indexdata.dk>
-.libs
-.deps
-*.lo
-*.la
-stamp-h*
+*
+!*.hpp
+!*.cpp
+!*.am
config.hpp
-socket
-Makefile
-Makefile.in
-config.hpp.in
-ex_filter_frontend_net
-ex_router_flexml
-test_boost_threads
-test_boost_time
-test_filter_auth_simple
-test_filter1
-test_filter2
-test_filter_frontend_net
-test_filter_log
-test_filter_multi
-test_filter_query_rewrite
-test_package1
-test_pipe
-test_thread_pool_observer
-test_session1
-test_session2
-test_filter_factory
-test_filter_z3950_client
-test_filter_backend_test
-test_filter_virt_db
-test_router_flexml
-test_ses_map
-tstdl
-metaproxy
-test_filter_bounce
-test_filter_record_transform
-test_filter_sru_to_z3950
-*.o
-metaproxy-config
bin_SCRIPTS = metaproxy-config
filter_src = \
- factory_filter.cpp factory_filter.hpp \
- factory_static.cpp factory_static.hpp \
filter_auth_simple.cpp filter_auth_simple.hpp \
filter_backend_test.cpp filter_backend_test.hpp \
filter_bounce.cpp filter_bounce.hpp \
filter_http_client.cpp filter_http_client.hpp \
filter_http_file.cpp filter_http_file.hpp \
filter_http_rewrite1.cpp filter_http_rewrite1.hpp \
+ filter_http_rewrite.cpp filter_http_rewrite.hpp \
filter_limit.cpp filter_limit.hpp \
filter_load_balance.cpp filter_load_balance.hpp \
filter_log.cpp filter_log.hpp \
filter_virt_db.cpp filter_virt_db.hpp \
filter_z3950_client.cpp filter_z3950_client.hpp \
filter_zeerex_explain.cpp filter_zeerex_explain.hpp \
- filter_zoom.cpp filter_zoom.hpp \
- router_chain.hpp router_chain.cpp \
- router_flexml.hpp router_flexml.cpp
+ filter_zoom.cpp filter_zoom.hpp
lib_LTLIBRARIES = libmetaproxy.la
libmetaproxy_la_LDFLAGS = -version-info 4:0:0 -export-dynamic
libmetaproxy_la_SOURCES = \
+ $(filter_src) \
+ factory_filter.cpp factory_filter.hpp \
+ factory_static.cpp factory_static.hpp \
filter.cpp \
gduutil.cpp gduutil.hpp \
origin.cpp \
torus.cpp torus.hpp \
url_recipe.cpp \
util.cpp \
+ html_parser.hpp html_parser.cpp \
+ router_chain.cpp \
+ router_flexml.hpp router_flexml.cpp \
+ router_xml.cpp \
xmlutil.cpp
libmetaproxy_la_LIBADD = $(YAZPPLALIB) \
$(BOOST_LIB) $(BOOST_SYSTEM_LIB) $(BOOST_THREAD_LIB) \
$(BOOST_REGEX_LIB) $(USEMARCONLALIB)
+tstdl_LDADD = $(metaproxy_LDADD)
+
LDADD = $(metaproxy_LDADD) $(BOOST_TEST_LIB)
AM_LDFLAGS = -export-dynamic
noinst_PROGRAMS = tstdl
tstdl_SOURCES = tstdl.cpp
-metaproxy_SOURCES = metaproxy_prog.cpp $(filter_src)
+metaproxy_SOURCES = metaproxy_prog.cpp
# Rules for dl programs
pkglib_LTLIBRARIES = metaproxy_filter_dl.la
test_filter_record_transform \
test_filter_sru_to_z3950 \
test_filter_virt_db \
+ test_filter_rewrite \
test_ses_map \
test_router_flexml \
+ test_html_parser \
test_xmlutil
TESTS=$(check_PROGRAMS)
test_package1_SOURCES=test_package1.cpp
test_pipe_SOURCES=test_pipe.cpp
-test_filter1_SOURCES=test_filter1.cpp $(filter_src)
-test_filter2_SOURCES=test_filter2.cpp $(filter_src)
+test_filter1_SOURCES=test_filter1.cpp
+test_filter2_SOURCES=test_filter2.cpp
test_session1_SOURCES=test_session1.cpp
test_session2_SOURCES=test_session2.cpp
test_boost_threads_SOURCES=test_boost_threads.cpp
test_thread_pool_observer_SOURCES = test_thread_pool_observer.cpp
-test_filter_auth_simple_SOURCES = test_filter_auth_simple.cpp $(filter_src)
-test_filter_factory_SOURCES = test_filter_factory.cpp $(filter_src)
-test_filter_frontend_net_SOURCES = test_filter_frontend_net.cpp $(filter_src)
-test_filter_log_SOURCES = test_filter_log.cpp $(filter_src)
-test_filter_multi_SOURCES = test_filter_multi.cpp $(filter_src)
-test_filter_query_rewrite_SOURCES = test_filter_query_rewrite.cpp $(filter_src)
-test_filter_z3950_client_SOURCES = test_filter_z3950_client.cpp $(filter_src)
-test_filter_backend_test_SOURCES = test_filter_backend_test.cpp $(filter_src)
-test_filter_bounce_SOURCES = test_filter_bounce.cpp $(filter_src)
-test_filter_record_transform_SOURCES = test_filter_record_transform.cpp \
- $(filter_src)
-test_filter_sru_to_z3950_SOURCES = test_filter_sru_to_z3950.cpp $(filter_src)
-test_filter_virt_db_SOURCES = test_filter_virt_db.cpp $(filter_src)
+test_filter_auth_simple_SOURCES = test_filter_auth_simple.cpp
+test_filter_factory_SOURCES = test_filter_factory.cpp
+test_filter_frontend_net_SOURCES = test_filter_frontend_net.cpp
+test_filter_log_SOURCES = test_filter_log.cpp
+test_filter_multi_SOURCES = test_filter_multi.cpp
+test_filter_query_rewrite_SOURCES = test_filter_query_rewrite.cpp
+test_filter_z3950_client_SOURCES = test_filter_z3950_client.cpp
+test_filter_backend_test_SOURCES = test_filter_backend_test.cpp
+test_filter_bounce_SOURCES = test_filter_bounce.cpp
+test_filter_record_transform_SOURCES = test_filter_record_transform.cpp
+test_filter_sru_to_z3950_SOURCES = test_filter_sru_to_z3950.cpp
+test_filter_virt_db_SOURCES = test_filter_virt_db.cpp
test_ses_map_SOURCES = test_ses_map.cpp
-test_router_flexml_SOURCES = test_router_flexml.cpp $(filter_src)
+test_router_flexml_SOURCES = test_router_flexml.cpp
test_xmlutil_SOURCES = test_xmlutil.cpp
+test_html_parser_SOURCES = test_html_parser.cpp
+test_filter_rewrite_SOURCES = test_filter_rewrite.cpp
+
# doxygen target
dox:
(cd $(top_srcdir) ; make dox)
return (it->second());
}
-bool mp::FactoryFilter::have_dl_support()
-{
-#if HAVE_DLFCN_H
- return true;
-#else
- return false;
-#endif
-}
-
bool mp::FactoryFilter::add_creator_dl(const std::string &fi,
const std::string &path)
{
bool add_creator_dl(const std::string &fi, const std::string &path);
- bool have_dl_support();
-
class NotFound : public std::runtime_error {
public:
NotFound(const std::string msg);
#include "filter_z3950_client.hpp"
#include "filter_zeerex_explain.hpp"
#include "filter_zoom.hpp"
+#include "filter_http_rewrite.hpp"
namespace mp = metaproxy_1;
mp::FactoryStatic::FactoryStatic()
{
-#ifdef HAVE_DLFCN_H
struct metaproxy_1_filter_struct *buildins[] = {
&metaproxy_1_filter_auth_simple,
&metaproxy_1_filter_backend_test,
#ifndef WIN32
&metaproxy_1_filter_cgi,
#endif
- &metaproxy_1_filter_cql_to_rpn,
+ &metaproxy_1_filter_cql_rpn,
&metaproxy_1_filter_frontend_net,
&metaproxy_1_filter_http_client,
&metaproxy_1_filter_http_file,
+ &metaproxy_1_filter_http_rewrite,
&metaproxy_1_filter_http_rewrite1,
&metaproxy_1_filter_limit,
&metaproxy_1_filter_load_balance,
&metaproxy_1_filter_sd_remove,
&metaproxy_1_filter_session_shared,
&metaproxy_1_filter_sort,
- &metaproxy_1_filter_sru_to_z3950,
+ &metaproxy_1_filter_sru_z3950,
&metaproxy_1_filter_template,
&metaproxy_1_filter_virt_db,
&metaproxy_1_filter_z3950_client,
for (i = 0; buildins[i]; i++)
add_creator(buildins[i]->type, buildins[i]->creator);
-// WIN32
-#endif
}
}
extern "C" {
- struct metaproxy_1_filter_struct metaproxy_1_filter_cql_to_rpn = {
+ struct metaproxy_1_filter_struct metaproxy_1_filter_cql_rpn = {
0,
"cql_rpn",
filter_creator
}
extern "C" {
- extern struct metaproxy_1_filter_struct metaproxy_1_filter_cql_to_rpn;
+ extern struct metaproxy_1_filter_struct metaproxy_1_filter_cql_rpn;
}
#endif
Z_GDU *res_gdu = 0;
mp::odr o;
yaz_url_t yaz_url = yaz_url_create();
- std::string uri;
+ const char *http_proxy =
+ z_HTTP_header_remove(&hreq->headers, "X-Metaproxy-Proxy");
+
+ if (!http_proxy)
+ http_proxy = proxy_host.c_str();
- if (proxy_host.length())
- yaz_url_set_proxy(yaz_url, proxy_host.c_str());
+ if (*http_proxy)
+ yaz_url_set_proxy(yaz_url, http_proxy);
+ std::string uri;
if (hreq->path[0] == '/')
{
if (default_host.length())
if (http_response)
{
res_gdu = o.create_HTTP_Response(package.session(), hreq, 200);
+ z_HTTP_header_remove(&http_response->headers, "Transfer-Encoding");
res_gdu->u.HTTP_Response = http_response;
}
else
--- /dev/null
+/* This file is part of Metaproxy.
+ Copyright (C) 2005-2013 Index Data
+
+Metaproxy is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 2, or (at your option) any later
+version.
+
+Metaproxy is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+#include "config.hpp"
+#include <metaproxy/filter.hpp>
+#include <metaproxy/package.hpp>
+#include <metaproxy/util.hpp>
+#include "filter_http_rewrite.hpp"
+
+#include <yaz/zgdu.h>
+#include <yaz/log.h>
+
+#include <boost/regex.hpp>
+#include <boost/lexical_cast.hpp>
+
+#include <vector>
+#include <map>
+
+#if HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+
+namespace mp = metaproxy_1;
+namespace yf = mp::filter;
+
+namespace metaproxy_1 {
+ namespace filter {
+ class HttpRewrite::RuleScope {
+ public:
+ std::vector<std::string> tags;
+ std::vector<std::string> attrs;
+ std::string content_type;
+ };
+ class HttpRewrite::Rule {
+ public:
+ enum Section { METHOD, HEADER, BODY };
+ std::string regex;
+ std::string recipe;
+ std::map<int, std::string> group_index;
+ std::vector<RuleScope> scopes;
+ Section section;
+ const std::string search_replace(
+ std::map<std::string, std::string> & vars,
+ const std::string & txt) const;
+ std::string sub_vars (
+ const std::map<std::string, std::string> & vars) const;
+ void parse_groups();
+ };
+ class HttpRewrite::Rules {
+ public:
+ std::vector<Rule> rules;
+ void rewrite_reqline (mp::odr & o, Z_HTTP_Request *hreq,
+ std::map<std::string, std::string> & vars) const;
+ void rewrite_headers(mp::odr & o, Z_HTTP_Header *headers,
+ std::map<std::string, std::string> & vars) const;
+ void rewrite_body (mp::odr & o,
+ char **content_buf, int *content_len,
+ std::map<std::string, std::string> & vars) const;
+ const std::string test_patterns(
+ std::map<std::string, std::string> & vars,
+ const std::string & txt) const;
+ };
+ }
+}
+
+yf::HttpRewrite::HttpRewrite() : req_rules(new Rules), res_rules(new Rules)
+{
+}
+
+yf::HttpRewrite::~HttpRewrite()
+{
+}
+
+void yf::HttpRewrite::process(mp::Package & package) const
+{
+ yaz_log(YLOG_LOG, "HttpRewrite begins....");
+ Z_GDU *gdu = package.request().get();
+ //map of request/response vars
+ std::map<std::string, std::string> vars;
+ //we have an http req
+ if (gdu && gdu->which == Z_GDU_HTTP_Request)
+ {
+ Z_HTTP_Request *hreq = gdu->u.HTTP_Request;
+ mp::odr o;
+ req_rules->rewrite_reqline(o, hreq, vars);
+ yaz_log(YLOG_LOG, ">> Request headers");
+ req_rules->rewrite_headers(o, hreq->headers, vars);
+ req_rules->rewrite_body(o,
+ &hreq->content_buf, &hreq->content_len,
+ vars);
+ package.request() = gdu;
+ }
+ package.move();
+ gdu = package.response().get();
+ if (gdu && gdu->which == Z_GDU_HTTP_Response)
+ {
+ Z_HTTP_Response *hres = gdu->u.HTTP_Response;
+ yaz_log(YLOG_LOG, "Response code %d", hres->code);
+ mp::odr o;
+ yaz_log(YLOG_LOG, "<< Respose headers");
+ res_rules->rewrite_headers(o, hres->headers, vars);
+ res_rules->rewrite_body(o, &hres->content_buf,
+ &hres->content_len, vars);
+ package.response() = gdu;
+ }
+}
+
+void yf::HttpRewrite::Rules::rewrite_reqline (mp::odr & o,
+ Z_HTTP_Request *hreq,
+ std::map<std::string, std::string> & vars) const
+{
+ //rewrite the request line
+ std::string path;
+ if (strstr(hreq->path, "http://") == hreq->path)
+ {
+ yaz_log(YLOG_LOG, "Path in the method line is absolute, "
+ "possibly a proxy request");
+ path += hreq->path;
+ }
+ else
+ {
+ //TODO what about proto
+ path += "http://";
+ path += z_HTTP_header_lookup(hreq->headers, "Host");
+ path += hreq->path;
+ }
+ yaz_log(YLOG_LOG, "Proxy request URL is %s", path.c_str());
+ std::string npath =
+ test_patterns(vars, path);
+ if (!npath.empty())
+ {
+ yaz_log(YLOG_LOG, "Rewritten request URL is %s", npath.c_str());
+ hreq->path = odr_strdup(o, npath.c_str());
+ }
+}
+
+void yf::HttpRewrite::Rules::rewrite_headers(mp::odr & o,
+ Z_HTTP_Header *headers,
+ std::map<std::string, std::string> & vars) const
+{
+ for (Z_HTTP_Header *header = headers;
+ header != 0;
+ header = header->next)
+ {
+ std::string sheader(header->name);
+ sheader += ": ";
+ sheader += header->value;
+ yaz_log(YLOG_LOG, "%s: %s", header->name, header->value);
+ std::string out = test_patterns(vars, sheader);
+ if (!out.empty())
+ {
+ size_t pos = out.find(": ");
+ if (pos == std::string::npos)
+ {
+ yaz_log(YLOG_LOG, "Header malformed during rewrite, ignoring");
+ continue;
+ }
+ header->name = odr_strdup(o, out.substr(0, pos).c_str());
+ header->value = odr_strdup(o, out.substr(pos+2,
+ std::string::npos).c_str());
+ }
+ }
+}
+
+void yf::HttpRewrite::Rules::rewrite_body (mp::odr & o,
+ char **content_buf,
+ int *content_len,
+ std::map<std::string, std::string> & vars) const
+{
+ if (*content_buf)
+ {
+ std::string body(*content_buf);
+ std::string nbody =
+ test_patterns(vars, body);
+ if (!nbody.empty())
+ {
+ *content_buf = odr_strdup(o, nbody.c_str());
+ *content_len = nbody.size();
+ }
+ }
+}
+
+/**
+ * Tests pattern from the vector in order and executes recipe on
+ the first match.
+ */
+const std::string yf::HttpRewrite::Rules::test_patterns(
+ std::map<std::string, std::string> & vars,
+ const std::string & txt) const
+{
+ for (size_t i = 0; i < rules.size(); i++)
+ {
+ std::string out = rules[i].search_replace(vars, txt);
+ if (!out.empty()) return out;
+ }
+ return "";
+}
+
+const std::string yf::HttpRewrite::Rule::search_replace(
+ std::map<std::string, std::string> & vars,
+ const std::string & txt) const
+{
+ //exec regex against value
+ boost::regex re(regex);
+ boost::smatch what;
+ std::string::const_iterator start, end;
+ start = txt.begin();
+ end = txt.end();
+ std::string out;
+ while (regex_search(start, end, what, re)) //find next full match
+ {
+ size_t i;
+ for (i = 1; i < what.size(); ++i)
+ {
+ //check if the group is named
+ std::map<int, std::string>::const_iterator it
+ = group_index.find(i);
+ if (it != group_index.end())
+ { //it is
+ if (!what[i].str().empty())
+ vars[it->second] = what[i];
+ }
+
+ }
+ //prepare replacement string
+ std::string rvalue = sub_vars(vars);
+ yaz_log(YLOG_LOG, "! Rewritten '%s' to '%s'",
+ what.str(0).c_str(), rvalue.c_str());
+ out.append(start, what[0].first);
+ out.append(rvalue);
+ start = what[0].second; //move search forward
+ }
+ //if we had a match cat the last part
+ if (start != txt.begin())
+ out.append(start, end);
+ return out;
+}
+
+void yf::HttpRewrite::Rule::parse_groups()
+{
+ int gnum = 0;
+ bool esc = false;
+ const std::string & str = regex;
+ std::string res;
+ yaz_log(YLOG_LOG, "Parsing groups from '%s'", str.c_str());
+ for (size_t i = 0; i < str.size(); ++i)
+ {
+ res += str[i];
+ if (!esc && str[i] == '\\')
+ {
+ esc = true;
+ continue;
+ }
+ if (!esc && str[i] == '(') //group starts
+ {
+ gnum++;
+ if (i+1 < str.size() && str[i+1] == '?') //group with attrs
+ {
+ i++;
+ if (i+1 < str.size() && str[i+1] == ':') //non-capturing
+ {
+ if (gnum > 0) gnum--;
+ res += str[i];
+ i++;
+ res += str[i];
+ continue;
+ }
+ if (i+1 < str.size() && str[i+1] == 'P') //optional, python
+ i++;
+ if (i+1 < str.size() && str[i+1] == '<') //named
+ {
+ i++;
+ std::string gname;
+ bool term = false;
+ while (++i < str.size())
+ {
+ if (str[i] == '>') { term = true; break; }
+ if (!isalnum(str[i]))
+ throw mp::filter::FilterException
+ ("Only alphanumeric chars allowed, found "
+ " in '"
+ + str
+ + "' at "
+ + boost::lexical_cast<std::string>(i));
+ gname += str[i];
+ }
+ if (!term)
+ throw mp::filter::FilterException
+ ("Unterminated group name '" + gname
+ + " in '" + str +"'");
+ group_index[gnum] = gname;
+ yaz_log(YLOG_LOG, "Found named group '%s' at $%d",
+ gname.c_str(), gnum);
+ }
+ }
+ }
+ esc = false;
+ }
+ regex = res;
+}
+
+std::string yf::HttpRewrite::Rule::sub_vars (
+ const std::map<std::string, std::string> & vars) const
+{
+ std::string out;
+ bool esc = false;
+ const std::string & in = recipe;
+ for (size_t i = 0; i < in.size(); ++i)
+ {
+ if (!esc && in[i] == '\\')
+ {
+ esc = true;
+ continue;
+ }
+ if (!esc && in[i] == '$') //var
+ {
+ if (i+1 < in.size() && in[i+1] == '{') //ref prefix
+ {
+ ++i;
+ std::string name;
+ bool term = false;
+ while (++i < in.size())
+ {
+ if (in[i] == '}') { term = true; break; }
+ name += in[i];
+ }
+ if (!term) throw mp::filter::FilterException
+ ("Unterminated var ref in '"+in+"' at "
+ + boost::lexical_cast<std::string>(i));
+ std::map<std::string, std::string>::const_iterator it
+ = vars.find(name);
+ if (it != vars.end())
+ {
+ out += it->second;
+ }
+ }
+ else
+ {
+ throw mp::filter::FilterException
+ ("Malformed or trimmed var ref in '"
+ +in+"' at "+boost::lexical_cast<std::string>(i));
+ }
+ continue;
+ }
+ //passthru
+ out += in[i];
+ esc = false;
+ }
+ return out;
+}
+
+void yf::HttpRewrite::configure_rules(const xmlNode *ptr,
+ Rules & rules)
+{
+ for (ptr = ptr->children; ptr; ptr = ptr->next)
+ {
+ if (ptr->type != XML_ELEMENT_NODE)
+ continue;
+ else if (!strcmp((const char *) ptr->name, "rewrite"))
+ {
+ Rule rule;
+ const struct _xmlAttr *attr;
+ for (attr = ptr->properties; attr; attr = attr->next)
+ {
+ if (!strcmp((const char *) attr->name, "from"))
+ rule.regex = mp::xml::get_text(attr->children);
+ else if (!strcmp((const char *) attr->name, "to"))
+ rule.recipe = mp::xml::get_text(attr->children);
+ else
+ throw mp::filter::FilterException
+ ("Bad attribute "
+ + std::string((const char *) attr->name)
+ + " in rewrite section of http_rewrite");
+ }
+ yaz_log(YLOG_LOG, "Found rewrite rule from '%s' to '%s'",
+ rule.regex.c_str(), rule.recipe.c_str());
+ rule.parse_groups();
+ if (!rule.regex.empty())
+ rules.rules.push_back(rule);
+ }
+ else
+ {
+ throw mp::filter::FilterException
+ ("Bad element o"
+ + std::string((const char *) ptr->name)
+ + " in http_rewrite1 filter");
+ }
+ }
+}
+
+void yf::HttpRewrite::configure(const xmlNode * ptr, bool test_only,
+ const char *path)
+{
+ for (ptr = ptr->children; ptr; ptr = ptr->next)
+ {
+ if (ptr->type != XML_ELEMENT_NODE)
+ continue;
+ else if (!strcmp((const char *) ptr->name, "request"))
+ {
+ configure_rules(ptr, *req_rules);
+ }
+ else if (!strcmp((const char *) ptr->name, "response"))
+ {
+ configure_rules(ptr, *res_rules);
+ }
+ else
+ {
+ throw mp::filter::FilterException
+ ("Bad element "
+ + std::string((const char *) ptr->name)
+ + " in http_rewrite1 filter");
+ }
+ }
+}
+
+static mp::filter::Base* filter_creator()
+{
+ return new mp::filter::HttpRewrite;
+}
+
+extern "C" {
+ struct metaproxy_1_filter_struct metaproxy_1_filter_http_rewrite = {
+ 0,
+ "http_rewrite",
+ filter_creator
+ };
+}
+
+
+/*
+ * Local variables:
+ * c-basic-offset: 4
+ * c-file-style: "Stroustrup"
+ * indent-tabs-mode: nil
+ * End:
+ * vim: shiftwidth=4 tabstop=8 expandtab
+ */
+
--- /dev/null
+/* This file is part of Metaproxy.
+ Copyright (C) 2005-2013 Index Data
+
+Metaproxy is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 2, or (at your option) any later
+version.
+
+Metaproxy is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+#ifndef FILTER_HTTP_REWRITE_HPP
+#define FILTER_HTTP_REWRITE_HPP
+
+#include <metaproxy/filter.hpp>
+#include <boost/scoped_ptr.hpp>
+
+namespace mp = metaproxy_1;
+
+namespace metaproxy_1 {
+ namespace filter {
+ class HttpRewrite : public Base {
+ class Rules;
+ class Rule;
+ class RuleScope;
+ boost::scoped_ptr<Rules> req_rules;
+ boost::scoped_ptr<Rules> res_rules;
+ void configure_rules(const xmlNode *ptr, Rules & rules);
+ public:
+ HttpRewrite();
+ ~HttpRewrite();
+ void process(metaproxy_1::Package & package) const;
+ void configure(const xmlNode * ptr,
+ bool test_only, const char *path);
+ };
+ }
+}
+
+extern "C" {
+ extern struct metaproxy_1_filter_struct metaproxy_1_filter_http_rewrite;
+}
+
+#endif
+/*
+ * Local variables:
+ * c-basic-offset: 4
+ * c-file-style: "Stroustrup"
+ * indent-tabs-mode: nil
+ * End:
+ * vim: shiftwidth=4 tabstop=8 expandtab
+ */
+
Odr_int start_pos,
ResultSetPtr s,
Odr_oid *syntax,
+ Z_RecordComposition *comp,
const char *resultSetId);
public:
Frontend(Impl *impl);
Odr_int start_pos,
ResultSetPtr s,
Odr_oid *syntax,
+ Z_RecordComposition *comp,
const char *resultSetId)
{
if (records && records->which == Z_Records_DBOSD && start_pos == 1)
*p_req->numberOfRecordsRequested = end_pos - pos + 1;
p_req->preferredRecordSyntax = syntax;
p_req->resultSetId = odr_strdup(odr, resultSetId);
+ p_req->recordComposition = comp;
present_package.request() = p_apdu;
present_package.move();
Z_APDU_searchResponse)
{
Z_SearchResponse *res = gdu_res->u.z3950->u.searchResponse;
+ Z_RecordComposition *record_comp =
+ mp::util::piggyback_to_RecordComposition(odr,
+ *res->resultCount, req);
s->hit_count = *res->resultCount;
handle_records(b_package, apdu_req, res->records, 1, s,
- syntax, resultSetId.c_str());
+ syntax, record_comp, resultSetId.c_str());
package.response() = gdu_res;
}
}
{
Z_PresentResponse *res = gdu_res->u.z3950->u.presentResponse;
handle_records(b_package, apdu_req, res->records,
- start, rset, syntax, resultSetId.c_str());
+ start, rset, syntax, req->recordComposition,
+ resultSetId.c_str());
package.response() = gdu_res;
}
}
mp::odr &odr_en,
Z_SRW_PDU *sru_pdu_res,
Z_SRW_searchRetrieveRequest const *sr_req,
- std::string zurl
+ std::string zurl,
+ std::string db_append
) const;
bool z3950_present_request(
bool enable_package_log = false;
std::string zurl;
+ std::string dbargs;
Z_SRW_extra_arg *arg;
for ( arg = sru_pdu_req->extra_args; arg; arg = arg->next)
package.log_enable();
}
}
+ else if (!strncmp(arg->name, "x-client-", 9) && arg->value)
+ {
+ if (dbargs.length())
+ dbargs += '&';
+ dbargs += mp_util::uri_encode(arg->name + 9);
+ dbargs += '=';
+ dbargs += mp_util::uri_encode(arg->value);
+ }
+
assert(sru_pdu_req);
// filter acts as sink for SRU explain requests
zurl, sru_pdu_res, sru_pdu_req))
{
ok = z3950_search_request(package, odr_en,
- sru_pdu_res, sr_req, zurl);
+ sru_pdu_res, sr_req, zurl, dbargs);
if (ok
&& sru_pdu_res->u.response->numberOfRecords
Z_SRW_PDU *sru_pdu_res,
Z_SRW_searchRetrieveRequest
const *sr_req,
- std::string zurl) const
+ std::string zurl,
+ std::string dbappend) const
{
assert(sru_pdu_res->u.response);
&z_searchRequest->num_databaseNames,
&z_searchRequest->databaseNames))
{
- z_searchRequest->num_databaseNames = 1;
- z_searchRequest->databaseNames = (char**)
- odr_malloc(odr_en, sizeof(char *));
+ std::string db;
if (sr_req->database)
- z_searchRequest->databaseNames[0]
- = odr_strdup(odr_en, const_cast<char *>(sr_req->database));
+ db = sr_req->database;
else
- z_searchRequest->databaseNames[0]
- = odr_strdup(odr_en, "Default");
+ db = "Default";
+
+ if (dbappend.length())
+ {
+ db += ",";
+ db += dbappend;
+ }
+ z_searchRequest->num_databaseNames = 1;
+ z_searchRequest->databaseNames = (char**)
+ odr_malloc(odr_en, sizeof(char *));
+ z_searchRequest->databaseNames[0] = odr_strdup(odr_en, db.c_str());
}
Z_Query *z_query = (Z_Query *) odr_malloc(odr_en, sizeof(Z_Query));
}
extern "C" {
- struct metaproxy_1_filter_struct metaproxy_1_filter_sru_to_z3950 = {
+ struct metaproxy_1_filter_struct metaproxy_1_filter_sru_z3950 = {
0,
"sru_z3950",
filter_creator
}
extern "C" {
- extern struct metaproxy_1_filter_struct metaproxy_1_filter_sru_to_z3950;
+ extern struct metaproxy_1_filter_struct metaproxy_1_filter_sru_z3950;
}
#endif
--- /dev/null
+/* This file is part of Metaproxy.
+ Copyright (C) 2005-2013 Index Data
+
+Metaproxy is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 2, or (at your option) any later
+version.
+
+Metaproxy is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+#include "config.hpp"
+#include "html_parser.hpp"
+
+#include <assert.h>
+#include <string.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <stdio.h>
+
+#define TAG_MAX_LEN 64
+
+#define SPACECHR " \t\r\n\f"
+
+#define DEBUG(x) x
+
+#if HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+
+namespace mp = metaproxy_1;
+
+mp::HTMLParser::HTMLParser()
+{
+}
+
+mp::HTMLParser::~HTMLParser()
+{
+}
+
+static void parse_str(mp::HTMLParserEvent & event, const char * str);
+
+void mp::HTMLParser::parse(mp::HTMLParserEvent & event, const char *str) const
+{
+ parse_str(event, str);
+}
+
+//static C functions follow would probably make sense to wrap this in PIMPL?
+
+static char* dupe (const char *buff, int len)
+{
+ char *value = (char *) malloc (len + 1);
+ assert (value);
+ memcpy (value, buff, len);
+ value[len] = '\0';
+ return value;
+}
+
+static int skipSpace (const char *cp)
+{
+ int i = 0;
+ while (cp[i] && strchr (SPACECHR, cp[i]))
+ i++;
+ return i;
+}
+
+static int skipName (const char *cp, char *dst)
+{
+ int i;
+ int j = 0;
+ for (i=0; cp[i] && !strchr (SPACECHR "/>=", cp[i]); i++)
+ if (j < TAG_MAX_LEN-1)
+ {
+ dst[j] = tolower(cp[j]);
+ j++;
+ }
+ dst[j] = '\0';
+ return i;
+}
+
+static int skipAttribute (const char *cp, char *name, const char **value, int *val_len)
+{
+ int i = skipName (cp, name);
+ *value = NULL;
+ if (!i)
+ return skipSpace (cp);
+ i += skipSpace (cp + i);
+ if (cp[i] == '=')
+ {
+ int v0, v1;
+ i++;
+ i += skipSpace (cp + i);
+ if (cp[i] == '\"' || cp[i] == '\'')
+ {
+ char tr = cp[i];
+ v0 = ++i;
+ while (cp[i] != tr && cp[i])
+ i++;
+ v1 = i;
+ if (cp[i])
+ i++;
+ }
+ else
+ {
+ v0 = i;
+ while (cp[i] && !strchr (SPACECHR ">", cp[i]))
+ i++;
+ v1 = i;
+ }
+ *value = cp + v0;
+ *val_len = v1 - v0;
+ }
+ i += skipSpace (cp + i);
+ return i;
+}
+
+static int tagAttrs (mp::HTMLParserEvent & event,
+ const char *tagName,
+ const char *cp)
+{
+ int i;
+ char attr_name[TAG_MAX_LEN];
+ const char *attr_value;
+ int val_len;
+ i = skipSpace (cp);
+ while (cp[i] && cp[i] != '>')
+ {
+ int nor = skipAttribute (cp+i, attr_name, &attr_value, &val_len);
+ i += nor;
+ if (nor)
+ {
+ DEBUG(printf ("------ attr %s=%s\n", attr_name, dupe(attr_value, val_len)));
+ event.attribute(tagName, attr_name, attr_value, val_len);
+ }
+ else
+ {
+ if (!nor)
+ i++;
+ }
+ }
+ return i;
+}
+
+static int tagStart (mp::HTMLParserEvent & event,
+ char *tagName, const char *cp, const char which)
+{
+ int i = 0;
+ i = skipName (cp, tagName);
+ switch (which)
+ {
+ case '/' :
+ DEBUG(printf ("------ tag close %s\n", tagName));
+ event.closeTag(tagName);
+ break;
+ case '!' :
+ DEBUG(printf ("------ dtd %s\n", tagName));
+ break;
+ case '?' :
+ DEBUG(printf ("------ pi %s\n", tagName));
+ break;
+ default :
+ DEBUG(printf ("------ tag open %s\n", tagName));
+ event.openTagStart(tagName);
+ break;
+ }
+ return i;
+}
+
+static int tagEnd (mp::HTMLParserEvent & event, const char *tagName, const char *cp)
+{
+ int i = 0;
+ while (cp[i] && cp[i] != '>')
+ i++;
+ if (cp[i] == '>')
+ {
+ event.anyTagEnd(tagName);
+ i++;
+ }
+ return i;
+}
+
+static void tagText (mp::HTMLParserEvent & event, const char *text_start, const char *text_end)
+{
+ if (text_end - text_start) //got text to flush
+ {
+ DEBUG(printf ("------ text %s\n", dupe(text_start, text_end-text_start)));
+ event.text(text_start, text_end-text_start);
+ }
+}
+
+static void parse_str (mp::HTMLParserEvent & event, const char *cp)
+{
+ const char *text_start = cp;
+ const char *text_end = cp;
+ while (*cp)
+ {
+ if (cp[0] == '<' && cp[1]) //tag?
+ {
+ char which = cp[1];
+ if (which == '/') cp++;
+ if (!strchr (SPACECHR, cp[1])) //valid tag starts
+ {
+ tagText (event, text_start, text_end); //flush any text
+ char tagName[TAG_MAX_LEN];
+ cp++;
+ if (which == '/')
+ {
+ cp += tagStart (event, tagName, cp, which);
+ }
+ else if (which == '!' || which == '?') //pi or dtd
+ {
+ cp++;
+ cp += tagStart (event, tagName, cp, which);
+ }
+ else
+ {
+ cp += tagStart (event, tagName, cp, which);
+ cp += tagAttrs (event, tagName, cp);
+ }
+ cp += tagEnd (event, tagName, cp);
+ text_start = cp;
+ text_end = cp;
+ continue;
+ }
+ }
+ //text
+ cp++;
+ text_end = cp;
+ }
+ tagText (event, text_start, text_end); //flush any text
+}
+
+/*
+ * Local variables:
+ * c-basic-offset: 4
+ * c-file-style: "Stroustrup"
+ * indent-tabs-mode: nil
+ * End:
+ * vim: shiftwidth=4 tabstop=8 expandtab
+ */
+
--- /dev/null
+/* This file is part of Metaproxy.
+ Copyright (C) 2005-2013 Index Data
+
+Metaproxy is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 2, or (at your option) any later
+version.
+
+Metaproxy is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+#ifndef HTML_PARSER_HPP
+#define HTML_PARSER_HPP
+
+#include <boost/scoped_ptr.hpp>
+
+namespace metaproxy_1 {
+ class HTMLParserEvent {
+ public:
+ virtual void openTagStart(const char *name) = 0;
+ virtual void anyTagEnd(const char *name) = 0;
+ virtual void attribute(const char *tagName,
+ const char *name,
+ const char *value,
+ int val_len) = 0;
+ virtual void closeTag(const char *name) = 0;
+ virtual void text(const char *value, int len) = 0;
+ };
+ class HTMLParser {
+ public:
+ HTMLParser();
+ ~HTMLParser();
+ void parse(HTMLParserEvent & event, const char *str) const;
+ };
+}
+
+#endif
+/*
+ * Local variables:
+ * c-basic-offset: 4
+ * c-file-style: "Stroustrup"
+ * indent-tabs-mode: nil
+ * End:
+ * vim: shiftwidth=4 tabstop=8 expandtab
+ */
+
#include <metaproxy/filter.hpp>
#include <metaproxy/package.hpp>
#include <metaproxy/util.hpp>
-#include "router_flexml.hpp"
-#include "factory_static.hpp"
+#include <metaproxy/router_xml.hpp>
#if HAVE_UNISTD_H
#include <unistd.h>
namespace mp = metaproxy_1;
-mp::RouterFleXML *routerp = 0;
+mp::RouterXML *routerp = 0;
static void set_log_prefix(void)
{
signal(SIGTERM, sig_term_handler);
signal(SIGUSR1, sig_usr1_handler);
#endif
- routerp = (mp::RouterFleXML*) data;
+ routerp = (mp::RouterXML*) data;
routerp->start();
mp::Package pack;
wrbuf_puts(base_path, ".");
ret = 0;
try {
- mp::FactoryStatic factory;
- mp::RouterFleXML *router =
- new mp::RouterFleXML(doc, factory, test_config, wrbuf_cstr(base_path));
+ mp::RouterXML *router =
+ new mp::RouterXML(doc, test_config, wrbuf_cstr(base_path));
if (!test_config)
{
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
-#include "router_chain.hpp"
+#include <metaproxy/router_chain.hpp>
#include <metaproxy/filter.hpp>
#include <list>
+++ /dev/null
-/* This file is part of Metaproxy.
- Copyright (C) 2005-2013 Index Data
-
-Metaproxy is free software; you can redistribute it and/or modify it under
-the terms of the GNU General Public License as published by the Free
-Software Foundation; either version 2, or (at your option) any later
-version.
-
-Metaproxy is distributed in the hope that it will be useful, but WITHOUT ANY
-WARRANTY; without even the implied warranty of MERCHANTABILITY or
-FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
-for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-*/
-
-#ifndef ROUTER_CHAIN_HPP
-#define ROUTER_CHAIN_HPP
-
-
-#include <metaproxy/router.hpp>
-
-#include <boost/scoped_ptr.hpp>
-#include <stdexcept>
-
-namespace metaproxy_1 {
- class RouterChain : public Router {
- class Rep;
- class Pos;
- public:
- RouterChain();
- virtual ~RouterChain();
- virtual RoutePos *createpos() const;
- RouterChain & append(const filter::Base &filter);
- void start();
- void stop();
- private:
- boost::scoped_ptr<Rep> m_p;
- /// disabled because class is singleton
- RouterChain(const RouterChain &);
-
- /// disabled because class is singleton
- RouterChain& operator=(const RouterChain &);
- };
-}
-
-#endif
-/*
- * Local variables:
- * c-basic-offset: 4
- * c-file-style: "Stroustrup"
- * indent-tabs-mode: nil
- * End:
- * vim: shiftwidth=4 tabstop=8 expandtab
- */
-
--- /dev/null
+/* This file is part of Metaproxy.
+ Copyright (C) 2005-2013 Index Data
+
+Metaproxy is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 2, or (at your option) any later
+version.
+
+Metaproxy is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+#include "config.hpp"
+#include <metaproxy/router_xml.hpp>
+#include "router_flexml.hpp"
+#include "factory_static.hpp"
+
+namespace mp = metaproxy_1;
+
+namespace metaproxy_1 {
+ class RouterXML::Rep {
+ public:
+ Rep(xmlDocPtr, bool, const char *);
+ Rep(std::string, bool);
+ ~Rep();
+ FactoryStatic m_factory;
+ boost::scoped_ptr<Router> m_flexml;
+ };
+}
+
+mp::RouterXML::Rep::Rep(xmlDocPtr doc, bool test_only,
+ const char *include_path)
+ : m_factory(),
+ m_flexml(new RouterFleXML(doc, m_factory, test_only, include_path))
+{
+}
+
+mp::RouterXML::Rep::Rep(std::string xmlconf, bool test_only)
+ : m_factory(),
+ m_flexml(new RouterFleXML(xmlconf, m_factory, test_only))
+{
+}
+
+mp::RouterXML::Rep::~Rep()
+{
+}
+
+mp::RouterXML::RouterXML(xmlDocPtr doc,
+ bool test_only, const char *file_include_path)
+ : m_p(new Rep(doc, test_only, file_include_path))
+{
+}
+
+mp::RouterXML::RouterXML(std::string xmlconf, bool test_only)
+ : m_p(new Rep(xmlconf, test_only))
+{
+}
+
+mp::RouterXML::~RouterXML()
+{
+}
+
+mp::RoutePos *mp::RouterXML::createpos() const
+{
+ return m_p->m_flexml->createpos();
+}
+
+void mp::RouterXML::start()
+{
+ m_p->m_flexml->start();
+}
+
+void mp::RouterXML::stop()
+{
+ m_p->m_flexml->stop();
+}
+
+/*
+ * Local variables:
+ * c-basic-offset: 4
+ * c-file-style: "Stroustrup"
+ * indent-tabs-mode: nil
+ * End:
+ * vim: shiftwidth=4 tabstop=8 expandtab
+ */
+
#include <libxml/tree.h>
#include <metaproxy/filter.hpp>
-#include "router_chain.hpp"
+#include <metaproxy/router_chain.hpp>
#include <metaproxy/package.hpp>
#include <iostream>
#include "filter_auth_simple.hpp"
#include <metaproxy/util.hpp>
-#include "router_chain.hpp"
+#include <metaproxy/router_chain.hpp>
#include <metaproxy/package.hpp>
#define BOOST_AUTO_TEST_MAIN
#include "filter_backend_test.hpp"
#include "filter_log.hpp"
-#include "router_chain.hpp"
+#include <metaproxy/router_chain.hpp>
#include <metaproxy/package.hpp>
#include <yaz/zgdu.h>
#include "filter_bounce.hpp"
#include <metaproxy/util.hpp>
#include "gduutil.hpp"
-#include "router_chain.hpp"
+#include <metaproxy/router_chain.hpp>
#include <metaproxy/package.hpp>
#include <iostream>
#include <metaproxy/util.hpp>
#include "filter_frontend_net.hpp"
-#include "router_chain.hpp"
+#include <metaproxy/router_chain.hpp>
#include <metaproxy/package.hpp>
#define BOOST_AUTO_TEST_MAIN
#include "filter_log.hpp"
#include <metaproxy/util.hpp>
-#include "router_chain.hpp"
+#include <metaproxy/router_chain.hpp>
#include <metaproxy/package.hpp>
#define BOOST_AUTO_TEST_MAIN
#include "filter_multi.hpp"
#include <metaproxy/util.hpp>
-#include "router_chain.hpp"
+#include <metaproxy/router_chain.hpp>
#include <metaproxy/package.hpp>
#define BOOST_AUTO_TEST_MAIN
#include "filter_query_rewrite.hpp"
#include <metaproxy/util.hpp>
-#include "router_chain.hpp"
+#include <metaproxy/router_chain.hpp>
#include <metaproxy/package.hpp>
#define BOOST_AUTO_TEST_MAIN
#include "config.hpp"
#include "filter_record_transform.hpp"
-#include "router_chain.hpp"
+#include <metaproxy/router_chain.hpp>
#include <metaproxy/package.hpp>
#define BOOST_AUTO_TEST_MAIN
--- /dev/null
+/* This file is part of Metaproxy.
+ Copyright (C) 2005-2013 Index Data
+
+Metaproxy is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 2, or (at your option) any later
+version.
+
+Metaproxy is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+#include "config.hpp"
+#include <iostream>
+#include <stdexcept>
+
+#include "filter_http_client.hpp"
+#include "filter_http_rewrite.hpp"
+#include <metaproxy/util.hpp>
+#include <metaproxy/router_chain.hpp>
+#include <metaproxy/package.hpp>
+
+#include <boost/regex.hpp>
+#include <boost/lexical_cast.hpp>
+
+#include <yaz/log.h>
+
+#define BOOST_AUTO_TEST_MAIN
+#define BOOST_TEST_DYN_LINK
+
+#include <boost/test/auto_unit_test.hpp>
+
+using namespace boost::unit_test;
+namespace mp = metaproxy_1;
+/*
+ * The global testconfig is commented out, as it won't even compile
+ * on old Centos5 machines
+struct TestConfig {
+ TestConfig()
+ {
+ std::cout << "global setup\n";
+ yaz_log_init_level(YLOG_ALL);
+ }
+ ~TestConfig()
+ {
+ std::cout << "global teardown\n";
+ }
+};
+
+BOOST_GLOBAL_FIXTURE( TestConfig );
+*/
+
+BOOST_AUTO_TEST_CASE( test_filter_rewrite_1 )
+{
+ try
+ {
+ std::cout << "Running non-xml config test case" << std::endl;
+ mp::RouterChain router;
+ mp::filter::HttpRewrite fhr;
+
+ std::string xmlconf =
+ "<?xml version='1.0'?>\n"
+ "<filter xmlns='http://indexdata.com/metaproxy'\n"
+ " id='rewrite1' type='http_rewrite'>\n"
+ " <request>\n"
+ " <rewrite from='"
+ "(?<proto>https?://)(?<pxhost>[^ /?#]+)/(?<pxpath>[^ /]+)"
+ "/(?<host>[^ /]+)(?<path>[^ ]*)'\n"
+ " to='${proto}${host}${path}' />\n"
+ " <rewrite from='(?:Host: )(.*)'\n"
+ " to='Host: ${host}' />\n"
+ " </request>\n"
+ " <response>\n"
+ " <rewrite from='"
+ "(?<proto>https?://)(?<host>[^/?# "'>]+)/(?<path>[^ "'>]+)'\n"
+ " to='${proto}${pxhost}/${pxpath}/${host}/${path}' />\n"
+ " </response>\n"
+ "</filter>\n"
+ ;
+
+ std::cout << xmlconf;
+
+ // reading and parsing XML conf
+ xmlDocPtr doc = xmlParseMemory(xmlconf.c_str(), xmlconf.size());
+ BOOST_CHECK(doc);
+ xmlNode *root_element = xmlDocGetRootElement(doc);
+ fhr.configure(root_element, true, "");
+ xmlFreeDoc(doc);
+
+ router.append(fhr);
+
+ // create an http request
+ mp::Package pack;
+
+ mp::odr odr;
+ Z_GDU *gdu_req = z_get_HTTP_Request_uri(odr,
+ "http://proxyhost/proxypath/targetsite/page1.html", 0, 1);
+
+ pack.request() = gdu_req;
+
+ //create the http response
+
+ const char *resp_buf =
+ "HTTP/1.1 200 OK\r\n"
+ "Content-Length: 441\r\n"
+ "Content-Type: text/html\r\n"
+ "Link: <http://targetsite/file.xml>; rel=absolute\r\n"
+ "Link: </dir/file.xml>; rel=relative\r\n"
+ "\r\n"
+ "<html><head><title>Hello proxy!</title>"
+ "<style>"
+ "body {"
+ " background-image:url('http://targetsite/images/bg.png');"
+ "}"
+ "</style>"
+ "</head>"
+ "<script>var jslink=\"http://targetsite/webservice.xml\";</script>"
+ "<body>"
+ "<p>Welcome to our website. It doesn't make it easy to get pro"
+ "xified"
+ "<a href=\"http://targetsite/page2.html\">"
+ " An absolute link</a>"
+ "<a target=_blank href='http://targetsite/page3.html\">"
+ " Another abs link</a>"
+ "<a href=\"/docs/page4.html\" />"
+ "</body></html>";
+
+ const char *resp_expected =
+ "HTTP/1.1 200 OK\r\n"
+ "Content-Length: 521\r\n"
+ "Content-Type: text/html\r\n"
+ "Link: <http://proxyhost/proxypath/targetsite/file.xml>; rel=absolute\r\n"
+ "Link: </dir/file.xml>; rel=relative\r\n"
+ "\r\n"
+ "<html><head><title>Hello proxy!</title>"
+ "<style>"
+ "body {"
+ " background-image:url('http://proxyhost/proxypath/targetsite/images/bg.png');"
+ "}"
+ "</style>"
+ "</head>"
+ "<script>var jslink=\"http://proxyhost/proxypath/targetsite/webservice.xml\";</script>"
+ "<body>"
+ "<p>Welcome to our website. It doesn't make it easy to get pro"
+ "xified"
+ "<a href=\"http://proxyhost/proxypath/targetsite/page2.html\">"
+ " An absolute link</a>"
+ "<a target=_blank href='http://proxyhost/proxypath/targetsite/page3.html\">"
+ " Another abs link</a>"
+ "<a href=\"/docs/page4.html\" />"
+ "</body></html>";
+
+ int r;
+ Z_GDU *gdu_res;
+ ODR dec = odr_createmem(ODR_DECODE);
+ odr_setbuf(dec, (char *) resp_buf, strlen(resp_buf), 0);
+ r = z_GDU(dec, &gdu_res, 0, 0);
+
+ BOOST_CHECK(r);
+ if (r)
+ {
+ BOOST_CHECK_EQUAL(gdu_res->which, Z_GDU_HTTP_Response);
+ }
+
+ pack.response() = gdu_res;
+
+ //feed to the router
+ pack.router(router).move();
+
+ //analyze the response
+ Z_GDU *gdu_res_rew = pack.response().get();
+ BOOST_CHECK(gdu_res_rew);
+ BOOST_CHECK_EQUAL(gdu_res_rew->which, Z_GDU_HTTP_Response);
+
+ Z_HTTP_Response *hres = gdu_res_rew->u.HTTP_Response;
+ BOOST_CHECK(hres);
+
+ //compare buffers
+ std::cout << "Expected result:\n" << resp_expected << std::endl;
+
+ ODR enc = odr_createmem(ODR_ENCODE);
+ z_GDU(enc, &gdu_res_rew, 0, 0);
+ char *resp_result;
+ int resp_result_len;
+ resp_result = odr_getbuf(enc, &resp_result_len, 0);
+
+ BOOST_CHECK(resp_result);
+ BOOST_CHECK_EQUAL((size_t) resp_result_len, strlen(resp_expected));
+
+ std::cout << "Rewriten result:\n" << resp_result << std::endl;
+ std::cout << "Rewriten result buf len: " << resp_result_len
+ << std::endl;
+
+ BOOST_CHECK(memcmp(resp_result, resp_expected, resp_result_len) == 0);
+
+ odr_destroy(dec);
+ odr_destroy(enc);
+ }
+ catch (std::exception & e) {
+ std::cout << e.what();
+ std::cout << std::endl;
+ BOOST_CHECK (false);
+ }
+}
+
+/*
+BOOST_AUTO_TEST_CASE( test_filter_rewrite_2 )
+{
+ try
+ {
+ std::cout << "Running xml config test case" << std::endl;
+ mp::RouterChain router;
+ mp::filter::HttpRewrite fhr;
+
+ std::string xmlconf =
+ "<?xml version='1.0'?>\n"
+ "<filter xmlns='http://indexdata.com/metaproxy'\n"
+ " id='rewrite1' type='http_rewrite'>\n"
+ " <request>\n"
+ " <rewrite from='"
+ "(?<proto>https?://)(?<pxhost>[^ /?#]+)/(?<pxpath>[^ /]+)"
+ "/(?<host>[^ /]+)(?<path>[^ ]*)'\n"
+ " to='${proto}${host}${path}' />\n"
+ " <rewrite from='(?:Host: )(.*)'\n"
+ " to='Host: ${host}' />\n"
+ " </request>\n"
+ " <response>\n"
+ " <rewrite from='"
+ "(?<proto>https?://)(?<host>[^/?# "'>]+)/(?<path>[^ "'>]+)'\n"
+ " to='${proto}${pxhost}/${pxpath}/${host}/${path}' />\n"
+ " </response>\n"
+ "</filter>\n"
+ ;
+
+ std::cout << xmlconf;
+
+ // reading and parsing XML conf
+ xmlDocPtr doc = xmlParseMemory(xmlconf.c_str(), xmlconf.size());
+ BOOST_CHECK(doc);
+ xmlNode *root_element = xmlDocGetRootElement(doc);
+ fhr.configure(root_element, true, "");
+ xmlFreeDoc(doc);
+
+ router.append(fhr);
+
+ // create an http request
+ mp::Package pack;
+
+ mp::odr odr;
+ Z_GDU *gdu_req = z_get_HTTP_Request_uri(odr,
+ "http://proxyhost/proxypath/targetsite/page1.html", 0, 1);
+
+ pack.request() = gdu_req;
+
+ //create the http response
+
+ const char *resp_buf =
+ "HTTP/1.1 200 OK\r\n"
+ "Content-Length: 50\r\n"
+ "Content-Type: text/html\r\n"
+ "Link: <http://targetsite/file.xml>; rel=absolute\r\n"
+ "Link: </dir/file.xml>; rel=relative\r\n"
+ "\r\n"
+ "<html><head><title>Hello proxy!</title>"
+ "<style>"
+ "body {"
+ " background-image:url('http://targetsite/images/bg.png');"
+ "}"
+ "</style>"
+ "</head>"
+ "<script>var jslink=\"http://targetsite/webservice.xml\";</script>"
+ "<body>"
+ "<p>Welcome to our website. It doesn't make it easy to get pro"
+ "xified"
+ "<a href=\"http://targetsite/page2.html\">"
+ " An absolute link</a>"
+ "<a target=_blank href='http://targetsite/page3.html\">"
+ " Another abs link</a>"
+ "<a href=\"/docs/page4.html\" />"
+ "</body></html>";
+
+ const char *resp_buf_rew =
+ "HTTP/1.1 200 OK\r\n"
+ "Content-Length: 50\r\n"
+ "Content-Type: text/html\r\n"
+ "Link: <http://proxyhost/proxypath/targetsite/file.xml>; rel=absolute\r\n"
+ "Link: </dir/file.xml>; rel=relative\r\n"
+ "\r\n"
+ "<html><head><title>Hello proxy!</title>"
+ "<style>"
+ "body {"
+ " background-image:url('http://proxyhost/proxypath/targetsite/images/bg.png');"
+ "}"
+ "</style>"
+ "</head>"
+ "<script>var jslink=\"http://proxyhost/proxypath/targetsite/webservice.xml\";</script>"
+ "<body>"
+ "<p>Welcome to our website. It doesn't make it easy to get pro"
+ "xified"
+ "<a href=\"http://proxyhost/proxypath/targetsite/page.html\">"
+ " An absolute link</a>"
+ "<a target=_blank href='http://proxyhost/proxypath/targetsite/anotherpage.html\">"
+ " Another abs link</a>"
+ "<a href=\"/docs/page2.html\" />"
+ "</body></html>";
+
+ int r;
+ Z_GDU *gdu_res;
+ ODR odr2 = odr_createmem(ODR_DECODE);
+ odr_setbuf(odr2, (char *) resp_buf, strlen(resp_buf), 0);
+ r = z_GDU(odr2, &gdu_res, 0, 0);
+
+ BOOST_CHECK(r == 0);
+ if (r)
+ {
+ BOOST_CHECK_EQUAL(gdu_res->which, Z_GDU_HTTP_Response);
+ }
+
+ pack.response() = gdu_res;
+
+ //feed to the router
+ pack.router(router).move();
+
+ //analyze the response
+ Z_GDU *gdu_res_rew = pack.response().get();
+ BOOST_CHECK(gdu_res_rew);
+ BOOST_CHECK_EQUAL(gdu_res_rew->which, Z_GDU_HTTP_Response);
+
+ Z_HTTP_Response *hres = gdu_res_rew->u.HTTP_Response;
+ BOOST_CHECK(hres);
+
+ //how to compare the buffers:
+
+ odr_destroy(odr2);
+ }
+ catch (std::exception & e) {
+ std::cout << e.what();
+ std::cout << std::endl;
+ BOOST_CHECK (false);
+ }
+}
+*/
+
+/*
+ * Local variables:
+ * c-basic-offset: 4
+ * c-file-style: "Stroustrup"
+ * indent-tabs-mode: nil
+ * End:
+ * vim: shiftwidth=4 tabstop=8 expandtab
+ */
+
#include "filter_sru_to_z3950.hpp"
#include <metaproxy/util.hpp>
#include "sru_util.hpp"
-#include "router_chain.hpp"
+#include <metaproxy/router_chain.hpp>
#include <metaproxy/package.hpp>
#include <iostream>
#include "filter_backend_test.hpp"
#include "filter_log.hpp"
-#include "router_chain.hpp"
+#include <metaproxy/router_chain.hpp>
#include <metaproxy/package.hpp>
#define BOOST_AUTO_TEST_MAIN
#include "filter_z3950_client.hpp"
#include <metaproxy/util.hpp>
-#include "router_chain.hpp"
+#include <metaproxy/router_chain.hpp>
#include <metaproxy/package.hpp>
#define BOOST_AUTO_TEST_MAIN
--- /dev/null
+/* This file is part of Metaproxy.
+ Copyright (C) 2005-2013 Index Data
+
+Metaproxy is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 2, or (at your option) any later
+version.
+
+Metaproxy is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+#include "config.hpp"
+#include <iostream>
+#include <stdexcept>
+
+#include "html_parser.hpp"
+#include <metaproxy/util.hpp>
+
+#include <boost/lexical_cast.hpp>
+
+#include <yaz/log.h>
+
+#define BOOST_AUTO_TEST_MAIN
+#define BOOST_TEST_DYN_LINK
+
+#include <boost/test/auto_unit_test.hpp>
+
+using namespace boost::unit_test;
+namespace mp = metaproxy_1;
+
+class MyEvent : public mp::HTMLParserEvent {
+ public:
+ std::string out;
+ void openTagStart(const char *name)
+ {
+ out += "<";
+ out += name;
+ }
+
+ void attribute(const char *tagName,
+ const char *name, const char *value, int val_len)
+ {
+ out += " ";
+ out += name;
+ out += "=\"";
+ out.append(value, val_len);
+ out += "\"";
+ }
+
+ void anyTagEnd(const char *name)
+ {
+ out += ">";
+ }
+
+ void closeTag(const char *name)
+ {
+ out += "</";
+ out += name;
+ }
+
+ void text(const char *value, int len)
+ {
+ out.append(value, len);
+ }
+};
+
+
+BOOST_AUTO_TEST_CASE( test_html_parser_1 )
+{
+ try
+ {
+ mp::HTMLParser hp;
+ const char* html =
+ "<html><body><a t1=v1 t2='v2' t3=\"v3\">some text</a>"
+ "<hr><table ></table ></body></html";
+ const char* expected =
+ "<html><body><a t1=\"v1\" t2=\"v2\" t3=\"v3\">some text</a>"
+ "<hr><table></table></body></html";
+ MyEvent e;
+ hp.parse(e, html);
+ BOOST_CHECK_EQUAL(std::string(expected), e.out);
+ }
+ catch (std::exception & e)
+ {
+ std::cout << e.what();
+ std::cout << std::endl;
+ BOOST_CHECK (false);
+ }
+}
+
+
+/*
+ * Local variables:
+ * c-basic-offset: 4
+ * c-file-style: "Stroustrup"
+ * indent-tabs-mode: nil
+ * End:
+ * vim: shiftwidth=4 tabstop=8 expandtab
+ */
+
}
+Z_RecordComposition *mp_util::piggyback_to_RecordComposition(
+ ODR odr, Odr_int result_set_size, Z_SearchRequest *sreq)
+{
+ Z_RecordComposition *comp = 0;
+ Odr_int present_dummy;
+ const char *element_set_name = 0;
+ mp::util::piggyback_sr(sreq, result_set_size,
+ present_dummy, &element_set_name);
+ if (element_set_name)
+ {
+ comp = (Z_RecordComposition *) odr_malloc(odr, sizeof(*comp));
+ comp->which = Z_RecordComp_simple;
+ comp->u.simple = (Z_ElementSetNames *)
+ odr_malloc(odr, sizeof(Z_ElementSetNames));
+ comp->u.simple->which = Z_ElementSetNames_generic;
+ comp->u.simple->u.generic = odr_strdup(odr, element_set_name);
+ }
+ return comp;
+}
+
void mp_util::piggyback_sr(Z_SearchRequest *sreq,
Odr_int result_set_size,
Odr_int &number_to_present,
DEBUG=0 # 0 for release, 1 for debug
# Metaproxy version
-VERSION=1.3.55
+VERSION=1.3.58
# YAZ and YAZ++ directories
YAZ_DIR=..\..\yaz
$(OBJDIR)\plainfile.obj \
$(OBJDIR)\router_chain.obj \
$(OBJDIR)\router_flexml.obj \
+ $(OBJDIR)\router_xml.obj \
$(OBJDIR)\session.obj \
$(OBJDIR)\sru_util.obj \
$(OBJDIR)\thread_pool_observer.obj \
attribute syntax { xsd:string },
attribute name { xsd:string }?,
attribute identifier { xsd:string }?,
- #attribute backendsyntax { xsd:string }?,
- #attribute backendname { xsd:string }?,
element y:backend {
attribute syntax { xsd:string },
attribute name { xsd:string }?,