From 7ed3b0bb398f43429c6c0d0d9bd8b5bada1d7389 Mon Sep 17 00:00:00 2001 From: snowdrop Date: Fri, 15 Oct 2004 13:33:13 +0000 Subject: added attachment support --- libcsoap/soap-client.c | 176 +++++++++++++++++++++++++++++++++++++++++++++---- libcsoap/soap-client.h | 100 ++++++++++++++-------------- libcsoap/soap-env.c | 122 ++++++++++++++++++++++++++++++++-- libcsoap/soap-env.h | 28 +++++++- libcsoap/soap-server.c | 115 ++++++++++++++++++++++++-------- libcsoap/soap-server.h | 3 +- 6 files changed, 449 insertions(+), 95 deletions(-) diff --git a/libcsoap/soap-client.c b/libcsoap/soap-client.c index d287609..58886ff 100644 --- a/libcsoap/soap-client.c +++ b/libcsoap/soap-client.c @@ -1,5 +1,5 @@ /****************************************************************** -* $Id: soap-client.c,v 1.7 2004/09/19 07:05:03 snowdrop Exp $ +* $Id: soap-client.c,v 1.8 2004/10/15 13:33:13 snowdrop Exp $ * * CSOAP Project: A SOAP client/server library in C * Copyright (C) 2003 Ferhat Ayaz @@ -38,35 +38,173 @@ int soap_client_init_args(int argc, char *argv[]) } -SoapEnv* -soap_client_invoke(SoapEnv *call, const char *url, const char *soap_action) + +static +long _file_get_size(const char* filename) +{ + FILE *f = fopen(filename, "r"); + long size; + + if (!f) return -1; + + fseek(f, 0, SEEK_END); + size=ftell(f); + fclose(f); + return size; +} + +SoapCtx* +soap_client_invoke(SoapCtx *call, const char *url, const char *soap_action) { + /* Status */ + hstatus_t status; + /* Result document */ SoapEnv* doc; + /* Result Context */ + SoapCtx *ctx; + /* Buffer variables*/ xmlBufferPtr buffer; char *content; + char tmp[15]; /* Transport variables */ httpc_conn_t *conn; hresponse_t *res; + /* multipart/related start id*/ + char start_id[150]; + static int counter=1; + part_t *part; + int file_count=0; + long total_size; + long file_size; + /* Create buffer */ buffer = xmlBufferCreate(); - xmlNodeDump(buffer, call->root->doc,call->root, 1 ,0); + xmlNodeDump(buffer, call->env->root->doc,call->env->root, 1 ,0); content = (char*)xmlBufferContent(buffer); /* Transport via HTTP */ conn = httpc_new(); - /* content-type is always 'text/xml' */ - httpc_set_header(conn, HEADER_CONTENT_TYPE, "text/xml"); - + /* Set soap action */ if (soap_action != NULL) { httpc_set_header(conn, "SoapAction", soap_action); } - res = httpc_post(conn, url, (int)strlen(content), content); + + /* check for attachments */ + if (!call->attachments) + { + /* content-type is always 'text/xml' */ + httpc_set_header(conn, HEADER_CONTENT_TYPE, "text/xml"); + + sprintf(tmp, "%d", (int)strlen(content)); + httpc_set_header(conn, HEADER_CONTENT_LENGTH, tmp); + status = httpc_post_begin(conn, url); + + if (status != H_OK) { + httpc_free(conn); + xmlBufferFree(buffer); + return soap_ctx_new( + soap_env_new_with_fault(Fault_Client, + "Can not begin post envelope","","")); + } + + status = http_output_stream_write_string(conn->out, content); + if (status != H_OK) { + httpc_free(conn); + xmlBufferFree(buffer); + return soap_ctx_new( + soap_env_new_with_fault(Fault_Client, + "Can not post envelope","","")); + } + + /* res = httpc_post(conn, url, (int)strlen(content), content);*/ + res = httpc_post_end(conn); + if (res == NULL) { + httpc_free(conn); + xmlBufferFree(buffer); + return soap_ctx_new( + soap_env_new_with_fault(Fault_Client, + conn->errmsg,"","")); + } + } + else + { + + /* Use content-length transport */ + /*for (part=call->attachments->parts; part; part=part->next) { + file_size = _file_get_size(part->filename); + if (file_size == -1) [ + httpc_free(conn); + xmlBufferFree(buffer); + return soap_ctx_new( + soap_env_new_with_fault(Fault_Client, + "Can not open file!","","")); + } + + total_size += file_size + BOUDARY_LENGTH; + }*/ + + /* Use chunked transport */ + httpc_set_header(conn, HEADER_TRANSFER_ENCODING, TRANSFER_ENCODING_CHUNKED); + + sprintf(start_id, "289247829121218%d", counter++); + status = httpc_mime_begin(conn, url, start_id, "", "text/xml"); + if (status != H_OK) { + httpc_free(conn); + xmlBufferFree(buffer); + return soap_ctx_new( + soap_env_new_with_fault(Fault_Client, + "Can not begin MIME transport","","")); + } + + status = httpc_mime_next(conn, start_id, "text/xml", "binary"); + if (status != H_OK) { + httpc_free(conn); + xmlBufferFree(buffer); + return soap_ctx_new( + soap_env_new_with_fault(Fault_Client, + "MIME transport error","","")); + } + + status = http_output_stream_write(conn->out, content, strlen(content)); + if (status != H_OK) { + httpc_free(conn); + xmlBufferFree(buffer); + return soap_ctx_new( + soap_env_new_with_fault(Fault_Client, + "MIME transport error","","")); + } + + + for (part=call->attachments->parts; part; part=part->next) + { + status = httpc_mime_send_file(conn, part->id, + part->content_type, part->transfer_encoding, part->filename); + if (status != H_OK) { + log_error2("Send file failed. Status:%d", status); + httpc_free(conn); + xmlBufferFree(buffer); + return soap_ctx_new( + soap_env_new_with_fault(Fault_Client, + "MIME transport error while sending file","","")); + } + } + + res = httpc_mime_end(conn); + if (!res) + { + httpc_free(conn); + xmlBufferFree(buffer); + return soap_ctx_new( + soap_env_new_with_fault(Fault_Client, + "MIME transport error","","")); + } + } /* Free buffer */ xmlBufferFree(buffer); @@ -75,7 +213,11 @@ soap_client_invoke(SoapEnv *call, const char *url, const char *soap_action) /* TODO: If res == NULL, find out where and why it is NULL! */ doc = _soap_client_build_result(res); - return doc; + /* Create Context */ + ctx = soap_ctx_new(doc); + soap_ctx_add_files(ctx, res->attachments); + + return ctx; } @@ -84,6 +226,7 @@ SoapEnv* _soap_client_build_result(hresponse_t *res) { xmlDocPtr doc; SoapEnv *env; + char *buffer; log_verbose2("Building result (%p)", res); @@ -91,12 +234,13 @@ SoapEnv* _soap_client_build_result(hresponse_t *res) return soap_env_new_with_fault(Fault_Client, "Response is NULL","",""); - if (res->body == NULL) + + if (res->in == NULL) return soap_env_new_with_fault(Fault_Client, "Empty response from server!","",""); - +/* doc = xmlParseDoc(BAD_CAST res->body); if (doc == NULL) { return soap_env_new_with_fault(Fault_Client, @@ -104,6 +248,8 @@ SoapEnv* _soap_client_build_result(hresponse_t *res) } env = soap_env_new_from_doc(doc); +*/ + env = soap_env_new_from_stream(res->in); if (env == NULL) { xmlFreeDoc(doc); @@ -114,3 +260,11 @@ SoapEnv* _soap_client_build_result(hresponse_t *res) return env; } + +SoapCtx *soap_client_ctx_new(const char *urn, const char *method) +{ + SoapCtx *ctx = soap_ctx_new(soap_env_new_with_method(urn, method)); + + return ctx; +} + diff --git a/libcsoap/soap-client.h b/libcsoap/soap-client.h index 5c7cb64..439a96d 100644 --- a/libcsoap/soap-client.h +++ b/libcsoap/soap-client.h @@ -1,55 +1,57 @@ -/****************************************************************** - * $Id: soap-client.h,v 1.3 2004/08/30 15:26:53 snowdrop Exp $ - * - * CSOAP Project: A SOAP client/server library in C - * Copyright (C) 2003 Ferhat Ayaz - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - * - * Email: ayaz@jprogrammer.net - ******************************************************************/ -#ifndef cSOAP_CLIENT_H -#define cSOAP_CLIENT_H - -#include - +/****************************************************************** + * $Id: soap-client.h,v 1.4 2004/10/15 13:33:13 snowdrop Exp $ + * + * CSOAP Project: A SOAP client/server library in C + * Copyright (C) 2003 Ferhat Ayaz + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + * Email: ayaz@jprogrammer.net + ******************************************************************/ +#ifndef cSOAP_CLIENT_H +#define cSOAP_CLIENT_H + +#include +#include /** Initializes the client side soap engine */ int soap_client_init_args(int argc, char *argv[]); - -/** - Establish connection to the soap server and send - the given envelope. - - @param env envelope to send - @param url url to the soap server - @soap_action value for "SoapAction:" in the - HTTP request header. - - @returns the result envelope. In case of failure, - this function return an envelope with a fault object. - */ -SoapEnv* soap_client_invoke(SoapEnv *env, - const char *url, - const char *soap_action); - - -#endif - - + +/** + Establish connection to the soap server and send + the given envelope. + + @param env envelope to send + @param url url to the soap server + @soap_action value for "SoapAction:" in the + HTTP request header. + + @returns the result envelope. In case of failure, + this function return an envelope with a fault object. + */ +SoapCtx* soap_client_invoke(SoapCtx *ctx, + const char *url, + const char *soap_action); + + +SoapCtx *soap_client_ctx_new(const char *urn, const char *method); + +#endif + + diff --git a/libcsoap/soap-env.c b/libcsoap/soap-env.c index 9c28f73..68b5734 100644 --- a/libcsoap/soap-env.c +++ b/libcsoap/soap-env.c @@ -1,5 +1,5 @@ /****************************************************************** -* $Id: soap-env.c,v 1.6 2004/09/19 07:05:03 snowdrop Exp $ +* $Id: soap-env.c,v 1.7 2004/10/15 13:33:13 snowdrop Exp $ * * CSOAP Project: A SOAP client/server library in C * Copyright (C) 2003 Ferhat Ayaz @@ -52,6 +52,27 @@ Parameters: "" +/* +Parameters: +1- soap_env_ns +2- soap_env_enc +3- xsi_ns +4- xsd_ns +3- method name +4- uri +5- method name(again) +*/ +#define _SOAP_MSG_TEMPLATE_EMPTY_TARGET_ \ + "" \ + " "\ + " <%s xmlns=\"%s\">"\ + " " \ + " "\ + "" + + /* ---------------------------------------------------------------------------- */ /* XML Serializers (implemented at the and of this document) */ /* ---------------------------------------------------------------------------- */ @@ -135,16 +156,51 @@ soap_env_new_with_method (const char *urn, const char *method) log_verbose2 ("URN = '%s'", urn); log_verbose2 ("Method = '%s'", method); - xmlStrPrintf (buffer, 1054, BAD_CAST _SOAP_MSG_TEMPLATE_, - soap_env_ns, soap_env_enc, soap_xsi_ns, - soap_xsd_ns, BAD_CAST method, BAD_CAST urn, BAD_CAST method); - + if (!strcmp(urn, "")) + { + xmlStrPrintf (buffer, 1054, BAD_CAST _SOAP_MSG_TEMPLATE_EMPTY_TARGET_, + soap_env_ns, soap_env_enc, soap_xsi_ns, + soap_xsd_ns, BAD_CAST method, BAD_CAST urn, BAD_CAST method); + } + else + { + xmlStrPrintf (buffer, 1054, BAD_CAST _SOAP_MSG_TEMPLATE_, + soap_env_ns, soap_env_enc, soap_xsi_ns, + soap_xsd_ns, BAD_CAST method, BAD_CAST urn, BAD_CAST method); + + } env = xmlParseDoc (buffer); call = soap_env_new_from_doc (env); return call; } +static +int _soap_env_xml_io_read(void* ctx, char *buffer, int len) +{ + http_input_stream_t *in = (http_input_stream_t *)ctx; + if(!http_input_stream_is_ready(in)) + return 0; + return http_input_stream_read(in, buffer, len); +} + +static +int _soap_env_xml_io_close(void *ctx) +{ + /* do nothing */ + return 0; +} + +SoapEnv * +soap_env_new_from_stream(http_input_stream_t *in) +{ + xmlDocPtr doc; + + doc = xmlReadIO(_soap_env_xml_io_read, + _soap_env_xml_io_close, in, "", NULL, 0); + + return soap_env_new_from_doc (doc); +} xmlNodePtr @@ -175,6 +231,7 @@ soap_env_add_item (SoapEnv * call, const char *type, } + xmlNodePtr soap_env_add_itemf (SoapEnv * call, const char *type, const char *name, const char *format, ...) @@ -192,6 +249,32 @@ soap_env_add_itemf (SoapEnv * call, const char *type, } + +xmlNodePtr +soap_env_add_attachment(SoapEnv* call, const char *name, const char *href) +{ + xmlNodePtr newnode; + + newnode = xmlNewTextChild (call->cur, NULL, BAD_CAST name, BAD_CAST ""); + + if (newnode == NULL) + { + log_error1 ("Can not create new xml node"); + return NULL; + } + + if (href) + { + if (!xmlNewProp (newnode, BAD_CAST "href", BAD_CAST href)) + { + log_error1 ("Can not create new xml attribute"); + return NULL; + } + } + + return newnode; +} + void soap_env_add_custom (SoapEnv * call, void *obj, XmlSerializerCallback cb, const char *type, const char *name) @@ -336,6 +419,28 @@ soap_env_get_body (SoapEnv * env) } +xmlNodePtr +soap_env_get_fault(SoapEnv * env) +{ + xmlNodePtr node; + + + node = soap_env_get_body(env); + + if (!node) return NULL; + + while (node != NULL) + { + if (!xmlStrcmp (node->name, BAD_CAST "Fault")) + return node; + node = soap_xml_get_next (node); + } + +/* log_warn1 ("Node Fault tag found!");*/ + return NULL; +} + + xmlNodePtr soap_env_get_method (SoapEnv * env) { @@ -439,8 +544,13 @@ soap_env_find_urn (SoapEnv * env, char *urn) return 1; /* namespace found! */ } } + else + { + strcpy(urn,""); + log_warn1("No namespace found"); + return 1; + } - log_error1 ("No namespace found. Returning 0"); return 0; } diff --git a/libcsoap/soap-env.h b/libcsoap/soap-env.h index 4625890..5b3bd7f 100644 --- a/libcsoap/soap-env.h +++ b/libcsoap/soap-env.h @@ -1,5 +1,5 @@ /****************************************************************** - * $Id: soap-env.h,v 1.6 2004/09/02 11:48:28 rans Exp $ + * $Id: soap-env.h,v 1.7 2004/10/15 13:33:13 snowdrop Exp $ * * CSOAP Project: A SOAP client/server library in C * Copyright (C) 2003 Ferhat Ayaz @@ -26,6 +26,7 @@ #include #include +#include /** @@ -158,6 +159,11 @@ SoapEnv *soap_env_new_from_doc(xmlDocPtr doc); SoapEnv *soap_env_new_from_buffer(const char* buffer); +/** + Create an envelope from input stream +*/ +SoapEnv *soap_env_new_from_stream(http_input_stream_t *in); + /* --------------------------------------------------- */ /* XML Serializer functions and typedefs */ /* --------------------------------------------------- */ @@ -197,6 +203,26 @@ soap_env_add_item(SoapEnv* env, const char *type, const char *name, const char *value); +/** + Adds attachment href node to the envelope current parent. + +
+    
+   
+ + @param env The envelope object + @param name Name of the xml node + @param href href. A CID string filled by + soap_ctx_add_attachment() + + @returns The added xmlNode pointer. + + @see soap_ctx_add_file tutorial + */ +xmlNodePtr +soap_env_add_attachment(SoapEnv* env, const char *name, const char *href); + + /** Serialize and adds obj to the envelope. TODO: Document this function ! diff --git a/libcsoap/soap-server.c b/libcsoap/soap-server.c index f6fc08f..5fb4efe 100644 --- a/libcsoap/soap-server.c +++ b/libcsoap/soap-server.c @@ -1,5 +1,5 @@ /****************************************************************** -* $Id: soap-server.c,v 1.4 2004/08/30 13:22:04 snowdrop Exp $ +* $Id: soap-server.c,v 1.5 2004/10/15 13:33:13 snowdrop Exp $ * * CSOAP Project: A SOAP client/server library in C * Copyright (C) 2003 Ferhat Ayaz @@ -45,10 +45,13 @@ SoapRouterNode *router_node_new(SoapRouter *router, static SoapRouter *router_find(const char *context); +static +void _soap_server_send_ctx(httpd_conn_t* conn, SoapCtx *ctxres); + /*---------------------------------*/ void soap_server_entry(httpd_conn_t *conn, hrequest_t *req); static -void _soap_server_send_env(hsocket_t sock, SoapEnv* env); +void _soap_server_send_env(http_output_stream_t *out, SoapEnv* env); static void _soap_server_send_fault(httpd_conn_t *conn, hpair_t *header, const char* errmsg); @@ -109,34 +112,36 @@ void soap_server_entry(httpd_conn_t *conn, hrequest_t *req) char urn[150]; char method[150]; long received; - SoapEnv *env, *envres; + SoapCtx *ctx, *ctxres; SoapRouter *router; SoapService *service; + SoapEnv *env; - if (strcmp(req->method, "POST")) { + if (req->method != HTTP_REQUEST_POST) { - httpd_send_header(conn, 200, "OK", header); - hsocket_send(conn->sock, ""); - hsocket_send(conn->sock, "

Sorry!


"); - hsocket_send(conn->sock, "I only speak with 'POST' method"); - hsocket_send(conn->sock, ""); + httpd_send_header(conn, 200, "OK"); + http_output_stream_write_string(conn->out, ""); + http_output_stream_write_string(conn->out, "

Sorry!


"); + http_output_stream_write_string(conn->out, "I only speak with 'POST' method"); + http_output_stream_write_string(conn->out, ""); return; } - postdata = httpd_get_postdata(conn, req, &received, -1); +/* postdata = httpd_get_postdata(conn, req, &received, -1);*/ + env = soap_env_new_from_stream(req->in); header = hpairnode_new(HEADER_CONTENT_TYPE, "text/xml", NULL); - - if (postdata == NULL) { + if (env == NULL) { _soap_server_send_fault(conn, header,"Can not receive POST data!"); } else { - env = soap_env_new_from_buffer(postdata); + ctx = soap_ctx_new(env); + soap_ctx_add_files(ctx, req->attachments); - if (env == NULL) { + if (ctx->env == NULL) { _soap_server_send_fault(conn, header,"Can not parse POST data!"); @@ -152,17 +157,19 @@ void soap_server_entry(httpd_conn_t *conn, hrequest_t *req) } else { - if (!soap_env_find_urn(env, urn)) { + if (!soap_env_find_urn(ctx->env, urn)) { _soap_server_send_fault(conn, header, "No URN found!"); + soap_ctx_free(ctx); return; } else { log_verbose2("urn: '%s'", urn); } - if (!soap_env_find_methodname(env, method)) { + if (!soap_env_find_methodname(ctx->env, method)) { _soap_server_send_fault(conn, header, "No method found!"); + soap_ctx_free(ctx); return; }else { log_verbose2("method: '%s'", method); @@ -174,42 +181,90 @@ void soap_server_entry(httpd_conn_t *conn, hrequest_t *req) sprintf(buffer, "URN '%s' not found", urn); _soap_server_send_fault(conn, header, buffer); + soap_ctx_free(ctx); return; } else { log_verbose2("func: %p", service->func); - envres = service->func(env); - log_verbose2("func returned: (%p)", envres); - if (envres == NULL) { + /* ===================================== */ + /* CALL SERVICE FUNCTION */ + /* ===================================== */ + ctxres = service->func(ctx); + log_verbose2("func returned: (%p)", ctxres); + if (ctxres == NULL) { sprintf(buffer, "Service '%s' returned no envelope", urn); _soap_server_send_fault(conn, header, buffer); + soap_ctx_free(ctx); return; } else { - httpd_send_header(conn, 200, "OK", header); - _soap_server_send_env(conn->sock, envres); - /* free envres */ +/* httpd_send_header(conn, 200, "OK"); + _soap_server_send_env(conn->out, ctxres->env); +*/ + _soap_server_send_ctx(conn, ctxres); + /* free envctx */ + soap_ctx_free(ctxres); } } } } + soap_ctx_free(ctx); } } static -void _soap_server_send_env(hsocket_t sock, SoapEnv* env) +void _soap_server_send_ctx(httpd_conn_t* conn, SoapCtx *ctx) +{ + xmlBufferPtr buffer; + static int counter = 1; + char strbuffer[150]; + part_t *part; + + if (ctx->env == NULL || ctx->env->root == NULL) return; + + buffer = xmlBufferCreate(); +/* xmlIndentTreeOutput = 1;*/ + xmlThrDefIndentTreeOutput(1); +/* xmlKeepBlanksDefault(0);*/ + xmlNodeDump(buffer, ctx->env->root->doc, ctx->env->root, 1 ,1); + + if (ctx->attachments) + { + sprintf(strbuffer, "000128590350940924234%d", counter++); + httpd_mime_send_header(conn, strbuffer, "", "text/xml", 200, "OK"); + httpd_mime_next(conn, strbuffer, "text/xml", "binary"); + http_output_stream_write_string(conn->out, (const char*)xmlBufferContent(buffer)); + part = ctx->attachments->parts; + while (part) + { + httpd_mime_send_file(conn, part->id, part->content_type, part->transfer_encoding, part->filename); + part = part->next; + } + httpd_mime_end(conn); + } + else + { + httpd_send_header(conn, 200, "OK"); + http_output_stream_write_string(conn->out, (const char*)xmlBufferContent(buffer)); + } + xmlBufferFree(buffer); + +} + +static +void _soap_server_send_env(http_output_stream_t *out, SoapEnv* env) { xmlBufferPtr buffer; if (env == NULL || env->root == NULL) return; buffer = xmlBufferCreate(); xmlNodeDump(buffer, env->root->doc, env->root, 1 ,1); - hsocket_send(sock, (const char*)xmlBufferContent(buffer)); + http_output_stream_write_string(out, (const char*)xmlBufferContent(buffer)); xmlBufferFree(buffer); } @@ -219,11 +274,12 @@ void _soap_server_send_fault(httpd_conn_t *conn, hpair_t *header, const char* errmsg) { SoapEnv *envres; - httpd_send_header(conn, 500, "FAILED", header); + httpd_set_headers(conn, header); + httpd_send_header(conn, 500, "FAILED"); envres = soap_env_new_with_fault(Fault_Server, errmsg?errmsg:"General error", "cSOAP_Server", NULL); - _soap_server_send_env(conn->sock, envres); + _soap_server_send_env(conn->out, envres); } @@ -235,7 +291,7 @@ SoapRouterNode *router_node_new(SoapRouter *router, SoapRouterNode *next) { SoapRouterNode *node; - const char *noname = "/lost_find"; + const char *noname = "/lost_found"; node = (SoapRouterNode*)malloc(sizeof(SoapRouterNode)); if (context) { @@ -267,3 +323,8 @@ SoapRouter *router_find(const char* context) return NULL; } + + + + + diff --git a/libcsoap/soap-server.h b/libcsoap/soap-server.h index 8f0391b..13abd92 100644 --- a/libcsoap/soap-server.h +++ b/libcsoap/soap-server.h @@ -1,5 +1,5 @@ /****************************************************************** - * $Id: soap-server.h,v 1.2 2004/02/10 09:51:10 snowdrop Exp $ + * $Id: soap-server.h,v 1.3 2004/10/15 13:33:13 snowdrop Exp $ * * CSOAP Project: A SOAP client/server library in C * Copyright (C) 2003 Ferhat Ayaz @@ -26,6 +26,7 @@ #include #include +#include /** -- cgit v1.1-32-gdbae