1 /***************************************************************************
2  begin       : Thu Apr 03 2003
3  copyright   : (C) 2003-2010 by Martin Preuss
4  email       : martin@libchipcard.de
5 
6  ***************************************************************************
7  *                                                                         *
8  *   This library is free software; you can redistribute it and/or         *
9  *   modify it under the terms of the GNU Lesser General Public            *
10  *   License as published by the Free Software Foundation; either          *
11  *   version 2.1 of the License, or (at your option) any later version.    *
12  *                                                                         *
13  *   This library 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 GNU     *
16  *   Lesser General Public License for more details.                       *
17  *                                                                         *
18  *   You should have received a copy of the GNU Lesser General Public      *
19  *   License along with this library; if not, write to the Free Software   *
20  *   Foundation, Inc., 59 Temple Place, Suite 330, Boston,                 *
21  *   MA  02111-1307  USA                                                   *
22  *                                                                         *
23  ***************************************************************************/
24 
25 #ifdef HAVE_CONFIG_H
26 # include <config.h>
27 #endif
28 
29 #define DISABLE_DEBUGLOG
30 
31 
32 #include "plugindescr_p.h"
33 #include "i18n_l.h"
34 #include <gwenhywfar/buffer.h>
35 #include <gwenhywfar/debug.h>
36 #include <gwenhywfar/directory.h>
37 #include <gwenhywfar/i18n.h>
38 
39 #include <sys/types.h>
40 #include <sys/stat.h>
41 #ifdef HAVE_UNISTD_H
42 # include <unistd.h>
43 #endif
44 #include <errno.h>
45 #include <string.h>
46 #ifdef HAVE_STRINGS_H
47 # include <strings.h>
48 #endif
49 
50 
51 
GWEN_LIST_FUNCTIONS(GWEN_PLUGIN_DESCRIPTION,GWEN_PluginDescription)52 GWEN_LIST_FUNCTIONS(GWEN_PLUGIN_DESCRIPTION, GWEN_PluginDescription)
53 GWEN_LIST2_FUNCTIONS(GWEN_PLUGIN_DESCRIPTION, GWEN_PluginDescription)
54 
55 
56 
57 GWEN_PLUGIN_DESCRIPTION *GWEN_PluginDescription_new(GWEN_XMLNODE *node)
58 {
59   GWEN_PLUGIN_DESCRIPTION *pd;
60   const char *p;
61 
62   GWEN_NEW_OBJECT(GWEN_PLUGIN_DESCRIPTION, pd);
63   pd->refCount=1;
64   DBG_MEM_INC("GWEN_PLUGIN_DESCRIPTION", 0);
65   GWEN_LIST_INIT(GWEN_PLUGIN_DESCRIPTION, pd);
66   p=GWEN_XMLNode_GetProperty(node, "name", 0);
67   if (!p) {
68     DBG_ERROR(GWEN_LOGDOMAIN, "Unnamed plugin");
69     GWEN_PluginDescription_free(pd);
70     return 0;
71   }
72   pd->name=strdup(p);
73   pd->xmlNode=GWEN_XMLNode_dup(node);
74 
75   p=GWEN_XMLNode_GetProperty(node, "i18n", NULL);
76   if (!p) {
77     DBG_NOTICE(GWEN_LOGDOMAIN, "Plugin has no I18N domain, using GWEN");
78     p="gwenhywfar";
79   }
80   pd->langDomain=strdup(p);
81 
82   p=GWEN_XMLNode_GetProperty(node, "type", 0);
83   if (!p) {
84     DBG_ERROR(GWEN_LOGDOMAIN, "Plugin has no type");
85     GWEN_PluginDescription_free(pd);
86     return 0;
87   }
88   pd->type=strdup(p);
89 
90   p=GWEN_XMLNode_GetCharValue(node, "version", 0);
91   if (p)
92     pd->version=strdup(p);
93   p=GWEN_XMLNode_GetCharValue(node, "author", 0);
94   if (p)
95     pd->author=strdup(p);
96   p=GWEN_XMLNode_GetCharValue(node, "short", 0);
97   if (p)
98     pd->shortDescr=strdup(p);
99   p=GWEN_XMLNode_GetCharValue(node, "descr", 0);
100   if (p)
101     pd->longDescr=strdup(p);
102   return pd;
103 }
104 
105 
106 
GWEN_PluginDescription_free(GWEN_PLUGIN_DESCRIPTION * pd)107 void GWEN_PluginDescription_free(GWEN_PLUGIN_DESCRIPTION *pd)
108 {
109   if (pd) {
110     assert(pd->refCount);
111     if (pd->refCount==1) {
112       DBG_MEM_DEC("GWEN_PLUGIN_DESCRIPTION");
113       GWEN_LIST_FINI(GWEN_PLUGIN_DESCRIPTION, pd);
114       free(pd->path);
115       GWEN_XMLNode_free(pd->xmlNode);
116       free(pd->fileName);
117       free(pd->longDescr);
118       free(pd->shortDescr);
119       free(pd->author);
120       free(pd->version);
121       free(pd->langDomain);
122       free(pd->type);
123       free(pd->name);
124       pd->refCount=0;
125       GWEN_FREE_OBJECT(pd);
126     }
127     else
128       pd->refCount--;
129   }
130 }
131 
132 
133 
GWEN_PluginDescription_Attach(GWEN_PLUGIN_DESCRIPTION * pd)134 void GWEN_PluginDescription_Attach(GWEN_PLUGIN_DESCRIPTION *pd)
135 {
136   assert(pd);
137   assert(pd->refCount);
138   pd->refCount++;
139 }
140 
141 
142 
GWEN_PluginDescription_dup(const GWEN_PLUGIN_DESCRIPTION * pd)143 GWEN_PLUGIN_DESCRIPTION *GWEN_PluginDescription_dup(const GWEN_PLUGIN_DESCRIPTION *pd)
144 {
145   GWEN_PLUGIN_DESCRIPTION *np;
146   const char *s;
147 
148   assert(pd);
149   GWEN_NEW_OBJECT(GWEN_PLUGIN_DESCRIPTION, np);
150   np->refCount=1;
151   DBG_MEM_INC("GWEN_PLUGIN_DESCRIPTION", 0);
152   GWEN_LIST_INIT(GWEN_PLUGIN_DESCRIPTION, np);
153 
154   s=pd->fileName;
155   if (s)
156     np->fileName=strdup(s);
157 
158   s=pd->path;
159   if (s)
160     np->path=strdup(s);
161   s=pd->name;
162   if (s)
163     np->name=strdup(s);
164   s=pd->type;
165   if (s)
166     np->type=strdup(s);
167   s=pd->langDomain;
168   if (s)
169     np->langDomain=strdup(s);
170   s=pd->shortDescr;
171   if (s)
172     np->shortDescr=strdup(s);
173   s=pd->author;
174   if (s)
175     np->author=strdup(s);
176   s=pd->version;
177   if (s)
178     np->version=strdup(s);
179   s=pd->longDescr;
180   if (s)
181     np->longDescr=strdup(s);
182   np->isActive=pd->isActive;
183   if (pd->xmlNode)
184     np->xmlNode=GWEN_XMLNode_dup(pd->xmlNode);
185 
186   return np;
187 }
188 
189 
190 
GWEN_PluginDescription_List2_freeAll_cb(GWEN_PLUGIN_DESCRIPTION * pd,void * user_data)191 GWEN_PLUGIN_DESCRIPTION *GWEN_PluginDescription_List2_freeAll_cb(GWEN_PLUGIN_DESCRIPTION *pd,
192                                                                  __attribute__((unused)) void *user_data)
193 {
194   GWEN_PluginDescription_free(pd);
195   return 0;
196 }
197 
198 
199 
GWEN_PluginDescription_List2_freeAll(GWEN_PLUGIN_DESCRIPTION_LIST2 * pdl)200 void GWEN_PluginDescription_List2_freeAll(GWEN_PLUGIN_DESCRIPTION_LIST2 *pdl)
201 {
202   GWEN_PluginDescription_List2_ForEach
203   (pdl,
204    GWEN_PluginDescription_List2_freeAll_cb,
205    0);
206   GWEN_PluginDescription_List2_free(pdl);
207 }
208 
209 
210 
GWEN_PluginDescription_GetPath(const GWEN_PLUGIN_DESCRIPTION * pd)211 const char *GWEN_PluginDescription_GetPath(const GWEN_PLUGIN_DESCRIPTION *pd)
212 {
213   assert(pd);
214   return pd->path;
215 }
216 
217 
218 
GWEN_PluginDescription_SetPath(GWEN_PLUGIN_DESCRIPTION * pd,const char * s)219 void GWEN_PluginDescription_SetPath(GWEN_PLUGIN_DESCRIPTION *pd,
220                                     const char *s)
221 {
222   assert(pd);
223   free(pd->path);
224   if (s)
225     pd->path=strdup(s);
226   else
227     pd->path=0;
228 }
229 
230 
231 
GWEN_PluginDescription_GetName(const GWEN_PLUGIN_DESCRIPTION * pd)232 const char *GWEN_PluginDescription_GetName(const GWEN_PLUGIN_DESCRIPTION *pd)
233 {
234   assert(pd);
235   return pd->name;
236 }
237 
238 
239 
GWEN_PluginDescription_GetType(const GWEN_PLUGIN_DESCRIPTION * pd)240 const char *GWEN_PluginDescription_GetType(const GWEN_PLUGIN_DESCRIPTION *pd)
241 {
242   assert(pd);
243   return pd->type;
244 }
245 
246 
247 
GWEN_PluginDescription_GetShortDescr(const GWEN_PLUGIN_DESCRIPTION * pd)248 const char *GWEN_PluginDescription_GetShortDescr(const GWEN_PLUGIN_DESCRIPTION *pd)
249 {
250   assert(pd);
251   return GWEN_I18N_Translate(pd->langDomain, pd->shortDescr);
252 }
253 
254 
255 
GWEN_PluginDescription_GetAuthor(const GWEN_PLUGIN_DESCRIPTION * pd)256 const char *GWEN_PluginDescription_GetAuthor(const GWEN_PLUGIN_DESCRIPTION *pd)
257 {
258   assert(pd);
259   return pd->author;
260 }
261 
262 
263 
GWEN_PluginDescription_GetVersion(const GWEN_PLUGIN_DESCRIPTION * pd)264 const char *GWEN_PluginDescription_GetVersion(const GWEN_PLUGIN_DESCRIPTION *pd)
265 {
266   assert(pd);
267   return pd->version;
268 }
269 
270 
271 
GWEN_PluginDescription_GetLongDescr(const GWEN_PLUGIN_DESCRIPTION * pd)272 const char *GWEN_PluginDescription_GetLongDescr(const GWEN_PLUGIN_DESCRIPTION *pd)
273 {
274   assert(pd);
275   return GWEN_I18N_Translate(pd->langDomain, pd->longDescr);
276 }
277 
278 
279 
GWEN_PluginDescription__GetLongDescrByFormat(const GWEN_PLUGIN_DESCRIPTION * pd,const char * s,GWEN_BUFFER * buf)280 int GWEN_PluginDescription__GetLongDescrByFormat(const GWEN_PLUGIN_DESCRIPTION *pd,
281                                                  const char *s,
282                                                  GWEN_BUFFER *buf)
283 {
284   GWEN_XMLNODE *n;
285 
286   assert(pd);
287   assert(pd->xmlNode);
288 
289   n=GWEN_XMLNode_FindFirstTag(pd->xmlNode, "descr", 0, 0);
290   if (n) {
291     n=GWEN_XMLNode_FindFirstTag(n, "text", "format", s);
292     while (n) {
293       if (0==GWEN_XMLNode_GetProperty(n, "lang", 0)) {
294         int rv;
295 
296         rv=GWEN_XMLNode_toBuffer(n, buf, GWEN_XML_FLAGS_TOLERANT_ENDTAGS);
297         if (rv) {
298           DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
299           return rv;
300         }
301         return 0;
302       }
303       n=GWEN_XMLNode_FindNextTag(n, "text", "format", s);
304     } /* while */
305   }
306 
307   return -1;
308 }
309 
310 
311 
GWEN_PluginDescription__GetLocalizedLongDescrByFormat(const GWEN_PLUGIN_DESCRIPTION * pd,const char * s,const char * lang,GWEN_BUFFER * buf)312 int GWEN_PluginDescription__GetLocalizedLongDescrByFormat(const GWEN_PLUGIN_DESCRIPTION *pd,
313                                                           const char *s,
314                                                           const char *lang,
315                                                           GWEN_BUFFER *buf)
316 {
317   GWEN_XMLNODE *n;
318 
319   assert(pd);
320   assert(pd->xmlNode);
321 
322   n=GWEN_XMLNode_FindFirstTag(pd->xmlNode, "descr", 0, 0);
323   if (n) {
324     n=GWEN_XMLNode_FindFirstTag(n, "text", "lang", lang);
325     while (n) {
326       const char *fmt;
327 
328       fmt=GWEN_XMLNode_GetProperty(n, "format", 0);
329       if (fmt && strcasecmp(fmt, s)==0) {
330         int rv;
331 
332         rv=GWEN_XMLNode_toBuffer(n, buf, GWEN_XML_FLAGS_TOLERANT_ENDTAGS);
333         if (rv) {
334           DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
335           return rv;
336         }
337         return 0;
338       }
339       n=GWEN_XMLNode_FindNextTag(n, "text", "lang", lang);
340     } /* while */
341   }
342 
343   return -1;
344 }
345 
346 
347 
348 #ifndef NO_DEPRECATED_SYMBOLS
GWEN_PluginDescription_GetLongDescrByFormat(const GWEN_PLUGIN_DESCRIPTION * pd,const char * s,GWEN_BUFFER * buf)349 int GWEN_PluginDescription_GetLongDescrByFormat(const GWEN_PLUGIN_DESCRIPTION *pd,
350                                                 const char *s,
351                                                 GWEN_BUFFER *buf)
352 {
353   GWEN_STRINGLIST *langl;
354   int rv;
355 
356   langl=GWEN_I18N_GetCurrentLocaleList();
357   if (langl) {
358     GWEN_STRINGLISTENTRY *se;
359 
360     se=GWEN_StringList_FirstEntry(langl);
361     while (se) {
362       const char *l;
363 
364       l=GWEN_StringListEntry_Data(se);
365       DBG_NOTICE(GWEN_LOGDOMAIN, "Trying locale \"%s\"", l);
366       assert(l);
367 
368       rv=GWEN_PluginDescription__GetLocalizedLongDescrByFormat(pd,
369                                                                s,
370                                                                l,
371                                                                buf);
372       if (rv==0)
373         return rv;
374 
375       se=GWEN_StringListEntry_Next(se);
376     } /* while */
377   } /* if language list available */
378 
379   /* no localized version found, return text for default language */
380   rv=GWEN_PluginDescription__GetLongDescrByFormat(pd, s, buf);
381   if (rv) {
382     DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
383     return rv;
384   }
385 
386   return 0;
387 }
388 #endif  // ifndef NO_DEPRECATED_SYMBOLS
389 
390 
GWEN_PluginDescription_GetFileName(const GWEN_PLUGIN_DESCRIPTION * pd)391 const char *GWEN_PluginDescription_GetFileName(const GWEN_PLUGIN_DESCRIPTION *pd)
392 {
393   assert(pd);
394   return pd->fileName;
395 }
396 
397 
398 
GWEN_PluginDescription_SetFileName(GWEN_PLUGIN_DESCRIPTION * pd,const char * s)399 void GWEN_PluginDescription_SetFileName(GWEN_PLUGIN_DESCRIPTION *pd,
400                                         const char *s)
401 {
402   assert(pd);
403   free(pd->fileName);
404   if (s)
405     pd->fileName=strdup(s);
406   else
407     pd->fileName=0;
408 }
409 
410 
411 
GWEN_PluginDescription_GetXmlNode(const GWEN_PLUGIN_DESCRIPTION * pd)412 GWEN_XMLNODE *GWEN_PluginDescription_GetXmlNode(const GWEN_PLUGIN_DESCRIPTION *pd)
413 {
414   assert(pd);
415   return pd->xmlNode;
416 }
417 
418 
419 
GWEN_LoadPluginDescrs(const char * path)420 GWEN_PLUGIN_DESCRIPTION_LIST2 *GWEN_LoadPluginDescrs(const char *path)
421 {
422   GWEN_PLUGIN_DESCRIPTION_LIST2 *pl;
423 
424   pl=GWEN_PluginDescription_List2_new();
425 
426   GWEN_LoadPluginDescrsByType(path, 0, pl);
427   if (GWEN_PluginDescription_List2_GetSize(pl)==0) {
428     GWEN_PluginDescription_List2_free(pl);
429     return 0;
430   }
431   return pl;
432 }
433 
434 
435 
GWEN_PluginDescription_IsActive(const GWEN_PLUGIN_DESCRIPTION * pd)436 int GWEN_PluginDescription_IsActive(const GWEN_PLUGIN_DESCRIPTION *pd)
437 {
438   assert(pd);
439   return pd->isActive;
440 }
441 
442 
443 
GWEN_PluginDescription_SetIsActive(GWEN_PLUGIN_DESCRIPTION * pd,int i)444 void GWEN_PluginDescription_SetIsActive(GWEN_PLUGIN_DESCRIPTION *pd, int i)
445 {
446   assert(pd);
447   pd->isActive=i;
448 }
449 
450 
451 
GWEN_LoadPluginDescrsByType(const char * path,const char * type,GWEN_PLUGIN_DESCRIPTION_LIST2 * pdl)452 int GWEN_LoadPluginDescrsByType(const char *path,
453                                 const char *type,
454                                 GWEN_PLUGIN_DESCRIPTION_LIST2 *pdl)
455 {
456   GWEN_DIRECTORY *d;
457   GWEN_BUFFER *nbuf;
458   char nbuffer[64];
459   unsigned int pathLen;
460 
461   if (!path)
462     path="";
463 
464   /* create path */
465   nbuf=GWEN_Buffer_new(0, 256, 0, 1);
466   GWEN_Buffer_AppendString(nbuf, path);
467   pathLen=GWEN_Buffer_GetUsedBytes(nbuf);
468 
469   d=GWEN_Directory_new();
470   if (GWEN_Directory_Open(d, GWEN_Buffer_GetStart(nbuf))) {
471     DBG_INFO(GWEN_LOGDOMAIN,
472              "Path \"%s\" is not available",
473              GWEN_Buffer_GetStart(nbuf));
474     GWEN_Buffer_free(nbuf);
475     GWEN_Directory_free(d);
476     return -1;
477   }
478 
479   while (!GWEN_Directory_Read(d,
480                               nbuffer,
481                               sizeof(nbuffer))) {
482     if (strcmp(nbuffer, ".") &&
483         strcmp(nbuffer, "..")) {
484       int nlen;
485 
486       nlen=strlen(nbuffer);
487       if (nlen>3) {
488         if (strcasecmp(nbuffer+nlen-4, ".xml")==0) {
489           struct stat st;
490 
491           GWEN_Buffer_Crop(nbuf, 0, pathLen);
492           GWEN_Buffer_SetPos(nbuf, pathLen);
493           GWEN_Buffer_AppendByte(nbuf, GWEN_DIR_SEPARATOR);
494           GWEN_Buffer_AppendString(nbuf, nbuffer);
495 
496           if (stat(GWEN_Buffer_GetStart(nbuf), &st)) {
497             DBG_ERROR(GWEN_LOGDOMAIN, "stat(%s): %s",
498                       GWEN_Buffer_GetStart(nbuf),
499                       strerror(errno));
500           }
501           else {
502             if (!S_ISDIR(st.st_mode)) {
503               GWEN_XMLNODE *fileNode;
504 
505               fileNode=GWEN_XMLNode_new(GWEN_XMLNodeTypeTag, "root");
506               if (GWEN_XML_ReadFile(fileNode,
507                                     GWEN_Buffer_GetStart(nbuf),
508                                     GWEN_XML_FLAGS_DEFAULT |
509                                     GWEN_XML_FLAGS_HANDLE_HEADERS |
510                                     GWEN_XML_FLAGS_HANDLE_OPEN_HTMLTAGS)) {
511                 DBG_WARN(GWEN_LOGDOMAIN,
512                          "Bad file \"%s\"", GWEN_Buffer_GetStart(nbuf));
513               }
514               else {
515                 GWEN_XMLNODE *node;
516                 GWEN_XMLNODE *n;
517                 GWEN_STRINGLIST *langl;
518 
519                 n=0;
520                 node=GWEN_XMLNode_FindFirstTag(fileNode, "PluginDescr", 0, 0);
521                 if (!node)
522                   node=fileNode;
523                 langl=GWEN_I18N_GetCurrentLocaleList();
524                 if (langl) {
525                   GWEN_STRINGLISTENTRY *se;
526 
527                   se=GWEN_StringList_FirstEntry(langl);
528                   while (se) {
529                     const char *l;
530 
531                     l=GWEN_StringListEntry_Data(se);
532                     DBG_DEBUG(GWEN_LOGDOMAIN, "Trying locale \"%s\"", l);
533                     assert(l);
534                     n=GWEN_XMLNode_FindFirstTag(node, "plugin", "lang", l);
535                     if (n)
536                       break;
537                     se=GWEN_StringListEntry_Next(se);
538                   } /* while */
539                 } /* if language list available */
540 
541                 if (!n)
542                   n=GWEN_XMLNode_FindFirstTag(node, "plugin", 0, 0);
543                 if (n) {
544                   GWEN_PLUGIN_DESCRIPTION *pd;
545                   int loadIt;
546 
547                   loadIt=1;
548                   if (type) {
549                     const char *ft;
550 
551                     ft=GWEN_XMLNode_GetProperty(n, "type", 0);
552                     if (!ft)
553                       loadIt=0;
554                     else if (strcasecmp(ft, type)!=0) {
555                       loadIt=0;
556                     }
557                   } /* if type specified */
558                   if (loadIt) {
559                     pd=GWEN_PluginDescription_new(n);
560                     if (!pd) {
561                       DBG_WARN(GWEN_LOGDOMAIN, "Bad plugin description");
562                     }
563                     else {
564                       GWEN_PluginDescription_SetFileName
565                       (pd, GWEN_Buffer_GetStart(nbuf));
566                       GWEN_Buffer_Crop(nbuf, 0, pathLen);
567                       GWEN_Buffer_SetPos(nbuf, pathLen);
568                       GWEN_PluginDescription_SetPath
569                       (pd, GWEN_Buffer_GetStart(nbuf));
570                       GWEN_PluginDescription_List2_PushBack(pdl, pd);
571                     }
572                   } /* if loadIt */
573                   else {
574                     DBG_INFO(GWEN_LOGDOMAIN,
575                              "Ignoring file \"%s\" (bad/missing type)",
576                              GWEN_Buffer_GetStart(nbuf));
577                   }
578                 }
579                 else {
580                   DBG_WARN(GWEN_LOGDOMAIN,
581                            "File \"%s\" does not contain a plugin "
582                            "description",
583                            GWEN_Buffer_GetStart(nbuf));
584                 }
585               }
586               GWEN_XMLNode_free(fileNode);
587             } /* if !dir */
588           } /* if stat was ok */
589         } /* if XML */
590       } /* if name has more than 3 chars */
591     } /* if not "." and not ".." */
592   } /* while */
593   GWEN_Directory_Close(d);
594   GWEN_Directory_free(d);
595   GWEN_Buffer_free(nbuf);
596 
597   return 0;
598 }
599 
600 
601 
602 
603 
604 
605 
606 
607 
608 
609 
610 
611