test: Dispatch called service
[libisds.git] / test / simline / service.c
blob51b9b1574b9382d395a809a811d84725e6f0f5b0
1 #include "http.h"
2 #include <string.h>
3 #include <libxml/parser.h>
4 #include <libxml/xpath.h>
5 #include <libxml/xpathInternals.h>
7 static const char *soap_mime_type = "text/xml"; /* SOAP/1.1 requires text/xml */
8 /* DummyOperation response */
9 static const char *pong = "<?xml version='1.0' encoding='utf-8'?><SOAP-ENV:Envelope xmlns:SOAP-ENV=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\"><SOAP-ENV:Body><q:DummyOperationResponse xmlns:q=\"http://isds.czechpoint.cz/v20\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"><q:dmStatus><q:dmStatusCode>0000</q:dmStatusCode><q:dmStatusMessage>Provedeno úspěšně.</q:dmStatusMessage></q:dmStatus></q:DummyOperationResponse></SOAP-ENV:Body></SOAP-ENV:Envelope>";
11 /* Used to choose proper name space for message elements.
12 * See _isds_register_namespaces(). */
13 typedef enum {
14 MESSAGE_NS_1,
15 MESSAGE_NS_UNSIGNED,
16 MESSAGE_NS_SIGNED_INCOMING,
17 MESSAGE_NS_SIGNED_OUTGOING,
18 MESSAGE_NS_SIGNED_DELIVERY
19 } message_ns_type;
21 #define SOAP_NS "http://schemas.xmlsoap.org/soap/envelope/"
22 #define SOAP2_NS "http://www.w3.org/2003/05/soap-envelope"
23 #define ISDS1_NS "http://isds.czechpoint.cz"
24 #define ISDS_NS "http://isds.czechpoint.cz/v20"
25 #define SISDS_INCOMING_NS "http://isds.czechpoint.cz/v20/message"
26 #define SISDS_OUTGOING_NS "http://isds.czechpoint.cz/v20/SentMessage"
27 #define SISDS_DELIVERY_NS "http://isds.czechpoint.cz/v20/delivery"
28 #define SCHEMA_NS "http://www.w3.org/2001/XMLSchema"
29 #define DEPOSIT_NS "urn:uschovnaWSDL"
32 struct service {
33 const char *end_point;
34 const xmlChar *name;
35 void (*function) (int, xmlDocPtr, xmlXPathContextPtr, xmlNodePtr);
38 /* Parse and respond to DummyOperation */
39 static void service_DummyOperation(int socket, const xmlDocPtr soap_request,
40 xmlXPathContextPtr xpath_ctx, xmlNodePtr isds_request) {
41 http_send_response_200(socket, pong, strlen(pong), soap_mime_type);
45 /* List of implemented services */
46 static struct service services[] = {
47 { "dz", BAD_CAST "DummyOperation", service_DummyOperation },
51 /* Makes known all relevant namespaces to given XPath context
52 * @xpath_ctx is XPath context
53 * @message_ns selects proper message name space. Unsigned and signed
54 * messages and delivery info's differ in prefix and URI.
55 * @return 0 in success, otherwise not 0. */
56 static int register_namespaces(xmlXPathContextPtr xpath_ctx,
57 const message_ns_type message_ns) {
58 const xmlChar *message_namespace = NULL;
60 if (!xpath_ctx) return -1;
62 switch(message_ns) {
63 case MESSAGE_NS_1:
64 message_namespace = BAD_CAST ISDS1_NS; break;
65 case MESSAGE_NS_UNSIGNED:
66 message_namespace = BAD_CAST ISDS_NS; break;
67 case MESSAGE_NS_SIGNED_INCOMING:
68 message_namespace = BAD_CAST SISDS_INCOMING_NS; break;
69 case MESSAGE_NS_SIGNED_OUTGOING:
70 message_namespace = BAD_CAST SISDS_OUTGOING_NS; break;
71 case MESSAGE_NS_SIGNED_DELIVERY:
72 message_namespace = BAD_CAST SISDS_DELIVERY_NS; break;
73 default:
74 return -1;
77 if (xmlXPathRegisterNs(xpath_ctx, BAD_CAST "soap", BAD_CAST SOAP_NS))
78 return -1;
79 if (xmlXPathRegisterNs(xpath_ctx, BAD_CAST "isds", BAD_CAST ISDS_NS))
80 return -1;
81 if (xmlXPathRegisterNs(xpath_ctx, BAD_CAST "sisds", message_namespace))
82 return -1;
83 if (xmlXPathRegisterNs(xpath_ctx, BAD_CAST "xs", BAD_CAST SCHEMA_NS))
84 return -1;
85 if (xmlXPathRegisterNs(xpath_ctx, BAD_CAST "deposit", BAD_CAST DEPOSIT_NS))
86 return -1;
87 return 0;
91 /* Parse soap request, pass it to service endpoint and respond to it.
92 * It sends final HTTP response. */
93 void soap(int socket, const void *request, size_t request_length) {
94 xmlDocPtr request_doc = NULL;
95 xmlXPathContextPtr xpath_ctx = NULL;
96 xmlXPathObjectPtr request_soap_body = NULL;
97 xmlNodePtr isds_request = NULL; /* pointer only */
98 _Bool service_handled = 0;
100 if (NULL == request || request_length == 0) {
101 http_send_response_400(socket, "Client sent empty body");
102 return;
105 request_doc = xmlParseMemory(request, request_length);
106 if (NULL == request_doc) {
107 http_send_response_400(socket, "Client sent invalid XML document");
108 return;
111 xpath_ctx = xmlXPathNewContext(request_doc);
112 if (NULL == xpath_ctx) {
113 xmlFreeDoc(request_doc);
114 http_send_response_500(socket, "Could not create XPath context");
115 return;
118 if (register_namespaces(xpath_ctx, MESSAGE_NS_UNSIGNED)) {
119 xmlXPathFreeContext(xpath_ctx);
120 xmlFreeDoc(request_doc);
121 http_send_response_500(socket,
122 "Could not register name spaces to the XPath context");
123 return;
126 /* Get SOAP Body */
127 request_soap_body = xmlXPathEvalExpression(
128 BAD_CAST "/soap:Envelope/soap:Body", xpath_ctx);
129 if (NULL == request_soap_body) {
130 xmlXPathFreeContext(xpath_ctx);
131 xmlFreeDoc(request_doc);
132 http_send_response_400(socket, "Client sent invalid SOAP request");
133 return;
135 if (xmlXPathNodeSetIsEmpty(request_soap_body->nodesetval)) {
136 xmlXPathFreeObject(request_soap_body);
137 xmlXPathFreeContext(xpath_ctx);
138 xmlFreeDoc(request_doc);
139 http_send_response_400(socket,
140 "SOAP request does not contain SOAP Body element");
141 return;
143 if (request_soap_body->nodesetval->nodeNr > 1) {
144 xmlXPathFreeObject(request_soap_body);
145 xmlXPathFreeContext(xpath_ctx);
146 xmlFreeDoc(request_doc);
147 http_send_response_400(socket,
148 "SOAP response has more than one Body element");
149 return;
151 isds_request = request_soap_body->nodesetval->nodeTab[0]->children;
152 if (isds_request->next != NULL) {
153 xmlXPathFreeObject(request_soap_body);
154 xmlXPathFreeContext(xpath_ctx);
155 xmlFreeDoc(request_doc);
156 http_send_response_400(socket, "SOAP body has more than one child");
157 return;
159 if (isds_request->type != XML_ELEMENT_NODE || isds_request->ns == NULL ||
160 xmlStrcmp(isds_request->ns->href, BAD_CAST ISDS_NS)) {
161 xmlXPathFreeObject(request_soap_body);
162 xmlXPathFreeContext(xpath_ctx);
163 xmlFreeDoc(request_doc);
164 http_send_response_400(socket,
165 "SOAP body does not contain an ISDS elment");
166 return;
170 /* Dispatch request to service */
171 /* TODO: Use end point */
172 for (int i = 0; i < sizeof(services)/sizeof(services[0]); i++) {
173 if (!xmlStrcmp(services[i].name, isds_request->name)) {
174 services[i].function(socket, request_doc, xpath_ctx, isds_request);
175 service_handled = 1;
176 break;
180 xmlXPathFreeObject(request_soap_body);
181 xmlXPathFreeContext(xpath_ctx);
182 xmlFreeDoc(request_doc);
184 if (service_handled) {
185 http_send_response_500(socket,
186 "Requested ISDS service not implemented");