/* * This file is a part of Winix * and is distributed under the 2-Clause BSD licence. * Author: Tomasz Sowa */ /* * Copyright (c) 2010-2021, Tomasz Sowa * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * */ #include #include #include "ticketinfo.h" #include "core/error.h" #include "core/log.h" #include "core/misc.h" #include "pluginmsg.h" #include "sessiondata.h" #include "convert/text.h" namespace Winix { 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; pt::Space & space = conf_tab[mount_dir_id].conf; return (conf_parser.parse_space(config_file.item_content.content_raw, space) == 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) { std::wstring * type = space.get_wstr(L"type"); if( !type ) return; if( *type == L"integer" ) { std::wstring * min_str = space.get_wstr(L"min"); std::wstring * max_str = space.get_wstr(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( *type == L"progress" ) { // !! dodac tez min/max if( par.intv < 0 ) par.intv = 0; if( par.intv > 100 ) par.intv = 100; } else if( *type == L"select" ) { pt::Space::TableType * child_table = space.get_table(L"options"); // CHECKME it was space.find_child_space_table(); if( child_table ) { for(pt::Space * sp : *child_table) { if( sp->to_long(L"id") == par.intv ) { return; } } } par.intv = 0; std::wstring * def = space.get_wstr(L"default"); if( def ) par.intv = Tol(*def); } } pt::Space & TicketInfo::FindAddMetaByParam(pt::Space & meta, long param) { pt::Space * params = meta.get_space(L"params"); // CHECKME it was meta.find_child_space_table(); if( params && params->is_table() ) { for(pt::Space * sp : *params->get_table() ) { if( sp->to_long(L"id") == param ) { return *sp; } } } else if( !params ) { params = &meta.add_empty_space(L"params"); } pt::Space & sp = params->add_empty_space(); sp.add(L"id", param); return sp; } bool TicketInfo::ReadTicketValue(pt::Space & config_param, long param_id, Ticket::TicketParam & par, const std::wstring & value, pt::Space & meta) { if( config_param.is_equal(L"type", L"integer") || config_param.is_equal(L"type", L"progress") || config_param.is_equal(L"type", L"select") ) { par.intv = Tol(value); par.decv.clear(); CheckMinMaxValue(config_param, par); return true; } else if( config_param.is_equal(L"type", L"string") || config_param.is_equal(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( config_param.is_equal(L"type", L"images") || config_param.is_equal(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 & config_param, 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.item_content.privileges = system->NewFilePrivileges(); file.item_content.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 & meta_param = FindAddMetaByParam(meta, param_id); pt::Space & meta_files = meta_param.get_add_space(L"files"); pt::Space & file_space = meta_files.add_empty_space(); if( file.item_content.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) { std::wstring * type = space.get_wstr(L"type"); if( type && (*type == L"images" || *type == L"files") ) { std::wstring * upload_path = space.get_wstr(L"upload_dir"); if( upload_path && !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 & config_param, Ticket & ticket, long param_id, const std::wstring & value, pt::Space & meta) { ticket_param.param = param_id; for(size_t i2=0 ; i2get_table(L"params"); if( params ) { for(pt::Space * space : *params) { if( space->to_long(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) { pt::Space::TableType * child_table = cur_conf->get_table(L"params"); // CHECKME it was cur_conf->find_child_space_table(); if( child_table ) { for(pt::Space * sp : *child_table) { if( sp->to_long(L"id") == param_id ) { ReadTicketValue(*sp, 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) { pt::Space::TableType * params = meta.get_table(L"params"); if( params ) { for(pt::Space * param : *params) { pt::Space * files_space = param->get_space(L"files"); if( files_space && files_space->is_table() ) { pt::Space::TableType * files = files_space->get_table(); for(size_t f=0 ; f < files->size() ; ++f) { pt::Space * file = (*files)[f]; if( file->to_long(L"itemid") == file_id ) { files_space->remove(f); // !! 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( pt::is_substr(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( pt::is_substr(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( pt::is_substr(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.item_content.meta.get_add_space(L"ticket"); ticket_meta = ticket_space; } 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 } // namespace Winix