3 Copyright (C) 2012 Belledonne Communications SARL
4 Yann DIORCET (yann.diorcet@linphone.org)
6 This program is free software; you can redistribute it and/or
7 modify it under the terms of the GNU General Public License
8 as published by the Free Software Foundation; either version 2
9 of the License, or (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23 #include <libxml/xmlsave.h>
24 #include <libxml/xmlversion.h>
26 #define LPC2XML_BZ 2048
28 struct _lpc2xml_context {
34 char errorBuffer[LPC2XML_BZ];
35 char warningBuffer[LPC2XML_BZ];
39 lpc2xml_context* lpc2xml_context_new(lpc2xml_function cbf, void *ctx) {
40 lpc2xml_context *xmlCtx = (lpc2xml_context*)malloc(sizeof(lpc2xml_context));
47 xmlCtx->errorBuffer[0]='\0';
48 xmlCtx->warningBuffer[0]='\0';
53 void lpc2xml_context_destroy(lpc2xml_context *ctx) {
54 if(ctx->doc != NULL) {
61 static void lpc2xml_context_clear_logs(lpc2xml_context *ctx) {
62 ctx->errorBuffer[0]='\0';
63 ctx->warningBuffer[0]='\0';
66 static void lpc2xml_log(lpc2xml_context *xmlCtx, int level, const char *fmt, ...) {
69 if(xmlCtx->cbf != NULL) {
70 xmlCtx->cbf((xmlCtx)->ctx, level, fmt, args);
75 static void lpc2xml_genericxml_error(void *ctx, const char *fmt, ...) {
76 lpc2xml_context *xmlCtx = (lpc2xml_context *)ctx;
77 int sl = strlen(xmlCtx->errorBuffer);
80 vsnprintf(xmlCtx->errorBuffer + sl, LPC2XML_BZ-sl, fmt, args);
85 static void lpc2xml_genericxml_warning(void *ctx, const char *fmt, ...) {
86 lpc2xml_context *xmlCtx = (lpc2xml_context *)ctx;
87 int sl = strlen(xmlCtx->warningBuffer);
90 vsnprintf(xmlCtx->warningBuffer + sl, LPC2XML_BZ-sl, fmt, args);
95 static int processEntry(const char *section, const char *entry, xmlNode *node, lpc2xml_context *ctx) {
96 const char *content = lp_config_get_string(ctx->lpc, section, entry, NULL);
98 lpc2xml_log(ctx->ctx, LPC2XML_ERROR, "Issue when reading the lpc");
102 lpc2xml_log(ctx, LPC2XML_MESSAGE, "Set %s|%s = %s", section, entry, content);
103 xmlNodeSetContent(node, (const xmlChar *) content);
107 struct __processSectionCtx {
111 lpc2xml_context *ctx;
114 static void processSection_cb(const char *entry, struct __processSectionCtx *ctx) {
116 xmlNode *node = xmlNewChild(ctx->node, NULL, (const xmlChar *)"entry", NULL);
118 lpc2xml_log(ctx->ctx, LPC2XML_ERROR, "Can't create \"entry\" element");
122 xmlAttr *name_attr = xmlSetProp(node, (const xmlChar *)"name", (const xmlChar *)entry);
123 if(name_attr == NULL) {
124 lpc2xml_log(ctx->ctx, LPC2XML_ERROR, "Can't create name attribute for \"entry\" element");
129 ctx->ret = processEntry(ctx->section, entry, node, ctx->ctx);
133 static int processSection(const char *section, xmlNode *node, lpc2xml_context *ctx) {
134 struct __processSectionCtx pc_ctx = {0, section, node, ctx};
135 lp_config_for_each_entry(ctx->lpc, section, (void (*)(const char *, void *))processSection_cb, (void*)&pc_ctx);
141 struct __processConfigCtx {
144 lpc2xml_context *ctx;
147 static void processConfig_cb(const char *section, struct __processConfigCtx *ctx) {
149 xmlNode *node = xmlNewChild(ctx->node, NULL, (const xmlChar *)"section", NULL);
151 lpc2xml_log(ctx->ctx, LPC2XML_ERROR, "Can't create \"section\" element");
155 xmlAttr *name_attr = xmlSetProp(node, (const xmlChar *)"name", (const xmlChar *)section);
156 if(name_attr == NULL) {
157 lpc2xml_log(ctx->ctx, LPC2XML_ERROR, "Can't create name attribute for \"section\" element");
161 ctx->ret = processSection(section, node, ctx->ctx);
165 static int processConfig(xmlNode *node, lpc2xml_context *ctx) {
166 struct __processConfigCtx pc_ctx = {0, node, ctx};
167 lp_config_for_each_section(ctx->lpc, (void (*)(const char *, void *))processConfig_cb, (void*)&pc_ctx);
171 static int processDoc(xmlDoc *doc, lpc2xml_context *ctx) {
173 xmlNode *root_node = xmlNewNode(NULL, (const xmlChar *)"config");
174 if(root_node == NULL) {
175 lpc2xml_log(ctx, LPC2XML_ERROR, "Can't create \"config\" element");
178 xmlNs *lpc_ns = xmlNewNs(root_node, (const xmlChar *)"http://www.linphone.org/xsds/lpconfig.xsd", NULL);
180 lpc2xml_log(ctx, LPC2XML_WARNING, "Can't create lpc namespace");
182 xmlSetNs(root_node, lpc_ns);
184 xmlNs *xsi_ns = xmlNewNs(root_node, (const xmlChar *)"http://www.w3.org/2001/XMLSchema-instance", (const xmlChar *)"xsi");
186 lpc2xml_log(ctx, LPC2XML_WARNING, "Can't create xsi namespace");
188 xmlAttr *schemaLocation = xmlNewNsProp(root_node, xsi_ns, (const xmlChar *)"schemaLocation", (const xmlChar *)"http://www.linphone.org/xsds/lpconfig.xsd lpconfig.xsd");
189 if(schemaLocation == NULL) {
190 lpc2xml_log(ctx, LPC2XML_WARNING, "Can't create schemaLocation");
192 ret = processConfig(root_node, ctx);
193 xmlDocSetRootElement(doc, root_node);
197 static int internal_convert_lpc2xml(lpc2xml_context *ctx) {
199 lpc2xml_log(ctx, LPC2XML_DEBUG, "Generation started");
200 if(ctx->doc != NULL) {
201 xmlFreeDoc(ctx->doc);
204 xmlDoc *doc = xmlNewDoc((const xmlChar *)"1.0");
205 ret = processDoc(doc, ctx);
211 lpc2xml_log(ctx, LPC2XML_DEBUG, "Generation ended ret:%d", ret);
215 int lpc2xml_set_lpc(lpc2xml_context* context, const LpConfig *lpc) {
220 int lpc2xml_convert_file(lpc2xml_context* context, const char *filename) {
222 lpc2xml_context_clear_logs(context);
223 xmlSetGenericErrorFunc(context, lpc2xml_genericxml_error);
224 xmlSaveCtxtPtr save_ctx = xmlSaveToFilename(filename, "UTF-8", XML_SAVE_FORMAT);
225 if(save_ctx != NULL) {
226 ret = internal_convert_lpc2xml(context);
228 ret = xmlSaveDoc(save_ctx, context->doc);
230 lpc2xml_log(context, LPC2XML_ERROR, "Can't save document");
231 lpc2xml_log(context, LPC2XML_ERROR, "%s", context->errorBuffer);
234 xmlSaveClose(save_ctx);
236 lpc2xml_log(context, LPC2XML_ERROR, "Can't open file:%s", filename);
237 lpc2xml_log(context, LPC2XML_ERROR, "%s", context->errorBuffer);
242 int lpc2xml_convert_fd(lpc2xml_context* context, int fd) {
244 lpc2xml_context_clear_logs(context);
245 xmlSetGenericErrorFunc(context, lpc2xml_genericxml_error);
246 xmlSaveCtxtPtr save_ctx = xmlSaveToFd(fd, "UTF-8", XML_SAVE_FORMAT);
247 if(save_ctx != NULL) {
248 ret = internal_convert_lpc2xml(context);
250 ret = xmlSaveDoc(save_ctx, context->doc);
252 lpc2xml_log(context, LPC2XML_ERROR, "Can't save document");
253 lpc2xml_log(context, LPC2XML_ERROR, "%s", context->errorBuffer);
256 xmlSaveClose(save_ctx);
258 lpc2xml_log(context, LPC2XML_ERROR, "Can't open fd:%d", fd);
259 lpc2xml_log(context, LPC2XML_ERROR, "%s", context->errorBuffer);
264 int lpc2xml_convert_string(lpc2xml_context* context, char **content) {
266 xmlBufferPtr buffer = xmlBufferCreate();
267 lpc2xml_context_clear_logs(context);
268 xmlSetGenericErrorFunc(context, lpc2xml_genericxml_error);
269 xmlSaveCtxtPtr save_ctx = xmlSaveToBuffer(buffer, "UTF-8", XML_SAVE_FORMAT);
270 if(save_ctx != NULL) {
271 ret = internal_convert_lpc2xml(context);
273 ret = xmlSaveDoc(save_ctx, context->doc);
275 lpc2xml_log(context, LPC2XML_ERROR, "Can't save document");
276 lpc2xml_log(context, LPC2XML_ERROR, "%s", context->errorBuffer);
279 xmlSaveClose(save_ctx);
281 lpc2xml_log(context, LPC2XML_ERROR, "Can't initialize internal buffer");
282 lpc2xml_log(context, LPC2XML_ERROR, "%s", context->errorBuffer);
285 #if LIBXML_VERSION >= 20800
286 *content = (char *)xmlBufferDetach(buffer);
288 *content = strdup((const char *)xmlBufferContent(buffer));
291 xmlBufferFree(buffer);