]> sjero.net Git - linphone/blob - tools/lpc2xml.c
Add check in lpc2xml
[linphone] / tools / lpc2xml.c
1 /*
2 linphone
3 Copyright (C) 2012 Belledonne Communications SARL
4 Yann DIORCET (yann.diorcet@linphone.org)
5
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.
10
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.
15
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.
19 */
20
21 #include "lpc2xml.h"
22 #include <string.h>
23 #include <libxml/xmlsave.h>
24 #include <libxml/xmlversion.h>
25
26 #define LPC2XML_BZ 2048
27
28 struct _lpc2xml_context {
29         const LpConfig *lpc;
30         lpc2xml_function cbf;
31         void *ctx;
32         
33         xmlDoc *doc;
34         char errorBuffer[LPC2XML_BZ];
35         char warningBuffer[LPC2XML_BZ];
36 };
37
38
39 lpc2xml_context* lpc2xml_context_new(lpc2xml_function cbf, void *ctx) {
40         lpc2xml_context *xmlCtx = (lpc2xml_context*)malloc(sizeof(lpc2xml_context));
41         if(xmlCtx != NULL) {
42                 xmlCtx->lpc = NULL;
43                 xmlCtx->cbf = cbf;
44                 xmlCtx->ctx = ctx;
45                 
46                 xmlCtx->doc = NULL;
47                 xmlCtx->errorBuffer[0]='\0';
48                 xmlCtx->warningBuffer[0]='\0';
49         }
50         return xmlCtx;
51 }
52
53 void lpc2xml_context_destroy(lpc2xml_context *ctx) {
54         if(ctx->doc != NULL) {
55                 xmlFreeDoc(ctx->doc);
56                 ctx->doc = NULL;
57         }
58         free(ctx);
59 }
60
61 static void lpc2xml_context_clear_logs(lpc2xml_context *ctx) {
62         ctx->errorBuffer[0]='\0';
63         ctx->warningBuffer[0]='\0';
64 }
65
66 static void lpc2xml_log(lpc2xml_context *xmlCtx, int level, const char *fmt, ...) {
67         va_list args;   
68         va_start(args, fmt);    
69         if(xmlCtx->cbf != NULL) {
70                 xmlCtx->cbf((xmlCtx)->ctx, level, fmt, args);
71         }
72         va_end(args);
73 }
74
75 static void lpc2xml_genericxml_error(void *ctx, const char *fmt, ...) {
76         lpc2xml_context *xmlCtx = (lpc2xml_context *)ctx;
77         int sl = strlen(xmlCtx->errorBuffer);
78         va_list args;   
79         va_start(args, fmt);    
80         vsnprintf(xmlCtx->errorBuffer + sl, LPC2XML_BZ-sl, fmt, args);
81         va_end(args);
82 }
83
84 static void lpc2xml_genericxml_warning(void *ctx, const char *fmt, ...) {
85         lpc2xml_context *xmlCtx = (lpc2xml_context *)ctx;
86         int sl = strlen(xmlCtx->warningBuffer);
87         va_list args;   
88         va_start(args, fmt);    
89         vsnprintf(xmlCtx->warningBuffer + sl, LPC2XML_BZ-sl, fmt, args);
90         va_end(args);
91 }
92
93 static int processEntry(const char *section, const char *entry, xmlNode *node, lpc2xml_context *ctx) {
94         const char *content = lp_config_get_string(ctx->lpc, section, entry, NULL);
95         if(content == NULL) {
96                 lpc2xml_log(ctx->ctx, LPC2XML_ERROR, "Issue when reading the lpc");
97                 return -1;
98         }
99         xmlNodeSetContent(node, (const xmlChar *) content);
100         return 0;
101 }
102
103 struct __processSectionCtx {
104         int ret;
105         const char *section;
106         xmlNode *node;
107         lpc2xml_context *ctx;
108 };
109
110 static void processSection_cb(const char *entry, struct __processSectionCtx *ctx) {
111         if(ctx->ret == 0) {
112                 xmlNode *node = xmlNewChild(ctx->node, NULL, (const xmlChar *)"entry", NULL);
113                 if(node == NULL) {
114                         lpc2xml_log(ctx->ctx, LPC2XML_ERROR, "Can't create \"entry\" element");
115                         ctx->ret = -1;
116                         return;
117                 }
118                 xmlAttr *name_attr = xmlSetProp(node, (const xmlChar *)"name", (const xmlChar *)entry);
119                 if(name_attr == NULL) {
120                         lpc2xml_log(ctx->ctx, LPC2XML_ERROR, "Can't create name attribute for \"entry\" element");
121                         ctx->ret = -1;
122                         return;
123                 }
124                 ctx->ret = processEntry(ctx->section, entry, node, ctx->ctx);
125         }
126 }
127
128 static int processSection(const char *section, xmlNode *node, lpc2xml_context *ctx) {
129         struct __processSectionCtx pc_ctx = {0, section, node, ctx};
130         lp_config_for_each_entry(ctx->lpc, section, (void (*)(const char *, void *))processSection_cb, (void*)&pc_ctx);
131         return pc_ctx.ret;
132 }
133
134
135
136 struct __processConfigCtx {
137         int ret;
138         xmlNode *node;
139         lpc2xml_context *ctx;
140 };
141
142 static void processConfig_cb(const char *section, struct __processConfigCtx *ctx) {
143         if(ctx->ret == 0) {
144                 xmlNode *node = xmlNewChild(ctx->node, NULL, (const xmlChar *)"section", NULL);
145                 if(node == NULL) {
146                         lpc2xml_log(ctx->ctx, LPC2XML_ERROR, "Can't create \"section\" element");
147                         ctx->ret = -1;
148                         return;
149                 }
150                 xmlAttr *name_attr = xmlSetProp(node, (const xmlChar *)"name", (const xmlChar *)section);
151                 if(name_attr == NULL) {
152                         lpc2xml_log(ctx->ctx, LPC2XML_ERROR, "Can't create name attribute for \"section\" element");
153                         ctx->ret = -1;
154                         return;
155                 }
156                 ctx->ret = processSection(section, node, ctx->ctx);
157         }
158 }
159
160 static int processConfig(xmlNode *node, lpc2xml_context *ctx) {
161         struct __processConfigCtx pc_ctx = {0, node, ctx};
162         lp_config_for_each_section(ctx->lpc, (void (*)(const char *, void *))processConfig_cb, (void*)&pc_ctx);
163         return pc_ctx.ret;
164 }
165
166 static int processDoc(xmlDoc *doc, lpc2xml_context *ctx) {
167         int ret = 0;
168         xmlNode *root_node = xmlNewNode(NULL, (const xmlChar *)"config");
169         if(root_node == NULL) {
170                 lpc2xml_log(ctx, LPC2XML_ERROR, "Can't create \"config\" element");
171                 return -1;
172         }
173         xmlNs *lpc_ns = xmlNewNs(root_node, (const xmlChar *)"http://www.linphone.org/xsds/lpconfig.xsd", NULL);
174         if(lpc_ns == NULL) {
175                 lpc2xml_log(ctx, LPC2XML_WARNING, "Can't create lpc namespace");
176         } else {
177                 xmlSetNs(root_node, lpc_ns);
178         }
179         xmlNs *xsi_ns = xmlNewNs(root_node, (const xmlChar *)"http://www.w3.org/2001/XMLSchema-instance", (const xmlChar *)"xsi");
180         if(lpc_ns == NULL) {
181                 lpc2xml_log(ctx, LPC2XML_WARNING, "Can't create xsi namespace");
182         }
183         xmlAttr *schemaLocation = xmlNewNsProp(root_node, xsi_ns, (const xmlChar *)"schemaLocation", (const xmlChar *)"http://www.linphone.org/xsds/lpconfig.xsd lpconfig.xsd");
184         if(schemaLocation == NULL) {
185                 lpc2xml_log(ctx, LPC2XML_WARNING, "Can't create schemaLocation");
186         }
187         ret = processConfig(root_node, ctx);
188         xmlDocSetRootElement(doc, root_node);
189         return ret;
190 }
191
192 static int internal_convert_lpc2xml(lpc2xml_context *ctx) {
193         int ret = 0;
194         lpc2xml_log(ctx, LPC2XML_DEBUG, "Generation started");
195         if(ctx->doc != NULL) {
196                 xmlFreeDoc(ctx->doc);
197                 ctx->doc = NULL;
198         }
199         xmlDoc *doc = xmlNewDoc((const xmlChar *)"1.0");
200         ret  = processDoc(doc, ctx);
201         if(ret == 0) {
202                 ctx->doc = doc;
203         } else {
204                 xmlFreeDoc(doc);
205         }
206         lpc2xml_log(ctx, LPC2XML_DEBUG, "Generation ended ret:%d", ret);
207         return ret;
208 }
209
210 int lpc2xml_set_lpc(lpc2xml_context* context, const LpConfig *lpc) {
211         context->lpc = lpc;
212         return 0;
213 }
214
215 int lpc2xml_convert_file(lpc2xml_context* context, const char *filename) {
216         int ret = -1;
217         lpc2xml_context_clear_logs(context);
218         xmlSetGenericErrorFunc(context, lpc2xml_genericxml_error);
219         xmlSaveCtxtPtr save_ctx = xmlSaveToFilename(filename, "UTF-8", XML_SAVE_FORMAT);
220         if(save_ctx != NULL) {
221                 ret = internal_convert_lpc2xml(context);
222                 if(ret == 0) {
223                         ret = xmlSaveDoc(save_ctx, context->doc);
224                         if(ret != 0) {
225                                 lpc2xml_log(context, LPC2XML_ERROR, "Can't save document");
226                                 lpc2xml_log(context, LPC2XML_ERROR, "%s", context->errorBuffer);
227                         }
228                 }
229                 xmlSaveClose(save_ctx);
230         } else {
231                 lpc2xml_log(context, LPC2XML_ERROR, "Can't open file:%s", filename);
232                 lpc2xml_log(context, LPC2XML_ERROR, "%s", context->errorBuffer);
233         }
234         return ret;
235 }
236
237 int lpc2xml_convert_fd(lpc2xml_context* context, int fd) {
238         int ret = -1;
239         lpc2xml_context_clear_logs(context);
240         xmlSetGenericErrorFunc(context, lpc2xml_genericxml_error);
241         xmlSaveCtxtPtr save_ctx = xmlSaveToFd(fd, "UTF-8", XML_SAVE_FORMAT);
242         if(save_ctx != NULL) {
243                 ret = internal_convert_lpc2xml(context);
244                 if(ret == 0) {
245                         ret = xmlSaveDoc(save_ctx, context->doc);
246                         if(ret != 0) {
247                                 lpc2xml_log(context, LPC2XML_ERROR, "Can't save document");
248                                 lpc2xml_log(context, LPC2XML_ERROR, "%s", context->errorBuffer);
249                         }
250                 }
251                 xmlSaveClose(save_ctx);
252         } else {
253                 lpc2xml_log(context, LPC2XML_ERROR, "Can't open fd:%d", fd);
254                 lpc2xml_log(context, LPC2XML_ERROR, "%s", context->errorBuffer);
255         }
256         return ret;
257 }
258
259 int lpc2xml_convert_string(lpc2xml_context* context, char **content) {
260         int ret = -1;
261         xmlBufferPtr buffer = xmlBufferCreate();
262         lpc2xml_context_clear_logs(context);
263         xmlSetGenericErrorFunc(context, lpc2xml_genericxml_error);
264         xmlSaveCtxtPtr save_ctx = xmlSaveToBuffer(buffer, "UTF-8", XML_SAVE_FORMAT);
265         if(save_ctx != NULL) {
266                 ret = internal_convert_lpc2xml(context);
267                 if(ret == 0) {
268                         ret = xmlSaveDoc(save_ctx, context->doc);
269                         if(ret != 0) {
270                                 lpc2xml_log(context, LPC2XML_ERROR, "Can't save document");
271                                 lpc2xml_log(context, LPC2XML_ERROR, "%s", context->errorBuffer);
272                         }
273                 }
274                 xmlSaveClose(save_ctx);
275         } else {
276                 lpc2xml_log(context, LPC2XML_ERROR, "Can't initialize internal buffer");
277                 lpc2xml_log(context, LPC2XML_ERROR, "%s", context->errorBuffer);
278         }
279         if(ret == 0) {
280 #if LIBXML_VERSION >= 20800
281                 *content = (char *)xmlBufferDetach(buffer);
282 #else
283                 *content = strdup((const char *)xmlBufferContent(buffer));
284 #endif
285         }
286         xmlBufferFree(buffer);
287         return ret;
288 }