+ Z_SearchRequest *sr = apdu->u.searchRequest;
+ int err = 0;
+ char *addinfo = 0;
+
+ Yaz_ProxyConfig *cfg = check_reconfigure();
+ if (cfg)
+ err = cfg->check_query(odr_encode(), m_default_target,
+ sr->query, &addinfo);
+ if (err)
+ {
+ Z_APDU *new_apdu = create_Z_PDU(Z_APDU_searchResponse);
+
+ new_apdu->u.searchResponse->referenceId = sr->referenceId;
+ new_apdu->u.searchResponse->records =
+ create_nonSurrogateDiagnostics(odr_encode(), err, addinfo);
+ *new_apdu->u.searchResponse->searchStatus = 0;
+
+ send_to_client(new_apdu);
+
+ return 0;
+ }
+ }
+ else if (apdu->which == Z_APDU_scanRequest)
+ {
+ Z_ScanRequest *sr = apdu->u.scanRequest;
+ int err = 0;
+ char *addinfo = 0;
+
+#if 0
+ Yaz_ProxyConfig *cfg = check_reconfigure();
+// Something like this needs to be implemented later:
+ if (cfg)
+ err = cfg->check_type_1_attributes(odr_encode(), m_default_target,
+ sr->termListAndStartPoint->attributes, &addinfo);
+#endif
+ if (err)
+ {
+ Z_APDU *new_apdu = create_Z_PDU(Z_APDU_scanResponse);
+
+ new_apdu->u.scanResponse->referenceId = sr->referenceId;
+ new_apdu->u.scanResponse->entries =
+ create_nonSurrogateDiagnostics2(odr_encode(), err, addinfo);
+ *new_apdu->u.scanResponse->scanStatus = Z_Scan_failure;
+
+ send_to_client(new_apdu);
+
+ return 0;
+ }
+ }
+
+ return apdu;
+}
+
+int Yaz_Proxy::handle_authentication(Z_APDU *apdu)
+{
+ if (apdu->which != Z_APDU_initRequest)
+ return 1; // pass if no init request
+ Z_InitRequest *req = apdu->u.initRequest;
+
+ Yaz_ProxyConfig *cfg = check_reconfigure();
+ if (!cfg)
+ return 1; // pass if no config
+
+ int ret;
+ if (req->idAuthentication == 0)
+ {
+ ret = cfg->client_authentication(m_default_target, 0, 0, 0,
+ m_peername);
+ }
+ else if (req->idAuthentication->which == Z_IdAuthentication_idPass)
+ {
+ ret = cfg->client_authentication(
+ m_default_target,
+ req->idAuthentication->u.idPass->userId,
+ req->idAuthentication->u.idPass->groupId,
+ req->idAuthentication->u.idPass->password,
+ m_peername);
+ }
+ else if (req->idAuthentication->which == Z_IdAuthentication_open)
+ {
+ char user[64], pass[64];
+ *user = '\0';
+ *pass = '\0';
+ sscanf(req->idAuthentication->u.open, "%63[^/]/%63s", user, pass);
+ ret = cfg->client_authentication(m_default_target, user, 0, pass,
+ m_peername);
+ }
+ else
+ ret = cfg->client_authentication(m_default_target, 0, 0, 0,
+ m_peername);
+ return ret;
+}
+
+int Yaz_Proxy::handle_global_authentication(Z_APDU *apdu)
+{
+ if (apdu->which != Z_APDU_initRequest)
+ return 1; // pass if no init request
+ Z_InitRequest *req = apdu->u.initRequest;
+
+ Yaz_ProxyConfig *cfg = check_reconfigure();
+ if (!cfg)
+ return 1; // pass if no config
+
+ int ret;
+ if (req->idAuthentication == 0)
+ {
+ ret = cfg->global_client_authentication(0, 0, 0,
+ m_peername);
+ }
+ else if (req->idAuthentication->which == Z_IdAuthentication_idPass)
+ {
+ ret = cfg->global_client_authentication(
+ req->idAuthentication->u.idPass->userId,
+ req->idAuthentication->u.idPass->groupId,
+ req->idAuthentication->u.idPass->password,
+ m_peername);
+ }
+ else if (req->idAuthentication->which == Z_IdAuthentication_open)
+ {
+ char user[64], pass[64];
+ *user = '\0';
+ *pass = '\0';
+ sscanf(req->idAuthentication->u.open, "%63[^/]/%63s", user, pass);
+ ret = cfg->global_client_authentication(user, 0, pass,
+ m_peername);
+ }
+ else
+ ret = cfg->global_client_authentication(0, 0, 0, m_peername);
+ return ret;
+}
+
+Z_APDU *Yaz_Proxy::handle_syntax_validation(Z_APDU *apdu)
+{
+ m_marcxml_mode = none;
+ if (apdu->which == Z_APDU_searchRequest)
+ {
+ Z_SearchRequest *sr = apdu->u.searchRequest;
+ int err = 0;
+ char *addinfo = 0;
+ Yaz_ProxyConfig *cfg = check_reconfigure();
+
+ Z_RecordComposition rc_temp, *rc = 0;
+ if (sr->smallSetElementSetNames)
+ {
+ rc_temp.which = Z_RecordComp_simple;
+ rc_temp.u.simple = sr->smallSetElementSetNames;
+ rc = &rc_temp;
+ }
+
+ if (sr->preferredRecordSyntax)
+ oid_oidcpy(m_frontend_type, sr->preferredRecordSyntax);
+ else
+ m_frontend_type[0] = -1;
+
+ char *stylesheet_name = 0;
+ if (cfg)
+ err = cfg->check_syntax(odr_encode(),
+ m_default_target,
+ sr->preferredRecordSyntax, rc,
+ &addinfo, &stylesheet_name, &m_schema,
+ &m_backend_type, &m_backend_charset,
+ &m_usemarcon_ini_stage1,
+ &m_usemarcon_ini_stage2,
+ &m_backend_elementset);
+ if (stylesheet_name)
+ {
+ m_parent->low_socket_close();
+
+#if YAZ_HAVE_XSLT
+ if (m_stylesheet_xsp)
+ xsltFreeStylesheet((xsltStylesheetPtr) m_stylesheet_xsp);
+ m_stylesheet_xsp = xsltParseStylesheetFile((const xmlChar*)
+ stylesheet_name);
+#endif
+ m_stylesheet_offset = 0;
+ xfree(stylesheet_name);
+
+ m_parent->low_socket_open();
+ }
+ if (err == -1)
+ {
+ sr->smallSetElementSetNames = 0;
+ sr->mediumSetElementSetNames = 0;
+ m_marcxml_mode = marcxml;
+ sr->preferredRecordSyntax =
+ yaz_string_to_oid_odr(
+ yaz_oid_std(), CLASS_RECSYN,
+ m_backend_type ? m_backend_type : "usmarc",
+ odr_encode());
+ }
+ else if (err)
+ {
+ Z_APDU *new_apdu = create_Z_PDU(Z_APDU_searchResponse);
+
+ new_apdu->u.searchResponse->referenceId = sr->referenceId;
+ new_apdu->u.searchResponse->records =
+ create_nonSurrogateDiagnostics(odr_encode(), err, addinfo);
+ *new_apdu->u.searchResponse->searchStatus = 0;
+
+ send_to_client(new_apdu);
+
+ return 0;
+ }
+ else if (m_backend_type)
+ {
+ sr->preferredRecordSyntax =
+ yaz_string_to_oid_odr(yaz_oid_std(), CLASS_RECSYN,
+ m_backend_type, odr_encode());
+ }
+ if (m_backend_elementset)
+ {
+ Z_ElementSetNames *esn =
+ mk_esn_from_schema(
+ odr_encode(),
+ *m_backend_elementset ? m_backend_elementset : 0);
+ sr->smallSetElementSetNames = esn;
+ sr->mediumSetElementSetNames = esn;
+ }
+ }
+ else if (apdu->which == Z_APDU_presentRequest)
+ {
+ Z_PresentRequest *pr = apdu->u.presentRequest;
+ int err = 0;
+ char *addinfo = 0;
+ Yaz_ProxyConfig *cfg = check_reconfigure();
+
+ if (pr->preferredRecordSyntax)
+ oid_oidcpy(m_frontend_type, pr->preferredRecordSyntax);
+ else
+ m_frontend_type[0] = -1;
+
+ char *stylesheet_name = 0;
+ if (cfg)
+ err = cfg->check_syntax(odr_encode(), m_default_target,
+ pr->preferredRecordSyntax,
+ pr->recordComposition,
+ &addinfo, &stylesheet_name, &m_schema,
+ &m_backend_type, &m_backend_charset,
+ &m_usemarcon_ini_stage1,
+ &m_usemarcon_ini_stage2,
+ &m_backend_elementset);
+ if (stylesheet_name)
+ {
+ m_parent->low_socket_close();
+
+#if YAZ_HAVE_XSLT
+ if (m_stylesheet_xsp)
+ xsltFreeStylesheet((xsltStylesheetPtr) m_stylesheet_xsp);
+ m_stylesheet_xsp = xsltParseStylesheetFile((const xmlChar*)
+ stylesheet_name);
+#endif
+ m_stylesheet_offset = 0;
+ xfree(stylesheet_name);
+
+ m_parent->low_socket_open();
+ }
+ if (err == -1)
+ {
+ pr->recordComposition = 0;
+ m_marcxml_mode = marcxml;
+
+ pr->preferredRecordSyntax =
+ yaz_string_to_oid_odr(
+ yaz_oid_std(), CLASS_RECSYN,
+ m_backend_type ? m_backend_type : "usmarc",
+ odr_encode());
+ }
+ else if (err)
+ {
+ Z_APDU *new_apdu = create_Z_PDU(Z_APDU_presentResponse);
+
+ new_apdu->u.presentResponse->referenceId = pr->referenceId;
+ new_apdu->u.presentResponse->records =
+ create_nonSurrogateDiagnostics(odr_encode(), err, addinfo);
+ *new_apdu->u.presentResponse->presentStatus =
+ Z_PresentStatus_failure;
+
+ send_to_client(new_apdu);
+
+ return 0;
+ }
+ else if (m_backend_type)
+ {
+ pr->preferredRecordSyntax =
+ yaz_string_to_oid_odr(yaz_oid_std(),
+ CLASS_RECSYN, m_backend_type,
+ odr_encode());
+ }
+ if (m_backend_elementset)
+ {
+ Z_ElementSetNames *esn =
+ mk_esn_from_schema(
+ odr_encode(),
+ *m_backend_elementset ? m_backend_elementset : 0);
+ Z_RecordComposition *comp = (Z_RecordComposition *)
+ odr_malloc(odr_encode(), sizeof(Z_RecordComposition));
+ comp->which = Z_RecordComp_simple;
+ comp->u.simple = esn;
+ pr->recordComposition = comp;
+ }
+ }
+ return apdu;
+}
+
+Z_ElementSetNames *Yaz_Proxy::mk_esn_from_schema(ODR o, const char *schema)
+{
+ if (!schema)
+ return 0;
+ Z_ElementSetNames *esn = (Z_ElementSetNames *)
+ odr_malloc(o, sizeof(Z_ElementSetNames));
+ esn->which = Z_ElementSetNames_generic;
+ esn->u.generic = odr_strdup(o, schema);
+ return esn;
+}
+
+void Yaz_Proxy::srw_get_client(const char *db, const char **backend_db)
+{
+ const char *t = 0;
+ Yaz_ProxyConfig *cfg = check_reconfigure();
+ if (cfg)
+ t = cfg->get_explain_name(db, backend_db);
+
+ if (m_client && m_default_target && t && strcmp(m_default_target, t))
+ {
+ releaseClient();
+ }
+
+ if (t)
+ {
+ xfree(m_default_target);
+ m_default_target = xstrdup(t);
+ }
+}
+
+int Yaz_Proxy::file_access(Z_HTTP_Request *hreq)
+{
+ struct stat sbuf;
+ if (strcmp(hreq->method, "GET"))
+ return 0;
+ if (hreq->path[0] != '/')
+ return 0;
+ const char *cp = hreq->path;
+ while (*cp)
+ {
+ if (*cp == '/' && strchr("/.", cp[1]))
+ return 0;
+ cp++;
+ }
+
+ Yaz_ProxyConfig *cfg = check_reconfigure();
+
+ if (!cfg->get_file_access_info(hreq->path+1))
+ return 0;