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:
@@ -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");
|
||||
|
11
core/data.h
11
core/data.h
@@ -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;
|
||||
|
@@ -45,6 +45,7 @@ public:
|
||||
unknown_param,
|
||||
|
||||
mount_unknown,
|
||||
unknown_filesystem,
|
||||
no_mountpoint,
|
||||
mount_no_param,
|
||||
|
||||
|
@@ -41,6 +41,7 @@
|
||||
#define FUN_CHMOD 25
|
||||
#define FUN_CHOWN 26
|
||||
#define FUN_CKEDITOR 27
|
||||
#define FUN_DOWNLOAD 28
|
||||
|
||||
|
||||
|
||||
|
@@ -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
|
||||
|
||||
|
@@ -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)
|
||||
{
|
||||
|
@@ -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);
|
||||
|
@@ -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);
|
||||
|
11
core/mount.h
11
core/mount.h
@@ -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();
|
||||
|
||||
|
||||
|
@@ -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();
|
||||
|
||||
|
@@ -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);
|
||||
|
@@ -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;
|
||||
}
|
||||
|
@@ -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);
|
||||
|
159
core/request.cpp
159
core/request.cpp
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
@@ -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:
|
||||
|
||||
|
Reference in New Issue
Block a user