changed: the way how plugins work

all your plugin functions can have signature either:
void my_function(PluginInfo & info); or
void my_function();
only the main Init should have:
extern "C" void Init(PluginFunction & info);

added: directory 'plugins' for plugins
added: 'stats' plugin
		  


git-svn-id: svn://ttmath.org/publicrep/winix/trunk@624 e52654a7-88a9-db11-a3e9-0013d4bc506e
This commit is contained in:
2010-07-27 20:41:56 +00:00
parent e4683b9a05
commit 031ace3fe5
33 changed files with 1268 additions and 399 deletions

View File

@@ -12,7 +12,7 @@ all: $(o)
depend:
makedepend -Y. -f- *.cpp > Makefile.dep
makedepend -Y. -I.. -I../../ezc/src -f- *.cpp > Makefile.dep
echo -n "o = " > Makefile.o.dep
ls -1 *.cpp | xargs -I foo echo -n foo " " | sed -E "s/([^\.]*)\.cpp[ ]/\1\.o/g" >> Makefile.o.dep

View File

@@ -57,12 +57,12 @@ mounts.o: acceptencodingparser.h acceptbaseparser.h htmlfilter.h
mounts.o: postmultiparser.h ticket.h mountparser.h db.h
notify.o: log.h notify.h ../templatesnotify/templatesnotify.h ../core/mount.h
notify.o: ../core/locale.h ../confparser/confparser.h ../templates/misc.h
notify.o: ../templates/localefilter.h data.h dirs.h item.h dircontainer.h
notify.o: users.h user.h ugcontainer.h groups.h group.h functions.h
notify.o: function.h lastcontainer.h mounts.h mount.h error.h rebus.h
notify.o: loadavg.h misc.h request.h requesttypes.h session.h plugindata.h
notify.o: thread.h compress.h acceptencodingparser.h acceptbaseparser.h
notify.o: htmlfilter.h postmultiparser.h ticket.h
notify.o: ../templates/localefilter.h ../../ezc/src/ezc.h data.h dirs.h
notify.o: item.h dircontainer.h users.h user.h ugcontainer.h groups.h group.h
notify.o: functions.h function.h lastcontainer.h mounts.h mount.h error.h
notify.o: rebus.h loadavg.h misc.h request.h requesttypes.h session.h
notify.o: plugindata.h thread.h compress.h acceptencodingparser.h
notify.o: acceptbaseparser.h htmlfilter.h postmultiparser.h ticket.h
plugin.o: plugin.h request.h requesttypes.h session.h item.h error.h log.h
plugin.o: user.h rebus.h plugindata.h function.h thread.h compress.h
plugin.o: acceptencodingparser.h acceptbaseparser.h htmlfilter.h
@@ -88,8 +88,9 @@ request.o: postparser.h cookieparser.h data.h dirs.h dircontainer.h users.h
request.o: ugcontainer.h groups.h group.h functions.h lastcontainer.h
request.o: mounts.h mount.h loadavg.h plugin.h pluginmsg.h misc.h db.h
requestcontroller.o: requestcontroller.h ../content/content.h ../core/item.h
requestcontroller.o: ../templates/templates.h ../templates/patterncacher.h
requestcontroller.o: misc.h item.h ../templates/ckeditorgetparser.h
requestcontroller.o: ../templates/templates.h ../../ezc/src/ezc.h
requestcontroller.o: ../templates/patterncacher.h misc.h item.h
requestcontroller.o: ../templates/ckeditorgetparser.h
requestcontroller.o: ../core/httpsimpleparser.h ../core/log.h
requestcontroller.o: ../core/locale.h ../confparser/confparser.h
requestcontroller.o: ../templates/indexpatterns.h ../templates/localefilter.h

View File

@@ -79,7 +79,6 @@ bool Config::ReadConfig(bool errors_to_stdout_)
if( status == ConfParser::ok )
{
AssignValues();
data.SetAdditionalVariables();
return true;
}
@@ -151,7 +150,7 @@ void Config::AssignValues()
data.title_separator = Text("title_separator", " / ");
ListText(data.plugin_file, "plugin");
ListText(data.plugin_file, "plugins");
}

View File

@@ -11,11 +11,11 @@
#define headerfilecmslucoreconfig
#include <string>
#include "../confparser/confparser.h"
class Config
{
@@ -24,14 +24,6 @@ public:
bool ReadConfig(bool errors_to_stdout_);
private:
ConfParser conf_parser;
void ShowError();
void AssignValues();
std::string Text(const char * name);
std::string Text(const char * name, const char * def);
std::string Text(const std::string & name, const std::string & def);
@@ -47,17 +39,27 @@ private:
void ListText(std::vector<std::string> & list, const char * name);
void ListText(std::vector<std::string> & list, const std::string & name);
void NoLastSlash(std::string & s);
void NoFirstHttp(std::string & s);
private:
ConfParser conf_parser;
void ShowError();
void AssignValues();
std::string default_str;
int default_int;
bool default_bool;
bool errors_to_stdout;
void NoLastSlash(std::string & s);
void NoFirstHttp(std::string & s);
};
extern Config config;
#endif

View File

@@ -791,24 +791,27 @@ return result;
PGresult * Db::GetItemsQuery(const ItemQuery & iq)
PGresult * Db::GetItemsQuery(const ItemQuery & iq, bool skip_other_sel)
{
std::ostringstream query;
query << "select item.id";
if( iq.sel_parent_id ) query << " ,parent_id";
if( iq.sel_user_id ) query << " ,user_id, modification_user_id";
if( iq.sel_group_id ) query << " ,group_id";
if( iq.sel_guest_name) query << " ,guest_name";
if( iq.sel_privileges ) query << " ,privileges";
if( iq.sel_date ) query << " ,date_creation, date_modification";
if( iq.sel_subject ) query << " ,subject";
if( iq.sel_content ) query << " ,content, content_type, content_id";
if( iq.sel_url ) query << " ,url";
if( iq.sel_type ) query << " ,type";
if( iq.sel_default_item ) query << " ,default_item";
if( iq.sel_auth ) query << " ,auth, auth_path";
if( !skip_other_sel )
{
if( iq.sel_parent_id ) query << " ,parent_id";
if( iq.sel_user_id ) query << " ,user_id, modification_user_id";
if( iq.sel_group_id ) query << " ,group_id";
if( iq.sel_guest_name) query << " ,guest_name";
if( iq.sel_privileges ) query << " ,privileges";
if( iq.sel_date ) query << " ,date_creation, date_modification";
if( iq.sel_subject ) query << " ,subject";
if( iq.sel_content ) query << " ,content, content_type, content_id";
if( iq.sel_url ) query << " ,url";
if( iq.sel_type ) query << " ,type";
if( iq.sel_default_item ) query << " ,default_item";
if( iq.sel_auth ) query << " ,auth, auth_path";
}
query << " from core.item";
if( iq.sel_content ) query << " left join core.content on item.content_id = content.id";
@@ -857,8 +860,6 @@ void Db::GetItems(std::vector<Item> & item_table, const ItemQuery & item_query)
item_table.clear();
PGresult * r = 0;
item_table.clear();
try
{
AssertConnection();
@@ -886,6 +887,35 @@ void Db::GetItems(std::vector<Item> & item_table, const ItemQuery & item_query)
}
void Db::GetItems(std::vector<long> & item_table, const ItemQuery & item_query)
{
item_table.clear();
PGresult * r = 0;
try
{
AssertConnection();
r = GetItemsQuery(item_query, true);
AssertResultStatus(r, PGRES_TUPLES_OK);
int rows = PQntuples(r);
for(int i = 0 ; i<rows ; ++i)
{
long id = atol( AssertValue(r, i, 0) );
item_table.push_back(id);
}
}
catch(const Error &)
{
}
ClearResult(r);
}
// how many items there are in a 'parent_id' directory
long Db::Size(long parent_id, Item::Type type)
{

View File

@@ -82,7 +82,7 @@ public:
bool sort_asc;
void SetAll(bool sel, bool where_)
void SetAllSel(bool sel)
{
sel_parent_id = sel;
sel_user_id = sel;
@@ -96,13 +96,22 @@ public:
sel_type = sel;
sel_default_item= sel;
sel_auth = sel;
}
void SetAllWhere(bool where_)
{
where_id = where_;
where_parent_id = where_;
where_type = where_;
where_auth = where_;
}
void SetAll(bool sel, bool where_)
{
SetAllSel(sel);
SetAllWhere(where_);
}
void WhereId(long id_) { where_id = true; id = id_; }
void WhereParentId(long parent_id_) { where_parent_id = true; parent_id = parent_id_; }
void WhereType(Item::Type type_) { where_type = true; type = type_; }
@@ -125,8 +134,7 @@ public:
void GetItems(std::vector<Item> & item_table, const ItemQuery & item_query);
void GetItems(std::vector<long> & item_table, const ItemQuery & item_query);
// !! pobiera tylko jeden item (cos wymyslec innego z nazwa albo argumentem)
@@ -213,7 +221,7 @@ protected:
void CheckAllUrlSubjectModifyItem(Item & item);
PGresult * GetItemsQuery(const ItemQuery & iq);
PGresult * GetItemsQuery(const ItemQuery & iq, bool skip_other_sel = false);
bool DelItemDelItem(const Item & item);
void DelItemDelContent(const Item & item);

View File

@@ -324,6 +324,20 @@ return DateToStr(ptm);
}
const char * DateToStrWithoutHours(tm * ptm)
{
return DateToStr(ptm->tm_year + 1900, ptm->tm_mon+1, ptm->tm_mday);
}
const char * DateToStrWithoutHours(time_t t)
{
tm * ptm = std::localtime(&t);
return DateToStrWithoutHours(ptm);
}
// this format is used with cookies
const char * DateToStrCookie(int year, int month, int day, int hour, int min, int sec)

View File

@@ -36,6 +36,8 @@ const char * DateToStr(int year, int month, int day);
const char * DateToStr(int year, int month, int day, int hour, int min, int sec);
const char * DateToStr(tm * ptm);
const char * DateToStr(time_t t);
const char * DateToStrWithoutHours(tm * ptm);
const char * DateToStrWithoutHours(time_t t);
const char * DateToStrCookie(int year, int month, int day, int hour, int min, int sec);
const char * DateToStrCookie(tm * ptm);

View File

@@ -21,7 +21,7 @@ size_t i;
slots.clear();
for(i=0 ; i<plugins.size() ; ++i)
dlclose(plugins[i]);
dlclose(plugins[i].handle);
plugins.clear();
}
@@ -54,88 +54,158 @@ void Plugin::LoadPlugin(const std::string & filename)
}
void Plugin::LoadPlugin(const char * filename)
void * Plugin::LoadInitFun(const char * filename, Fun1 & fun_init)
{
void * p = dlopen(filename, RTLD_NOW | RTLD_LOCAL);
if( !p )
{
log << log1 << "Pl: cannot load a plugin: " << filename << logend;
/*
const char * t = dlerror();
if( t )
log << log1 << t << logend;
*/
return;
log << log1 << "Plugin: cannot load a plugin: " << filename << logend;
return 0;
}
Fun fun = (Fun)dlfunc(p, "Init");
fun_init = (Fun1)dlfunc(p, "Init");
if( !fun )
if( !fun_init )
{
log << log1 << "Pl: cannot load a plugin: " << filename << " (there is no Init() function)" << logend;
log << log1 << "Plugin: cannot load a plugin: " << filename
<< " (there is no Init() function)" << logend;
dlclose(p);
return 0;
}
log << log1 << "Plugin: plugin loaded"
<< ", file: " << filename
<< ", index: " << plugins.size() << logend;
return p;
}
void Plugin::LoadPlugin(const char * filename)
{
Fun1 fun_init;
void * plugin_handle;
int old_current_plugin;
if( !(plugin_handle = LoadInitFun(filename, fun_init)) )
return;
}
arg.Clear();
int old_current_plugin = current_plugin;
info.Clear();
old_current_plugin = current_plugin;
current_plugin = (int)plugins.size();
info.plugin_id = current_plugin;
current_plugin = (int)plugins.size();
arg.plugin_id = current_plugin;
fun_init(info);
if( fun(&arg) )
{
log << log1 << "Pl: plugin loaded: " << filename << ", index: " << plugins.size() << logend;
plugins.push_back(p);
}
else
{
log << log1 << "Pl: plugin Init() returned false (" << filename << ") " << logend;
dlclose(p);
}
PluginsItem item;
item.handle = plugin_handle;
item.plugin_name = (const char *)info.p1;
plugins.push_back(item);
current_plugin = old_current_plugin;
}
void Plugin::Call(int message, Slots::iterator & slot)
{
current_plugin = slot->second.index;
info.plugin_id = current_plugin;
Arg * Plugin::Call(int message, void * a, void * a2, void * a3)
if( request.session && current_plugin != -1 )
info.plugin_data_base = request.session->plugin_data.Get(current_plugin);
else
info.plugin_data_base = 0;
if( !slot->second.is_running )
{
slot->second.is_running = true;
if( slot->second.fun1 )
slot->second.fun1(info);
if( slot->second.fun2 )
slot->second.fun2();
slot->second.is_running = false;
}
else
{
log << log1 << "Plugin: id: " << slot->second.index
<< ", message: " << message
<< ", recurrences are not allowed" << logend;
}
}
void Plugin::Call(int message, void * p1_, void * p2_, long l1_, long l2_)
{
Slots::iterator i = slots.lower_bound(message);
arg.Clear();
int old_current_plugin = current_plugin;
for( ; i!=slots.end() && i->first==message ; ++i )
{
arg.app = a;
arg.app2 = a2;
arg.app3 = a3;
current_plugin = i->second.index;
arg.plugin_id = current_plugin;
info.Clear();
info.p1 = p1_;
info.p2 = p2_;
info.l1 = l1_;
info.l2 = l2_;
if( request.session && current_plugin != -1 )
arg.plugin_data_base = request.session->plugin_data.Get(current_plugin);
else
arg.plugin_data_base = 0;
if( i->second.fun(&arg) )
arg.ret_true++;
else
arg.ret_false++;
Call(message, i);
}
current_plugin = old_current_plugin;
return &arg;
}
void Plugin::Call(int message)
{
Call(message, 0, 0, 0, 0);
}
void Plugin::Call(int message, void * p1_)
{
Call(message, p1_, 0, 0, 0);
}
void Plugin::Call(int message, void * p1_, void * p2_)
{
Call(message, p1_, p2_, 0, 0);
}
void Plugin::Call(int message, long l1_)
{
Call(message, 0, 0, l1_, 0);
}
void Plugin::Call(int message, long l1_, long l2_)
{
Call(message, 0, 0, l1_, l2_);
}
void Plugin::Call(int message, void * p1_, long l1_)
{
Call(message, p1_, 0, l1_, 0);
}
void Plugin::Call(int message, void * p1_, long l1_, long l2_)
{
Call(message, p1_, 0, l1_, l2_);
}
void Plugin::Call(int message, void * p1_, void * p2_, long l1_)
{
Call(message, p1_, p2_, l1_, 0);
}
size_t Plugin::Size()
{
return plugins.size();
@@ -143,14 +213,26 @@ size_t Plugin::Size()
void Plugin::Assign(int message, Fun fun)
void Plugin::Assign(int message, Fun1 fun1)
{
Slot s;
Slot s;
s.fun = fun;
s.fun1 = fun1;
s.index = current_plugin;
slots.insert( std::make_pair(message, s) );
log << log3 << "Plugin: added function for message: " << message << ", plugin index: " << s.index << logend;
}
void Plugin::Assign(int message, Fun2 fun2)
{
Slot s;
s.fun2 = fun2;
s.index = current_plugin;
slots.insert( std::make_pair(message, s) );
log << log3 << "Plugin: added function for message: " << message << ", plugin index: " << s.index << logend;
}

View File

@@ -21,30 +21,56 @@
#include "plugindata.h"
// plugin arguments
struct Arg
/*
all your plugin functions can have signature either:
void my_function(PluginInfo & info); or
void my_function();
only the main Init should have:
extern "C" void Init(PluginFunction & info);
in the Init you can add your own functions by using plugin.Assign() method
and you can set the name of the plugin by setting info.p1 pointer
to a string buffer (const char *)
(this buffer will not be copied so it should not be destroyed after Init finishes)
*/
struct PluginInfo
{
void * app; // used for some purposes
void * app2; // used for some purposes
void * app3; // used for some purposes
// these variables are used for some purposes
// depending on a hook in which they are used
void * p1;
void * p2;
long l1;
long l2;
// unique plugin identifier
int plugin_id;
int plugin_id; // unique plugin identifier
// pointer to the plugin session (can be null if not set by the plugin)
// you should use WINIX_SESSION_CREATED and WINIX_SESSION_REMOVE
// to create your plugin's session data
PluginDataBase * plugin_data_base;
PluginDataBase * plugin_data_base; // pointer to the plugin session
int ret_true; // how many plugins returned true
int ret_false; // how many plugins returned false
// function return status
// default: false (if not set by the plugin)
bool ret;
void Clear()
{
app = 0;
app2 = 0;
app3 = 0;
ret_true = 0;
ret_false = 0;
p1 = 0;
p2 = 0;
l1 = 0;
l2 = 0;
plugin_id = -1;
plugin_data_base = 0;
ret = false;
}
};
@@ -58,46 +84,73 @@ public:
// normally: -1
int current_plugin;
// Fun is a type of a function you should provide in your plugin
typedef void (*Fun1)(PluginInfo &);
typedef void (*Fun2)(void);
// !! zmienic sygnature funkcji (niech nie zwraca zadnej wartosci, bo to tylko wkurwia)
// albo dodac jeszcze inna sygnature (niech nie pobiera zadnego argumentu)
typedef bool (*Fun)(Arg *);
//typedef void (*Fun2)();
struct Slot
{
Fun fun;
// Fun2 fun2; // dla drugiej sygnatury
int index; // plugin index
Fun1 fun1;
Fun2 fun2;
int index; // plugin index (which plugin has inserted the slot)
bool is_running;
Slot()
{
fun1 = 0;
fun2 = 0;
index = -1;
is_running = false;
}
};
Plugin();
~Plugin();
void LoadPlugin(const char * filename);
void LoadPlugin(const std::string & filename);
void LoadPlugins(const std::vector<std::string> & plugins);
void UnloadPlugins();
Arg * Call(int message, void * a=0, void * a2=0, void * a3=0);
void Call(int message);
void Call(int message, void * p1_);
void Call(int message, void * p1_, void * p2_);
void Call(int message, long l1_);
void Call(int message, long l1_, long l2_);
void Call(int message, void * p1_, long l1_);
void Call(int message, void * p1_, long l1_, long l2_);
void Call(int message, void * p1_, void * p2_, long l1_);
void Call(int message, void * p1_, void * p2_, long l1_, long l2_);
// how many plugins there are
size_t Size();
void Assign(int message, Fun);
// assign a function to a message
// you can assign more than one function to a specific message
void Assign(int message, Fun1);
void Assign(int message, Fun2);
private:
typedef std::vector<void*> Plugins;
struct PluginsItem
{
void * handle;
const char * plugin_name; // plugin name (can be null if was not set by the plugin)
};
typedef std::vector<PluginsItem> Plugins;
Plugins plugins;
typedef std::multimap<int, Slot> Slots;
Slots slots;
Arg arg;
PluginInfo info;
void * LoadInitFun(const char * filename, Fun1 & fun_init);
void Call(int message, Slots::iterator & slot);
};

View File

@@ -11,8 +11,10 @@
#ifndef headerfilecmslupluginmsg
#define headerfilecmslupluginmsg
// here you can add your own EZC functions ([function])
// PluginInfo.p1 is a pointer to Ezc::Functions object
#define WINIX_TEMPLATES_CREATEFUNCTIONS 999
#define WINIX_REQUEST_CLEAR 1000
#define WINIX_CONTENT_MAKE 2000
@@ -28,11 +30,23 @@
// when a session is changed (you can save a pointer to your data here)
#define WINIX_SESSION_CHANGED 3002
// all plugins have been started, now you can init
#define WINIX_PLUGIN_INIT 3003
// the winix is closing
#define WINIX_CLOSE 3004
// item was removed (rm function)
// PluginInfo::l1 is the file (item) id
#define WINIX_FILE_REMOVED 3005
// directory was removed (rm function)
// PluginInfo::l1 is the dir id
#define WINIX_DIR_REMOVED 3006
// preparing to remove a directory (rm function)
// PluginInfo::l1 is the dir id
#define WINIX_DIR_PREPARE_TO_REMOVE 3007