/**************************************************************************** mod_dav_pgsql (DASL) for apache 2.X CopyRight(C) 2005 SolutionBox Inc. All Rights reserved. Author : sean kim (sean@solutionbox.co.kr) $Id: search.c,v 1.2 2006/09/20 09:22:59 sean Exp $ Redistribution and use in source and binary forms, with or with out modification, are not permitted in outside of SolutionBox Inc. ****************************************************************************/ /* ** DASL SEARCH method */ #include #include #include #include #include /* for ap_construct_url */ #include #include #include "dav_repos.h" #include "dbms.h" #include "util.h" /** * Used to hold the mappings from dead properties to the temporary * table aliases they should be associated with. */ struct dead_prop_list { char *prop; struct dead_prop_list *next; }; typedef struct { char *query; char *where_cond; char *orderby; char *limit; char *err_msg; } search_ctx; typedef struct dead_prop_list dead_prop_list; int build_query(request_rec * r, apr_xml_doc * doc, search_ctx * sctx, dav_repos_resource * search_result); int build_xml_response(dav_repos_resource * query_results, dav_response ** res); int parse_select(request_rec * r, search_ctx * sctx, apr_xml_elem * select_elem, dead_prop_list ** sel_list); int parse_from(request_rec * r, dav_repos_resource * search_result, search_ctx * sctx, apr_xml_elem * from_elem, dead_prop_list * sel_list, dead_prop_list * where_list); int parse_where(request_rec * r, search_ctx * sctx, apr_xml_elem * where_elem, dead_prop_list ** where_list); int parse_orderby(request_rec * r, search_ctx * sctx, apr_xml_elem * orderby_elem); int parse_limit(request_rec * r, search_ctx * sctx, apr_xml_elem * limit_elem); int is_dead_prop(const char *prop); static dav_error *dav_repos_set_option_head(request_rec * r) { TRACE(); /*DASL: * DASL: * DASL: */ /* apr_table_addn(r->headers_out, "DASL", ""); apr_table_addn(r->headers_out, "DASL", ""); */ apr_table_addn(r->headers_out, "DASL", ""); return NULL; } /** * Handles the DASL SEARCH method * @param r The method request record * @return The HTTP response code */ static dav_error *dav_repos_search_resource(request_rec * r, dav_response ** res) { int result; apr_xml_doc *doc = NULL; apr_xml_doc *response_body = NULL; dav_repos_resource *search_result = NULL; search_ctx *sctx = apr_pcalloc(r->pool, sizeof(*sctx)); /* FIXME : */ sctx->err_msg = "unknown: Plesae specify your error!"; TRACE(); if ((result = ap_xml_parse_input(r, &doc)) != 0) { return solbox_dav_new_error(r->pool, HTTP_BAD_REQUEST, 0, "ap_xml_parse_input error"); } /*initialize search result structure */ search_result = (dav_repos_resource *) apr_pcalloc(r->pool, sizeof(*search_result)); search_result->p = r->pool; /* We need XML doc */ if (doc == NULL || doc->root == NULL) { return solbox_dav_new_error(r->pool, HTTP_BAD_REQUEST, 0, "doc is NULL"); } /* Build query */ if ((result = build_query(r, doc, sctx, search_result)) != HTTP_OK) { return solbox_dav_new_error(r->pool, result, 0, sctx->err_msg); } /* Seek DBMS */ if ((dbms_search(sctx->query, search_result)) != 0) { return solbox_dav_new_error(r->pool, HTTP_INTERNAL_SERVER_ERROR, 0, "DBMS_SEARCH error"); } /** FIXME : It might be too slow */ /* Get properties in a form of property link for every resource */ dbms_fill_dead_property(search_result); /* Make result */ response_body = (apr_xml_doc *) apr_pcalloc(r->pool, sizeof(*response_body)); if ((result = build_xml_response(search_result, res) != HTTP_OK)) { return solbox_dav_new_error(r->pool, HTTP_BAD_REQUEST, 0, "An error occurred while building XML response!"); } return NULL; } /** * Builds the SQL query from the XML body of the request * @param r The method request record * @param doc The XML doc being parsed * @param query The SQL query being built * @param search_result The result record(s) returned from the DB query * @param db_handle Pointer to the DB * @return The HTTP response code */ int build_query(request_rec * r, apr_xml_doc * doc, search_ctx * sctx, dav_repos_resource * search_result) { int result = -23; apr_xml_elem *cur_elem = NULL; apr_xml_elem *from_elem = NULL; apr_xml_elem *select_elem = NULL; apr_xml_elem *where_elem = NULL; apr_xml_elem *order_elem = NULL; apr_xml_elem *limit_elem = NULL; dead_prop_list *sel_list = NULL; dead_prop_list *where_list = NULL; TRACE(); /* basicsearch */ cur_elem = dav_find_child(doc->root, "basicsearch"); if (cur_elem == NULL) { sctx->err_msg = apr_pstrdup(r->pool, "Requested search grammar not supported." " We support only "); return HTTP_BAD_REQUEST; } /* initialize the query */ sctx->query = apr_pstrdup(r->pool, "SELECT distinct "); /* Find elements */ select_elem = dav_find_child(cur_elem, "select"); from_elem = dav_find_child(cur_elem, "from"); where_elem = dav_find_child(cur_elem, "where"); order_elem = dav_find_child(cur_elem, "orderby"); limit_elem = dav_find_child(cur_elem, "limit"); /* process the select portion */ if (select_elem == NULL) { sctx->err_msg = apr_pstrdup(r->pool, "We don't have