import the first version of cmslu
git-svn-id: svn://ttmath.org/publicrep/cmslu/trunk@460 e52654a7-88a9-db11-a3e9-0013d4bc506epull/3/head 0.1.0
parent
d4a5f1f963
commit
c53e985a92
@ -0,0 +1,46 @@
|
||||
CC = g++
|
||||
o = templates.o log.o requestcontroller.o main.o misc.o db.o session.o request.o content.o sessionmanager.o httpsimpleparser.o data.o dir.o error.o done.o dircontainer.o ezc.o
|
||||
CFLAGS = -Wall -pedantic -g -I/usr/local/include -L/usr/local/lib
|
||||
name = cmslu.fcgi
|
||||
|
||||
|
||||
all: $(name) $(mod_cms)
|
||||
|
||||
$(name): $(o)
|
||||
g++ -o $(name) $(CFLAGS) $(o) -lfcgi -lpq
|
||||
|
||||
|
||||
|
||||
|
||||
.SUFFIXES: .cpp .o
|
||||
|
||||
.cpp.o:
|
||||
$(CC) -c $(CFLAGS) $<
|
||||
|
||||
|
||||
|
||||
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
|
||||
log.o: core/log.cpp core/log.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
|
||||
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
|
||||
misc.o: core/misc.cpp core/misc.h core/log.h core/item.h
|
||||
db.o: core/db.cpp core/db.h core/log.h core/item.h core/misc.h core/error.h core/dircontainer.h
|
||||
session.o: core/session.cpp core/session.h core/requesttypes.h core/error.h core/log.h core/item.h 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
|
||||
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
|
||||
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
|
||||
httpsimpleparser.o: core/httpsimpleparser.cpp core/httpsimpleparser.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
|
||||
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
|
||||
error.o: core/error.cpp core/error.h core/log.h
|
||||
done.o: core/done.cpp core/done.h
|
||||
dircontainer.o: core/dircontainer.cpp core/dircontainer.h core/item.h core/log.h
|
||||
|
||||
ezc.o: ../ezc/src/ezc.cpp ../ezc/src/ezc.h
|
||||
|
||||
|
||||
|
||||
clean:
|
||||
rm -f *.o
|
||||
rm -f $(name)
|
||||
|
@ -0,0 +1,477 @@
|
||||
/*
|
||||
* 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 "content.h"
|
||||
|
||||
|
||||
|
||||
|
||||
bool Content::Init()
|
||||
{
|
||||
templates.Read();
|
||||
|
||||
|
||||
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];
|
||||
|
||||
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;
|
||||
PrepareUrlSubject(request.item);
|
||||
|
||||
request.session->done_status = db.AddItem(request.item);
|
||||
request.session->done_timer = 1;
|
||||
|
||||
// if( request.session->done_status != Request::added_item )
|
||||
//request.item_table.resize(1);
|
||||
//request.item_table[0] = request.item;
|
||||
}
|
||||
catch(const Error & e)
|
||||
{
|
||||
request.session->done_status = e;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
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() );
|
||||
|
||||
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.type = Item::file;
|
||||
PrepareUrlSubject(request.item);
|
||||
|
||||
request.session->done_status = db.EditItem(request.item, with_subject);
|
||||
request.session->done_timer = 1;
|
||||
}
|
||||
catch(const Error & e)
|
||||
{
|
||||
request.session->done_status = e;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Content::LogUser()
|
||||
{
|
||||
try
|
||||
{
|
||||
std::string & login = request.PostVar("login");
|
||||
std::string & pass = request.PostVar("password");
|
||||
long user_id;
|
||||
|
||||
if( db.CheckUser(login, pass, user_id) )
|
||||
{
|
||||
request.session->is_logged = true;
|
||||
request.session->user_id = user_id;
|
||||
request.session->user = login;
|
||||
|
||||
log << log2 << "User " << login << " (id: " << user_id << ") logged" << logend;
|
||||
}
|
||||
}
|
||||
catch(const Error &)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void Content::MakeDirectoryStructure()
|
||||
{
|
||||
GetTable::size_type get_table_len = request.get_table.size();
|
||||
long parent = -1;
|
||||
|
||||
for( get_index = 0 ; get_index < get_table_len ; ++get_index)
|
||||
{
|
||||
Item * pdir;
|
||||
|
||||
if( !data.dir.GetDir(request.get_table[get_index], parent, &pdir) )
|
||||
break;
|
||||
|
||||
parent = pdir->id;
|
||||
request.cur_dir_table.push_back( *pdir );
|
||||
}
|
||||
|
||||
// parent - last directory (or -1 if none)
|
||||
request.dir = parent;
|
||||
data.dir.GetDirChilds(parent, request.dir_table);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
Request::Result Content::StandardFunction(std::string & name)
|
||||
{
|
||||
Request::Result res = Request::err404;
|
||||
|
||||
// language polish
|
||||
// in the future there'll be something here
|
||||
// names of functions should not begin with an underscore '_'
|
||||
|
||||
if( name == "dodaj" )
|
||||
res = Request::add_item;
|
||||
else
|
||||
if( name == "edytuj" )
|
||||
res = Request::edit_item;
|
||||
else
|
||||
if( name == "id" )
|
||||
res = Request::show_item_by_id;
|
||||
else
|
||||
if( name == "usun" )
|
||||
res = Request::del_item;
|
||||
else
|
||||
if( name == "potwierdz" )
|
||||
res = Request::confirm;
|
||||
else
|
||||
if( name == "wyloguj" )
|
||||
res = Request::logout;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void Content::PrepareUrlSubject(Item & item)
|
||||
{
|
||||
SetUrlSubjectFromSubject(item);
|
||||
|
||||
if( StandardFunction(item.url_subject) != Request::err404 )
|
||||
{
|
||||
// names of functions should not begin with an underscore '_'
|
||||
// and we can simply add one '_' at the beginning
|
||||
// and the name will be unique
|
||||
item.url_subject.insert(item.url_subject.begin(), '_');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool Content::MakeGetCheckDir()
|
||||
{
|
||||
if( get_index == request.get_table.size() )
|
||||
{
|
||||
// request was for a directory
|
||||
db.GetItems(request.item_table, item);
|
||||
|
||||
|
||||
|
||||
// !! temporarily
|
||||
long default_id = -1;
|
||||
if( request.cur_dir_table.empty() )
|
||||
{
|
||||
default_id = data.dir.root.default_item;
|
||||
}
|
||||
else
|
||||
{
|
||||
default_id = request.cur_dir_table.back().default_item;
|
||||
}
|
||||
|
||||
|
||||
if( default_id != -1 )
|
||||
{
|
||||
request.result = Request::show_item;
|
||||
|
||||
std::vector<Item>::iterator i;
|
||||
for(i = request.item_table.begin() ; i != request.item_table.end() ; ++i)
|
||||
{
|
||||
if( i->id == default_id )
|
||||
request.item_table[0] = *i;
|
||||
}
|
||||
|
||||
request.item_table.resize(1);
|
||||
}
|
||||
else
|
||||
|
||||
if( data.one_item_is_showed &&
|
||||
request.item_table.size() == 1 &&
|
||||
request.item_table[0].type == Item::file )
|
||||
{
|
||||
request.result = Request::show_item;
|
||||
}
|
||||
else
|
||||
{
|
||||
request.result = Request::show_dir;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// zrobic tak ze gdzie podajemy cala liste aby nie ladowac contentu z bazy danych do itemow
|
||||
void Content::MakeGet()
|
||||
{
|
||||
MakeDirectoryStructure();
|
||||
|
||||
item.Clear();
|
||||
|
||||
// request.dir is set by MakeDirectoryStructure()
|
||||
item.parent_id = request.dir;
|
||||
|
||||
if( MakeGetCheckDir() )
|
||||
return;
|
||||
|
||||
// request was for an item or a standard function
|
||||
request.result = StandardFunction( request.get_table[get_index] );
|
||||
|
||||
if( request.result != Request::err404 )
|
||||
{
|
||||
// request for a standard function
|
||||
++get_index;
|
||||
return;
|
||||
}
|
||||
|
||||
if( request.get_table[get_index].empty() )
|
||||
// we do not have an empty url_subject
|
||||
// err404 at the end
|
||||
return;
|
||||
|
||||
// if we want to search by url_subject then request.get_table[get_index] should not be empty
|
||||
item.url_subject = request.get_table[get_index++];
|
||||
db.GetItems(request.item_table, item);
|
||||
|
||||
if( request.item_table.empty() )
|
||||
// err404 at the end
|
||||
return;
|
||||
|
||||
if( get_index == request.get_table.size() )
|
||||
{
|
||||
request.result = Request::show_item;
|
||||
return;
|
||||
}
|
||||
|
||||
// there is a standard function at the end
|
||||
request.result = StandardFunction( request.get_table[get_index++] );
|
||||
}
|
||||
|
||||
|
||||
void Content::MakeEditItem()
|
||||
{
|
||||
if( !request.item_table.empty() )
|
||||
request.item = request.item_table[0];
|
||||
else
|
||||
{
|
||||
log << log1 << "Content: request.item_table should not be empty" << logend;
|
||||
request.result = Request::err404;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Content::AppendCurDir(std::string & dir)
|
||||
{
|
||||
std::vector<Item>::size_type a;
|
||||
|
||||
for(a=0 ; a<request.cur_dir_table.size() ; ++a)
|
||||
{
|
||||
dir += request.cur_dir_table[a].url_subject;
|
||||
dir += '/';
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void Content::MakeShowItemById()
|
||||
{
|
||||
if( get_index == request.get_table.size() )
|
||||
{
|
||||
request.result = Request::err404;
|
||||
}
|
||||
else
|
||||
{
|
||||
long id = atol( request.get_table[get_index++].c_str() );
|
||||
db.GetItem(request.item_table, id);
|
||||
|
||||
if( request.item_table.empty() )
|
||||
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_subject;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void Content::MakeDelItem()
|
||||
{
|
||||
if( !request.session->is_logged )
|
||||
return;
|
||||
|
||||
|
||||
if( request.item_table.empty() )
|
||||
{
|
||||
request.result = Request::err404;
|
||||
return;
|
||||
}
|
||||
|
||||
if( get_index == request.get_table.size() )
|
||||
{
|
||||
request.CopyFirstItem();
|
||||
request.session->item = request.item;
|
||||
|
||||
if( db.DelItem( request.item.id ) )
|
||||
{
|
||||
request.session->done = Done::deleted_item;
|
||||
request.session->done_status = Error::ok;
|
||||
log << log2 << "Content: deleted item: subject: " << request.item.subject << ", id: " << request.item.id << logend;
|
||||
}
|
||||
else
|
||||
{
|
||||
request.session->done = Done::deleted_item;
|
||||
request.session->done_status = Error::db_no_item;
|
||||
}
|
||||
|
||||
request.result = Request::redirect;
|
||||
request.str = data.base_url;
|
||||
AppendCurDir(request.str);
|
||||
request.session->done_timer = 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
if( StandardFunction( request.get_table[get_index++] ) == Request::confirm )
|
||||
{
|
||||
request.result = Request::del_item_confirm;
|
||||
request.CopyFirstItem();
|
||||
}
|
||||
else
|
||||
request.result = Request::err404;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Content::MakeLogout()
|
||||
{
|
||||
if( request.session->is_logged )
|
||||
{
|
||||
log << log2 << "User " << request.session->user << " (id: " << request.session->user_id << ") logged out" << logend;
|
||||
|
||||
request.session->is_logged = false;
|
||||
request.session->user.clear();
|
||||
request.session->user_id = 0;
|
||||
}
|
||||
|
||||
request.result = Request::redirect;
|
||||
std::string path;
|
||||
data.dir.MakePath(request.dir, path);
|
||||
request.str = data.base_url + path;
|
||||
|
||||
if( !request.item_table.empty() )
|
||||
request.str += request.item_table[0].url_subject;
|
||||
|
||||
request.session->done = Done::loggedout;
|
||||
request.session->done_timer = 2;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void Content::MakeStandardFunction()
|
||||
{
|
||||
if( request.result == Request::edit_item )
|
||||
{
|
||||
MakeEditItem();
|
||||
}
|
||||
else
|
||||
if( request.result == Request::show_item_by_id )
|
||||
{
|
||||
MakeShowItemById();
|
||||
}
|
||||
else
|
||||
if( request.result == Request::del_item )
|
||||
{
|
||||
MakeDelItem();
|
||||
}
|
||||
else
|
||||
if( request.result == Request::logout )
|
||||
{
|
||||
MakeLogout();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
void Content::MakePost()
|
||||
{
|
||||
if( request.IsPostVar("add_item") )
|
||||
AddItem();
|
||||
else
|
||||
if( request.IsPostVar("edit_item") )
|
||||
EditItem();
|
||||
else
|
||||
if( request.IsPostVar("logging") )
|
||||
LogUser();
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
void Content::Make()
|
||||
{
|
||||
MakePost();
|
||||
MakeGet();
|
||||
MakeStandardFunction();
|
||||
|
||||
templates.Generate();
|
||||
|
||||
// request.PrintGetTable();
|
||||
//request.PrintEnv();
|
||||
// request.PrintIn();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -0,0 +1,73 @@
|
||||
/*
|
||||
* 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 headerfilecontent
|
||||
#define headerfilecontent
|
||||
|
||||
#include <cstdlib>
|
||||
#include <fcgiapp.h>
|
||||
|
||||
#include "templates.h"
|
||||
#include "request.h"
|
||||
#include "error.h"
|
||||
#include "misc.h"
|
||||
#include "db.h"
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
class Content
|
||||
{
|
||||
// index to request.get_table
|
||||
// set after calling MakeDirectoryStructure()
|
||||
// index of the last item which is not a directory (or is equal get_table.size())
|
||||
GetTable::size_type get_index;
|
||||
|
||||
|
||||
// temporarily object used for some purposes
|
||||
Item item;
|
||||
|
||||
|
||||
Templates templates;
|
||||
|
||||
|
||||
|
||||
void AddItem();
|
||||
void EditItem();
|
||||
void LogUser();
|
||||
|
||||
void MakeDirectoryStructure();
|
||||
Request::Result StandardFunction(std::string & name);
|
||||
void PrepareUrlSubject(Item & item);
|
||||
bool MakeGetCheckDir();
|
||||
|
||||
void MakeEditItem();
|
||||
void MakeShowItemById();
|
||||
void MakeDelItem();
|
||||
void MakeLogout();
|
||||
void MakeStandardFunction();
|
||||
|
||||
|
||||
void AppendCurDir(std::string & dir);
|
||||
|
||||
void MakePost();
|
||||
void MakeGet();
|
||||
|
||||
public:
|
||||
|
||||
bool Init();
|
||||
|
||||
void Make();
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
||||
#endif
|
@ -0,0 +1,70 @@
|
||||
/*
|
||||
* 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 headerfilecookieparser
|
||||
#define headerfilecookieparser
|
||||
|
||||
#include <fcgiapp.h>
|
||||
#include "httpsimpleparser.h"
|
||||
#include "requesttypes.h"
|
||||
|
||||
|
||||
|
||||
|
||||
class CookieParser : public HttpSimpleParser
|
||||
{
|
||||
|
||||
const char * cookie_string;
|
||||
CookieTable & cookie_table;
|
||||
|
||||
|
||||
protected:
|
||||
|
||||
|
||||
virtual int GetChar()
|
||||
{
|
||||
if( !cookie_string || *cookie_string == 0 )
|
||||
return -1;
|
||||
|
||||
return (int)(unsigned char)*(cookie_string++);
|
||||
}
|
||||
|
||||
|
||||
virtual void Parameter(std::string & name, std::string & value)
|
||||
{
|
||||
// Cookie names are case insensitive according to section 3.1 of RFC 2965
|
||||
ToLower(name);
|
||||
|
||||
std::pair<CookieTable::iterator, bool> res = cookie_table.insert( std::make_pair(name, value) );
|
||||
|
||||
log << log2 << "Cookie, name: \"" << name << "\", value: \"" << value << "\"";
|
||||
|
||||
if( res.second == false )
|
||||
log << log2 << " (skipped)";
|
||||
|
||||
log << log2 << logend;
|
||||
}
|
||||
|
||||
|
||||
public:
|
||||
|
||||
|
||||
CookieParser(const char * cookie_string_, CookieTable & cookie_table_) : cookie_string(cookie_string_), cookie_table(cookie_table_)
|
||||
{
|
||||
HttpSimpleParser::separator = ';';
|
||||
HttpSimpleParser::value_can_be_quoted = true;
|
||||
HttpSimpleParser::skip_white_chars = true;
|
||||
HttpSimpleParser::recognize_special_chars = false;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
#endif
|
@ -0,0 +1,46 @@
|
||||
/*
|
||||
* 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 "data.h"
|
||||
|
||||
|
||||
|
||||
Data::Data()
|
||||
{
|
||||
// all these data will be reading from a config file
|
||||
|
||||
log_file = "cmslu.log";
|
||||
fcgi_socket = "/var/cmslu/s1";
|
||||
fcgi_socket_chmod = 0770;
|
||||
fcgi_socket_user = "tomek";
|
||||
fcgi_socket_group = "www";
|
||||
|
||||
log_level = 2;
|
||||
log_stdout = true;
|
||||
|
||||
templates = "../httpd/templates"; // templates dir
|
||||
default_index = "index.html";
|
||||
http_session_id_name = "slimaczek_sid";
|
||||
db_database = "tomek";
|
||||
db_user = "tomek";
|
||||
db_pass = "monitorekasd";
|
||||
|
||||
// !! add a method which will be adding a slash at the end of url-es
|
||||
base_url = "http://s10.slimaczek.pl/"; // with a slash at the end
|
||||
|
||||
one_item_is_showed = true;
|
||||
|
||||
dir.root.default_item = 134;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -0,0 +1,88 @@
|
||||
/*
|
||||
* 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 headerfiledata
|
||||
#define headerfiledata
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
|
||||
#include "misc.h"
|
||||
#include "item.h"
|
||||
#include "error.h"
|
||||
#include "dir.h"
|
||||
|
||||
|
||||
|
||||
class Data
|
||||
{
|
||||
|
||||
|
||||
public:
|
||||
|
||||
|
||||
|
||||
// log file name
|
||||
std::string log_file;
|
||||
|
||||
// 1 - minimum
|
||||
// 2 - (default)
|
||||
// 3 - maximum - all logs
|
||||
int log_level;
|
||||
|
||||
// logging to stdout too
|
||||
bool log_stdout;
|
||||
|
||||
|
||||
// fast cgi: socket (unix domain)
|
||||
std::string fcgi_socket;
|
||||
|
||||
// fast cgi: socket permissions
|
||||
int fcgi_socket_chmod;
|
||||
|
||||
// fast cgi: owner of the socket
|
||||
std::string fcgi_socket_user;
|
||||
|
||||
// fast cgi: group of the socket
|
||||
std::string fcgi_socket_group;
|
||||
|
||||
std::string templates;
|
||||
std::string default_index;
|
||||
|
||||
std::string db_database;
|
||||
std::string db_user;
|
||||
std::string db_pass;
|
||||
std::string base_url;
|
||||
std::string http_session_id_name;
|
||||
|
||||
|
||||
|
||||
|
||||
Dir dir;
|
||||
|
||||
|
||||
// if there is one item in a directory
|
||||
// it will be showed
|
||||
// (instead of showing directory contents)
|
||||
bool one_item_is_showed;
|
||||
|
||||
|
||||
|
||||
Data();
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
extern Data data;
|
||||
|
||||
|
||||
#endif
|
@ -0,0 +1,668 @@
|
||||
/*
|
||||
* 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 "db.h"
|
||||
|
||||
|
||||
Db::Db()
|
||||
{
|
||||
pg_conn = 0;
|
||||
}
|
||||
|
||||
|
||||
Db::~Db()
|
||||
{
|
||||
Close();
|
||||
}
|
||||
|
||||
|
||||
|
||||
void Db::Init(const std::string & d, const std::string & u, const std::string & p)
|
||||
{
|
||||
db_database = d;
|
||||
db_user = u;
|
||||
db_pass = p;
|
||||
|
||||
Connect();
|
||||
}
|
||||
|
||||
|
||||
void Db::Connect()
|
||||
{
|
||||
std::ostringstream buf;
|
||||
buf << "dbname=" << db_database << " user=" << db_user << " password=" << db_pass;
|
||||
|
||||
pg_conn = PQconnectdb(buf.str().c_str());
|
||||
|
||||
if( !pg_conn )
|
||||
log << log1 << "Db: Fatal error during connecting" << logend;
|
||||
|
||||
if( PQsetClientEncoding(pg_conn, "LATIN2") == -1 )
|
||||
log << log1 << "Db: Can't set the proper client encoding" << logend;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void Db::Close()
|
||||
{
|
||||
if( pg_conn )
|
||||
{
|
||||
PQfinish(pg_conn);
|
||||
pg_conn = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Db::AssertConnection()
|
||||
{
|
||||
if( !pg_conn )
|
||||
{
|
||||
log << log1 << "Db: Trying to connect into the database...";
|
||||
Connect();
|
||||
|
||||
if( !pg_conn )
|
||||
// logend from Connect()
|
||||
throw Error(Error::db_fatal_error_during_connecting);
|
||||
|
||||
log << log1 << "ok" << logend;
|
||||
}
|
||||
|
||||
|
||||
if( PQstatus(pg_conn) != CONNECTION_OK )
|
||||
{
|
||||
log << log2 << "Db: connection into the database is lost, trying to recover..." << logend;
|
||||
PQreset(pg_conn);
|
||||
|
||||
if( PQstatus(pg_conn) != CONNECTION_OK )
|
||||
{
|
||||
log << log2 << "no" << logend;
|
||||
throw Error(Error::db_fatal_error_during_connecting);
|
||||
}
|
||||
else
|
||||
{
|
||||
log << log2 << "ok" << logend;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
std::string Db::Escape(const std::string & s)
|
||||
{
|
||||
std::string result;
|
||||
|
||||
result.resize(s.length() * 2 + 1);
|
||||
|
||||
size_t len = PQescapeStringConn(pg_conn, const_cast<char*>( result.c_str() ), s.c_str(), s.length(), 0);
|
||||
result.resize(len);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
std::string Db::Escape(const char * s)
|
||||
{
|
||||
std::string result;
|
||||
int len;
|
||||
|
||||
for(len=0 ; s[len] != 0 ; ++len);
|
||||
|
||||
result.resize(len * 2 + 1);
|
||||
|
||||
size_t len_new = PQescapeStringConn(pg_conn, const_cast<char*>( result.c_str() ), s, len, 0);
|
||||
result.resize(len_new);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// ------------------
|
||||
|
||||
|
||||
|
||||
PGresult * Db::AssertQuery(const std::string & q)
|
||||
{
|
||||
PGresult * r = PQexec(pg_conn, q.c_str());
|
||||
|
||||
if( !r )
|
||||
{
|
||||
log << log1 << "Db: Problem with query: " << PQerrorMessage(pg_conn) << logend;
|
||||
throw Error(Error::db_incorrect_query);
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void Db::AssertResultStatus(PGresult * r, ExecStatusType t)
|
||||
{
|
||||
if( PQresultStatus(r) != t )
|
||||
{
|
||||
log << "Db: Incorrect result status: " << PQerrorMessage(pg_conn) << logend;
|
||||
|
||||
throw Error(Error::db_incorrent_result_status);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
int Db::AssertColumn(PGresult * r, const char * column_name)
|
||||
{
|
||||
int c = PQfnumber(r, column_name);
|
||||
|
||||
if( c == -1 )
|
||||
{
|
||||
log << log1 << "Db: there is no column: " << column_name << logend;
|
||||
|
||||
throw Error(Error::db_no_column);
|
||||
}
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
|
||||
const char * Db::AssertValue(PGresult * r, int row, int col)
|
||||
{
|
||||
const char * res = PQgetvalue(r, row, col);
|
||||
|
||||
if( !res )
|
||||
{
|
||||
log << log1 << "Db: there is no such an item in the result, row:" << row << ", col:" << col << logend;
|
||||
|
||||
throw Error(Error::db_no_item);
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
void Db::ClearResult(PGresult * r)
|
||||
{
|
||||
if( r )
|
||||
PQclear(r);
|
||||
}
|
||||
|
||||
|
||||
bool Db::CheckUser(std::string & login, std::string & password, long & user_id)
|
||||
{
|
||||
PGresult * r = 0;
|
||||
bool user_ok = false;
|
||||
|
||||
try
|
||||
{
|
||||
AssertConnection();
|
||||
|
||||
std::ostringstream query;
|
||||
query << "select id from core.user where login='" << Escape(login) << "' and password='" << Escape(password) << "';";
|
||||
|
||||
r = AssertQuery( query.str() );
|
||||
|
||||
AssertResultStatus(r, PGRES_TUPLES_OK);
|
||||
|
||||
int rows = PQntuples(r);
|
||||
|
||||
if( rows == 0 )
|
||||
throw Error(Error::db_incorrect_login);
|
||||
|
||||
if( rows > 1 )
|
||||
{
|
||||
log << log1 << "Db: there is more than one user: " << login << " (with the same password)" << logend;
|
||||
throw Error(Error::db_more_than_one_login);
|
||||
}
|
||||
|
||||
int cuser_id = AssertColumn(r, "id");
|
||||
const char * fuser_id = AssertValue(r, 0, cuser_id);
|
||||
user_id = atol( fuser_id );
|
||||
|
||||
user_ok = true;
|
||||
}
|
||||
catch(const Error &)
|
||||
{
|
||||
}
|
||||
|
||||
ClearResult(r);
|
||||
|
||||
|
||||
return user_ok;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
bool Db::AddItemCreateUrlSubject(Item & item)
|
||||
{
|
||||
bool is_that_url;
|
||||
PGresult * r = 0;
|
||||
int index = 1;
|
||||
const int max_index = 100;
|
||||
char appendix[20];
|
||||
appendix[0] = 0;
|
||||
|
||||
|
||||
try
|
||||
{
|
||||
do
|
||||
{
|
||||
std::ostringstream query;
|
||||
|
||||
// this Escape can be put at the beginning (performance)
|
||||
query << "select id from core.item where url_subject='" << Escape(item.url_subject) << appendix << "' and parent_id='" << item.parent_id << "';";
|
||||
r = AssertQuery(query.str());
|
||||
AssertResultStatus(r, PGRES_TUPLES_OK);
|
||||
|
||||
if( PQntuples(r) != 0 )
|
||||
{
|
||||
sprintf(appendix, "_(%d)", ++index);
|
||||
is_that_url = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
item.url_subject += appendix;
|
||||
is_that_url = false;
|
||||
}
|
||||
|
||||
ClearResult(r);
|
||||
r = 0;
|
||||
}
|
||||
while( is_that_url && index <= max_index );
|
||||
}
|
||||
catch(const Error &)
|
||||
{
|
||||
is_that_url = true; // for return false
|
||||
}
|
||||
|
||||
|
||||
ClearResult(r);
|
||||
|
||||
|
||||
return !is_that_url;
|
||||
}
|
||||
|
||||
|
||||
// for testing consistency
|
||||
void Db::CheckAllUrlSubjectModifyItem(Item & item)
|
||||
{
|
||||
PGresult * r = 0;
|
||||
|
||||
try
|
||||
{
|
||||
std::ostringstream query;
|
||||
query << "update core.item set url_subject=";
|
||||
|
||||
// url_subject
|
||||
if( AddItemCreateUrlSubject(item) )
|
||||
query << '\'' << Escape(item.url_subject) << '\'';
|
||||
else
|
||||
{
|
||||
query << '\'' << item.id << '\'';
|
||||
item.url_subject.clear();
|
||||
}
|
||||
|
||||
query << " where id='" << item.id << "';";
|
||||
|
||||
r = AssertQuery(query.str());
|
||||
AssertResultStatus(r, PGRES_COMMAND_OK);
|
||||
}
|
||||
catch(const Error &)
|
||||
{
|
||||
}
|
||||
|
||||
ClearResult(r);
|
||||
}
|
||||
|
||||
|
||||
|
||||
// for checking consistency
|
||||
void Db::CheckAllUrlSubject()
|
||||
{
|
||||
PGresult * r = 0;
|
||||
Item item;
|
||||
|
||||
try
|
||||
{
|
||||
AssertConnection();
|
||||
std::ostringstream query, query2;
|
||||
query << "select id, subject from core.item where url_subject is null or url_subject=''";
|
||||
|
||||
r = AssertQuery(query.str());
|
||||
AssertResultStatus(r, PGRES_TUPLES_OK);
|
||||
|
||||
int rows = PQntuples(r);
|
||||
int cid = AssertColumn(r, "id");
|
||||
int csubject = AssertColumn(r, "subject");
|
||||
|
||||
for(int i = 0 ; i<rows ; ++i)
|
||||
{
|
||||
item.id = atol( AssertValue(r, i, cid) );
|
||||
item.subject = AssertValue(r, i, csubject);
|
||||
|
||||
CheckAllUrlSubjectModifyItem(item);
|
||||
}
|
||||
}
|
||||
catch(const Error &)
|
||||
{
|
||||
}
|
||||
|
||||
ClearResult(r);
|
||||
}
|
||||
|
||||
|
||||
|
||||
long Db::AssertCurrval(const char * table)
|
||||
{
|
||||
PGresult * r;
|
||||
std::ostringstream query;
|
||||
|
||||
query << "select currval('" << table << "');";
|
||||
|
||||
r = AssertQuery(query.str());
|
||||
AssertResultStatus(r, PGRES_TUPLES_OK);
|
||||
|
||||
if( PQntuples(r) != 1 )
|
||||
{
|
||||
log << log1 << "Db: error (currval) for table: " << table << ", " << PQerrorMessage(pg_conn) << logend;
|
||||
throw Error(Error::db_err_currval);
|
||||
}
|
||||
|
||||
long res = strtol( AssertValue(r, 0, 0), 0, 10 );
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
|
||||
Error Db::AddItem(Item & item)
|
||||
{
|
||||
PGresult * r = 0;
|
||||
Error result = Error::ok;
|
||||
bool url_without_id = false;
|
||||
|
||||
try
|
||||
{
|
||||
AssertConnection();
|
||||
std::ostringstream query;
|
||||
query << "insert into core.item (subject, content, url_subject, type, parent_id) values (";
|
||||
query << '\'' << Escape(item.subject) << "', ";
|
||||
query << '\'' << Escape(item.content) << "', ";
|
||||
|
||||
// url_subject
|
||||
url_without_id = AddItemCreateUrlSubject(item);
|
||||
|
||||
if( url_without_id )
|
||||
{
|
||||
query << '\'' << Escape(item.url_subject) << "', ";
|
||||
}
|
||||
else
|
||||
{
|
||||
query << "currval('core.item_id_seq')" << ", ";
|
||||
}
|
||||
|
||||
|
||||
query << '\'' << static_cast<int>(item.type) << "', ";
|
||||
query << '\'' << item.parent_id << "' ";
|
||||
query << ");";
|
||||
|
||||
r = AssertQuery(query.str());
|
||||
AssertResultStatus(r, PGRES_COMMAND_OK);
|
||||
|
||||
item.id = AssertCurrval("core.item_id_seq");
|
||||
|
||||
if( !url_without_id )
|
||||
ToString(item.url_subject, item.id);
|
||||
|
||||
}
|
||||
catch(const Error & e)
|
||||
{
|
||||
result = e;
|
||||
}
|
||||
|
||||
ClearResult(r);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
Error Db::EditItem(Item & item, bool with_subject)
|
||||
{
|
||||
PGresult * r = 0;
|
||||
Error result = Error::ok;
|
||||
bool url_without_id = false;
|
||||
|
||||
try
|
||||
{
|
||||
AssertConnection();
|
||||
std::ostringstream query;
|
||||
query << "update core.item set (";
|
||||
|
||||
if( with_subject )
|
||||
query << "subject, url_subject, ";
|
||||
|
||||
query << "content, type, parent_id) = (";
|
||||
|
||||
if( with_subject )
|
||||
{
|
||||
query << '\'' << Escape(item.subject) << "', ";
|
||||
|
||||
// url_subject
|
||||
url_without_id = AddItemCreateUrlSubject(item);
|
||||
|
||||
if( url_without_id )
|
||||
{
|
||||
query << '\'' << Escape(item.url_subject) << "', ";
|
||||
}
|
||||
else
|
||||
{
|
||||
query << '\'' << item.id << "', ";
|
||||
}
|
||||
}
|
||||
|
||||
query << '\'' << Escape(item.content) << "', ";
|
||||
|
||||
query << '\'' << static_cast<int>(item.type) << "', ";
|
||||
query << '\'' << item.parent_id << "' ";
|
||||
query << ") where id='" << item.id << "';";
|
||||
|
||||
r = AssertQuery(query.str());
|
||||
AssertResultStatus(r, PGRES_COMMAND_OK);
|
||||
|
||||
if( with_subject && !url_without_id )
|
||||
ToString(item.url_subject, item.id);
|
||||
}
|
||||
catch(const Error & e)
|
||||
{
|
||||
result = e;
|
||||
}
|
||||
|
||||
ClearResult(r);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
PGresult * Db::GetItemsQuery(Item & item_ref)
|
||||
{
|
||||
std::ostringstream query;
|
||||
query << "select * from core.item where type!='0' and parent_id='" << item_ref.parent_id << "'";
|
||||
|
||||
if( item_ref.id != -1 )
|
||||
query << " and id='" << item_ref.id << "'";
|
||||
|
||||
if( !item_ref.url_subject.empty() )
|
||||
query << " and url_subject='" << Escape(item_ref.url_subject) << "'";
|
||||
|
||||
query << ';';
|
||||
|
||||
return AssertQuery(query.str());
|
||||
}
|
||||
|
||||
|
||||
|
||||
void Db::GetItems(std::vector<Item> & item_table, Item & item_ref)
|
||||
{
|
||||
item_table.clear();
|
||||
PGresult * r = 0;
|
||||
|
||||
try
|
||||
{
|
||||
AssertConnection();
|
||||
|
||||
r = GetItemsQuery(item_ref);
|
||||
AssertResultStatus(r, PGRES_TUPLES_OK);
|
||||
|
||||
Item item;
|
||||
int rows = PQntuples(r);
|
||||
|
||||
ItemColumns col;
|
||||
col.SetColumns(r);
|
||||
|
||||
for(int i = 0 ; i<rows ; ++i)
|
||||
{
|
||||
col.SetItem(r, i, item);
|
||||
item_table.push_back(item);
|
||||
}
|
||||
}
|
||||
catch(const Error &)
|
||||
{
|
||||
}
|
||||
|
||||
ClearResult(r);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void Db::GetItem(std::vector<Item> & item_table, long id)
|
||||
{
|
||||
PGresult * r = 0;
|
||||
|
||||
try
|
||||
{
|
||||
AssertConnection();
|
||||
|
||||
std::ostringstream query;
|
||||
query << "select * from core.item where type='1' and id='" << id << "';";
|
||||
|
||||
r = AssertQuery( query.str() );
|
||||
AssertResultStatus(r, PGRES_TUPLES_OK);
|
||||
|
||||
Item item;
|
||||
int rows = PQntuples(r);
|
||||
|
||||
if( rows > 1 )
|
||||
log << log1 << "Db: we have more than one item with id: " << id << logend;
|
||||
|
||||
ItemColumns col;
|
||||
col.SetColumns(r);
|
||||
|
||||
for(int i = 0 ; i<rows ; ++i)
|
||||
{
|
||||
col.SetItem(r, i, item);
|
||||
item_table.push_back(item);
|
||||
}
|
||||
}
|
||||
catch(const Error &)
|
||||
{
|
||||
}
|
||||
|
||||
ClearResult(r);
|
||||
}
|
||||
|
||||
|
||||
bool Db::DelItem(long id)
|
||||
{
|
||||
long rows = 0;
|
||||
PGresult * r = 0;
|
||||
|
||||
try
|
||||
{
|
||||
AssertConnection();
|
||||
|
||||
std::ostringstream query;
|
||||
query << "delete from core.item where type='1' and id='" << id << "';";
|
||||
|
||||
r = AssertQuery( query.str() );
|
||||
AssertResultStatus(r, PGRES_COMMAND_OK);
|
||||
|
||||
const char * crows = PQcmdTuples(r);
|
||||
if( crows )
|
||||
{
|
||||
rows = atol(crows);
|
||||
|
||||
if( rows > 1 )
|
||||
log << log1 << "Db: more than one item were deleted" << logend;
|
||||
}
|
||||
}
|
||||
catch(const Error &)
|
||||
{
|
||||
}
|
||||
|
||||
ClearResult(r);
|
||||
|
||||
return rows != 0;
|
||||
}
|
||||
|
||||
|
||||
void Db::GetDirs(DirContainer & dir_table)
|
||||
{
|
||||
PGresult * r = 0;
|
||||
|
||||
try
|
||||
{
|
||||
AssertConnection();
|
||||
|
||||
std::ostringstream query;
|
||||
query << "select * from core.item where type='0';";
|
||||
|
||||
r = AssertQuery( query.str() );
|
||||
AssertResultStatus(r, PGRES_TUPLES_OK);
|
||||
|
||||
Item item;
|
||||
int rows = PQntuples(r);
|
||||
|
||||
ItemColumns col;
|
||||
col.SetColumns(r);
|
||||
|
||||
for(int i = 0 ; i<rows ; ++i)
|
||||
{
|
||||
col.SetItem(r, i, item);
|
||||
dir_table.PushBack( item );
|
||||
}
|
||||
}
|
||||
catch(const Error &)
|
||||
{
|
||||
}
|
||||
|
||||
ClearResult(r);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -0,0 +1,119 @@
|
||||
/*
|
||||
* 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 headerfilecoredb
|
||||
#define headerfilecoredb
|
||||
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <sstream>
|
||||
#include <libpq-fe.h>
|
||||
#include <cstdio>
|
||||
|
||||
|
||||
#include "log.h"
|
||||
#include "item.h"
|
||||
#include "misc.h"
|
||||
#include "error.h"
|
||||
#include "dircontainer.h"
|
||||
|
||||
|
||||
|
||||
class Db
|
||||
{
|
||||
|
||||
protected:
|
||||
|
||||
PGconn * pg_conn;
|
||||
|
||||
std::string db_database, db_user, db_pass;
|
||||
|
||||
public:
|
||||
|
||||
Db();
|
||||
~Db();
|
||||
|
||||
void Init(const std::string & database, const std::string & user, const std::string & pass);
|
||||
void Connect();
|
||||
|
||||
void Close();
|
||||
void AssertConnection();
|
||||
std::string Escape(const std::string & s);
|
||||
std::string Escape(const char * s);
|
||||
|
||||
PGresult * AssertQuery(const std::string & q);
|
||||
void AssertResultStatus(PGresult * r, ExecStatusType t);
|
||||
static int AssertColumn(PGresult * r, const char * column_name);
|
||||
static const char * AssertValue(PGresult * r, int row, int col);
|
||||
|
||||
void ClearResult(PGresult * r);
|
||||
|
||||
bool CheckUser(std::string & login, std::string & password, long & user_id);
|
||||
|
||||
long AssertCurrval(const char * table);
|
||||
|
||||
|
||||
bool AddItemCreateUrlSubject(Item & item);
|
||||
Error AddItem(Item & item);
|
||||
Error EditItem(Item & item, bool with_subject = true);
|
||||
|
||||
void CheckAllUrlSubjectModifyItem(Item & item);
|
||||
void CheckAllUrlSubject();
|
||||
|
||||
PGresult * GetItemsQuery(Item & item_ref);
|
||||
void GetItems(std::vector<Item> & item_table, Item & item_ref);
|
||||
void GetItem(std::vector<Item> & item_table, long id);
|
||||
|
||||
bool DelItem(long id);
|
||||
|
||||
void GetDirs(DirContainer & dir_table);
|
||||
|
||||
|
||||
|
||||
struct ItemColumns
|
||||
{
|
||||
int id, subject, content, url_subject, type, parent_id, default_item;
|
||||
|
||||
void SetColumns(PGresult * r)
|
||||
{
|
||||
id = Db::AssertColumn(r, "id");
|
||||
subject = Db::AssertColumn(r, "subject");
|
||||
content = Db::AssertColumn(r, "content");
|
||||
url_subject = Db::AssertColumn(r, "url_subject");
|
||||
type = Db::AssertColumn(r, "type");
|
||||
parent_id = Db::AssertColumn(r, "parent_id");
|
||||
default_item = Db::AssertColumn(r, "default_item");
|
||||
}
|
||||
|
||||
|
||||
void SetItem(PGresult * r, long row, Item & item)
|
||||
{
|
||||
item.id = atol( Db::AssertValue(r, row, id) );
|
||||
item.subject = Db::AssertValue(r, row, subject);
|
||||
item.content = Db::AssertValue(r, row, content);
|
||||
item.url_subject = Db::AssertValue(r, row, url_subject);
|
||||
item.type = static_cast<Item::Type>( atoi( Db::AssertValue(r, row, type) ) );
|
||||
item.parent_id = atol( Db::AssertValue(r, row, parent_id) );
|
||||
item.default_item = atol( Db::AssertValue(r, row, default_item) );
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
||||
}; // class Db
|
||||
|
||||
|
||||
extern Db db;
|
||||
|
||||
|
||||
#endif
|
||||
|