added: issues ticket system

added functions: ticket, createticket, editticket
         (there is no 'rm' function working for tickets yet)
changed: mount parser and mount points
         now we have more parameters (arguments in parameters)
some refactoring in functions 'emacs' and 'mkdir'



git-svn-id: svn://ttmath.org/publicrep/cmslu/trunk@554 e52654a7-88a9-db11-a3e9-0013d4bc506e
This commit is contained in:
2010-01-25 04:52:17 +00:00
parent 356e93914b
commit 89daf6489d
48 changed files with 2856 additions and 874 deletions

View File

@@ -4,21 +4,21 @@ acceptbaseparser.o: acceptbaseparser.h
compress.o: compress.h log.h
config.o: config.h ../confparser/confparser.h log.h data.h dirs.h item.h
config.o: dircontainer.h users.h user.h ugcontainer.h groups.h group.h
config.o: functions.h function.h lastcontainer.h mounts.h mount.h rebus.h
config.o: plugin.h request.h requesttypes.h session.h done.h error.h thread.h
config.o: functions.h function.h lastcontainer.h mounts.h mount.h error.h
config.o: rebus.h plugin.h request.h requesttypes.h session.h done.h thread.h
config.o: compress.h acceptencodingparser.h acceptbaseparser.h htmlfilter.h
config.o: postmultiparser.h pluginmsg.h misc.h
config.o: postmultiparser.h ticket.h pluginmsg.h misc.h
data.o: data.h dirs.h item.h dircontainer.h users.h user.h ugcontainer.h
data.o: log.h groups.h group.h functions.h function.h lastcontainer.h
data.o: mounts.h mount.h rebus.h
data.o: mounts.h mount.h error.h rebus.h
db.o: db.h item.h user.h group.h thread.h error.h log.h dircontainer.h
db.o: ugcontainer.h misc.h
db.o: ugcontainer.h ticket.h misc.h
db_itemcolumns.o: db.h item.h user.h group.h thread.h error.h log.h
db_itemcolumns.o: dircontainer.h ugcontainer.h
db_itemcolumns.o: dircontainer.h ugcontainer.h ticket.h
dircontainer.o: dircontainer.h item.h log.h
dirs.o: dirs.h item.h dircontainer.h error.h log.h db.h user.h group.h
dirs.o: thread.h ugcontainer.h data.h users.h groups.h functions.h function.h
dirs.o: lastcontainer.h mounts.h mount.h rebus.h
dirs.o: thread.h ugcontainer.h ticket.h data.h users.h groups.h functions.h
dirs.o: function.h lastcontainer.h mounts.h mount.h rebus.h
done.o: done.h
error.o: error.h log.h
function.o: function.h item.h
@@ -26,39 +26,39 @@ functioncodeparser.o: functioncodeparser.h item.h function.h log.h
functionparser.o: functionparser.h requesttypes.h log.h item.h error.h data.h
functionparser.o: dirs.h dircontainer.h users.h user.h ugcontainer.h groups.h
functionparser.o: group.h functions.h function.h lastcontainer.h mounts.h
functionparser.o: mount.h rebus.h db.h thread.h request.h session.h done.h
functionparser.o: compress.h acceptencodingparser.h acceptbaseparser.h
functionparser.o: mount.h rebus.h db.h thread.h ticket.h request.h session.h
functionparser.o: done.h compress.h acceptencodingparser.h acceptbaseparser.h
functionparser.o: htmlfilter.h postmultiparser.h
functions.o: functions.h function.h item.h
groups.o: groups.h group.h ugcontainer.h log.h db.h item.h user.h thread.h
groups.o: error.h dircontainer.h
groups.o: error.h dircontainer.h ticket.h
htmlfilter.o: htmlfilter.h
httpsimpleparser.o: httpsimpleparser.h
lastcontainer.o: lastcontainer.h log.h
log.o: log.h
misc.o: misc.h item.h log.h data.h dirs.h dircontainer.h users.h user.h
misc.o: ugcontainer.h groups.h group.h functions.h function.h lastcontainer.h
misc.o: mounts.h mount.h rebus.h
misc.o: mounts.h mount.h error.h rebus.h
mount.o: mount.h
mountparser.o: mountparser.h mount.h item.h error.h log.h data.h dirs.h
mountparser.o: dircontainer.h users.h user.h ugcontainer.h groups.h group.h
mountparser.o: functions.h function.h lastcontainer.h mounts.h rebus.h
mounts.o: mounts.h mount.h data.h dirs.h item.h dircontainer.h users.h user.h
mounts.o: ugcontainer.h log.h groups.h group.h functions.h function.h
mounts.o: lastcontainer.h rebus.h request.h requesttypes.h session.h done.h
mounts.o: error.h thread.h compress.h acceptencodingparser.h
mounts.o: acceptbaseparser.h htmlfilter.h postmultiparser.h mountparser.h
mounts.o: db.h
mountparser.o: functions.h function.h lastcontainer.h mounts.h rebus.h misc.h
mounts.o: mounts.h mount.h error.h log.h data.h dirs.h item.h dircontainer.h
mounts.o: users.h user.h ugcontainer.h groups.h group.h functions.h
mounts.o: function.h lastcontainer.h rebus.h request.h requesttypes.h
mounts.o: session.h done.h thread.h compress.h acceptencodingparser.h
mounts.o: acceptbaseparser.h htmlfilter.h postmultiparser.h ticket.h
mounts.o: mountparser.h db.h
notify.o: log.h notify.h ../templatesnotify/templatesnotify.h ../core/mount.h
notify.o: data.h dirs.h item.h dircontainer.h users.h user.h ugcontainer.h
notify.o: groups.h group.h functions.h function.h lastcontainer.h mounts.h
notify.o: mount.h rebus.h misc.h request.h requesttypes.h session.h done.h
notify.o: error.h thread.h compress.h acceptencodingparser.h
notify.o: acceptbaseparser.h htmlfilter.h postmultiparser.h
notify.o: mount.h error.h rebus.h misc.h request.h requesttypes.h session.h
notify.o: done.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 done.h item.h error.h
plugin.o: log.h user.h rebus.h function.h thread.h compress.h
plugin.o: acceptencodingparser.h acceptbaseparser.h htmlfilter.h
plugin.o: postmultiparser.h data.h dirs.h dircontainer.h users.h
plugin.o: postmultiparser.h ticket.h data.h dirs.h dircontainer.h users.h
plugin.o: ugcontainer.h groups.h group.h functions.h lastcontainer.h mounts.h
plugin.o: mount.h pluginmsg.h
postmultiparser.o: postmultiparser.h error.h log.h requesttypes.h data.h
@@ -69,20 +69,21 @@ rebus.o: log.h rebus.h misc.h item.h
request.o: request.h requesttypes.h session.h done.h item.h error.h log.h
request.o: user.h rebus.h function.h thread.h compress.h
request.o: acceptencodingparser.h acceptbaseparser.h htmlfilter.h
request.o: postmultiparser.h getparser.h httpsimpleparser.h postparser.h
request.o: cookieparser.h data.h dirs.h dircontainer.h users.h ugcontainer.h
request.o: groups.h group.h functions.h lastcontainer.h mounts.h mount.h
request.o: plugin.h pluginmsg.h misc.h
request.o: postmultiparser.h ticket.h getparser.h httpsimpleparser.h
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 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: ../core/thread.h sessionmanager.h sessioncontainer.h
requestcontroller.o: session.h done.h item.h error.h log.h user.h rebus.h
requestcontroller.o: functionparser.h requesttypes.h data.h dirs.h
requestcontroller.o: dircontainer.h users.h ugcontainer.h groups.h group.h
requestcontroller.o: functions.h function.h lastcontainer.h mounts.h mount.h
requestcontroller.o: request.h thread.h compress.h acceptencodingparser.h
requestcontroller.o: acceptbaseparser.h htmlfilter.h postmultiparser.h
requestcontroller.o: postparser.h httpsimpleparser.h cookieparser.h notify.h
requestcontroller.o: ../core/thread.h ../core/ticket.h ../core/done.h
requestcontroller.o: sessionmanager.h sessioncontainer.h session.h done.h
requestcontroller.o: item.h error.h log.h user.h rebus.h functionparser.h
requestcontroller.o: requesttypes.h data.h dirs.h dircontainer.h users.h
requestcontroller.o: ugcontainer.h groups.h group.h functions.h function.h
requestcontroller.o: lastcontainer.h mounts.h mount.h request.h thread.h
requestcontroller.o: compress.h acceptencodingparser.h acceptbaseparser.h
requestcontroller.o: htmlfilter.h postmultiparser.h ticket.h postparser.h
requestcontroller.o: httpsimpleparser.h cookieparser.h notify.h
requestcontroller.o: ../templatesnotify/templatesnotify.h ../core/mount.h
session.o: session.h done.h item.h error.h log.h user.h rebus.h
sessioncontainer.o: sessioncontainer.h session.h done.h item.h error.h log.h
@@ -92,8 +93,8 @@ sessioncontainer.o: lastcontainer.h mounts.h mount.h
sessionmanager.o: sessionmanager.h sessioncontainer.h session.h done.h item.h
sessionmanager.o: error.h log.h user.h rebus.h request.h requesttypes.h
sessionmanager.o: function.h thread.h compress.h acceptencodingparser.h
sessionmanager.o: acceptbaseparser.h htmlfilter.h postmultiparser.h data.h
sessionmanager.o: dirs.h dircontainer.h users.h ugcontainer.h groups.h
sessionmanager.o: acceptbaseparser.h htmlfilter.h postmultiparser.h ticket.h
sessionmanager.o: data.h dirs.h dircontainer.h users.h ugcontainer.h groups.h
sessionmanager.o: group.h functions.h lastcontainer.h mounts.h mount.h
sessionmanager.o: sessionparser.h
sessionparser.o: sessionparser.h session.h done.h item.h error.h log.h user.h
@@ -101,4 +102,4 @@ sessionparser.o: rebus.h sessioncontainer.h data.h dirs.h dircontainer.h
sessionparser.o: users.h ugcontainer.h groups.h group.h functions.h
sessionparser.o: function.h lastcontainer.h mounts.h mount.h
users.o: users.h user.h ugcontainer.h log.h db.h item.h group.h thread.h
users.o: error.h dircontainer.h
users.o: error.h dircontainer.h ticket.h

View File

@@ -935,6 +935,42 @@ Error Db::GetItem(long parent_id, const std::string & url, Item & item)
return result;
}
Error Db::GetItemById(long item_id, Item & item)
{
PGresult * r = 0;
Error result = Error::ok;
try
{
AssertConnection();
std::ostringstream query;
query << "select * from core.item left join core.content on item.content_id = content.id where item.id='" << item_id << "';";
r = AssertQuery( query.str() );
AssertResultStatus(r, PGRES_TUPLES_OK);
int rows = PQntuples(r);
if( rows == 0 )
throw Error(Error::no_item);
ItemColumns col;
col.SetColumns(r);
col.SetItem(r, 0, item);
}
catch(const Error & e)
{
result = e;
}
ClearResult(r);
return result;
}
long Db::GetItemId(long parent_id, const std::string & url, Item::Type type)
{
@@ -1443,7 +1479,10 @@ Error Db::GetThreadByDirId(long dir_id, Thread & thread)
AssertConnection();
std::ostringstream query;
query << "select thread.id, thread.parent_id, thread.dir_id, thread.closed, thread.items, thread.last_item, item.date_modification, item.user_id from core.thread left join core.item on thread.last_item = item.id where thread.dir_id = '" << dir_id << "';";
query << "select thread.id, thread.parent_id, thread.dir_id, thread.closed, thread.items, "
"thread.last_item, item.date_modification, item.user_id "
"from core.thread left join core.item on thread.last_item = item.id "
"where thread.dir_id = '" << dir_id << "';";
r = AssertQuery( query.str() );
AssertResultStatus(r, PGRES_TUPLES_OK);
@@ -1513,7 +1552,7 @@ Error Db::GetThreads(long parent_id, std::vector<Thread> & thread_tab)
int cclosed = AssertColumn(r, "closed");
int citems = AssertColumn(r, "items");
int clast_item = AssertColumn(r, "last_item");
int cdate_modification = PQfnumber(r, "date_modification");
int cdate_modification = PQfnumber(r, "date_modification"); // !! czemu tutaj jest pqfnumber zamiast assertcolumn?
int cuser_id = PQfnumber(r, "user_id");
int cguest_name = PQfnumber(r, "guest_name");
@@ -1676,3 +1715,197 @@ Error Db::RemoveThread(long dir_id)
return status;
}
Error Db::GetTicketByDirId(long dir_id, Ticket & ticket)
{
PGresult * r = 0;
Error status = Error::ok;
try
{
AssertConnection();
std::ostringstream query;
query << "select ticket.id, ticket.dir_id, ticket.parent_id, ticket.type, ticket.status, ticket.priority, "
"ticket.category, ticket.expected, ticket.progress, ticket.item_id "
"from core.ticket "
"where ticket.dir_id = '" << dir_id << "';";
r = AssertQuery( query.str() );
AssertResultStatus(r, PGRES_TUPLES_OK);
int rows = PQntuples(r);
if( rows > 1 )
log << log1 << "Db: there is more than one ticket with dir_id: " << dir_id << logend;
else
if( rows == 0 )
throw Error(Error::no_ticket);
TicketColumns tc;
tc.SetColumns(r);
tc.SetTicket(r, 0, ticket);
}
catch(const Error & e)
{
status = e;
}
ClearResult(r);
return status;
}
Error Db::GetTickets(long parent_id, std::vector<Ticket> & ticket_tab)
{
PGresult * r = 0;
Error status = Error::ok;
try
{
AssertConnection();
std::ostringstream query;
query << "select ticket.id, ticket.dir_id, ticket.parent_id, ticket.type, ticket.status, ticket.priority, "
"ticket.category, ticket.expected, ticket.progress, ticket.item_id "
"from core.ticket "
"where ticket.parent_id = '" << parent_id << "';";
r = AssertQuery( query.str() );
AssertResultStatus(r, PGRES_TUPLES_OK);
int rows = PQntuples(r);
Ticket ticket;
TicketColumns tc;
tc.SetColumns(r);
for(int i=0 ; i<rows ; ++i)
{
tc.SetTicket(r, i, ticket);
ticket_tab.push_back(ticket);
}
}
catch(const Error & e)
{
status = e;
}
ClearResult(r);
return status;
}
/*
bool Db::IsTicket(long dir_id)
{
PGresult * r = 0;
bool is_ticket = false;
try
{
AssertConnection();
std::ostringstream query;
query << "select ticket.id from core.ticket "
"where ticket.dir_id = '" << dir_id << "';";
r = AssertQuery( query.str() );
AssertResultStatus(r, PGRES_TUPLES_OK);
is_ticket = (PQntuples(r) == 1);
}
catch(const Error &)
{
}
ClearResult(r);
return is_ticket;
}
*/
Error Db::AddTicket(Ticket & ticket)
{
PGresult * r = 0;
Error status = Error::ok;
try
{
AssertConnection();
std::ostringstream query;
query << "insert into core.ticket (dir_id, parent_id, type, status, priority, category, expected, progress, item_id) values (";
query << '\'' << ticket.dir_id << "', ";
query << '\'' << ticket.parent_id << "', ";
query << '\'' << ticket.type << "', ";
query << '\'' << ticket.status << "', ";
query << '\'' << ticket.priority << "', ";
query << '\'' << ticket.category << "', ";
query << '\'' << ticket.expected << "', ";
query << '\'' << ticket.progress << "', ";
query << '\'' << ticket.item_id << "');";
r = AssertQuery(query.str());
AssertResultStatus(r, PGRES_COMMAND_OK);
ticket.id = AssertCurrval("core.ticket_id_seq");
}
catch(const Error & e)
{
status = e;
}
ClearResult(r);
return status;
}
Error Db::EditTicketById(Ticket & ticket)
{
PGresult * r = 0;
Error status = Error::ok;
try
{
AssertConnection();
std::ostringstream query;
query << "update core.ticket set (dir_id, parent_id, type, status, priority, category, expected, progress, item_id) = (";
query << '\'' << ticket.dir_id << "', ";
query << '\'' << ticket.parent_id << "', ";
query << '\'' << ticket.type << "', ";
query << '\'' << ticket.status << "', ";
query << '\'' << ticket.priority << "', ";
query << '\'' << ticket.category << "', ";
query << '\'' << ticket.expected << "', ";
query << '\'' << ticket.progress << "', ";
query << '\'' << ticket.item_id << "') ";
query << "where id='" << ticket.id << "';";
r = AssertQuery(query.str());
AssertResultStatus(r, PGRES_COMMAND_OK);
}
catch(const Error & e)
{
status = e;
}
ClearResult(r);
return status;
}

View File

@@ -27,7 +27,7 @@
#include "error.h"
#include "dircontainer.h"
#include "ugcontainer.h"
#include "ticket.h"
class Db
@@ -67,6 +67,7 @@ public:
// !! nowy interfejs
long Size(long parent_id, Item::Type type = Item::none);
Error GetItemById(long item_id, Item & item);
Error GetItem(long parent_id, const std::string & url, Item & item);
Error EditDefaultItem(long id, long new_default_item);
@@ -89,6 +90,13 @@ public:
Error EditThreadRemoveItem(long dir_id);
Error RemoveThread(long dir_id);
Error GetTicketByDirId(long dir_id, Ticket & ticket);
Error GetTickets(long parent_id, std::vector<Ticket> & ticket_tab);
//bool IsTicket(long dir_id);
Error AddTicket(Ticket & ticket);
Error EditTicketById(Ticket & ticket);
protected:
PGconn * pg_conn;
@@ -137,6 +145,14 @@ protected:
};
struct TicketColumns
{
int id, dir_id, parent_id, type, status, priority, category, expected, progress, item_id;
void SetColumns(PGresult * r);
void SetTicket(PGresult * r, long row, Ticket & ticket);
};
}; // class Db

View File

@@ -59,5 +59,35 @@ void Db::ItemColumns::SetItem(PGresult * r, long row, Item & item)
void Db::TicketColumns::SetColumns(PGresult * r)
{
// PQfnumber returns -1 if there is no such a column
id = PQfnumber(r, "id");
dir_id = PQfnumber(r, "dir_id");
parent_id = PQfnumber(r, "parent_id");
type = PQfnumber(r, "type");
status = PQfnumber(r, "status");
priority = PQfnumber(r, "priority");
category = PQfnumber(r, "category");
expected = PQfnumber(r, "expected");
progress = PQfnumber(r, "progress");
item_id = PQfnumber(r, "item_id");
}
void Db::TicketColumns::SetTicket(PGresult * r, long row, Ticket & ticket)
{
if( id != -1 ) ticket.id = atol( Db::AssertValue(r, row, id) );
if( dir_id != -1 ) ticket.dir_id = atol( Db::AssertValue(r, row, dir_id) );
if( parent_id != -1 ) ticket.parent_id = atol( Db::AssertValue(r, row, parent_id) );
if( type != -1 ) ticket.type = atoi( Db::AssertValue(r, row, type) );
if( status != -1 ) ticket.status = atoi( Db::AssertValue(r, row, status) );
if( priority != -1 ) ticket.priority = atoi( Db::AssertValue(r, row, priority) );
if( category != -1 ) ticket.category = atoi( Db::AssertValue(r, row, category) );
if( expected != -1 ) ticket.expected = atoi( Db::AssertValue(r, row, expected) );
if( progress != -1 ) ticket.progress = atoi( Db::AssertValue(r, row, progress) );
if( item_id != -1 ) ticket.item_id = atol( Db::AssertValue(r, row, item_id) );
}

View File

@@ -27,8 +27,11 @@ public:
privileged_item,
added_dir,
added_thread,
added_ticket,
edited_ticket,
defaulted_dir,
reloaded_templates,
edited_fstab,
loggedout
};

View File

@@ -58,6 +58,8 @@ public:
input_too_large,
cant_create_file,
no_ticket,
unknown = 1000

View File

@@ -14,24 +14,27 @@
#include "item.h"
#define FUN_NONE 0
#define FUN_LS 1
#define FUN_CAT 2
#define FUN_NODE 3
#define FUN_EMACS 4
#define FUN_MKDIR 5
#define FUN_DEFAULT 6
#define FUN_PRIV 7
#define FUN_RM 8
#define FUN_LOGIN 9
#define FUN_LOGOUT 10
#define FUN_RUN 11
#define FUN_WHO 12
#define FUN_LAST 13
#define FUN_CREATETHREAD 14
#define FUN_THREAD 15
#define FUN_RELOAD 16
#define FUN_UPLOAD 17
#define FUN_NONE 0
#define FUN_LS 1
#define FUN_CAT 2
#define FUN_NODE 3
#define FUN_EMACS 4
#define FUN_MKDIR 5
#define FUN_DEFAULT 6
#define FUN_PRIV 7
#define FUN_RM 8
#define FUN_LOGIN 9
#define FUN_LOGOUT 10
#define FUN_RUN 11
#define FUN_WHO 12
#define FUN_LAST 13
#define FUN_CREATETHREAD 14
#define FUN_THREAD 15
#define FUN_RELOAD 16
#define FUN_UPLOAD 17
#define FUN_CREATETICKET 18
#define FUN_EDITTICKET 19
#define FUN_TICKET 20

View File

@@ -100,6 +100,19 @@ void Functions::ReadFunctions()
f.item.url = "upload";
table.insert( std::make_pair(f.item.url, f) );
f.code = FUN_CREATETICKET;
f.item.url = "createticket";
table.insert( std::make_pair(f.item.url, f) );
f.code = FUN_EDITTICKET;
f.item.url = "editticket";
table.insert( std::make_pair(f.item.url, f) );
f.code = FUN_TICKET;
f.item.url = "ticket";
table.insert( std::make_pair(f.item.url, f) );
// functions which need more privileges
f.code = FUN_RELOAD;

View File

@@ -88,6 +88,20 @@ Item()
}
void SetDateToNow()
{
time_t t = std::time(0);
date_creation = *std::localtime( &t );
date_modification = date_creation;
}
void SetDateModifyToNow()
{
time_t t = std::time(0);
date_modification = *std::localtime( &t );
}
void Clear()
{
@@ -113,9 +127,7 @@ void Clear()
static_auth = static_none;
time_t t = std::time(0);
date_creation = *std::localtime( &t );
date_modification = date_creation;
SetDateToNow();
}

View File

@@ -16,6 +16,8 @@
#include <ctime>
#include "item.h"
// !! wrzucic do pliku version.h i dodac przedrostek typu WINIX_
// albo dac nazwy typu WINIX_VER_MAJOR
#define MAJOR_VER 0
#define MINOR_VER 2
#define REVISION_VER 0

View File

@@ -14,15 +14,17 @@
Mount::Mount()
{
type = cms;
type = cms;
dir_id = -1;
param.resize(par_none);
}
const char * Mount::TypeToStr()
{
static char buffer[30];
static char buffer[30];
switch( type )
{
@@ -34,8 +36,12 @@ const char * Mount::TypeToStr()
sprintf(buffer, "thread");
break;
case ticket:
sprintf(buffer, "ticket");
break;
default:
sprintf(buffer, "the name is not set");
sprintf(buffer, "unknown");
break;
}
@@ -43,82 +49,105 @@ return buffer;
}
bool Mount::ParseStrParam(const std::string & param, const std::vector<int> & args)
Mount::ParamCode Mount::ParseParam(const char * param_name)
{
Param p = none;
if( param == "asc" )
p = asc;
else
if( param == "desc" )
p = desc;
else
if( param == "withheader" )
p = withheader;
else
if( param == "withinfo" )
p = withinfo;
else
if( param == "thread_with_header" )
p = thread_with_header;
else
if( param == "thread_with_info" )
p = thread_with_info;
else
if( param == "restrictcreatethread" )
p = restrictcreatethread;
else
if( param == "only_root_can_remove" )
p = only_root_can_remove;
else
if( param == "can_use_emacs_on" )
p = can_use_emacs_on;
else
if( param == "can_use_mkdir_on" )
p = can_use_mkdir_on;
else
if( param == "none" )
return true;
else
return false;
param_table.insert( std::make_pair(p, args) );
return true;
}
bool Mount::IsParam(Param p)
{
ParamTable::iterator i = param_table.find(p);
if( i == param_table.end() )
return false;
return true;
}
bool Mount::IsParam(Param p, int * first_arg)
{
ParamTable::iterator i = param_table.find(p);
if( i == param_table.end() )
struct ParName
{
*first_arg = -1;
return false;
ParamCode param_code;
const char * name;
};
static ParName par_name_tab[] = {
{ par_page, "page" },
{ par_thread, "thread" },
{ par_ticket, "ticket" },
{ par_ticket_type, "ticket_type" },
{ par_ticket_type_default, "ticket_type_default" },
{ par_ticket_status, "ticket_status" },
{ par_ticket_status_default, "ticket_status_default" },
{ par_ticket_priority, "ticket_priority" },
{ par_ticket_priority_default, "ticket_priority_default" },
{ par_ticket_category, "ticket_category" },
{ par_ticket_category_default, "ticket_category_default" },
{ par_ticket_expected, "ticket_expected" },
{ par_ticket_expected_default, "ticket_expected_default" },
{ par_createthread_on, "createthread_on" },
{ par_createticket_on, "createticket_on" },
{ par_only_root_remove, "only_root_remove" },
{ par_emacs_on, "emacs_on" },
{ par_mkdir_on, "mkdir_on" }
};
size_t i, len = sizeof(par_name_tab) / sizeof(ParName);
for(i=0 ; i<len ; ++i)
{
if( strcmp(par_name_tab[i].name, param_name) == 0 )
return par_name_tab[i].param_code;
}
if( !i->second.empty() )
*first_arg = i->second[0];
else
*first_arg = -1;
return true;
return par_none;
}
void Mount::ClearParams()
{
param_table.clear();
size_t i;
for(i=0 ; i<param.size() ; ++i)
param[i].Clear();
}
bool Mount::IsPar(Mount::ParamCode code)
{
if( !param[code].defined )
return false;
return true;
}
bool Mount::IsArg(Mount::ParamCode code, const char * arg)
{
ParamArg::iterator i;
if( !param[code].defined )
return false;
for(i=param[code].arg.begin() ; i!=param[code].arg.end() ; ++i)
{
if( *i == arg )
return true;
}
return false;
}
bool Mount::IsArg(Mount::ParamCode code, const std::string & arg)
{
return IsArg(code, arg.c_str());
}
bool Mount::IsArg(Mount::ParamCode code, int arg)
{
ParamArg::iterator i;
if( !param[code].defined )
return false;
for(i=param[code].arg.begin() ; i!=param[code].arg.end() ; ++i)
{
if( atoi(i->c_str()) == arg )
return true;
}
return false;
}

View File

@@ -16,6 +16,8 @@
#include <vector>
class Mount
{
public:
@@ -24,42 +26,71 @@ public:
enum Type
{
cms = 0,
thread
thread,
ticket
};
enum Param
// the first should be with 0 index
// the last should be 'none'
enum ParamCode
{
none = 0,
asc,
desc,
withheader,
withinfo,
thread_with_header,
thread_with_info,
restrictcreatethread,
only_root_can_remove,
can_use_emacs_on,
can_use_mkdir_on
par_page = 0,
par_thread,
par_ticket,
par_ticket_type,
par_ticket_type_default,
par_ticket_status,
par_ticket_status_default,
par_ticket_priority,
par_ticket_priority_default,
par_ticket_category,
par_ticket_category_default,
par_ticket_expected,
par_ticket_expected_default,
par_createthread_on,
par_createticket_on,
par_only_root_remove,
par_emacs_on,
par_mkdir_on,
par_none
};
typedef std::vector<std::string> ParamArg;
long dir_id;
struct ParamRow
{
bool defined;
ParamArg arg;
ParamRow() { defined = false; }
void Clear() { defined = false; arg.clear(); }
};
typedef std::vector<ParamRow> Param;
Param param;
long dir_id;
Type type;
Mount();
const char * TypeToStr();
bool ParseStrParam(const std::string & param, const std::vector<int> & args);
bool IsParam(Param p);
bool IsParam(Param p, int * first_arg);
void ClearParams();
private:
typedef std::map<Param, std::vector<int> > ParamTable;
ParamTable param_table;
};
static ParamCode ParseParam(const char * param);
void ClearParams();
bool IsPar(Mount::ParamCode code);
bool IsArg(Mount::ParamCode code, const char * arg);
bool IsArg(Mount::ParamCode code, const std::string & arg);
bool IsArg(Mount::ParamCode code, int arg);
};

View File

@@ -10,7 +10,7 @@
#include "mountparser.h"
#include "data.h"
#include "log.h"
#include "misc.h"
bool MountParser::IsWhite(int c)
@@ -39,11 +39,38 @@ void MountParser::SkipLine()
}
void MountParser::ReadWord(std::string & res)
void MountParser::ReadWordQuote(std::string & res)
{
++pinput;
while( *pinput && *pinput!=10 && *pinput!='\"' )
{
if( pinput[0]=='\\' && pinput[1]=='\"' )
{
res += '\"';
pinput += 2;
}
else
if( pinput[0]=='\\' && pinput[1]=='\\' )
{
res += '\\';
pinput += 2;
}
else
{
res += *pinput;
pinput += 1;
}
}
if( *pinput == '"' )
++pinput;
}
// a white character is the separator
void MountParser::ReadWordWhite(std::string & res)
{
res.clear();
while( *pinput && *pinput!=10 && !IsWhite(*pinput) )
{
res += *pinput;
@@ -52,64 +79,71 @@ void MountParser::ReadWord(std::string & res)
}
bool MountParser::ReadParamArg(int & out)
// the comma or the second bracket ')' are the separators
void MountParser::ReadWordComma(std::string & res)
{
SkipWhite();
char * new_pos;
long temp = strtol(pinput, &new_pos, 10);
while( *pinput && *pinput!=10 && *pinput!=',' && *pinput!=')' )
{
res += *pinput;
++pinput;
}
if( pinput == new_pos )
return false;
pinput = new_pos;
SkipWhite();
// here can we make a test whether the temp is greater from 'int' type
out = (int)temp;
return true;
// trimming last white characters
// (white characters can be in the middle of the string)
TrimWhite(res);
}
void MountParser::ReadParamArgs(std::vector<int> & args)
void MountParser::ReadWord(std::string & res, bool comma_bracket_separator)
{
int arg;
res.clear();
SkipWhite();
while( ReadParamArg(arg) )
if( *pinput == '"' )
{
args.push_back(arg);
log << log3 << "MP: mount param arg: " << arg << logend;
ReadWordQuote(res);
}
else
if( comma_bracket_separator )
{
ReadWordComma(res);
}
else
{
ReadWordWhite(res);
}
}
void MountParser::ReadParamArgsLoop(Mount::ParamArg & args)
{
SkipWhite();
while( *pinput && *pinput!=10 && *pinput!=')' )
{
ReadWord(temp_arg, true);
if( !temp_arg.empty() )
args.push_back(temp_arg);
if( *pinput == ',' )
++pinput;
}
}
void MountParser::ReadParam(std::string & res, std::vector<int> & args)
void MountParser::ReadParamArgs(Mount::ParamArg & args)
{
SkipWhite();
res.clear();
args.clear();
while( *pinput && *pinput!=10 && *pinput!=',' && *pinput!='(' && !IsWhite(*pinput) )
{
res += *pinput;
++pinput;
}
if( res.empty() )
return;
// reading arguments
SkipWhite();
if( *pinput == '(' )
{
++pinput;
ReadParamArgs(args);
ReadParamArgsLoop(args);
if( *pinput != ')' )
{
@@ -121,16 +155,42 @@ void MountParser::ReadParam(std::string & res, std::vector<int> & args)
++pinput;
}
}
}
void MountParser::ReadParamName(std::string & res)
{
SkipWhite();
res.clear();
while( *pinput && *pinput!=10 && *pinput!=',' && *pinput!='(' && !IsWhite(*pinput) )
{
res += *pinput;
++pinput;
}
}
void MountParser::ReadParam(std::string & res, Mount::ParamArg & args)
{
ReadParamName(res);
if( res.empty() )
return;
ReadParamArgs(args);
SkipWhite();
if( *pinput == ',' )
++pinput;
}
void MountParser::ReadMountType()
{
SkipWhite();
ReadWord(temp);
if( temp.empty() )
@@ -151,6 +211,12 @@ void MountParser::ReadMountType()
log << log3 << "MP: mount type: thread" << logend;
}
else
if( temp == "ticket" )
{
mount.type = Mount::ticket;
log << log3 << "MP: mount type: ticket" << logend;
}
else
{
err = Error::mount_unknown;
log << log1 << "MP: unknown mount type: " << temp << logend;
@@ -161,9 +227,6 @@ void MountParser::ReadMountType()
void MountParser::ReadMountPoint()
{
SkipWhite();
// !! narazie bez cudzyslowow
ReadWord(temp);
pdir = data.dirs.GetDir(temp);
@@ -182,21 +245,41 @@ void MountParser::ReadMountPoint()
void MountParser::LogMountParams()
{
size_t i;
log << log3 << "MP: mount param: " << temp << "(";
for(i=0 ; i<param_args.size() ; ++i)
{
log << param_args[i];
if( i != param_args.size()-1 )
log << ",";
}
log << ")" << logend;
}
void MountParser::ReadMountParams()
{
mount.ClearParams();
for( ReadParam(temp, param_args) ; !temp.empty() ; ReadParam(temp, param_args) )
{
if( !mount.ParseStrParam(temp, param_args) )
Mount::ParamCode p = Mount::ParseParam(temp.c_str());
if( p != Mount::par_none )
{
log << log1 << "MP: unknown mount param: " << temp << logend;
err = Error::mount_no_param;
return;
mount.param[p].defined = true;
mount.param[p].arg = param_args;
LogMountParams();
}
else
{
log << log3 << "MP: mount param: " << temp << logend;
log << log1 << "MP: unknown mount param: " << temp << " (skipped)" << logend;
}
}
}
@@ -221,8 +304,13 @@ void MountParser::ReadRow(std::map<long, Mount> & output)
ReadMountParams();
if( err == Error::ok )
output.insert( std::make_pair(mount.dir_id, mount) );
{
std::pair<std::map<long, Mount>::iterator, bool> res = output.insert( std::make_pair(mount.dir_id, mount) );
if( !res.second )
log << log1 << "MP: this mount point exists (skipped)" << logend;
}
SkipLine();
}

View File

@@ -34,18 +34,24 @@ private:
bool IsWhite(int c);
void SkipWhite();
void SkipLine();
void ReadWord(std::string & res);
bool ReadParamArg(int & out);
void ReadParamArgs(std::vector<int> & args);
void ReadParam(std::string & res, std::vector<int> & args);
void ReadWordQuote(std::string & res);
void ReadWordWhite(std::string & res);
void ReadWordComma(std::string & res);
void ReadWord(std::string & res, bool comma_bracket_separator = false);
void ReadParamArgsLoop(Mount::ParamArg & args);
void ReadParamArgs(Mount::ParamArg & args);
void ReadParamName(std::string & res);
void ReadParam(std::string & res, Mount::ParamArg & args);
void ReadMountType();
void ReadMountPoint();
void LogMountParams();
void ReadMountParams();
void ReadRow(std::map<long, Mount> & output);
const char * pinput;
std::string temp;
std::vector<int> param_args;
std::string temp_arg;
Mount::ParamArg param_args;
Mount mount;

View File

@@ -16,23 +16,34 @@
Mounts::Mounts()
{
pmount = 0;
}
// reading from 'mounts'
void Mounts::ReadMounts(const std::string & mounts)
Error Mounts::ReadMounts(const std::string & mounts)
{
MountParser mp;
Error err = mp.Parse(mounts, mount_table);
Error err = mp.Parse(mounts, mount_tab);
if( err != Error::ok )
{
log << log1 << "M: some problems with mountpoints (mountpoints table will be empty)" << logend;
mount_table.clear();
mount_tab.clear();
}
CalcCurMount();
return err;
}
// reading from /etc/fstab
void Mounts::ReadMounts()
Error Mounts::ReadMounts()
{
static std::string file = "fstab";
@@ -41,7 +52,7 @@ void Mounts::ReadMounts()
if( !etc )
{
log << log1 << "M: there is no /etc directory" << logend;
return;
return Error::no_item;
}
Item fstab;
@@ -50,81 +61,63 @@ void Mounts::ReadMounts()
if( err == Error::no_item )
{
log << log1 << "M: there is no /etc/fstab file" << logend;
return;
return err;
}
if( err != Error::ok )
{
log << log1 << "M: cannot read /etc/fstab" << logend;
return;
return err;
}
ReadMounts(fstab.content);
}
/*
Mount Mounts::GetCurrentMountPoint()
{
return current_dir;
}
*/
Mount::Type Mounts::CurrentMountType()
{
return current_dir.type;
}
bool Mounts::CurrentMountIsParam(Mount::Param p)
{
return current_dir.IsParam(p);
}
bool Mounts::CurrentMountIsParam(Mount::Param p, int * first_arg)
{
return current_dir.IsParam(p, first_arg);
return ReadMounts(fstab.content);
}
void Mounts::MountCmsForRoot()
{
current_dir.type = Mount::cms;
Mount mount;
mount.type = Mount::cms;
Item * proot = data.dirs.GetRootDir();
if( proot )
current_dir.dir_id = proot->id;
mount.dir_id = proot->id;
else
{
current_dir.dir_id = -1;
mount.dir_id = -1;
log << log1 << "M: there is no a root dir" << logend;
}
std::pair<MountTab::iterator, bool> res = mount_tab.insert( std::make_pair(mount.dir_id, mount) );
pmount = &(res.first->second);
}
void Mounts::CalculateCurrentMountType()
void Mounts::CalcCurMount()
{
std::vector<Item*>::reverse_iterator i;
// when the program starts (when the dir_table is empty()
// we don't want to call MountCmsForRoot()
if( request.dir_table.empty() )
return;
for(i = request.dir_table.rbegin() ; i!=request.dir_table.rend() ; ++i)
{
std::map<long, Mount>::iterator m = mount_table.find( (*i)->id );
std::map<long, Mount>::iterator m = mount_tab.find( (*i)->id );
if( m != mount_table.end() )
if( m != mount_tab.end() )
{
current_dir = m->second;
log << log2 << "M: current mount point is: " << current_dir.TypeToStr() << logend;
pmount = &(m->second);
log << log2 << "M: current mount point is: " << pmount->TypeToStr() << logend;
return;
}
}
// if nothing was found
// we assume that 'cms' mount point is used
MountCmsForRoot();
log << log2 << "M: current mount point is: cms (default)" << logend;

View File

@@ -15,36 +15,32 @@
#include <map>
#include <string>
#include "mount.h"
#include "error.h"
class Mounts
{
public:
void ReadMounts(const std::string & mounts);
void ReadMounts();
Mounts();
Error ReadMounts(const std::string & mounts);
Error ReadMounts();
void CalcCurMount();
void CalculateCurrentMountType();
// !! nie lepiej aby zwracal tutaj referencje albo wskaznik na biezacy punkt?
// !! w Mount mamy strukture std::set
//Mount GetCurrentMountPoint();
Mount::Type CurrentMountType();
bool CurrentMountIsParam(Mount::Param p);
bool CurrentMountIsParam(Mount::Param p, int * first_arg);
void MountCmsForRoot();
// current mount point
// will not be null after calling CalcCurMount() or ReadMounts([...])
Mount * pmount;
private:
Mount current_dir;
// dir_id, mount_point
std::map<long, Mount> mount_table;
typedef std::map<long, Mount> MountTab;
MountTab mount_tab;
void MountCmsForRoot();
};

View File

@@ -198,7 +198,7 @@ Users::Iterator i;
return;
n.notify_code = notify_code;
n.current_mount_type = data.mounts.CurrentMountType();
n.current_mount_type = data.mounts.pmount->type;
n.doc_base_url = data.base_url;
CreateItemDir(n.item_dir);
CreateItemLink(n.item_link);
@@ -214,13 +214,13 @@ Users::Iterator i;
{
sending = false;
if( data.mounts.CurrentMountType() == Mount::thread )
if( data.mounts.pmount->type == Mount::thread )
{
if( (i->thread_notify & notify_code) != 0 )
sending = true;
}
else
if( data.mounts.CurrentMountType() == Mount::cms )
if( data.mounts.pmount->type == Mount::cms )
{
if( (i->cms_notify & notify_code) != 0 )
sending = true;

View File

@@ -18,7 +18,7 @@
#include "data.h"
#include "plugin.h"
#include "misc.h"
#include "db.h"
Request::Request() : char_empty(0)
@@ -95,6 +95,11 @@ void Request::Clear()
is_thread = false;
thread.Clear();
thread_tab.clear();
is_ticket = false;
ticket.Clear();
ticket_tab.clear();
notify_code = 0;
browser_msie = false;
redirect_to.clear();
@@ -416,13 +421,13 @@ void Request::SendHeaders(bool compressing, Header header)
{
case h_404:
FCGX_PutS("Status: 404 Not Found\r\n", out);
FCGX_PutS("Content-Type: Text/Html\r\n", out);
FCGX_PutS("Content-Type: text/html\r\n", out);
log << log2 << "Request: response: 404 Not Found" << logend;
break;
case h_403:
FCGX_PutS("Status: 403 Forbidden\r\n", out);
FCGX_PutS("Content-Type: Text/Html\r\n", out);
FCGX_PutS("Content-Type: text/html\r\n", out);
log << log2 << "Request: response: 403 Forbidden" << logend;
break;
@@ -430,7 +435,7 @@ void Request::SendHeaders(bool compressing, Header header)
FCGX_PutS("Status: 200 OK\r\n", out);
if( role != authorizer )
FCGX_PutS("Content-Type: Text/Html\r\n", out);
FCGX_PutS("Content-Type: text/html\r\n", out);
}
}
@@ -683,31 +688,76 @@ bool Request::CanCreateThread(bool check_root)
if( !HasWriteAccess(*request.dir_table.back()) )
return false;
if( data.mounts.CurrentMountType() != Mount::thread )
if( !data.mounts.pmount || data.mounts.pmount->type != Mount::thread )
return false;
if( !check_root && session && session->puser && session->puser->super_user )
// super can create thread regardless of the restrictcreatethread option
return true;
if( !data.mounts.pmount->IsPar(Mount::par_createthread_on) )
return true;
// !! w przyszlosci mozna odczytywac wiecej parametrow od restrictcreatethread
// tymczasowo wykorzystujemy tylko pierwszy
int level;
if( data.mounts.CurrentMountIsParam(Mount::restrictcreatethread, &level) )
{
if( level == -1 )
return false;
if( data.mounts.pmount->IsArg(Mount::par_createthread_on, request.dir_table.size()) )
return true;
// we can only allow on a specific level
if( int(request.dir_table.size()) != level )
return false;
}
return false;
}
// returning true if we can create a ticket in the current directory
bool Request::CanCreateTicket(bool check_root)
{
if( request.dir_table.empty() )
return false;
if( request.is_item )
return false;
if( !HasWriteAccess(*request.dir_table.back()) )
return false;
if( !data.mounts.pmount || data.mounts.pmount->type != Mount::ticket )
return false;
// checking for par_createticket_on mount option
if( !check_root && session && session->puser && session->puser->super_user )
// super can create tickets regardless of the createticket_on option
return true;
if( !data.mounts.pmount->IsPar(Mount::par_createticket_on) )
return true;
if( data.mounts.pmount->IsArg(Mount::par_createticket_on, request.dir_table.size()) )
return true;
return false;
}
bool Request::CanEditTicket()
{
if( request.dir_table.empty() )
return false;
if( request.is_item || !request.is_ticket )
return false;
if( !HasWriteAccess(*request.dir_table.back()) )
return false;
if( !data.mounts.pmount || data.mounts.pmount->type != Mount::ticket )
return false;
return true;
}
bool Request::CanRemove(const Item & item)
{
if( item.parent_id == -1 )
@@ -729,8 +779,7 @@ bool Request::CanRemove(const Item & item)
return false;
}
if( data.mounts.CurrentMountIsParam(Mount::only_root_can_remove) )
// this can be deleted only be a root
if( data.mounts.pmount->IsPar(Mount::par_only_root_remove) )
if( !request.session->puser || !request.session->puser->super_user )
return false;
@@ -747,13 +796,13 @@ bool Request::CanUseEmacs(const Item & item, bool check_root)
if( !request.HasWriteAccess(item) )
return false;
int level;
if( data.mounts.CurrentMountIsParam(Mount::can_use_emacs_on, &level) )
if( level != int(request.dir_table.size()) )
return false;
if( !data.mounts.pmount->IsPar(Mount::par_emacs_on) )
return true;
if( data.mounts.pmount->IsArg(Mount::par_emacs_on, request.dir_table.size()) )
return true;
return true;
return false;
}
@@ -770,13 +819,13 @@ bool Request::CanUseMkdir(const Item & item, bool check_root)
if( !request.HasWriteAccess(item) )
return false;
int level;
if( data.mounts.CurrentMountIsParam(Mount::can_use_mkdir_on, &level) )
if( level != int(request.dir_table.size()) )
return false;
if( !data.mounts.pmount->IsPar(Mount::par_mkdir_on) )
return true;
if( data.mounts.pmount->IsArg(Mount::par_mkdir_on, request.dir_table.size()) )
return true;
return true;
return false;
}
@@ -839,20 +888,32 @@ return false;
bool Request::MakeDirsOnFS(std::string & path)
// !! dobrac lepsze nazwy dla tych dwoch metod
void Request::MakePath(std::string & path)
{
size_t i;
path = data.static_auth_dir;
// skipping the first - the first is root
for(i=1 ; i<dir_table.size() ; ++i)
{
path += '/';
path += dir_table[i]->url;
}
}
bool Request::MakeDirsOnFS()
{
size_t i;
std::string path = data.static_auth_dir;
// skipping the first - the first is root
for(i=1 ; i<dir_table.size() ; ++i)
{
path += '/';
path += dir_table[i]->url;
if( mkdir(path.c_str(), 0750) < 0 )
if( mkdir(path.c_str(), 0755) < 0 )
{
// oops
log << log1 << "Request: can't create the directory on fs: " << path << logend;

View File

@@ -25,6 +25,7 @@
#include "acceptencodingparser.h"
#include "htmlfilter.h"
#include "postmultiparser.h"
#include "ticket.h"
struct Request
@@ -104,6 +105,11 @@ struct Request
Thread thread;
std::vector<Thread> thread_tab;
// current ticket (if exists)
bool is_ticket;
Ticket ticket;
std::vector<Ticket> ticket_tab;
// if not empty means an address for redirecting to
std::string redirect_to;
@@ -146,6 +152,8 @@ struct Request
bool HasReadExecAccess(const Item & item);
bool CanCreateThread(bool check_root = false);
bool CanCreateTicket(bool check_root = false);
bool CanEditTicket();
bool CanRemove(const Item & item);
bool CanUseEmacs(const Item & item, bool check_root = false);
bool CanUseMkdir(const Item & item, bool check_root = false);
@@ -155,7 +163,8 @@ struct Request
bool CanUseBBCode(long user_id);
bool CanUseRaw(long user_id);
bool MakeDirsOnFS(std::string & path);
void MakePath(std::string & path);
bool MakeDirsOnFS();
private:

View File

@@ -199,7 +199,7 @@ void RequestController::Loop()
request.session->CheckTimers();
function_parser.Parse();
data.mounts.CalculateCurrentMountType();
data.mounts.CalcCurMount();
content.ReadAdditionalInfo();
content.Make();

View File

@@ -19,8 +19,6 @@ class Thread
public:
long id;
// !! parent_id potrzebne w ogole jest?
long parent_id;
long dir_id;

58
core/ticket.h Executable file
View File

@@ -0,0 +1,58 @@
/*
* This file is a part of CMSLU -- Content Management System like Unix
* and is not publicly distributed
*
* Copyright (c) 2008-2009, Tomasz Sowa
* All rights reserved.
*
*/
#ifndef headerfilecmslucoreticket
#define headerfilecmslucoreticket
#include <string>
struct Ticket
{
long id;
long dir_id;
long parent_id;
unsigned int type;
unsigned int status;
unsigned int priority;
unsigned int category;
unsigned int expected;
unsigned int progress; // 0 - 100 (percentage)
// the first item (with the content for the ticket)
long item_id;
void Clear()
{
id = -1;
dir_id = -1;
parent_id = -1;
type = 0;
status = 0;
priority = 0;
category = 0;
expected = 0;
progress = 0;
item_id = -1;
}
Ticket()
{
Clear();
}
};
#endif