2008-12-10 05:42:49 +01:00
|
|
|
/*
|
|
|
|
* 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 "request.h"
|
|
|
|
|
|
|
|
|
|
|
|
|
2008-12-12 04:11:29 +01:00
|
|
|
Request::Request() : char_empty(0)
|
2008-12-10 05:42:49 +01:00
|
|
|
{
|
|
|
|
Clear();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void Request::Clear()
|
|
|
|
{
|
|
|
|
// warning: don't clear in, out, err, env
|
|
|
|
|
|
|
|
get_table.clear();
|
|
|
|
post_table.clear();
|
|
|
|
cookie_table.clear();
|
|
|
|
|
|
|
|
method = none;
|
|
|
|
|
|
|
|
headers.str("");
|
|
|
|
page.str("");
|
|
|
|
debug.str("");
|
|
|
|
|
2008-12-12 04:11:29 +01:00
|
|
|
env_request_method = &char_empty;
|
|
|
|
env_request_uri = &char_empty;
|
|
|
|
env_http_cookie = &char_empty;
|
|
|
|
env_remote_addr = &char_empty;
|
|
|
|
env_http_host = &char_empty;
|
|
|
|
|
2008-12-10 05:42:49 +01:00
|
|
|
|
|
|
|
session = 0;
|
|
|
|
|
|
|
|
result = err404; // tutaj moze cos lepszego, cos w stylu 'not implemented'
|
|
|
|
|
|
|
|
dir = -1;
|
|
|
|
cur_dir_table.clear();
|
|
|
|
item_table.clear();
|
|
|
|
dir_table.clear();
|
|
|
|
|
|
|
|
item.Clear();
|
|
|
|
str.clear();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void Request::CopyFirstItem()
|
|
|
|
{
|
|
|
|
if( !request.item_table.empty() )
|
|
|
|
request.item = request.item_table[0];
|
|
|
|
else
|
|
|
|
{
|
|
|
|
request.item.Clear();
|
|
|
|
|
|
|
|
log << log1 << "Request::CopyFirstItem: item_table is empty" << logend;
|
|
|
|
request.result = err_internal;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// value can be null
|
|
|
|
void Request::SetCookie(const char * name, const char * value)
|
|
|
|
{
|
|
|
|
request.headers << "Set-Cookie: " << name << "=";
|
|
|
|
|
|
|
|
if( value && value[0]!=0 )
|
|
|
|
request.headers << value;
|
|
|
|
else
|
|
|
|
request.headers << "\"\"";
|
|
|
|
|
|
|
|
request.headers << "; path=/\r\n";
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void Request::SetCookie(const char * name, long value)
|
|
|
|
{
|
|
|
|
request.headers << "Set-Cookie: " << name << "=" << value << "; path=/\r\n";
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bool Request::IsPostVar(const char * var)
|
|
|
|
{
|
|
|
|
PostTable::iterator p;
|
|
|
|
|
|
|
|
p = post_table.find(var);
|
|
|
|
|
|
|
|
if( p == post_table.end() )
|
|
|
|
return false;
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
std::string & Request::PostVar(const char * var)
|
|
|
|
{
|
|
|
|
PostTable::iterator p;
|
|
|
|
|
|
|
|
p = post_table.find(var);
|
|
|
|
|
|
|
|
if( p == post_table.end() )
|
2008-12-21 22:17:09 +01:00
|
|
|
throw Error(Error::no_cookie);
|
2008-12-10 05:42:49 +01:00
|
|
|
|
|
|
|
return p->second;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
|
|
|
|
|
|
|
void Request::PrintGetTable()
|
|
|
|
{
|
|
|
|
debug << "get_table: " << get_table.size() << "\n";
|
|
|
|
|
|
|
|
for(GetTable::iterator i = get_table.begin() ; i != get_table.end() ; ++i)
|
|
|
|
debug << " \"" << *i << "\"\n";
|
|
|
|
|
|
|
|
debug << std::endl;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void Request::PrintEnv()
|
|
|
|
{
|
|
|
|
char ** e;
|
|
|
|
|
|
|
|
debug << "environment variables:\n";
|
|
|
|
|
|
|
|
for( e = env ; *e ; ++e )
|
|
|
|
debug << ' ' << *e << "\n";
|
|
|
|
|
|
|
|
debug << std::endl;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void Request::PrintIn()
|
|
|
|
{
|
|
|
|
char buf[100];
|
|
|
|
int buf_len = sizeof(buf) / sizeof(char);
|
|
|
|
int len;
|
|
|
|
|
|
|
|
debug << "fcgi input:\n";
|
|
|
|
|
|
|
|
do
|
|
|
|
{
|
|
|
|
len = FCGX_GetStr(buf, buf_len - 1, in);
|
|
|
|
|
|
|
|
if( len != 0 )
|
|
|
|
{
|
|
|
|
buf[len] = 0;
|
|
|
|
debug << buf;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
while( len == buf_len - 1 );
|
|
|
|
|
|
|
|
debug << std::endl;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2008-12-12 04:11:29 +01:00
|
|
|
const char * Request::SetEnvVar(const char * var)
|
|
|
|
{
|
|
|
|
const char * v = FCGX_GetParam(var, env);
|
|
|
|
|
|
|
|
if( v )
|
|
|
|
return v;
|
|
|
|
|
|
|
|
// char_empty contains '\0'
|
|
|
|
return &char_empty;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2008-12-10 05:42:49 +01:00
|
|
|
void Request::ReadEnvVariables()
|
|
|
|
{
|
|
|
|
// we store that values because FCGX_GetParam has O(n) complexity
|
|
|
|
// with this variables (env_*) we have O(1)
|
|
|
|
|
2008-12-12 04:11:29 +01:00
|
|
|
env_request_method = SetEnvVar("REQUEST_METHOD");
|
|
|
|
env_request_uri = SetEnvVar("REQUEST_URI");
|
|
|
|
env_http_cookie = SetEnvVar("HTTP_COOKIE");
|
|
|
|
env_remote_addr = SetEnvVar("REMOTE_ADDR");
|
|
|
|
env_http_host = SetEnvVar("HTTP_HOST");
|
2008-12-11 03:46:16 +01:00
|
|
|
|
|
|
|
log << log1 << "IP: " << env_remote_addr << logend;
|
2008-12-10 05:42:49 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void Request::CheckMethod()
|
|
|
|
{
|
|
|
|
method = none;
|
|
|
|
|
|
|
|
if( env_request_method[0] == 'G' )
|
|
|
|
method = get;
|
|
|
|
else
|
|
|
|
if( env_request_method[0] == 'P' )
|
|
|
|
method = post;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void Request::ReadParameters()
|
|
|
|
{
|
|
|
|
// some parameters (get) we have always
|
|
|
|
// if( method == get )
|
|
|
|
{
|
|
|
|
GetParser get_parser(env_request_uri, get_table);
|
|
|
|
get_parser.Parse();
|
|
|
|
}
|
|
|
|
|
|
|
|
if( method == post )
|
|
|
|
{
|
|
|
|
PostParser post_parser(in, post_table);
|
|
|
|
post_parser.Parse();
|
|
|
|
}
|
|
|
|
|
|
|
|
CookieParser cookie_parser(env_http_cookie, cookie_table);
|
|
|
|
cookie_parser.Parse();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// reading everything
|
|
|
|
void Request::Read()
|
|
|
|
{
|
|
|
|
ReadEnvVariables();
|
|
|
|
CheckMethod();
|
|
|
|
ReadParameters();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void Request::SendAll()
|
|
|
|
{
|
|
|
|
if( result == redirect )
|
|
|
|
{
|
|
|
|
FCGX_PutS("Status: 301 Moved Permanently\r\n", out);
|
|
|
|
FCGX_FPrintF(out, "Location: %s\r\n", str.c_str());
|
|
|
|
|
|
|
|
log << log2 << "Redirect into: " << str << logend;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
FCGX_PutS("Status: 200 OK\r\n", out);
|
|
|
|
FCGX_PutS("Content-Type: Text/Html\r\n", out);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
FCGX_PutS(headers.str().c_str(), out);
|
|
|
|
FCGX_PutS("\r\n", out);
|
|
|
|
|
|
|
|
|
|
|
|
if( result == redirect )
|
|
|
|
// if there is a redirect we do not send a content
|
|
|
|
return;
|
|
|
|
|
|
|
|
FCGX_PutS(page.str().c_str(), out);
|
|
|
|
|
|
|
|
const std::string & d = debug.str();
|
|
|
|
|
|
|
|
if( !d.empty() )
|
|
|
|
{
|
|
|
|
FCGX_PutS("\n<!--\n", out);
|
|
|
|
FCGX_PutS(d.c_str(), out);
|
|
|
|
FCGX_PutS("\n-->\n", out);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2008-12-21 22:17:09 +01:00
|
|
|
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
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|