added: to mount points: file systems

we have two file systems now:
       - simplefs - the files stored on the hard drive have the same structure as in the database (dir1/dir2/file)
       - hashfs - files are stored in special directories
extented: the mountparser can read file system 
added: function download
       this is a default function for items which have static content
  


git-svn-id: svn://ttmath.org/publicrep/winix/trunk@588 e52654a7-88a9-db11-a3e9-0013d4bc506e
This commit is contained in:
2010-02-18 23:30:22 +00:00
parent 87747fab06
commit 16e51cd4e5
34 changed files with 487 additions and 157 deletions

View File

@@ -109,8 +109,9 @@ void Config::AssignValues()
data.log_stdout = false;
data.post_file_max = Int("post_file_max", 8388608); // 8 MB
data.static_auth_dir = Text("static_auth_dir");
data.static_auth_dir_tmp = Text("static_auth_dir_tmp");
data.static_simplefs_dir = Text("static_simplefs_dir");
data.static_hashfs_dir = Text("static_hashfs_dir");
data.static_tmp_dir = Text("static_tmp_dir");
data.templates_dir = Text("templates_dir");
data.templates_dir_default = Text("templates_dir_default");

View File

@@ -112,12 +112,13 @@ public:
// 0 - not used
int post_file_max;
// directory for static files (for fastcgi authorizer mode)
std::string static_auth_dir;
// directories for static files
std::string static_simplefs_dir;
std::string static_hashfs_dir;
// temporary dir for static content used by upload function
// should be on the same partition as static_auth_dir
std::string static_auth_dir_tmp;
// temporary directory for static content used by the upload function
// should be on the same partition as static_simplefs_dir and static_hashfs_dir
std::string static_tmp_dir;
// default locale: en pl
std::string locale_str;

View File

@@ -45,6 +45,7 @@ public:
unknown_param,
mount_unknown,
unknown_filesystem,
no_mountpoint,
mount_no_param,

View File

@@ -41,6 +41,7 @@
#define FUN_CHMOD 25
#define FUN_CHOWN 26
#define FUN_CKEDITOR 27
#define FUN_DOWNLOAD 28

View File

@@ -139,6 +139,10 @@ void Functions::ReadFunctions()
f.item.url = "ckeditor";
table.insert( std::make_pair(f.item.url, f) );
f.code = FUN_DOWNLOAD;
f.item.url = "download";
table.insert( std::make_pair(f.item.url, f) );
// functions which need more privileges

View File

@@ -586,6 +586,28 @@ bool IsFile(const std::string & file)
}
bool CreateDir(const char * dir, int priv)
{
if( !IsFile(dir) )
{
if( mkdir(dir, priv) < 0 )
{
log << log1 << "Can't create a directory on fs: " << dir << logend;
return false;
}
}
return true;
}
bool CreateDir(const std::string & dir, int priv)
{
return CreateDir(dir.c_str(), priv);
}
// if there is not an extension it returns a pointer to the last '\0' character
const char * GetFileExt(const char * name)
{

View File

@@ -64,6 +64,8 @@ bool ValidateEmail(const std::string & email);
bool IsFile(const char * file);
bool IsFile(const std::string & file);
bool CreateDir(const char * dir, int priv);
bool CreateDir(const std::string & dir, int priv);
const char * GetFileExt(const char * name);
Item::StaticAuth SelectFileType(const char * file_name);

View File

@@ -16,6 +16,7 @@ Mount::Mount()
{
type = cms;
dir_id = -1;
fs = simplefs;
param.resize(par_none);
}
@@ -49,6 +50,29 @@ return buffer;
}
const char * Mount::FsToStr()
{
static char buffer[30];
switch( fs )
{
case simplefs:
sprintf(buffer, "simplefs");
break;
case hashfs:
sprintf(buffer, "hashfs");
break;
default:
sprintf(buffer, "unknown");
break;
}
return buffer;
}
Mount::ParamCode Mount::ParseParam(const char * param_name)
{
@@ -76,7 +100,8 @@ Mount::ParamCode Mount::ParseParam(const char * param_name)
{ par_createticket_on, "createticket_on" },
{ par_only_root_remove, "only_root_remove" },
{ par_emacs_on, "emacs_on" },
{ par_mkdir_on, "mkdir_on" }
{ par_mkdir_on, "mkdir_on" },
{ par_app, "app" }
};
size_t i, len = sizeof(par_name_tab) / sizeof(ParName);

View File

@@ -30,6 +30,12 @@ public:
ticket
};
enum Fs
{
simplefs = 0,
hashfs
};
// the first should be with 0 index
// the last should be 'none'
@@ -53,6 +59,7 @@ public:
par_only_root_remove,
par_emacs_on,
par_mkdir_on,
par_app,
par_none
};
@@ -74,13 +81,15 @@ public:
long dir_id;
Type type;
Fs fs;
Mount();
const char * TypeToStr();
const char * FsToStr();
static ParamCode ParseParam(const char * param);
void ClearParams();

View File

@@ -2,7 +2,7 @@
* This file is a part of CMSLU -- Content Management System like Unix
* and is not publicly distributed
*
* Copyright (c) 2009, Tomasz Sowa
* Copyright (c) 2010, Tomasz Sowa
* All rights reserved.
*
*/
@@ -245,6 +245,30 @@ void MountParser::ReadMountPoint()
void MountParser::ReadFs()
{
ReadWord(temp);
if( temp == "simplefs" )
{
mount.fs = Mount::simplefs;
log << log1 << "MP: file system: simplefs" << logend;
}
else
if( temp == "hashfs" )
{
mount.fs = Mount::hashfs;
log << log1 << "MP: file system: hashfs" << logend;
}
else
{
err = Error::unknown_filesystem;
log << log1 << "MP: unknown filesystem: " << temp << logend;
}
}
void MountParser::LogMountParams()
{
size_t i;
@@ -263,6 +287,7 @@ size_t i;
}
void MountParser::ReadMountParams()
{
mount.ClearParams();
@@ -300,6 +325,9 @@ void MountParser::ReadRow(std::map<long, Mount> & output)
if( err == Error::ok )
ReadMountPoint();
if( err == Error::ok )
ReadFs();
if( err == Error::ok )
ReadMountParams();

View File

@@ -2,7 +2,7 @@
* This file is a part of CMSLU -- Content Management System like Unix
* and is not publicly distributed
*
* Copyright (c) 2009, Tomasz Sowa
* Copyright (c) 2010, Tomasz Sowa
* All rights reserved.
*
*/
@@ -44,6 +44,7 @@ private:
void ReadParam(std::string & res, Mount::ParamArg & args);
void ReadMountType();
void ReadMountPoint();
void ReadFs();
void LogMountParams();
void ReadMountParams();
void ReadRow(std::map<long, Mount> & output);

View File

@@ -78,7 +78,8 @@ void Mounts::MountCmsForRoot()
{
Mount mount;
mount.type = Mount::cms;
mount.fs = Mount::simplefs;
Item * proot = data.dirs.GetRootDir();
if( proot )
@@ -112,7 +113,8 @@ std::vector<Item*>::reverse_iterator i;
if( m != mount_tab.end() )
{
pmount = &(m->second);
log << log2 << "M: current mount point is: " << pmount->TypeToStr() << logend;
log << log2 << "M: current mount point is: " << pmount->TypeToStr()
<< ", fs: " << pmount->FsToStr() << logend;
return;
}
}
@@ -120,5 +122,6 @@ std::vector<Item*>::reverse_iterator i;
// if nothing was found
// we assume that 'cms' mount point is used
MountCmsForRoot();
log << log2 << "M: current mount point is: cms (default)" << logend;
log << log2 << "M: current mount point is: " << pmount->TypeToStr() << " (default)"
<< ", fs: " << pmount->FsToStr() << logend;
}

View File

@@ -433,7 +433,14 @@ void PostMultiParser::CreateTmpFile()
{
char buf[100];
sprintf(buf, "%s/winix_%u_%d_%u", data.static_auth_dir_tmp.c_str(), (unsigned)getpid(), tmp_filename_postfix, rand());
if( data.static_tmp_dir.empty() )
{
log << log1 << "PMP: static_tmp_dir is not set in the config" << logend;
err = Error::cant_create_file;
return;
}
sprintf(buf, "%s/winix_%u_%d_%u", data.static_tmp_dir.c_str(), (unsigned)getpid(), tmp_filename_postfix, rand());
tmp_filename_postfix += 1;
tmp_file.open(buf, std::ios_base::binary | std::ios_base::out);

View File

@@ -103,7 +103,8 @@ void Request::Clear()
notify_code = 0;
browser_msie = false;
redirect_to.clear();
x_sendfile.clear();
send_as_attachment = false;
plugin.Call(WINIX_REQUEST_CLEAR);
}
@@ -409,6 +410,9 @@ void Request::SendSessionCookie()
void Request::SendHeaders(bool compressing, Header header)
{
if( send_as_attachment )
FCGX_PutS("Content-Disposition: attachment\r\n", out);
if( !redirect_to.empty() )
{
FCGX_PutS("Status: 301 Moved Permanently\r\n", out);
@@ -416,6 +420,13 @@ void Request::SendHeaders(bool compressing, Header header)
log << log2 << "Redirect to: " << redirect_to << logend;
}
else
if( !x_sendfile.empty() )
{
FCGX_FPrintF(out, "X-LIGHTTPD-send-file: %s\r\n", x_sendfile.c_str());
FCGX_PutS("Status: 200 OK\r\n", out);
log << log2 << "Sending file: " << x_sendfile << logend;
}
else
{
switch(header)
{
@@ -490,7 +501,7 @@ void Request::SendAll()
{
const std::string & source = page.str();
Header header = h_200;
bool compressing = data.compression && role == responder &&
bool compressing = data.compression && role == responder && redirect_to.empty() && x_sendfile.empty() &&
!browser_msie && !browser_konqueror &&
accept_encoding_parser.AcceptDeflate() && source.size() >= 512;
@@ -504,8 +515,8 @@ bool compressing = data.compression && role == responder &&
SendSessionCookie();
SendHeaders(compressing, header);
if( !redirect_to.empty() )
// if there is a redirect we do not send a content
if( !redirect_to.empty() || !x_sendfile.empty() )
// if there is a redirect or a file to send then we do not send a content
return;
if( header == h_200 && role == authorizer && is_item && item.static_auth != Item::static_none )
@@ -852,8 +863,30 @@ bool Request::CanUseUpload(const Item & item, bool check_root)
if( item.type != Item::dir )
return false;
// we must know where to store the file
if( !data.mounts.pmount )
return false;
if( data.mounts.pmount->fs == Mount::simplefs && data.static_simplefs_dir.empty() )
{
log << log1 << "Request: can't use upload function, static_simplefs_dir must be set in the config file" << logend;
return false;
}
if( data.mounts.pmount->fs == Mount::hashfs && data.static_hashfs_dir.empty() )
{
log << log1 << "Request: can't use upload function, static_hashfs_dir must be set in the config file" << logend;
return false;
}
if( data.static_tmp_dir.empty() )
{
log << log1 << "Request: can't use upload function, static_tmp_dir must be set in the config file" << logend;
return false;
}
if( !check_root && request.session->puser && request.session->puser->super_user )
// super user can use mkdir everywhere
// super user can use upload everywhere
return true;
if( !request.HasWriteAccess(item) )
@@ -905,41 +938,105 @@ return false;
// !! dobrac lepsze nazwy dla tych dwoch metod
void Request::MakePath(std::string & path)
bool Request::MakePathSimpleFs(std::string & path, bool create_dir)
{
size_t i;
path = data.static_auth_dir;
size_t i;
path = data.static_simplefs_dir;
if( path.empty() )
{
log << log1 << "Request: static_simplefs_dir is not set in the config file" << logend;
return false;
}
// skipping the first - the first is root
for(i=1 ; i<dir_table.size() ; ++i)
{
path += '/';
path += dir_table[i]->url;
if( create_dir && !CreateDir(path, 0755) )
return false;
}
}
bool Request::MakeDirsOnFS()
{
size_t i;
std::string path = data.static_auth_dir;
// skipping the first - the first is root
for(i=1 ; i<dir_table.size() ; ++i)
{
path += '/';
path += dir_table[i]->url;
if( !IsFile(path.c_str()) )
{
if( mkdir(path.c_str(), 0755) < 0 )
{
log << log1 << "Request: can't create the directory on fs: " << path << logend;
return false;
}
}
}
path += '/';
return true;
}
// the path depends on id
bool Request::MakePathHashFs(std::string & path, long id, bool create_dir)
{
char buffer[50];
char * hash = buffer;
// get 'id' as hexadecimal
buffer[0] = '0';
sprintf(buffer+1, "%lx", (unsigned long)id);
path = data.static_hashfs_dir;
if( path.empty() )
{
log << log1 << "Request: static_hashfs_dir is not set in the config file" << logend;
return false;
}
path += '/';
// make sure that the length is even
if( (strlen(hash) & 1) != 0 )
hash = buffer + 1; // the first character was our zero
// creating dirs without the last part
// the last part is a part of a file (not a directory)
for(size_t i=0 ; hash[i] != 0 ; i+=2)
{
path += hash[i];
path += hash[i+1];
if( hash[i+2] != 0 )
{
if( create_dir && !CreateDir(path, 0755) )
return false;
path += '/';
}
}
// one character more to make sure the path is unique
// (we can have a directory without the character)
path += "_";
return true;
}
// making a complete path to a request.item static file
bool Request::MakePath(std::string & path, bool create_dir)
{
bool res;
if( data.mounts.pmount->fs == Mount::hashfs )
{
res = MakePathHashFs(path, request.item.id, create_dir);
}
else
{
res = MakePathSimpleFs(path, create_dir);
}
if( res )
path += request.item.url;
else
path.clear();
return res;
}

View File

@@ -113,6 +113,12 @@ struct Request
// if not empty means an address for redirecting to
std::string redirect_to;
// send header X-LIGHTTPD-send-file with path to a file
std::string x_sendfile;
// send as attachment (causing header: content-disposition: attachment)
bool send_as_attachment;
// for debugging
void PrintGetTable();
void PrintEnv();
@@ -164,8 +170,9 @@ struct Request
bool CanUseBBCode(long user_id);
bool CanUseRaw(long user_id);
void MakePath(std::string & path);
bool MakeDirsOnFS();
bool MakePathSimpleFs(std::string & path, bool create_dir = false);
bool MakePathHashFs(std::string & path, long id, bool create_dir = false);
bool MakePath(std::string & path, bool create_dir = false);
private: