00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #ifdef HAVE_CONFIG_H
00029 # include <config.h>
00030 #endif
00031
00032 #include "plugindescr_p.h"
00033 #include "i18n_l.h"
00034 #include <gwenhywfar/buffer.h>
00035 #include <gwenhywfar/debug.h>
00036 #include <gwenhywfar/directory.h>
00037 #include <gwenhywfar/bio_buffer.h>
00038
00039 #include <sys/types.h>
00040 #include <sys/stat.h>
00041 #ifdef HAVE_UNISTD_H
00042 # include <unistd.h>
00043 #endif
00044 #include <errno.h>
00045 #include <string.h>
00046 #ifdef HAVE_STRINGS_H
00047 # include <strings.h>
00048 #endif
00049
00050
00051
00052 GWEN_LIST_FUNCTIONS(GWEN_PLUGIN_DESCRIPTION, GWEN_PluginDescription)
00053 GWEN_LIST2_FUNCTIONS(GWEN_PLUGIN_DESCRIPTION, GWEN_PluginDescription)
00054
00055
00056
00057 GWEN_PLUGIN_DESCRIPTION *GWEN_PluginDescription_new(GWEN_XMLNODE *node){
00058 GWEN_PLUGIN_DESCRIPTION *pd;
00059 const char *p;
00060
00061 GWEN_NEW_OBJECT(GWEN_PLUGIN_DESCRIPTION, pd);
00062 DBG_MEM_INC("GWEN_PLUGIN_DESCRIPTION", 0);
00063 GWEN_LIST_INIT(GWEN_PLUGIN_DESCRIPTION, pd);
00064 p=GWEN_XMLNode_GetProperty(node, "name", 0);
00065 if (!p) {
00066 DBG_ERROR(GWEN_LOGDOMAIN, "Unnamed plugin");
00067 GWEN_PluginDescription_free(pd);
00068 return 0;
00069 }
00070 pd->name=strdup(p);
00071 pd->xmlNode=GWEN_XMLNode_dup(node);
00072 p=GWEN_XMLNode_GetProperty(node, "type", 0);
00073 if (!p) {
00074 DBG_ERROR(GWEN_LOGDOMAIN, "Plugin has no type");
00075 GWEN_PluginDescription_free(pd);
00076 return 0;
00077 }
00078 pd->type=strdup(p);
00079 p=GWEN_XMLNode_GetLocalizedCharValue(node, "version", 0);
00080 if (p)
00081 pd->version=strdup(p);
00082 p=GWEN_XMLNode_GetLocalizedCharValue(node, "author", 0);
00083 if (p)
00084 pd->author=strdup(p);
00085 p=GWEN_XMLNode_GetLocalizedCharValue(node, "short", 0);
00086 if (p)
00087 pd->shortDescr=strdup(p);
00088 p=GWEN_XMLNode_GetLocalizedCharValue(node, "descr", 0);
00089 if (p)
00090 pd->longDescr=strdup(p);
00091 return pd;
00092 }
00093
00094
00095
00096 void GWEN_PluginDescription_free(GWEN_PLUGIN_DESCRIPTION *pd){
00097 if (pd) {
00098 DBG_MEM_DEC("GWEN_PLUGIN_DESCRIPTION");
00099 GWEN_LIST_FINI(GWEN_PLUGIN_DESCRIPTION, pd);
00100 free(pd->path);
00101 GWEN_XMLNode_free(pd->xmlNode);
00102 free(pd->fileName);
00103 free(pd->longDescr);
00104 free(pd->shortDescr);
00105 free(pd->author);
00106 free(pd->version);
00107 free(pd->type);
00108 free(pd->name);
00109 GWEN_FREE_OBJECT(pd);
00110 }
00111 }
00112
00113
00114
00115 GWEN_PLUGIN_DESCRIPTION*
00116 GWEN_PluginDescription_dup(const GWEN_PLUGIN_DESCRIPTION *pd) {
00117 GWEN_PLUGIN_DESCRIPTION *np;
00118 const char *s;
00119
00120 assert(pd);
00121 GWEN_NEW_OBJECT(GWEN_PLUGIN_DESCRIPTION, np);
00122 DBG_MEM_INC("GWEN_PLUGIN_DESCRIPTION", 0);
00123 GWEN_LIST_INIT(GWEN_PLUGIN_DESCRIPTION, np);
00124
00125 s=pd->fileName;
00126 if (s) np->fileName=strdup(s);
00127
00128 s=pd->path;
00129 if (s) np->path=strdup(s);
00130 s=pd->name;
00131 if (s) np->name=strdup(s);
00132 s=pd->type;
00133 if (s) np->type=strdup(s);
00134 s=pd->shortDescr;
00135 if (s) np->shortDescr=strdup(s);
00136 s=pd->author;
00137 if (s) np->author=strdup(s);
00138 s=pd->version;
00139 if (s) np->version=strdup(s);
00140 s=pd->longDescr;
00141 if (s) np->longDescr=strdup(s);
00142 np->isActive=pd->isActive;
00143 if (pd->xmlNode)
00144 np->xmlNode=GWEN_XMLNode_dup(pd->xmlNode);
00145
00146 return np;
00147 }
00148
00149
00150
00151 GWEN_PLUGIN_DESCRIPTION*
00152 GWEN_PluginDescription_List2_freeAll_cb(GWEN_PLUGIN_DESCRIPTION *pd,
00153 void *user_data) {
00154 GWEN_PluginDescription_free(pd);
00155 return 0;
00156 }
00157
00158
00159
00160 void GWEN_PluginDescription_List2_freeAll(GWEN_PLUGIN_DESCRIPTION_LIST2 *pdl){
00161 GWEN_PluginDescription_List2_ForEach
00162 (pdl,
00163 GWEN_PluginDescription_List2_freeAll_cb,
00164 0);
00165 GWEN_PluginDescription_List2_free(pdl);
00166 }
00167
00168
00169
00170 const char *GWEN_PluginDescription_GetPath(const GWEN_PLUGIN_DESCRIPTION *pd){
00171 assert(pd);
00172 return pd->path;
00173 }
00174
00175
00176
00177 void GWEN_PluginDescription_SetPath(GWEN_PLUGIN_DESCRIPTION *pd,
00178 const char *s){
00179 assert(pd);
00180 free(pd->path);
00181 if (s) pd->path=strdup(s);
00182 else pd->path=0;
00183 }
00184
00185
00186
00187 const char *GWEN_PluginDescription_GetName(const GWEN_PLUGIN_DESCRIPTION *pd){
00188 assert(pd);
00189 return pd->name;
00190 }
00191
00192
00193
00194 const char *GWEN_PluginDescription_GetType(const GWEN_PLUGIN_DESCRIPTION *pd){
00195 assert(pd);
00196 return pd->type;
00197 }
00198
00199
00200
00201 const char*
00202 GWEN_PluginDescription_GetShortDescr(const GWEN_PLUGIN_DESCRIPTION *pd){
00203 assert(pd);
00204 return pd->shortDescr;
00205 }
00206
00207
00208
00209 const char*
00210 GWEN_PluginDescription_GetAuthor(const GWEN_PLUGIN_DESCRIPTION *pd){
00211 assert(pd);
00212 return pd->author;
00213 }
00214
00215
00216
00217 const char*
00218 GWEN_PluginDescription_GetVersion(const GWEN_PLUGIN_DESCRIPTION *pd){
00219 assert(pd);
00220 return pd->version;
00221 }
00222
00223
00224
00225 const char*
00226 GWEN_PluginDescription_GetLongDescr(const GWEN_PLUGIN_DESCRIPTION *pd){
00227 assert(pd);
00228 return pd->longDescr;
00229 }
00230
00231
00232
00233 int
00234 GWEN_PluginDescription__GetLongDescrByFormat(const GWEN_PLUGIN_DESCRIPTION *pd,
00235 const char *s,
00236 GWEN_BUFFER *buf){
00237 GWEN_XMLNODE *n;
00238
00239 assert(pd);
00240 assert(pd->xmlNode);
00241
00242 n=GWEN_XMLNode_FindFirstTag(pd->xmlNode, "descr", 0, 0);
00243 if (n) {
00244 n=GWEN_XMLNode_FindFirstTag(n, "text", "format", s);
00245 while (n) {
00246 if (0==GWEN_XMLNode_GetProperty(n, "lang", 0)) {
00247 int rv;
00248
00249 rv=GWEN_XMLNode_toBuffer(n, buf, GWEN_XML_FLAGS_TOLERANT_ENDTAGS);
00250 if (rv) {
00251 DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
00252 return rv;
00253 }
00254 return 0;
00255 }
00256 n=GWEN_XMLNode_FindNextTag(n, "text", "format", s);
00257 }
00258 }
00259
00260 return -1;
00261 }
00262
00263
00264
00265 int
00266 GWEN_PluginDescription__GetLocalizedLongDescrByFormat(const GWEN_PLUGIN_DESCRIPTION *pd,
00267 const char *s,
00268 const char *lang,
00269 GWEN_BUFFER *buf){
00270 GWEN_XMLNODE *n;
00271
00272 assert(pd);
00273 assert(pd->xmlNode);
00274
00275 n=GWEN_XMLNode_FindFirstTag(pd->xmlNode, "descr", 0, 0);
00276 if (n) {
00277 n=GWEN_XMLNode_FindFirstTag(n, "text", "lang", lang);
00278 while (n) {
00279 const char *fmt;
00280
00281 fmt=GWEN_XMLNode_GetProperty(n, "format", 0);
00282 if (fmt && strcasecmp(fmt, s)==0) {
00283 int rv;
00284
00285 rv=GWEN_XMLNode_toBuffer(n, buf, GWEN_XML_FLAGS_TOLERANT_ENDTAGS);
00286 if (rv) {
00287 DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
00288 return rv;
00289 }
00290 return 0;
00291 }
00292 n=GWEN_XMLNode_FindNextTag(n, "text", "lang", lang);
00293 }
00294 }
00295
00296 return -1;
00297 }
00298
00299
00300
00301 int
00302 GWEN_PluginDescription_GetLongDescrByFormat(const GWEN_PLUGIN_DESCRIPTION *pd,
00303 const char *s,
00304 GWEN_BUFFER *buf){
00305 GWEN_STRINGLIST *langl;
00306 int rv;
00307
00308 langl=GWEN_I18N_GetCurrentLocaleList();
00309 if (langl) {
00310 GWEN_STRINGLISTENTRY *se;
00311
00312 se=GWEN_StringList_FirstEntry(langl);
00313 while(se) {
00314 const char *l;
00315
00316 l=GWEN_StringListEntry_Data(se);
00317 DBG_NOTICE(GWEN_LOGDOMAIN, "Trying locale \"%s\"", l);
00318 assert(l);
00319
00320 rv=GWEN_PluginDescription__GetLocalizedLongDescrByFormat(pd,
00321 s,
00322 l,
00323 buf);
00324 if (rv==0)
00325 return rv;
00326
00327 se=GWEN_StringListEntry_Next(se);
00328 }
00329 }
00330
00331
00332 rv=GWEN_PluginDescription__GetLongDescrByFormat(pd, s, buf);
00333 if (rv) {
00334 DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
00335 return rv;
00336 }
00337
00338 return 0;
00339 }
00340
00341
00342 const char*
00343 GWEN_PluginDescription_GetFileName(const GWEN_PLUGIN_DESCRIPTION *pd){
00344 assert(pd);
00345 return pd->fileName;
00346 }
00347
00348
00349
00350 void GWEN_PluginDescription_SetFileName(GWEN_PLUGIN_DESCRIPTION *pd,
00351 const char *s){
00352 assert(pd);
00353 free(pd->fileName);
00354 if (s) pd->fileName=strdup(s);
00355 else pd->fileName=0;
00356 }
00357
00358
00359
00360 GWEN_XMLNODE*
00361 GWEN_PluginDescription_GetXmlNode(const GWEN_PLUGIN_DESCRIPTION *pd){
00362 assert(pd);
00363 return pd->xmlNode;
00364 }
00365
00366
00367
00368 GWEN_PLUGIN_DESCRIPTION_LIST2 *GWEN_LoadPluginDescrs(const char *path) {
00369 GWEN_PLUGIN_DESCRIPTION_LIST2 *pl;
00370 int rv;
00371
00372 pl=GWEN_PluginDescription_List2_new();
00373
00374 rv=GWEN_LoadPluginDescrsByType(path, 0, pl);
00375 if (GWEN_PluginDescription_List2_GetSize(pl)==0) {
00376 GWEN_PluginDescription_List2_free(pl);
00377 return 0;
00378 }
00379 return pl;
00380 }
00381
00382
00383
00384 int GWEN_PluginDescription_IsActive(const GWEN_PLUGIN_DESCRIPTION *pd){
00385 assert(pd);
00386 return pd->isActive;
00387 }
00388
00389
00390
00391 void GWEN_PluginDescription_SetIsActive(GWEN_PLUGIN_DESCRIPTION *pd, int i){
00392 assert(pd);
00393 pd->isActive=i;
00394 }
00395
00396
00397
00398 int GWEN_LoadPluginDescrsByType(const char *path,
00399 const char *type,
00400 GWEN_PLUGIN_DESCRIPTION_LIST2 *pdl){
00401 GWEN_DIRECTORY *d;
00402 GWEN_BUFFER *nbuf;
00403 char nbuffer[64];
00404 unsigned int pathLen;
00405
00406 if (!path)
00407 path="";
00408
00409
00410 nbuf=GWEN_Buffer_new(0, 256, 0, 1);
00411 GWEN_Buffer_AppendString(nbuf, path);
00412 pathLen=GWEN_Buffer_GetUsedBytes(nbuf);
00413
00414 d=GWEN_Directory_new();
00415 if (GWEN_Directory_Open(d, GWEN_Buffer_GetStart(nbuf))) {
00416 DBG_INFO(GWEN_LOGDOMAIN,
00417 "Path \"%s\" is not available",
00418 GWEN_Buffer_GetStart(nbuf));
00419 GWEN_Buffer_free(nbuf);
00420 GWEN_Directory_free(d);
00421 return -1;
00422 }
00423
00424 while(!GWEN_Directory_Read(d,
00425 nbuffer,
00426 sizeof(nbuffer))) {
00427 if (strcmp(nbuffer, ".") &&
00428 strcmp(nbuffer, "..")) {
00429 int nlen;
00430
00431 nlen=strlen(nbuffer);
00432 if (nlen>3) {
00433 if (strcasecmp(nbuffer+nlen-4, ".xml")==0) {
00434 struct stat st;
00435
00436 GWEN_Buffer_Crop(nbuf, 0, pathLen);
00437 GWEN_Buffer_SetPos(nbuf, pathLen);
00438 GWEN_Buffer_AppendByte(nbuf, GWEN_DIR_SEPARATOR);
00439 GWEN_Buffer_AppendString(nbuf, nbuffer);
00440
00441 if (stat(GWEN_Buffer_GetStart(nbuf), &st)) {
00442 DBG_ERROR(GWEN_LOGDOMAIN, "stat(%s): %s",
00443 GWEN_Buffer_GetStart(nbuf),
00444 strerror(errno));
00445 }
00446 else {
00447 if (!S_ISDIR(st.st_mode)) {
00448 GWEN_XMLNODE *fileNode;
00449
00450 fileNode=GWEN_XMLNode_new(GWEN_XMLNodeTypeTag, "root");
00451 if (GWEN_XML_ReadFile(fileNode,
00452 GWEN_Buffer_GetStart(nbuf),
00453 GWEN_XML_FLAGS_DEFAULT |
00454 GWEN_XML_FLAGS_HANDLE_HEADERS |
00455 GWEN_XML_FLAGS_HANDLE_OPEN_HTMLTAGS)) {
00456 DBG_WARN(GWEN_LOGDOMAIN,
00457 "Bad file \"%s\"", GWEN_Buffer_GetStart(nbuf));
00458 }
00459 else {
00460 GWEN_XMLNODE *node;
00461 GWEN_XMLNODE *n;
00462 GWEN_STRINGLIST *langl;
00463
00464 n=0;
00465 node=GWEN_XMLNode_FindFirstTag(fileNode, "PluginDescr", 0, 0);
00466 if (!node)
00467 node=fileNode;
00468 langl=GWEN_I18N_GetCurrentLocaleList();
00469 if (langl) {
00470 GWEN_STRINGLISTENTRY *se;
00471
00472 se=GWEN_StringList_FirstEntry(langl);
00473 while(se) {
00474 const char *l;
00475
00476 l=GWEN_StringListEntry_Data(se);
00477 DBG_DEBUG(GWEN_LOGDOMAIN, "Trying locale \"%s\"", l);
00478 assert(l);
00479 n=GWEN_XMLNode_FindFirstTag(node, "plugin", "lang", l);
00480 if (n)
00481 break;
00482 se=GWEN_StringListEntry_Next(se);
00483 }
00484 }
00485
00486 if (!n)
00487 n=GWEN_XMLNode_FindFirstTag(node, "plugin", 0, 0);
00488 if (n) {
00489 GWEN_PLUGIN_DESCRIPTION *pd;
00490 int loadIt;
00491
00492 loadIt=1;
00493 if (type) {
00494 const char *ft;
00495
00496 ft=GWEN_XMLNode_GetProperty(n, "type", 0);
00497 if (!ft)
00498 loadIt=0;
00499 else if (strcasecmp(ft, type)!=0){
00500 loadIt=0;
00501 }
00502 }
00503 if (loadIt) {
00504 pd=GWEN_PluginDescription_new(n);
00505 if (!pd) {
00506 DBG_WARN(GWEN_LOGDOMAIN, "Bad plugin description");
00507 }
00508 else {
00509 GWEN_PluginDescription_SetFileName
00510 (pd, GWEN_Buffer_GetStart(nbuf));
00511 GWEN_Buffer_Crop(nbuf, 0, pathLen);
00512 GWEN_Buffer_SetPos(nbuf, pathLen);
00513 GWEN_PluginDescription_SetPath
00514 (pd, GWEN_Buffer_GetStart(nbuf));
00515 GWEN_PluginDescription_List2_PushBack(pdl, pd);
00516 }
00517 }
00518 else {
00519 DBG_INFO(GWEN_LOGDOMAIN,
00520 "Ignoring file \"%s\" (bad/missing type)",
00521 GWEN_Buffer_GetStart(nbuf));
00522 }
00523 }
00524 else {
00525 DBG_WARN(GWEN_LOGDOMAIN,
00526 "File \"%s\" does not contain a plugin "
00527 "description",
00528 GWEN_Buffer_GetStart(nbuf));
00529 }
00530 }
00531 GWEN_XMLNode_free(fileNode);
00532 }
00533 }
00534 }
00535 }
00536 }
00537 }
00538 GWEN_Directory_Close(d);
00539 GWEN_Directory_free(d);
00540 GWEN_Buffer_free(nbuf);
00541
00542 return 0;
00543 }
00544
00545
00546
00547
00548
00549
00550
00551
00552
00553
00554
00555