test: Check for end point path
[libisds.git] / test / simline / service.c
blob90ec5fa0547cf61f3fdfd76a901aca238f825dea
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 { "DS/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 const char *end_point) {
95 xmlDocPtr request_doc = NULL;
96 xmlXPathContextPtr xpath_ctx = NULL;
97 xmlXPathObjectPtr request_soap_body = NULL;
98 xmlNodePtr isds_request = NULL; /* pointer only */
99 _Bool service_handled = 0;
101 if (NULL == request || request_length == 0) {
102 http_send_response_400(socket, "Client sent empty body");
103 return;
106 request_doc = xmlParseMemory(request, request_length);
107 if (NULL == request_doc) {
108 http_send_response_400(socket, "Client sent invalid XML document");
109 return;
112 xpath_ctx = xmlXPathNewContext(request_doc);
113 if (NULL == xpath_ctx) {
114 xmlFreeDoc(request_doc);
115 http_send_response_500(socket, "Could not create XPath context");
116 return;
119 if (register_namespaces(xpath_ctx, MESSAGE_NS_UNSIGNED)) {
120 xmlXPathFreeContext(xpath_ctx);
121 xmlFreeDoc(request_doc);
122 http_send_response_500(socket,
123 "Could not register name spaces to the XPath context");
124 return;
127 /* Get SOAP Body */
128 request_soap_body = xmlXPathEvalExpression(
129 BAD_CAST "/soap:Envelope/soap:Body", xpath_ctx);
130 if (NULL == request_soap_body) {
131 xmlXPathFreeContext(xpath_ctx);
132 xmlFreeDoc(request_doc);
133 http_send_response_400(socket, "Client sent invalid SOAP request");
134 return;
136 if (xmlXPathNodeSetIsEmpty(request_soap_body->nodesetval)) {
137 xmlXPathFreeObject(request_soap_body);
138 xmlXPathFreeContext(xpath_ctx);
139 xmlFreeDoc(request_doc);
140 http_send_response_400(socket,
141 "SOAP request does not contain SOAP Body element");
142 return;
144 if (request_soap_body->nodesetval->nodeNr > 1) {
145 xmlXPathFreeObject(request_soap_body);
146 xmlXPathFreeContext(xpath_ctx);
147 xmlFreeDoc(request_doc);
148 http_send_response_400(socket,
149 "SOAP response has more than one Body element");
150 return;
152 isds_request = request_soap_body->nodesetval->nodeTab[0]->children;
153 if (isds_request->next != NULL) {
154 xmlXPathFreeObject(request_soap_body);
155 xmlXPathFreeContext(xpath_ctx);
156 xmlFreeDoc(request_doc);
157 http_send_response_400(socket, "SOAP body has more than one child");
158 return;
160 if (isds_request->type != XML_ELEMENT_NODE || isds_request->ns == NULL ||
161 xmlStrcmp(isds_request->ns->href, BAD_CAST ISDS_NS)) {
162 xmlXPathFreeObject(request_soap_body);
163 xmlXPathFreeContext(xpath_ctx);
164 xmlFreeDoc(request_doc);
165 http_send_response_400(socket,
166 "SOAP body does not contain an ISDS elment");
167 return;
171 /* Dispatch request to service */
172 for (int i = 0; i < sizeof(services)/sizeof(services[0]); i++) {
173 if (!strcmp(services[i].end_point, end_point) &&
174 !xmlStrcmp(services[i].name, isds_request->name)) {
175 services[i].function(socket, request_doc, xpath_ctx, isds_request);
176 service_handled = 1;
177 break;
181 xmlXPathFreeObject(request_soap_body);
182 xmlXPathFreeContext(xpath_ctx);
183 xmlFreeDoc(request_doc);
185 if (service_handled) {
186 http_send_response_500(socket,
187 "Requested ISDS service not implemented");