1 /*****************************************************************
2  * gmerlin - a general purpose multimedia framework and applications
3  *
4  * Copyright (c) 2001 - 2011 Members of the Gmerlin project
5  * gmerlin-general@lists.sourceforge.net
6  * http://gmerlin.sourceforge.net
7  *
8  * This program is free software: you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation, either version 2 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
20  * *****************************************************************/
21 
22 #include <stdlib.h>
23 #include <string.h>
24 // #include <locale.h>
25 
26 #include <gmerlin/cfg_registry.h>
27 #include <registry_priv.h>
28 #include <gmerlin/utils.h>
29 #include <gmerlin/xmlutils.h>
30 
load_item(xmlDocPtr xml_doc,xmlNodePtr xml_item,bg_cfg_section_t * cfg_section)31 static void load_item(xmlDocPtr xml_doc, xmlNodePtr xml_item,
32                       bg_cfg_section_t * cfg_section)
33   {
34   char * tmp_type;
35   char * tmp_string;
36   char * start;
37 
38   bg_parameter_info_t info;
39 
40   bg_cfg_item_t * item;
41 
42   memset(&info, 0, sizeof(info));
43 
44   tmp_type = BG_XML_GET_PROP(xml_item, "type");
45   info.name = BG_XML_GET_PROP(xml_item, "name");
46 
47   if(!tmp_type || !info.name)
48     {
49     if(tmp_type)
50       xmlFree(tmp_type);
51     if(info.name)
52       xmlFree(info.name);
53     return;
54     }
55 
56   /* Check for the type */
57 
58   if(!strcmp(tmp_type, "int"))
59     {
60     info.type = BG_PARAMETER_INT;
61     }
62   else if(!strcmp(tmp_type, "float"))
63     {
64     info.type = BG_PARAMETER_FLOAT;
65     }
66   else if(!strcmp(tmp_type, "string"))
67     {
68     info.type = BG_PARAMETER_STRING;
69     }
70   else if(!strcmp(tmp_type, "string_hidden"))
71     {
72     info.type = BG_PARAMETER_STRING_HIDDEN;
73     }
74   else if(!strcmp(tmp_type, "color"))
75     {
76     info.type = BG_PARAMETER_COLOR_RGBA;
77     }
78   else if(!strcmp(tmp_type, "time"))
79     {
80     info.type = BG_PARAMETER_TIME;
81     }
82   else if(!strcmp(tmp_type, "pos"))
83     {
84     info.type = BG_PARAMETER_POSITION;
85     }
86   else
87     {
88     return;
89     }
90 
91   /* Find the item */
92 
93   item = bg_cfg_section_find_item(cfg_section, &info);
94 
95   tmp_string = (char*)xmlNodeListGetString(xml_doc, xml_item->children, 1);
96 
97   switch(item->type)
98     {
99     case BG_CFG_INT:
100       sscanf(tmp_string, "%d", &item->value.val_i);
101       break;
102     case BG_CFG_TIME:
103       sscanf(tmp_string, "%" PRId64, &item->value.val_time);
104       break;
105     case BG_CFG_FLOAT:
106       sscanf(tmp_string, "%lf", &item->value.val_f);
107       break;
108     case BG_CFG_STRING:
109       item->value.val_str = bg_strdup(item->value.val_str,
110                                       tmp_string);
111       break;
112     case BG_CFG_STRING_HIDDEN:
113       if(item->value.val_str)
114         {
115         free(item->value.val_str);
116         item->value.val_str = NULL;
117         }
118       if(tmp_string && (*tmp_string != '\0'))
119         item->value.val_str = bg_descramble_string(tmp_string);
120 
121       break;
122     case BG_CFG_COLOR:
123       start = tmp_string;
124       sscanf(tmp_string, "%f %f %f %f",
125              &item->value.val_color[0],
126              &item->value.val_color[1],
127              &item->value.val_color[2],
128              &item->value.val_color[3]);
129       break;
130     case BG_CFG_POSITION:
131       start = tmp_string;
132       sscanf(tmp_string, "%lf %lf",
133              &item->value.val_pos[0],
134              &item->value.val_pos[1]);
135       break;
136     }
137   if(tmp_string)
138     xmlFree(tmp_string);
139   if(info.name)
140     xmlFree(info.name);
141   if(tmp_type)
142     xmlFree(tmp_type);
143   }
144 
bg_cfg_xml_2_section(xmlDocPtr xml_doc,xmlNodePtr xml_section,bg_cfg_section_t * cfg_section)145 void bg_cfg_xml_2_section(xmlDocPtr xml_doc,
146                           xmlNodePtr xml_section,
147                           bg_cfg_section_t * cfg_section)
148   {
149   xmlNodePtr cur;
150   char * tmp_string;
151   bg_cfg_section_t * cfg_child_section;
152 
153   cur = xml_section->children;
154 
155   tmp_string = BG_XML_GET_PROP(xml_section, "gettext_domain");
156   if(tmp_string)
157     {
158     cfg_section->gettext_domain =
159       bg_strdup(cfg_section->gettext_domain, tmp_string);
160     xmlFree(tmp_string);
161     }
162   tmp_string = BG_XML_GET_PROP(xml_section, "gettext_directory");
163   if(tmp_string)
164     {
165     cfg_section->gettext_directory =
166       bg_strdup(cfg_section->gettext_directory, tmp_string);
167     xmlFree(tmp_string);
168     }
169 
170   while(cur)
171     {
172     if(!cur->name)
173       {
174       cur = cur->next;
175       continue;
176       }
177     /* Load items */
178     else if(!BG_XML_STRCMP(cur->name, "ITEM"))
179       {
180       load_item(xml_doc, cur, cfg_section);
181       }
182     /* Load child */
183     else if(!BG_XML_STRCMP(cur->name, "SECTION"))
184       {
185       tmp_string = BG_XML_GET_PROP(cur, "name");
186       if(tmp_string)
187         {
188         cfg_child_section = bg_cfg_section_find_subsection(cfg_section, tmp_string);
189         bg_cfg_xml_2_section(xml_doc, cur, cfg_child_section);
190         xmlFree(tmp_string);
191         }
192       }
193     cur = cur->next;
194     }
195   }
196 
bg_cfg_registry_load(bg_cfg_registry_t * r,const char * filename)197 void bg_cfg_registry_load(bg_cfg_registry_t * r, const char * filename)
198   {
199   xmlDocPtr xml_doc;
200   xmlNodePtr node;
201   bg_cfg_section_t * cfg_section;
202   char * tmp_string;
203 
204   if(!filename)
205     return;
206 
207   xml_doc = bg_xml_parse_file(filename);
208 
209   if(!xml_doc)
210     return;
211 
212   node = xml_doc->children;
213 
214   if(BG_XML_STRCMP(node->name, "REGISTRY"))
215     {
216     xmlFreeDoc(xml_doc);
217     return;
218     }
219 
220   node = node->children;
221 
222   while(node)
223     {
224     if(node->name && !BG_XML_STRCMP(node->name, "SECTION"))
225       {
226       tmp_string = BG_XML_GET_PROP(node, "name");
227       if(tmp_string)
228         {
229         cfg_section = bg_cfg_registry_find_section(r, tmp_string);
230         bg_cfg_xml_2_section(xml_doc, node, cfg_section);
231         xmlFree(tmp_string);
232         }
233       }
234     node = node->next;
235     }
236 
237   xmlFreeDoc(xml_doc);
238   }
239 
bg_cfg_section_2_xml(const bg_cfg_section_t * section,xmlNodePtr xml_section)240 void bg_cfg_section_2_xml(const bg_cfg_section_t * section, xmlNodePtr xml_section)
241   {
242   char * tmp_string;
243   bg_cfg_item_t    * item;
244   bg_cfg_section_t * tmp_section;
245 
246   char buffer[1024];
247 
248   xmlNodePtr xml_item, xml_child;
249 
250   /* Save items */
251 
252   item = section->items;
253 
254   if(section->gettext_domain)
255     BG_XML_SET_PROP(xml_section, "gettext_domain", section->gettext_domain);
256   if(section->gettext_directory)
257     BG_XML_SET_PROP(xml_section, "gettext_directory", section->gettext_directory);
258 
259   xmlAddChild(xml_section, BG_XML_NEW_TEXT("\n"));
260 
261   while(item)
262     {
263     xml_item = xmlNewTextChild(xml_section, NULL, (xmlChar*)"ITEM", NULL);
264     BG_XML_SET_PROP(xml_item, "name", item->name);
265 
266     switch(item->type)
267       {
268       case BG_CFG_INT:
269         BG_XML_SET_PROP(xml_item, "type", "int");
270         sprintf(buffer, "%d", item->value.val_i);
271         xmlAddChild(xml_item, BG_XML_NEW_TEXT(buffer));
272         break;
273       case BG_CFG_TIME:
274         BG_XML_SET_PROP(xml_item, "type", "time");
275         sprintf(buffer, "%" PRId64, item->value.val_time);
276         xmlAddChild(xml_item, BG_XML_NEW_TEXT(buffer));
277         break;
278       case BG_CFG_FLOAT:
279         BG_XML_SET_PROP(xml_item, "type", "float");
280         sprintf(buffer, "%.15e", item->value.val_f);
281         xmlAddChild(xml_item, BG_XML_NEW_TEXT(buffer));
282         break;
283       case BG_CFG_STRING:
284         BG_XML_SET_PROP(xml_item, "type", "string");
285         /* Yes, that's stupid */
286         if(item->value.val_str)
287           xmlAddChild(xml_item, BG_XML_NEW_TEXT(item->value.val_str));
288         break;
289       case BG_CFG_STRING_HIDDEN:
290         BG_XML_SET_PROP(xml_item, "type", "string_hidden");
291         /* Yes, that's stupid */
292         if(item->value.val_str)
293           {
294           tmp_string = bg_scramble_string(item->value.val_str);
295           xmlAddChild(xml_item, BG_XML_NEW_TEXT(tmp_string));
296           free(tmp_string);
297           }
298         break;
299       case BG_CFG_COLOR:
300         BG_XML_SET_PROP(xml_item, "type", "color");
301         sprintf(buffer, "%f %f %f %f",
302                 item->value.val_color[0],
303                 item->value.val_color[1],
304                 item->value.val_color[2],
305                 item->value.val_color[3]);
306         xmlAddChild(xml_item, BG_XML_NEW_TEXT(buffer));
307         break;
308       case BG_CFG_POSITION:
309         BG_XML_SET_PROP(xml_item, "type", "pos");
310         sprintf(buffer, "%f %f",
311                 item->value.val_pos[0],
312                 item->value.val_pos[1]);
313         xmlAddChild(xml_item, BG_XML_NEW_TEXT(buffer));
314         break;
315       }
316     xmlAddChild(xml_section, BG_XML_NEW_TEXT("\n"));
317 
318     item = item->next;
319     }
320 
321   /* Save child sections */
322 
323   tmp_section = section->children;
324   while(tmp_section)
325     {
326     xml_child = xmlNewTextChild(xml_section, NULL, (xmlChar*)"SECTION", NULL);
327     BG_XML_SET_PROP(xml_child, "name", tmp_section->name);
328 
329     bg_cfg_section_2_xml(tmp_section, xml_child);
330     xmlAddChild(xml_section, BG_XML_NEW_TEXT("\n"));
331 
332     tmp_section = tmp_section->next;
333     }
334   }
335 
bg_cfg_registry_save(bg_cfg_registry_t * r,const char * filename)336 void bg_cfg_registry_save(bg_cfg_registry_t * r, const char * filename)
337   {
338   xmlDocPtr  xml_doc;
339   xmlNodePtr xml_registry, xml_section;
340 
341   bg_cfg_section_t * tmp_section;
342   if(!filename)
343     return;
344 
345   xml_doc = xmlNewDoc((xmlChar*)"1.0");
346   xml_registry = xmlNewDocRawNode(xml_doc, NULL, (xmlChar*)"REGISTRY", NULL);
347   xmlDocSetRootElement(xml_doc, xml_registry);
348 
349   xmlAddChild(xml_registry, BG_XML_NEW_TEXT("\n"));
350 
351   tmp_section = r->sections;
352   while(tmp_section)
353     {
354     xml_section = xmlNewTextChild(xml_registry, NULL, (xmlChar*)"SECTION", NULL);
355     BG_XML_SET_PROP(xml_section, "name", tmp_section->name);
356 
357     bg_cfg_section_2_xml(tmp_section, xml_section);
358     tmp_section = tmp_section->next;
359 
360     xmlAddChild(xml_registry, BG_XML_NEW_TEXT("\n"));
361 
362     }
363   xmlSaveFile(filename, xml_doc);
364   xmlFreeDoc(xml_doc);
365   }
366 
bg_cfg_section_dump(bg_cfg_section_t * section,const char * filename)367 void bg_cfg_section_dump(bg_cfg_section_t * section, const char * filename)
368   {
369   xmlDocPtr  xml_doc;
370   xmlNodePtr xml_section;
371   xml_doc = xmlNewDoc((xmlChar*)"1.0");
372   xml_section = xmlNewDocRawNode(xml_doc, NULL, (xmlChar*)"SECTION", NULL);
373   xmlDocSetRootElement(xml_doc, xml_section);
374   BG_XML_SET_PROP(xml_section, "name", section->name);
375   bg_cfg_section_2_xml(section, xml_section);
376   xmlSaveFile(filename, xml_doc);
377   xmlFreeDoc(xml_doc);
378   }
379