SILC currently supports SOCKS4 and SOCKS5 but it needs to be compiled
in separately.
+ o Add silc_xml_parse_stream to parse SilcStream XML stream.
+
+ o SILC XML API (wrapper to expat). (***DONE)
+
o Bring silchttp HTTP server library to SRT. (***DONE)
o Simple SILC Rand API for pseudo-random numbers. (***DONE)
rwlock implementation using atomic operations.) not for now.
-SILC XML Library, lib/silcxml/
-==============================
-
- o SILC XML API (wrapper to expat). Look at the expat API and simplify
- it. The SILC XML API should have at most 8-10 API functions. It should
- be possible to create full XML parser with only one function. And, it
- should be possible to have a function that is able to parse an entire
- XML document. It should also have a parser function to be able to
- parse a stream of XML data (SilcStream). It MUST NOT have operations
- that require multiple function calls to be able to execute that one
- operation (like creating parser).
-
-
Windows Support
===============
fi
+# Check for Expat
+AC_ARG_WITH(expat,
+ [[ --with-expat[=DIR] use Expat XML [search in DIR/include and DIR/lib]]],
+ [
+ case "${withval}" in
+ no)
+ ;;
+ *)
+ if test -d $withval/include; then
+ CPPFLAGS="$CPPFLAGS -I$withval/include"
+ CFLAGS="$CFLAGS -I$withval/include"
+ fi
+ if test -d $withval/lib; then
+ LDFLAGS="$LDFLAGS -L$withval/lib"
+ fi
+ ;;
+ esac
+ ])
+
+AC_CHECK_HEADERS(expat.h,
+ [ LIBS="$LIBS -lexpat" ],
+ [ AC_MSG_ERROR(Expat XML Library is required to compile SRT) ])
+
+
##
## Native WIN32 compilation under cygwin
##
silcthreadqueue.c \
silcrand.c \
silcglobal.c \
- silcbufferstream.c
+ silcbufferstream.c \
+ silcxml.c
include_HEADERS = \
$(SILC_DIST_HEADER) \
silcglobal.h \
silcruntime.h \
silcdir.h \
- silcbufferstream.h
+ silcbufferstream.h \
+ silcxml.h
SILC_EXTRA_DIST =
#endif /* __SILC_ENABLE_STACKTRACE */
/* SILC Runtime Toolkit includes */
-#include <silcerrno.h>
#include <silctypes.h>
+#include <silcerrno.h>
#include <silcbitops.h>
#include <silcmutex.h>
#include <silcatomic.h>
#include <silcmime.h>
#include <silcrand.h>
#include <silcbufferstream.h>
+#include <silcxml.h>
#include <silchttpserver.h>
#include <silchttpphp.h>
--- /dev/null
+/*
+
+ silcxml.c
+
+ Author: Pekka Riikonen <priikone@silcnet.org>
+
+ Copyright (C) 2008 Pekka Riikonen
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; version 2 of the License.
+
+ This program 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 General Public License for more details.
+
+*/
+
+#include <silcruntime.h>
+
+/* XML parser context */
+struct SilcXMLParserStruct {
+ void *parser; /* Parser implementation */
+ SilcXMLParserHandlerStruct handler; /* Handler */
+ void *context; /* User context */
+ SilcXMLParamsStruct params; /* Parser parameters */
+};
+
+#ifdef HAVE_EXPAT_H
+
+#include <expat.h>
+
+/* Map expat error to silc_errno */
+
+static SilcResult silc_xml_expat_error(XML_Parser parser)
+{
+ enum XML_Error error = XML_GetErrorCode(parser);
+
+ switch (error) {
+ case XML_ERROR_NONE:
+ return SILC_OK;
+ case XML_ERROR_NO_MEMORY:
+ return SILC_ERR_OUT_OF_MEMORY;
+ case XML_ERROR_UNKNOWN_ENCODING:
+ case XML_ERROR_INCORRECT_ENCODING:
+ return SILC_ERR_BAD_ENCODING;
+ case XML_ERROR_ABORTED:
+ return SILC_ERR_ABORTED;
+ default:
+ return SILC_ERR_SYNTAX;
+ }
+}
+
+/* Return error string */
+
+static const char *silc_xml_get_error(SilcXMLParser parser)
+{
+ return XML_ErrorString(XML_GetErrorCode(parser->parser));
+}
+
+/* Start element */
+
+static void silc_xml_expat_start_element(void *userData,
+ const XML_Char *name,
+ const XML_Char **atts)
+{
+ SilcXMLParser parser = userData;
+ SilcHashTable t = NULL;
+ int i;
+
+ if (atts && atts[0]) {
+ t = silc_hash_table_alloc(NULL, 0, silc_hash_utf8_string, NULL,
+ silc_hash_utf8_compare, NULL,
+ NULL, NULL, TRUE);
+ if (!t) {
+ silc_set_errno(SILC_ERR_OUT_OF_MEMORY);
+ silc_set_errno_location(NULL,
+ XML_GetCurrentLineNumber(parser->parser),
+ XML_GetCurrentColumnNumber(parser->parser));
+ XML_StopParser(parser->parser, FALSE);
+ return;
+ }
+
+ for (i = 0; atts[i]; i += 2)
+ silc_hash_table_add(t, (void *)atts[i], (void *)atts[i + 1]);
+ }
+
+ if (parser->handler.start_element)
+ parser->handler.start_element(parser, name, t, parser->context);
+
+ if (t)
+ silc_hash_table_free(t);
+}
+
+/* End element */
+
+static void silc_xml_expat_end_element(void *userData,
+ const XML_Char *name)
+{
+ SilcXMLParser parser = userData;
+
+ if (parser->handler.end_element)
+ parser->handler.end_element(parser, name, parser->context);
+}
+
+/* Characters */
+
+static void silc_xml_expat_data(void *userData,
+ const XML_Char *s,
+ int len)
+
+{
+ SilcXMLParser parser = userData;
+
+ if (parser->handler.data)
+ parser->handler.data(parser, (const unsigned char *)s,
+ (SilcUInt32)len, parser->context);
+}
+
+/* Processing instruction */
+
+static void silc_xml_expat_pi(void *userData,
+ const XML_Char *target,
+ const XML_Char *data)
+{
+ SilcXMLParser parser = userData;
+
+ if (parser->handler.pi)
+ parser->handler.pi(parser, target, data, parser->context);
+}
+
+/* Create parser */
+
+SilcXMLParser silc_xml_parser_create(SilcXMLParams params,
+ SilcXMLParserHandler handler,
+ void *context)
+{
+ SilcXMLParser parser;
+ XML_Parser ep;
+
+ parser = silc_calloc(1, sizeof(*parser));
+ if (!parser)
+ return NULL;
+
+ SILC_LOG_DEBUG(("Allcoated XML parser %p", parser));
+
+ if (params)
+ parser->params = *params;
+ if (handler)
+ parser->handler = *handler;
+ parser->context = context;
+
+ /* Allocate expat parser */
+ if (parser->params.no_namespace)
+ ep = XML_ParserCreate("UTF-8");
+ else
+ ep = XML_ParserCreateNS("UTF-8", '\0');
+
+ if (!ep) {
+ silc_set_errno(SILC_ERR_OUT_OF_MEMORY);
+ silc_free(ep);
+ return NULL;
+ }
+
+ parser->parser = ep;
+
+ /* Set callbacks */
+ XML_SetUserData(ep, parser);
+ XML_SetElementHandler(ep, silc_xml_expat_start_element,
+ silc_xml_expat_end_element);
+ XML_SetCharacterDataHandler(ep, silc_xml_expat_data);
+ XML_SetProcessingInstructionHandler(ep, silc_xml_expat_pi);
+
+ return parser;
+}
+
+/* Free parser */
+
+void silc_xml_parser_free(SilcXMLParser parser)
+{
+ if (!parser)
+ return;
+
+ SILC_LOG_DEBUG(("Free XML parser %p", parser));
+
+ if (parser->parser)
+ XML_ParserFree(parser->parser);
+ silc_free(parser);
+}
+
+/* Parse */
+
+SilcBool silc_xml_parse(SilcXMLParser parser,
+ const unsigned char *data,
+ SilcUInt32 data_len)
+{
+ int ret;
+
+ SILC_LOG_DEBUG(("Parse XML data with parser %p", parser));
+
+ if (!parser || !data) {
+ silc_set_errno(SILC_ERR_INVALID_ARGUMENT);
+ return FALSE;
+ }
+
+ /* Parse */
+ ret = XML_Parse(parser->parser, (const char *)data, (int)data_len, 1);
+ if (!ret) {
+ silc_set_errno_reason(silc_xml_expat_error(parser->parser),
+ silc_xml_get_error(parser));
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+/* Parse file */
+
+SilcBool silc_xml_parse_file(SilcXMLParser parser,
+ const char *filename)
+{
+ unsigned char *data;
+ SilcUInt32 data_len;
+ SilcBool ret;
+
+ if (!filename) {
+ silc_set_errno(SILC_ERR_INVALID_ARGUMENT);
+ return FALSE;
+ }
+
+ SILC_LOG_DEBUG(("Parse XML file '%s' with parser %p", filename, parser));
+
+ data = silc_file_readfile(filename, &data_len, NULL);
+ if (!data)
+ return FALSE;
+
+ ret = silc_xml_parse(parser, data, data_len);
+ if (!ret) {
+ silc_set_errno_reason(silc_xml_expat_error(parser->parser),
+ silc_xml_get_error(parser));
+ silc_set_errno_location(filename,
+ XML_GetCurrentLineNumber(parser->parser),
+ XML_GetCurrentColumnNumber(parser->parser));
+ return FALSE;
+ }
+
+ silc_free(data);
+
+ return ret;
+}
+
+/* Get attribute */
+
+const char *silc_xml_get_attribute(SilcXMLParser parser,
+ SilcHashTable attributes,
+ const char *name)
+{
+ char *val;
+
+ if (!attributes)
+ return NULL;
+
+ if (!silc_hash_table_find(attributes, (void *)name, NULL, (void *)&val))
+ return NULL;
+
+ return val;
+}
+
+/* Return current location */
+
+void silc_xml_current_location(SilcXMLParser parser,
+ SilcUInt32 *current_line,
+ SilcUInt32 *current_column)
+{
+ if (current_line)
+ *current_line = XML_GetCurrentLineNumber(parser->parser);
+ if (current_column)
+ *current_column = XML_GetCurrentColumnNumber(parser->parser);
+}
+
+#endif /* HAVE_EXPAT_H */
--- /dev/null
+/*
+
+ silcxml.h
+
+ Author: Pekka Riikonen <priikone@silcnet.org>
+
+ Copyright (C) 2008 Pekka Riikonen
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; version 2 of the License.
+
+ This program 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 General Public License for more details.
+
+*/
+
+/****h* silcutil/XML Interface
+ *
+ * DESCRIPTION
+ *
+ * XML parser interface provides simple stream based interface for parsing
+ * XML data and files.
+ *
+ * EXAMPLE
+ *
+ * SilcXMLParser parser;
+ *
+ * // Create XML parser
+ * parser = silc_xml_parser_create(NULL, &handler, ctx);
+ *
+ * // Parse XML file
+ * if (!silc_xml_parse_file(parser, filename)) {
+ * silc_errno_location(NULL, &cur_line, NULL);
+ * fatal("Error %s:%d: %s", filename, cur_line, silc_errno_reason());
+ * }
+ *
+ * // Free parser
+ * silc_xml_parser_free(parser);
+ *
+ ***/
+
+#ifndef SILCXML_H
+#define SILCXML_H
+
+/****s* silcutil/SilcXMLParser
+ *
+ * NAME
+ *
+ * typedef struct SilcXMLParserStruct *SilcXMLParser;
+ *
+ * DESCRIPTION
+ *
+ * The XLM parser context allocated by silc_xml_parser_create. It is
+ * freed by calling silc_xml_parser_free.
+ *
+ ***/
+typedef struct SilcXMLParserStruct *SilcXMLParser;
+
+/****s* silcutil/SilcXMLParserHandler
+ *
+ * NAME
+ *
+ * typedef struct SilcXMLParserHandlerObject { ... }
+ * SilcXMLParserHandler, SilcXMLParserHandlerStruct;
+ *
+ * DESCRIPTION
+ *
+ * The XML parser handler function callbacks are declared in this
+ * structure. The structure is given as argument to the
+ * silc_xml_parser_create.
+ *
+ * SOURCE
+ */
+typedef struct SilcXMLParserHandlerObject {
+ /* Called at the start of an XML element. The `name' is the element name.
+ The `attributes' is the element attributes or NULL if there were no
+ attributes. The `attributes' may be enumerated using the SilcHashTable
+ API. The silc_xml_get_attribute can be used to retrieve the attribute
+ values from the `attributes' by their name. */
+ void (*start_element)(SilcXMLParser parser,
+ const char *name,
+ SilcHashTable attributes,
+ void *context);
+
+ /* Called and the end of an XML element. The `name' is the element name. */
+ void (*end_element)(SilcXMLParser parser,
+ const char *name,
+ void *context);
+
+ /* Called to deliver the characters or whatever data is in the element. */
+ void (*data)(SilcXMLParser parser,
+ const unsigned char *data,
+ SilcUInt32 data_len,
+ void *context);
+
+ /* Called to deliver a processing instruction. The `target' is the first
+ word in the processing instruction. The `data' is the rest of the
+ characters in it skipping all whitespace after the initial word. This
+ callback may be NULL if it is not needed. */
+ void (*pi)(SilcXMLParser parser,
+ const char *target,
+ const char *data,
+ void *context);
+} *SilcXMLParserHandler, SilcXMLParserHandlerStruct;
+/***/
+
+/****s* silcutil/SilcXMLParams
+ *
+ * NAME
+ *
+ * typedef struct SilcXMLParamsObject { ... }
+ * *SilcXMLParams, SilcXMLParamsStruct;
+ *
+ * DESCRIPTION
+ *
+ * The XML parser parameters that can be give as argument to the
+ * silc_xml_parser_create.
+ *
+ * SOURCE
+ */
+typedef struct SilcXMLParamsObject {
+ /* Do not process XML namespaces. */
+ SilcBool no_namespace;
+} *SilcXMLParams, SilcXMLParamsStruct;
+
+/****f* silcutil/silc_xml_parser_create
+ *
+ * SYNOPSIS
+ *
+ * SilcXMLParser silc_xml_parser_create(SilcXMLParams params,
+ * SilcXMLParserHandler handler,
+ * void *context);
+ *
+ * DESCRIPTION
+ *
+ * Create XML parser and return in. The `handler' contains the callback
+ * functions to be called while parsing XML data. The `context' is
+ * delivered to each callback function. The `params' define parser
+ * parameters, and may be NULL. The parser parses XML data with UTF-8
+ * encoding. All characters delivered to callbacks are in UTF-8 encoding.
+ *
+ ***/
+SilcXMLParser silc_xml_parser_create(SilcXMLParams params,
+ SilcXMLParserHandler handler,
+ void *context);
+
+/****f* silcutil/silc_xml_parser_free
+ *
+ * SYNOPSIS
+ *
+ * void silc_xml_parser_free(SilcXMLParser parser);
+ *
+ * DESCRIPTION
+ *
+ * Free's XML parser.
+ *
+ ***/
+void silc_xml_parser_free(SilcXMLParser parser);
+
+/****f* silcutil/silc_xml_parse
+ *
+ * SYNOPSIS
+ *
+ * SilcBool silc_xml_parse(SilcXMLParser parser,
+ * const unsigned char *data,
+ * SilcUInt32 data_len);
+ *
+ * DESCRIPTION
+ *
+ * Parse XML data `data' of length of `data_len' bytes. Returns TRUE
+ * after the data has been parsed. The handler callback functions set for
+ * `parser' will be called while parsing the XML data.
+ *
+ * Returns FALSE and set silc_errno and silc_errno_reason if error
+ * occurs.
+ *
+ ***/
+SilcBool silc_xml_parse(SilcXMLParser parser,
+ const unsigned char *data,
+ SilcUInt32 data_len);
+
+/****f* silcutil/silc_xml_parse_file
+ *
+ * SYNOPSIS
+ *
+ * SilcBool silc_xml_parse_file(SilcXMLParser parser,
+ * const char *filename);
+ *
+ * DESCRIPTION
+ *
+ * Parse XML file indicated by `filename'. Returns TRUE after the file
+ * has been parsed. The handler callback functions set for `parser' will
+ * be called while parsing the XML file.
+ *
+ * Returns FALSE and set silc_errno and silc_errno_reason if error
+ * occurs. The silc_errno_location can be used to retrieve the exact
+ * location in the file where the error occurred.
+ *
+ ***/
+SilcBool silc_xml_parse_file(SilcXMLParser parser,
+ const char *filename);
+
+/****f* silcutil/silc_xml_get_attribute
+ *
+ * SYNOPSIS
+ *
+ * const char *silc_xml_get_attribute(SilcXMLParser parser,
+ * SilcHashTable attributes,
+ * const char *name);
+ *
+ * DESCRIPTION
+ *
+ * Returns the value of the attributes namaed `name' or NULL if no such
+ * attribute exist in the hash table of `attributes'.
+ *
+ ***/
+const char *silc_xml_get_attribute(SilcXMLParser parser,
+ SilcHashTable attributes,
+ const char *name);
+
+/****f* silcutil/silc_xml_get_attribute
+ *
+ * SYNOPSIS
+ *
+ * void silc_xml_current_location(SilcXMLParser parser,
+ * SilcUInt32 *current_line,
+ * SilcUInt32 *current_column);
+ *
+ * DESCRIPTION
+ *
+ * Return the current location of the parsed XML data. The current line
+ * number and columns can be returned. This may be used also when an
+ * error occurs but it is preferred to use silc_errno_location in case
+ * of error.
+ *
+ ***/
+void silc_xml_current_location(SilcXMLParser parser,
+ SilcUInt32 *current_line,
+ SilcUInt32 *current_column);
+
+#endif /* SILCXML_H */
test_silcatomic test_silcmutex test_silctime test_silcthread \
test_silcdll test_silcenv test_silctimer test_silcbitops \
test_silcregex test_silcbuffmt test_silcdir test_silcthreadqueue \
- test_silcrand test_silcglobal test_silcbufferstream
+ test_silcrand test_silcglobal test_silcbufferstream test_silcxml
TESTS = test_silcstrutil test_silcstringprep test_silchashtable \
test_silclist test_silcfsm test_silcasync test_silcschedule \
--- /dev/null
+/* SILC XML tests */
+
+#include "silcruntime.h"
+
+SilcXMLParser parser;
+SilcBool success = FALSE;
+
+static void xml_start_element(SilcXMLParser parser,
+ const char *name,
+ SilcHashTable attributes,
+ void *context)
+{
+ fprintf(stderr, "<%s", name);
+
+ if (attributes) {
+ SilcHashTableList htl;
+ char *att, *val;
+
+ silc_hash_table_list(attributes, &htl);
+ while (silc_hash_table_get(&htl, (void *)&att, (void *)&val))
+ fprintf(stderr, " %s='%s'", att, val);
+
+ silc_hash_table_list_reset(&htl);
+ }
+ fprintf(stderr, ">");
+}
+
+static void xml_end_element(SilcXMLParser parser,
+ const char *name,
+ void *context)
+{
+ fprintf(stderr, "</%s>", name);
+}
+
+static void xml_data(SilcXMLParser parser,
+ const unsigned char *data,
+ SilcUInt32 data_len,
+ void *context)
+{
+ silc_file_write(2, data, data_len);
+}
+
+static void xml_pi(SilcXMLParser parser,
+ const char *target,
+ const char *data,
+ void *context)
+{
+ fprintf(stderr, "%s %s", target, data);
+}
+
+static SilcXMLParserHandlerStruct handler =
+{
+ xml_start_element,
+ xml_end_element,
+ xml_data,
+ xml_pi
+};
+
+int main(int argc, char **argv)
+{
+ SilcXMLParamsStruct params;
+ SilcUInt32 cur_line;
+ char *file;
+
+ silc_runtime_init();
+
+ if (argc != 2) {
+ fprintf(stderr, "Usage: test_silcxml <filename>\n");
+ goto err;
+ }
+
+ memset(¶ms, 0, sizeof(params));
+ parser = silc_xml_parser_create(¶ms, &handler, NULL);
+ if (!parser)
+ goto err;
+
+ if (!silc_xml_parse_file(parser, argv[1])) {
+ silc_errno_location(&file, &cur_line, NULL);
+ fprintf(stderr, "%s:%d: %s\n", file, cur_line, silc_errno_reason());
+ goto err;
+ }
+
+ silc_xml_parser_free(parser);
+
+ success = TRUE;
+
+ err:
+ SILC_LOG_DEBUG(("Testing was %s", success ? "SUCCESS" : "FAILURE"));
+ fprintf(stderr, "Testing was %s\n", success ? "SUCCESS" : "FAILURE");
+
+ silc_runtime_uninit();
+
+ return !success;
+}