+ return true;
+}
+
+yf::Zoom::BackendPtr yf::Zoom::Frontend::get_backend_from_databases(
+ mp::Package &package,
+ std::string &database, int *error, char **addinfo, mp::odr &odr,
+ int *proxy_step)
+{
+ bool connection_reuse = false;
+ std::string proxy;
+
+ std::list<BackendPtr>::const_iterator map_it;
+ if (m_backend && !m_backend->enable_explain &&
+ m_backend->m_frontend_database == database)
+ {
+ connection_reuse = true;
+ proxy = m_backend->m_proxy;
+ }
+
+ std::string input_args;
+ std::string torus_db;
+ size_t db_arg_pos = database.find(',');
+ if (db_arg_pos != std::string::npos)
+ {
+ torus_db = database.substr(0, db_arg_pos);
+ input_args = database.substr(db_arg_pos + 1);
+ }
+ else
+ torus_db = database;
+
+ std::string authentication;
+ std::string content_authentication;
+ std::string content_proxy;
+ std::string realm = session_realm;
+ if (realm.length() == 0)
+ realm = m_p->default_realm;
+
+ const char *param_user = 0;
+ const char *param_password = 0;
+ const char *param_content_user = 0;
+ const char *param_content_password = 0;
+ const char *param_nocproxy = 0;
+ const char *param_retry = 0;
+ int no_parms = 0;
+
+ char **names;
+ char **values;
+ int no_out_args = 0;
+ if (input_args.length())
+ no_parms = yaz_uri_to_array(input_args.c_str(),
+ odr, &names, &values);
+ // adding 10 because we'll be adding other URL args
+ const char **out_names = (const char **)
+ odr_malloc(odr, (10 + no_parms) * sizeof(*out_names));
+ const char **out_values = (const char **)
+ odr_malloc(odr, (10 + no_parms) * sizeof(*out_values));
+
+ // may be changed if it's a content connection
+ std::string torus_url = m_p->torus_searchable_url;
+ int i;
+ for (i = 0; i < no_parms; i++)
+ {
+ const char *name = names[i];
+ const char *value = values[i];
+ assert(name);
+ assert(value);
+ if (!strcmp(name, "user"))
+ param_user = value;
+ else if (!strcmp(name, "password"))
+ param_password = value;
+ else if (!strcmp(name, "content-user"))
+ param_content_user = value;
+ else if (!strcmp(name, "content-password"))
+ param_content_password = value;
+ else if (!strcmp(name, "content-proxy"))
+ content_proxy = value;
+ else if (!strcmp(name, "nocproxy"))
+ param_nocproxy = value;
+ else if (!strcmp(name, "retry"))
+ param_retry = value;
+ else if (!strcmp(name, "proxy"))
+ {
+ char **dstr;
+ int dnum = 0;
+ nmem_strsplit(((ODR) odr)->mem, ",", value, &dstr, &dnum);
+ if (connection_reuse)
+ {
+ // find the step after our current proxy
+ int i;
+ for (i = 0; i < dnum; i++)
+ if (!strcmp(proxy.c_str(), dstr[i]))
+ break;
+ if (i >= dnum - 1)
+ *proxy_step = 0;
+ else
+ *proxy_step = i + 1;
+ }
+ else
+ {
+ // step is known.. Guess our proxy from it
+ if (*proxy_step >= dnum)
+ *proxy_step = 0;
+ else
+ {
+ proxy = dstr[*proxy_step];
+
+ (*proxy_step)++;
+ if (*proxy_step == dnum)
+ *proxy_step = 0;
+ }
+ }
+ }
+ else if (!strcmp(name, "cproxysession"))
+ {
+ out_names[no_out_args] = name;
+ out_values[no_out_args++] = value;
+ torus_url = m_p->torus_content_url;
+ }
+ else if (!strcmp(name, "realm") && session_realm.length() == 0)
+ realm = value;
+ else if (!strcmp(name, "torus_url") && session_realm.length() == 0)
+ torus_url = value;
+ else if (name[0] == 'x' && name[1] == '-')
+ {
+ out_names[no_out_args] = name;
+ out_values[no_out_args++] = value;
+ }
+ else
+ {
+ BackendPtr notfound;
+ char *msg = (char*) odr_malloc(odr, strlen(name) + 30);
+ *error = YAZ_BIB1_TEMPORARY_SYSTEM_ERROR;
+ sprintf(msg, "zoom: bad database argument: %s", name);
+ *addinfo = msg;
+ return notfound;
+ }
+ }
+ if (proxy.length())
+ package.log("zoom", YLOG_LOG, "proxy: %s", proxy.c_str());
+
+ if (connection_reuse)
+ {
+ m_backend->connect("", error, addinfo, odr);
+ return m_backend;
+ }
+
+ if (param_user)
+ {
+ authentication = std::string(param_user);
+ if (param_password)
+ authentication += "/" + std::string(param_password);
+ }
+ if (param_content_user)
+ {
+ content_authentication = std::string(param_content_user);
+ if (param_content_password)
+ content_authentication += "/" + std::string(param_content_password);
+ }
+
+ if (torus_db.compare("IR-Explain---1") == 0)
+ return explain_search(package, database, error, addinfo, odr, torus_url,
+ torus_db, realm);
+
+ SearchablePtr sptr;
+
+ std::map<std::string,SearchablePtr>::iterator it;
+ it = m_p->s_map.find(torus_db);
+ if (it != m_p->s_map.end())
+ sptr = it->second;
+ else if (torus_url.length() > 0)
+ {
+ std::string torus_addinfo;
+ std::string torus_query = "udb==" + torus_db;
+ xmlDoc *doc = mp::get_searchable(package,torus_url, torus_db,
+ torus_query,
+ realm, m_p->proxy,
+ torus_addinfo);
+ if (!doc)
+ {
+ *error = YAZ_BIB1_UNSPECIFIED_ERROR;
+ if (torus_addinfo.length())
+ *addinfo = odr_strdup(odr, torus_addinfo.c_str());
+ BackendPtr b;
+ return b;
+ }
+ const xmlNode *ptr = xmlDocGetRootElement(doc);
+ if (ptr && ptr->type == XML_ELEMENT_NODE)
+ {
+ if (!strcmp((const char *) ptr->name, "record"))
+ {
+ sptr = m_p->parse_torus_record(ptr);
+ }
+ else if (!strcmp((const char *) ptr->name, "records"))
+ {
+ for (ptr = ptr->children; ptr; ptr = ptr->next)
+ {
+ if (ptr->type == XML_ELEMENT_NODE
+ && !strcmp((const char *) ptr->name, "record"))
+ {
+ if (sptr)
+ {
+ *error = YAZ_BIB1_UNSPECIFIED_ERROR;
+ *addinfo = (char*)
+ odr_malloc(odr, 40 + torus_db.length());
+ sprintf(*addinfo, "multiple records for udb=%s",
+ database.c_str());
+ xmlFreeDoc(doc);
+ BackendPtr b;
+ return b;
+ }
+ sptr = m_p->parse_torus_record(ptr);
+ }
+ }
+ }
+ else
+ {
+ *error = YAZ_BIB1_UNSPECIFIED_ERROR;
+ *addinfo = (char*) odr_malloc(
+ odr, 40 + strlen((const char *) ptr->name));
+ sprintf(*addinfo, "bad root element for torus: %s", ptr->name);
+ xmlFreeDoc(doc);
+ BackendPtr b;
+ return b;
+ }
+ }
+ xmlFreeDoc(doc);
+ }
+
+ if (!sptr)
+ {
+ *error = YAZ_BIB1_DATABASE_DOES_NOT_EXIST;
+ *addinfo = odr_strdup(odr, torus_db.c_str());
+ BackendPtr b;
+ return b;
+ }
+
+ xsltStylesheetPtr xsp = 0;
+ if (sptr->transform_xsl_content.length())
+ {
+ xmlDoc *xsp_doc = xmlParseMemory(sptr->transform_xsl_content.c_str(),
+ sptr->transform_xsl_content.length());
+ if (!xsp_doc)
+ {
+ *error = YAZ_BIB1_TEMPORARY_SYSTEM_ERROR;
+ *addinfo = odr_strdup(odr, "zoom: xmlParseMemory failed "
+ "for literalTransform XSL");
+ BackendPtr b;
+ return b;
+ }
+ xsp = xsltParseStylesheetDoc(xsp_doc);
+ if (!xsp)
+ {
+ *error = YAZ_BIB1_DATABASE_DOES_NOT_EXIST;
+ *addinfo =
+ odr_strdup(odr,"zoom: xsltParseStylesheetDoc failed "
+ "for literalTransform XSL");
+ BackendPtr b;
+ xmlFreeDoc(xsp_doc);
+ return b;
+ }
+ }
+ else if (sptr->transform_xsl_fname.length())
+ {
+ const char *path = 0;
+
+ if (m_p->xsldir.length())
+ path = m_p->xsldir.c_str();
+ else
+ path = m_p->file_path.c_str();
+ std::string fname;
+
+ char fullpath[1024];
+ char *cp = yaz_filepath_resolve(sptr->transform_xsl_fname.c_str(),
+ path, 0, fullpath);
+ if (cp)
+ fname.assign(cp);
+ else
+ {
+ *error = YAZ_BIB1_TEMPORARY_SYSTEM_ERROR;
+ *addinfo = (char *)
+ odr_malloc(odr, 40 + sptr->transform_xsl_fname.length());
+ sprintf(*addinfo, "zoom: could not open file %s",
+ sptr->transform_xsl_fname.c_str());
+ BackendPtr b;
+ return b;
+ }
+ xmlDoc *xsp_doc = xmlParseFile(fname.c_str());
+ if (!xsp_doc)
+ {
+ *error = YAZ_BIB1_TEMPORARY_SYSTEM_ERROR;
+ *addinfo = (char *) odr_malloc(odr, 50 + fname.length());
+ sprintf(*addinfo, "zoom: xmlParseFile failed for file %s",
+ fname.c_str());
+ BackendPtr b;
+ return b;
+ }
+ xsp = xsltParseStylesheetDoc(xsp_doc);
+ if (!xsp)
+ {
+ *error = YAZ_BIB1_TEMPORARY_SYSTEM_ERROR;
+ *addinfo = (char *) odr_malloc(odr, 50 + fname.length());
+ sprintf(*addinfo, "zoom: xsltParseStylesheetDoc failed "
+ "for file %s", fname.c_str());
+ BackendPtr b;
+ xmlFreeDoc(xsp_doc);
+ return b;
+ }
+ }
+
+ cql_transform_t cqlt = 0;
+ if (sptr->rpn2cql_fname.length())
+ {
+ char fullpath[1024];
+ char *cp = yaz_filepath_resolve(sptr->rpn2cql_fname.c_str(),
+ m_p->file_path.c_str(), 0, fullpath);
+ if (cp)
+ cqlt = cql_transform_open_fname(fullpath);
+ }
+ else
+ cqlt = cql_transform_create();
+
+ if (!cqlt)
+ {
+ *error = YAZ_BIB1_TEMPORARY_SYSTEM_ERROR;
+ *addinfo = odr_strdup(odr, "zoom: missing/invalid cql2rpn file");
+ BackendPtr b;
+ xsltFreeStylesheet(xsp);
+ return b;
+ }
+
+ m_backend.reset();
+
+ BackendPtr b(new Backend);
+
+ b->cqlt = cqlt;
+ b->sptr = sptr;
+ b->xsp = xsp;
+ b->m_frontend_database = database;
+ b->enable_cproxy = param_nocproxy ? false : true;
+
+ if (param_retry)
+ b->retry_on_failure = param_retry;
+ else
+ b->retry_on_failure = b->sptr->retry_on_failure;
+
+ if (sptr->query_encoding.length())
+ b->set_option("rpnCharset", sptr->query_encoding);
+
+ std::string extraArgs = sptr->extraArgs;
+
+ b->set_option("timeout", m_p->zoom_timeout.c_str());
+
+ if (m_p->apdu_log)
+ b->set_option("apdulog", "1");
+
+ if (sptr->piggyback && sptr->sru.length())
+ b->set_option("count", "1"); /* some SRU servers INSIST on getting
+ maximumRecords > 0 */
+ b->set_option("piggyback", sptr->piggyback ? "1" : "0");
+
+ if (authentication.length() == 0)
+ authentication = sptr->authentication;
+
+ if (proxy.length() == 0)
+ proxy = sptr->cfProxy;
+ b->m_proxy = proxy;
+
+ if (sptr->cfAuth.length())
+ {
+ // A CF target
+ b->set_option("user", sptr->cfAuth);
+ if (authentication.length())
+ {
+ size_t found = authentication.find('/');
+ if (found != std::string::npos)
+ {
+ out_names[no_out_args] = "user";
+ out_values[no_out_args++] =
+ odr_strdup(odr, authentication.substr(0, found).c_str());
+
+ out_names[no_out_args] = "password";
+ out_values[no_out_args++] =
+ odr_strdup(odr, authentication.substr(found+1).c_str());
+ }
+ else
+ {
+ out_names[no_out_args] = "user";
+ out_values[no_out_args++] =
+ odr_strdup(odr, authentication.c_str());
+ }
+ }
+ if (proxy.length())
+ {
+ out_names[no_out_args] = "proxy";
+ out_values[no_out_args++] = odr_strdup(odr, proxy.c_str());
+ }
+ if (sptr->cfSubDB.length())
+ {
+ out_names[no_out_args] = "subdatabase";
+ out_values[no_out_args++] = odr_strdup(odr, sptr->cfSubDB.c_str());
+ }
+ if (!param_nocproxy && b->sptr->contentConnector.length())
+ param_nocproxy = "1";
+
+ if (param_nocproxy)
+ {
+ out_names[no_out_args] = "nocproxy";
+ out_values[no_out_args++] = odr_strdup(odr, param_nocproxy);
+ }
+ }
+ else
+ {
+ const char *auth = authentication.c_str();
+ const char *cp1 = strchr(auth, ' ');
+ if (!cp1 && sptr->sru.length())
+ cp1 = strchr(auth, '/');
+ if (!cp1)
+ {
+ /* Z39.50 user/password style, or no password for SRU */
+ b->set_option("user", auth);
+ }
+ else
+ {
+ /* now consider group as well */
+ const char *cp2 = strchr(cp1 + 1, ' ');