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:
Tomasz Sowa 2010-02-18 23:30:22 +00:00
parent 87747fab06
commit 16e51cd4e5
34 changed files with 487 additions and 157 deletions

View File

@ -23,7 +23,7 @@ winix: FORCE
@cd templates ; $(MAKE) -e @cd templates ; $(MAKE) -e
@cd templatesnotify ; $(MAKE) -e @cd templatesnotify ; $(MAKE) -e
@cd ../ezc/src ; $(MAKE) -e @cd ../ezc/src ; $(MAKE) -e
$(CXX) -shared -o winix.so $(CXXFLAGS) core/*.o content/*.o templates/*.o templatesnotify/*.o confparser/*.o ../ezc/src/ezc.a -lfcgi -lpq -lz $(CXX) -shared -o winix.so $(CXXFLAGS) core/*.o content/*.o templates/*.o templatesnotify/*.o confparser/*.o ../ezc/src/ezc.a -lfcgi -lpq -lz -lpthread
@cd main ; $(MAKE) -e @cd main ; $(MAKE) -e
# use the full path with winix.so # use the full path with winix.so
$(CXX) -o winix $(CXXFLAGS) main/*.o /home/tomek/roboczy/winix/winix.so $(CXX) -o winix $(CXXFLAGS) main/*.o /home/tomek/roboczy/winix/winix.so

View File

@ -11,7 +11,10 @@ cat.o: ../core/error.h ../core/log.h ../core/user.h ../core/rebus.h
cat.o: ../core/function.h ../core/thread.h ../core/compress.h cat.o: ../core/function.h ../core/thread.h ../core/compress.h
cat.o: ../core/acceptencodingparser.h ../core/acceptbaseparser.h cat.o: ../core/acceptencodingparser.h ../core/acceptbaseparser.h
cat.o: ../core/htmlfilter.h ../core/postmultiparser.h ../core/ticket.h cat.o: ../core/htmlfilter.h ../core/postmultiparser.h ../core/ticket.h
cat.o: ../core/error.h cat.o: ../core/error.h ../core/data.h ../core/dirs.h ../core/dircontainer.h
cat.o: ../core/users.h ../core/ugcontainer.h ../core/groups.h ../core/group.h
cat.o: ../core/functions.h ../core/lastcontainer.h ../core/mounts.h
cat.o: ../core/mount.h ../core/loadavg.h
content.o: content.h ../core/item.h ../templates/templates.h content.o: content.h ../core/item.h ../templates/templates.h
content.o: ../templates/patterncacher.h ../templates/misc.h content.o: ../templates/patterncacher.h ../templates/misc.h
content.o: ../templates/localefilter.h ../core/locale.h content.o: ../templates/localefilter.h ../core/locale.h
@ -81,6 +84,22 @@ default.o: ../core/ugcontainer.h ../core/data.h ../core/dirs.h
default.o: ../core/users.h ../core/groups.h ../core/functions.h default.o: ../core/users.h ../core/groups.h ../core/functions.h
default.o: ../core/lastcontainer.h ../core/mounts.h ../core/mount.h default.o: ../core/lastcontainer.h ../core/mounts.h ../core/mount.h
default.o: ../core/loadavg.h default.o: ../core/loadavg.h
download.o: content.h ../core/item.h ../templates/templates.h
download.o: ../templates/patterncacher.h ../templates/misc.h
download.o: ../templates/localefilter.h ../core/locale.h
download.o: ../confparser/confparser.h ../templates/ckeditorgetparser.h
download.o: ../core/httpsimpleparser.h ../core/log.h ../core/thread.h
download.o: ../core/ticket.h ../core/done.h ../core/request.h
download.o: ../core/requesttypes.h ../core/session.h ../core/done.h
download.o: ../core/item.h ../core/error.h ../core/log.h ../core/user.h
download.o: ../core/rebus.h ../core/function.h ../core/thread.h
download.o: ../core/compress.h ../core/acceptencodingparser.h
download.o: ../core/acceptbaseparser.h ../core/htmlfilter.h
download.o: ../core/postmultiparser.h ../core/ticket.h ../core/data.h
download.o: ../core/dirs.h ../core/dircontainer.h ../core/users.h
download.o: ../core/ugcontainer.h ../core/groups.h ../core/group.h
download.o: ../core/functions.h ../core/lastcontainer.h ../core/mounts.h
download.o: ../core/mount.h ../core/loadavg.h
editticket.o: content.h ../core/item.h ../templates/templates.h editticket.o: content.h ../core/item.h ../templates/templates.h
editticket.o: ../templates/patterncacher.h ../templates/misc.h editticket.o: ../templates/patterncacher.h ../templates/misc.h
editticket.o: ../templates/localefilter.h ../core/locale.h editticket.o: ../templates/localefilter.h ../core/locale.h

View File

@ -1 +1 @@
o = cat.o content.o createthread.o createticket.o default.o editticket.o emacs.o last.o login.o logout.o ls.o misc_item.o misc_specialfile.o mkdir.o node.o priv.o reload.o rm.o run.o thread.o ticket.o upload.o who.o o = cat.o content.o createthread.o createticket.o default.o download.o editticket.o emacs.o last.o login.o logout.o ls.o misc_item.o misc_specialfile.o mkdir.o node.o priv.o reload.o rm.o run.o thread.o ticket.o upload.o who.o

View File

@ -10,6 +10,7 @@
#include "content.h" #include "content.h"
#include "../core/request.h" #include "../core/request.h"
#include "../core/error.h" #include "../core/error.h"
#include "../core/data.h"
@ -18,7 +19,7 @@ void Content::FunCat()
{ {
if( !request.is_item ) if( !request.is_item )
{ {
log << log1 << "Content: Cat function requires an item" << logend; log << log1 << "Content: cat function requires an item" << logend;
request.status = Error::no_item; request.status = Error::no_item;
return; return;
} }
@ -29,6 +30,8 @@ void Content::FunCat()
request.status = Error::permission_denied; request.status = Error::permission_denied;
return; return;
} }
request.send_as_attachment = request.IsParam("attachment");
} }

View File

@ -46,6 +46,9 @@ return true;
void Content::SetDefaultFunctionForFile() void Content::SetDefaultFunctionForFile()
{ {
if( request.item.static_auth != Item::static_none )
request.pfunction = data.functions.GetFunction(FUN_DOWNLOAD);
else
if( request.HasReadExecAccess(request.item) ) if( request.HasReadExecAccess(request.item) )
request.pfunction = data.functions.GetFunction(FUN_RUN); request.pfunction = data.functions.GetFunction(FUN_RUN);
else else
@ -223,6 +226,9 @@ void Content::MakeStandardFunction()
else else
if( request.pfunction->code == FUN_CHOWN ) if( request.pfunction->code == FUN_CHOWN )
FunPriv(); FunPriv();
else
if( request.pfunction->code == FUN_DOWNLOAD )
FunDownload();
else else
request.status = Error::permission_denied; request.status = Error::permission_denied;
@ -309,7 +315,13 @@ void Content::MakePage()
{ {
bool sent = false; bool sent = false;
if( request.is_item && request.item.content_type == Item::ct_raw && request.status == Error::ok && request.pfunction ) if( !request.redirect_to.empty() ||
!request.x_sendfile.empty() )
return;
if( request.is_item && request.item.static_auth == Item::static_none &&
request.item.content_type == Item::ct_raw && request.status == Error::ok && request.pfunction )
{ {
if( request.pfunction->code == FUN_CAT ) if( request.pfunction->code == FUN_CAT )
{ {

View File

@ -29,6 +29,8 @@ class Content
std::string temp; std::string temp;
void FunDownload();
void CheckSpecialFile(); void CheckSpecialFile();
void PrepareUrl(Item & item); void PrepareUrl(Item & item);
@ -53,6 +55,8 @@ class Content
void FunEmacs(); void FunEmacs();
void AddPathToStaticAuth(std::string & path);
void FunCKEditor(); void FunCKEditor();
bool FunRmCheckAccess(); bool FunRmCheckAccess();
@ -141,7 +145,7 @@ class Content
void UploadSingle(); void UploadSingle();
bool FunUploadCheckAbuse(); bool FunUploadCheckAbuse();
void PostFunUpload(); void PostFunUpload();
std::string tmp_path, tmp_path2; std::string tmp_path;
bool FunCreateTicketCheckAccess(); bool FunCreateTicketCheckAccess();
void FunCreateTicket(); void FunCreateTicket();

48
content/download.cpp Executable file
View File

@ -0,0 +1,48 @@
/*
* This file is a part of CMSLU -- Content Management System like Unix
* and is not publicly distributed
*
* Copyright (c) 2008-2009, Tomasz Sowa
* All rights reserved.
*
*/
#include "content.h"
#include "../core/request.h"
#include "../core/data.h"
void Content::FunDownload()
{
// !! moze wywalic to no_item i wszedzie w takich miejscach dac poprostu permission_denied?
if( !request.is_item )
{
log << log1 << "Content: pv function requires an item" << logend;
request.status = Error::no_item;
return;
}
if( !request.HasReadAccess(request.item) ||
request.item.static_auth == Item::static_none ||
data.static_simplefs_dir.empty() )
{
request.status = Error::permission_denied;
return;
}
request.send_as_attachment = request.IsParam("attachment");
if( !request.MakePath(request.x_sendfile) )
{
request.status = Error::permission_denied;
return;
}
}

View File

@ -27,12 +27,6 @@ bool Content::FunUploadCheckAccess()
return false; return false;
} }
// !! in the future the 'upload' can be used everywhere
if( data.mounts.pmount->type != Mount::cms )
{
request.status = Error::permission_denied;
return false;
}
return true; return true;
} }
@ -41,10 +35,7 @@ return true;
bool Content::UploadCreatePath(std::string & path) bool Content::UploadCreatePath(std::string & path)
{ {
path.clear(); if( !request.MakePath(path, true) )
request.MakePath(path);
if( !request.MakeDirsOnFS() )
{ {
request.status = Error::permission_denied; request.status = Error::permission_denied;
return false; return false;
@ -116,11 +107,6 @@ void Content::UploadMulti()
request.item.privileges = 0644; // !! tymczasowo request.item.privileges = 0644; // !! tymczasowo
SetUser(request.item); SetUser(request.item);
if( !UploadCreatePath(tmp_path) )
return;
tmp_path2 = tmp_path; // remember the path
PostFileTable::iterator i = request.post_file_table.begin(); PostFileTable::iterator i = request.post_file_table.begin();
for( ; i != request.post_file_table.end() ; ++i) for( ; i != request.post_file_table.end() ; ++i)
@ -134,14 +120,11 @@ void Content::UploadMulti()
PrepareUrl(request.item); PrepareUrl(request.item);
PostFunEmacsAdd(); // always adding a new item PostFunEmacsAdd(); // always adding a new item
if( request.session->done_status == Error::ok ) if( !UploadCreatePath(tmp_path) )
{ return;
tmp_path += '/';
tmp_path += request.item.url; // item.url could have been changed
if( request.session->done_status == Error::ok )
UploadSaveFile(i->second.tmp_filename, tmp_path); UploadSaveFile(i->second.tmp_filename, tmp_path);
tmp_path = tmp_path2; // restoring the oryginal path
}
} }
RedirectToLastDir(); RedirectToLastDir();
@ -180,16 +163,19 @@ void Content::UploadSingle()
if( !UploadCreatePath(tmp_path) ) if( !UploadCreatePath(tmp_path) )
return; return;
tmp_path += '/';
tmp_path += request.item.url; // item.url could have been changed
UploadSaveFile(tmp_filename, tmp_path); UploadSaveFile(tmp_filename, tmp_path);
} }
if( request.session->done_status == Error::ok ) if( request.session->done_status == Error::ok )
RedirectTo(request.item); {
if( !request.IsParam("ckeditor_upload") )
RedirectTo(request.item);
}
} }
// !! dodac usuwanie plikow statycznych przez rm // !! dodac usuwanie plikow statycznych przez rm
void Content::PostFunUpload() void Content::PostFunUpload()
{ {

View File

@ -109,8 +109,9 @@ void Config::AssignValues()
data.log_stdout = false; data.log_stdout = false;
data.post_file_max = Int("post_file_max", 8388608); // 8 MB data.post_file_max = Int("post_file_max", 8388608); // 8 MB
data.static_auth_dir = Text("static_auth_dir"); data.static_simplefs_dir = Text("static_simplefs_dir");
data.static_auth_dir_tmp = Text("static_auth_dir_tmp"); 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 = Text("templates_dir");
data.templates_dir_default = Text("templates_dir_default"); data.templates_dir_default = Text("templates_dir_default");

View File

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

View File

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

View File

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

View File

@ -139,6 +139,10 @@ void Functions::ReadFunctions()
f.item.url = "ckeditor"; f.item.url = "ckeditor";
table.insert( std::make_pair(f.item.url, f) ); 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 // 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 // if there is not an extension it returns a pointer to the last '\0' character
const char * GetFileExt(const char * name) 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 char * file);
bool IsFile(const std::string & 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); const char * GetFileExt(const char * name);
Item::StaticAuth SelectFileType(const char * file_name); Item::StaticAuth SelectFileType(const char * file_name);

View File

@ -16,6 +16,7 @@ Mount::Mount()
{ {
type = cms; type = cms;
dir_id = -1; dir_id = -1;
fs = simplefs;
param.resize(par_none); 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) 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_createticket_on, "createticket_on" },
{ par_only_root_remove, "only_root_remove" }, { par_only_root_remove, "only_root_remove" },
{ par_emacs_on, "emacs_on" }, { 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); size_t i, len = sizeof(par_name_tab) / sizeof(ParName);

View File

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

View File

@ -2,7 +2,7 @@
* This file is a part of CMSLU -- Content Management System like Unix * This file is a part of CMSLU -- Content Management System like Unix
* and is not publicly distributed * and is not publicly distributed
* *
* Copyright (c) 2009, Tomasz Sowa * Copyright (c) 2010, Tomasz Sowa
* All rights reserved. * 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() void MountParser::LogMountParams()
{ {
size_t i; size_t i;
@ -263,6 +287,7 @@ size_t i;
} }
void MountParser::ReadMountParams() void MountParser::ReadMountParams()
{ {
mount.ClearParams(); mount.ClearParams();
@ -300,6 +325,9 @@ void MountParser::ReadRow(std::map<long, Mount> & output)
if( err == Error::ok ) if( err == Error::ok )
ReadMountPoint(); ReadMountPoint();
if( err == Error::ok )
ReadFs();
if( err == Error::ok ) if( err == Error::ok )
ReadMountParams(); ReadMountParams();

View File

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

View File

@ -78,7 +78,8 @@ void Mounts::MountCmsForRoot()
{ {
Mount mount; Mount mount;
mount.type = Mount::cms; mount.type = Mount::cms;
mount.fs = Mount::simplefs;
Item * proot = data.dirs.GetRootDir(); Item * proot = data.dirs.GetRootDir();
if( proot ) if( proot )
@ -112,7 +113,8 @@ std::vector<Item*>::reverse_iterator i;
if( m != mount_tab.end() ) if( m != mount_tab.end() )
{ {
pmount = &(m->second); 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; return;
} }
} }
@ -120,5 +122,6 @@ std::vector<Item*>::reverse_iterator i;
// if nothing was found // if nothing was found
// we assume that 'cms' mount point is used // we assume that 'cms' mount point is used
MountCmsForRoot(); 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]; 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_filename_postfix += 1;
tmp_file.open(buf, std::ios_base::binary | std::ios_base::out); tmp_file.open(buf, std::ios_base::binary | std::ios_base::out);

View File

@ -103,7 +103,8 @@ void Request::Clear()
notify_code = 0; notify_code = 0;
browser_msie = false; browser_msie = false;
redirect_to.clear(); redirect_to.clear();
x_sendfile.clear();
send_as_attachment = false;
plugin.Call(WINIX_REQUEST_CLEAR); plugin.Call(WINIX_REQUEST_CLEAR);
} }
@ -409,6 +410,9 @@ void Request::SendSessionCookie()
void Request::SendHeaders(bool compressing, Header header) void Request::SendHeaders(bool compressing, Header header)
{ {
if( send_as_attachment )
FCGX_PutS("Content-Disposition: attachment\r\n", out);
if( !redirect_to.empty() ) if( !redirect_to.empty() )
{ {
FCGX_PutS("Status: 301 Moved Permanently\r\n", out); 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; log << log2 << "Redirect to: " << redirect_to << logend;
} }
else 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) switch(header)
{ {
@ -490,7 +501,7 @@ void Request::SendAll()
{ {
const std::string & source = page.str(); const std::string & source = page.str();
Header header = h_200; 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 && !browser_msie && !browser_konqueror &&
accept_encoding_parser.AcceptDeflate() && source.size() >= 512; accept_encoding_parser.AcceptDeflate() && source.size() >= 512;
@ -504,8 +515,8 @@ bool compressing = data.compression && role == responder &&
SendSessionCookie(); SendSessionCookie();
SendHeaders(compressing, header); SendHeaders(compressing, header);
if( !redirect_to.empty() ) if( !redirect_to.empty() || !x_sendfile.empty() )
// if there is a redirect we do not send a content // if there is a redirect or a file to send then we do not send a content
return; return;
if( header == h_200 && role == authorizer && is_item && item.static_auth != Item::static_none ) 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 ) if( item.type != Item::dir )
return false; 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 ) 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; return true;
if( !request.HasWriteAccess(item) ) 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; size_t i;
path = data.static_auth_dir;
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 // skipping the first - the first is root
for(i=1 ; i<dir_table.size() ; ++i) for(i=1 ; i<dir_table.size() ; ++i)
{ {
path += '/'; path += '/';
path += dir_table[i]->url; path += dir_table[i]->url;
if( create_dir && !CreateDir(path, 0755) )
return false;
} }
}
path += '/';
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;
}
}
}
return true; 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 // if not empty means an address for redirecting to
std::string redirect_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 // for debugging
void PrintGetTable(); void PrintGetTable();
void PrintEnv(); void PrintEnv();
@ -164,8 +170,9 @@ struct Request
bool CanUseBBCode(long user_id); bool CanUseBBCode(long user_id);
bool CanUseRaw(long user_id); bool CanUseRaw(long user_id);
void MakePath(std::string & path); bool MakePathSimpleFs(std::string & path, bool create_dir = false);
bool MakeDirsOnFS(); bool MakePathHashFs(std::string & path, long id, bool create_dir = false);
bool MakePath(std::string & path, bool create_dir = false);
private: private:

View File

@ -1,28 +1,19 @@
[is mount_page_is "subject"] [is mount_page_is "subject"][is mount_page_is "info"]<h1 class="withinfo">[else]<h1>[end][item_subject]</h1>[end]
[is mount_page_is "info"][item_info][end]
[is mount_page_is "info"]<h1 class="withinfo">[else]<h1>[end][item_subject]</h1>[end]
[is mount_page_is "info"]
[item_info]
[end]
[if-one item_static_auth_is_image] [if-one item_static_auth_is_image]
<img src="[item_link_static_auth]" alt="[item_subject]"> <img class="catimage" src="[item_link]/download/thumb" alt="[item_subject]">
[item_print_content] [item_print_content]
[else] [else]
[if-one item_static_auth_is_other] [if-no item_static_auth_is_none]
{download}: <a href="[item_link_static_auth]" title="[item_subject]">[item_subject]</a> {download}: <a href="[item_link]/download" title="[item_subject]">[item_subject]</a>
[item_print_content] [item_print_content]
[else] [else]
[if-one item_static_auth_is_none] [item_print_content]
[item_print_content]
[end]
[end] [end]
[end] [end]
[include "item_options.html"] [include "item_options.html"]

View File

@ -34,9 +34,9 @@
<input type="hidden" name="contenttype" value="2"> <input type="hidden" name="contenttype" value="2">
[is winix_function_param_is "full"] [is winix_function_param_is "full"]
<script type="text/javascript">CKEDITOR.replace('itemcontent', \{filebrowserUploadUrl: '[doc_base_url][dir]upload/', filebrowserBrowseUrl: '[doc_base_url][dir]ls/ckeditor_browse/fullscreen/', customConfig : '[doc_base_url_static_ext]/ckeditor_full.js' \});</script> <script type="text/javascript">CKEDITOR.replace('itemcontent', \{filebrowserUploadUrl: '[doc_base_url][dir]upload/ckeditor_upload/', filebrowserBrowseUrl: '[doc_base_url][dir]ls/ckeditor_browse/fullscreen/', customConfig : '[doc_base_url_static_ext]/ckeditor_full.js' \});</script>
[else] [else]
<script type="text/javascript">CKEDITOR.replace('itemcontent', \{filebrowserUploadUrl: '[doc_base_url][dir]upload/', filebrowserBrowseUrl: '[doc_base_url][dir]ls/ckeditor_browse/fullscreen/', customConfig : '[doc_base_url_static_ext]/ckeditor_winix.js' \});</script> <script type="text/javascript">CKEDITOR.replace('itemcontent', \{filebrowserUploadUrl: '[doc_base_url][dir]upload/ckeditor_upload/', filebrowserBrowseUrl: '[doc_base_url][dir]ls/ckeditor_browse/fullscreen/', customConfig : '[doc_base_url_static_ext]/ckeditor_winix.js' \});</script>
[end] [end]
[if-no user_logged] [if-no user_logged]

View File

@ -1,44 +1,49 @@
<h1>{upload_header}</h1> [is winix_function_param_is "ckeditor_upload"]
<script type="text/javascript">window.parent.CKEDITOR.tools.callFunction([upload_ckeditor_funnum], '[item_link]');</script>
[else]
[include "err_abuse.html"] <h1>{upload_header}</h1>
<form id="additem" method="post" action="[doc_base_url][dir][if-one item_is][item_url]/[end]upload" enctype="multipart/form-data"> [include "err_abuse.html"]
<fieldset>
<legend>{upload_form_legend}</legend> <form id="additem" method="post" action="[doc_base_url][dir][if-one item_is][item_url]/[end]upload" enctype="multipart/form-data">
<fieldset>
[is winix_function_param_is "multi"] <legend>{upload_form_legend}</legend>
<p class="withnext">{upload_form_file_multi}</p> [is winix_function_param_is "multi"]
<input size="68" class="edit" type="file" name="fileupload1">
<input size="68" class="edit" type="file" name="fileupload2"> <p class="withnext">{upload_form_file_multi}</p>
<input size="68" class="edit" type="file" name="fileupload3"> <input size="68" class="edit" type="file" name="fileupload1">
<input size="68" class="edit" type="file" name="fileupload4"> <input size="68" class="edit" type="file" name="fileupload2">
<input size="68" class="edit" type="file" name="fileupload5"> <input size="68" class="edit" type="file" name="fileupload3">
<input size="68" class="edit" type="file" name="fileupload4">
[else] <input size="68" class="edit" type="file" name="fileupload5">
<p class="withnext">{upload_form_file}</p> [else]
<input size="68" class="edit" type="file" name="fileupload">
<p class="withnext">{upload_form_file}</p>
<p class="withnext">{title}:</p> <input size="68" class="edit" type="file" name="fileupload">
<input class="edit" type="text" name="subject" value="[item_subject]">
<p class="withnext">{title}:</p>
<p class="withnext">{suggested_url}:</p> <input class="edit" type="text" name="subject" value="[item_subject]">
<input class="edit" type="text" name="url" value="[item_url]">
<p class="withnext">{suggested_url}:</p>
[include "fun_emacs_post.html"] <input class="edit" type="text" name="url" value="[item_url]">
[end] [include "fun_emacs_post.html"]
[if-no user_logged] [end]
<p class="withnext">{nick}:</p>
<input class="edit" type="text" name="guestname" value="[item_guest_name]"> [if-no user_logged]
<p class="withnext">{nick}:</p>
<p class="withnext">{rebus_how_is_it} [rebus_question]?</p> <input class="edit" type="text" name="guestname" value="[item_guest_name]">
<input class="edit" type="text" name="rebus">
[end] <p class="withnext">{rebus_how_is_it} [rebus_question]?</p>
<input class="edit" type="text" name="rebus">
<input class="submit" type="submit" value="{upload_submit}"> [end]
</fieldset>
</form> <input class="submit" type="submit" value="{upload_submit}">
</fieldset>
</form>
[end]

View File

@ -652,3 +652,7 @@ strong {
font-weight: bold; font-weight: bold;
} }
img.catimage {
max-width: 600px;
}

View File

@ -168,6 +168,15 @@ ticket.o: ../core/done.h ../core/thread.h ../core/compress.h
ticket.o: ../core/acceptencodingparser.h ../core/acceptbaseparser.h ticket.o: ../core/acceptencodingparser.h ../core/acceptbaseparser.h
ticket.o: ../core/htmlfilter.h ../core/postmultiparser.h ../core/ticket.h ticket.o: ../core/htmlfilter.h ../core/postmultiparser.h ../core/ticket.h
ticket.o: ../core/misc.h ticket.o: ../core/misc.h
upload.o: templates.h patterncacher.h ../core/item.h misc.h localefilter.h
upload.o: ../core/locale.h ../confparser/confparser.h ckeditorgetparser.h
upload.o: ../core/httpsimpleparser.h ../core/log.h ../core/request.h
upload.o: ../core/requesttypes.h ../core/session.h ../core/done.h
upload.o: ../core/item.h ../core/error.h ../core/log.h ../core/user.h
upload.o: ../core/rebus.h ../core/function.h ../core/thread.h
upload.o: ../core/compress.h ../core/acceptencodingparser.h
upload.o: ../core/acceptbaseparser.h ../core/htmlfilter.h
upload.o: ../core/postmultiparser.h ../core/ticket.h
uptime.o: templates.h patterncacher.h ../core/item.h misc.h localefilter.h uptime.o: templates.h patterncacher.h ../core/item.h misc.h localefilter.h
uptime.o: ../core/locale.h ../confparser/confparser.h ckeditorgetparser.h uptime.o: ../core/locale.h ../confparser/confparser.h ckeditorgetparser.h
uptime.o: ../core/httpsimpleparser.h ../core/log.h ../core/data.h uptime.o: ../core/httpsimpleparser.h ../core/log.h ../core/data.h

View File

@ -1 +1 @@
o = dir.o doc.o done.o item.o last.o localefilter.o ls.o misc.o mount.o patterncacher.o priv.o rebus.o sys.o templates.o thread.o ticket.o uptime.o user.o who.o winix.o o = dir.o doc.o done.o item.o last.o localefilter.o ls.o misc.o mount.o patterncacher.o priv.o rebus.o sys.o templates.o thread.o ticket.o upload.o uptime.o user.o who.o winix.o

View File

@ -166,12 +166,6 @@ void item_link(Info & i)
} }
void item_link_static_auth(Info & i)
{
HtmlEscape(i.out, data.base_url_static_auth);
item_dir(i);
item_url(i);
}
void item_static_auth_is_none(Info & i) void item_static_auth_is_none(Info & i)
@ -186,12 +180,6 @@ void item_static_auth_is_image(Info & i)
} }
void item_static_auth_is_other(Info & i)
{
i.result = request.item.static_auth == Item::static_other;
}
void item_can_read(Info & i) void item_can_read(Info & i)
{ {
i.result = request.HasReadAccess(request.item); i.result = request.HasReadAccess(request.item);

View File

@ -17,7 +17,7 @@ namespace TemplatesFunctions
{ {
static size_t ls_ckeditor_reqid = 0; static size_t ls_ckeditor_reqid = 0;
static int ls_ckeditor_funnum = 0;
@ -33,9 +33,11 @@ void ls_ckeditor_funnum_browse(Info & i)
const char * str = request.param_table[request.param_table.size()-1]->c_str() + 1; // the first char is '?' const char * str = request.param_table[request.param_table.size()-1]->c_str() + 1; // the first char is '?'
ckeditor_getparser.Parse(str); ckeditor_getparser.Parse(str);
} }
ls_ckeditor_funnum = ckeditor_getparser.fun_num;
} }
i.out << ckeditor_getparser.fun_num; i.out << ls_ckeditor_funnum;
} }

View File

@ -198,10 +198,8 @@ void Templates::CreateFunctions()
functions.Insert("item_url", item_url); functions.Insert("item_url", item_url);
functions.Insert("item_url_is", item_url_is); functions.Insert("item_url_is", item_url_is);
functions.Insert("item_link", item_link); functions.Insert("item_link", item_link);
functions.Insert("item_link_static_auth", item_link_static_auth);
functions.Insert("item_static_auth_is_none", item_static_auth_is_none); functions.Insert("item_static_auth_is_none", item_static_auth_is_none);
functions.Insert("item_static_auth_is_image", item_static_auth_is_image); functions.Insert("item_static_auth_is_image", item_static_auth_is_image);
functions.Insert("item_static_auth_is_other", item_static_auth_is_other);
functions.Insert("item_can_read", item_can_read); functions.Insert("item_can_read", item_can_read);
functions.Insert("item_can_write", item_can_write); functions.Insert("item_can_write", item_can_write);
@ -449,6 +447,12 @@ void Templates::CreateFunctions()
functions.Insert("rebus_question", rebus_question); functions.Insert("rebus_question", rebus_question);
/*
upload
*/
functions.Insert("upload_ckeditor_funnum", upload_ckeditor_funnum);
/* /*
uptime uptime
*/ */

View File

@ -112,10 +112,8 @@ namespace TemplatesFunctions
void item_url(Info & i); void item_url(Info & i);
void item_url_is(Info & i); void item_url_is(Info & i);
void item_link(Info & i); void item_link(Info & i);
void item_link_static_auth(Info & i);
void item_static_auth_is_none(Info & i); void item_static_auth_is_none(Info & i);
void item_static_auth_is_image(Info & i); void item_static_auth_is_image(Info & i);
void item_static_auth_is_other(Info & i);
void item_can_read(Info & i); void item_can_read(Info & i);
void item_can_write(Info & i); void item_can_write(Info & i);
void item_can_remove(Info & i); void item_can_remove(Info & i);
@ -356,6 +354,12 @@ namespace TemplatesFunctions
void rebus_question(Info & i); void rebus_question(Info & i);
/*
upload
*/
void upload_ckeditor_funnum(Info & i);
/* /*
uptime uptime
*/ */

42
templates/upload.cpp Executable file
View File

@ -0,0 +1,42 @@
/*
* This file is a part of CMSLU -- Content Management System like Unix
* and is not publicly distributed
*
* Copyright (c) 2008-2010, Tomasz Sowa
* All rights reserved.
*
*/
#include <ctime>
#include "templates.h"
#include "../core/request.h"
namespace TemplatesFunctions
{
static size_t upload_ckeditor_reqid = 0;
static int upload_fun_num = 0;
void upload_ckeditor_funnum(Info & i)
{
if( upload_ckeditor_reqid != request.id )
{
upload_ckeditor_reqid = request.id;
ckeditor_getparser.fun_num = 2; // default if there is a problem with parsing info
if( !request.param_table.empty() )
{
const char * str = request.param_table[request.param_table.size()-1]->c_str() + 1; // the first char is '?'
ckeditor_getparser.Parse(str);
}
upload_fun_num = ckeditor_getparser.fun_num;
}
i.out << upload_fun_num;
}
} // namespace