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