winix/plugins/ticket/ticketinfo.cpp

604 lines
13 KiB
C++
Executable File

/*
* This file is a part of Winix
* and is not publicly distributed
*
* Copyright (c) 2010-2013, Tomasz Sowa
* All rights reserved.
*
*/
#include <algorithm>
#include <ctime>
#include "ticketinfo.h"
#include "core/error.h"
#include "core/log.h"
#include "core/misc.h"
#include "core/plugin.h"
#include "pluginmsg.h"
#include "sessiondata.h"
namespace Ticket
{
TicketInfo::TicketInfo()
{
Clear();
}
void TicketInfo::SetTDb(TDb * ptdb)
{
tdb = ptdb;
}
void TicketInfo::SetDb(Db * pdb)
{
db = pdb;
}
void TicketInfo::SetConfig(Config * pconfig)
{
config = pconfig;
}
void TicketInfo::SetSystem(System * psystem)
{
system = psystem;
}
void TicketInfo::SetCur(Cur * pcur)
{
cur = pcur;
}
void TicketInfo::SetFunctions(Functions * pfunctions)
{
functions = pfunctions;
}
void TicketInfo::Clear()
{
ticket = &ticket_empty;
item = &item_empty;
ticket->Clear();
item->Clear();
// we use meta from item which should not be const
cur_conf_wrap = &cur_conf_wrap_empty;
cur_conf = &cur_conf_empty;
cur_conf->Clear();
item_tab.clear();
ticket_tab.clear();
item_sort_tab.clear();
create_new_ticket = false;
}
void TicketInfo::MarkAllConfToDelete()
{
ConfTab::iterator i = conf_tab.begin();
for( ; i!=conf_tab.end() ; ++i)
i->second.to_delete = true;
}
void TicketInfo::DeleteAllMarkedConf()
{
ConfTab::iterator inext;
ConfTab::iterator i = conf_tab.begin();
while( i != conf_tab.end() )
{
inext = i;
++inext;
if( i->second.to_delete )
{
log << log3 << "Ticket: deleting ticket conf for dir id: " << i->first << logend;
conf_tab.erase(i);
}
i = inext;
}
}
bool TicketInfo::GetConfContent(const std::wstring & path)
{
int status = system->FollowAllLinks(path, config_dir_tab, config_file, false, false, false);
if( status != 1 )
{
log << log1 << "Ticket: problem with reading a config file: " << path << ", status: " << status << logend;
return false;
}
return true;
}
bool TicketInfo::ParseTicketConf(long mount_dir_id, const std::wstring & path)
{
log << log3 << "Ticket: parsing conf file: " << path << logend;
conf_tab[mount_dir_id].file_name = path;
conf_parser.UTF8(true);
conf_parser.SetSpace(conf_tab[mount_dir_id].conf);
conf_parser.SplitSingle(true);
conf_tab[mount_dir_id].conf.Clear();
return (conf_parser.ParseString(config_file.content) == PT::SpaceParser::ok);
}
void TicketInfo::ReadTicketConf(const Mount & mount, bool skip_existing_configs)
{
if( mount.param[mount_par_ticket_conf].defined &&
mount.param[mount_par_ticket_conf].arg.size() == 1 )
{
const std::wstring & file_name = mount.param[mount_par_ticket_conf].arg[0];
ConfTab::iterator c = conf_tab.find(mount.dir_id);
bool exists = (c != conf_tab.end() && c->second.file_name == file_name);
if( exists )
c->second.to_delete = false;
if( !(skip_existing_configs && exists) )
{
if( GetConfContent(file_name) )
{
if( !ParseTicketConf(mount.dir_id, file_name) )
conf_tab[mount.dir_id].to_delete = true;
}
else
{
if( exists )
c->second.to_delete = true;
}
}
}
}
// if skip_existing_configs is true then only new config files will be parsed
void TicketInfo::ReadTicketConf(Mounts & mounts, bool skip_existing_configs)
{
Mounts::MountTab::const_iterator i;
const Mounts::MountTab * mtab = mounts.GetMountTab();
// loop through all mount points
for(i=mtab->begin() ; i!=mtab->end() ; ++i)
{
const Mount & mount = i->second;
ReadTicketConf(mount, skip_existing_configs);
}
}
// if skip_existing_configs is true then only new config files will be parsed
void TicketInfo::ReadTicketConf(bool skip_existing_configs)
{
MarkAllConfToDelete();
ReadTicketConf(system->mounts, skip_existing_configs);
DeleteAllMarkedConf();
}
void TicketInfo::FindCurrentConf(long dir_id)
{
Mount * mount = system->mounts.CalcMount(dir_id);
if( mount )
{
// long dir_id = cur->mount->dir_id;
ConfTab::iterator i = conf_tab.find(mount->dir_id);
if( i != conf_tab.end() )
{
cur_conf_wrap = &i->second;
cur_conf = &i->second.conf;
}
else
{
log << log1 << "Ticket: there is no a ticket_conf parameter in the mount point (an empty config used)" << logend;
}
}
else
{
log << log1 << "Ticket: I cannot find the mount point for dir id: " << dir_id << logend;
}
}
void TicketInfo::FindCurrentConf()
{
if( !cur->request->dir_tab.empty() )
FindCurrentConf(cur->request->dir_tab.back()->id);
}
void TicketInfo::CheckMinMaxValue(PT::Space & space, Ticket::TicketParam & par)
{
if( space.Text(L"type") == L"integer" )
{
std::wstring * min_str = space.GetValue(L"min");
std::wstring * max_str = space.GetValue(L"min");
if( min_str )
{
long minv = Tol(*min_str);
if( par.intv < minv )
par.intv = minv;
}
if( max_str )
{
long maxv = Tol(*max_str);
if( par.intv > maxv )
par.intv = maxv;
}
}
else
if( space.Text(L"type") == L"progress" )
{
// !! dodac tez min/max
if( par.intv < 0 )
par.intv = 0;
if( par.intv > 100 )
par.intv = 100;
}
else
if( space.Text(L"type") == L"select" )
{
for(size_t a=0 ; a<space.spaces.size() ; ++a)
{
PT::Space & sp = *space.spaces[a];
if( sp.name == L"option" && sp.Long(L"id") == par.intv )
return;
}
par.intv = Tol(space.Text(L"default"));
}
}
PT::Space & TicketInfo::FindAddMetaByParam(PT::Space & meta, long param)
{
for(size_t i=0 ; i<meta.spaces.size() ; ++i)
{
PT::Space & sp = *meta.spaces[i];
if( sp.name == L"param" && sp.Long(L"id") == param )
return sp;
}
PT::Space & sp = meta.AddSpace(L"param");
sp.Add(L"id", param);
return sp;
}
bool TicketInfo::ReadTicketValue(PT::Space & space, long param_id, Ticket::TicketParam & par, const std::wstring & value, PT::Space & meta)
{
if( space.Text(L"type") == L"integer" ||
space.Text(L"type") == L"progress" ||
space.Text(L"type") == L"select" )
{
par.intv = Tol(value);
par.decv.clear();
CheckMinMaxValue(space, par);
return true;
}
else
if( space.Text(L"type") == L"string" ||
space.Text(L"type") == L"multistring" )
{
// !! dodac cos co sprawdzi czy string nie zawiera znakow konca linii
PT::Space & sp = FindAddMetaByParam(meta, param_id);
sp.Add(L"value", value);
return false;
}
if( space.Text(L"type") == L"images" ||
space.Text(L"type") == L"files" )
{
if( !value.empty() )
{
log << log1 << "Ticket: images or files should be added only by a specific html tag (ignored)" << logend;
}
else
{
// an empty field from the html form (ignoring)
}
return false;
}
else
{
// !! dodac obsluge komunikatow
// niech zostanie wyslany komunikat o dodawaniu nieznanego parametru
// i jesli nic nie odpowie na ten komunikat to wtedy zglaszamy blad
log << log1 << "Ticket: incorrect parameter, param: " << par.param << ", value: " << value << " (ignored)" << logend;
}
return false;
}
void TicketInfo::ReadTicketValue(PT::Space & space,
long param_id,
const PostFile & value,
PT::Space & meta,
Item & upload_dir)
{
file.Clear(); // clearing and setting date
file.parent_id = upload_dir.id;
file.type = Item::file;
file.privileges = system->NewFilePrivileges();
file.file_type = SelectFileType(value.filename);
file.url = value.filename;
functions->PrepareUrl(file);
functions->SetUser(file);
functions->fun_upload.UploadFile(file, value.tmp_filename);
if( cur->request->status == WINIX_ERR_OK )
{
PT::Space & space = FindAddMetaByParam(meta, param_id);
PT::Space & file_space = space.AddSpace(L"file");
if( file.file_type == WINIX_ITEM_FILETYPE_IMAGE )
file_space.Add(L"type", L"image");
else
file_space.Add(L"type", L"file");
file_space.Add(L"itemid", file.id);
system->MakePath(file, file_path);
file_space.Add(L"path", file_path);
}
else
{
log << log1 << "Ticket: problem with uploading" << logend;
}
}
void TicketInfo::ReadTicketValue(PT::Space & space,
long param_id, const PostFile & value, PT::Space & meta)
{
if( space.Text(L"type") == L"images" || space.Text(L"type") == L"files" )
{
std::wstring & upload_path = space.Text(L"upload_dir");
if( !upload_path.empty() )
{
Item * upload_dir = system->dirs.GetDir(upload_path);
if( upload_dir )
ReadTicketValue(space, param_id, value, meta, *upload_dir);
else
log << log1 << "Ticket: there is no an upload directory: " << upload_path << logend;
}
else
{
log << log1 << "Ticket: you must set 'upload_dir' directory in the config" << logend;
}
}
}
// adding a new parameter only if it not exists in ticket.par_tab
void TicketInfo::ReadTicketParam(PT::Space & space, Ticket & ticket, long param_id, const std::wstring & value, PT::Space & meta)
{
ticket_param.param = param_id;
for(size_t i2=0 ; i2<ticket.par_tab.size() ; ++i2)
{
if( ticket.par_tab[i2].param == param_id )
{
// parameter param_id already exists in ticket.par_tab
// (overwritting)
if( ReadTicketValue(space, param_id, ticket_param, value, meta) )
ticket.par_tab[i2] = ticket_param;
return;
}
}
// adding a new parameter param_id
if( ReadTicketValue(space, param_id, ticket_param, value, meta) )
ticket.par_tab.push_back(ticket_param);
}
void TicketInfo::ReadTicketParam(Ticket & ticket, long param_id, const std::wstring & value, PT::Space & meta)
{
ticket_param.Clear();
for(size_t i=0 ; i<cur_conf->spaces.size() ; ++i)
{
PT::Space & space = *cur_conf->spaces[i];
if( space.name == L"param" && Tol(space.Text(L"id")) == param_id )
{
ReadTicketParam(space, ticket, param_id, value, meta);
return;
}
}
log << log1 << "Ticket: skipped incorrect parameter: " << param_id << " (not defined in the config)" << logend;
}
// always adds a new parameter
void TicketInfo::ReadTicketParam(long param_id, const PostFile & value, PT::Space & meta)
{
for(size_t i=0 ; i<cur_conf->spaces.size() ; ++i)
{
PT::Space & space = *cur_conf->spaces[i];
if( space.name == L"param" && space.Long(L"id") == param_id )
{
ReadTicketValue(space, param_id, value, meta);
return;
}
}
log << log1 << "Ticket: skipped incorrect parameter: " << param_id << " (not defined in the config)" << logend;
}
bool TicketInfo::DeleteTicketFile(Ticket & ticket, long file_id, PT::Space & meta)
{
for(size_t i=0 ; i<meta.spaces.size() ; ++i)
{
PT::Space & param = *meta.spaces[i];
if( param.name == L"param" )
{
for(size_t z=0 ; z<param.spaces.size() ; ++z)
{
PT::Space & file = *param.spaces[z];
if( file.name == L"file" )
{
if( file.Long(L"itemid") == file_id )
{
param.RemoveSpace(z);
// !! IMPROVE ME
// temporarily we delete the file here
// but it should be really deleted when the user will press
// the submit button
//functions->fun_rm.RemoveFileOrSymlink(file_id, true);
return true;
}
}
}
}
}
return false;
}
void TicketInfo::ReadTicketParams(Ticket & ticket, bool clear_ticket, PT::Space & meta, bool & file_was_deleted)
{
PostTab::iterator i;
PostFileTab::iterator i2;
file_was_deleted = false;
if( clear_ticket )
ticket.Clear();
// !! IMPROVE ME move me somewhere
std::wstring ticket_delete_prefix = L"ticketdeletefile_";
for(i=cur->request->post_tab.begin() ; i!=cur->request->post_tab.end() ; ++i)
{
// !! CHECKME why ticket_form_prefix is in the global config?
// (this is a plugin variable)
if( IsSubString(config->ticket_form_prefix, i->first) )
{
long param_id = Tol(i->first.c_str() + config->ticket_form_prefix.size());
ReadTicketParam(ticket, param_id, i->second, meta);
}
if( IsSubString(ticket_delete_prefix, i->first) )
{
long file_id = Tol(i->first.c_str() + ticket_delete_prefix.size());
if( DeleteTicketFile(ticket, file_id, meta) )
{
file_was_deleted = true;
}
}
}
for(i2=cur->request->post_file_tab.begin() ; i2!=cur->request->post_file_tab.end() ; ++i2)
{
if( IsSubString(config->ticket_form_prefix, i2->first) )
ReadTicketParam(Tol(i2->first.c_str() + config->ticket_form_prefix.size()), i2->second, meta);
}
ticket.SortParTab();
}
void TicketInfo::RemoveTicket(long file_id)
{
/*
* IMPROVEME
* we should also remove some files (images) for a ticket
* may when 'rm' function is displayed we should show some checkboxes
* 'remove static files etc.' and if they are checked then the files are removed?
*
*/
if( tdb->GetTicket(file_id, rm_ticket) == WINIX_ERR_OK )
{
tdb->RemoveTicket(file_id);
}
}
void TicketInfo::CopyTicketSpace(PT::Space & ticket_space, Item & item)
{
PT::Space & ticket_meta = item.meta.FindAddSpace(L"ticket");
ticket_meta = ticket_space;
ticket_meta.name = L"ticket";
}
void TicketInfo::MakeRedirectIfPossible(const Item & item)
{
PluginRes res = plugin.Call(WINIX_PL_TICKET_CAN_MAKE_REDIRECT);
if( res.res_false > 0 )
{
log << log4 << "Ticket: redirect prevented" << logend;
return;
}
system->RedirectTo(item);
}
} // namespace