diff --git a/Makefile b/Makefile index ac2fbe4..ff185eb 100755 --- a/Makefile +++ b/Makefile @@ -1,5 +1,5 @@ CC = g++ -o = dir.o data.o content.o log.o sessionmanager.o requestcontroller.o dircontainer.o session.o main.o done.o request.o misc.o templates.o httpsimpleparser.o db.o error.o db_itemcolumns.o config.o confparser.o ezc.o +o = data.o content.o log.o sessionmanager.o requestcontroller.o dircontainer.o session.o main.o done.o request.o misc.o templates.o httpsimpleparser.o db.o error.o db_itemcolumns.o users.o config.o dirs.o groups.o confparser.o ezc.o CFLAGS = -Wall -pedantic -g -I/usr/local/include -L/usr/local/lib name = cmslu.fcgi @@ -19,29 +19,32 @@ $(name): $(o) -dir.o: core/dir.cpp core/dir.h core/item.h core/error.h core/log.h core/db.h core/misc.h core/dircontainer.h -data.o: core/data.cpp core/data.h core/misc.h core/log.h core/item.h core/error.h core/dir.h core/db.h core/dircontainer.h -content.o: core/content.cpp core/content.h core/templates.h core/../../ezc/src/ezc.h core/data.h core/misc.h core/log.h core/item.h core/error.h core/dir.h core/db.h core/dircontainer.h core/request.h core/requesttypes.h core/session.h core/done.h core/getparser.h core/httpsimpleparser.h core/postparser.h core/cookieparser.h +data.o: core/data.cpp core/data.h core/misc.h core/log.h core/item.h core/error.h core/dirs.h core/db.h core/dircontainer.h core/user.h core/group.h core/ugcontainer.h core/users.h core/groups.h +content.o: core/content.cpp core/content.h core/templates.h core/../../ezc/src/ezc.h core/data.h core/misc.h core/log.h core/item.h core/error.h core/dirs.h core/db.h core/dircontainer.h core/user.h core/group.h core/ugcontainer.h core/users.h core/groups.h core/request.h core/requesttypes.h core/session.h core/done.h core/getparser.h core/httpsimpleparser.h core/postparser.h core/cookieparser.h log.o: core/log.cpp core/log.h -sessionmanager.o: core/sessionmanager.cpp core/sessionmanager.h core/request.h core/requesttypes.h core/log.h core/session.h core/error.h core/item.h core/done.h core/getparser.h core/httpsimpleparser.h core/postparser.h core/cookieparser.h core/data.h core/misc.h core/dir.h core/db.h core/dircontainer.h -requestcontroller.o: core/requestcontroller.cpp core/requestcontroller.h core/data.h core/misc.h core/log.h core/item.h core/error.h core/dir.h core/db.h core/dircontainer.h core/request.h core/requesttypes.h core/session.h core/done.h core/getparser.h core/httpsimpleparser.h core/postparser.h core/cookieparser.h core/content.h core/templates.h core/../../ezc/src/ezc.h core/sessionmanager.h +sessionmanager.o: core/sessionmanager.cpp core/sessionmanager.h core/request.h core/requesttypes.h core/log.h core/session.h core/error.h core/item.h core/done.h core/user.h core/getparser.h core/httpsimpleparser.h core/postparser.h core/cookieparser.h core/data.h core/misc.h core/dirs.h core/db.h core/dircontainer.h core/group.h core/ugcontainer.h core/users.h core/groups.h +requestcontroller.o: core/requestcontroller.cpp core/requestcontroller.h core/data.h core/misc.h core/log.h core/item.h core/error.h core/dirs.h core/db.h core/dircontainer.h core/user.h core/group.h core/ugcontainer.h core/users.h core/groups.h core/request.h core/requesttypes.h core/session.h core/done.h core/getparser.h core/httpsimpleparser.h core/postparser.h core/cookieparser.h core/content.h core/templates.h core/../../ezc/src/ezc.h core/sessionmanager.h dircontainer.o: core/dircontainer.cpp core/dircontainer.h core/item.h core/log.h -session.o: core/session.cpp core/session.h core/requesttypes.h core/error.h core/log.h core/item.h core/done.h -main.o: core/main.cpp core/requestcontroller.h core/data.h core/misc.h core/log.h core/item.h core/error.h core/dir.h core/db.h core/dircontainer.h core/request.h core/requesttypes.h core/session.h core/done.h core/getparser.h core/httpsimpleparser.h core/postparser.h core/cookieparser.h core/content.h core/templates.h core/../../ezc/src/ezc.h core/sessionmanager.h core/config.h core/../confparser/confparser.h +session.o: core/session.cpp core/session.h core/requesttypes.h core/error.h core/log.h core/item.h core/done.h core/user.h +main.o: core/main.cpp core/requestcontroller.h core/data.h core/misc.h core/log.h core/item.h core/error.h core/dirs.h core/db.h core/dircontainer.h core/user.h core/group.h core/ugcontainer.h core/users.h core/groups.h core/request.h core/requesttypes.h core/session.h core/done.h core/getparser.h core/httpsimpleparser.h core/postparser.h core/cookieparser.h core/content.h core/templates.h core/../../ezc/src/ezc.h core/sessionmanager.h core/config.h core/../confparser/confparser.h done.o: core/done.cpp core/done.h -request.o: core/request.cpp core/request.h core/requesttypes.h core/log.h core/session.h core/error.h core/item.h core/done.h core/getparser.h core/httpsimpleparser.h core/postparser.h core/cookieparser.h +request.o: core/request.cpp core/request.h core/requesttypes.h core/log.h core/session.h core/error.h core/item.h core/done.h core/user.h core/getparser.h core/httpsimpleparser.h core/postparser.h core/cookieparser.h misc.o: core/misc.cpp core/misc.h core/log.h core/item.h -templates.o: core/templates.cpp core/templates.h core/../../ezc/src/ezc.h core/data.h core/misc.h core/log.h core/item.h core/error.h core/dir.h core/db.h core/dircontainer.h core/request.h core/requesttypes.h core/session.h core/done.h core/getparser.h core/httpsimpleparser.h core/postparser.h core/cookieparser.h +templates.o: core/templates.cpp core/templates.h core/../../ezc/src/ezc.h core/data.h core/misc.h core/log.h core/item.h core/error.h core/dirs.h core/db.h core/dircontainer.h core/user.h core/group.h core/ugcontainer.h core/users.h core/groups.h core/request.h core/requesttypes.h core/session.h core/done.h core/getparser.h core/httpsimpleparser.h core/postparser.h core/cookieparser.h httpsimpleparser.o: core/httpsimpleparser.cpp core/httpsimpleparser.h -db.o: core/db.cpp core/db.h core/log.h core/item.h core/misc.h core/error.h core/dircontainer.h +db.o: core/db.cpp core/db.h core/log.h core/item.h core/misc.h core/error.h core/dircontainer.h core/user.h core/group.h core/ugcontainer.h error.o: core/error.cpp core/error.h core/log.h -db_itemcolumns.o: core/db_itemcolumns.cpp core/db.h core/log.h core/item.h core/misc.h core/error.h core/dircontainer.h -config.o: core/config.cpp core/config.h core/../confparser/confparser.h core/error.h core/log.h core/data.h core/misc.h core/item.h core/dir.h core/db.h core/dircontainer.h +db_itemcolumns.o: core/db_itemcolumns.cpp core/db.h core/log.h core/item.h core/misc.h core/error.h core/dircontainer.h core/user.h core/group.h core/ugcontainer.h +users.o: core/users.cpp core/users.h core/user.h core/db.h core/log.h core/item.h core/misc.h core/error.h core/dircontainer.h core/group.h core/ugcontainer.h +config.o: core/config.cpp core/config.h core/../confparser/confparser.h core/error.h core/log.h core/data.h core/misc.h core/item.h core/dirs.h core/db.h core/dircontainer.h core/user.h core/group.h core/ugcontainer.h core/users.h core/groups.h +dirs.o: core/dirs.cpp core/dirs.h core/item.h core/error.h core/log.h core/db.h core/misc.h core/dircontainer.h core/user.h core/group.h core/ugcontainer.h +groups.o: core/groups.cpp core/groups.h core/group.h core/db.h core/log.h core/item.h core/misc.h core/error.h core/dircontainer.h core/user.h core/ugcontainer.h confparser.o: confparser/confparser.cpp confparser/confparser.h ezc.o: ../ezc/src/ezc.cpp ../ezc/src/ezc.h + clean: rm -f *.o rm -f $(name) diff --git a/core/config.cpp b/core/config.cpp index df36c10..46ceadc 100755 --- a/core/config.cpp +++ b/core/config.cpp @@ -103,7 +103,10 @@ void Config::AssignValues() data.db_pass = Text("db_pass"); data.base_url = Text("base_url"); data.one_item_is_showed = Bool("one_item_is_showed"); - data.dir.root.default_item = Int("dir.root.default_item"); + data.dirs.root.default_item = Int("dir.root.default_item"); + + data.priv_no_user = Text("priv_no_user"); + data.priv_no_group = Text("priv_no_group"); } diff --git a/core/content.cpp b/core/content.cpp index f286d6e..fe383c9 100755 --- a/core/content.cpp +++ b/core/content.cpp @@ -26,72 +26,99 @@ return true; void Content::AddItem() { - if( !request.session->is_logged ) - return; - try { request.session->done = Done::added_item; -// request.item_table.resize(1); -// Item & item = request.item_table[0]; + if( !request.session->puser || !request.session->puser->super_user ) + // !! chwilowo tylko super user moze + throw Error(Error::permision_denied); - request.item.subject = request.PostVar("subject"); - request.item.content = request.PostVar("content"); - request.item.parent_id = data.dir.GetDirId( request.PostVar("directory") ); - request.item.type = Item::file; + request.item.user_id = data.users.GetUserId( request.PostVar("user") ); + request.item.group_id = data.groups.GetGroupId( request.PostVar("group") ); + request.item.privileges = strtol( request.PostVar("privileges").c_str() , 0, 8); + request.item.subject = request.PostVar("subject"); + request.item.content = request.PostVar("content"); + request.item.parent_id = data.dirs.GetDirId( request.PostVar("directory") ); + request.item.type = Item::file; PrepareUrlSubject(request.item); request.session->done_status = db.AddItem(request.item); - request.session->done_timer = 1; + request.session->done_timer = 2; + request.session->item = request.item; - // if( request.session->done_status != Request::added_item ) - //request.item_table.resize(1); - //request.item_table[0] = request.item; + RedirectTo(request.item); + } catch(const Error & e) { + log << log1 << "Content: AddItem: Error: " << e << logend; request.session->done_status = e; + request.session->done_timer = 1; } } +void Content::AssertPrivileges(Item & old_item, Item & new_item) +{ + if( !request.CanChangeUser(old_item, new_item.user_id) ) + throw Error(Error::cant_change_user); + + if( !request.CanChangeGroup(old_item, new_item.group_id) ) + throw Error(Error::cant_change_group); + + if( !request.CanChangePrivileges(old_item, new_item.privileges) ) + throw Error(Error::cant_change_privileges); +} + + + void Content::EditItem() { - if( !request.session->is_logged ) - return; - try { request.session->done = Done::edited_item; - -// request.item_table.resize(1); -// Item & item = request.item_table[0]; - request.item.subject = request.PostVar("subject"); - request.item.content = request.PostVar("content"); - request.item.id = atol( request.PostVar("id").c_str() ); + request.item.id = atol( request.PostVar("id").c_str() ); + request.item.user_id = data.users.GetUserId( request.PostVar("user") ); + request.item.group_id = data.groups.GetGroupId( request.PostVar("group") ); + request.item.privileges = strtol( request.PostVar("privileges").c_str() , 0, 8); + request.item.subject = request.PostVar("subject"); + request.item.content = request.PostVar("content"); bool with_subject = false; if( request.PostVar("old_subject") != request.item.subject ) with_subject = true; - request.item.parent_id = data.dir.GetDirId( request.PostVar("directory") ); + request.item.parent_id = data.dirs.GetDirId( request.PostVar("directory") ); // !! moze nie byc takiego, zglosic komunikat request.item.type = Item::file; PrepareUrlSubject(request.item); - - request.session->done_status = db.EditItem(request.item, with_subject); - request.session->done_timer = 1; + + Item old_item; + db.GetPriv(old_item, request.item.id); + AssertPrivileges(old_item, request.item); + + if( !request.HasWriteAccess(old_item) ) + throw Error(Error::permision_denied); + + request.session->done_status = db.EditItemById(request.item, with_subject); } catch(const Error & e) { + log << log1 << "Content: EditItem: Error: " << e << logend; request.session->done_status = e; } + + request.session->item = request.item; + request.session->done_timer = 2; + RedirectTo(request.item); + } + void Content::LogUser() { try @@ -102,9 +129,17 @@ void Content::LogUser() if( db.CheckUser(login, pass, user_id) ) { + request.session->puser = data.users.GetUser(user_id); + + if( !request.session->puser ) + { + log << log1 << "Content: user: " << login << " is in the database but is not in data.users" << logend; + return; + } + request.session->is_logged = true; request.session->user_id = user_id; - request.session->user = login; + log << log2 << "User " << login << " (id: " << user_id << ") logged" << logend; } @@ -125,7 +160,7 @@ void Content::MakeDirectoryStructure() { Item * pdir; - if( !data.dir.GetDir(request.get_table[get_index], parent, &pdir) ) + if( !data.dirs.GetDir(request.get_table[get_index], parent, &pdir) ) break; parent = pdir->id; @@ -134,7 +169,7 @@ void Content::MakeDirectoryStructure() // parent - last directory (or -1 if none) request.dir = parent; - data.dir.GetDirChilds(parent, request.dir_table); + data.dirs.GetDirChilds(parent, request.dir_table); } @@ -190,6 +225,16 @@ bool Content::MakeGetCheckDir() if( get_index == request.get_table.size() ) { // request was for a directory + + //// + if( !request.cur_dir_table.empty() && !request.HasReadAccess(request.cur_dir_table.back()) ) + { + request.result = Request::err_per_denied; + return true; + } + //// + + db.GetItems(request.item_table, item); @@ -198,7 +243,7 @@ bool Content::MakeGetCheckDir() long default_id = -1; if( request.cur_dir_table.empty() ) { - default_id = data.dir.root.default_item; + default_id = data.dirs.root.default_item; } else { @@ -277,9 +322,15 @@ void Content::MakeGet() // err404 at the end return; + //// + if( request.HasReadAccess(request.item_table[0]) )// !! tymczasowo dla 0 tylko + request.result = Request::show_item; + else + request.result = Request::err_per_denied; + //// + if( get_index == request.get_table.size() ) { - request.result = Request::show_item; return; } @@ -288,6 +339,21 @@ void Content::MakeGet() } + +void Content::MakeAddItem() +{ + if( !request.session->puser ) + { + // not logged + request.item.Clear(); + } + else + { + request.item.user_id = request.session->puser->id; + } +} + + void Content::MakeEditItem() { if( !request.item_table.empty() ) @@ -328,10 +394,7 @@ void Content::MakeShowItemById() request.result = Request::err404; else { - request.result = Request::redirect; - std::string path; - data.dir.MakePath(request.item_table[0].parent_id, path); - request.str = data.base_url + path + request.item_table[0].url; + RedirectTo(request.item_table[0]); } } } @@ -340,15 +403,24 @@ void Content::MakeShowItemById() void Content::MakeDelItem() { - if( !request.session->is_logged ) - return; - - if( request.item_table.empty() ) { request.result = Request::err404; return; } + + + if( !request.session->puser || !request.session->puser->super_user ) + // !! chwilowo tylko super user moze + { + + request.result = Request::err_per_denied; + request.CopyFirstItem(); + + return; + } + + if( get_index == request.get_table.size() ) { @@ -389,16 +461,16 @@ void Content::MakeLogout() { if( request.session->is_logged ) { - log << log2 << "User " << request.session->user << " (id: " << request.session->user_id << ") logged out" << logend; + log << log2 << "User id: " << request.session->user_id << " logged out" << logend; request.session->is_logged = false; - request.session->user.clear(); request.session->user_id = 0; + request.session->puser = 0; } request.result = Request::redirect; std::string path; - data.dir.MakePath(request.dir, path); + data.dirs.MakePath(request.dir, path); request.str = data.base_url + path; if( !request.item_table.empty() ) @@ -412,6 +484,11 @@ void Content::MakeLogout() void Content::MakeStandardFunction() { + if( request.result == Request::add_item ) + { + MakeAddItem(); + } + else if( request.result == Request::edit_item ) { MakeEditItem(); @@ -455,6 +532,10 @@ void Content::MakePost() void Content::Make() { MakePost(); + + if( request.result == Request::redirect ) + return; + MakeGet(); MakeStandardFunction(); @@ -467,6 +548,14 @@ void Content::Make() +void Content::RedirectTo(const Item & item) +{ +std::string path; + + request.result = Request::redirect; + data.dirs.MakePath(item.parent_id, path); + request.str = data.base_url + path + item.url; +} diff --git a/core/content.h b/core/content.h index da5c840..2111a95 100755 --- a/core/content.h +++ b/core/content.h @@ -18,7 +18,7 @@ #include "error.h" #include "misc.h" #include "db.h" - +#include "user.h" @@ -38,6 +38,7 @@ class Content Templates templates; + void AssertPrivileges(Item & old_item, Item & new_item); void AddItem(); void EditItem(); @@ -48,6 +49,7 @@ class Content void PrepareUrlSubject(Item & item); bool MakeGetCheckDir(); + void MakeAddItem(); void MakeEditItem(); void MakeShowItemById(); void MakeDelItem(); @@ -60,6 +62,10 @@ class Content void MakePost(); void MakeGet(); + + + void RedirectTo(const Item & item); + public: bool Init(); diff --git a/core/data.h b/core/data.h index 00ede86..bf17d4d 100755 --- a/core/data.h +++ b/core/data.h @@ -18,7 +18,10 @@ #include "misc.h" #include "item.h" #include "error.h" -#include "dir.h" +#include "dirs.h" +#include "users.h" +#include "groups.h" + @@ -75,6 +78,10 @@ public: // (instead of showing directory contents) bool one_item_is_showed; + // string used in a place where is a user (or group) selected + std::string priv_no_user; + std::string priv_no_group; + // end config members // ----------------------------------------------------------------- @@ -87,7 +94,7 @@ public: volatile bool signal_hup; // contains current directories tree - Dir dir; + Dirs dirs; // based on base_url // set by SetAdditionalVariables() @@ -97,6 +104,13 @@ public: void SetAdditionalVariables(); + + // users + Users users; + + // groups + Groups groups; + Data(); diff --git a/core/db.cpp b/core/db.cpp index 2d907d5..3a183fb 100755 --- a/core/db.cpp +++ b/core/db.cpp @@ -89,6 +89,9 @@ void Db::AssertConnection() else { log << log2 << "ok" << logend; + + if( PQsetClientEncoding(pg_conn, "LATIN2") == -1 ) + log << log1 << "Db: Can't set the proper client encoding" << logend; } } } @@ -493,10 +496,10 @@ Error Db::EditItemInItem(Item & item, bool with_subject) { AssertConnection(); std::ostringstream query; - query << "update core.item set (user_id, group_id, privileges, type, parent_id,"; + query << "update core.item set (user_id, group_id, privileges, type, parent_id"; if( with_subject ) - query << " url"; + query << ", url"; query << ") = ("; query << '\'' << item.user_id << "', "; @@ -566,19 +569,106 @@ return result; } - - -Error Db::EditItem(Item & item, bool with_subject) +Error Db::EditItemGetId(Item & item) { - Error result = EditItemInContent(item); + PGresult * r = 0; + Error result = Error::ok; + + try + { + AssertConnection(); + std::ostringstream query; + query << "select item.id, content.id from core.item left join core.content on item.content_id = content.id where item.parent_id='"; + query << item.parent_id << "' and item.url='" << Escape(item.url) << "';"; + + r = AssertQuery(query.str()); + AssertResultStatus(r, PGRES_TUPLES_OK); - if( result == Error::ok ) - result = EditItemInItem(item, with_subject); + if( PQntuples(r) != 1 || PQnfields(r) != 2 ) + throw Error(Error::db_no_item); + + // we cannot use AssertColumn() with a name because both columns are called 'id' + item.id = atol( AssertValue(r, 0, 0) ); + item.content_id = atol( AssertValue(r, 0, 1) ); + } + catch(const Error & e) + { + result = e; + } + + ClearResult(r); return result; } +Error Db::EditItemGetContentId(Item & item) +{ + PGresult * r = 0; + Error result = Error::ok; + + try + { + AssertConnection(); + std::ostringstream query; + query << "select content_id from core.item left join core.content on item.content_id = content.id where item.id='"; + query << item.id << "';"; + + r = AssertQuery(query.str()); + AssertResultStatus(r, PGRES_TUPLES_OK); + + if( PQntuples(r) != 1 || PQnfields(r) != 1 ) + throw Error(Error::db_no_item); + + item.content_id = atol( AssertValue(r, 0, 0) ); + } + catch(const Error & e) + { + result = e; + } + + ClearResult(r); + +return result; +} + + +// item.id must be set +Error Db::EditItemById(Item & item, bool with_subject) +{ + Error result = EditItemGetContentId(item); + + if( result == Error::ok ) + { + result = EditItemInContent(item); + + if( result == Error::ok ) + result = EditItemInItem(item, with_subject); + } + +return result; +} + + + +// item.url and item.parent_id must be set +Error Db::EditItemByUrl(Item & item, bool with_subject) +{ + Error result = EditItemGetId(item); + + if( result == Error::ok ) + { + result = EditItemInContent(item); + + if( result == Error::ok ) + result = EditItemInItem(item, with_subject); + } + +return result; +} + + + PGresult * Db::GetItemsQuery(Item & item_ref) @@ -670,6 +760,44 @@ void Db::GetItem(std::vector & item_table, long id) +bool Db::GetPriv(Item & item, long id) +{ +bool result = false; + + PGresult * r = 0; + + try + { + AssertConnection(); + + std::ostringstream query; + query << "select user_id, group_id, privileges, subject, content from core.item left join core.content on item.content_id = content.id where item.id='" << id << "';"; // !! tymczasowo odczytujemy z content i subject + + r = AssertQuery( query.str() ); + AssertResultStatus(r, PGRES_TUPLES_OK); + + int rows = PQntuples(r); + + if( rows != 1 ) + throw Error(); + + ItemColumns col; + col.SetColumns(r); + col.SetItem(r, 0, item); + + result = true; + } + catch(const Error &) + { + } + + ClearResult(r); + +return result; +} + + + bool Db::DelItemDelItem(const Item & item) { @@ -831,6 +959,115 @@ void Db::GetDirs(DirContainer & dir_table) +void Db::GetUsers(UGContainer & user_table) +{ + PGresult * r = 0; + + try + { + AssertConnection(); + + std::ostringstream query; + query << "select id, login, super_user, group_id from core.user left outer join core.group_mem on core.user.id = core.group_mem.user_id order by id asc;"; + + r = AssertQuery( query.str() ); + AssertResultStatus(r, PGRES_TUPLES_OK); + + int rows = PQntuples(r); + + int cid = AssertColumn(r, "id"); + int cname = AssertColumn(r, "login"); + int csuper_user = AssertColumn(r, "super_user"); + int cgroup_id = AssertColumn(r, "group_id"); + + User u; + long last_id = -1; + UGContainer::Iterator iter; + + for(int i = 0 ; i( atoi( AssertValue(r, i, csuper_user) ) ); + log << log1 << "Db: get user: id:" << u.id << ", name:" << u.name << ", super_user:" << u.super_user << logend; + + iter = user_table.PushBack( u ); + last_id = u.id; + } + + long group_id = atol( AssertValue(r, i, cgroup_id) ); + + if( !PQgetisnull(r, i, cgroup_id) && group_id!=-1 && !user_table.Empty() ) + { + iter->groups.push_back(group_id); + log << log3 << "Db: user:" << iter->name << " is a member of group_id:" << group_id << logend; + } + } + } + catch(const Error &) + { + } + + ClearResult(r); +} + + + +void Db::GetGroups(UGContainer & group_table) +{ + PGresult * r = 0; + + try + { + AssertConnection(); + + std::ostringstream query; + query << "select id, core.group.group, user_id from core.group left outer join core.group_mem on core.group.id = core.group_mem.group_id order by id asc;"; + + r = AssertQuery( query.str() ); + AssertResultStatus(r, PGRES_TUPLES_OK); + + int rows = PQntuples(r); + + int cid = AssertColumn(r, "id"); + int cname = AssertColumn(r, "group"); + int cuser_id = AssertColumn(r, "user_id"); + + Group g; + long last_id = -1; + UGContainer::Iterator iter; + + for(int i = 0 ; imembers.push_back(user_id); + log << log3 << "Db: get group member: user_id:" << user_id << logend; + } + } + } + catch(const Error &) + { + } + + ClearResult(r); +} diff --git a/core/db.h b/core/db.h index aa9b9a1..d669eea 100755 --- a/core/db.h +++ b/core/db.h @@ -24,7 +24,9 @@ #include "misc.h" #include "error.h" #include "dircontainer.h" - +#include "user.h" +#include "group.h" +#include "ugcontainer.h" class Db @@ -37,13 +39,16 @@ public: void Init(const std::string & database, const std::string & user, const std::string & pass); bool CheckUser(std::string & login, std::string & password, long & user_id); Error AddItem(Item & item); - Error EditItem(Item & item, bool with_subject = true); + Error EditItemById(Item & item, bool with_subject = true); + Error EditItemByUrl(Item & item, bool with_subject = true); void CheckAllUrlSubject(); void GetItems(std::vector & item_table, Item & item_ref); void GetItem(std::vector & item_table, long id); + bool GetPriv(Item & item, long id); bool DelItem(const Item & item); void GetDirs(DirContainer & dir_table); - + void GetUsers(UGContainer & user_table); + void GetGroups(UGContainer & group_table); @@ -70,6 +75,8 @@ protected: Error EditItemInItem(Item & item, bool with_subject); Error EditItemInContent(Item & item); + Error EditItemGetId(Item & item); + Error EditItemGetContentId(Item & item); void CheckAllUrlSubjectModifyItem(Item & item); diff --git a/core/db_itemcolumns.cpp b/core/db_itemcolumns.cpp index 7ce89ec..d1b90f1 100755 --- a/core/db_itemcolumns.cpp +++ b/core/db_itemcolumns.cpp @@ -1,7 +1,7 @@ -#include "db.h" - - - +#include "db.h" + + + void Db::ItemColumns::SetColumns(PGresult * r) { // PQfnumber returns -1 if there is no such a column @@ -18,7 +18,7 @@ void Db::ItemColumns::SetColumns(PGresult * r) content = PQfnumber(r, "content"); content_type = PQfnumber(r, "content_type"); } - + void Db::ItemColumns::SetItem(PGresult * r, long row, Item & item) @@ -36,11 +36,11 @@ void Db::ItemColumns::SetItem(PGresult * r, long row, Item & item) if( content != -1 ) item.content = Db::AssertValue(r, row, content); if( content_type != -1 ) item.content_type = atoi( Db::AssertValue(r, row, content_type) ); } - - - - - - - - + + + + + + + + diff --git a/core/dircontainer.cpp b/core/dircontainer.cpp index d654d59..4a5cd95 100755 --- a/core/dircontainer.cpp +++ b/core/dircontainer.cpp @@ -9,8 +9,8 @@ #include "dircontainer.h" -// !! tutaj ostatecznie ustawic wartosc np okolo 100 -// chwilowo do testow ustawione 2 + + DirContainer::DirContainer() { } diff --git a/core/dir.cpp b/core/dirs.cpp similarity index 77% rename from core/dir.cpp rename to core/dirs.cpp index efd9df8..e1734a0 100755 --- a/core/dir.cpp +++ b/core/dirs.cpp @@ -7,10 +7,10 @@ * */ -#include "dir.h" +#include "dirs.h" -void Dir::Clear() +void Dirs::Clear() { dir_table.Clear(); @@ -20,7 +20,7 @@ void Dir::Clear() } -void Dir::ReadDirs() +void Dirs::ReadDirs() { Clear(); @@ -30,7 +30,7 @@ void Dir::ReadDirs() -bool Dir::GetDir(const std::string & name, long parent, Item ** item) +bool Dirs::GetDir(const std::string & name, long parent, Item ** item) { DirContainer::ParentIterator i = dir_table.FindFirstParent(parent); @@ -45,7 +45,7 @@ return false; } -bool Dir::ExtractName(const char * & s, std::string & name) +bool Dirs::ExtractName(const char * & s, std::string & name) { name.clear(); @@ -61,7 +61,7 @@ return !name.empty(); -bool Dir::GetDir(const std::string & path, Item ** item) +bool Dirs::GetDir(const std::string & path, Item ** item) { long parent = -1; std::string name; @@ -82,7 +82,7 @@ return true; -bool Dir::GetDirId(const std::string & path, long * id) +bool Dirs::GetDirId(const std::string & path, long * id) { Item * pitem; @@ -95,7 +95,7 @@ return true; } -bool Dir::GetDirId(const std::string & name, long parent, long * id) +bool Dirs::GetDirId(const std::string & name, long parent, long * id) { Item * pitem; @@ -109,7 +109,7 @@ return true; -bool Dir::IsDir(long id) +bool Dirs::IsDir(long id) { if( id == -1 ) // root directory @@ -126,7 +126,7 @@ return true; -bool Dir::GetDirChilds(long parent, std::vector & childs_table) +bool Dirs::GetDirChilds(long parent, std::vector & childs_table) { if( !IsDir(parent) ) return false; @@ -146,7 +146,7 @@ return true; // dodatkowo moze metoda AppendPath dodajaca sciezke do biezacego stringa? // albo tutaj stringa nie czyscic? // O(m * log n) (m- how many parts are in 'id') -bool Dir::MakePath(long id, std::string & path) +bool Dirs::MakePath(long id, std::string & path) { DirContainer::Iterator i; @@ -172,7 +172,7 @@ DirContainer::Iterator i; // with exceptions -Item * Dir::GetDir(const std::string & path) +Item * Dirs::GetDir(const std::string & path) { Item * pitem; @@ -183,7 +183,7 @@ return pitem; } -Item * Dir::GetDir(const std::string & name, long parent) +Item * Dirs::GetDir(const std::string & name, long parent) { Item * pitem; @@ -195,7 +195,7 @@ return pitem; } -long Dir::GetDirId(const std::string & path) +long Dirs::GetDirId(const std::string & path) { long id; @@ -206,7 +206,7 @@ return id; } -long Dir::GetDirId(const std::string & name, long parent) +long Dirs::GetDirId(const std::string & name, long parent) { long id; diff --git a/core/dir.h b/core/dirs.h similarity index 96% rename from core/dir.h rename to core/dirs.h index d85a324..706455b 100755 --- a/core/dir.h +++ b/core/dirs.h @@ -7,8 +7,8 @@ * */ -#ifndef headerfiledir -#define headerfiledir +#ifndef headerfiledirs +#define headerfiledirs #include @@ -21,7 +21,8 @@ #include "dircontainer.h" -class Dir + +class Dirs { private: diff --git a/core/error.cpp b/core/error.cpp index 2b713f1..4ff68a4 100755 --- a/core/error.cpp +++ b/core/error.cpp @@ -28,6 +28,12 @@ Error::Error(int i) } +Error::Error(const Error & e) +{ + code = e.code; +} + + Error::operator int() const { return static_cast(code); @@ -40,6 +46,11 @@ Error & Error::operator=(Code c) return *this; } +Error & Error::operator=(const Error & e) +{ + code = e.code; + return *this; +} bool Error::operator==(Code c) const { diff --git a/core/error.h b/core/error.h index 80ff0a8..b8d4a42 100755 --- a/core/error.h +++ b/core/error.h @@ -33,18 +33,25 @@ public: db_incorrect_login, db_more_than_one_login, db_err_currval, - - + no_cookie, incorrect_dir, + cant_change_user, + cant_change_group, + cant_change_privileges, + permision_denied, unknown = 1000 + + }; Error(); Error(Code c); Error(int i); + Error(const Error & e); Error & operator=(Code c); + Error & operator=(const Error & e); operator int() const; diff --git a/core/group.h b/core/group.h new file mode 100755 index 0000000..1869193 --- /dev/null +++ b/core/group.h @@ -0,0 +1,43 @@ +/* + * This file is a part of CMSLU -- Content Management System like Unix + * and is not publicly distributed + * + * Copyright (c) 2008, Tomasz Sowa + * All rights reserved. + * + */ + +#ifndef headerfilegroup +#define headerfilegroup + +#include +#include + + + +struct Group +{ + long id; + std::string name; // group name + std::vector members; // users id + + Group() + { + Clear(); + } + + + void Clear() + { + id = -1; + name.clear(); + members.clear(); + } + +}; + + + + + +#endif diff --git a/core/groups.cpp b/core/groups.cpp new file mode 100755 index 0000000..f3962ca --- /dev/null +++ b/core/groups.cpp @@ -0,0 +1,118 @@ +/* + * This file is a part of CMSLU -- Content Management System like Unix + * and is not publicly distributed + * + * Copyright (c) 2008, Tomasz Sowa + * All rights reserved. + * + */ + +#include "groups.h" + + + + + + +Groups::Groups() +{ + Clear(); +} + + +void Groups::Clear() +{ + table.Clear(); +} + + +void Groups::ReadGroups() +{ + Clear(); + + db.GetGroups(table); +} + + +Group * Groups::GetGroup(long group_id) +{ + Table::Iterator i = table.FindId(group_id); + + if( i == table.End() ) + return 0; + +return &(*i); +} + + +Group * Groups::GetGroup(const std::string & name) +{ + Table::Iterator i = table.FindName(name); + + if( i == table.End() ) + return 0; + +return &(*i); +} + + +long Groups::GetGroupId(const std::string & name) +{ + Group * pgroup = GetGroup(name); + + if( !pgroup ) + return -1; + +return pgroup->id; +} + + + +Groups::Iterator Groups::Begin() +{ + return table.Begin(); +} + + + +Groups::Iterator Groups::End() +{ + return table.End(); +} + + + +Groups::SizeType Groups::Size() +{ + return table.Size(); +} + + +Group & Groups::operator[](Groups::SizeType pos) +{ + return table[pos]; +} + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/core/groups.h b/core/groups.h new file mode 100755 index 0000000..e56f91b --- /dev/null +++ b/core/groups.h @@ -0,0 +1,51 @@ +/* + * This file is a part of CMSLU -- Content Management System like Unix + * and is not publicly distributed + * + * Copyright (c) 2008, Tomasz Sowa + * All rights reserved. + * + */ + +#ifndef headerfilegroups +#define headerfilegroups + +#include +#include "group.h" +#include "db.h" +#include "ugcontainer.h" + + +class Groups +{ +typedef UGContainer Table; + +Table table; + +public: + + typedef Table::Iterator Iterator; + typedef Table::SizeType SizeType; + + Groups(); + void Clear(); + void ReadGroups(); + Group * GetGroup(long group_id); + Group * GetGroup(const std::string & name); + long GetGroupId(const std::string & name); + Iterator Begin(); + Iterator End(); + SizeType Size(); + Group & operator[](SizeType pos); + +}; + + + + + + + + + +#endif diff --git a/core/misc.cpp b/core/misc.cpp index 2c71ec5..f924efa 100755 --- a/core/misc.cpp +++ b/core/misc.cpp @@ -119,6 +119,9 @@ std::string::const_iterator i; else if( *i == '>' ) out << ">"; + else + if( *i == '&' ) + out << "&"; else out << *i; } @@ -136,3 +139,4 @@ return out.str(); + diff --git a/core/misc.h b/core/misc.h index 5254398..51800c1 100755 --- a/core/misc.h +++ b/core/misc.h @@ -29,5 +29,4 @@ void HtmlSpecial(std::ostringstream & out, const std::string & in); std::string HtmlSpecial(const std::string & in); - #endif diff --git a/core/request.cpp b/core/request.cpp index 660fabf..ca493c3 100755 --- a/core/request.cpp +++ b/core/request.cpp @@ -113,7 +113,7 @@ std::string & Request::PostVar(const char * var) p = post_table.find(var); if( p == post_table.end() ) - throw Error(); + throw Error(Error::no_cookie); return p->second; } @@ -288,3 +288,133 @@ void Request::SendAll() +bool Request::CanChangeUser(const Item & item, long new_user_id) +{ + if( !session ) + // session must be set + return false; + + if( session->puser && session->puser->super_user ) + // super user is allowed everything + return true; + + if( item.user_id != new_user_id ) + // only super user can change the owner of an item + return false; + +return true; +} + + +bool Request::CanChangeGroup(const Item & item, long new_group_id) +{ + if( !session ) + // session must be set + return false; + + if( session->puser && session->puser->super_user ) + // super user is allowed everything + return true; + + if( item.group_id != new_group_id ) + { + // user is allowed to change the group only if he is an owner of the item + // he can change only into a group in which he is a member of, or into a 'no_group' + + if( !session->puser ) + return false; + + if( session->puser->id != item.user_id ) + return false; + + if( new_group_id == -1 ) + return true; + + if( !session->puser->IsMemberOf(new_group_id) ) + return false; + + // is logged, is the owner of the item, is the member of the new group + } + +return true; +} + + +bool Request::CanChangePrivileges(const Item & item, int new_priv) +{ + if( !session ) + // session must be set + return false; + + if( session->puser && session->puser->super_user ) + // super user is allowed everything + return true; + + if( item.privileges != new_priv ) + { + // the owner of an item is allowed to change the privileges + + if( !session->puser ) + return false; + + if( session->puser->id != item.user_id ) + return false; + } + +return true; +} + + + +bool Request::HasAccess(const Item & item, int mask) +{ + if( !session ) + // session must be set + return false; + + if( session->puser && session->puser->super_user ) + // super user is allowed everything + return true; + + if( session->puser && session->puser->id == item.user_id ) + { + // the owner + return ((item.privileges >> 6) & mask) == mask; + } + + if( session->puser && session->puser->IsMemberOf(item.group_id) ) + { + // group + return ((item.privileges >> 3) & mask) == mask; + } + + // others + +return (item.privileges & mask) == mask; +} + + +bool Request::HasReadAccess(const Item & item) +{ + return HasAccess(item, 4); +} + + +bool Request::HasWriteAccess(const Item & item) +{ + return HasAccess(item, 2); +} + +bool Request::HasReadWriteAccess(const Item & item) +{ + return HasAccess(item, 6); // r+w +} + + +bool Request::HasExecAccess(const Item & item) +{ + return HasAccess(item, 5); // r+x +} + + + diff --git a/core/request.h b/core/request.h index ae53c17..4124eb8 100755 --- a/core/request.h +++ b/core/request.h @@ -58,7 +58,7 @@ struct Request Error done_status; // what to do - enum Result { err_internal, err404, show_dir, show_item, show_item_by_id, add_item, edit_item, del_item, del_item_confirm, confirm, redirect, logout } result; // zamienic na to_do + enum Result { err_internal, err404, err_per_denied, show_dir, show_item, show_item_by_id, add_item, edit_item, del_item, del_item_confirm, confirm, redirect, logout } result; // zamienic na to_do @@ -109,6 +109,17 @@ struct Request void SendAll(); + bool CanChangeUser(const Item & item, long new_user_id); + bool CanChangeGroup(const Item & item, long new_group_id); + bool CanChangePrivileges(const Item & item, int new_priv); + + bool HasAccess(const Item & item, int mask); + bool HasReadAccess(const Item & item); + bool HasWriteAccess(const Item & item); + bool HasReadWriteAccess(const Item & item); + bool HasExecAccess(const Item & item); + + private: // used to set some env_* variables into it, when the server didn't set that variable // it contains '\0' diff --git a/core/requestcontroller.cpp b/core/requestcontroller.cpp index b2527cc..33f1b4e 100755 --- a/core/requestcontroller.cpp +++ b/core/requestcontroller.cpp @@ -96,8 +96,9 @@ bool RequestController::Init() // - data.dir.ReadDirs(); - + data.dirs.ReadDirs(); + data.users.ReadUsers(); + data.groups.ReadGroups(); // if( !content.Init() ) diff --git a/core/session.cpp b/core/session.cpp index 1530dfd..60652dd 100755 --- a/core/session.cpp +++ b/core/session.cpp @@ -23,8 +23,8 @@ void Session::Clear() id = 0; time = 0; is_logged = false; - user_id = 0; - user.clear(); + user_id = -1; + puser = 0; done = Done::none; done_status = Error::ok; item.Clear(); diff --git a/core/session.h b/core/session.h index bf5dcd7..9d3017d 100755 --- a/core/session.h +++ b/core/session.h @@ -15,7 +15,7 @@ #include "error.h" #include "item.h" #include "done.h" - +#include "user.h" @@ -26,9 +26,12 @@ struct Session int time; bool is_logged; + + // !! moze tutaj -1 kiedy nie zalogowany i wywalic is_logged? long user_id; // logged user - std::string user; // user name + // !! moze wywalic user_id i zostawic tylko to? kiedy nie zalogowany to bedzie tutaj 0 + User * puser; // what is done Done done; diff --git a/core/templates.cpp b/core/templates.cpp index b67b34e..aca812b 100755 --- a/core/templates.cpp +++ b/core/templates.cpp @@ -20,11 +20,21 @@ Pattern pat_dir; Pattern pat_item_add_edit; Pattern pat_item_del_confirm; Pattern pat_err_404; +Pattern pat_err_per_denied; Pattern pat_err_internal; Functions functions; +void is_group_tv(Info & i) +{ + long gid = data.groups.GetGroupId("tv"); + + if( request.session->puser && request.session->puser->IsMemberOf(gid) ) + i.result = true; +} + + void language(Info & i) { // at the moment only Polish language @@ -62,6 +72,16 @@ void version_revision(Info & i) } +void user_name(Info & i) +{ + User * puser = data.users.GetUser(request.session->user_id); + + if( puser ) + i.out << puser->name; +} + + + void content(Info & i) { @@ -90,6 +110,10 @@ Pattern * p; p = &pat_err_internal; break; + case Request::err_per_denied: + p = &pat_err_per_denied; + break; + case Request::err404: default: p = &pat_err_404; @@ -121,9 +145,10 @@ void user_logged(Info & i) } -void user(Info & i) +void user_super_user(Info & i) { - i.out << request.session->user; + if( request.session->puser && request.session->puser->super_user ) + i.result = true; } @@ -137,17 +162,34 @@ void item_id(Info & i) void item_subject(Info & i) { - i.out << HtmlSpecial(request.item.subject); + i.out << request.item.subject; } void item_content(Info & i) { - //i.out << HtmlSpecial(request.item.content); i.out << request.item.content; } +void item_subject_escape(Info & i) +{ + i.out << HtmlSpecial(request.item.subject); +} + + +void item_content_escape(Info & i) +{ + i.out << HtmlSpecial(request.item.content); +} + + +void item_privileges(Info & i) +{ + i.out << std::setbase(8) << request.item.privileges << std::setbase(10); +} + + void item_url_subject(Info & i) // !! zmienic nazwe { i.out << request.item.url; @@ -158,7 +200,7 @@ void item_dir(Info & i) { std::string path; - if( data.dir.MakePath(request.item.parent_id, path) ) + if( data.dirs.MakePath(request.item.parent_id, path) ) { i.out << path; } @@ -200,7 +242,7 @@ void old_item_dir(Info & i) { std::string path; - if( data.dir.MakePath(request.session->item.parent_id, path) ) + if( data.dirs.MakePath(request.session->item.parent_id, path) ) { i.out << path; } @@ -415,6 +457,192 @@ void loggedout(Info & i) +std::vector fgroup_table; +size_t fgroup_index; + + + + +void fitem_group_initializing() +{ + fgroup_table.clear(); + + if( !request.session->puser ) + { + // not logged + fgroup_table.push_back(request.item.group_id); + } + else + if( request.session->puser->super_user ) + { + // super user is allowed to change to any group + for(size_t i=0 ; ipuser->id == request.item.user_id ) + { + bool was_current_group = false; + // owner of the item -- is allowed to change only to a group in which he belongs to + for(size_t i=0 ; ipuser->groups.size() ; ++i) + { + fgroup_table.push_back( request.session->puser->groups[i] ); + + if( request.item.group_id == request.session->puser->groups[i] ) + was_current_group = true; + } + + // we're showing the item.group_id if it's different + if( !was_current_group ) + fgroup_table.push_back(request.item.group_id); + + // switching to -1 is allowed too + fgroup_table.push_back(-1); + } + else + { + // not the owner and not a super user -- the same as not logged + fgroup_table.push_back(request.item.group_id); + } +} + + +void fitem_group(Info & i) +{ + if( i.iter == 0 ) + fitem_group_initializing(); + + fgroup_index = i.iter; + i.result = fgroup_index < fgroup_table.size(); +} + + + + +void fitem_group_name(Info & i) +{ + if( fgroup_index < fgroup_table.size() ) + { + long gid = fgroup_table[fgroup_index]; + + if( gid != -1 ) + { + Group * pgroup = data.groups.GetGroup( gid ); + + if( pgroup ) + i.out << pgroup->name; + else + i.out << "group_id: " << gid; + } + else + { + i.out << data.priv_no_group; + } + } +} + + + +void fitem_group_default(Info & i) +{ + if( fgroup_index < fgroup_table.size() ) + { + long gid = fgroup_table[fgroup_index]; + + if( gid == request.item.group_id ) + i.result = true; + } +} + + + + + + +std::vector fuser_table; +size_t fuser_index; + + +void fitem_user_initializing() +{ + fuser_table.clear(); + + if( !request.session->puser ) + { + // not logged + fuser_table.push_back(request.item.user_id); + } + else + if( request.session->puser->super_user ) + { + // super user is allowed to change to any user + for(size_t i=0 ; iname; + else + i.out << "user_id: " << uid; + } + else + { + i.out << data.priv_no_user; + } + } +} + + + +void fitem_user_default(Info & i) +{ + if( fuser_index < fuser_table.size() ) + { + long uid = fuser_table[fuser_index]; + + if( uid == request.item.user_id ) + i.result = true; + } +} + + + + } // namespace TemplatesFunctions @@ -426,6 +654,9 @@ void Templates::CreateFunctions() functions.Clear(); + + functions.Insert("is_group_tv", is_group_tv); + functions.Insert("language", language); functions.Insert("title", title); functions.Insert("charset", charset); @@ -436,13 +667,17 @@ void Templates::CreateFunctions() functions.Insert("base_url", base_url); functions.Insert("current_url", current_url); functions.Insert("user_logged", user_logged); - functions.Insert("user", user); + functions.Insert("user_super_user", user_super_user); + functions.Insert("item_id", item_id); functions.Insert("item_subject", item_subject); functions.Insert("item_content", item_content); + functions.Insert("item_subject_escape", item_subject_escape); + functions.Insert("item_content_escape", item_content_escape); functions.Insert("item_url_subject", item_url_subject); functions.Insert("item_dir", item_dir); + functions.Insert("item_privileges", item_privileges); functions.Insert("old_item_id", old_item_id); functions.Insert("old_item_subject", old_item_subject); @@ -486,6 +721,17 @@ void Templates::CreateFunctions() functions.Insert("fitems_in_dir", fitems_in_dir); + + functions.Insert("user_name", user_name); + + functions.Insert("fitem_group", fitem_group); + functions.Insert("fitem_group_name", fitem_group_name); + functions.Insert("fitem_group_default", fitem_group_default); + + functions.Insert("fitem_user", fitem_user); + functions.Insert("fitem_user_name", fitem_user_name); + functions.Insert("fitem_user_default", fitem_user_default); + } @@ -511,6 +757,9 @@ void Templates::Read() pat_err_404.Directory(data.templates); pat_err_404.ParseFile("err_404.html"); + pat_err_per_denied.Directory(data.templates); + pat_err_per_denied.ParseFile("err_per_denied.html"); + pat_item_del_confirm.Directory(data.templates); pat_item_del_confirm.ParseFile("item_del_confirm.html"); diff --git a/core/templates.h b/core/templates.h index 7167ad4..dc93bc4 100755 --- a/core/templates.h +++ b/core/templates.h @@ -10,6 +10,7 @@ #ifndef headerfiletemplates #define headerfiletemplates +#include #include "../../ezc/src/ezc.h" #include "data.h" @@ -17,6 +18,11 @@ #include "item.h" #include "db.h" #include "error.h" +#include "user.h" +#include "group.h" +#include "users.h" +#include "groups.h" + using namespace Ezc; diff --git a/core/ugcontainer.h b/core/ugcontainer.h new file mode 100755 index 0000000..6abb1bd --- /dev/null +++ b/core/ugcontainer.h @@ -0,0 +1,191 @@ +/* + * This file is a part of CMSLU -- Content Management System like Unix + * and is not publicly distributed + * + * Copyright (c) 2008, Tomasz Sowa + * All rights reserved. + * + */ + +#ifndef headerfileugcontainer +#define headerfileugcontainer + +#include +#include +#include +#include "log.h" + + + +template +class UGContainer +{ + +public: + typedef typename std::vector Table; + typedef typename Table::iterator Iterator; + typedef typename Table::size_type SizeType; + + typedef typename std::map TableId; + typedef typename std::map TableName; + + + UGContainer(); + + Iterator Begin(); + Iterator End(); + SizeType Size(); + bool Empty(); + Iterator PushBack(const Type & type); + void Clear(); + + Iterator FindId(long id); + Iterator FindName(const std::string & name); + + Type & operator[](SizeType pos); + + +private: + + void AddIndexes(SizeType pos); + void RebuildIndexes(); + + // main table + Table table; + + // indexes + TableId table_id; + TableName table_name; +}; + + + +template +UGContainer::UGContainer() // : table(100) +{ +} + + +template +typename UGContainer::Iterator UGContainer::Begin() +{ + return table.begin(); +} + + + +template +typename UGContainer::Iterator UGContainer::End() +{ + return table.end(); +} + + + +template +typename UGContainer::SizeType UGContainer::Size() +{ + return table.size(); +} + + + +template +bool UGContainer::Empty() +{ + return table.empty(); +} + + + +template +typename UGContainer::Iterator UGContainer::PushBack(const Type & type) +{ + table.push_back(type); + log << log2 << "UGCont: added, id: " << type.id << ", name: " << type.name << logend; + + AddIndexes( table.size() - 1 ); + +return --table.end(); +} + + + +template +void UGContainer::Clear() +{ + table.clear(); + table_id.clear(); + table_name.clear(); +} + + + +template +typename UGContainer::Iterator UGContainer::FindId(long id) +{ + typename TableId::iterator i = table_id.find(id); + + if( i == table_id.end() ) + return table.end(); + +return table.begin() + i->second; +} + + + +template +typename UGContainer::Iterator UGContainer::FindName(const std::string & name) +{ + typename TableName::iterator i = table_name.find(name); + + if( i == table_name.end() ) + return table.end(); + +return table.begin() + i->second; +} + + + +template +void UGContainer::AddIndexes(UGContainer::SizeType pos) +{ + table_id.insert( std::make_pair(table[pos].id, pos) ); + table_name.insert( std::make_pair(table[pos].name, pos) ); + + log << log2 << "UGCont: added indexes to: id: " << table[pos].id << ", name: " << table[pos].name << logend; +} + + + +template +void UGContainer::RebuildIndexes() +{ + log << log2 << "UGCont: rebuilding indexes" << logend; + + table_id.clear(); + table_name.clear(); + + SizeType i, len = table.size(); + + + for(i=0 ; i!=len ; ++i) + AddIndexes( i ); + + log << log2 << "UGCont: indexes rebuilt, table.size: " << table.size() << ", table_id.size: " + << table_id.size() << ", table_name.size: " << table_name.size() << logend; +} + + + +template +Type & UGContainer::operator[](UGContainer::SizeType pos) +{ + if( pos >= table.size() ) + throw std::out_of_range("UGContainer: operator[]: index is out of range"); + + return table[pos]; +} + + +#endif diff --git a/core/user.h b/core/user.h new file mode 100755 index 0000000..8922be0 --- /dev/null +++ b/core/user.h @@ -0,0 +1,53 @@ +/* + * This file is a part of CMSLU -- Content Management System like Unix + * and is not publicly distributed + * + * Copyright (c) 2008, Tomasz Sowa + * All rights reserved. + * + */ + +#ifndef headerfileuser +#define headerfileuser + +#include +#include + +struct User +{ + long id; + std::string name; + bool super_user; + std::vector groups; + + User() + { + Clear(); + } + + + void Clear() + { + id = -1; + name.clear(); + super_user = false; + groups.clear(); + } + + + bool IsMemberOf(long group) + { + std::vector::iterator i; + + for(i=groups.begin() ; i!=groups.end() ; ++i) + if( *i == group ) + return true; + + return false; + } + + +}; + + +#endif diff --git a/core/users.cpp b/core/users.cpp new file mode 100755 index 0000000..cf6002d --- /dev/null +++ b/core/users.cpp @@ -0,0 +1,110 @@ +/* + * This file is a part of CMSLU -- Content Management System like Unix + * and is not publicly distributed + * + * Copyright (c) 2008, Tomasz Sowa + * All rights reserved. + * + */ + +#include "users.h" + + + + +Users::Users() +{ + Clear(); +} + + + +void Users::Clear() +{ + table.Clear(); +} + + + +void Users::ReadUsers() +{ + Clear(); + + db.GetUsers(table); +} + + + +User * Users::GetUser(long user_id) +{ + Table::Iterator i = table.FindId(user_id); + + if( i == table.End() ) + return 0; + +return &(*i); +} + + +User * Users::GetUser(const std::string & name) +{ + Table::Iterator i = table.FindName(name); + + if( i == table.End() ) + return 0; + +return &(*i); +} + + + +long Users::GetUserId(const std::string & name) +{ +User * puser = GetUser(name); + + if( !puser ) + return -1; + +return puser->id; +} + + + +Users::Iterator Users::Begin() +{ + return table.Begin(); +} + + + +Users::Iterator Users::End() +{ + return table.End(); +} + + + +Users::SizeType Users::Size() +{ + return table.Size(); +} + + + +User & Users::operator[](Users::SizeType pos) +{ + return table[pos]; +} + + + + + + + + + + + + + diff --git a/core/users.h b/core/users.h new file mode 100755 index 0000000..748575d --- /dev/null +++ b/core/users.h @@ -0,0 +1,52 @@ +/* + * This file is a part of CMSLU -- Content Management System like Unix + * and is not publicly distributed + * + * Copyright (c) 2008, Tomasz Sowa + * All rights reserved. + * + */ + +#ifndef headerfileusers +#define headerfileusers + +#include +#include "user.h" +#include "db.h" +#include "ugcontainer.h" + + +class Users +{ + +typedef UGContainer Table; +Table table; + + +public: + + typedef Table::Iterator Iterator; + typedef Table::SizeType SizeType; + + + Users(); + void Clear(); + void ReadUsers(); + User * GetUser(long user_id); + User * GetUser(const std::string & name); + long GetUserId(const std::string & name); + Iterator Begin(); + Iterator End(); + SizeType Size(); + User & operator[](SizeType pos); + +}; + + + + + + + + +#endif