]> sjero.net Git - linphone/commitdiff
Add XML2LPC lib/tool
authorYann Diorcet <yann.diorcet@belledonne-communications.com>
Thu, 13 Dec 2012 15:07:41 +0000 (16:07 +0100)
committerYann Diorcet <yann.diorcet@belledonne-communications.com>
Thu, 13 Dec 2012 15:08:43 +0000 (16:08 +0100)
Makefile.am
configure.ac
coreapi/lpconfig.h
share/Makefile.am
share/xml/Makefile.am [new file with mode: 0644]
share/xml/lpconfig.xsd [new file with mode: 0644]
tools/Makefile.am [new file with mode: 0644]
tools/xml2lpc.c [new file with mode: 0644]
tools/xml2lpc.h [new file with mode: 0644]
tools/xml2lpc_test.c [new file with mode: 0644]

index 7a9d755b2f0edf5b3a9246c7dfb67c656f3d100c..e15dae0700f39d2a332bd0876ffdb005607ba058 100644 (file)
@@ -4,7 +4,7 @@
 ACLOCAL_AMFLAGS = -I m4 $(ACLOCAL_MACOS_FLAGS)
 
 SUBDIRS = build m4 pixmaps po @ORTP_DIR@ @MS2_DIR@ \
-               coreapi console gtk share scripts
+               coreapi console gtk share scripts tools
 
 
 
index 97474be2eb6ce7b77fd64b83da39664e88c5cc51..1005ab2f598d11fbcb486437f22943fb5bd2ee30 100644 (file)
@@ -140,6 +140,33 @@ AC_ARG_ENABLE(console_ui,
         *) AC_MSG_ERROR(bad value ${enableval} for --enable-console_ui) ;;
       esac],[console_ui=true])
 
+dnl conditionnal build of tools.
+AC_ARG_ENABLE(tools,
+      [AS_HELP_STRING([--enable-tools=[yes/no]], [Turn on or off compilation of console interface (default=yes)])],
+      [case "${enableval}" in
+        yes) build_tools=true ;;
+        no)  build_tools=false ;;
+        *) AC_MSG_ERROR(bad value ${enableval} for --enable-tools) ;;
+      esac],[build_tools=check])
+
+dnl check libxml2 (needed for tools)
+if test "$build_tools" != "false" ; then
+       PKG_CHECK_MODULES(LIBXML2, [libxml-2.0],[],
+       [
+               if test "$build_tools" = "true" ; then
+                       AC_MSG_ERROR([Could not found libxml2, tools cannot be compiled.])
+               else
+                       build_tools=false
+               fi
+       ])
+fi
+
+AM_CONDITIONAL(BUILD_TOOLS, test x$build_tools != xfalse)
+if test "$build_tools" != "false" ; then
+   build_tools=true
+   AC_DEFINE(BUILD_TOOLS, 1, [Define if tools enabled] ) 
+fi
+
 dnl conditionnal build of gtk interface.
 AC_ARG_ENABLE(gtk_ui,
       [AS_HELP_STRING([--enable-gtk_ui=[yes/no]], [Turn on or off compilation of gtk interface (default=yes)])],
@@ -418,8 +445,10 @@ AC_ARG_ENABLE(portaudio,
 
 dnl build console if required
 AM_CONDITIONAL(BUILD_CONSOLE, test x$console_ui = xtrue)
+
 dnl special things for arm-linux cross compilation toolchain
 AM_CONDITIONAL(ARMBUILD, test x$use_arm_toolchain = xyes)
+
 dnl compilation of gtk user interface
 AM_CONDITIONAL(BUILD_GTK_UI, [test x$gtk_ui = xtrue ] )
 AM_CONDITIONAL(BUILD_WIN32, test x$mingw_found = xyes )
@@ -642,9 +671,11 @@ share/fr/Makefile
 share/it/Makefile
 share/ja/Makefile
 share/cs/Makefile
+share/xml/Makefile
 share/linphone.pc
 share/linphone.desktop
 scripts/Makefile
+tools/Makefile
 linphone.spec
 linphone.iss
 ])
@@ -657,6 +688,7 @@ printf "* Video support\t\t\t%s\n" $video
 printf "* GTK interface\t\t\t%s\n" $gtk_ui
 printf "* Account assistant\t\t%s\n" $build_wizard
 printf "* Console interface\t\t%s\n" $console_ui
+printf "* Tools\t\t\t\t%s\n" $build_tools
 printf "* zRTP encryption (GPLv3)\t%s\n" $zrtp
 
 if test "$enable_tunnel" = "true" ; then
index 8f3cae0a11bcbbd11bf401052ed4d6227bfb9dda..8e6f921283ea96c0a47d6d664973c7c6acd0babb 100644 (file)
@@ -25,6 +25,8 @@
 #ifndef LPCONFIG_H
 #define LPCONFIG_H
 
+#include <ortp/port.h>
+
 /**
  * The LpConfig object is used to manipulate a configuration file.
  * 
index 2f551f53d4c371ecdd18d13ce851c37b508c3543..83c3a934e295d593c0dac9b0404ccef6de5760aa 100644 (file)
@@ -1,5 +1,5 @@
 
-SUBDIRS=C fr it ja cs
+SUBDIRS=C fr it ja cs xml
 
 LINPHONE_SOUNDS=ringback.wav hello8000.wav hello16000.wav
 LINPHONE_RINGS=rings/orig.wav \
diff --git a/share/xml/Makefile.am b/share/xml/Makefile.am
new file mode 100644 (file)
index 0000000..c553a5c
--- /dev/null
@@ -0,0 +1 @@
+EXTRA_DIST=lpconfig.xsd
diff --git a/share/xml/lpconfig.xsd b/share/xml/lpconfig.xsd
new file mode 100644 (file)
index 0000000..49bb561
--- /dev/null
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" 
+               targetNamespace="http://www.linphone.org/xsds/lpconfig.xsd" 
+               xmlns:tns="http://www.linphone.org/xsds/lpconfig.xsd" 
+               elementFormDefault="qualified">
+
+    <xs:element name="config" type="tns:LPConfig"></xs:element>
+
+    <xs:complexType name="LPConfig">
+       <xs:sequence>
+               <xs:element name="section" type="tns:LPSection" minOccurs="0" maxOccurs="unbounded"></xs:element>
+       </xs:sequence>
+    </xs:complexType>
+    
+    <xs:complexType name="LPSection">
+       <xs:sequence>
+               <xs:element name="entry" type="tns:LPEntry" maxOccurs="unbounded" minOccurs="0">
+               </xs:element>
+       </xs:sequence>
+       <xs:attribute name="name" use="required">
+               <xs:simpleType>
+                       <xs:restriction base="xs:string">
+                               <xs:minLength value="1"></xs:minLength>
+                       </xs:restriction>
+               </xs:simpleType>
+       </xs:attribute>
+    </xs:complexType>
+
+    <xs:complexType name="LPEntry">
+       <xs:simpleContent>
+               <xs:extension base="xs:string">
+                       <xs:attribute name="overwrite" type="xs:boolean"
+                               use="optional" default="false">
+                       </xs:attribute>
+                       <xs:attribute name="name" use="required">
+                               <xs:simpleType>
+                                       <xs:restriction base="xs:string">
+                                               <xs:minLength value="1"></xs:minLength>
+                                       </xs:restriction>
+                               </xs:simpleType>
+                       </xs:attribute>
+               </xs:extension>
+       </xs:simpleContent>
+    </xs:complexType>
+</xs:schema>
diff --git a/tools/Makefile.am b/tools/Makefile.am
new file mode 100644 (file)
index 0000000..0c9f7e5
--- /dev/null
@@ -0,0 +1,31 @@
+## Process this file with automake to produce Makefile.in
+
+AM_CPPFLAGS=\
+       -I$(top_srcdir) \
+       -I$(top_srcdir)/coreapi \
+       -I$(top_srcdir)/exosip
+
+COMMON_CFLAGS=\
+       -DIN_LINPHONE \
+       $(LIBXML2_CFLAGS) \
+       $(ORTP_CFLAGS) \
+       $(STRICT_OPTIONS)
+
+if BUILD_TOOLS
+
+lib_LTLIBRARIES=libxml2lpc.la
+
+libxml2lpc_la_SOURCES=xml2lpc.c xml2lpc.h
+libxml2lpc_la_CFLAGS=$(COMMON_CFLAGS)
+libxml2lpc_la_LIBADD=\
+       $(LIBXML2_LIBS)
+
+bin_PROGRAMS=xml2lpc_test
+
+xml2lpc_test_SOURCES=xml2lpc_test.c
+xml2lpc_test_CFLAGS=$(COMMON_CFLAGS)
+xml2lpc_test_LDADD=$(top_builddir)/coreapi/liblinphone.la libxml2lpc.la
+
+endif
+
+
diff --git a/tools/xml2lpc.c b/tools/xml2lpc.c
new file mode 100644 (file)
index 0000000..ce12eeb
--- /dev/null
@@ -0,0 +1,341 @@
+/*
+linphone
+Copyright (C) 2012 Belledonne Communications SARL
+Yann DIORCET (yann.diorcet@linphone.org)
+
+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; either version 2
+of the License, or (at your option) any later version.
+
+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.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+*/
+
+#include "xml2lpc.h"
+#include <string.h>
+#include <libxml/xmlreader.h>
+
+
+#define XML2LPC_BZ 2048
+
+struct _xml2lpc_context {
+       LpConfig *lpc;
+       xml2lpc_function cbf;
+       void *ctx;
+       
+       xmlDoc *doc;
+       xmlDoc *xsd;
+       char errorBuffer[XML2LPC_BZ];
+       char warningBuffer[XML2LPC_BZ];
+};
+
+
+xml2lpc_context* xml2lpc_context_new(xml2lpc_function cbf, void *ctx) {
+       xml2lpc_context *xmlCtx = (xml2lpc_context*)malloc(sizeof(xml2lpc_context));
+       if(xmlCtx != NULL) {
+               xmlCtx->lpc = NULL;
+               xmlCtx->cbf = cbf;
+               xmlCtx->ctx = ctx;
+               
+               xmlCtx->doc = NULL;
+               xmlCtx->xsd = NULL;
+               xmlCtx->errorBuffer[0]='\0';
+               xmlCtx->warningBuffer[0]='\0';
+       }
+       return xmlCtx;
+}
+
+void xml2lpc_context_destroy(xml2lpc_context *ctx) {
+       if(ctx->doc != NULL) {
+               xmlFreeDoc(ctx->doc);
+               ctx->doc = NULL;
+       }
+       if(ctx->xsd != NULL) {
+               xmlFreeDoc(ctx->xsd);
+               ctx->xsd = NULL;
+       }
+       free(ctx);
+}
+
+void xml2lpc_context_clear_logs(xml2lpc_context *ctx) {
+       ctx->errorBuffer[0]='\0';
+       ctx->warningBuffer[0]='\0';
+}
+
+void xml2lpc_log(xml2lpc_context *xmlCtx, int level, const char *fmt, ...) {
+       va_list args;   
+       va_start(args, fmt);    
+       if(xmlCtx->cbf != NULL) {
+               xmlCtx->cbf((xmlCtx)->ctx, level, fmt, args);
+       }
+       va_end(args);
+}
+
+void xml2lpc_genericxml_error(void *ctx, const char *fmt, ...) {       
+       xml2lpc_context *xmlCtx = (xml2lpc_context *)ctx;
+       int sl = strlen(xmlCtx->errorBuffer);
+       va_list args;   
+       va_start(args, fmt);    
+       vsnprintf(xmlCtx->errorBuffer + sl, XML2LPC_BZ-sl, fmt, args);
+       va_end(args);
+}
+
+void xml2lpc_genericxml_warning(void *ctx, const char *fmt, ...) {     
+       xml2lpc_context *xmlCtx = (xml2lpc_context *)ctx;
+       int sl = strlen(xmlCtx->warningBuffer);
+       va_list args;   
+       va_start(args, fmt);    
+       vsnprintf(xmlCtx->warningBuffer + sl, XML2LPC_BZ-sl, fmt, args);
+       va_end(args);
+}
+
+static void dumpNodes(int level, xmlNode * a_node, xml2lpc_context *ctx) {
+    xmlNode *cur_node = NULL;
+
+    for (cur_node = a_node; cur_node; cur_node = cur_node->next) {
+        if (cur_node->type == XML_ELEMENT_NODE) {
+               xml2lpc_log(ctx, XML2LPC_DEBUG, "node level: %d type: Element, name: %s", level, cur_node->name);
+        } else {
+               xml2lpc_log(ctx, XML2LPC_DEBUG, "node level: %d type: %d, name: %s", level, cur_node->type, cur_node->name);
+        }
+
+        dumpNodes(level + 1, cur_node->children, ctx);
+    }
+}
+
+
+static void dumpNode(xmlNode *node, xml2lpc_context *ctx) {
+        xml2lpc_log(ctx, XML2LPC_DEBUG, "node type: %d, name: %s", node->type, node->name);
+}
+
+static void dumpAttr(xmlNode *node, xml2lpc_context *ctx) {
+        xml2lpc_log(ctx, XML2LPC_DEBUG, "attr name: %s value:%s", node->name, node->children->content);
+}
+
+static void dumpContent(xmlNode *node, xml2lpc_context *ctx) {
+        xml2lpc_log(ctx, XML2LPC_DEBUG, "content: %s", node->children->content);
+}
+
+static int processEntry(xmlElement *element, const char *sectionName, xml2lpc_context *ctx) {
+       xmlNode *cur_attr = NULL;
+       const char *name = NULL;
+       const char *value = NULL;
+       bool_t overwrite = FALSE;
+
+       for (cur_attr = (xmlNode *)element->attributes; cur_attr; cur_attr = cur_attr->next) {
+               dumpAttr(cur_attr, ctx);
+               if(strcmp((const char*)cur_attr->name, "name") == 0) {
+                       name = (const char*)cur_attr->children->content;
+               } else if(strcmp((const char*)cur_attr->name, "overwrite") == 0) {
+                       if(strcmp((const char*)cur_attr->children->content, "true") == 0) {
+                               overwrite = TRUE;
+                       }
+               }
+       }
+
+       value = (const char *)element->children->content;
+       dumpContent((xmlNode *)element, ctx);
+
+       if(name != NULL) {
+               const char *str = lp_config_get_string(ctx->lpc, sectionName, name, NULL);
+               if(str == NULL || overwrite) {
+                       xml2lpc_log(ctx, XML2LPC_MESSAGE, "Set %s|%s = %s",sectionName, name, value);
+                       lp_config_set_string(ctx->lpc, sectionName, name, value);
+               } else {
+                       xml2lpc_log(ctx, XML2LPC_MESSAGE, "Don't touch %s|%s = %s",sectionName, name, str);
+               }
+       } else {
+               xml2lpc_log(ctx, XML2LPC_WARNING, "ignored entry with no \"name\" attribute line:%d",xmlGetLineNo((xmlNode*)element));
+       }
+        return 0;
+}
+
+static int processSection(xmlElement *element, xml2lpc_context *ctx) {
+       xmlNode *cur_node = NULL;
+       xmlNode *cur_attr = NULL;
+       const char *name = NULL;
+
+       for (cur_attr = (xmlNode *)element->attributes; cur_attr; cur_attr = cur_attr->next) {
+               dumpAttr(cur_attr, ctx);
+               if(strcmp((const char*)cur_attr->name, "name") == 0) {
+                       name = (const char*)cur_attr->children->content;
+               }
+       }
+
+       if(name != NULL) {
+               for (cur_node = element->children; cur_node; cur_node = cur_node->next) {
+                       dumpNode(cur_node, ctx);
+                       if (cur_node->type == XML_ELEMENT_NODE) {
+                               if(strcmp((const char*)cur_node->name, "entry") == 0 ) {
+                                       processEntry((xmlElement*)cur_node, name, ctx);
+                               }
+                       }
+                       
+               }
+        } else {
+               xml2lpc_log(ctx, XML2LPC_WARNING, "ignored section with no \"name\" attribute, line:%d", xmlGetLineNo((xmlNode*)element));
+        }
+
+        return 0;
+}
+
+static int processConfig(xmlElement *element, xml2lpc_context *ctx) {
+       xmlNode *cur_node = NULL;
+
+       for (cur_node = element->children; cur_node; cur_node = cur_node->next) {
+               dumpNode(cur_node, ctx);
+               if (cur_node->type == XML_ELEMENT_NODE && 
+                       strcmp((const char*)cur_node->name, "section") == 0 ) {
+                       processSection((xmlElement*)cur_node, ctx);
+               }
+               
+        }
+       return 0;
+}
+
+static int processDoc(xmlNode *node, xml2lpc_context *ctx) {
+       dumpNode(node, ctx);
+       
+       if (node->type == XML_ELEMENT_NODE && 
+               strcmp((const char*)node->name, "config") == 0 ) {
+               processConfig((xmlElement*)node, ctx);
+       } else {
+               xml2lpc_log(ctx, XML2LPC_WARNING, "root element is not \"config\", line:%d", xmlGetLineNo(node));
+       }
+       return 0;
+}
+
+static int internal_convert_xml2lpc(xmlDoc *doc, xml2lpc_context *ctx) {
+       xml2lpc_log(ctx, XML2LPC_DEBUG, "Parse started");
+       xmlNode *rootNode = xmlDocGetRootElement(doc);
+       //dumpNodes(0, rootNode, cbf, ctx);
+        int ret = processDoc(rootNode, ctx);
+       xml2lpc_log(ctx, XML2LPC_DEBUG, "Parse ended ret:%d", ret);
+       return ret;
+}
+
+int xml2lpc_validate(xml2lpc_context *xmlCtx) {
+       xml2lpc_context_clear_logs(xmlCtx);
+       xmlSchemaValidCtxtPtr validCtx;
+       xmlSchemaParserCtxtPtr parserCtx = xmlSchemaNewDocParserCtxt(xmlCtx->xsd);
+       validCtx = xmlSchemaNewValidCtxt(xmlSchemaParse(parserCtx));
+       xmlSchemaSetValidErrors(validCtx, xml2lpc_genericxml_error, xml2lpc_genericxml_warning, xmlCtx);
+       int ret =  xmlSchemaValidateDoc(validCtx, xmlCtx->doc);
+       if(ret >0) {
+               xml2lpc_log(xmlCtx, XML2LPC_WARNING, "%s", xmlCtx->warningBuffer);
+               xml2lpc_log(xmlCtx, XML2LPC_ERROR, "%s", xmlCtx->errorBuffer);
+       } else {
+               xml2lpc_log(xmlCtx, XML2LPC_ERROR, "Internal error");
+       }
+       xmlSchemaFreeValidCtxt(validCtx);
+       return ret;
+}
+
+int xml2lpc_convert(xml2lpc_context *xmlCtx, LpConfig *lpc) {
+       xml2lpc_context_clear_logs(xmlCtx);
+       xmlCtx->lpc = lpc;
+       return internal_convert_xml2lpc(xmlCtx->doc, xmlCtx);
+}
+
+int xml2lpc_set_xml_file(xml2lpc_context* xmlCtx, const char *filename) {
+       xml2lpc_context_clear_logs(xmlCtx);
+       xmlSetGenericErrorFunc(xmlCtx, xml2lpc_genericxml_error);
+       if(xmlCtx->doc != NULL) {
+               xmlFreeDoc(xmlCtx->doc);
+               xmlCtx->doc = NULL;
+       }
+       xmlCtx->doc = xmlReadFile(filename, NULL, 0);
+       if(xmlCtx->doc == NULL) {
+               xml2lpc_log(xmlCtx, XML2LPC_ERROR, "Can't open/parse file \"%s\"", filename);
+               xml2lpc_log(xmlCtx, XML2LPC_ERROR, "%s", xmlCtx->errorBuffer);
+               return -1;
+       }
+       return 0;
+}
+
+int xml2lpc_set_xml_fd(xml2lpc_context* xmlCtx, int fd) {
+       xml2lpc_context_clear_logs(xmlCtx);
+       xmlSetGenericErrorFunc(xmlCtx, xml2lpc_genericxml_error);
+       if(xmlCtx->doc != NULL) {
+               xmlFreeDoc(xmlCtx->doc);
+               xmlCtx->doc = NULL;
+       }
+       xmlCtx->doc = xmlReadFd(fd, 0, NULL, 0);
+       if(xmlCtx->doc == NULL) {
+               xml2lpc_log(xmlCtx, XML2LPC_ERROR, "Can't open/parse fd \"%d\"", fd);
+               xml2lpc_log(xmlCtx, XML2LPC_ERROR, "%s", xmlCtx->errorBuffer);
+               return -1;
+       }
+       return 0;
+}
+
+int xml2lpc_set_xml_string(xml2lpc_context* xmlCtx, const char *content) {
+       xml2lpc_context_clear_logs(xmlCtx);
+       xmlSetGenericErrorFunc(xmlCtx, xml2lpc_genericxml_error);
+       if(xmlCtx->doc != NULL) {
+               xmlFreeDoc(xmlCtx->doc);
+               xmlCtx->doc = NULL;
+       }
+       xmlCtx->doc = xmlReadDoc((const unsigned char*)content, 0, NULL, 0);
+       if(xmlCtx->doc == NULL) {
+               xml2lpc_log(xmlCtx, XML2LPC_ERROR, "Can't parse string");
+               xml2lpc_log(xmlCtx, XML2LPC_ERROR, "%s", xmlCtx->errorBuffer);
+               return -1;
+       }
+       return 0;
+}
+
+int xml2lpc_set_xsd_file(xml2lpc_context* xmlCtx, const char *filename) {
+       xml2lpc_context_clear_logs(xmlCtx);
+       xmlSetGenericErrorFunc(xmlCtx, xml2lpc_genericxml_error);
+       if(xmlCtx->xsd != NULL) {
+               xmlFreeDoc(xmlCtx->xsd);
+               xmlCtx->xsd = NULL;
+       }
+       xmlCtx->xsd = xmlReadFile(filename, NULL, 0);
+       if(xmlCtx->xsd == NULL) {
+               xml2lpc_log(xmlCtx, XML2LPC_ERROR, "Can't open/parse file \"%s\"", filename);
+               xml2lpc_log(xmlCtx, XML2LPC_ERROR, "%s", xmlCtx->errorBuffer);
+               return -1;
+       }
+       return 0;
+}
+
+int xml2lpc_set_xsd_fd(xml2lpc_context* xmlCtx, int fd) {
+       xml2lpc_context_clear_logs(xmlCtx);
+       xmlSetGenericErrorFunc(xmlCtx, xml2lpc_genericxml_error);
+       if(xmlCtx->xsd != NULL) {
+               xmlFreeDoc(xmlCtx->xsd);
+               xmlCtx->xsd = NULL;
+       }
+       xmlCtx->xsd = xmlReadFd(fd, 0, NULL, 0);
+       if(xmlCtx->xsd == NULL) {
+               xml2lpc_log(xmlCtx, XML2LPC_ERROR, "Can't open/parse fd \"%d\"", fd);
+               xml2lpc_log(xmlCtx, XML2LPC_ERROR, "%s", xmlCtx->errorBuffer);
+               return -1;
+       }
+       return 0;
+}
+
+int xml2lpc_set_xsd_string(xml2lpc_context* xmlCtx, const char *content) {
+       xml2lpc_context_clear_logs(xmlCtx);
+       xmlSetGenericErrorFunc(xmlCtx, xml2lpc_genericxml_error);
+       if(xmlCtx->xsd != NULL) {
+               xmlFreeDoc(xmlCtx->xsd);
+               xmlCtx->xsd = NULL;
+       }
+       xmlCtx->xsd = xmlReadDoc((const unsigned char*)content, 0, NULL, 0);
+       if(xmlCtx->xsd == NULL) {
+               xml2lpc_log(xmlCtx, XML2LPC_ERROR, "Can't parse string");
+               xml2lpc_log(xmlCtx, XML2LPC_ERROR, "%s", xmlCtx->errorBuffer);
+               return -1;
+       }
+       return 0;
+}
\ No newline at end of file
diff --git a/tools/xml2lpc.h b/tools/xml2lpc.h
new file mode 100644 (file)
index 0000000..746fb02
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+linphone
+Copyright (C) 2012 Belledonne Communications SARL
+
+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; either version 2
+of the License, or (at your option) any later version.
+
+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.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+*/
+
+#ifndef XML2LPC_H_
+#define XML2LPC_H_
+
+#include "lpconfig.h"
+
+typedef struct _xml2lpc_context xml2lpc_context;
+
+typedef enum _xml2lpc_log_level {
+       XML2LPC_DEBUG = 0,
+       XML2LPC_MESSAGE,
+       XML2LPC_WARNING,
+       XML2LPC_ERROR
+} xml2lpc_log_level;
+
+typedef void(*xml2lpc_function)(void *ctx, xml2lpc_log_level level, const char *fmt, va_list list);
+
+xml2lpc_context* xml2lpc_context_new(xml2lpc_function cbf, void *ctx);
+void xml2lpc_context_destroy(xml2lpc_context*);
+
+int xml2lpc_set_xml_file(xml2lpc_context* context, const char *filename);
+int xml2lpc_set_xml_fd(xml2lpc_context* context, int fd);
+int xml2lpc_set_xml_string(xml2lpc_context* context, const char *content);
+
+int xml2lpc_set_xsd_file(xml2lpc_context* context, const char *filename);
+int xml2lpc_set_xsd_fd(xml2lpc_context* context, int fd);
+int xml2lpc_set_xsd_string(xml2lpc_context* context, const char *content);
+
+int xml2lpc_validate(xml2lpc_context *context);
+int xml2lpc_convert(xml2lpc_context *context, LpConfig *lpc);
+
+
+
+#endif //XML2LPC_H_
diff --git a/tools/xml2lpc_test.c b/tools/xml2lpc_test.c
new file mode 100644 (file)
index 0000000..cac2965
--- /dev/null
@@ -0,0 +1,72 @@
+/*
+linphone
+Copyright (C) 2012 Belledonne Communications SARL
+
+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; either version 2
+of the License, or (at your option) any later version.
+
+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.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+*/
+
+#include <stdio.h>
+#include "xml2lpc.h"
+
+void cb_function(void *ctx, xml2lpc_log_level level, const char *msg, va_list list) {
+       const char *header;
+       switch(level) {
+               case XML2LPC_DEBUG:
+                       header = "DEBUG";
+                       break;
+               case XML2LPC_MESSAGE:
+                       header = "MESSAGE";
+                       break;
+               case XML2LPC_WARNING:
+                       header = "WARNING";
+                       break;
+               case XML2LPC_ERROR:
+                       header = "ERROR";
+                       break;
+       }
+       fprintf(stdout, "%s - ", header);
+       vfprintf(stdout, msg, list);
+       fprintf(stdout, "\n");
+}
+
+void show_usage(int argc, char *argv[]) {
+       fprintf(stderr, "usage %s convert <xml_file> <lpc_file>\n"
+                       "      %s validate <xml_file> <xsd_file>\n", 
+                       argv[0], argv[0]);
+}
+
+int main(int argc, char *argv[]) {
+       if(argc != 4) {
+               show_usage(argc, argv);
+               return -1;
+       }
+       
+       xml2lpc_context *ctx = xml2lpc_context_new(cb_function, NULL);
+       xml2lpc_set_xml_file(ctx, argv[2]);
+       if(strcmp("convert", argv[1]) == 0) {
+               LpConfig *lpc = lp_config_new(argv[3]);
+               xml2lpc_convert(ctx, lpc);
+               lp_config_sync(lpc);
+               lp_config_destroy(lpc);
+       } else if(strcmp("validate", argv[1]) == 0) {
+               xml2lpc_set_xsd_file(ctx, argv[3]);
+               xml2lpc_validate(ctx);
+       } else {
+               show_usage(argc, argv);
+       }
+       xml2lpc_context_destroy(ctx);
+       return 0;
+}
+