Compare commits
144 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 0045c6c72c | |||
| 4809016b78 | |||
| 6e2ba65524 | |||
| 8033ac66c4 | |||
| 9ef3736989 | |||
| 099dd55d0c | |||
| 53b4175d00 | |||
| 8aa6f08e08 | |||
| c5024598cb | |||
| dfcf6b29c0 | |||
| 7f48d1eb2e | |||
| eaa97995d2 | |||
| 14f997b844 | |||
| 26e87b20b1 | |||
| 5cdf6eff36 | |||
| 4ed535a3b7 | |||
| da15323c2f | |||
| bd1f717b4c | |||
| 72013046fc | |||
| 14ae19143f | |||
| d8260d8383 | |||
| 9174555ff8 | |||
| 0c6ddc2218 | |||
| 43b4075b16 | |||
| 8f8e44fee5 | |||
| 260c12894d | |||
| adf273479a | |||
| 54480da405 | |||
| 90261b2005 | |||
| cc71c225a3 | |||
| e739f30088 | |||
| 51d95b49a0 | |||
| b5c155b927 | |||
| 5a5fe1b0cc | |||
| 1c4e010fc1 | |||
| d8d523d983 | |||
| 1c2589a2f2 | |||
| 1ec61ffa11 | |||
| ca0a5c9cbe | |||
| 8dd31e737f | |||
| e98cca7fbc | |||
| 9830b0a50f | |||
| f76a0ca3e9 | |||
| 5a6d1991ac | |||
| 329e2d8001 | |||
| 403cca5aad | |||
| b8ff5d4cfc | |||
| 54e6c07efc | |||
| d11cda3577 | |||
| abafb80caf | |||
| e0dd85ca99 | |||
| 2c38fe180e | |||
| 0d0f12b394 | |||
| 86d6c96aeb | |||
| b605fb0a77 | |||
| ec773e5f29 | |||
| 9d5d088b4a | |||
| 1b858f5782 | |||
| 5b845f1d03 | |||
| db9d381a43 | |||
| 0df088e1e2 | |||
| 67099d5d06 | |||
| 07e8e0c63c | |||
| ecc89d8596 | |||
| c94b0311b6 | |||
| fc33b4f882 | |||
| 1da1eef768 | |||
| baf10a9ba9 | |||
| bcea4f9464 | |||
| 920290e9dc | |||
| 1d83cf42a1 | |||
| 09bfdf9e77 | |||
| e83fd91423 | |||
| 70421b7bd1 | |||
| 71ae70f670 | |||
| b1b3cea64e | |||
| 2712c57f15 | |||
| 0b528c7225 | |||
| b7007da5a9 | |||
| 489310ba1c | |||
| 6c2c12fe5e | |||
| e61f0db57e | |||
| 3e3546a2fd | |||
| d2fa3b7171 | |||
| 0e9f587591 | |||
| 9208b15167 | |||
| a45fb30e0a | |||
| 97c7edafd6 | |||
| 1a51b1adc7 | |||
| 9d2be5c50d | |||
| f381f24402 | |||
| f6db85fcdb | |||
| 9687d5cd66 | |||
| 6e2d00bc5b | |||
| 5aaab89cd8 | |||
| 7407d24586 | |||
| c9931da5ba | |||
| 4311f06ade | |||
| 8b64b5d372 | |||
| 631ca4f8a3 | |||
| 424618de38 | |||
| b2d3ca9543 | |||
| cb33f20a24 | |||
| 973d804db2 | |||
| 84eaa6b7b6 | |||
| f967a428ce | |||
| 543d464cbc | |||
| 43470b2a41 | |||
| fa05e25a9d | |||
| fe2f1605f1 | |||
| 48b5c167bf | |||
| 08a0a36dfd | |||
| d135c31ca0 | |||
| dce68221ad | |||
| 93273bd470 | |||
| 92f7c11999 | |||
| 024ce8e73c | |||
| 7902389ef1 | |||
| 1e9ab2f805 | |||
| 0550212b64 | |||
| c7b6ca67a2 | |||
| 9dae2de2fa | |||
| 968593106e | |||
| 302cb0130d | |||
| 89efaa790f | |||
| 60f0e62c23 | |||
| f113e2ef31 | |||
| 39923d6617 | |||
| 72be443414 | |||
| 392e8060ba | |||
| 8c01b0f6c0 | |||
| b984475e49 | |||
| 4f114ea33c | |||
| 5b8a9c0108 | |||
| ee6500ac65 | |||
| 3b2a1c3f25 | |||
| 4d87359aca | |||
| c37c1ff812 | |||
| 1812a2e9ad | |||
| ccc02f41bf | |||
| eaf10c70b7 | |||
| 06f42dd9cb | |||
| 1d6ff73aad | |||
| 700a6fe643 |
48
Makefile
48
Makefile
@@ -6,11 +6,17 @@ CXX = g++
|
||||
endif
|
||||
|
||||
ifndef CXXFLAGS
|
||||
CXXFLAGS = -fPIC -Wall -pedantic -O2 -I/usr/local/include -I/home/tomek/roboczy/winix -I/home/tomek/roboczy/ezc/src -L/usr/local/lib -DEZC_USE_WINIX_LOGGER -DEZC_HAS_SPECIAL_STREAM
|
||||
CXXFLAGS = -fPIC -Wall -O2 -pthread -I/usr/local/include -I/home/tomek/roboczy/winix -I/home/tomek/roboczy/ezc/src -I/home/tomek/roboczy/tito/src -I/home/tomek/roboczy/pikotools -DEZC_USE_WINIX_LOGGER -DEZC_HAS_SPECIAL_STREAM
|
||||
endif
|
||||
|
||||
ifndef LDFLAGS
|
||||
LDFLAGS = -L/usr/local/lib
|
||||
endif
|
||||
|
||||
|
||||
export CXX
|
||||
export CXXFLAGS
|
||||
export LDFLAGS
|
||||
|
||||
|
||||
all: winix.so plugins winix
|
||||
@@ -18,19 +24,21 @@ all: winix.so plugins winix
|
||||
|
||||
|
||||
winix.so: FORCE
|
||||
@cd core ; $(MAKE) -e
|
||||
@cd db ; $(MAKE) -e
|
||||
@cd functions ; $(MAKE) -e
|
||||
@cd notify ; $(MAKE) -e
|
||||
@cd templates ; $(MAKE) -e
|
||||
@cd ../ezc/src ; $(MAKE) -e
|
||||
$(CXX) -shared -o winix.so $(CXXFLAGS) core/*.o db/*.o functions/*.o templates/*.o notify/*.o ../ezc/src/ezc.a -lfcgi -lpq -lz -lpthread -lfetch
|
||||
@cd core ; $(MAKE) -e
|
||||
@cd db ; $(MAKE) -e
|
||||
@cd functions ; $(MAKE) -e
|
||||
@cd notify ; $(MAKE) -e
|
||||
@cd templates ; $(MAKE) -e
|
||||
@cd ../ezc/src ; $(MAKE) -e
|
||||
@cd ../tito/src ; $(MAKE) -e
|
||||
@cd ../pikotools ; $(MAKE) -e
|
||||
$(CXX) -shared -rdynamic -Wl,-whole-archive -o winix.so $(CXXFLAGS) core/*.o db/*.o functions/*.o templates/*.o notify/*.o ../ezc/src/ezc.a ../tito/src/tito.a ../pikotools/utf8/utf8.a ../pikotools/space/space.a ../pikotools/mainparser/mainparser.a ../pikotools/date/date.a $(LDFLAGS) -lfcgi -lpq -lz -lfetch -lpthread -Wl,-no-whole-archive
|
||||
|
||||
|
||||
winix: FORCE
|
||||
winix: winix.so FORCE
|
||||
@cd main ; $(MAKE) -e
|
||||
# use the full path with winix.so
|
||||
$(CXX) -o winix $(CXXFLAGS) main/*.o /home/tomek/roboczy/winix/winix.so
|
||||
$(CXX) -o winix $(CXXFLAGS) $(LDFLAGS) main/*.o /home/tomek/roboczy/winix/winix.so
|
||||
|
||||
|
||||
|
||||
@@ -39,7 +47,9 @@ plugins: FORCE
|
||||
@cd plugins/thread ; $(MAKE) -e
|
||||
@cd plugins/ticket ; $(MAKE) -e
|
||||
@cd plugins/gallery ; $(MAKE) -e
|
||||
@cd plugins/groupitem ; $(MAKE) -e
|
||||
@cd plugins/group ; $(MAKE) -e
|
||||
@cd plugins/menu ; $(MAKE) -e
|
||||
@cd plugins/export ; $(MAKE) -e
|
||||
|
||||
|
||||
FORCE:
|
||||
@@ -55,8 +65,12 @@ clean:
|
||||
@cd plugins/thread ; $(MAKE) -e clean
|
||||
@cd plugins/ticket ; $(MAKE) -e clean
|
||||
@cd plugins/gallery ; $(MAKE) -e clean
|
||||
@cd plugins/groupitem ; $(MAKE) -e clean
|
||||
@cd plugins/group ; $(MAKE) -e clean
|
||||
@cd plugins/menu ; $(MAKE) -e clean
|
||||
@cd plugins/export ; $(MAKE) -e clean
|
||||
@cd ../ezc/src ; $(MAKE) -e clean
|
||||
@cd ../tito/src ; $(MAKE) -e clean
|
||||
@cd ../pikotools ; $(MAKE) -e clean
|
||||
@cd main ; $(MAKE) -e clean
|
||||
rm -f winix.so
|
||||
rm -f winix
|
||||
@@ -75,8 +89,12 @@ depend:
|
||||
@cd plugins/thread ; $(MAKE) -e depend
|
||||
@cd plugins/ticket ; $(MAKE) -e depend
|
||||
@cd plugins/gallery ; $(MAKE) -e depend
|
||||
@cd plugins/groupitem ; $(MAKE) -e depend
|
||||
@cd plugins/group ; $(MAKE) -e depend
|
||||
@cd plugins/menu ; $(MAKE) -e depend
|
||||
@cd plugins/export ; $(MAKE) -e depend
|
||||
@cd ../ezc/src ; $(MAKE) -e depend
|
||||
@cd ../tito/src ; $(MAKE) -e depend
|
||||
@cd ../pikotools ; $(MAKE) -e depend
|
||||
@cd main ; $(MAKE) -e depend
|
||||
|
||||
|
||||
@@ -87,6 +105,10 @@ install: all
|
||||
cp winix.so /usr/local/winix/bin
|
||||
# use the full path with winix.so (we have to recompile winix with a new path to winix.so)
|
||||
$(CXX) -o /usr/local/winix/bin/winix $(CXXFLAGS) main/*.o /usr/local/winix/bin/winix.so
|
||||
# etc configs
|
||||
mkdir -p /usr/local/winix/etc
|
||||
cp -rf etc/ /usr/local/winix/etc/
|
||||
find /usr/local/winix/etc/ -type d -name ".svn" | xargs -I foo rm -fr foo
|
||||
# html templates
|
||||
mkdir -p /usr/local/winix/html
|
||||
cp -rf html/ /usr/local/winix/html/
|
||||
|
||||
@@ -9,7 +9,7 @@ all: $(o)
|
||||
|
||||
|
||||
depend:
|
||||
makedepend -Y. -I.. -I../../ezc/src -f- *.cpp > Makefile.dep
|
||||
makedepend -Y. -I.. -I../../ezc/src -I../../pikotools -I../../tito/src -f- *.cpp > Makefile.dep
|
||||
echo -n "o = " > Makefile.o.dep
|
||||
ls -1 *.cpp | xargs -I foo echo -n foo " " | sed -E "s/([^\.]*)\.cpp[ ]/\1\.o/g" >> Makefile.o.dep
|
||||
|
||||
|
||||
1123
core/Makefile.dep
1123
core/Makefile.dep
File diff suppressed because it is too large
Load Diff
@@ -1 +1 @@
|
||||
o = acceptbaseparser.o app.o basethread.o bbcodeparser.o compress.o config.o confparser.o crypt.o dircontainer.o dirs.o groups.o htmlfilter.o httpsimpleparser.o item.o lastcontainer.o loadavg.o log.o misc.o mount.o mountparser.o mounts.o plugin.o plugindata.o postmultiparser.o rebus.o request.o run.o session.o sessioncontainer.o sessionmanager.o sessionparser.o slog.o synchro.o system.o textstream.o thumb.o users.o
|
||||
o = acceptbaseparser.o app.o basethread.o bbcodeparser.o compress.o config.o crypt.o dircontainer.o dirs.o groups.o htmlfilter.o httpsimpleparser.o image.o ipbancontainer.o item.o job.o lastcontainer.o loadavg.o lock.o log.o misc.o mount.o mountparser.o mounts.o plugin.o plugindata.o postmultiparser.o rebus.o request.o run.o session.o sessioncontainer.o sessionmanager.o sessionparser.o slog.o synchro.o system.o threadmanager.o timezone.o timezones.o user.o users.o
|
||||
|
||||
582
core/app.cpp
582
core/app.cpp
@@ -2,7 +2,7 @@
|
||||
* This file is a part of Winix
|
||||
* and is not publicly distributed
|
||||
*
|
||||
* Copyright (c) 2010-2011, Tomasz Sowa
|
||||
* Copyright (c) 2010-2012, Tomasz Sowa
|
||||
* All rights reserved.
|
||||
*
|
||||
*/
|
||||
@@ -15,12 +15,14 @@
|
||||
#include <cstdio>
|
||||
#include <fetch.h>
|
||||
#include <signal.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
|
||||
#include "app.h"
|
||||
#include "plugin.h"
|
||||
#include "misc.h"
|
||||
#include "functions/functions.h"
|
||||
#include "utf8.h"
|
||||
#include "utf8/utf8.h"
|
||||
|
||||
|
||||
|
||||
@@ -34,6 +36,7 @@ App::App()
|
||||
// temporary there is only one request
|
||||
cur.request = &req;
|
||||
cur.session = session_manager.GetTmpSession();
|
||||
cur.mount = system.mounts.GetEmptyMount();
|
||||
|
||||
db.SetConn(db_conn);
|
||||
|
||||
@@ -54,11 +57,14 @@ App::App()
|
||||
functions.SetSystem(&system);
|
||||
functions.SetTemplates(&templates);
|
||||
functions.SetSynchro(&synchro);
|
||||
functions.SetSessionManager(&session_manager);
|
||||
|
||||
system.SetConfig(&config);
|
||||
system.SetCur(&cur);
|
||||
system.SetDb(&db);
|
||||
system.SetSynchro(&synchro);
|
||||
system.SetFunctions(&functions);
|
||||
system.SetSessionManager(&session_manager);
|
||||
|
||||
templates.SetConfig(&config);
|
||||
templates.SetCur(&cur);
|
||||
@@ -142,25 +148,21 @@ bool App::Init()
|
||||
compress.Init();
|
||||
system.Init();
|
||||
functions.Init();
|
||||
|
||||
// init templates after functions are created
|
||||
templates.CreateFunctions(); // create functions first (functions will be cached by patterns)
|
||||
templates.ReadIndexFileNames();
|
||||
templates.ReadTemplates();
|
||||
templates.Init(); // init templates after functions are created
|
||||
|
||||
// init notify after templates (it uses locales from templates)
|
||||
system.notify.ReadTemplates();
|
||||
session_manager.InitBanList();
|
||||
session_manager.InitTmpSession();
|
||||
session_manager.LoadSessions();
|
||||
|
||||
CreateStaticTree();
|
||||
|
||||
get_parser.UTF8(config.utf8);
|
||||
post_parser.UTF8(config.utf8);
|
||||
post_parser.LogValueSize(config.log_post_value_size);
|
||||
// post_multi_parser has a pointer to the config
|
||||
|
||||
plugin.Call(WINIX_PLUGIN_INIT);
|
||||
plugin.Call((Session*)0, WINIX_PLUGIN_INIT);
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -176,24 +178,124 @@ void App::Close()
|
||||
}
|
||||
|
||||
|
||||
void App::BaseUrlRedirect(int code, bool add_subdomain)
|
||||
{
|
||||
system.PutUrlProto(config.use_ssl, cur.request->redirect_to);
|
||||
|
||||
if( add_subdomain && !cur.request->subdomain.empty() )
|
||||
{
|
||||
cur.request->redirect_to += cur.request->subdomain;
|
||||
cur.request->redirect_to += '.';
|
||||
}
|
||||
|
||||
cur.request->redirect_to += config.base_url;
|
||||
AssignString(cur.request->env_request_uri, cur.request->redirect_to, false);
|
||||
// cur.request->env_request_uri should not be UrlEncoded because it contains slashes
|
||||
cur.request->redirect_type = code;
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool App::BaseUrlRedirect()
|
||||
{
|
||||
if( config.base_url_http_host.empty() )
|
||||
plugin.Call((Session*)0, WINIX_BASE_URL_REDIRECT);
|
||||
|
||||
if( !cur.request->redirect_to.empty() )
|
||||
return true;
|
||||
|
||||
if( !config.base_url_redirect )
|
||||
return false;
|
||||
|
||||
if( config.base_url.empty() )
|
||||
return false;
|
||||
|
||||
if( cur.request->method == Request::post )
|
||||
return false;
|
||||
|
||||
if( Equal(config.base_url_http_host.c_str(), cur.request->env_http_host) )
|
||||
if( Equal(config.base_url.c_str(), cur.request->env_http_host) )
|
||||
return false;
|
||||
|
||||
cur.request->redirect_to = config.base_url;
|
||||
AssignString(cur.request->env_request_uri, cur.request->redirect_to, false);
|
||||
|
||||
log << log3 << "RC: BaseUrlRedirect from: " << cur.request->env_http_host << logend;
|
||||
BaseUrlRedirect(config.base_url_redirect_code, false);
|
||||
log << log3 << "App: BaseUrlRedirect from: " << cur.request->env_http_host << logend;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void App::CheckIfNeedSSLredirect()
|
||||
{
|
||||
if( cur.request->method == Request::post )
|
||||
{
|
||||
// something comes via POST, don't do the redirect because you lose the date
|
||||
return;
|
||||
}
|
||||
|
||||
if( config.use_ssl )
|
||||
{
|
||||
if( !cur.request->using_ssl )
|
||||
{
|
||||
if( !config.use_ssl_only_for_logged_users ||
|
||||
cur.session->puser ||
|
||||
(cur.request->function && cur.request->function->need_ssl) )
|
||||
{
|
||||
log << log3 << "App: this operation should be used through SSL" << logend;
|
||||
BaseUrlRedirect(config.use_ssl_redirect_code, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if( cur.request->using_ssl )
|
||||
{
|
||||
log << log3 << "App: this operation should NOT be used through SSL" << logend;
|
||||
BaseUrlRedirect(config.use_ssl_redirect_code, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void App::SetLocale()
|
||||
{
|
||||
size_t locale_id;
|
||||
|
||||
if( cur.session->puser )
|
||||
{
|
||||
locale_id = cur.session->puser->locale_id;
|
||||
|
||||
if( !TemplatesFunctions::locale.HasLanguage(locale_id) )
|
||||
locale_id = config.locale_default_id;
|
||||
}
|
||||
else
|
||||
{
|
||||
locale_id = config.locale_default_id;
|
||||
}
|
||||
|
||||
TemplatesFunctions::locale.SetCurLang(locale_id);
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool App::CheckAccessFromPlugins()
|
||||
{
|
||||
PluginRes res = plugin.Call(WINIX_CHECK_PLUGIN_ACCESS);
|
||||
|
||||
if( res.res_false > 0 )
|
||||
{
|
||||
cur.request->status = WINIX_ERR_PERMISSION_DENIED;
|
||||
log << log2 << "App: access prevented by a plugin" << logend;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void App::ProcessRequestThrow()
|
||||
{
|
||||
ReadRequest();
|
||||
@@ -205,6 +307,7 @@ void App::ProcessRequestThrow()
|
||||
{
|
||||
session_manager.SetSession();
|
||||
cur.session = session_manager.GetCurSession();
|
||||
SetLocale();
|
||||
|
||||
if( cur.session->new_session )
|
||||
{
|
||||
@@ -213,11 +316,10 @@ void App::ProcessRequestThrow()
|
||||
}
|
||||
|
||||
plugin.Call(WINIX_SESSION_CHANGED);
|
||||
|
||||
functions.Parse(); // parsing directories,files,functions and parameters
|
||||
system.mounts.CalcCurMount();
|
||||
cur.mount = system.mounts.CalcCurMount();
|
||||
|
||||
if( system.mounts.pmount->type != system.mounts.MountTypeStatic() )
|
||||
if( cur.mount->type != system.mounts.MountTypeStatic() )
|
||||
Make();
|
||||
}
|
||||
|
||||
@@ -229,6 +331,7 @@ void App::ProcessRequest()
|
||||
{
|
||||
try
|
||||
{
|
||||
cur.request->RequestStarts();
|
||||
system.load_avg.StartRequest();
|
||||
log << log2 << config.log_delimiter << logend;
|
||||
|
||||
@@ -236,7 +339,6 @@ void App::ProcessRequest()
|
||||
SaveSessionsIfNeeded(); // !! przerzucic to na watek sesji
|
||||
|
||||
system.load_avg.StopRequest();
|
||||
log << logendrequest;
|
||||
}
|
||||
catch(const std::exception & e)
|
||||
{
|
||||
@@ -258,12 +360,15 @@ void App::ProcessRequest()
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
log << log1 << "App: an exception when clearing the request (from a plugin)" << logend;
|
||||
log << log1 << "App: an exception when clearing after a request (exception from a plugin)" << logend;
|
||||
}
|
||||
|
||||
|
||||
// simple operations which should not throw an exception
|
||||
templates.RequestEnd();
|
||||
cur.request->Clear();
|
||||
cur.session->ClearOnEndRequest();
|
||||
cur.session = session_manager.GetTmpSession();
|
||||
log << logendrequest;
|
||||
}
|
||||
|
||||
|
||||
@@ -302,9 +407,12 @@ void App::MakePage()
|
||||
bool sent = false;
|
||||
|
||||
|
||||
if( !cur.request->redirect_to.empty() || !cur.request->x_sendfile.empty() )
|
||||
if( cur.request->page_generated || !cur.request->redirect_to.empty() || !cur.request->x_sendfile.empty() )
|
||||
return;
|
||||
|
||||
templates.SetEzcParameters( cur.request->gen_trim_white,
|
||||
cur.request->gen_skip_new_line,
|
||||
cur.request->gen_use_special_chars);
|
||||
|
||||
if( cur.request->is_item && cur.request->item.file_type == WINIX_ITEM_FILETYPE_NONE &&
|
||||
cur.request->item.content_type == Item::ct_raw && cur.request->status == WINIX_ERR_OK && cur.request->function )
|
||||
@@ -326,19 +434,57 @@ bool sent = false;
|
||||
{
|
||||
templates.Generate();
|
||||
}
|
||||
|
||||
|
||||
if( cur.request->ajax_serializer )
|
||||
{
|
||||
std::wstring & ajax_content = cur.request->ajax.Add(L"content", L"");
|
||||
ajax_content = cur.request->page.Str();
|
||||
cur.request->ajax_serializer->Serialize(cur.request->ajax, cur.request->ajaxpage, true);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void App::CheckPostRedirect()
|
||||
{
|
||||
if( cur.request->method == Request::post )
|
||||
{
|
||||
if( cur.request->IsParam(L"postredirect") )
|
||||
{
|
||||
cur.request->redirect_to = cur.request->ParamValue(L"postredirect");
|
||||
cur.request->redirect_type = 303;
|
||||
}
|
||||
else
|
||||
if( cur.request->IsPostVar(L"postredirect") )
|
||||
{
|
||||
cur.request->redirect_to = cur.request->PostVar(L"postredirect");
|
||||
cur.request->redirect_type = 303;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// zmienic nazwe np na ProcessRequest
|
||||
// !! ta nazwa chyba juz zajeta...
|
||||
// !! IMPROVE ME need some refactoring
|
||||
void App::Make()
|
||||
{
|
||||
if( cur.request->dir_tab.empty() )
|
||||
{
|
||||
log << log1 << "Content: there is no a root dir (dir_tab is empty)" << logend;
|
||||
log << log1 << "App: there is no a root dir (dir_tab is empty)" << logend;
|
||||
return;
|
||||
}
|
||||
|
||||
if( cur.session->ip_ban && cur.session->ip_ban->IsIPBanned() )
|
||||
{
|
||||
PT::Date date(cur.session->ip_ban->expires);
|
||||
|
||||
log << log2 << "App: this IP address is banned until to: " << date << " UTC" << logend;
|
||||
slog << logerror << T("this_ip_is_banned_until") << ' ' << date << " UTC" << logend;
|
||||
|
||||
cur.request->status = WINIX_ERR_PERMISSION_DENIED;
|
||||
}
|
||||
|
||||
// cur.request->status can be changed by function_parser
|
||||
if( cur.request->status == WINIX_ERR_OK )
|
||||
plugin.Call(WINIX_PREPARE_REQUEST);
|
||||
@@ -346,6 +492,15 @@ void App::Make()
|
||||
if( cur.request->status == WINIX_ERR_OK )
|
||||
functions.CheckFunctionAndSymlink();
|
||||
|
||||
CheckAccessFromPlugins();
|
||||
|
||||
// !! CHECK ME CheckFunctionAndSymlink can set redirect_to
|
||||
// may it should be tested before calling CheckIfNeedSSLredirect?
|
||||
CheckIfNeedSSLredirect();
|
||||
|
||||
if( !cur.request->redirect_to.empty() )
|
||||
return;
|
||||
|
||||
if( cur.request->status == WINIX_ERR_OK )
|
||||
functions.MakeFunction();
|
||||
|
||||
@@ -358,6 +513,8 @@ void App::Make()
|
||||
if( cur.request->status == WINIX_ERR_OK )
|
||||
plugin.Call(WINIX_PROCESS_REQUEST);
|
||||
|
||||
CheckPostRedirect();
|
||||
|
||||
if( !cur.request->redirect_to.empty() )
|
||||
return;
|
||||
|
||||
@@ -374,12 +531,22 @@ void App::Make()
|
||||
{
|
||||
// !! dodac inne informacje (get, post, itp)
|
||||
// jesli jest debug_info wlaczone to nie robic przekierowan
|
||||
cur.request->PrintGetTab();
|
||||
//cur.request->PrintEnv(); // !! PrintEnv() mozna przeniesc tutaj (do klasy App)
|
||||
PrintEnv();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void App::PrintEnv()
|
||||
{
|
||||
char ** e;
|
||||
|
||||
cur.request->debug << "environment variables:\n";
|
||||
|
||||
for( e = fcgi_request.envp ; *e ; ++e )
|
||||
cur.request->debug << ' ' << *e << "\n";
|
||||
|
||||
cur.request->debug << '\n';
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -389,6 +556,8 @@ void App::ReadRequest()
|
||||
ReadEnvVariables();
|
||||
CheckRequestMethod();
|
||||
CheckFCGIRole();
|
||||
CheckSSL();
|
||||
SetSubdomain();
|
||||
|
||||
LogAccess();
|
||||
|
||||
@@ -399,8 +568,11 @@ void App::ReadRequest()
|
||||
CheckIE();
|
||||
CheckKonqueror();
|
||||
|
||||
if( cur.request->using_ssl )
|
||||
log << log3 << "App: connection secure through SSL" << logend;
|
||||
|
||||
if( cur.request->role == Request::authorizer )
|
||||
log << log3 << "Request: fast cgi role: authorizer" << logend;
|
||||
log << log3 << "App: fast cgi role: authorizer" << logend;
|
||||
}
|
||||
|
||||
|
||||
@@ -431,6 +603,9 @@ void App::ReadEnvVariables()
|
||||
SetEnv(cur.request->env_fcgi_role, "FCGI_ROLE");
|
||||
SetEnv(cur.request->env_content_type, "CONTENT_TYPE");
|
||||
SetEnv(cur.request->env_http_accept_encoding, "HTTP_ACCEPT_ENCODING");
|
||||
SetEnv(cur.request->env_https, "HTTPS");
|
||||
|
||||
cur.request->ip = (int)inet_addr(cur.request->env_remote_addr);
|
||||
}
|
||||
|
||||
|
||||
@@ -460,16 +635,37 @@ void App::CheckFCGIRole()
|
||||
}
|
||||
|
||||
|
||||
void App::CheckSSL()
|
||||
{
|
||||
// !! CHECK ME
|
||||
// value "on" exists in lighttpd server
|
||||
// make sure that for other servers is "on" too
|
||||
|
||||
if( EqualNoCase(cur.request->env_https, "on") )
|
||||
cur.request->using_ssl = true;
|
||||
}
|
||||
|
||||
|
||||
void App::SetSubdomain()
|
||||
{
|
||||
CreateSubdomain(config.base_url.c_str(), cur.request->env_http_host, cur.request->subdomain);
|
||||
}
|
||||
|
||||
|
||||
void App::LogAccess()
|
||||
{
|
||||
log.PutDate(log1);
|
||||
log << log1;
|
||||
log.PrintDate(cur.request->start_date, config.log_time_zone_id);
|
||||
|
||||
log << cur.request->env_remote_addr << ' '
|
||||
log << ' '
|
||||
<< cur.request->env_remote_addr << ' '
|
||||
<< cur.request->env_request_method << ' '
|
||||
<< cur.request->env_http_host
|
||||
<< cur.request->env_request_uri << ' '
|
||||
<< cur.request->env_http_user_agent << logend;
|
||||
|
||||
if( !cur.request->subdomain.empty() )
|
||||
log << log3 << "Subdomain: " << cur.request->subdomain << logend;
|
||||
}
|
||||
|
||||
|
||||
@@ -478,13 +674,13 @@ void App::LogAccess()
|
||||
void App::ReadGetPostVars()
|
||||
{
|
||||
// get parameters we have always
|
||||
get_parser.Parse(cur.request->env_request_uri, cur.request->get_tab);
|
||||
//get_parser.Parse(cur.request->env_request_uri, cur.request->get_tab);
|
||||
|
||||
if( cur.request->method == Request::post )
|
||||
{
|
||||
if( IsSubStringNoCase("multipart/form-data", cur.request->env_content_type) )
|
||||
{
|
||||
log << log3 << "Request: post content type: multipart/form-data" << logend;
|
||||
log << log3 << "App: post content type: multipart/form-data" << logend;
|
||||
post_multi_parser.Parse(fcgi_request.in, cur.request->post_tab, cur.request->post_file_tab);
|
||||
}
|
||||
else
|
||||
@@ -535,14 +731,42 @@ void App::PrepareSessionCookie()
|
||||
}
|
||||
else
|
||||
{
|
||||
time_t t = std::time(0) + config.session_remember_max_idle;
|
||||
tm expires = Time(t);
|
||||
PT::Date expires = cur.request->start_time + config.session_remember_max_idle;
|
||||
cur.request->SetCookie(config.http_session_id_name.c_str(), cur.session->id, &expires);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool App::SendHeadersStaticCreateResource()
|
||||
{
|
||||
size_t i = 0;
|
||||
Item * dir = system.dirs.GetDir(system.mounts.pmount->dir_id);
|
||||
sendh_t3.clear();
|
||||
|
||||
if( !dir )
|
||||
{
|
||||
log << log1 << "App: cannot find the mount directory" << logend;
|
||||
return false;
|
||||
}
|
||||
|
||||
size_t how_many_dirs = system.dirs.DirLevel(dir->id);
|
||||
const char * path = SkipDirs(cur.request->env_request_uri, how_many_dirs);
|
||||
|
||||
// the path begins with a slash only if how_many_dirs is zero
|
||||
while( *path == '/' )
|
||||
path += 1;
|
||||
|
||||
while( path[i]!=0 && path[i]!='?' && path[i]!='#' )
|
||||
++i;
|
||||
|
||||
if( i > 0 )
|
||||
sendh_t3.assign(path, i);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void App::SendHeadersStatic()
|
||||
{
|
||||
if( PathHasUpDir(cur.request->env_request_uri) )
|
||||
@@ -562,41 +786,130 @@ void App::SendHeadersStatic()
|
||||
return;
|
||||
}
|
||||
|
||||
Ezc::WideToUTF8(config.http_header_send_file, sendheadersstatic_t);
|
||||
Ezc::WideToUTF8(config.static_dirs[index], sendheadersstatic_t2);
|
||||
PT::WideToUTF8(config.http_header_send_file, sendh_t);
|
||||
PT::WideToUTF8(config.static_dirs[index], sendh_t2);
|
||||
|
||||
Item * dir = system.dirs.GetDir(system.mounts.pmount->dir_id);
|
||||
|
||||
if( !dir )
|
||||
if( !SendHeadersStaticCreateResource() )
|
||||
{
|
||||
log << log1 << "App: cannot find the mount directory" << logend;
|
||||
SendHeadersForbidden();
|
||||
return;
|
||||
}
|
||||
|
||||
size_t how_many_dirs = system.dirs.DirLevel(dir->id);
|
||||
const char * path = SkipDirs(cur.request->env_request_uri, how_many_dirs);
|
||||
|
||||
// the path begins with a slash only if how_many_dirs is zero
|
||||
while( *path == '/' )
|
||||
path += 1;
|
||||
|
||||
FCGX_FPrintF(fcgi_request.out, "%s: %s/%s\r\n", sendheadersstatic_t.c_str(), sendheadersstatic_t2.c_str(), path);
|
||||
FCGX_FPrintF(fcgi_request.out, "%s: %s/%s\r\n", sendh_t.c_str(), sendh_t2.c_str(), sendh_t3.c_str());
|
||||
FCGX_PutS("Status: 200 OK\r\n", fcgi_request.out);
|
||||
log << log2 << "Sending file from a static mountpoint: " << sendheadersstatic_t2 << "/" << path << logend;
|
||||
log << log2 << "App: sending a file from a static mountpoint: " << sendh_t2 << "/" << sendh_t3 << logend;
|
||||
}
|
||||
|
||||
|
||||
void App::SendHeaderContentType()
|
||||
{
|
||||
switch( config.content_type_header )
|
||||
{
|
||||
case 1:
|
||||
FCGX_PutS("Content-Type: application/xhtml+xml", fcgi_request.out);
|
||||
break;
|
||||
|
||||
case 2:
|
||||
FCGX_PutS("Content-Type: application/xml", fcgi_request.out);
|
||||
break;
|
||||
|
||||
case 0:
|
||||
default:
|
||||
FCGX_PutS("Content-Type: text/html", fcgi_request.out);
|
||||
}
|
||||
|
||||
if( config.utf8 )
|
||||
FCGX_PutS("; charset=UTF-8", fcgi_request.out);
|
||||
|
||||
FCGX_PutS("\r\n", fcgi_request.out);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void App::SendHeadersForbidden()
|
||||
{
|
||||
FCGX_PutS("Status: 403 Forbidden\r\n", fcgi_request.out);
|
||||
FCGX_PutS("Content-Type: text/html\r\n", fcgi_request.out);
|
||||
log << log2 << "Request: response: 403 Forbidden" << logend;
|
||||
SendHeaderContentType();
|
||||
log << log2 << "App: response: 403 Forbidden" << logend;
|
||||
}
|
||||
|
||||
|
||||
void App::SendHeadersRedirect()
|
||||
{
|
||||
switch(cur.request->redirect_type)
|
||||
{
|
||||
case 300:
|
||||
FCGX_PutS("Status: 300 Multiple Choices\r\n", fcgi_request.out);
|
||||
break;
|
||||
|
||||
case 301:
|
||||
FCGX_PutS("Status: 301 Moved Permanently\r\n", fcgi_request.out);
|
||||
break;
|
||||
|
||||
case 302:
|
||||
FCGX_PutS("Status: 302 Found\r\n", fcgi_request.out);
|
||||
break;
|
||||
|
||||
case 307:
|
||||
FCGX_PutS("Status: 307 Temporary Redirect\r\n", fcgi_request.out);
|
||||
break;
|
||||
|
||||
case 303:
|
||||
default:
|
||||
FCGX_PutS("Status: 303 See Other\r\n", fcgi_request.out);
|
||||
break;
|
||||
}
|
||||
|
||||
PT::WideToUTF8(cur.request->redirect_to, cur.request->aredirect_to);
|
||||
FCGX_FPrintF(fcgi_request.out, "Location: %s\r\n", cur.request->aredirect_to.c_str());
|
||||
log << log2 << "App: redirect to: " << cur.request->aredirect_to << logend;
|
||||
}
|
||||
|
||||
|
||||
void App::SendHeadersSendFile()
|
||||
{
|
||||
PT::WideToUTF8(config.http_header_send_file, sendfilea);
|
||||
PT::WideToUTF8(cur.request->x_sendfile, sendfile2a);
|
||||
FCGX_FPrintF(fcgi_request.out, "%s: %s\r\n", sendfilea.c_str(), sendfile2a.c_str());
|
||||
|
||||
FCGX_PutS("Status: 200 OK\r\n", fcgi_request.out);
|
||||
log << log2 << "App: sending file: " << cur.request->x_sendfile << logend;
|
||||
}
|
||||
|
||||
|
||||
void App::SendHeadersCompression(int compress_encoding)
|
||||
{
|
||||
if( compress_encoding == 0 || compress_encoding == 1 )
|
||||
FCGX_PutS("Content-Encoding: deflate\r\n", fcgi_request.out);
|
||||
else
|
||||
FCGX_PutS("Content-Encoding: gzip\r\n", fcgi_request.out);
|
||||
}
|
||||
|
||||
|
||||
void App::SendHeadersNormal(Header header)
|
||||
{
|
||||
switch( header )
|
||||
{
|
||||
case h_404:
|
||||
FCGX_PutS("Status: 404 Not Found\r\n", fcgi_request.out);
|
||||
SendHeaderContentType();
|
||||
log << log2 << "App: response: 404 Not Found" << logend;
|
||||
break;
|
||||
|
||||
case h_403:
|
||||
SendHeadersForbidden();
|
||||
break;
|
||||
|
||||
default:
|
||||
FCGX_PutS("Status: 200 OK\r\n", fcgi_request.out);
|
||||
|
||||
if( cur.request->role != Request::authorizer )
|
||||
SendHeaderContentType();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void App::SendHeaders(bool compressing, int compress_encoding, Header header)
|
||||
{
|
||||
PrepareSessionCookie();
|
||||
@@ -606,10 +919,7 @@ void App::SendHeaders(bool compressing, int compress_encoding, Header header)
|
||||
|
||||
if( !cur.request->redirect_to.empty() )
|
||||
{
|
||||
FCGX_PutS("Status: 301 Moved Permanently\r\n", fcgi_request.out);
|
||||
UrlEncode(cur.request->redirect_to, cur.request->aredirect_to);
|
||||
FCGX_FPrintF(fcgi_request.out, "Location: %s\r\n", cur.request->aredirect_to.c_str());
|
||||
log << log2 << "Redirect to: " << cur.request->aredirect_to << logend;
|
||||
SendHeadersRedirect();
|
||||
}
|
||||
else
|
||||
if( system.mounts.pmount->type == system.mounts.MountTypeStatic() )
|
||||
@@ -619,44 +929,15 @@ void App::SendHeaders(bool compressing, int compress_encoding, Header header)
|
||||
else
|
||||
if( !cur.request->x_sendfile.empty() )
|
||||
{
|
||||
static std::string temp, temp2; // !! wrzucic gdzies to
|
||||
|
||||
Ezc::WideToUTF8(config.http_header_send_file, temp);
|
||||
Ezc::WideToUTF8(cur.request->x_sendfile, temp2);
|
||||
FCGX_FPrintF(fcgi_request.out, "%s: %s\r\n", temp.c_str(), temp2.c_str());
|
||||
|
||||
FCGX_PutS("Status: 200 OK\r\n", fcgi_request.out);
|
||||
log << log2 << "Sending file: " << cur.request->x_sendfile << logend;
|
||||
SendHeadersSendFile();
|
||||
}
|
||||
else
|
||||
{
|
||||
switch( header )
|
||||
{
|
||||
case h_404:
|
||||
FCGX_PutS("Status: 404 Not Found\r\n", fcgi_request.out);
|
||||
FCGX_PutS("Content-Type: text/html\r\n", fcgi_request.out);
|
||||
log << log2 << "Request: response: 404 Not Found" << logend;
|
||||
break;
|
||||
|
||||
case h_403:
|
||||
SendHeadersForbidden();
|
||||
break;
|
||||
|
||||
default:
|
||||
FCGX_PutS("Status: 200 OK\r\n", fcgi_request.out);
|
||||
|
||||
if( cur.request->role != Request::authorizer )
|
||||
FCGX_PutS("Content-Type: text/html\r\n", fcgi_request.out);
|
||||
}
|
||||
SendHeadersNormal(header);
|
||||
}
|
||||
|
||||
if( compressing )
|
||||
{
|
||||
if( compress_encoding == 0 || compress_encoding == 1 )
|
||||
FCGX_PutS("Content-Encoding: deflate\r\n", fcgi_request.out);
|
||||
else
|
||||
FCGX_PutS("Content-Encoding: gzip\r\n", fcgi_request.out);
|
||||
}
|
||||
SendHeadersCompression(compress_encoding);
|
||||
|
||||
FCGX_PutS(cur.request->headers.CStr(), fcgi_request.out);
|
||||
FCGX_PutS("\r\n", fcgi_request.out);
|
||||
@@ -672,7 +953,7 @@ void App::FilterCompressSend(bool compressing, int compress_encoding, const std:
|
||||
bool raw = cur.request->is_item && cur.request->item.content_type == Item::ct_raw && cur.request->status == WINIX_ERR_OK &&
|
||||
cur.request->function && (cur.request->function == &functions.fun_cat || cur.request->function == &functions.fun_run);
|
||||
|
||||
if( config.html_filter && !raw )
|
||||
if( config.html_filter && cur.request->use_html_filter && !raw && !cur.request->ajax_serializer )
|
||||
{
|
||||
TemplatesFunctions::html_filter.Filter(*source, clean_html);
|
||||
AddDebugInfo(clean_html);
|
||||
@@ -686,7 +967,7 @@ void App::FilterCompressSend(bool compressing, int compress_encoding, const std:
|
||||
}
|
||||
|
||||
if( config.utf8 )
|
||||
Ezc::WideToUTF8(*source, source_a);
|
||||
PT::WideToUTF8(*source, source_a);
|
||||
else
|
||||
AssignString(*source, source_a);
|
||||
|
||||
@@ -698,6 +979,7 @@ void App::FilterCompressSend(bool compressing, int compress_encoding, const std:
|
||||
|
||||
|
||||
|
||||
|
||||
int App::SelectDeflateVersion()
|
||||
{
|
||||
if( cur.request->browser_msie )
|
||||
@@ -791,15 +1073,20 @@ void App::AddDebugInfo(std::wstring & out)
|
||||
|
||||
|
||||
|
||||
void App::SendAnswer()
|
||||
void App::SendTextAnswer()
|
||||
{
|
||||
const std::wstring & source = cur.request->page.Str();
|
||||
const std::wstring * source;
|
||||
Header header = h_200;
|
||||
Error status = cur.request->status;
|
||||
bool compressing;
|
||||
int compress_encoding;
|
||||
|
||||
SelectCompression(source.length(), compressing, compress_encoding);
|
||||
if( cur.request->ajax_serializer )
|
||||
source = &cur.request->ajaxpage.Str();
|
||||
else
|
||||
source = &cur.request->page.Str();
|
||||
|
||||
SelectCompression(source->length(), compressing, compress_encoding);
|
||||
|
||||
if( status == WINIX_ERR_NO_ITEM || status == WINIX_ERR_NO_FUNCTION || status == WINIX_ERR_UNKNOWN_PARAM )
|
||||
header = h_404;
|
||||
@@ -812,11 +1099,91 @@ int compress_encoding;
|
||||
if( CanSendContent(header) )
|
||||
{
|
||||
// filtering (html), compressing and sending back to the web browser
|
||||
FilterCompressSend(compressing, compress_encoding, source);
|
||||
FilterCompressSend(compressing, compress_encoding, *source);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void App::SendData(const BinaryPage & page, FCGX_Stream * out)
|
||||
{
|
||||
const size_t buf_size = 4096;
|
||||
|
||||
if( send_data_buf.size() != buf_size )
|
||||
send_data_buf.resize(buf_size);
|
||||
|
||||
BinaryPage::const_iterator i = page.begin();
|
||||
BinaryPage::const_iterator end = page.end();
|
||||
|
||||
// log << log1 << "size: " << page.size() << logend;
|
||||
|
||||
// for(size_t x=0 ; x<page.size() ; ++x)
|
||||
// log << int((unsigned char)page[x]) << ' ';
|
||||
|
||||
// log << logend;
|
||||
|
||||
while( i != end )
|
||||
{
|
||||
size_t s = 0;
|
||||
|
||||
for( ; i != end && s < buf_size ; ++i, ++s)
|
||||
{
|
||||
send_data_buf[s] = *i;
|
||||
|
||||
// log << "swinka: " << int((unsigned char)*i) << logend;
|
||||
}
|
||||
|
||||
if( s > 0 )
|
||||
FCGX_PutStr(send_data_buf.c_str(), s, fcgi_request.out);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void App::SendBinaryAnswer()
|
||||
{
|
||||
BinaryPage & source = cur.request->binary_page;
|
||||
BinaryPage & compressed_page = cur.request->compressed_page;
|
||||
Header header = h_200;
|
||||
Error status = cur.request->status;
|
||||
bool compressing;
|
||||
int compress_encoding;
|
||||
|
||||
|
||||
SelectCompression(source.size(), compressing, compress_encoding);
|
||||
|
||||
if( status == WINIX_ERR_NO_ITEM || status == WINIX_ERR_NO_FUNCTION || status == WINIX_ERR_UNKNOWN_PARAM )
|
||||
header = h_404;
|
||||
|
||||
if( status == WINIX_ERR_PERMISSION_DENIED || status == WINIX_ERR_CANT_CHANGE_USER || status == WINIX_ERR_CANT_CHANGE_GROUP )
|
||||
header = h_403;
|
||||
|
||||
// !! IMPROVE ME add header: content-size
|
||||
|
||||
SendHeaders(compressing, compress_encoding, header);
|
||||
|
||||
if( CanSendContent(header) )
|
||||
{
|
||||
if( compressing )
|
||||
{
|
||||
compress.Compressing(source, compressed_page, compress_encoding);
|
||||
SendData(compressed_page, fcgi_request.out);
|
||||
}
|
||||
else
|
||||
{
|
||||
SendData(source, fcgi_request.out);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void App::SendAnswer()
|
||||
{
|
||||
if( cur.request->use_text_page )
|
||||
SendTextAnswer();
|
||||
else
|
||||
SendBinaryAnswer();
|
||||
}
|
||||
|
||||
|
||||
void App::LogUser(const char * msg, uid_t id)
|
||||
{
|
||||
log << log3 << msg << " ";
|
||||
@@ -1085,9 +1452,7 @@ void App::WaitForThreads()
|
||||
// but it doesn't matter, don't use pthread_join on it
|
||||
//pthread_join(signal_thread, 0);
|
||||
|
||||
system.notify.WaitForThread();
|
||||
session_manager.WaitForThread();
|
||||
system.thumb.WaitForThread();
|
||||
system.thread_manager.StopAll();
|
||||
}
|
||||
|
||||
|
||||
@@ -1120,10 +1485,10 @@ sigset_t set;
|
||||
app->Lock();
|
||||
app->synchro.was_stop_signal = true;
|
||||
FCGX_ShutdownPending();
|
||||
Ezc::WideToUTF8(app->config.base_url, app->url_to_fetch_on_exit);
|
||||
app->system.notify.PrepareToStopThread();
|
||||
app->session_manager.WakeUpThread();
|
||||
app->system.thumb.WakeUpThread();
|
||||
|
||||
// here we don't have to use SSL version so we always use config.url_proto
|
||||
PT::WideToUTF8(app->config.url_proto, app->url_to_fetch_on_exit);
|
||||
PT::WideToUTF8(app->config.base_url, app->url_to_fetch_on_exit, false);
|
||||
app->Unlock();
|
||||
|
||||
// this thread will hang on this method
|
||||
@@ -1138,27 +1503,14 @@ sigset_t set;
|
||||
|
||||
void App::StartThreads()
|
||||
{
|
||||
sigset_t set;
|
||||
|
||||
sigemptyset(&set);
|
||||
sigaddset(&set, SIGTERM);
|
||||
sigaddset(&set, SIGINT);
|
||||
|
||||
// blocking SIGTERM and SIGINT
|
||||
// new threads will have the signals blocked too
|
||||
pthread_sigmask(SIG_BLOCK, &set, 0);
|
||||
// make sure system.thread_manager.Init() was called beforehand
|
||||
// it is called in Init() -> system.Init()
|
||||
|
||||
// special thread only for signals
|
||||
pthread_create(&signal_thread, 0, SpecialThreadForSignals, this);
|
||||
|
||||
// thread for notifications
|
||||
system.notify.StartThread();
|
||||
|
||||
// gc for sessions
|
||||
session_manager.StartThread();
|
||||
|
||||
// thumbnails
|
||||
system.thumb.StartThread();
|
||||
system.thread_manager.Add(&session_manager, L"session_manager");
|
||||
system.thread_manager.StartAll();
|
||||
}
|
||||
|
||||
|
||||
|
||||
45
core/app.h
45
core/app.h
@@ -2,7 +2,7 @@
|
||||
* This file is a part of Winix
|
||||
* and is not publicly distributed
|
||||
*
|
||||
* Copyright (c) 2010-2011, Tomasz Sowa
|
||||
* Copyright (c) 2010-2012, Tomasz Sowa
|
||||
* All rights reserved.
|
||||
*
|
||||
*/
|
||||
@@ -30,7 +30,6 @@
|
||||
#include "functions/functions.h"
|
||||
#include "templates/templates.h"
|
||||
#include "compress.h"
|
||||
#include "getparser.h"
|
||||
#include "postparser.h"
|
||||
#include "cookieparser.h"
|
||||
#include "postmultiparser.h"
|
||||
@@ -38,7 +37,6 @@
|
||||
|
||||
|
||||
|
||||
|
||||
class App
|
||||
{
|
||||
public:
|
||||
@@ -82,25 +80,17 @@ public:
|
||||
model
|
||||
*/
|
||||
|
||||
// file system
|
||||
// ...
|
||||
System system;
|
||||
|
||||
// functions (ls, cat, emacs, ...)
|
||||
Functions functions;
|
||||
|
||||
// false at the beginning
|
||||
// !! moze to do loggera dac?
|
||||
bool stdout_is_closed;
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
controllers
|
||||
(note that the whole app object is actually a controller too)
|
||||
*/
|
||||
|
||||
// functions (ls, cat, emacs, ...)
|
||||
Functions functions;
|
||||
|
||||
|
||||
/*
|
||||
view
|
||||
*/
|
||||
@@ -117,11 +107,10 @@ private:
|
||||
h_403
|
||||
};
|
||||
|
||||
GetParser get_parser;
|
||||
PostParser post_parser;
|
||||
PostMultiParser post_multi_parser;
|
||||
CookieParser cookie_parser;
|
||||
AcceptEncodingParser accept_encoding_parser;
|
||||
AcceptEncodingParser accept_encoding_parser;
|
||||
Compress compress;
|
||||
std::wstring clean_html, html_with_debug;
|
||||
FCGX_Request fcgi_request;
|
||||
@@ -130,19 +119,31 @@ private:
|
||||
pthread_t signal_thread;
|
||||
std::string url_to_fetch_on_exit;
|
||||
std::string source_a;
|
||||
std::string sendheadersstatic_t, sendheadersstatic_t2;
|
||||
std::string sendh_t, sendh_t2, sendh_t3;
|
||||
std::string sendfilea, sendfile2a;
|
||||
std::string send_data_buf;
|
||||
|
||||
bool CheckAccessFromPlugins();
|
||||
void ProcessRequestThrow();
|
||||
void ProcessRequest();
|
||||
void BaseUrlRedirect(int code, bool add_subdomain);
|
||||
bool BaseUrlRedirect();
|
||||
void CheckIfNeedSSLredirect();
|
||||
void SetLocale();
|
||||
void CheckPostRedirect();
|
||||
void MakePage();
|
||||
void Make();
|
||||
void SaveSessionsIfNeeded(); // !! wywalic do menagera sesji??
|
||||
void LogAccess();
|
||||
void SendData(const BinaryPage & page, FCGX_Stream * out);
|
||||
|
||||
void ReadRequest();
|
||||
void SendTextAnswer();
|
||||
void SendBinaryAnswer();
|
||||
void SendAnswer();
|
||||
|
||||
void PrintEnv();
|
||||
|
||||
void SetEnv(const char * & env, const char * name);
|
||||
void ReadEnvVariables();
|
||||
void ReadGetPostVars();
|
||||
@@ -151,12 +152,20 @@ private:
|
||||
void CheckKonqueror();
|
||||
void CheckRequestMethod();
|
||||
void CheckFCGIRole();
|
||||
void CheckSSL();
|
||||
void SetSubdomain();
|
||||
|
||||
void PrepareSessionCookie();
|
||||
void AddDebugInfo(std::wstring & out);
|
||||
void FilterCompressSend(bool compressing, int compress_encoding, const std::wstring & source_ref);
|
||||
bool SendHeadersStaticCreateResource();
|
||||
void SendHeadersStatic();
|
||||
void SendHeaderContentType();
|
||||
void SendHeadersForbidden();
|
||||
void SendHeadersRedirect();
|
||||
void SendHeadersSendFile();
|
||||
void SendHeadersCompression(int compress_encoding);
|
||||
void SendHeadersNormal(Header header);
|
||||
void SendHeaders(bool compressing, int compress_encoding, Header header);
|
||||
int SelectDeflateVersion();
|
||||
void SelectCompression(size_t source_len, bool & compression_allowed, int & compression_encoding);
|
||||
|
||||
@@ -2,14 +2,14 @@
|
||||
* This file is a part of Winix
|
||||
* and is not publicly distributed
|
||||
*
|
||||
* Copyright (c) 2010, Tomasz Sowa
|
||||
* Copyright (c) 2010-2011, Tomasz Sowa
|
||||
* All rights reserved.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <errno.h>
|
||||
#include "basethread.h"
|
||||
#include "log.h"
|
||||
|
||||
|
||||
|
||||
BaseThread::BaseThread() : thread_signal(PTHREAD_COND_INITIALIZER)
|
||||
@@ -21,6 +21,7 @@ BaseThread::BaseThread() : thread_signal(PTHREAD_COND_INITIALIZER)
|
||||
}
|
||||
|
||||
|
||||
|
||||
void BaseThread::SetSynchro(Synchro * psynchro)
|
||||
{
|
||||
synchro = psynchro;
|
||||
@@ -34,6 +35,12 @@ void BaseThread::Mode(int mode)
|
||||
}
|
||||
|
||||
|
||||
pthread_t BaseThread::ThreadId()
|
||||
{
|
||||
return thread_id;
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool BaseThread::Lock()
|
||||
{
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* This file is a part of Winix
|
||||
* and is not publicly distributed
|
||||
*
|
||||
* Copyright (c) 2010, Tomasz Sowa
|
||||
* Copyright (c) 2010-2012, Tomasz Sowa
|
||||
* All rights reserved.
|
||||
*
|
||||
*/
|
||||
@@ -36,20 +36,19 @@ public:
|
||||
// starting the second thread
|
||||
bool StartThread();
|
||||
|
||||
|
||||
// virtual methods which should/can be inherited by your class
|
||||
// the methods will be called from the other thread
|
||||
|
||||
// wake up the second thread
|
||||
// (if it waits for the signal)
|
||||
// you should use it with: synchro->Lock() and Unlock()
|
||||
// if the thread doesn't wait on a signal then nothing is done
|
||||
void WakeUpThread();
|
||||
virtual void WakeUpThread();
|
||||
|
||||
// waiting until the thread exits
|
||||
// you should call WakeUpThread() before
|
||||
void WaitForThread();
|
||||
|
||||
|
||||
|
||||
// virtual methods which should/can be inherited by your class
|
||||
// the methods will be called from the other thread
|
||||
virtual void WaitForThread();
|
||||
|
||||
// initialize the thread
|
||||
// (global objects are locked)
|
||||
@@ -63,6 +62,11 @@ public:
|
||||
// it's called only if Init() returned true
|
||||
virtual void Uninit() {}
|
||||
|
||||
// returns the thread id
|
||||
// this identifier is set by StartThread() metdhod
|
||||
pthread_t ThreadId();
|
||||
|
||||
|
||||
|
||||
protected:
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* This file is a part of Winix
|
||||
* and is not publicly distributed
|
||||
*
|
||||
* Copyright (c) 2008-2011, Tomasz Sowa
|
||||
* Copyright (c) 2008-2012, Tomasz Sowa
|
||||
* All rights reserved.
|
||||
*
|
||||
*/
|
||||
@@ -15,7 +15,8 @@
|
||||
|
||||
Compress::Compress()
|
||||
{
|
||||
buffer = 0;
|
||||
buffer_in = 0;
|
||||
buffer_out = 0;
|
||||
buffer_max_len = 65536; // 64KB
|
||||
ready_for_compress = false;
|
||||
compress_level = 6;
|
||||
@@ -27,8 +28,8 @@ Compress::Compress()
|
||||
|
||||
Compress::~Compress()
|
||||
{
|
||||
if( buffer )
|
||||
delete [] buffer;
|
||||
delete [] buffer_in;
|
||||
delete [] buffer_out;
|
||||
|
||||
if( raw_deflate_inited )
|
||||
deflateEnd(&strm_raw_deflate);
|
||||
@@ -43,17 +44,23 @@ Compress::~Compress()
|
||||
|
||||
bool Compress::AllocateMemory()
|
||||
{
|
||||
if( buffer )
|
||||
delete [] buffer;
|
||||
if( buffer_in )
|
||||
delete [] buffer_in;
|
||||
|
||||
if( buffer_out )
|
||||
delete [] buffer_out;
|
||||
|
||||
buffer_in = 0;
|
||||
buffer_out = 0;
|
||||
|
||||
try
|
||||
{
|
||||
buffer = new char[buffer_max_len];
|
||||
buffer_in = new char[buffer_max_len];
|
||||
buffer_out = new char[buffer_max_len];
|
||||
}
|
||||
catch(const std::bad_alloc &)
|
||||
{
|
||||
log << log1 << "Compress: can't allocate memory" << logend;
|
||||
buffer = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -133,9 +140,8 @@ int Compress::Init(int compress_level_)
|
||||
{
|
||||
compress_level = compress_level_;
|
||||
|
||||
if( buffer == 0 )
|
||||
if( !AllocateMemory() )
|
||||
return 1;
|
||||
if( !AllocateMemory() )
|
||||
return 1;
|
||||
|
||||
if( InitRawDeflate() && InitDeflate() && InitGzip() )
|
||||
ready_for_compress = true;
|
||||
@@ -163,7 +169,69 @@ size_t have;
|
||||
do
|
||||
{
|
||||
strm.avail_out = buffer_max_len;
|
||||
strm.next_out = (Bytef*)buffer;
|
||||
strm.next_out = (Bytef*)buffer_out;
|
||||
ret = deflate(&strm, flush);
|
||||
|
||||
if( ret == Z_STREAM_ERROR || ret == Z_BUF_ERROR )
|
||||
{
|
||||
log << log1 << "Compress: problem with deflate()" << logend;
|
||||
return 2;
|
||||
}
|
||||
|
||||
have = buffer_max_len - strm.avail_out;
|
||||
last_out_size += have;
|
||||
FCGX_PutStr(buffer_out, have, out_stream);
|
||||
}
|
||||
while( strm.avail_out == 0 );
|
||||
|
||||
if( strm.avail_in != 0 )
|
||||
{
|
||||
log << log1 << "Compress: problem with deflate() - not all input is used" << logend;
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
while( flush != Z_FINISH );
|
||||
|
||||
|
||||
if( ret != Z_STREAM_END )
|
||||
{
|
||||
log << log1 << "Compress: problem with deflate() - stream not complete" << logend;
|
||||
return 2;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void Compress::CopyToInputBuffer(BinaryPage::const_iterator & i, size_t len)
|
||||
{
|
||||
for(size_t a=0 ; a<len ; ++a, ++i)
|
||||
buffer_in[a] = *i;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// new way
|
||||
int Compress::MakeCompress(z_stream & strm, const BinaryPage & page, BinaryPage & out, int encoding)
|
||||
{
|
||||
int ret, flush;
|
||||
size_t have;
|
||||
BinaryPage::const_iterator i = page.begin();
|
||||
|
||||
size_t source_len = page.size();
|
||||
|
||||
do
|
||||
{
|
||||
strm.avail_in = (source_len > buffer_max_len) ? buffer_max_len : source_len;
|
||||
source_len -= strm.avail_in;
|
||||
flush = (source_len == 0) ? Z_FINISH : Z_NO_FLUSH;
|
||||
strm.next_in = (Bytef*)buffer_in;
|
||||
CopyToInputBuffer(i, strm.avail_in);
|
||||
|
||||
do
|
||||
{
|
||||
strm.avail_out = buffer_max_len;
|
||||
strm.next_out = (Bytef*)buffer_out;
|
||||
ret = deflate(&strm, flush);
|
||||
|
||||
if( ret == Z_STREAM_ERROR || ret == Z_BUF_ERROR )
|
||||
@@ -174,7 +242,7 @@ size_t have;
|
||||
|
||||
have = buffer_max_len - strm.avail_out;
|
||||
last_out_size += have;
|
||||
FCGX_PutStr(buffer, have, out_stream);
|
||||
out.write(buffer_out, have);
|
||||
}
|
||||
while( strm.avail_out == 0 );
|
||||
|
||||
@@ -289,3 +357,36 @@ return ret;
|
||||
|
||||
|
||||
|
||||
/*
|
||||
return:
|
||||
0 - ok;
|
||||
1 - can't allocate memory
|
||||
2 - error during compressing
|
||||
3 - not inited (use Init() first)
|
||||
100 - unknown
|
||||
*/
|
||||
int Compress::Compressing(const BinaryPage & in, BinaryPage & out, int encoding)
|
||||
{
|
||||
int ret;
|
||||
z_stream * pstrm;
|
||||
|
||||
last_out_size = 0;
|
||||
out.clear();
|
||||
|
||||
if( !ready_for_compress )
|
||||
{
|
||||
log << log1 << "Compress: not ready yet" << logend;
|
||||
return 3;
|
||||
}
|
||||
|
||||
if( in.empty() )
|
||||
return 0;
|
||||
|
||||
pstrm = SelectStream(encoding);
|
||||
ret = MakeCompress(*pstrm, in, out, encoding);
|
||||
ResetStream(pstrm, encoding);
|
||||
PutLog(in.size(), encoding);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* This file is a part of Winix
|
||||
* and is not publicly distributed
|
||||
*
|
||||
* Copyright (c) 2008-2011, Tomasz Sowa
|
||||
* Copyright (c) 2008-2012, Tomasz Sowa
|
||||
* All rights reserved.
|
||||
*
|
||||
*/
|
||||
@@ -13,6 +13,8 @@
|
||||
#include <cstring>
|
||||
#include <fcgiapp.h>
|
||||
#include <zlib.h>
|
||||
#include "requesttypes.h"
|
||||
|
||||
|
||||
|
||||
class Compress
|
||||
@@ -33,7 +35,8 @@ public:
|
||||
2 - gzip
|
||||
*/
|
||||
int CompressAndPut(const char * source, size_t source_len, FCGX_Stream * out_stream, int encoding = 2);
|
||||
size_t last_out_size;
|
||||
int Compressing(const BinaryPage & in, BinaryPage & out, int encoding = 2);
|
||||
|
||||
|
||||
private:
|
||||
|
||||
@@ -43,13 +46,20 @@ private:
|
||||
bool InitGzip();
|
||||
|
||||
int MakeCompress(z_stream & strm, const char * source, size_t source_len, FCGX_Stream * out_stream, int encoding);
|
||||
int MakeCompress(z_stream & strm, const BinaryPage & page, BinaryPage & out, int encoding);
|
||||
z_stream * SelectStream(int encoding);
|
||||
void ResetStream(z_stream * pstrm, int encoding);
|
||||
void PutLog(size_t source_len, int encoding);
|
||||
void CopyToInputBuffer(BinaryPage::const_iterator & i, size_t len);
|
||||
|
||||
int compress_level;
|
||||
size_t buffer_max_len;
|
||||
char * buffer;
|
||||
|
||||
// size of the last compressed page
|
||||
size_t last_out_size;
|
||||
|
||||
char * buffer_in;
|
||||
char * buffer_out;
|
||||
z_stream strm_raw_deflate, strm_deflate, strm_gzip;
|
||||
bool raw_deflate_inited, deflate_inited, gzip_inited;
|
||||
bool ready_for_compress;
|
||||
|
||||
351
core/config.cpp
351
core/config.cpp
@@ -2,7 +2,7 @@
|
||||
* This file is a part of Winix
|
||||
* and is not publicly distributed
|
||||
*
|
||||
* Copyright (c) 2008-2011, Tomasz Sowa
|
||||
* Copyright (c) 2008-2012, Tomasz Sowa
|
||||
* All rights reserved.
|
||||
*
|
||||
*/
|
||||
@@ -31,18 +31,22 @@ void Config::ShowError()
|
||||
|
||||
switch( parser.status )
|
||||
{
|
||||
case ConfParser::ok:
|
||||
case PT::SpaceParser::no_space:
|
||||
log << log2 << "Config: space not set" << logend;
|
||||
break;
|
||||
|
||||
case PT::SpaceParser::ok:
|
||||
log << log2 << "Config: syntax ok" << logend;
|
||||
break;
|
||||
|
||||
case ConfParser::cant_open_file:
|
||||
case PT::SpaceParser::cant_open_file:
|
||||
if( errors_to_stdout )
|
||||
std::cout << "Config: cant open a config file: " << config_file << std::endl;
|
||||
|
||||
log << log1 << "Config: cant open a config file: " << config_file << logend;
|
||||
break;
|
||||
|
||||
case ConfParser::syntax_error:
|
||||
case PT::SpaceParser::syntax_error:
|
||||
if( errors_to_stdout )
|
||||
std::cout << "Config: syntax error, line: " << parser.line << std::endl;
|
||||
|
||||
@@ -70,10 +74,11 @@ bool Config::ReadConfig(bool errors_to_stdout_, bool stdout_is_closed)
|
||||
|
||||
parser.SplitSingle(true);
|
||||
parser.UTF8(true); // config is always read in UTF-8
|
||||
ConfParser::Status status = parser.Parse( config_file );
|
||||
parser.SetSpace(space);
|
||||
|
||||
PT::SpaceParser::Status status = parser.Parse(config_file);
|
||||
|
||||
if( status == ConfParser::ok )
|
||||
if( status == PT::SpaceParser::ok )
|
||||
{
|
||||
AssignValues(stdout_is_closed);
|
||||
SetAdditionalVariables();
|
||||
@@ -91,117 +96,168 @@ bool Config::ReadConfig(bool errors_to_stdout_, bool stdout_is_closed)
|
||||
|
||||
void Config::AssignValues(bool stdout_is_closed)
|
||||
{
|
||||
demonize = Bool(L"demonize", true);
|
||||
demonize = Bool(L"demonize", true);
|
||||
|
||||
user = AText(L"user");
|
||||
group = AText(L"group");
|
||||
additional_groups = Bool(L"additional_groups", true);
|
||||
user = AText(L"user");
|
||||
group = AText(L"group");
|
||||
additional_groups = Bool(L"additional_groups", true);
|
||||
|
||||
log_file = AText(L"log_file");
|
||||
log_notify_file = AText(L"log_notify_file");
|
||||
log_delimiter = Text(L"log_delimiter", L"---------------------------------------------------------------------------------");
|
||||
fcgi_socket = AText(L"fcgi_socket");
|
||||
fcgi_socket_chmod = Int(L"fcgi_socket_chmod", 0770);
|
||||
fcgi_socket_user = AText(L"fcgi_socket_user");
|
||||
fcgi_socket_group = AText(L"fcgi_socket_group");
|
||||
log_level = Int(L"log_level", 1);
|
||||
log_request = Int(L"log_request", 1);
|
||||
log_save_each_line = Bool(L"log_save_each_line", false);
|
||||
log_stdout = Bool(L"log_stdout", false);
|
||||
log_db_query = Bool(L"log_db_query", false);
|
||||
log_plugin_call = Bool(L"log_plugin_call", false);
|
||||
log_post_value_size = Size(L"log_post_value_size", 80);
|
||||
log_file = AText(L"log_file");
|
||||
log_notify_file = AText(L"log_notify_file");
|
||||
log_delimiter = Text(L"log_delimiter", L"---------------------------------------------------------------------------------");
|
||||
fcgi_socket = AText(L"fcgi_socket");
|
||||
fcgi_socket_chmod = Int(L"fcgi_socket_chmod", 0770);
|
||||
fcgi_socket_user = AText(L"fcgi_socket_user");
|
||||
fcgi_socket_group = AText(L"fcgi_socket_group");
|
||||
log_level = Int(L"log_level", 1);
|
||||
log_request = Int(L"log_request", 1);
|
||||
log_save_each_line = Bool(L"log_save_each_line", false);
|
||||
log_time_zone_id = Size(L"log_time_zone_id", 34);
|
||||
log_stdout = Bool(L"log_stdout", false);
|
||||
log_db_query = Bool(L"log_db_query", false);
|
||||
log_plugin_call = Bool(L"log_plugin_call", false);
|
||||
log_post_value_size = Size(L"log_post_value_size", 80);
|
||||
|
||||
post_file_max = Size(L"post_file_max", 8388608); // 8 MB
|
||||
upload_dir = Text(L"upload_dir");
|
||||
upload_dirs_chmod = Int(L"upload_dirs_chmod", 0750);
|
||||
upload_files_chmod = Int(L"upload_files_chmod", 0640);
|
||||
post_file_max = Size(L"post_file_max", 8388608); // 8 MB
|
||||
|
||||
upload_dir = Text(L"upload_dir");
|
||||
common_dir = Text(L"common_dir");
|
||||
NoLastSlash(upload_dir);
|
||||
NoLastSlash(common_dir);
|
||||
|
||||
upload_dirs_chmod = Int(L"upload_dirs_chmod", 0750);
|
||||
upload_files_chmod = Int(L"upload_files_chmod", 0640);
|
||||
ListText(L"static_dirs", static_dirs);
|
||||
dont_use_static_dirs = Bool(L"dont_use_static_dirs", false);
|
||||
create_thumb = Bool(L"create_thumb", true);
|
||||
thumb_mode = Int(L"thumb_mode", 2);
|
||||
thumb_cx = Size(L"thumb_cx", 150);
|
||||
thumb_cy = Size(L"thumb_cy", 150);
|
||||
convert_cmd = Text(L"convert_cmd", L"/usr/local/bin/convert");
|
||||
dont_use_static_dirs = Bool(L"dont_use_static_dirs", false);
|
||||
create_thumb = Bool(L"create_thumb", true);
|
||||
thumb_mode = Int(L"thumb_mode", 2);
|
||||
thumb_cx = Size(L"thumb_cx", 150);
|
||||
thumb_cy = Size(L"thumb_cy", 150);
|
||||
thumb_quality = Int(L"thumb_quality", 92);
|
||||
image_resize = Bool(L"image_resize", true);
|
||||
image_mode = Int(L"image_mode", 6);
|
||||
image_cx = Size(L"image_cx", 1000);
|
||||
image_cy = Size(L"image_cy", 800);
|
||||
image_quality = Int(L"image_quality", 92);
|
||||
convert_cmd = Text(L"convert_cmd", L"/usr/local/bin/convert");
|
||||
|
||||
templates_dir = Text(L"templates_dir");
|
||||
templates_dir_default = Text(L"templates_dir_default");
|
||||
txt_templates_dir = Text(L"txt_templates_dir");
|
||||
templates_dir = Text(L"templates_dir");
|
||||
templates_dir_default = Text(L"templates_dir_default");
|
||||
txt_templates_dir = Text(L"txt_templates_dir");
|
||||
txt_templates_dir_default = Text(L"txt_templates_dir_default");
|
||||
templates_fun_prefix = Text(L"templates_fun_prefix", L"fun_");
|
||||
templates_fun_postfix = Text(L"templates_fun_postfix", L".html");
|
||||
templates_index = Text(L"templates_index", L"index.html");
|
||||
templates_fun_prefix = Text(L"templates_fun_prefix", L"fun_");
|
||||
templates_fun_postfix = Text(L"templates_fun_postfix", L".html");
|
||||
templates_index = Text(L"templates_index", L"index.html");
|
||||
template_only_root_use_template_fun = Bool(L"template_only_root_use_template_fun", false);
|
||||
|
||||
http_session_id_name = AText(L"http_session_id_name");
|
||||
db_database = AText(L"db_database");
|
||||
db_user = AText(L"db_user");
|
||||
db_pass = AText(L"db_pass");
|
||||
item_url_empty = Text(L"item_url_empty");
|
||||
http_session_id_name = AText(L"http_session_id_name");
|
||||
db_database = AText(L"db_database");
|
||||
db_user = AText(L"db_user");
|
||||
db_pass = AText(L"db_pass");
|
||||
item_url_empty = Text(L"item_url_empty");
|
||||
|
||||
base_server = Text(L"base_server");
|
||||
base_url = Text(L"base_url");
|
||||
base_url_static = Text(L"base_url_static");
|
||||
base_url_common = Text(L"base_url_common");
|
||||
url_proto = Text(L"url_proto", L"http://");
|
||||
url_ssl_proto = Text(L"url_ssl_proto", L"https://");
|
||||
|
||||
use_ssl = Bool(L"use_ssl", false);
|
||||
use_ssl_static = Bool(L"use_ssl_static", false);
|
||||
use_ssl_common = Bool(L"use_ssl_common", false);
|
||||
use_ssl_only_for_logged_users = Bool(L"use_ssl_only_for_logged_users", true);
|
||||
use_ssl_redirect_code = Int(L"use_ssl_redirect_code", 303);
|
||||
|
||||
base_url = Text(L"base_url");
|
||||
base_url_static = Text(L"base_url_static");
|
||||
base_url_common = Text(L"base_url_common");
|
||||
|
||||
base_url_redirect = Bool(L"base_url_redirect", false);
|
||||
base_url_redirect_code = Int(L"base_url_redirect_code", 301);
|
||||
|
||||
NoLastSlash(base_server);
|
||||
NoLastSlash(base_url);
|
||||
NoLastSlash(base_url_static);
|
||||
NoLastSlash(base_url_common);
|
||||
|
||||
priv_no_user = Text(L"priv_no_user", L"-- no user --");
|
||||
priv_no_group = Text(L"priv_no_group", L"-- no group --");
|
||||
priv_no_user = Text(L"priv_no_user", L"-- no user --");
|
||||
priv_no_group = Text(L"priv_no_group", L"-- no group --");
|
||||
|
||||
session_max_idle = Int(L"session_max_idle", 10800); // 3h
|
||||
session_max_idle = Int(L"session_max_idle", 10800); // 3h
|
||||
session_remember_max_idle = Int(L"session_remember_max_idle", 16070400); // 3 months
|
||||
session_file = AText(L"session_file");
|
||||
session_max = Size(L"session_max", 1000000);
|
||||
session_file = AText(L"session_file");
|
||||
session_max = Size(L"session_max", 1000000);
|
||||
|
||||
compression = Bool(L"compression", true);
|
||||
compression = Bool(L"compression", true);
|
||||
compression_page_min_size = Size(L"compression_page_min_size", 512);
|
||||
compression_encoding = Int(L"compression_encoding", 20);
|
||||
compression_encoding = Int(L"compression_encoding", 20);
|
||||
|
||||
html_filter = Bool(L"html_filter", true);
|
||||
html_filter_trim_white = Bool(L"html_filter_trim_white", true);
|
||||
html_filter_break_word = Int(L"html_filter_break_word", 60);
|
||||
html_filter_wrap_line = Int(L"html_filter_wrap_line", 110);
|
||||
html_filter_tabs = Size(L"html_filter_tabs", 2);
|
||||
html_filter = Bool(L"html_filter", true);
|
||||
html_filter_trim_white = Bool(L"html_filter_trim_white", true);
|
||||
html_filter_break_word = Int(L"html_filter_break_word", 60);
|
||||
html_filter_wrap_line = Int(L"html_filter_wrap_line", 110);
|
||||
html_filter_tabs = Size(L"html_filter_tabs", 2);
|
||||
html_filter_orphans = Bool(L"html_filter_orphans", true);
|
||||
html_filter_orphans_mode_str = AText(L"html_filter_orphans_mode_str", L"nbsp");
|
||||
html_filter_orphans_mode_str = Text(L"html_filter_orphans_mode_str", L"nbsp");
|
||||
|
||||
locale_dir = Text(L"locale_dir");
|
||||
locale_dir_default = Text(L"locale_dir_default");
|
||||
locale_default = Text(L"locale_default");
|
||||
locale_dir = Text(L"locale_dir");
|
||||
locale_dir_default = Text(L"locale_dir_default");
|
||||
locale_max_id = Size(L"locale_max_id", 100);
|
||||
locale_default_id = Size(L"locale_default_id", 0);
|
||||
ListText(L"locale_files", locale_files);
|
||||
|
||||
title_separator = Text(L"title_separator", L" / ");
|
||||
title_separator = Text(L"title_separator", L" / ");
|
||||
|
||||
http_header_send_file = Text(L"http_header_send_file", L"X-LIGHTTPD-send-file");
|
||||
debug_info = Bool(L"debug_info", false);
|
||||
http_header_send_file = Text(L"http_header_send_file", L"X-LIGHTTPD-send-file");
|
||||
debug_info = Bool(L"debug_info", false);
|
||||
|
||||
editors_html_safe_mode = Bool(L"editors_html_safe_mode", true);
|
||||
editors_html_safe_mode = Bool(L"editors_html_safe_mode", true);
|
||||
editors_html_safe_mode_skip_root = Bool(L"editors_html_safe_mode_skip_root", true);
|
||||
|
||||
plugins_dir = Text(L"plugins_dir", L"/usr/local/winix/plugins");
|
||||
plugins_dir = Text(L"plugins_dir", L"/usr/local/winix/plugins");
|
||||
NoLastSlash(plugins_dir);
|
||||
ListText(L"plugins", plugin_file);
|
||||
|
||||
time_zone_offset = Int(L"time_zone_offset", 0);
|
||||
time_zone_offset_guest = Int(L"time_zone_offset_guest", 0);
|
||||
utf8 = Bool(L"utf8", true);
|
||||
symlinks_follow_max = Size(L"symlinks_follow_max", 20);
|
||||
|
||||
utf8 = Bool(L"utf8", true);
|
||||
symlinks_follow_max = Size(L"symlinks_follow_max", 20);
|
||||
ticket_form_prefix = Text(L"ticket_form_prefix", L"ticketparam");
|
||||
|
||||
ticket_form_prefix = Text(L"ticket_form_prefix", L"ticketparam");
|
||||
pass_min_size = Size(L"pass_min_size", 5);
|
||||
pass_type = Int(L"pass_type", 12);
|
||||
pass_hash_use_salt = Bool(L"pass_hash_use_salt", false);
|
||||
pass_hash_salt = Text(L"pass_hash_salt");
|
||||
pass_use_rsa = Bool(L"pass_use_rsa", false);
|
||||
pass_rsa_private_key = Text(L"pass_rsa_private_key");
|
||||
|
||||
pass_min_size = Size(L"pass_min_size", 5);
|
||||
pass_type = Int(L"pass_type", 12);
|
||||
pass_hash_use_salt = Bool(L"pass_hash_use_salt", false);
|
||||
pass_hash_salt = Text(L"pass_hash_salt");
|
||||
pass_use_rsa = Bool(L"pass_use_rsa", false);
|
||||
pass_rsa_private_key = Text(L"pass_rsa_private_key");
|
||||
opensll_path = Text(L"opensll_path", L"/usr/bin/openssl");
|
||||
|
||||
opensll_path = Text(L"opensll_path", L"/usr/bin/openssl");
|
||||
pattern_cacher_when_delete = Size(L"pattern_cacher_when_delete", 130);
|
||||
pattern_cacher_how_many_delete = Size(L"pattern_cacher_how_many_delete", 30);
|
||||
|
||||
content_type_header = Int(L"content_type_header", 0);
|
||||
umask = Int(L"umask", 0222);
|
||||
|
||||
ezc_max_elements = Size(L"ezc_max_elements", 50000);
|
||||
ezc_max_loop_elements = Size(L"ezc_max_loop_elements", 5000);
|
||||
|
||||
account_need_email_verification = Bool(L"account_need_email_verification", true);
|
||||
reset_password_code_expiration_time = Long(L"reset_password_code_expiration_time", 86400);
|
||||
|
||||
time_zone_default_id = Size(L"time_zone_default_id", 34);
|
||||
time_zone_max_id = Size(L"time_zone_max_id", 130);
|
||||
|
||||
etc_dir = Text(L"etc_dir", L"");
|
||||
time_zones_file = Text(L"time_zones_file", L"time_zones.conf");
|
||||
|
||||
use_ban_list = Bool(L"use_ban_list", true);
|
||||
ban_list_soft_max_size = Size(L"ban_list_soft_max_size", 50000);
|
||||
ban_list_max_size = Size(L"ban_list_max_size", 51000);
|
||||
ban_level_1_delay = Size(L"ban_level_1_delay", 1800);
|
||||
ban_level_2_delay = Size(L"ban_level_2_delay", 86400);
|
||||
ban_level_3_delay = Size(L"ban_level_3_delay", 604800);
|
||||
|
||||
incorrect_login_min_time_between_get_post = Size(L"incorrect_login_min_time_between_get_post", 2);
|
||||
incorrect_login_captcha_treshold = Size(L"incorrect_login_captcha_treshold", 3);
|
||||
incorrect_login_cannot_login_mode = Int(L"incorrect_login_cannot_login_mode", 0);
|
||||
incorrect_login_cannot_login_treshold = Size(L"incorrect_login_cannot_login_treshold", 20);
|
||||
incorrect_login_cannot_login_delay = Size(L"incorrect_login_cannot_login_delay", 1800);
|
||||
}
|
||||
|
||||
|
||||
@@ -210,9 +266,7 @@ void Config::AssignValues(bool stdout_is_closed)
|
||||
|
||||
void Config::SetAdditionalVariables()
|
||||
{
|
||||
SetHttpHost(base_url, base_url_http_host);
|
||||
|
||||
if( html_filter_orphans_mode_str == "160" )
|
||||
if( html_filter_orphans_mode_str == L"160" )
|
||||
html_filter_orphans_mode = HTMLFilter::orphan_160space;
|
||||
else
|
||||
html_filter_orphans_mode = HTMLFilter::orphan_nbsp;
|
||||
@@ -220,46 +274,27 @@ void Config::SetAdditionalVariables()
|
||||
for(size_t i=0 ; i<static_dirs.size() ; ++i)
|
||||
NoLastSlash(static_dirs[i]);
|
||||
|
||||
CheckLocale();
|
||||
CheckPasswd();
|
||||
}
|
||||
|
||||
if( content_type_header < 0 || content_type_header > 2 )
|
||||
content_type_header = 0;
|
||||
|
||||
|
||||
void Config::CheckLocale()
|
||||
{
|
||||
bool found = false;
|
||||
if( locale_default_id > locale_max_id )
|
||||
locale_default_id = locale_max_id;
|
||||
|
||||
if( locale_files.empty() )
|
||||
locale_files.push_back(L"en");
|
||||
|
||||
if( locale_default.empty() )
|
||||
locale_default = locale_files[0];
|
||||
|
||||
for(size_t i=0 ; i<locale_files.size() ; ++i)
|
||||
{
|
||||
if( locale_files[i] == locale_default )
|
||||
{
|
||||
locale_default_index = i;
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if( !found )
|
||||
{
|
||||
// we have at least one item
|
||||
locale_default = locale_files[0];
|
||||
locale_default_index = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void Config::CheckPasswd()
|
||||
{
|
||||
switch(pass_type)
|
||||
{
|
||||
case WINIX_CRYPT_HASH_PLAIN:
|
||||
case WINIX_CRYPT_HASH_NONE:
|
||||
case WINIX_CRYPT_HASH_MD4:
|
||||
case WINIX_CRYPT_HASH_MD5:
|
||||
case WINIX_CRYPT_HASH_SHA1:
|
||||
@@ -275,130 +310,132 @@ void Config::CheckPasswd()
|
||||
}
|
||||
|
||||
|
||||
void Config::SetHttpHost(const std::wstring & in, std::wstring & out)
|
||||
{
|
||||
const char http[] = "http://";
|
||||
const char https[] = "https://";
|
||||
size_t http_len = sizeof(http) / sizeof(char) - 1;
|
||||
size_t https_len = sizeof(https) / sizeof(char) - 1;
|
||||
|
||||
if( IsSubString(http, in.c_str()) )
|
||||
out = in.substr(http_len);
|
||||
else
|
||||
if( IsSubString(https, in.c_str()) )
|
||||
out = in.substr(https_len);
|
||||
else
|
||||
out.clear(); // if empty the RequestController::BaseUrlRedirect() returns false and no redirecting will be done
|
||||
|
||||
std::wstring & Config::Text(const wchar_t * name)
|
||||
{
|
||||
return space.Text(name);
|
||||
}
|
||||
|
||||
|
||||
std::wstring Config::Text(const wchar_t * name)
|
||||
std::wstring & Config::Text(const wchar_t * name, const wchar_t * def)
|
||||
{
|
||||
return parser.Text(name);
|
||||
return space.Text(name, def);
|
||||
}
|
||||
|
||||
|
||||
std::wstring Config::Text(const wchar_t * name, const wchar_t * def)
|
||||
std::wstring & Config::Text(const std::wstring & name, const wchar_t * def)
|
||||
{
|
||||
return parser.Text(name, def);
|
||||
return space.Text(name, def);
|
||||
}
|
||||
|
||||
|
||||
std::wstring Config::Text(const std::wstring & name, const std::wstring & def)
|
||||
std::string & Config::AText(const wchar_t * name)
|
||||
{
|
||||
return parser.Text(name, def);
|
||||
return space.AText(name);
|
||||
}
|
||||
|
||||
|
||||
std::string Config::AText(const wchar_t * name)
|
||||
std::string & Config::AText(const wchar_t * name, const char * def)
|
||||
{
|
||||
return parser.AText(name);
|
||||
return space.AText(name, def);
|
||||
}
|
||||
|
||||
|
||||
std::string Config::AText(const wchar_t * name, const wchar_t * def)
|
||||
std::string & Config::AText(const std::wstring & name, const char * def)
|
||||
{
|
||||
return parser.AText(name, def);
|
||||
}
|
||||
|
||||
|
||||
std::string Config::AText(const std::wstring & name, const std::wstring & def)
|
||||
{
|
||||
return parser.AText(name, def);
|
||||
return space.AText(name, def);
|
||||
}
|
||||
|
||||
|
||||
|
||||
int Config::Int(const wchar_t * name)
|
||||
{
|
||||
return parser.Int(name);
|
||||
return space.Int(name);
|
||||
}
|
||||
|
||||
|
||||
int Config::Int(const wchar_t * name, int def)
|
||||
{
|
||||
return parser.Int(name, def);
|
||||
return space.Int(name, def);
|
||||
}
|
||||
|
||||
|
||||
int Config::Int(const std::wstring & name, int def)
|
||||
{
|
||||
return parser.Int(name, def);
|
||||
return space.Int(name, def);
|
||||
}
|
||||
|
||||
|
||||
long Config::Long(const wchar_t * name)
|
||||
{
|
||||
return space.Long(name);
|
||||
}
|
||||
|
||||
long Config::Long(const wchar_t * name, long def)
|
||||
{
|
||||
return space.Long(name, def);
|
||||
}
|
||||
|
||||
long Config::Long(const std::wstring & name, long def)
|
||||
{
|
||||
return space.Long(name, def);
|
||||
}
|
||||
|
||||
|
||||
|
||||
size_t Config::Size(const wchar_t * name)
|
||||
{
|
||||
return parser.Size(name);
|
||||
return space.Size(name);
|
||||
}
|
||||
|
||||
|
||||
size_t Config::Size(const wchar_t * name, size_t def)
|
||||
{
|
||||
return parser.Size(name, def);
|
||||
return space.Size(name, def);
|
||||
}
|
||||
|
||||
|
||||
size_t Config::Size(const std::wstring & name, size_t def)
|
||||
{
|
||||
return parser.Size(name, def);
|
||||
return space.Size(name, def);
|
||||
}
|
||||
|
||||
|
||||
bool Config::Bool(const wchar_t * name)
|
||||
{
|
||||
return parser.Bool(name);
|
||||
return space.Bool(name);
|
||||
}
|
||||
|
||||
|
||||
bool Config::Bool(const wchar_t * name, bool def)
|
||||
{
|
||||
return parser.Bool(name, def);
|
||||
return space.Bool(name, def);
|
||||
}
|
||||
|
||||
|
||||
bool Config::Bool(const std::wstring & name, bool def)
|
||||
{
|
||||
return parser.Bool(name, def);
|
||||
return space.Bool(name, def);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void Config::ListText(const wchar_t * name, std::vector<std::wstring> & list)
|
||||
bool Config::ListText(const wchar_t * name, std::vector<std::wstring> & list)
|
||||
{
|
||||
parser.ListText(name, list);
|
||||
return space.ListText(name, list);
|
||||
}
|
||||
|
||||
|
||||
void Config::ListText(const std::wstring & name, std::vector<std::wstring> & list)
|
||||
bool Config::ListText(const std::wstring & name, std::vector<std::wstring> & list)
|
||||
{
|
||||
parser.ListText(name, list);
|
||||
return space.ListText(name, list);
|
||||
}
|
||||
|
||||
|
||||
void Config::Print(std::ostream & out)
|
||||
void Config::Print(std::wostream & out)
|
||||
{
|
||||
parser.Print(out);
|
||||
space.Serialize(out);
|
||||
}
|
||||
|
||||
|
||||
|
||||
317
core/config.h
317
core/config.h
@@ -2,7 +2,7 @@
|
||||
* This file is a part of Winix
|
||||
* and is not publicly distributed
|
||||
*
|
||||
* Copyright (c) 2008-2011, Tomasz Sowa
|
||||
* Copyright (c) 2008-2012, Tomasz Sowa
|
||||
* All rights reserved.
|
||||
*
|
||||
*/
|
||||
@@ -11,12 +11,13 @@
|
||||
#define headerfile_winix_core_config
|
||||
|
||||
#include <string>
|
||||
#include "confparser.h"
|
||||
#include "space/spaceparser.h"
|
||||
#include "htmlfilter.h"
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
class Config
|
||||
{
|
||||
public:
|
||||
@@ -64,6 +65,12 @@ public:
|
||||
// default: false
|
||||
bool log_save_each_line;
|
||||
|
||||
// time zone identifier used in log messages
|
||||
// this affects only the first line of logs (where there is IP address, request method etc)
|
||||
// see time_zone_default_id below for more info
|
||||
// default: 34 (Coordinated Universal Time UTC+00:00)
|
||||
size_t log_time_zone_id;
|
||||
|
||||
// logging db queries
|
||||
// default: false
|
||||
bool log_db_query;
|
||||
@@ -119,11 +126,6 @@ public:
|
||||
|
||||
std::string http_session_id_name;
|
||||
|
||||
// when the HOST_HTTP environment variable doesn't point into 'base_url' (the part 'http://' and the last slash is removed)
|
||||
// the server will redirect into 'base_url' + 'REQUEST_URI'
|
||||
// it's useful when you want to redirect from 'mydomain.tld' into 'www.mydomain.tld' etc.
|
||||
bool base_url_redirect;
|
||||
|
||||
// string used in a place where is a user (or group) selected
|
||||
std::wstring priv_no_user;
|
||||
std::wstring priv_no_group;
|
||||
@@ -193,7 +195,7 @@ public:
|
||||
// orphans mode
|
||||
// either: "nbsp" or "160"
|
||||
// default: "nbsp"
|
||||
std::string html_filter_orphans_mode_str;
|
||||
std::wstring html_filter_orphans_mode_str;
|
||||
HTMLFilter::OrphanMode html_filter_orphans_mode;
|
||||
|
||||
// the url of a new empty item (if there is not the subject too)
|
||||
@@ -224,6 +226,14 @@ public:
|
||||
// so you can correct your mistake and then set this value to false
|
||||
bool dont_use_static_dirs;
|
||||
|
||||
// static common directory
|
||||
// this is a place where there are some common javascripts, images, css files
|
||||
// winix is allowed to read some files from there
|
||||
// for example ckeditor config, vim config and so on
|
||||
// winix read it as a ezc template and put it into database
|
||||
// default: empty
|
||||
std::wstring common_dir;
|
||||
|
||||
// chmod of newly created directories (under upload_dir)
|
||||
// default: 0750
|
||||
int upload_dirs_chmod;
|
||||
@@ -256,7 +266,36 @@ public:
|
||||
// default: 150
|
||||
size_t thumb_cy;
|
||||
|
||||
// the convert program
|
||||
// quality of thumbnails
|
||||
// from 0 (the worst) to 100 (the best)
|
||||
// more info: http://www.imagemagick.org/script/command-line-options.php?ImageMagick=p4jtel7557hovd34ui3tgb54h6#quality
|
||||
// default: 92
|
||||
int thumb_quality;
|
||||
|
||||
// resizing images
|
||||
// this not affects thumbnails
|
||||
// default: true
|
||||
bool image_resize;
|
||||
|
||||
// the mode of resizing an image
|
||||
// the same as 'thumb_mode' above
|
||||
// default: 6
|
||||
int image_mode;
|
||||
|
||||
// width of images
|
||||
// default: 1000
|
||||
size_t image_cx;
|
||||
|
||||
// height of images
|
||||
// default: 800
|
||||
size_t image_cy;
|
||||
|
||||
// quality of an image (the same as in thumbnails)
|
||||
// from 0 (the worst) to 100 (the best)
|
||||
// default: 92
|
||||
int image_quality;
|
||||
|
||||
// the convert program (ImageMagic) (for images and thumbnails)
|
||||
// default: /usr/local/bin/convert
|
||||
std::wstring convert_cmd;
|
||||
|
||||
@@ -270,24 +309,73 @@ public:
|
||||
// default: only one item: en
|
||||
std::vector<std::wstring> locale_files;
|
||||
|
||||
// default locale
|
||||
// default: the first item from locale_files
|
||||
std::wstring locale_default;
|
||||
// a maximum value of a locale identifier
|
||||
// default: 100 (maximum: 1000)
|
||||
// each locale files should have its own identifier (in "winix_locale_id" field)
|
||||
// from zero to this value
|
||||
size_t locale_max_id;
|
||||
|
||||
// default locale - index to locale_files
|
||||
// not available in config -- set automatically based on locale_default
|
||||
size_t locale_default_index;
|
||||
// locale for not logged users
|
||||
// or for newly created accounts
|
||||
// default: 0
|
||||
size_t locale_default_id;
|
||||
|
||||
// the main address of the server (e.g. someserver.com) (without the 'www' part etc)
|
||||
std::wstring base_server;
|
||||
// url protocol
|
||||
// default: http://
|
||||
std::wstring url_proto;
|
||||
|
||||
// the main address of the site (e.g. http://www.someserver.com)
|
||||
// url protocol when using SSL
|
||||
// default: https://
|
||||
std::wstring url_ssl_proto;
|
||||
|
||||
// enables SSL
|
||||
// it means this site should be accessed through SSL encrypted connection
|
||||
// default: false
|
||||
bool use_ssl;
|
||||
|
||||
// enables SSL for static content
|
||||
// used mainly in templates, look at doc_base_url_static ezc function
|
||||
// default: false
|
||||
bool use_ssl_static;
|
||||
|
||||
// enables SSL for common content
|
||||
// used mainly in templates, look at doc_base_url_common ezc function
|
||||
// default: false
|
||||
bool use_ssl_common;
|
||||
|
||||
// if SSL is enabled then if this is true the SSL will be used
|
||||
// only for logged users
|
||||
// default: true
|
||||
bool use_ssl_only_for_logged_users;
|
||||
|
||||
// if current connection is without SSL and should be made through SSL
|
||||
// or if is via SSL and should be done in plain text
|
||||
// then we make a redirect
|
||||
// default: 303
|
||||
int use_ssl_redirect_code;
|
||||
|
||||
// when the HOST_HTTP environment variable is not equal to 'base_url'
|
||||
// (the part 'http://' and the last slash is removed)
|
||||
// the server will redirect into base_url + 'REQUEST_URI'
|
||||
// it's useful when you want to redirect from 'mydomain.tld' into 'www.mydomain.tld' etc.
|
||||
// set this option to false if you have multiple subdomains
|
||||
// default: false
|
||||
bool base_url_redirect;
|
||||
|
||||
// the HTTP code used during the base redirect
|
||||
// default: 301
|
||||
int base_url_redirect_code;
|
||||
|
||||
// the main address of the site (e.g. www.someserver.com)
|
||||
// (without http:// prefix)
|
||||
std::wstring base_url;
|
||||
|
||||
// static content not authorized by winix
|
||||
// (e.g. static.someserver.com)
|
||||
std::wstring base_url_static;
|
||||
|
||||
// additional static server for common content (not authorized)
|
||||
// (e.g. common.someserver.com)
|
||||
std::wstring base_url_common;
|
||||
|
||||
// separator used in <title> html tag
|
||||
@@ -310,15 +398,6 @@ public:
|
||||
// (if true the html code for root is not filtered)
|
||||
bool editors_html_safe_mode_skip_root;
|
||||
|
||||
// temporarily we do not support time zones per user
|
||||
// there is one offset for all users
|
||||
// default: 0
|
||||
int time_zone_offset;
|
||||
|
||||
// time zone offset for guests (not logged users)
|
||||
// default: 0
|
||||
int time_zone_offset_guest;
|
||||
|
||||
// charset used in templates, locales, logs etc.
|
||||
// default: true (UTF-8)
|
||||
// if false it means 8-bit ASCII
|
||||
@@ -370,61 +449,187 @@ public:
|
||||
// !! once you set these keys don't change it any more (people wouldn't be allowed to login)
|
||||
std::wstring pass_rsa_private_key;
|
||||
|
||||
|
||||
// path to 'openssl'
|
||||
// default: /usr/bin/openssl
|
||||
std::wstring opensll_path;
|
||||
|
||||
/*
|
||||
*/
|
||||
// setting when we should delete patterns (EZC patterns)
|
||||
// we are deleting when we have more (or equal) patterns than 'when_delete'
|
||||
// and then we are deleting 'how_many_del' patterns
|
||||
// those patterns comes from items (pages) with executable bit set
|
||||
size_t pattern_cacher_when_delete;
|
||||
size_t pattern_cacher_how_many_delete;
|
||||
|
||||
// header "Content-Type" send to the client
|
||||
// 0 - text/html - for HTML
|
||||
// 1 - application/xhtml+xml - for XHTML 1.0
|
||||
// 2 - application/xml - for XHTML 1.0 or for XHTML 1.1
|
||||
// default: 0
|
||||
// if utf8 is true then "; charset=UTF-8" will also be appended
|
||||
int content_type_header;
|
||||
|
||||
// global umask
|
||||
// it is used when an user doesn't have your own umask or for guests (not logged users)
|
||||
// default: 0222
|
||||
int umask;
|
||||
|
||||
// maximum number for elements through the whole template
|
||||
// default: 50000
|
||||
size_t ezc_max_elements;
|
||||
|
||||
// maximum number of each [for] loop
|
||||
// default: 5000 (from ezc generator)
|
||||
size_t ezc_max_loop_elements;
|
||||
|
||||
// when true then when a user want to create a new account
|
||||
// he has to provide his email and a message will be sent back to him
|
||||
// with a link to activate the account
|
||||
// default: true
|
||||
bool account_need_email_verification;
|
||||
|
||||
// when a user forgot his password we are able to send an email to him
|
||||
// with a link to the page where there is a html form for setting a new password
|
||||
// this option tells how long (in seconds) the link is valid
|
||||
// default: 86400 (24 hours)
|
||||
long reset_password_code_expiration_time;
|
||||
|
||||
// time zone identifier for not logged users
|
||||
// or for newly created accounts
|
||||
// those identifiers you can see in etc/time_zones.conf file
|
||||
// or by using timezone winix function with 'a' parameter (timezone/a) (!!IMPROVE ME NOT IMPLEMENTED YET)
|
||||
// default: 34 (Coordinated Universal Time UTC+00:00)
|
||||
size_t time_zone_default_id;
|
||||
|
||||
// a maximum value of a time zone identifier
|
||||
// time zones with an id greater than this will be skipped
|
||||
// default: 130 (maximum: 1000)
|
||||
size_t time_zone_max_id;
|
||||
|
||||
// a directory in which there are some config files
|
||||
// used mainly when winix starts
|
||||
// default: empty (means not for using)
|
||||
std::wstring etc_dir;
|
||||
|
||||
// a file in etc_dir with time zones info
|
||||
// default: time_zones.conf
|
||||
// this is a Space structure with all time zones
|
||||
// with following format:
|
||||
// "tz_-12:00" ( # the name of a space is also a key to the locale files
|
||||
// tz_offset_str = "-12:00" # a string representing the offset from UTC in a format: [+|-]HH:MM
|
||||
// tz_has_dst = "false" # whether the time zone has daylight saving time (bool)
|
||||
// tz_dst_offset = "" # offset of the daylight saving time
|
||||
// tz_dst_start = "" # when the daylight saving time starts, format: MM:DD HH:MM:SS
|
||||
// tz_dst_end = "") # when the daylight saving time ends, format: MM:DD HH:MM:SS
|
||||
// each time zone is in a seperate space
|
||||
std::wstring time_zones_file;
|
||||
|
||||
// turn on the IP ban mechanizm
|
||||
// we have got three levels of bans (level 1, level 2, and the highest level 3)
|
||||
// default: true
|
||||
bool use_ban_list;
|
||||
|
||||
// the so called 'soft' max size
|
||||
// read below description for explanation
|
||||
// this is introduced to avoid deleting only one record from the ban list
|
||||
// default: 50000
|
||||
size_t ban_list_soft_max_size;
|
||||
|
||||
// this is the 'hard' max size of an IP's ban list
|
||||
// if there are more records than this value
|
||||
// then some of them will be removed (until the size will be ban_list_soft_max_size equal)
|
||||
// this value should be a little larger from ban_list_soft_max_size
|
||||
// default: 51000
|
||||
size_t ban_list_max_size;
|
||||
|
||||
// delay in seconds of the first level ban
|
||||
// default: 1800 (30 minutes)
|
||||
// it means withing the next 30 minutes you see only 'you are banned...' message on your webbrowser
|
||||
size_t ban_level_1_delay;
|
||||
|
||||
// delay in seconds of the second level ban
|
||||
// default: 86400 (24 hours)
|
||||
size_t ban_level_2_delay;
|
||||
|
||||
// delay in seconds of the third level ban
|
||||
// default: 604800 (7 days)
|
||||
size_t ban_level_3_delay;
|
||||
|
||||
// the minimum time in seconds which has to pass between the first GET request
|
||||
// (showing your the login form) and the second POST request (which sends the
|
||||
// login and password to the server)
|
||||
// if the time is shorter then the login attempt is treated as incorrect
|
||||
// (the same as if you provide incorrect user/password)
|
||||
// default: 2
|
||||
size_t incorrect_login_min_time_between_get_post;
|
||||
|
||||
// how many incorrect logins there must have been passed to display a captcha
|
||||
// next to the login form
|
||||
// default: 3
|
||||
size_t incorrect_login_captcha_treshold;
|
||||
|
||||
// the way how we prevent to login if there are too many incorrect login attempts
|
||||
// 0 - 'block logging' - do not show the login form in 'login' winix function
|
||||
// (instead a warning message will be printed)
|
||||
// 1 - add to ban list (warning: people from this IP will not be able to see your site and do anything)
|
||||
// default: 0
|
||||
int incorrect_login_cannot_login_mode;
|
||||
|
||||
// after how many incorrect login attempts we do the incorrect_login_cannot_login_mode action
|
||||
// default: 20
|
||||
size_t incorrect_login_cannot_login_treshold;
|
||||
|
||||
// used when incorrect_login_cannot_login_mode is zero
|
||||
// it is the time which should be passed to allow logging
|
||||
// default: 1800 (30 minutes)
|
||||
// if incorrect_login_cannot_login_mode is one then ban_level_X_delay times
|
||||
// will be taken accordingly
|
||||
size_t incorrect_login_cannot_login_delay;
|
||||
|
||||
// based on base_url
|
||||
// set by SetAdditionalVariables()
|
||||
// without the first part http:// (or https://) or the whole string is empty
|
||||
std::wstring base_url_http_host;
|
||||
|
||||
|
||||
Config();
|
||||
bool ReadConfig(bool errors_to_stdout_, bool stdout_is_closed = true);
|
||||
|
||||
std::wstring Text(const wchar_t * name);
|
||||
std::wstring Text(const wchar_t * name, const wchar_t * def);
|
||||
std::wstring Text(const std::wstring & name, const std::wstring & def);
|
||||
std::string AText(const wchar_t * name);
|
||||
std::string AText(const wchar_t * name, const wchar_t * def);
|
||||
std::string AText(const std::wstring & name, const std::wstring & def);
|
||||
std::wstring & Text(const wchar_t * name);
|
||||
std::wstring & Text(const wchar_t * name, const wchar_t * def);
|
||||
std::wstring & Text(const std::wstring & name, const wchar_t * def);
|
||||
std::string & AText(const wchar_t * name);
|
||||
std::string & AText(const wchar_t * name, const char * def);
|
||||
std::string & AText(const std::wstring & name, const char * def);
|
||||
|
||||
int Int(const wchar_t *);
|
||||
int Int(const wchar_t * name, int def);
|
||||
int Int(const std::wstring & name, int def);
|
||||
int Int(const wchar_t *);
|
||||
int Int(const wchar_t * name, int def);
|
||||
int Int(const std::wstring & name, int def);
|
||||
long Long(const wchar_t *);
|
||||
long Long(const wchar_t * name, long def);
|
||||
long Long(const std::wstring & name, long def);
|
||||
size_t Size(const wchar_t *);
|
||||
size_t Size(const wchar_t * name, size_t def);
|
||||
size_t Size(const std::wstring & name, size_t def);
|
||||
bool Bool(const wchar_t *);
|
||||
bool Bool(const wchar_t * name, bool def);
|
||||
bool Bool(const std::wstring & name, bool def);
|
||||
void ListText(const wchar_t * name, std::vector<std::wstring> & list);
|
||||
void ListText(const std::wstring & name, std::vector<std::wstring> & list);
|
||||
bool ListText(const wchar_t * name, std::vector<std::wstring> & list);
|
||||
bool ListText(const std::wstring & name, std::vector<std::wstring> & list);
|
||||
|
||||
// for debug
|
||||
void Print(std::ostream & out);
|
||||
void Print(std::wostream & out);
|
||||
|
||||
// raw access to the config
|
||||
PT::Space space;
|
||||
|
||||
|
||||
private:
|
||||
|
||||
PT::SpaceParser parser;
|
||||
std::string default_str;
|
||||
bool errors_to_stdout;
|
||||
|
||||
void ShowError();
|
||||
void AssignValues(bool stdout_is_closed);
|
||||
void SetHttpHost(const std::wstring & in, std::wstring & out);
|
||||
void SetAdditionalVariables();
|
||||
void CheckLocale();
|
||||
void CheckPasswd();
|
||||
|
||||
ConfParser parser;
|
||||
|
||||
std::string default_str;
|
||||
int default_int;
|
||||
bool default_bool;
|
||||
|
||||
bool errors_to_stdout;
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -1,729 +0,0 @@
|
||||
/*
|
||||
* This file is a part of Winix
|
||||
* and is not publicly distributed
|
||||
*
|
||||
* Copyright (c) 2008-2010, Tomasz Sowa
|
||||
* All rights reserved.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <cstdlib>
|
||||
#include <wchar.h>
|
||||
#include "confparser.h"
|
||||
#include "misc.h"
|
||||
#include "utf8.h"
|
||||
|
||||
|
||||
|
||||
ConfParser::ConfParser()
|
||||
{
|
||||
// you can change this separators to what you want
|
||||
// you shoud not use only white characters here (as expected by IsWhite() method)
|
||||
// and new line characters ('\n')
|
||||
separator = '=';
|
||||
commentary = '#';
|
||||
list_start = '(';
|
||||
list_end = ')';
|
||||
list_delimiter = ',';
|
||||
split_single = false;
|
||||
skip_empty = false;
|
||||
use_escape_char = true;
|
||||
input_as_utf8 = false;
|
||||
|
||||
default_str = L"";
|
||||
default_int = 0;
|
||||
default_size = 0;
|
||||
default_bool = false;
|
||||
}
|
||||
|
||||
|
||||
void ConfParser::SplitSingle(bool split)
|
||||
{
|
||||
split_single = split;
|
||||
}
|
||||
|
||||
|
||||
void ConfParser::SkipEmpty(bool skip)
|
||||
{
|
||||
skip_empty = skip;
|
||||
}
|
||||
|
||||
|
||||
void ConfParser::UseEscapeChar(bool escape)
|
||||
{
|
||||
use_escape_char = escape;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
ConfParser::Status ConfParser::Parse(const char * file_name)
|
||||
{
|
||||
line = 1;
|
||||
table.clear();
|
||||
table_single.clear();
|
||||
|
||||
file.clear();
|
||||
file.open( file_name );
|
||||
|
||||
if( file )
|
||||
{
|
||||
status = ParseFile();
|
||||
file.close();
|
||||
}
|
||||
else
|
||||
{
|
||||
status = cant_open_file;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
|
||||
ConfParser::Status ConfParser::Parse(const std::string & file_name)
|
||||
{
|
||||
return Parse(file_name.c_str());
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
ConfParser::Status ConfParser::Parse(const wchar_t * file_name)
|
||||
{
|
||||
Ezc::WideToUTF8(file_name, afile_name);
|
||||
return Parse(afile_name.c_str());
|
||||
}
|
||||
|
||||
|
||||
|
||||
ConfParser::Status ConfParser::Parse(const std::wstring & file_name)
|
||||
{
|
||||
return Parse(file_name.c_str());
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
ConfParser::Status ConfParser::ParseFile()
|
||||
{
|
||||
ReadChar();
|
||||
SkipWhiteLines();
|
||||
|
||||
while( lastc != -1 )
|
||||
{
|
||||
if( !ReadVariable() )
|
||||
return syntax_error;
|
||||
|
||||
if( lastc != separator )
|
||||
return syntax_error;
|
||||
|
||||
if( !ReadValue() )
|
||||
return syntax_error;
|
||||
|
||||
AddOption();
|
||||
SkipWhite();
|
||||
|
||||
if( lastc != -1 && lastc != '\n' )
|
||||
return syntax_error; // some characters have left at the end of an option
|
||||
|
||||
SkipWhiteLines();
|
||||
}
|
||||
|
||||
return ok;
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool ConfParser::IsVariableChar(int c)
|
||||
{
|
||||
if( (c>='a' && c<='z') ||
|
||||
(c>='A' && c<='Z') ||
|
||||
(c>='0' && c<='9') ||
|
||||
c=='.' || c==',' || c=='_' )
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void ConfParser::AddOption()
|
||||
{
|
||||
if( value.empty() && skip_empty )
|
||||
{
|
||||
DeleteFromTable(variable);
|
||||
DeleteFromTableSingle(variable);
|
||||
return;
|
||||
}
|
||||
|
||||
if( split_single && value.size() == 1 )
|
||||
{
|
||||
table_single[variable] = value[0];
|
||||
DeleteFromTable(variable);
|
||||
}
|
||||
else
|
||||
{
|
||||
table[variable] = value;
|
||||
DeleteFromTableSingle(variable);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void ConfParser::DeleteFromTable(const std::wstring & var)
|
||||
{
|
||||
Table::iterator i = table.find(var);
|
||||
|
||||
if( i != table.end() )
|
||||
table.erase(i);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void ConfParser::DeleteFromTableSingle(const std::wstring & var)
|
||||
{
|
||||
TableSingle::iterator i = table_single.find(var);
|
||||
|
||||
if( i != table_single.end() )
|
||||
table_single.erase(i);
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool ConfParser::ReadVariable()
|
||||
{
|
||||
variable.clear();
|
||||
SkipWhite();
|
||||
|
||||
while( IsVariableChar(lastc) )
|
||||
{
|
||||
variable += lastc;
|
||||
ReadChar();
|
||||
}
|
||||
|
||||
SkipWhite();
|
||||
|
||||
return !variable.empty();
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool ConfParser::ReadValue()
|
||||
{
|
||||
value.clear();
|
||||
ReadChar(); // skipping separator '='
|
||||
SkipWhite();
|
||||
|
||||
if( lastc == list_start )
|
||||
return ReadValueList();
|
||||
else
|
||||
return ReadValueNoList();
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool ConfParser::ReadValueList()
|
||||
{
|
||||
ReadChar(); // skipping first list character '('
|
||||
SkipWhiteLines(); // lists can be split into several lines
|
||||
|
||||
while( lastc != -1 && lastc != list_end )
|
||||
{
|
||||
if( !ReadValueNoList(true) )
|
||||
return false;
|
||||
|
||||
if( lastc == list_delimiter )
|
||||
ReadChar();
|
||||
|
||||
SkipWhiteLines();
|
||||
}
|
||||
|
||||
if( lastc != list_end )
|
||||
return false;
|
||||
|
||||
ReadChar(); // skipping last list character ')'
|
||||
SkipWhite();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool ConfParser::ReadValueNoList(bool use_list_delimiter)
|
||||
{
|
||||
bool res;
|
||||
|
||||
value_item.clear();
|
||||
|
||||
if( lastc == '"' )
|
||||
{
|
||||
res = ReadValueQuoted(); // quoted value
|
||||
|
||||
if( res )
|
||||
value.push_back(value_item);
|
||||
}
|
||||
else
|
||||
{
|
||||
res = ReadValueSimple(use_list_delimiter);
|
||||
|
||||
if( res && !value_item.empty() )
|
||||
value.push_back(value_item);
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool ConfParser::ReadValueQuoted()
|
||||
{
|
||||
ReadChar(); // skipping the first quote
|
||||
|
||||
while( lastc != '"' && lastc != -1 )
|
||||
{
|
||||
if( use_escape_char && lastc == '\\' )
|
||||
ReadChar();
|
||||
|
||||
value_item += lastc;
|
||||
ReadChar();
|
||||
}
|
||||
|
||||
if( lastc != '"' )
|
||||
return false;
|
||||
|
||||
ReadChar(); // skipping the last quote
|
||||
SkipWhite();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool ConfParser::ReadValueSimple(bool use_list_delimiter)
|
||||
{
|
||||
int list_delimiter1 = -1;
|
||||
int list_delimiter2 = -1;
|
||||
|
||||
if( use_list_delimiter )
|
||||
{
|
||||
list_delimiter1 = list_delimiter;
|
||||
list_delimiter2 = list_end;
|
||||
}
|
||||
|
||||
while( lastc!=-1 && lastc!='\n' && lastc!=commentary &&
|
||||
lastc!=list_delimiter1 && lastc!=list_delimiter2 )
|
||||
{
|
||||
value_item += lastc;
|
||||
ReadChar();
|
||||
}
|
||||
|
||||
Trim(value_item);
|
||||
SkipWhite();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
int ConfParser::ReadUTF8Char()
|
||||
{
|
||||
int c;
|
||||
bool correct;
|
||||
|
||||
lastc = -1;
|
||||
|
||||
do
|
||||
{
|
||||
Ezc::UTF8ToInt(file, c, correct);
|
||||
|
||||
if( !file )
|
||||
return lastc;
|
||||
}
|
||||
while( !correct );
|
||||
|
||||
lastc = c;
|
||||
|
||||
if( lastc == '\n' )
|
||||
++line;
|
||||
|
||||
return lastc;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int ConfParser::ReadASCIIChar()
|
||||
{
|
||||
lastc = file.get();
|
||||
|
||||
if( lastc == '\n' )
|
||||
++line;
|
||||
|
||||
return lastc;
|
||||
}
|
||||
|
||||
|
||||
int ConfParser::ReadChar()
|
||||
{
|
||||
if( input_as_utf8 )
|
||||
return ReadUTF8Char();
|
||||
|
||||
return ReadASCIIChar();
|
||||
}
|
||||
|
||||
|
||||
bool ConfParser::IsWhite(int c)
|
||||
{
|
||||
// dont use '\n' here
|
||||
// 13 (\r) is at the end of a line in a dos file \r\n
|
||||
// 160 is an unbreakable space
|
||||
if( c==' ' || c=='\t' || c==13 || c==160 )
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void ConfParser::SkipWhite()
|
||||
{
|
||||
while( IsWhite(lastc) || lastc == commentary )
|
||||
{
|
||||
if( lastc == commentary )
|
||||
SkipLine();
|
||||
else
|
||||
ReadChar();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void ConfParser::SkipWhiteLines()
|
||||
{
|
||||
while( IsWhite(lastc) || lastc == commentary || lastc=='\n' )
|
||||
{
|
||||
if( lastc == commentary )
|
||||
SkipLine();
|
||||
else
|
||||
ReadChar();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void ConfParser::SkipLine()
|
||||
{
|
||||
while( lastc != -1 && lastc != '\n' )
|
||||
ReadChar();
|
||||
}
|
||||
|
||||
|
||||
|
||||
void ConfParser::Trim(std::wstring & s)
|
||||
{
|
||||
std::wstring::size_type i;
|
||||
|
||||
if( s.empty() )
|
||||
return;
|
||||
|
||||
// looking for white characters at the end
|
||||
for(i=s.size()-1 ; i>0 && IsWhite(s[i]) ; --i);
|
||||
|
||||
if( i==0 && IsWhite(s[i]) )
|
||||
{
|
||||
// the whole string has white characters
|
||||
s.clear();
|
||||
return;
|
||||
}
|
||||
|
||||
// deleting white characters at the end
|
||||
if( i != s.size() - 1 )
|
||||
s.erase(i+1, std::wstring::npos);
|
||||
|
||||
// looking for white characters at the beginning
|
||||
for(i=0 ; i<s.size() && IsWhite(s[i]) ; ++i);
|
||||
|
||||
// deleting white characters at the beginning
|
||||
if( i != 0 )
|
||||
s.erase(0, i);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
std::wstring ConfParser::Text(const wchar_t * name)
|
||||
{
|
||||
return Text(std::wstring(name), default_str);
|
||||
}
|
||||
|
||||
|
||||
|
||||
std::wstring ConfParser::Text(const wchar_t * name, const wchar_t * def)
|
||||
{
|
||||
return Text(std::wstring(name), std::wstring(def));
|
||||
}
|
||||
|
||||
|
||||
std::wstring ConfParser::Text(const std::wstring & name, const std::wstring & def)
|
||||
{
|
||||
TableSingle::iterator i = table_single.find(name);
|
||||
|
||||
if( i == table_single.end() )
|
||||
{
|
||||
Table::iterator t = table.find(name);
|
||||
|
||||
if( t == table.end() || t->second.empty() )
|
||||
return def;
|
||||
|
||||
return t->second[0];
|
||||
}
|
||||
|
||||
return i->second;
|
||||
}
|
||||
|
||||
|
||||
|
||||
std::string ConfParser::AText(const wchar_t * name)
|
||||
{
|
||||
std::wstring res = Text(name);
|
||||
std::string ares;
|
||||
|
||||
Ezc::WideToUTF8(res, ares);
|
||||
|
||||
return ares;
|
||||
}
|
||||
|
||||
|
||||
|
||||
std::string ConfParser::AText(const wchar_t * name, const wchar_t * def)
|
||||
{
|
||||
std::wstring res = Text(name, def);
|
||||
std::string ares;
|
||||
|
||||
Ezc::WideToUTF8(res, ares);
|
||||
|
||||
return ares;
|
||||
}
|
||||
|
||||
|
||||
std::string ConfParser::AText(const std::wstring & name, const std::wstring & def)
|
||||
{
|
||||
std::wstring res = Text(name, def);
|
||||
std::string ares;
|
||||
|
||||
Ezc::WideToUTF8(res, ares);
|
||||
|
||||
return ares;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
int ConfParser::Int(const wchar_t * name)
|
||||
{
|
||||
return Int(std::wstring(name), default_int);
|
||||
}
|
||||
|
||||
|
||||
int ConfParser::Int(const wchar_t * name, int def)
|
||||
{
|
||||
return Int(std::wstring(name), def);
|
||||
}
|
||||
|
||||
|
||||
int ConfParser::ToInt(const std::wstring & value)
|
||||
{
|
||||
long res = (value[0] == '0')? wcstol(value.c_str() + 1, 0, 8) : wcstol(value.c_str(), 0, 10);
|
||||
|
||||
return static_cast<int>(res);
|
||||
}
|
||||
|
||||
|
||||
int ConfParser::Int(const std::wstring & name, int def)
|
||||
{
|
||||
TableSingle::iterator i = table_single.find(name);
|
||||
|
||||
if( i == table_single.end() )
|
||||
{
|
||||
Table::iterator t = table.find(name);
|
||||
|
||||
if( t == table.end() || t->second.empty() )
|
||||
return def;
|
||||
|
||||
return ToInt(t->second[0]);
|
||||
}
|
||||
|
||||
return ToInt(i->second);
|
||||
}
|
||||
|
||||
|
||||
|
||||
size_t ConfParser::Size(const wchar_t * name)
|
||||
{
|
||||
return Size(std::wstring(name), default_size);
|
||||
}
|
||||
|
||||
|
||||
size_t ConfParser::Size(const wchar_t * name, size_t def)
|
||||
{
|
||||
return Size(std::wstring(name), def);
|
||||
}
|
||||
|
||||
|
||||
|
||||
size_t ConfParser::ToSize(const std::wstring & value)
|
||||
{
|
||||
unsigned long res = (value[0] == '0')? wcstoul(value.c_str() + 1, 0, 8) : wcstoul(value.c_str(), 0, 10);
|
||||
|
||||
return static_cast<size_t>(res);
|
||||
}
|
||||
|
||||
|
||||
size_t ConfParser::Size(const std::wstring & name, size_t def)
|
||||
{
|
||||
TableSingle::iterator i = table_single.find(name);
|
||||
|
||||
if( i == table_single.end() )
|
||||
{
|
||||
Table::iterator t = table.find(name);
|
||||
|
||||
if( t == table.end() || t->second.empty() )
|
||||
return def;
|
||||
|
||||
return ToSize(t->second[0]);
|
||||
}
|
||||
|
||||
return ToSize(i->second);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
bool ConfParser::Bool(const wchar_t * name)
|
||||
{
|
||||
return Bool(std::wstring(name), default_bool);
|
||||
}
|
||||
|
||||
|
||||
bool ConfParser::Bool(const wchar_t * name, bool def)
|
||||
{
|
||||
return Bool(std::wstring(name), def);
|
||||
}
|
||||
|
||||
|
||||
bool ConfParser::ToBool(const std::wstring & value)
|
||||
{
|
||||
return ( EqualNoCase(value.c_str(), L"true") ||
|
||||
EqualNoCase(value.c_str(), L"yes") ||
|
||||
EqualNoCase(value.c_str(), L"1")
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
bool ConfParser::Bool(const std::wstring & name, bool def)
|
||||
{
|
||||
TableSingle::iterator i = table_single.find(name);
|
||||
|
||||
if( i == table_single.end() )
|
||||
{
|
||||
Table::iterator t = table.find(name);
|
||||
|
||||
if( t == table.end() || t->second.empty() )
|
||||
return def;
|
||||
|
||||
return ToBool(t->second[0]);
|
||||
}
|
||||
|
||||
return ToBool(i->second);
|
||||
}
|
||||
|
||||
|
||||
void ConfParser::SetDefaultText(const std::wstring & def)
|
||||
{
|
||||
default_str = def;
|
||||
}
|
||||
|
||||
void ConfParser::SetDefaultInt(int def)
|
||||
{
|
||||
default_int = def;
|
||||
}
|
||||
|
||||
void ConfParser::SetDefaultSize(size_t def)
|
||||
{
|
||||
default_size = def;
|
||||
}
|
||||
|
||||
void ConfParser::SetDefaultBool(bool def)
|
||||
{
|
||||
default_bool = def;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// in lists we don't use default values
|
||||
void ConfParser::ListText(const wchar_t * name, std::vector<std::wstring> & list)
|
||||
{
|
||||
ListText(std::wstring(name), list);
|
||||
}
|
||||
|
||||
|
||||
void ConfParser::ListText(const std::wstring & name, std::vector<std::wstring> & list)
|
||||
{
|
||||
list.clear();
|
||||
|
||||
ConfParser::TableSingle::iterator i = table_single.find(name);
|
||||
|
||||
if( i != table_single.end() )
|
||||
{
|
||||
list.push_back(i->second);
|
||||
return;
|
||||
}
|
||||
|
||||
ConfParser::Table::iterator z = table.find(name);
|
||||
|
||||
if( z != table.end() )
|
||||
{
|
||||
list = z->second;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void ConfParser::UTF8(bool utf)
|
||||
{
|
||||
input_as_utf8 = utf;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void ConfParser::Print(std::ostream & out)
|
||||
{
|
||||
TableSingle::iterator i1;
|
||||
|
||||
for(i1 = table_single.begin() ; i1 != table_single.end() ; ++i1)
|
||||
{
|
||||
Ezc::WideToUTF8(i1->first, out);
|
||||
out << '=';
|
||||
Ezc::WideToUTF8(i1->second, out);
|
||||
out << std::endl;
|
||||
}
|
||||
|
||||
Table::iterator i2;
|
||||
Value::iterator i3;
|
||||
|
||||
for(i2 = table.begin() ; i2 != table.end() ; ++i2)
|
||||
{
|
||||
Ezc::WideToUTF8(i2->first, out);
|
||||
out << '=';
|
||||
|
||||
for(i3 = i2->second.begin() ; i3 != i2->second.end() ; ++i3)
|
||||
{
|
||||
Ezc::WideToUTF8(*i3, out);
|
||||
out << ',';
|
||||
}
|
||||
|
||||
out << std::endl;
|
||||
}
|
||||
}
|
||||
@@ -1,406 +0,0 @@
|
||||
/*
|
||||
* This file is a part of Winix
|
||||
* and is not publicly distributed
|
||||
*
|
||||
* Copyright (c) 2008-2010, Tomasz Sowa
|
||||
* All rights reserved.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef headerfileconfparser
|
||||
#define headerfileconfparser
|
||||
|
||||
#include <fstream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
A parser for parsing config files.
|
||||
|
||||
A config file can look like this:
|
||||
variable1 = value 1
|
||||
variable2 = " value 2 "
|
||||
variable3 = (value 1, value 2)
|
||||
variable4 = (" value 1 " , "value2", value 3)
|
||||
|
||||
sample of use:
|
||||
ConfParser parser;
|
||||
parser.Parse("/path/to/config");
|
||||
|
||||
if( parser.status == ConfParser::ok )
|
||||
{
|
||||
// the whole config we have in parser.table (parser.table_single)
|
||||
}
|
||||
|
||||
config syntax:
|
||||
option = list
|
||||
|
||||
list can consists of any number of items, if you're using more than one item you should
|
||||
use brackets ()
|
||||
|
||||
for one item the brackets can be ommited:
|
||||
option = value
|
||||
white characters at the beginning of the value (and at the end) will be trimmed,
|
||||
or you can use quotes:
|
||||
option = "value"
|
||||
option2 = "value with spaces at the end "
|
||||
|
||||
the form without quotes:
|
||||
option = value
|
||||
should be written in one line, so this is not allowed:
|
||||
option =
|
||||
value
|
||||
you can use a new line characters only between brackets and quotes:
|
||||
option = "this is
|
||||
a multiline string"
|
||||
option = ( value1,
|
||||
value2 )
|
||||
|
||||
but there is one requirement: the first character " or ( should be in the same line,
|
||||
so this is not allowed
|
||||
option =
|
||||
"this is wrong"
|
||||
but this is ok:
|
||||
option = "
|
||||
that is ok"
|
||||
|
||||
empty lists:
|
||||
option = ()
|
||||
this creates an empty list: parser.table['option'].empty() == true
|
||||
|
||||
option =
|
||||
this creates an empty list too (the same as previously)
|
||||
|
||||
option = ""
|
||||
but this doesn't create an empty list, it creates a list with one (empty) item
|
||||
|
||||
commentaries:
|
||||
# this is a commentary (until the end of the line)
|
||||
option = value # this is a commentary too
|
||||
|
||||
commentaries are treated as white characters, other example:
|
||||
option = ( # this is my list
|
||||
"value 1" # this is a value one
|
||||
value 2 # and this is a value two
|
||||
) # end of my list
|
||||
|
||||
overwriting:
|
||||
option1 = some value
|
||||
option1 = other value
|
||||
# always the last option is used so option1 is "other value"
|
||||
|
||||
list delimiter:
|
||||
option1 = (value1, value2, value3)
|
||||
option2 = ("value1", "value2", "value3")
|
||||
above we're using a comma ',' as a list delimiter but when using quotes (second line)
|
||||
the commas can be omitted:
|
||||
option2 = ("value1" "value2" "value3")
|
||||
|
||||
white characters:
|
||||
the name of an option cannot consist of white characters
|
||||
some option = value # this is wrong
|
||||
some_option = value # this is ok
|
||||
|
||||
which characters are allowed in an option name is defined by IsVariableChar() method
|
||||
|
||||
you can use white characters in values
|
||||
option = value with spaces or tabs
|
||||
white characters at the beginning and at the end will be trimmed,
|
||||
so if you want them use quotes:
|
||||
option = " other value with spaces "
|
||||
|
||||
special characters in quoted strings:
|
||||
option = "this is a string with \" a quote inside"
|
||||
the option will be: this is a string with " a quote inside
|
||||
\\ - means one \
|
||||
basically: \char produces char
|
||||
so:
|
||||
"\a" gives "a"
|
||||
"\\" gives "\"
|
||||
"\Z" gives "Z" and so on
|
||||
you can call UseEscapeChar(false) to turn this off
|
||||
|
||||
|
||||
*/
|
||||
class ConfParser
|
||||
{
|
||||
public:
|
||||
|
||||
ConfParser();
|
||||
|
||||
|
||||
/*
|
||||
status of parsing
|
||||
*/
|
||||
enum Status { ok, cant_open_file, syntax_error };
|
||||
|
||||
|
||||
/*
|
||||
the last status of parsing, set by Parse() methods
|
||||
*/
|
||||
Status status;
|
||||
|
||||
|
||||
/*
|
||||
the main methods used to parse
|
||||
file_name is the path to a file
|
||||
*/
|
||||
Status Parse(const char * file_name);
|
||||
Status Parse(const std::string & file_name);
|
||||
Status Parse(const wchar_t * file_name);
|
||||
Status Parse(const std::wstring & file_name);
|
||||
|
||||
|
||||
/*
|
||||
a number of a line in which there is a syntax_error
|
||||
*/
|
||||
int line;
|
||||
|
||||
|
||||
/*
|
||||
this is the table which represents your config file
|
||||
in the Table map: the first (key) is your 'option' and the second is 'list'
|
||||
*/
|
||||
typedef std::vector<std::wstring> Value;
|
||||
typedef std::map<std::wstring, Value> Table;
|
||||
Table table;
|
||||
|
||||
|
||||
/*
|
||||
if your config file consists mainly of single forms such as:
|
||||
option = value
|
||||
option2 = value2
|
||||
then you can call SplitSingle(true) for not inserting single values to
|
||||
previous 'table' but instead to 'table_single'
|
||||
table_single as the second parameter takes only std::wstring (instead of the whole std::vector)
|
||||
so you can save a little memory from not using std::vector
|
||||
*/
|
||||
typedef std::map<std::wstring, std::wstring> TableSingle;
|
||||
TableSingle table_single;
|
||||
|
||||
|
||||
/*
|
||||
if your list consists of only one item, e.g:
|
||||
option1 = value 1
|
||||
option2 = "value 2"
|
||||
option3 = ( "value 3" )
|
||||
then if you call SplitSingle(true) then such values will be stored in
|
||||
'table_single' instead of 'table' map
|
||||
default: false
|
||||
*/
|
||||
void SplitSingle(bool split);
|
||||
|
||||
|
||||
/*
|
||||
if true then empty lists, e.g:
|
||||
option =
|
||||
option2 = ()
|
||||
will be omitted (not inserted to 'table' or 'table_single')
|
||||
default: false
|
||||
*/
|
||||
void SkipEmpty(bool skip);
|
||||
|
||||
|
||||
/*
|
||||
'\' character is used to escape other characters in a quoted string
|
||||
so "some \t t\"ext" will produce "some t t"ext"
|
||||
(this is only use in quoted string)
|
||||
default: true
|
||||
*/
|
||||
void UseEscapeChar(bool escape);
|
||||
|
||||
|
||||
/*
|
||||
those methods are used to extract information from table or table_single
|
||||
as a parameter they take the name of an option
|
||||
and a default value (if there is no such a parameter),
|
||||
they return appropriate value (either text, int or boolean)
|
||||
(in lists they return the first item if exists)
|
||||
*/
|
||||
std::wstring Text(const wchar_t * name);
|
||||
std::wstring Text(const wchar_t * name, const wchar_t * def);
|
||||
std::wstring Text(const std::wstring & name, const std::wstring & def);
|
||||
std::string AText(const wchar_t * name);
|
||||
std::string AText(const wchar_t * name, const wchar_t * def);
|
||||
std::string AText(const std::wstring & name, const std::wstring & def);
|
||||
int Int(const wchar_t *);
|
||||
int Int(const wchar_t * name, int def);
|
||||
int Int(const std::wstring & name, int def);
|
||||
size_t Size(const wchar_t *);
|
||||
size_t Size(const wchar_t * name, size_t def);
|
||||
size_t Size(const std::wstring & name, size_t def);
|
||||
bool Bool(const wchar_t *);
|
||||
bool Bool(const wchar_t * name, bool def);
|
||||
bool Bool(const std::wstring & name, bool def);
|
||||
|
||||
|
||||
/*
|
||||
some default values
|
||||
used in Text() Int() or Bool() when you don't explicitly set the default value
|
||||
|
||||
if you don't set it directly then:
|
||||
default text is: "" (empty)
|
||||
default int or size is: 0
|
||||
default bool is: false
|
||||
*/
|
||||
void SetDefaultText(const std::wstring & def);
|
||||
void SetDefaultInt(int def);
|
||||
void SetDefaultSize(size_t def);
|
||||
void SetDefaultBool(bool def);
|
||||
|
||||
|
||||
/*
|
||||
those methods are used to extract lists
|
||||
note: if there is one option in table_single they will return it
|
||||
*/
|
||||
void ListText(const wchar_t * name, std::vector<std::wstring> & list);
|
||||
void ListText(const std::wstring & name, std::vector<std::wstring> & list);
|
||||
|
||||
|
||||
/*
|
||||
if true then the input file is treated as UTF-8
|
||||
*/
|
||||
void UTF8(bool utf);
|
||||
|
||||
|
||||
/*
|
||||
printing the content
|
||||
(for debug purposes)
|
||||
*/
|
||||
void Print(std::ostream & out);
|
||||
|
||||
|
||||
private:
|
||||
|
||||
/*
|
||||
last read variable (option)
|
||||
*/
|
||||
std::wstring variable;
|
||||
|
||||
|
||||
/*
|
||||
last read list item
|
||||
*/
|
||||
std::wstring value_item;
|
||||
|
||||
|
||||
/*
|
||||
last read list
|
||||
*/
|
||||
Value value;
|
||||
|
||||
|
||||
/*
|
||||
separator between a variable and a value, default: '='
|
||||
*/
|
||||
int separator;
|
||||
|
||||
|
||||
/*
|
||||
commentary char, default: '#'
|
||||
*/
|
||||
int commentary;
|
||||
|
||||
|
||||
/*
|
||||
list starting character, default: '('
|
||||
*/
|
||||
int list_start;
|
||||
|
||||
|
||||
/*
|
||||
list ending character, default: ')'
|
||||
*/
|
||||
int list_end;
|
||||
|
||||
|
||||
/*
|
||||
list delimiter, default: ','
|
||||
*/
|
||||
int list_delimiter;
|
||||
|
||||
|
||||
/*
|
||||
last read char
|
||||
or -1 if the end
|
||||
*/
|
||||
int lastc;
|
||||
|
||||
|
||||
/*
|
||||
current file
|
||||
*/
|
||||
std::ifstream file;
|
||||
|
||||
|
||||
/*
|
||||
if true then lists with one item will be put into 'table_single' table
|
||||
default: false
|
||||
*/
|
||||
bool split_single;
|
||||
|
||||
|
||||
/*
|
||||
if true then empty lists, e.g:
|
||||
option =
|
||||
option2 = ()
|
||||
will be omitted (not inserted to 'table' or 'table_single')
|
||||
default: false
|
||||
*/
|
||||
bool skip_empty;
|
||||
|
||||
|
||||
/*
|
||||
input file is in UTF-8
|
||||
default: false
|
||||
*/
|
||||
bool input_as_utf8;
|
||||
|
||||
|
||||
/*
|
||||
if true you can use an escape character '\' in quoted values
|
||||
*/
|
||||
bool use_escape_char;
|
||||
|
||||
std::string afile_name;
|
||||
|
||||
std::wstring default_str;
|
||||
int default_int;
|
||||
size_t default_size;
|
||||
bool default_bool;
|
||||
|
||||
int ToInt(const std::wstring & value);
|
||||
size_t ToSize(const std::wstring & value);
|
||||
bool ToBool(const std::wstring & value);
|
||||
|
||||
Status ParseFile();
|
||||
void AddOption();
|
||||
|
||||
void DeleteFromTable(const std::wstring & var);
|
||||
void DeleteFromTableSingle(const std::wstring & var);
|
||||
|
||||
bool ReadVariable();
|
||||
bool ReadValue();
|
||||
bool ReadValueList();
|
||||
bool ReadValueNoList(bool use_list_delimiter = false);
|
||||
bool ReadValueQuoted();
|
||||
bool ReadValueSimple(bool use_list_delimiter = false);
|
||||
|
||||
int ReadUTF8Char();
|
||||
int ReadASCIIChar();
|
||||
int ReadChar();
|
||||
bool IsWhite(int c);
|
||||
bool IsVariableChar(int c);
|
||||
void SkipWhite();
|
||||
void SkipWhiteLines();
|
||||
void SkipLine();
|
||||
void Trim(std::wstring & s);
|
||||
};
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
123
core/crypt.cpp
123
core/crypt.cpp
@@ -2,15 +2,14 @@
|
||||
* This file is a part of Winix
|
||||
* and is not publicly distributed
|
||||
*
|
||||
* Copyright (c) 2011, Tomasz Sowa
|
||||
* Copyright (c) 2011-2012, Tomasz Sowa
|
||||
* All rights reserved.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <cstring>
|
||||
#include "crypt.h"
|
||||
#include "utf8.h"
|
||||
#include "misc.h"
|
||||
#include "utf8/utf8.h"
|
||||
#include "log.h"
|
||||
|
||||
|
||||
@@ -21,22 +20,19 @@ void Crypt::SetConfig(Config * pconfig)
|
||||
}
|
||||
|
||||
|
||||
void Crypt::TrimLastWhite(std::string & str)
|
||||
|
||||
char Crypt::ConvertToHexForm(int val)
|
||||
{
|
||||
if( str.empty() )
|
||||
return;
|
||||
if( val < 10 )
|
||||
return val + '0';
|
||||
|
||||
size_t i = str.size();
|
||||
|
||||
while( i > 0 && (IsWhite(str[i-1]) || str[i-1]==10) )
|
||||
i -= 1;
|
||||
|
||||
if( i < str.size() )
|
||||
str.erase(i);
|
||||
return val - 10 + 'a';
|
||||
}
|
||||
|
||||
|
||||
bool Crypt::Hash(int hash, const char * in, size_t inlen, std::string & out)
|
||||
|
||||
|
||||
bool Crypt::HashBin(int hash, const char * in, size_t inlen, std::string & out)
|
||||
{
|
||||
out.clear();
|
||||
|
||||
@@ -44,9 +40,10 @@ bool Crypt::Hash(int hash, const char * in, size_t inlen, std::string & out)
|
||||
return false;
|
||||
|
||||
run.Clear();
|
||||
Ezc::WideToUTF8(config->opensll_path, command);
|
||||
PT::WideToUTF8(config->opensll_path, command);
|
||||
run.Cmd(command);
|
||||
run.Par("dgst");
|
||||
run.Par("-binary");
|
||||
|
||||
switch(hash)
|
||||
{
|
||||
@@ -62,52 +59,96 @@ bool Crypt::Hash(int hash, const char * in, size_t inlen, std::string & out)
|
||||
return false;
|
||||
}
|
||||
|
||||
bool result = run.Go(in, inlen, out) == 0;
|
||||
TrimLastWhite(out);
|
||||
|
||||
return result;
|
||||
return run.Go(in, inlen, out) == 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool Crypt::Hash(int hash, const char * in, std::string & out)
|
||||
bool Crypt::HashBin(int hash, const char * in, std::string & out)
|
||||
{
|
||||
size_t len = strlen(in);
|
||||
return Hash(hash, in, len, out);
|
||||
return HashBin(hash, in, len, out);
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool Crypt::Hash(int hash, const std::string & in, std::string & out)
|
||||
bool Crypt::HashBin(int hash, const std::string & in, std::string & out)
|
||||
{
|
||||
return Hash(hash, in.c_str(), in.size(), out);
|
||||
return HashBin(hash, in.c_str(), in.size(), out);
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool Crypt::Hash(int hash, const wchar_t * in, size_t inlen, std::wstring & out)
|
||||
bool Crypt::HashBin(int hash, const wchar_t * in, size_t inlen, std::string & out)
|
||||
{
|
||||
Ezc::WideToUTF8(in, inlen, bufina);
|
||||
int res = Hash(hash, bufina.c_str(), bufina.size(), bufouta);
|
||||
PT::WideToUTF8(in, inlen, bufina);
|
||||
int res = HashBin(hash, bufina.c_str(), bufina.size(), out);
|
||||
bufina.clear();
|
||||
|
||||
// the output hash is not a UTF8 string
|
||||
// it consists only from ascii letters
|
||||
AssignString(bufouta, out);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
bool Crypt::HashBin(int hash, const wchar_t * in, std::string & out)
|
||||
{
|
||||
size_t len = wcslen(in);
|
||||
return HashBin(hash, in, len, out);
|
||||
}
|
||||
|
||||
|
||||
bool Crypt::HashBin(int hash, const std::wstring & in, std::string & out)
|
||||
{
|
||||
return HashBin(hash, in.c_str(), in.size(), out);
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool Crypt::HashHex(int hash, const char * in, size_t inlen, std::string & out)
|
||||
{
|
||||
int res = HashBin(hash, in, inlen, out_temp);
|
||||
|
||||
ConvertToHexForm(out_temp, out);
|
||||
out_temp.clear();
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
bool Crypt::Hash(int hash, const wchar_t * in, std::wstring & out)
|
||||
bool Crypt::HashHex(int hash, const char * in, std::string & out)
|
||||
{
|
||||
size_t len = wcslen(in);
|
||||
return Hash(hash, in, len, out);
|
||||
|
||||
size_t len = strlen(in);
|
||||
return HashHex(hash, in, len, out);
|
||||
}
|
||||
|
||||
bool Crypt::Hash(int hash, const std::wstring & in, std::wstring & out)
|
||||
|
||||
bool Crypt::HashHex(int hash, const std::string & in, std::string & out)
|
||||
{
|
||||
return Hash(hash, in.c_str(), in.size(), out);
|
||||
return HashHex(hash, in.c_str(), in.size(), out);
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool Crypt::HashHex(int hash, const wchar_t * in, size_t inlen, std::wstring & out)
|
||||
{
|
||||
int res = HashBin(hash, in, inlen, out_temp);
|
||||
|
||||
ConvertToHexForm(out_temp, out);
|
||||
out_temp.clear();
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
bool Crypt::HashHex(int hash, const wchar_t * in, std::wstring & out)
|
||||
{
|
||||
size_t len = wcslen(in);
|
||||
return HashHex(hash, in, len, out);
|
||||
}
|
||||
|
||||
|
||||
bool Crypt::HashHex(int hash, const std::wstring & in, std::wstring & out)
|
||||
{
|
||||
return HashHex(hash, in.c_str(), in.size(), out);
|
||||
}
|
||||
|
||||
|
||||
@@ -132,7 +173,7 @@ bool Crypt::RSA(bool encrypt, const char * keypath, const char * in, size_t inle
|
||||
return false;
|
||||
|
||||
run.Clear();
|
||||
Ezc::WideToUTF8(config->opensll_path, command);
|
||||
PT::WideToUTF8(config->opensll_path, command);
|
||||
run.Cmd(command);
|
||||
|
||||
run.Par("rsautl");
|
||||
@@ -164,7 +205,7 @@ bool Crypt::RSA(bool encrypt, const std::string & keypath, const std::string & i
|
||||
|
||||
bool Crypt::RSA(bool encrypt, const wchar_t * keypath, const char * in, size_t inlen, std::string & out)
|
||||
{
|
||||
Ezc::WideToUTF8(keypath, keypatha);
|
||||
PT::WideToUTF8(keypath, keypatha);
|
||||
return RSA(encrypt, keypatha.c_str(), in, inlen, out);
|
||||
}
|
||||
|
||||
@@ -193,13 +234,13 @@ bool Crypt::PassHash(const std::wstring & salt, UserPass & up)
|
||||
bool result = true;
|
||||
up.pass_hash_salted = false;
|
||||
|
||||
if( up.pass_type != WINIX_CRYPT_HASH_PLAIN )
|
||||
if( up.pass_type != WINIX_CRYPT_HASH_NONE )
|
||||
{
|
||||
pass_org = up.pass;
|
||||
pass_salted = up.pass;
|
||||
pass_salted += salt;
|
||||
|
||||
if( Hash(up.pass_type, pass_salted, up.pass) )
|
||||
if( HashHex(up.pass_type, pass_salted, up.pass) )
|
||||
{
|
||||
if( !salt.empty() )
|
||||
up.pass_hash_salted = true;
|
||||
@@ -209,7 +250,7 @@ bool Crypt::PassHash(const std::wstring & salt, UserPass & up)
|
||||
log << log1 << "Crypt: problem with generating a hash, the password will not be hashed" << logend;
|
||||
|
||||
up.pass = pass_org;
|
||||
up.pass_type = WINIX_CRYPT_HASH_PLAIN;
|
||||
up.pass_type = WINIX_CRYPT_HASH_NONE;
|
||||
result = false;
|
||||
}
|
||||
|
||||
@@ -229,7 +270,7 @@ bool Crypt::PassCrypt(const std::wstring & path_to_rsa_private_key, UserPass & u
|
||||
|
||||
if( !path_to_rsa_private_key.empty() )
|
||||
{
|
||||
Ezc::WideToUTF8(up.pass, passa);
|
||||
PT::WideToUTF8(up.pass, passa);
|
||||
|
||||
if( RSA(true, path_to_rsa_private_key, passa, up.pass_encrypted) )
|
||||
{
|
||||
|
||||
85
core/crypt.h
85
core/crypt.h
@@ -2,7 +2,7 @@
|
||||
* This file is a part of Winix
|
||||
* and is not publicly distributed
|
||||
*
|
||||
* Copyright (c) 2011, Tomasz Sowa
|
||||
* Copyright (c) 2011-2012, Tomasz Sowa
|
||||
* All rights reserved.
|
||||
*
|
||||
*/
|
||||
@@ -20,7 +20,7 @@
|
||||
/*
|
||||
the kind of hashes we are able to obtain in winix
|
||||
*/
|
||||
#define WINIX_CRYPT_HASH_PLAIN 0
|
||||
#define WINIX_CRYPT_HASH_NONE 0
|
||||
#define WINIX_CRYPT_HASH_MD4 1
|
||||
#define WINIX_CRYPT_HASH_MD5 2
|
||||
#define WINIX_CRYPT_HASH_SHA1 10
|
||||
@@ -50,11 +50,11 @@ public:
|
||||
in - input buffer
|
||||
inlen - the length of the buffer
|
||||
output:
|
||||
out - the hash
|
||||
out - the hash in binary form
|
||||
*/
|
||||
bool Hash(int hash, const char * in, size_t inlen, std::string & out);
|
||||
bool Hash(int hash, const char * in, std::string & out);
|
||||
bool Hash(int hash, const std::string & in, std::string & out);
|
||||
bool HashBin(int hash, const char * in, size_t inlen, std::string & out);
|
||||
bool HashBin(int hash, const char * in, std::string & out);
|
||||
bool HashBin(int hash, const std::string & in, std::string & out);
|
||||
|
||||
|
||||
/*
|
||||
@@ -66,11 +66,43 @@ public:
|
||||
in - input buffer
|
||||
inlen - the length of the buffer
|
||||
output:
|
||||
out - the hash
|
||||
out - the hash in binary form
|
||||
*/
|
||||
bool Hash(int hash, const wchar_t * in, size_t inlen, std::wstring & out);
|
||||
bool Hash(int hash, const wchar_t * in, std::wstring & out);
|
||||
bool Hash(int hash, const std::wstring & in, std::wstring & out);
|
||||
bool HashBin(int hash, const wchar_t * in, size_t inlen, std::string & out);
|
||||
bool HashBin(int hash, const wchar_t * in, std::string & out);
|
||||
bool HashBin(int hash, const std::wstring & in, std::string & out);
|
||||
|
||||
|
||||
/*
|
||||
calculating a hash from a given input
|
||||
|
||||
input:
|
||||
hash - the kind of the hash - WINIX_CRYPT_HASH_*
|
||||
in - input buffer
|
||||
inlen - the length of the buffer
|
||||
output:
|
||||
out - the hash in the hex form (one byte is saved as two hex digits)
|
||||
*/
|
||||
bool HashHex(int hash, const char * in, size_t inlen, std::string & out);
|
||||
bool HashHex(int hash, const char * in, std::string & out);
|
||||
bool HashHex(int hash, const std::string & in, std::string & out);
|
||||
|
||||
|
||||
/*
|
||||
calculating a hash from a given input
|
||||
the input string is first changed to UTF8 and then hash is calculated
|
||||
|
||||
input:
|
||||
hash - the kind of the hash - WINIX_CRYPT_HASH_*
|
||||
in - input buffer
|
||||
inlen - the length of the buffer
|
||||
output:
|
||||
out - the hash in the hex form (one byte is saved as two hex digits)
|
||||
the 'out' here is std::wstring (not std::string like beforehand)
|
||||
*/
|
||||
bool HashHex(int hash, const wchar_t * in, size_t inlen, std::wstring & out);
|
||||
bool HashHex(int hash, const wchar_t * in, std::wstring & out);
|
||||
bool HashHex(int hash, const std::wstring & in, std::wstring & out);
|
||||
|
||||
|
||||
/*
|
||||
@@ -83,7 +115,7 @@ public:
|
||||
inlen - the size of the buffer
|
||||
|
||||
output:
|
||||
out - encrypted or decrypted buffer
|
||||
out - encrypted or decrypted buffer (always binary)
|
||||
*/
|
||||
bool RSA(bool encrypt, const char * keypath, const char * in, size_t inlen, std::string & out);
|
||||
bool RSA(bool encrypt, const char * keypath, const std::string & in, std::string & out);
|
||||
@@ -179,22 +211,27 @@ public:
|
||||
|
||||
private:
|
||||
|
||||
void TrimLastWhite(std::string & str);
|
||||
|
||||
Config * config;
|
||||
Run run;
|
||||
std::string command, bufina, bufouta, keypatha;
|
||||
std::string command, bufina, keypatha;
|
||||
//std::wstring pass_salted;//, pass_hashed;
|
||||
//std::string pass_hasheda, pass_encrypteda;
|
||||
|
||||
std::wstring pass_salted, pass_org;
|
||||
std::string passa;
|
||||
std::string passa, out_temp;
|
||||
std::wstring empty;
|
||||
|
||||
|
||||
template<typename StringType>
|
||||
void ConvertToHexForm(const std::string & in, StringType & out);
|
||||
|
||||
char ConvertToHexForm(int val);
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
template<class StringType>
|
||||
template<typename StringType>
|
||||
void Crypt::ClearString(StringType & str)
|
||||
{
|
||||
for(size_t i=0 ; i<str.size() ; ++i)
|
||||
@@ -204,6 +241,22 @@ void Crypt::ClearString(StringType & str)
|
||||
}
|
||||
|
||||
|
||||
template<typename StringType>
|
||||
void Crypt::ConvertToHexForm(const std::string & in, StringType & out)
|
||||
{
|
||||
out.clear();
|
||||
|
||||
if( in.size() * 2 > out.capacity() )
|
||||
out.reserve(in.size() * 2);
|
||||
|
||||
for(size_t i=0 ; i<in.size() ; ++i)
|
||||
{
|
||||
out += ConvertToHexForm(((unsigned char)in[i]) >> 4);
|
||||
out += ConvertToHexForm(((unsigned char)in[i]) & 0x0f);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* This file is a part of Winix
|
||||
* and is not publicly distributed
|
||||
*
|
||||
* Copyright (c) 2010, Tomasz Sowa
|
||||
* Copyright (c) 2010-2011, Tomasz Sowa
|
||||
* All rights reserved.
|
||||
*
|
||||
*/
|
||||
@@ -12,6 +12,7 @@
|
||||
|
||||
#include "request.h"
|
||||
#include "session.h"
|
||||
#include "mount.h"
|
||||
|
||||
|
||||
/*
|
||||
@@ -21,6 +22,7 @@ struct Cur
|
||||
{
|
||||
Request * request;
|
||||
Session * session;
|
||||
Mount * mount;
|
||||
|
||||
// those pointers are never null, if there is no a session for the user
|
||||
// the 'session' pointer pointers at a special temporary session
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* This file is a part of Winix
|
||||
* and is not publicly distributed
|
||||
*
|
||||
* Copyright (c) 2008-2010, Tomasz Sowa
|
||||
* Copyright (c) 2008-2012, Tomasz Sowa
|
||||
* All rights reserved.
|
||||
*
|
||||
*/
|
||||
@@ -48,7 +48,7 @@ public:
|
||||
|
||||
bool DelById(long id);
|
||||
|
||||
ParentIterator ParentBegin();
|
||||
ParentIterator ParentBegin(); // IMPROVE ME: may it should be renamed to ChildBegin() similarly as FindFirstChild() ?
|
||||
ParentIterator ParentEnd();
|
||||
ParentSizeType ParentSize();
|
||||
bool ParentEmpty();
|
||||
|
||||
140
core/dirs.cpp
140
core/dirs.cpp
@@ -2,7 +2,7 @@
|
||||
* This file is a part of Winix
|
||||
* and is not publicly distributed
|
||||
*
|
||||
* Copyright (c) 2008-2011, Tomasz Sowa
|
||||
* Copyright (c) 2008-2012, Tomasz Sowa
|
||||
* All rights reserved.
|
||||
*
|
||||
*/
|
||||
@@ -41,7 +41,7 @@ void Dirs::Clear()
|
||||
bool Dirs::HasReadExecAccessForRoot(const Item & item)
|
||||
{
|
||||
// there must be at least one 'x' (for the root)
|
||||
return (item.privileges & 01111) != 0; // !! in the future there'll be another 'x'
|
||||
return (item.privileges & 01111) != 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -53,8 +53,8 @@ void Dirs::CheckRootDir()
|
||||
{
|
||||
if( !HasReadExecAccessForRoot(*i) )
|
||||
{
|
||||
i->privileges = 0755;
|
||||
log << log1 << "Dirs: there is no access for root (admin) to the root dir, setting 0755 for root dir" << logend;
|
||||
i->privileges = 07555;
|
||||
log << log1 << "Dirs: there is no access for a root (admin) to the root dir, setting 07555 for the root directory" << logend;
|
||||
db->EditPrivById(*i, i->id);
|
||||
}
|
||||
|
||||
@@ -62,7 +62,7 @@ void Dirs::CheckRootDir()
|
||||
}
|
||||
|
||||
|
||||
log << log1 << "Dirs: there is no a root dir in the database (creating one)" << logend;
|
||||
log << log1 << "Dirs: there is no a root directory in the database (creating one)" << logend;
|
||||
|
||||
Item root;
|
||||
|
||||
@@ -70,7 +70,7 @@ void Dirs::CheckRootDir()
|
||||
root.parent_id = -1;
|
||||
root.user_id = -1;
|
||||
root.group_id = -1;
|
||||
root.privileges = 0755;
|
||||
root.privileges = 07555;
|
||||
|
||||
// !! upewnic sie ze baza nie zmieni url (gdyby wczesniej juz byl w bazie pusty url)
|
||||
// !! zrobic jakis wyjatek do wprowadzania roota?
|
||||
@@ -158,10 +158,10 @@ DirContainer::ParentIterator Dirs::ParentEnd()
|
||||
}
|
||||
|
||||
|
||||
// dodatkowo moze metoda AppendPath dodajaca sciezke do biezacego stringa?
|
||||
// !! dodatkowo moze metoda AppendPath dodajaca sciezke do biezacego stringa?
|
||||
// albo tutaj stringa nie czyscic?
|
||||
// O(m * log n) (m- how many parts are in 'id')
|
||||
// path with a slash at the end
|
||||
// path with a slash at the end and at the beginning
|
||||
bool Dirs::MakePath(long id, std::wstring & path, bool clear_path)
|
||||
{
|
||||
DirContainer::Iterator i;
|
||||
@@ -196,6 +196,22 @@ DirContainer::Iterator i;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void Dirs::MakePath(const std::vector<Item*> dir_tab, std::wstring & path, bool clear_path)
|
||||
{
|
||||
if( clear_path )
|
||||
path.clear();
|
||||
|
||||
for(size_t i=0 ; i<dir_tab.size() ; ++i)
|
||||
{
|
||||
path += dir_tab[i]->url;
|
||||
path += '/';
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
size_t Dirs::DirLevel(long id)
|
||||
{
|
||||
DirContainer::Iterator i;
|
||||
@@ -208,7 +224,6 @@ size_t level = 0;
|
||||
if( i == dir_tab.End() ||
|
||||
i->parent_id == id ) // means a loop (something wrong in the db)
|
||||
{
|
||||
// we don't change path if there is no such a directory
|
||||
return level;
|
||||
}
|
||||
|
||||
@@ -221,6 +236,30 @@ size_t level = 0;
|
||||
}
|
||||
|
||||
|
||||
bool Dirs::IsChild(long parent_id, long child_id)
|
||||
{
|
||||
if( child_id == parent_id )
|
||||
return false;
|
||||
|
||||
DirContainer::Iterator i;
|
||||
|
||||
while( child_id != -1 )
|
||||
{
|
||||
i = dir_tab.FindId(child_id);
|
||||
|
||||
if( i == dir_tab.End() )
|
||||
return false;
|
||||
|
||||
if( i->parent_id == parent_id )
|
||||
return true;
|
||||
|
||||
child_id = i->parent_id;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool Dirs::ChangeParent(long dir_id, long new_parent_id)
|
||||
{
|
||||
return dir_tab.ChangeParent(dir_id, new_parent_id);
|
||||
@@ -312,7 +351,7 @@ return &(*etc);
|
||||
}
|
||||
|
||||
|
||||
Item * Dirs::GetDir(const std::wstring & name, long parent)
|
||||
Item * Dirs::GetDir(const wchar_t * name, long parent)
|
||||
{
|
||||
DirContainer::ParentIterator i = dir_tab.FindFirstChild(parent);
|
||||
|
||||
@@ -324,23 +363,30 @@ return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
Item * Dirs::GetDir(const std::wstring & path)
|
||||
Item * Dirs::GetDir(const std::wstring & name, long parent)
|
||||
{
|
||||
return GetDir(name.c_str(), parent);
|
||||
}
|
||||
|
||||
|
||||
|
||||
Item * Dirs::GetDir(const wchar_t * path)
|
||||
{
|
||||
if( *path == 0 )
|
||||
return 0;
|
||||
|
||||
DirContainer::Iterator root = dir_tab.GetRoot();
|
||||
|
||||
if( root == dir_tab.End() )
|
||||
// ops, we do not have a root dir
|
||||
return 0;
|
||||
|
||||
Item * pitem = &(*root);
|
||||
|
||||
std::wstring name; // !! dodac jako skladowa klasy
|
||||
const wchar_t * s = path.c_str();
|
||||
Item * pitem = &(*root);
|
||||
const wchar_t * s = path;
|
||||
|
||||
while( ExtractName(s, name) )
|
||||
while( ExtractName(s, get_dir_temp) )
|
||||
{
|
||||
pitem = GetDir(name, pitem->id);
|
||||
pitem = GetDir(get_dir_temp, pitem->id);
|
||||
|
||||
if( !pitem )
|
||||
return 0;
|
||||
@@ -350,6 +396,13 @@ return pitem;
|
||||
}
|
||||
|
||||
|
||||
|
||||
Item * Dirs::GetDir(const std::wstring & path)
|
||||
{
|
||||
return GetDir(path.c_str());
|
||||
}
|
||||
|
||||
|
||||
Item * Dirs::GetDir(long id)
|
||||
{
|
||||
DirContainer::Iterator i = dir_tab.FindId(id);
|
||||
@@ -450,7 +503,7 @@ return 0;
|
||||
|
||||
|
||||
|
||||
// current_dir_tab can be the same container as out_dir_tab
|
||||
// current_dir_tab can be the same container as out_dir_tab
|
||||
void Dirs::CopyDirTab(const std::vector<Item*> & in, std::vector<Item*> & out)
|
||||
{
|
||||
if( &in != &out )
|
||||
@@ -465,13 +518,13 @@ void Dirs::CopyDirTab(const std::vector<Item*> & in, std::vector<Item*> & out)
|
||||
|
||||
|
||||
|
||||
size_t Dirs::AnalyzeDir(std::vector<Item*> & dir_tab, const std::wstring & link_to)
|
||||
bool Dirs::AnalyzeDir(std::vector<Item*> & dir_tab, const std::wstring & link_to, size_t & i)
|
||||
{
|
||||
if( dir_tab.empty() )
|
||||
return 0;
|
||||
|
||||
size_t i = 0;
|
||||
size_t old_i;
|
||||
i = 0;
|
||||
|
||||
if( dir_tab.empty() )
|
||||
return false;
|
||||
|
||||
while( true )
|
||||
{
|
||||
@@ -479,7 +532,7 @@ size_t Dirs::AnalyzeDir(std::vector<Item*> & dir_tab, const std::wstring & link_
|
||||
for( ; i<link_to.size() && link_to[i] == '/' ; ++i);
|
||||
|
||||
if( i == link_to.size() )
|
||||
return i; // end of the path
|
||||
return true; // end of the path
|
||||
|
||||
// creating a name
|
||||
old_i = i;
|
||||
@@ -488,12 +541,26 @@ size_t Dirs::AnalyzeDir(std::vector<Item*> & dir_tab, const std::wstring & link_
|
||||
for( ; i<link_to.size() && link_to[i] != '/' ; ++i)
|
||||
analyze_temp += link_to[i];
|
||||
|
||||
Item * pdir = GetDir(analyze_temp, dir_tab.back()->id);
|
||||
|
||||
if( !pdir )
|
||||
return old_i; // analyze_temp is not a directory
|
||||
if( analyze_temp == L".." )
|
||||
{
|
||||
if( dir_tab.size() <= 1 )
|
||||
return false;
|
||||
|
||||
dir_tab.push_back(pdir);
|
||||
dir_tab.pop_back();
|
||||
}
|
||||
else
|
||||
if( analyze_temp != L"." )
|
||||
{
|
||||
Item * pdir = GetDir(analyze_temp, dir_tab.back()->id);
|
||||
|
||||
if( !pdir )
|
||||
{
|
||||
i = old_i;
|
||||
return true; // analyze_temp is not a directory
|
||||
}
|
||||
|
||||
dir_tab.push_back(pdir);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -504,7 +571,10 @@ size_t Dirs::AnalyzeDir(std::vector<Item*> & dir_tab, const std::wstring & link_
|
||||
|
||||
int Dirs::FollowLink(std::vector<Item*> & dir_tab, const std::wstring & link_to, std::wstring & out_item)
|
||||
{
|
||||
size_t i = AnalyzeDir(dir_tab, link_to);
|
||||
size_t i;
|
||||
|
||||
if( !AnalyzeDir(dir_tab, link_to, i) )
|
||||
return 2; // incorrect link_to
|
||||
|
||||
if( i < link_to.size() )
|
||||
{
|
||||
@@ -537,7 +607,7 @@ return 0;
|
||||
4 - current_dir_tab was empty
|
||||
|
||||
current_dir_tab can be the same container as out_dir_tab
|
||||
link_to can be a relative path (without the first slash)
|
||||
link_to can be a relative path (without the first slash) and can contain ".." or "."
|
||||
*/
|
||||
int Dirs::FollowLink(const std::vector<Item*> & current_dir_tab, const std::wstring & link_to,
|
||||
std::vector<Item*> & out_dir_tab, std::wstring & out_item)
|
||||
@@ -656,9 +726,9 @@ Item * Dirs::CreateVarDir()
|
||||
if( root )
|
||||
{
|
||||
v.parent_id = root->id;
|
||||
v.user_id = -1;
|
||||
v.group_id = -1;
|
||||
v.privileges = 0755;
|
||||
v.user_id = root->user_id;
|
||||
v.group_id = root->group_id;
|
||||
v.privileges = root->privileges;
|
||||
v.subject = L"var";
|
||||
v.url = L"var";
|
||||
v.type = Item::dir;
|
||||
|
||||
13
core/dirs.h
13
core/dirs.h
@@ -2,7 +2,7 @@
|
||||
* This file is a part of Winix
|
||||
* and is not publicly distributed
|
||||
*
|
||||
* Copyright (c) 2008-2011, Tomasz Sowa
|
||||
* Copyright (c) 2008-2012, Tomasz Sowa
|
||||
* All rights reserved.
|
||||
*
|
||||
*/
|
||||
@@ -40,12 +40,14 @@ public:
|
||||
bool IsDir(long dir_id);
|
||||
bool GetDirChilds(long parent_id, std::vector<Item*> & childs_tab); // !! zamienic na GetChilds()
|
||||
bool MakePath(long dir_id, std::wstring & path, bool clear_path = true);
|
||||
void MakePath(const std::vector<Item*> dir_tab, std::wstring & path, bool clear_path = true);
|
||||
bool ChangeParent(long dir_id, long new_parent_id);
|
||||
|
||||
bool HasParent(long dir_id, long parent_id);
|
||||
|
||||
bool DelDir(long dir_id);
|
||||
|
||||
// if returns true then out_dir_tab is not empty
|
||||
bool CreateDirTab(long dir_id, std::vector<Item*> & out_dir_tab);
|
||||
|
||||
void LogDir(const std::vector<Item*> & dir_tab);
|
||||
@@ -65,7 +67,10 @@ public:
|
||||
Item * GetRootDir();
|
||||
Item * GetEtcDir();
|
||||
Item * GetVarDir();
|
||||
|
||||
Item * GetDir(const wchar_t * name, long parent);
|
||||
Item * GetDir(const std::wstring & name, long parent);
|
||||
Item * GetDir(const wchar_t * path);
|
||||
Item * GetDir(const std::wstring & path);
|
||||
Item * GetDir(long id);
|
||||
Item * AddDir(const Item & item);
|
||||
@@ -83,6 +88,9 @@ public:
|
||||
// "/abc/def" -> 2
|
||||
size_t DirLevel(long id);
|
||||
|
||||
// checking if child_id is really a child of parent_id
|
||||
bool IsChild(long parent_id, long child_id);
|
||||
|
||||
private:
|
||||
|
||||
Cur * cur;
|
||||
@@ -94,8 +102,9 @@ private:
|
||||
std::wstring temp_link_to;
|
||||
|
||||
size_t AnalyzeDir(Item * pdir, const std::wstring & path, long & dir_id, std::wstring & dir);
|
||||
size_t AnalyzeDir(std::vector<Item*> & dir_tab, const std::wstring & link_to);
|
||||
bool AnalyzeDir(std::vector<Item*> & dir_tab, const std::wstring & link_to, size_t & i);
|
||||
std::wstring analyze_temp;
|
||||
std::wstring get_dir_temp;
|
||||
|
||||
void CopyDirTab(const std::vector<Item*> & in, std::vector<Item*> & out);
|
||||
int FollowLink(std::vector<Item*> & dir_tab, const std::wstring & link_to, std::wstring & out_item);
|
||||
|
||||
10
core/error.h
10
core/error.h
@@ -48,10 +48,10 @@
|
||||
|
||||
#define WINIX_ERR_NO_TICKET 24
|
||||
|
||||
#define WINIX_ERR_PASSWORDS_DIFFERENT 25
|
||||
#define WINIX_ERR_PASSWORD_TOO_SHORT 26
|
||||
#define WINIX_ERR_USER_EXISTS 27
|
||||
#define WINIX_ERR_LOGIN_EMPTY 28
|
||||
//#define WINIX_ERR_PASSWORDS_DIFFERENT 25
|
||||
//#define WINIX_ERR_PASSWORD_TOO_SHORT 26
|
||||
//#define WINIX_ERR_USER_EXISTS 27
|
||||
//#define WINIX_ERR_LOGIN_EMPTY 28
|
||||
#define WINIX_DIFFERENT_MOUNT_POINTS 29
|
||||
|
||||
|
||||
@@ -68,7 +68,9 @@
|
||||
|
||||
//#define WINIX_ERR_UNKNOWN 1000
|
||||
#define WINIX_NOTHING_TO_DO 109
|
||||
#define WINIX_ERR_INCORRECT_URI 110
|
||||
|
||||
#define WINIX_ERR_INTERNAL_ERROR 2000
|
||||
|
||||
|
||||
typedef int Error;
|
||||
|
||||
@@ -1,87 +0,0 @@
|
||||
/*
|
||||
* This file is a part of Winix
|
||||
* and is not publicly distributed
|
||||
*
|
||||
* Copyright (c) 2008-2010, Tomasz Sowa
|
||||
* All rights reserved.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef headerfile_winix_core_getparser
|
||||
#define headerfile_winix_core_getparser
|
||||
|
||||
#include "httpsimpleparser.h"
|
||||
#include "requesttypes.h"
|
||||
#include "misc.h"
|
||||
#include "utf8.h"
|
||||
#include "log.h"
|
||||
|
||||
|
||||
class GetParser : public HttpSimpleParser
|
||||
{
|
||||
|
||||
const char * get_string;
|
||||
GetTab * get_tab;
|
||||
std::wstring temp;
|
||||
bool input_as_utf8;
|
||||
|
||||
protected:
|
||||
|
||||
virtual int GetChar()
|
||||
{
|
||||
if( !get_string || *get_string == 0 )
|
||||
return -1;
|
||||
|
||||
return (int)(unsigned char)*(get_string++);
|
||||
}
|
||||
|
||||
|
||||
virtual void Parameter(std::string &, std::string & value)
|
||||
{
|
||||
if( input_as_utf8 )
|
||||
Ezc::UTF8ToWide(value, temp);
|
||||
else
|
||||
AssignString(value, temp);
|
||||
|
||||
get_tab->push_back(temp);
|
||||
log << log2 << "Get, value: \"" << temp << "\"" << logend;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public:
|
||||
|
||||
|
||||
GetParser()
|
||||
{
|
||||
HttpSimpleParser::separator = '/';
|
||||
HttpSimpleParser::read_name = false;
|
||||
input_as_utf8 = false;
|
||||
}
|
||||
|
||||
|
||||
void UTF8(bool utf)
|
||||
{
|
||||
input_as_utf8 = utf;
|
||||
}
|
||||
|
||||
|
||||
// get_string_ can be null
|
||||
void Parse(const char * get_string_, GetTab & get_tab_)
|
||||
{
|
||||
get_string = get_string_;
|
||||
get_tab = &get_tab_;
|
||||
|
||||
if( get_string && *get_string == separator )
|
||||
{
|
||||
// skipping one '/' at the beginning
|
||||
++get_string;
|
||||
}
|
||||
|
||||
HttpSimpleParser::Parse();
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
@@ -2,7 +2,7 @@
|
||||
* This file is a part of Winix
|
||||
* and is not publicly distributed
|
||||
*
|
||||
* Copyright (c) 2008-2010, Tomasz Sowa
|
||||
* Copyright (c) 2008-2012, Tomasz Sowa
|
||||
* All rights reserved.
|
||||
*
|
||||
*/
|
||||
@@ -86,9 +86,9 @@ Groups::SizeType Groups::Size()
|
||||
}
|
||||
|
||||
|
||||
Group & Groups::operator[](Groups::SizeType pos)
|
||||
bool Groups::Remove(long group_id)
|
||||
{
|
||||
return table[pos];
|
||||
return table.Remove(group_id);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* This file is a part of Winix
|
||||
* and is not publicly distributed
|
||||
*
|
||||
* Copyright (c) 2008-2010, Tomasz Sowa
|
||||
* Copyright (c) 2008-2012, Tomasz Sowa
|
||||
* All rights reserved.
|
||||
*
|
||||
*/
|
||||
@@ -38,7 +38,7 @@ public:
|
||||
Iterator Begin();
|
||||
Iterator End();
|
||||
SizeType Size();
|
||||
Group & operator[](SizeType pos);
|
||||
bool Remove(long group_id);
|
||||
|
||||
};
|
||||
|
||||
|
||||
@@ -1202,6 +1202,7 @@ void HTMLFilter::CheckExceptions()
|
||||
IsLastTag(L"img") ||
|
||||
IsLastTag(L"link") ||
|
||||
IsLastTag(L"param") ||
|
||||
IsLastTag(L"col") ||
|
||||
IsLastTag(L"area") )
|
||||
{
|
||||
LastItem().type = Item::simple;
|
||||
|
||||
415
core/image.cpp
Executable file
415
core/image.cpp
Executable file
@@ -0,0 +1,415 @@
|
||||
/*
|
||||
* This file is a part of Winix
|
||||
* and is not publicly distributed
|
||||
*
|
||||
* Copyright (c) 2010-2012, Tomasz Sowa
|
||||
* All rights reserved.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <ctime>
|
||||
#include "image.h"
|
||||
#include "utf8/utf8.h"
|
||||
#include "log.h"
|
||||
#include "system.h"
|
||||
#include "plugin.h"
|
||||
|
||||
|
||||
|
||||
|
||||
void Image::SetDb(Db * pdb)
|
||||
{
|
||||
db = pdb;
|
||||
}
|
||||
|
||||
|
||||
void Image::SetConfig(Config * pconfig)
|
||||
{
|
||||
config = pconfig;
|
||||
}
|
||||
|
||||
|
||||
void Image::SetSystem(System * psystem)
|
||||
{
|
||||
system = psystem;
|
||||
}
|
||||
|
||||
|
||||
// first thread (objects locked)
|
||||
void Image::Resize(const Item & item, size_t cx, size_t cy, int aspect_mode, int quality)
|
||||
{
|
||||
item_temp.type = WINIX_IMAGE_TYPE_RESIZE;
|
||||
item_temp.file = item;
|
||||
item_temp.cx = cx;
|
||||
item_temp.cy = cy;
|
||||
item_temp.aspect_mode = aspect_mode;
|
||||
item_temp.quality = quality;
|
||||
|
||||
CheckParam(item_temp);
|
||||
image_tab.insert(image_tab.end(), item_temp);
|
||||
WakeUpThread();
|
||||
}
|
||||
|
||||
|
||||
// first thread (objects locked)
|
||||
void Image::CreateThumb(const Item & item, size_t cx, size_t cy, int aspect_mode, int quality)
|
||||
{
|
||||
item_temp.type = WINIX_IMAGE_TYPE_CREATE_THUMB;
|
||||
item_temp.file = item;
|
||||
item_temp.cx = cx;
|
||||
item_temp.cy = cy;
|
||||
item_temp.aspect_mode = aspect_mode;
|
||||
item_temp.quality = quality;
|
||||
|
||||
CheckParam(item_temp);
|
||||
image_tab.insert(image_tab.end(), item_temp);
|
||||
WakeUpThread();
|
||||
}
|
||||
|
||||
|
||||
|
||||
void Image::CheckParam(ImageItem & item)
|
||||
{
|
||||
if( item.aspect_mode < 1 )
|
||||
item.aspect_mode = 1;
|
||||
|
||||
if( item.aspect_mode > 7 )
|
||||
item.aspect_mode = 7;
|
||||
|
||||
if( item.quality < 0 )
|
||||
item.quality = 0;
|
||||
|
||||
if( item.quality > 100 )
|
||||
item.quality = 100;
|
||||
|
||||
if( item_temp.cx < 5 )
|
||||
item_temp.cx = 5;
|
||||
|
||||
if( item_temp.cy < 5 )
|
||||
item_temp.cy = 5;
|
||||
|
||||
if( item_temp.cx > 10000 )
|
||||
item_temp.cx = 10000;
|
||||
|
||||
if( item_temp.cy > 10000 )
|
||||
item_temp.cy = 10000;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// second thread (objects locked)
|
||||
bool Image::SignalReceived()
|
||||
{
|
||||
return !image_tab.empty();
|
||||
}
|
||||
|
||||
|
||||
|
||||
// second thread (objects not locked)
|
||||
void Image::Do()
|
||||
{
|
||||
ImageTab::iterator i;
|
||||
bool end;
|
||||
|
||||
Lock();
|
||||
i = image_tab.begin();
|
||||
Unlock();
|
||||
|
||||
do
|
||||
{
|
||||
Lock();
|
||||
|
||||
if( i != image_tab.end() )
|
||||
{
|
||||
item_work = *i;
|
||||
image_tab.erase(i++);
|
||||
end = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
end = true;
|
||||
}
|
||||
|
||||
Unlock();
|
||||
|
||||
if( !end )
|
||||
CreateImage();
|
||||
|
||||
}
|
||||
while( !end && !IsExitSignal() );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void Image::Add(const std::wstring & in, TextStream<std::string> & out)
|
||||
{
|
||||
PT::WideToUTF8(in, add_tempa);
|
||||
out << add_tempa;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void Image::EscapePath(const std::string & path, TextStream<std::string> & out, bool clear_stream)
|
||||
{
|
||||
if( clear_stream )
|
||||
out.Clear();
|
||||
|
||||
out << '"';
|
||||
|
||||
for(size_t i=0 ; i<path.size() ; ++i)
|
||||
{
|
||||
if( path[i] == '"' )
|
||||
out << '\\';
|
||||
|
||||
out << path[i];
|
||||
}
|
||||
|
||||
out << '\"';
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
from: http://www.imagemagick.org/script/command-line-processing.php#geometry
|
||||
|
||||
scale% Height and width both scaled by specified percentage.
|
||||
scale-x%xscale-y% Height and width individually scaled by specified percentages. (Only one % symbol needed.)
|
||||
width Width given, height automagically selected to preserve aspect ratio.
|
||||
xheight Height given, width automagically selected to preserve aspect ratio.
|
||||
widthxheight Maximum values of height and width given, aspect ratio preserved.
|
||||
widthxheight^ Minimum values of width and height given, aspect ratio preserved.
|
||||
widthxheight! Width and height emphatically given, original aspect ratio ignored.
|
||||
widthxheight> Change as per widthxheight but only if an image dimension exceeds a specified dimension.
|
||||
widthxheight< Change dimensions only if both image dimensions exceed specified dimensions.
|
||||
*/
|
||||
void Image::SelectAspect()
|
||||
{
|
||||
switch( item_work.aspect_mode )
|
||||
{
|
||||
case WINIX_IMAGE_MODE_1:
|
||||
command << item_work.cx;
|
||||
break;
|
||||
|
||||
case WINIX_IMAGE_MODE_3:
|
||||
command << item_work.cx << "x" << item_work.cy;
|
||||
break;
|
||||
|
||||
case WINIX_IMAGE_MODE_4:
|
||||
command << '"' << item_work.cx << "x" << item_work.cy << "^\"";
|
||||
break;
|
||||
|
||||
case WINIX_IMAGE_MODE_5:
|
||||
command << '"' << item_work.cx << "x" << item_work.cy << "!\"";
|
||||
break;
|
||||
|
||||
case WINIX_IMAGE_MODE_6:
|
||||
command << '"' << item_work.cx << "x" << item_work.cy << ">\"";
|
||||
break;
|
||||
|
||||
case WINIX_IMAGE_MODE_7:
|
||||
command << '"' << item_work.cx << "x" << item_work.cy << "<\"";
|
||||
break;
|
||||
|
||||
case WINIX_IMAGE_MODE_2:
|
||||
default:
|
||||
command << "x" << item_work.cy;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// second thread (objects locked)
|
||||
bool Image::CreateInputFileName()
|
||||
{
|
||||
if( system->MakeFilePath(item_work.file, src_path) )
|
||||
{
|
||||
PT::WideToUTF8(src_path, input_file_name);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
log << log1 << "Image: cannot create a source path" << logend;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// second thread (objects locked)
|
||||
void Image::CreateTmpFileName()
|
||||
{
|
||||
stream_tmp_path.Clear();
|
||||
stream_tmp_path << config->upload_dir << L"/tmp/image_" << std::time(0);
|
||||
PT::WideToUTF8(stream_tmp_path.Str(), tmp_file_name);
|
||||
}
|
||||
|
||||
|
||||
|
||||
// second thread (objects are not locked)
|
||||
bool Image::CreateCommand()
|
||||
{
|
||||
Lock();
|
||||
|
||||
iq.SetAll(true, false);
|
||||
iq.WhereId(item_work.file.id);
|
||||
|
||||
// !! skoro teraz i tak wczytujemy caly obiekt
|
||||
// to teraz w kolejce wystarczy zapamietywac tylko samo item.id (a nie caly obiekt item)
|
||||
|
||||
// the file could have been changed especially when there is a long queue of files
|
||||
if( db->GetItem(item_work.file, iq) != WINIX_ERR_OK )
|
||||
{
|
||||
Unlock();
|
||||
return false;
|
||||
}
|
||||
|
||||
if( !CreateInputFileName() )
|
||||
{
|
||||
Unlock();
|
||||
return false;
|
||||
}
|
||||
|
||||
command.Clear();
|
||||
Add(config->convert_cmd, command);
|
||||
|
||||
command << " ";
|
||||
EscapePath(input_file_name, command, false);
|
||||
command << " -quiet -quality " << item_work.quality;
|
||||
|
||||
if( item_work.type == WINIX_IMAGE_TYPE_RESIZE )
|
||||
command << " -resize ";
|
||||
else
|
||||
command << " -strip -thumbnail ";
|
||||
|
||||
SelectAspect();
|
||||
CreateTmpFileName();
|
||||
|
||||
command << " ";
|
||||
EscapePath(tmp_file_name, command, false);
|
||||
|
||||
log << log4 << "Image: running: " << command.Str() << logend;
|
||||
|
||||
Unlock();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// second thread (objects are not locked)
|
||||
void Image::SaveImage()
|
||||
{
|
||||
bool moved = false;
|
||||
|
||||
Lock();
|
||||
|
||||
// the file could have been changed especially when creating the image lasted too long
|
||||
iq.SetAll(true, false);
|
||||
iq.WhereId(item_work.file.id);
|
||||
|
||||
if( db->GetItem(item_work.file, iq) == WINIX_ERR_OK )
|
||||
{
|
||||
bool thumb = (item_work.type == WINIX_IMAGE_TYPE_CREATE_THUMB);
|
||||
|
||||
if( system->MakeFilePath(item_work.file, dst_path, thumb, true, config->upload_dirs_chmod) )
|
||||
{
|
||||
if( RenameFile(stream_tmp_path.Str(), dst_path) )
|
||||
{
|
||||
if( thumb )
|
||||
{
|
||||
item_work.file.has_thumb = true;
|
||||
db->EditHasThumbById(true, item_work.file.id);
|
||||
log << log3 << "Image: generated a thumbnail: " << dst_path << logend;
|
||||
plugin.Call((Session*)0, WINIX_CREATED_THUMB, &item_work.file);
|
||||
}
|
||||
else
|
||||
{
|
||||
log << log3 << "Image: image resized: " << dst_path << logend;
|
||||
plugin.Call((Session*)0, WINIX_IMAGE_RESIZED, &item_work.file);
|
||||
}
|
||||
|
||||
moved = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
log << log1 << "Image: cannot move a temporary file: " << stream_tmp_path.Str() << ", to: " << dst_path << logend;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
log << log1 << "Image: cannot create a destination path" << logend;
|
||||
}
|
||||
}
|
||||
|
||||
if( !moved )
|
||||
::RemoveFile(stream_tmp_path.Str());
|
||||
|
||||
Unlock();
|
||||
}
|
||||
|
||||
|
||||
|
||||
// second thread (objects are not locked)
|
||||
void Image::CreateImage()
|
||||
{
|
||||
if( !CreateCommand() )
|
||||
return;
|
||||
|
||||
int res = std::system(command.CStr());
|
||||
|
||||
if( res == 0 )
|
||||
{
|
||||
SaveImage();
|
||||
}
|
||||
else
|
||||
{
|
||||
Lock();
|
||||
log << log3 << "Image: some problems with creating an image"
|
||||
<< ", 'convert' process returned: " << res << logend;
|
||||
Unlock();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// second thread (objects are not locked)
|
||||
// !! there is a problem with GIF files
|
||||
// Bus error (core dumped)
|
||||
/*
|
||||
#include "wand/MagickWand.h"
|
||||
|
||||
// compiler options:
|
||||
// include: -I/usr/local/include/ImageMagick
|
||||
// link with: `MagickWand-config --ldflags --libs`
|
||||
|
||||
void Image::CreateThumbnail()
|
||||
{
|
||||
PT::WideToUTF8(item_work.source, sourcea);
|
||||
PT::WideToUTF8(item_work.dst, dsta);
|
||||
|
||||
MagickWandGenesis();
|
||||
|
||||
MagickWand * wand = NewMagickWand();
|
||||
|
||||
if( MagickReadImage(wand, sourcea.c_str()) )
|
||||
{
|
||||
MagickThumbnailImage(wand, item_work.cx, item_work.cy);
|
||||
|
||||
if( MagickWriteImage(wand, dsta.c_str()) )
|
||||
{
|
||||
Lock();
|
||||
log << log3 << "Image: created a thumbnail: " << dsta << logend;
|
||||
Unlock();
|
||||
}
|
||||
}
|
||||
|
||||
DestroyMagickWand(wand);
|
||||
|
||||
MagickWandTerminus();
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
@@ -2,13 +2,13 @@
|
||||
* This file is a part of Winix
|
||||
* and is not publicly distributed
|
||||
*
|
||||
* Copyright (c) 2010, Tomasz Sowa
|
||||
* Copyright (c) 2010-2011, Tomasz Sowa
|
||||
* All rights reserved.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef headerfile_winix_core_thumb
|
||||
#define headerfile_winix_core_thumb
|
||||
#ifndef headerfile_winix_core_image
|
||||
#define headerfile_winix_core_image
|
||||
|
||||
#include <string>
|
||||
#include <list>
|
||||
@@ -24,73 +24,90 @@ class System;
|
||||
|
||||
|
||||
// Width given, height automagically selected to preserve aspect ratio.
|
||||
#define WINIX_THUMB_MODE_1 1
|
||||
#define WINIX_IMAGE_MODE_1 1
|
||||
|
||||
// Height given, width automagically selected to preserve aspect ratio.
|
||||
#define WINIX_THUMB_MODE_2 2
|
||||
#define WINIX_IMAGE_MODE_2 2
|
||||
|
||||
// Maximum values of height and width given, aspect ratio preserved.
|
||||
#define WINIX_THUMB_MODE_3 3
|
||||
#define WINIX_IMAGE_MODE_3 3
|
||||
|
||||
// Minimum values of width and height given, aspect ratio preserved.
|
||||
#define WINIX_THUMB_MODE_4 4
|
||||
#define WINIX_IMAGE_MODE_4 4
|
||||
|
||||
// Width and height emphatically given, original aspect ratio ignored.
|
||||
#define WINIX_THUMB_MODE_5 5
|
||||
#define WINIX_IMAGE_MODE_5 5
|
||||
|
||||
// Change as per widthxheight but only if an image dimension exceeds a specified dimension.
|
||||
#define WINIX_THUMB_MODE_6 6
|
||||
#define WINIX_IMAGE_MODE_6 6
|
||||
|
||||
// Change dimensions only if both image dimensions are less than specified dimensions.
|
||||
#define WINIX_THUMB_MODE_7 7
|
||||
#define WINIX_IMAGE_MODE_7 7
|
||||
|
||||
|
||||
// resizing
|
||||
#define WINIX_IMAGE_TYPE_RESIZE 1
|
||||
|
||||
// generating a thumbnail
|
||||
#define WINIX_IMAGE_TYPE_CREATE_THUMB 2
|
||||
|
||||
|
||||
|
||||
|
||||
class Thumb : public BaseThread
|
||||
class Image : public BaseThread
|
||||
{
|
||||
public:
|
||||
|
||||
void CreateThumb(const Item & item, size_t cx, size_t cy, int aspect_mode);
|
||||
|
||||
void SetDb(Db * pdb);
|
||||
void SetConfig(Config * pconfig);
|
||||
void SetSystem(System * psystem);
|
||||
|
||||
void Resize(const Item & item, size_t cx, size_t cy, int aspect_mode, int quality);
|
||||
void CreateThumb(const Item & item, size_t cx, size_t cy, int aspect_mode, int quality);
|
||||
|
||||
|
||||
private:
|
||||
|
||||
Db * db;
|
||||
Config * config;
|
||||
System * system;
|
||||
|
||||
struct ThumbItem
|
||||
struct ImageItem
|
||||
{
|
||||
int type; // WINIX_IMAGE_TYPE_*
|
||||
Item file;
|
||||
size_t cx;
|
||||
size_t cy;
|
||||
int aspect_mode;
|
||||
int quality;
|
||||
};
|
||||
|
||||
// queue of thumbnails to create
|
||||
typedef std::list<ThumbItem> ThumbTab;
|
||||
ThumbTab thumb_tab;
|
||||
ThumbItem item_temp;
|
||||
typedef std::list<ImageItem> ImageTab;
|
||||
ImageTab image_tab;
|
||||
ImageItem item_temp;
|
||||
|
||||
// only for second thread
|
||||
ThumbItem item_work;
|
||||
ImageItem item_work;
|
||||
std::wstring src_path, dst_path;
|
||||
std::string tempa, string_tmp_patha;
|
||||
TextStream<std::string> command;
|
||||
TextStream<std::wstring> stream_tmp_path;
|
||||
DbItemQuery iq;
|
||||
std::string add_tempa;
|
||||
std::string input_file_name;
|
||||
std::string tmp_file_name;
|
||||
|
||||
virtual bool SignalReceived();
|
||||
virtual void Do();
|
||||
bool CreateCommand();
|
||||
void SaveTmpThumbnail();
|
||||
void CreateThumbnail();
|
||||
bool CreateInputFileName();
|
||||
void CreateTmpFileName();
|
||||
void SaveImage();
|
||||
void CreateImage();
|
||||
void SelectAspect();
|
||||
void EscapePath(const std::string & path);
|
||||
void EscapePath(const std::string & path, TextStream<std::string> & out, bool clear_stream = true);
|
||||
void CheckParam(ImageItem & item);
|
||||
void Add(const std::wstring & in, TextStream<std::string> & out);
|
||||
};
|
||||
|
||||
|
||||
148
core/ipban.h
Normal file
148
core/ipban.h
Normal file
@@ -0,0 +1,148 @@
|
||||
/*
|
||||
* This file is a part of Winix
|
||||
* and is not publicly distributed
|
||||
*
|
||||
* Copyright (c) 2012, Tomasz Sowa
|
||||
* All rights reserved.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef headerfile_winix_core_ipban
|
||||
#define headerfile_winix_core_ipban
|
||||
|
||||
|
||||
// telling if the IPBan record is active
|
||||
// we have two records: active and non active
|
||||
// non active records is something like a history
|
||||
// it is used to remember the last ban level
|
||||
// so based on this in the future a next greater ban can be calculated
|
||||
#define WINIX_IPBAN_FLAG_ACTIVE 1
|
||||
|
||||
// current ban level
|
||||
// (if one of these flag is set and the record is active then it means the IP is banned at the moment)
|
||||
// level 1: banned for short time
|
||||
// level 2: can be set after level 1 has expired and the attacker still have not given up
|
||||
// banned for some longer time in level 1
|
||||
// level 3: can be set after level 2
|
||||
// banned for much more time
|
||||
#define WINIX_IPBAN_FLAG_BAN_LEVEL1 2
|
||||
#define WINIX_IPBAN_FLAG_BAN_LEVEL2 4
|
||||
#define WINIX_IPBAN_FLAG_BAN_LEVEL3 8
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
struct defining some restrictions to an IP address
|
||||
*/
|
||||
struct IPBan
|
||||
{
|
||||
// at the moment only IPv4 are supported
|
||||
int ip;
|
||||
|
||||
// one or more flags from WINIX_IPBAN_FLAG_*
|
||||
int flags;
|
||||
|
||||
// when this record was last used
|
||||
time_t last_used;
|
||||
|
||||
// when the restrictions (ban) should be removed
|
||||
// valid only if some of WINIX_IPBAN_FLAG_BAN_LEVELX flags are set
|
||||
// actually we do not remove the record but unsets WINIX_IPBAN_FLAG_ACTIVE flag
|
||||
// so in the future we can check whether we need to change
|
||||
// the ban level to a greater value
|
||||
time_t expires;
|
||||
|
||||
// how many incorrect login attempts there are
|
||||
unsigned int incorrect_login_events;
|
||||
|
||||
// in the future there can be more *_events fields
|
||||
|
||||
|
||||
|
||||
bool HasFlag(int flag) const
|
||||
{
|
||||
return (flags & flag) != 0;
|
||||
}
|
||||
|
||||
|
||||
void SetFlag(int flag)
|
||||
{
|
||||
flags = flags | flag;
|
||||
}
|
||||
|
||||
|
||||
void ClearFlag(int flag)
|
||||
{
|
||||
flags = flags & (~flag);
|
||||
}
|
||||
|
||||
|
||||
bool IsIPBanned() const
|
||||
{
|
||||
if( !HasFlag(WINIX_IPBAN_FLAG_ACTIVE) )
|
||||
return false;
|
||||
|
||||
return HasFlag(WINIX_IPBAN_FLAG_BAN_LEVEL1) ||
|
||||
HasFlag(WINIX_IPBAN_FLAG_BAN_LEVEL2) ||
|
||||
HasFlag(WINIX_IPBAN_FLAG_BAN_LEVEL3);
|
||||
}
|
||||
|
||||
|
||||
void AddNextBanLevel(time_t level1_expires, time_t level2_expires, time_t level3_expires)
|
||||
{
|
||||
if( HasFlag(WINIX_IPBAN_FLAG_BAN_LEVEL3) )
|
||||
{
|
||||
expires = level3_expires;
|
||||
return;
|
||||
}
|
||||
else
|
||||
if( HasFlag(WINIX_IPBAN_FLAG_BAN_LEVEL2) )
|
||||
{
|
||||
SetFlag(WINIX_IPBAN_FLAG_BAN_LEVEL3);
|
||||
expires = level3_expires;
|
||||
return;
|
||||
}
|
||||
else
|
||||
if( HasFlag(WINIX_IPBAN_FLAG_BAN_LEVEL1) )
|
||||
{
|
||||
SetFlag(WINIX_IPBAN_FLAG_BAN_LEVEL2);
|
||||
expires = level2_expires;
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
SetFlag(WINIX_IPBAN_FLAG_BAN_LEVEL1);
|
||||
expires = level1_expires;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
IPBan()
|
||||
{
|
||||
Clear();
|
||||
}
|
||||
|
||||
|
||||
void Clear()
|
||||
{
|
||||
ip = 0;
|
||||
flags = 0;
|
||||
last_used = 0;
|
||||
expires = 0;
|
||||
incorrect_login_events = 0;
|
||||
}
|
||||
|
||||
|
||||
void ClearAfterRemovingBan()
|
||||
{
|
||||
ClearFlag(WINIX_IPBAN_FLAG_ACTIVE);
|
||||
incorrect_login_events = 0;
|
||||
expires = 0;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
221
core/ipbancontainer.cpp
Normal file
221
core/ipbancontainer.cpp
Normal file
@@ -0,0 +1,221 @@
|
||||
/*
|
||||
* This file is a part of Winix
|
||||
* and is not publicly distributed
|
||||
*
|
||||
* Copyright (c) 2012, Tomasz Sowa
|
||||
* All rights reserved.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <algorithm>
|
||||
#include "ipbancontainer.h"
|
||||
#include "log.h"
|
||||
#include "date/date.h"
|
||||
|
||||
|
||||
|
||||
IPBanContainer::IPBanContainer()
|
||||
{
|
||||
is_ipban_tab_sorted = true; // an empty list is sorted
|
||||
soft_max_size = 100;
|
||||
max_size = 110;
|
||||
}
|
||||
|
||||
|
||||
void IPBanContainer::SetMaxSize(size_t soft_size, size_t size)
|
||||
{
|
||||
soft_max_size = soft_size;
|
||||
max_size = size;
|
||||
|
||||
if( max_size < soft_max_size )
|
||||
max_size = soft_max_size + 1;
|
||||
|
||||
ipban_tab.reserve(max_size);
|
||||
sort_helper_tab.reserve(max_size);
|
||||
}
|
||||
|
||||
|
||||
// returning a reference to the added (or existed) record
|
||||
IPBan & IPBanContainer::AddIP(int ip)
|
||||
{
|
||||
IPBan * old_ip_ban = FindIP(ip);
|
||||
|
||||
if( !old_ip_ban )
|
||||
{
|
||||
IPBan ip_ban;
|
||||
ip_ban.ip = ip;
|
||||
|
||||
if( ipban_tab.size() >= max_size )
|
||||
RemoveOldRecords();
|
||||
|
||||
ipban_tab.push_back(ip_ban);
|
||||
is_ipban_tab_sorted = false;
|
||||
return ipban_tab.back();
|
||||
}
|
||||
else
|
||||
{
|
||||
return *old_ip_ban;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void IPBanContainer::RemoveIP(int ip)
|
||||
{
|
||||
IPBan * ipban = FindIP(ip);
|
||||
|
||||
if( ipban )
|
||||
{
|
||||
size_t index = ipban - &ipban_tab[0];
|
||||
ipban_tab.erase(ipban_tab.begin() + index);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool IPBanContainer::IsSorted()
|
||||
{
|
||||
return is_ipban_tab_sorted;
|
||||
}
|
||||
|
||||
|
||||
void IPBanContainer::Clear()
|
||||
{
|
||||
ipban_tab.clear();
|
||||
is_ipban_tab_sorted = true;
|
||||
}
|
||||
|
||||
|
||||
// we need to remove some old records for the size of the container
|
||||
// to be less or equal to soft_max_size
|
||||
void IPBanContainer::RemoveOldRecords()
|
||||
{
|
||||
size_t to_remove = 0;
|
||||
|
||||
if( ipban_tab.size() >= soft_max_size )
|
||||
to_remove = ipban_tab.size() - soft_max_size;
|
||||
|
||||
if( to_remove > 0 )
|
||||
{
|
||||
sort_helper_tab.resize(ipban_tab.size());
|
||||
|
||||
for(size_t i=0 ; i<ipban_tab.size() ; ++i)
|
||||
sort_helper_tab[i] = i;
|
||||
|
||||
std::sort(sort_helper_tab.begin(), sort_helper_tab.end(), SortByLastUsedHelper(this));
|
||||
sort_helper_tab.resize(to_remove);
|
||||
std::sort(sort_helper_tab.begin(), sort_helper_tab.end());
|
||||
|
||||
while( to_remove-- > 0 )
|
||||
ipban_tab.erase(ipban_tab.begin() + sort_helper_tab[to_remove]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// for debug purposes
|
||||
void IPBanContainer::PrintTab()
|
||||
{
|
||||
log << log4 << "ipban_tab (size: " << ipban_tab.size() << ")" << logend;
|
||||
|
||||
for(size_t i=0 ; i<ipban_tab.size() ; ++i)
|
||||
{
|
||||
log << log4 << i << ": ip: " << ipban_tab[i].ip << ", flags: " << ipban_tab[i].flags << ", last_used: ";
|
||||
|
||||
PT::Date date(ipban_tab[i].last_used);
|
||||
log << date << ", expires: ";
|
||||
|
||||
date = ipban_tab[i].expires;
|
||||
log << date << logend;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// for debug purposes
|
||||
void IPBanContainer::PrintTab2()
|
||||
{
|
||||
log << log4 << "sort_helper_tab (size: " << sort_helper_tab.size() << ")" << logend;
|
||||
|
||||
for(size_t i=0 ; i<sort_helper_tab.size() ; ++i)
|
||||
{
|
||||
IPBan & ipban = ipban_tab[sort_helper_tab[i]];
|
||||
|
||||
log << log4 << i << ": ip: " << ipban.ip << ", flags: " << ipban.flags << ", last_used: ";
|
||||
|
||||
PT::Date date(ipban.last_used);
|
||||
log << date << ", expires: ";
|
||||
|
||||
date = ipban.expires;
|
||||
log << date << logend;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool IPBanContainer::SortByLastUsedHelper::operator()(size_t index1, size_t index2)
|
||||
{
|
||||
if( index1 < container->ipban_tab.size() &&
|
||||
index2 < container->ipban_tab.size() )
|
||||
{
|
||||
IPBan & ip1 = container->ipban_tab[index1];
|
||||
IPBan & ip2 = container->ipban_tab[index2];
|
||||
|
||||
// prefer to select records which do not have WINIX_IPBAN_FLAG_ACTIVE
|
||||
if( ip1.HasFlag(WINIX_IPBAN_FLAG_ACTIVE) !=
|
||||
ip2.HasFlag(WINIX_IPBAN_FLAG_ACTIVE) )
|
||||
{
|
||||
return ip2.HasFlag(WINIX_IPBAN_FLAG_ACTIVE);
|
||||
}
|
||||
|
||||
return ip1.last_used < ip2.last_used;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
IPBan * IPBanContainer::FindIP(int ip)
|
||||
{
|
||||
// !! IMPROVE ME add binary search if is_ipban_tab_sorted is true
|
||||
|
||||
for(size_t i=0 ; i<ipban_tab.size() ; ++i)
|
||||
{
|
||||
if( ipban_tab[i].ip == ip )
|
||||
{
|
||||
return &ipban_tab[i];
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
IPBan & IPBanContainer::GetIPBan(size_t index)
|
||||
{
|
||||
return ipban_tab[index];
|
||||
}
|
||||
|
||||
|
||||
void IPBanContainer::Sort()
|
||||
{
|
||||
std::sort(ipban_tab.begin(), ipban_tab.end(), SortIPBansFunction);
|
||||
is_ipban_tab_sorted = true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
size_t IPBanContainer::Size()
|
||||
{
|
||||
return ipban_tab.size();
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool IPBanContainer::SortIPBansFunction(const IPBan & ip1, const IPBan & ip2)
|
||||
{
|
||||
return ip1.ip < ip2.ip;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
58
core/ipbancontainer.h
Normal file
58
core/ipbancontainer.h
Normal file
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* This file is a part of Winix
|
||||
* and is not publicly distributed
|
||||
*
|
||||
* Copyright (c) 2012, Tomasz Sowa
|
||||
* All rights reserved.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef headerfile_winix_core_ipbancontainer
|
||||
#define headerfile_winix_core_ipbancontainer
|
||||
|
||||
#include <vector>
|
||||
#include "ipban.h"
|
||||
|
||||
|
||||
|
||||
class IPBanContainer
|
||||
{
|
||||
public:
|
||||
|
||||
IPBanContainer();
|
||||
|
||||
IPBan & AddIP(int ip);
|
||||
IPBan * FindIP(int ip);
|
||||
void Sort();
|
||||
size_t Size();
|
||||
IPBan & GetIPBan(size_t index);
|
||||
void SetMaxSize(size_t soft_size, size_t size);
|
||||
void RemoveIP(int ip);
|
||||
void Clear();
|
||||
bool IsSorted();
|
||||
|
||||
private:
|
||||
|
||||
std::vector<IPBan> ipban_tab;
|
||||
bool is_ipban_tab_sorted;
|
||||
size_t soft_max_size, max_size;
|
||||
std::vector<size_t> sort_helper_tab;
|
||||
|
||||
static bool SortIPBansFunction(const IPBan & ip1, const IPBan & ip2);
|
||||
void RemoveOldRecords();
|
||||
void PrintTab();
|
||||
void PrintTab2();
|
||||
|
||||
struct SortByLastUsedHelper
|
||||
{
|
||||
IPBanContainer * container;
|
||||
|
||||
SortByLastUsedHelper(IPBanContainer * c) : container(c) {}
|
||||
bool operator()(size_t index1, size_t index2);
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
@@ -2,13 +2,14 @@
|
||||
* This file is a part of Winix
|
||||
* and is not publicly distributed
|
||||
*
|
||||
* Copyright (c) 2010, Tomasz Sowa
|
||||
* Copyright (c) 2010-2012, Tomasz Sowa
|
||||
* All rights reserved.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "item.h"
|
||||
#include "misc.h"
|
||||
#include "crypt.h"
|
||||
|
||||
|
||||
|
||||
@@ -18,16 +19,20 @@ Item::Item()
|
||||
}
|
||||
|
||||
|
||||
// !! IMPROVE ME
|
||||
// now we have Request::start_time and Request::start_date
|
||||
// we can somehow get the current time from the request
|
||||
// may setting the date should be completetly removed from here?
|
||||
void Item::SetDateToNow()
|
||||
{
|
||||
date_creation = Time(std::time(0));
|
||||
date_creation = std::time(0);
|
||||
date_modification = date_creation;
|
||||
}
|
||||
|
||||
|
||||
void Item::SetDateModifyToNow()
|
||||
{
|
||||
date_modification = Time(std::time(0));
|
||||
date_modification = std::time(0);
|
||||
}
|
||||
|
||||
|
||||
@@ -61,10 +66,15 @@ void Item::Clear()
|
||||
file_path.clear();
|
||||
file_fs = -1;
|
||||
file_type = WINIX_ITEM_FILETYPE_NONE;
|
||||
|
||||
hash.clear();
|
||||
hash_type = WINIX_CRYPT_HASH_NONE;
|
||||
file_size = 0;
|
||||
has_thumb = false;
|
||||
|
||||
html_template.clear();
|
||||
sort_index = 0;
|
||||
meta.Clear();
|
||||
ameta.Clear();
|
||||
|
||||
SetDateToNow();
|
||||
}
|
||||
|
||||
102
core/item.h
102
core/item.h
@@ -2,7 +2,7 @@
|
||||
* This file is a part of Winix
|
||||
* and is not publicly distributed
|
||||
*
|
||||
* Copyright (c) 2008-2010, Tomasz Sowa
|
||||
* Copyright (c) 2008-2012, Tomasz Sowa
|
||||
* All rights reserved.
|
||||
*
|
||||
*/
|
||||
@@ -11,78 +11,94 @@
|
||||
#define headerfile_winix_core_item
|
||||
|
||||
#include <string>
|
||||
#include "space/space.h"
|
||||
#include "date/date.h"
|
||||
|
||||
|
||||
|
||||
#define WINIX_ITEM_FILETYPE_NONE 0
|
||||
#define WINIX_ITEM_FILETYPE_IMAGE 1
|
||||
#define WINIX_ITEM_FILETYPE_DOCUMENT 2
|
||||
#define WINIX_ITEM_FILETYPE_UNKNOWN 3
|
||||
#define WINIX_ITEM_FILETYPE_VIDEO 3
|
||||
#define WINIX_ITEM_FILETYPE_UNKNOWN 10
|
||||
|
||||
|
||||
|
||||
|
||||
struct Item
|
||||
{
|
||||
long id;
|
||||
long parent_id;
|
||||
long id;
|
||||
long parent_id;
|
||||
|
||||
|
||||
long user_id;
|
||||
long group_id;
|
||||
std::wstring guest_name; // used as a user name when user_id is equal -1
|
||||
long user_id;
|
||||
long group_id;
|
||||
std::wstring guest_name; // used as a user name when user_id is equal -1
|
||||
|
||||
long modification_user_id; // who has modified the item last (not taken into account when checking permissions)
|
||||
long modification_user_id; // who has modified the item last (not taken into account when checking permissions)
|
||||
|
||||
int privileges;
|
||||
int privileges;
|
||||
|
||||
tm date_creation;
|
||||
tm date_modification;
|
||||
PT::Date date_creation;
|
||||
PT::Date date_modification;
|
||||
|
||||
std::wstring subject;
|
||||
std::wstring content;
|
||||
std::wstring subject;
|
||||
std::wstring content;
|
||||
|
||||
std::wstring url;
|
||||
int modify_index;
|
||||
std::wstring url;
|
||||
int modify_index;
|
||||
|
||||
enum ContentType
|
||||
{
|
||||
ct_text = 0,
|
||||
ct_formatted_text,
|
||||
ct_html,
|
||||
ct_bbcode,
|
||||
ct_raw
|
||||
};
|
||||
enum ContentType
|
||||
{
|
||||
ct_text = 0,
|
||||
ct_formatted_text,
|
||||
ct_html,
|
||||
ct_bbcode,
|
||||
ct_raw
|
||||
};
|
||||
|
||||
ContentType content_type;
|
||||
ContentType content_type;
|
||||
|
||||
|
||||
|
||||
enum Type
|
||||
{
|
||||
dir = 0,
|
||||
file = 1,
|
||||
symlink = 2,
|
||||
enum Type
|
||||
{
|
||||
dir = 0,
|
||||
file = 1,
|
||||
symlink = 2,
|
||||
|
||||
none = 1000
|
||||
};
|
||||
none = 1000
|
||||
};
|
||||
|
||||
|
||||
Type type;
|
||||
Type type;
|
||||
|
||||
|
||||
// used when type is symlink or to a directory too (function 'default')
|
||||
std::wstring link_to;
|
||||
int link_redirect;
|
||||
// used when type is symlink or to a directory too (function 'default')
|
||||
std::wstring link_to;
|
||||
int link_redirect;
|
||||
|
||||
|
||||
// static file (if exists)
|
||||
std::wstring file_path; // relative file path
|
||||
int file_fs; // file system type where the file was saved
|
||||
int file_type; // file type (none, image, doc, etc)
|
||||
bool has_thumb;
|
||||
// static file (if exists)
|
||||
std::wstring file_path; // relative file path
|
||||
int file_fs; // file system type where the file was saved
|
||||
int file_type; // file type (none, image, doc, etc)
|
||||
bool has_thumb; // whether or not we have a thumbnail
|
||||
std::wstring hash; // file hash (md4, md5, ...)
|
||||
int hash_type; // hash type WINIX_CRYPT_HASH_* (see crypt.h)
|
||||
size_t file_size; // size of the file
|
||||
|
||||
|
||||
std::wstring html_template;
|
||||
std::wstring html_template;
|
||||
|
||||
|
||||
// sort index used when displaying a group of items
|
||||
int sort_index;
|
||||
|
||||
|
||||
// meta information
|
||||
PT::Space meta;
|
||||
PT::Space ameta;
|
||||
|
||||
|
||||
// methods
|
||||
@@ -97,8 +113,8 @@ private:
|
||||
long content_id; // content id in 'content' table
|
||||
int ref; // content references
|
||||
|
||||
friend class Db;
|
||||
friend class DbItemColumns;
|
||||
friend class Db;
|
||||
friend struct DbItemColumns;
|
||||
};
|
||||
|
||||
|
||||
|
||||
165
core/job.cpp
Executable file
165
core/job.cpp
Executable file
@@ -0,0 +1,165 @@
|
||||
/*
|
||||
* This file is a part of Winix
|
||||
* and is not publicly distributed
|
||||
*
|
||||
* Copyright (c) 2012, Tomasz Sowa
|
||||
* All rights reserved.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "job.h"
|
||||
#include "plugin.h"
|
||||
#include "log.h"
|
||||
|
||||
|
||||
|
||||
Job::Job()
|
||||
{
|
||||
jobs_queue_tab.resize(WINIX_JOBS_HOW_MANY_PRIORITIES);
|
||||
}
|
||||
|
||||
|
||||
void Job::CheckPriority(int & priority) const
|
||||
{
|
||||
if( priority < 0 )
|
||||
priority = 0;
|
||||
|
||||
if( priority >= WINIX_JOBS_HOW_MANY_PRIORITIES )
|
||||
priority = WINIX_JOBS_HOW_MANY_PRIORITIES - 1;
|
||||
}
|
||||
|
||||
|
||||
// first thread (objects locked)
|
||||
void Job::Add(PT::Space & job, int priority)
|
||||
{
|
||||
CheckPriority(priority);
|
||||
jobs_queue_tab[priority].push(job);
|
||||
WakeUpThread();
|
||||
}
|
||||
|
||||
|
||||
|
||||
size_t Job::Size(int priority) const
|
||||
{
|
||||
CheckPriority(priority);
|
||||
return jobs_queue_tab[priority].size();
|
||||
}
|
||||
|
||||
|
||||
|
||||
size_t Job::Size() const
|
||||
{
|
||||
size_t sum = 0;
|
||||
|
||||
for(size_t i=0 ; i<WINIX_JOBS_HOW_MANY_PRIORITIES ; ++i)
|
||||
sum += Size(i);
|
||||
|
||||
return sum;
|
||||
}
|
||||
|
||||
|
||||
bool Job::Empty(int priority) const
|
||||
{
|
||||
CheckPriority(priority);
|
||||
return jobs_queue_tab[priority].empty();
|
||||
}
|
||||
|
||||
|
||||
bool Job::Empty() const
|
||||
{
|
||||
for(size_t i=0 ; i<WINIX_JOBS_HOW_MANY_PRIORITIES ; ++i)
|
||||
if( !Empty(i) )
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
second thread
|
||||
*/
|
||||
|
||||
// second thread (objects locked)
|
||||
bool Job::SignalReceived()
|
||||
{
|
||||
return !Empty();
|
||||
}
|
||||
|
||||
|
||||
// second thread (objects not locked)
|
||||
void Job::Do()
|
||||
{
|
||||
size_t i = WINIX_JOBS_HOW_MANY_PRIORITIES;
|
||||
bool is_empty;
|
||||
|
||||
while( i-- > 0 && !IsExitSignal() )
|
||||
{
|
||||
do
|
||||
{
|
||||
Lock();
|
||||
is_empty = Empty(i);
|
||||
Unlock();
|
||||
|
||||
if( !is_empty )
|
||||
DoQueue(jobs_queue_tab[i]);
|
||||
}
|
||||
while( !is_empty && !IsExitSignal() );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// second thread (objects not locked, jobs_queue is not empty)
|
||||
void Job::DoQueue(JobsQueue & jobs_queue)
|
||||
{
|
||||
bool is_empty;
|
||||
|
||||
do
|
||||
{
|
||||
Lock();
|
||||
// references will not be invalidated after insertion to jobs_queue
|
||||
// (jobs_queue is std::queue and it uses std::deque by default)
|
||||
PT::Space & job = jobs_queue.front();
|
||||
Unlock();
|
||||
|
||||
DoJob(job);
|
||||
|
||||
Lock();
|
||||
jobs_queue.pop();
|
||||
is_empty = jobs_queue.empty();
|
||||
Unlock();
|
||||
}
|
||||
while( !is_empty && !IsExitSignal() );
|
||||
}
|
||||
|
||||
|
||||
// second thread (objects not locked)
|
||||
void Job::DoJob(PT::Space & job)
|
||||
{
|
||||
try
|
||||
{
|
||||
PluginRes res = plugin.Call((Session*)0, WINIX_JOB, &job);
|
||||
|
||||
if( res.res_true == 0 )
|
||||
DoWinixJob(job);
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// second thread (objects not locked)
|
||||
void Job::DoWinixJob(PT::Space & job)
|
||||
{
|
||||
Lock();
|
||||
//log << log1 << "standard winix job: " << job.Text(L"type") << logend;
|
||||
Unlock();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
82
core/job.h
Executable file
82
core/job.h
Executable file
@@ -0,0 +1,82 @@
|
||||
/*
|
||||
* This file is a part of Winix
|
||||
* and is not publicly distributed
|
||||
*
|
||||
* Copyright (c) 2012, Tomasz Sowa
|
||||
* All rights reserved.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef headerfile_winix_core_jobs
|
||||
#define headerfile_winix_core_jobs
|
||||
|
||||
#include <vector>
|
||||
#include <queue>
|
||||
#include "basethread.h"
|
||||
#include "space/space.h"
|
||||
|
||||
|
||||
|
||||
#define WINIX_JOBS_HOW_MANY_PRIORITIES 32
|
||||
|
||||
|
||||
|
||||
|
||||
class Job : public BaseThread
|
||||
{
|
||||
public:
|
||||
|
||||
Job();
|
||||
|
||||
/*
|
||||
add a new job to the queue
|
||||
priority: 0-31 (0 - the lowest priority, 31 - the highest priority)
|
||||
*/
|
||||
void Add(PT::Space & job, int priority = 0);
|
||||
|
||||
|
||||
/*
|
||||
queue size, and size of all jobs in any priority
|
||||
*/
|
||||
size_t Size(int priority) const;
|
||||
size_t Size() const;
|
||||
|
||||
|
||||
/*
|
||||
true if specified queue is empty
|
||||
or if all queues are empty
|
||||
*/
|
||||
bool Empty(int priority) const;
|
||||
bool Empty() const;
|
||||
|
||||
|
||||
private:
|
||||
|
||||
typedef std::queue<PT::Space> JobsQueue;
|
||||
typedef std::vector<JobsQueue> JobsQueueTab;
|
||||
JobsQueueTab jobs_queue_tab;
|
||||
|
||||
void CheckPriority(int & priority) const;
|
||||
void SaveToFile();
|
||||
void ReadFromFile();
|
||||
|
||||
|
||||
/*
|
||||
second thread
|
||||
*/
|
||||
|
||||
// standard winix jobs
|
||||
// Image image;
|
||||
// sending emails
|
||||
// etc.
|
||||
|
||||
bool SignalReceived();
|
||||
void Do();
|
||||
void DoQueue(JobsQueue & jobs_queue);
|
||||
void DoJob(PT::Space & job);
|
||||
void DoWinixJob(PT::Space & job);
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -18,23 +18,12 @@ LastItem::LastItem()
|
||||
user_id = 0;
|
||||
ip = 0;
|
||||
session_id = 0;
|
||||
memset((char*)&start, 0, sizeof(start));
|
||||
memset((char*)&end, 0, sizeof(end));
|
||||
}
|
||||
|
||||
|
||||
bool LastItem::IsLoggedOut()
|
||||
{
|
||||
if( end.tm_sec == 0 &&
|
||||
end.tm_min == 0 &&
|
||||
end.tm_hour == 0 &&
|
||||
end.tm_mday == 0 &&
|
||||
end.tm_mon == 0 &&
|
||||
end.tm_year == 0 )
|
||||
|
||||
return false;
|
||||
|
||||
return true;
|
||||
return end.year > 1970;
|
||||
}
|
||||
|
||||
|
||||
@@ -87,7 +76,7 @@ LastTab::iterator i = FindNotLoggedOut(user_id, session_id);
|
||||
li.name = name;
|
||||
li.ip = ip;
|
||||
li.session_id = session_id;
|
||||
li.start = Time(std::time(0));
|
||||
li.start = std::time(0);
|
||||
|
||||
last_tab.insert(last_tab.end(), li);
|
||||
|
||||
@@ -103,10 +92,17 @@ LastTab::iterator i = FindNotLoggedOut(user_id, session_id);
|
||||
|
||||
if( i != last_tab.end() )
|
||||
{
|
||||
i->end = Time(std::time(0));
|
||||
i->end = std::time(0);
|
||||
}
|
||||
else
|
||||
{
|
||||
log << log4 << "LC: there is no such a user to log out" << logend;
|
||||
/*
|
||||
!! IMPROVE ME
|
||||
users read from the session file (at boot time)
|
||||
are not added to LastContainer
|
||||
*/
|
||||
|
||||
log << log4 << "LC: there is no such a user to log out: user_id: "
|
||||
<< user_id << " ses_id: " << session_id << logend;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
#include <list>
|
||||
#include <cstring>
|
||||
#include <ctime>
|
||||
#include "date/date.h"
|
||||
|
||||
|
||||
|
||||
@@ -37,8 +38,8 @@ struct LastItem
|
||||
long session_id;
|
||||
|
||||
// start logging and end logging
|
||||
tm start;
|
||||
tm end;
|
||||
PT::Date start;
|
||||
PT::Date end;
|
||||
|
||||
|
||||
LastItem();
|
||||
|
||||
49
core/lock.cpp
Executable file
49
core/lock.cpp
Executable file
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* This file is a part of Winix
|
||||
* and is not publicly distributed
|
||||
*
|
||||
* Copyright (c) 2012, Tomasz Sowa
|
||||
* All rights reserved.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "lock.h"
|
||||
|
||||
|
||||
|
||||
Lock::Lock()
|
||||
{
|
||||
synchro = 0;
|
||||
}
|
||||
|
||||
|
||||
Lock::Lock(Synchro * synchro_)
|
||||
{
|
||||
synchro = synchro_;
|
||||
synchro->Lock();
|
||||
}
|
||||
|
||||
|
||||
Lock::Lock(Synchro & synchro_)
|
||||
{
|
||||
synchro = &synchro_;
|
||||
synchro->Lock();
|
||||
}
|
||||
|
||||
|
||||
Lock::~Lock()
|
||||
{
|
||||
Unlock();
|
||||
}
|
||||
|
||||
|
||||
void Lock::Unlock()
|
||||
{
|
||||
if( synchro )
|
||||
{
|
||||
synchro->Unlock();
|
||||
synchro = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
37
core/lock.h
Executable file
37
core/lock.h
Executable file
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* This file is a part of Winix
|
||||
* and is not publicly distributed
|
||||
*
|
||||
* Copyright (c) 2012, Tomasz Sowa
|
||||
* All rights reserved.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef headerfile_winix_core_lock
|
||||
#define headerfile_winix_core_lock
|
||||
|
||||
#include "synchro.h"
|
||||
|
||||
|
||||
class Lock
|
||||
{
|
||||
public:
|
||||
|
||||
Lock(Synchro * synchro_);
|
||||
Lock(Synchro & synchro_);
|
||||
|
||||
~Lock();
|
||||
|
||||
void Unlock();
|
||||
|
||||
|
||||
private:
|
||||
|
||||
Synchro * synchro;
|
||||
|
||||
Lock();
|
||||
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
155
core/log.cpp
155
core/log.cpp
@@ -2,7 +2,7 @@
|
||||
* This file is a part of Winix
|
||||
* and is not publicly distributed
|
||||
*
|
||||
* Copyright (c) 2008-2011, Tomasz Sowa
|
||||
* Copyright (c) 2008-2012, Tomasz Sowa
|
||||
* All rights reserved.
|
||||
*
|
||||
*/
|
||||
@@ -10,7 +10,8 @@
|
||||
#include "log.h"
|
||||
#include <ctime>
|
||||
#include <string.h>
|
||||
#include "utf8.h"
|
||||
#include "utf8/utf8.h"
|
||||
#include "timezones.h"
|
||||
|
||||
|
||||
Log::Log()
|
||||
@@ -22,6 +23,7 @@ Log::Log()
|
||||
lines = 0;
|
||||
max_lines = 5000;
|
||||
log_file_open = false;
|
||||
time_zones = 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -31,6 +33,21 @@ Log::~Log()
|
||||
}
|
||||
|
||||
|
||||
|
||||
void Log::SetTimeZones(TimeZones * ptime_zones)
|
||||
{
|
||||
time_zones = ptime_zones;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int Log::LogLevel()
|
||||
{
|
||||
return log_level;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void Log::Init(int log_level_, bool save_each_line_, const std::string & log_file_, bool log_std, int log_max_requests)
|
||||
{
|
||||
log_level = log_level_;
|
||||
@@ -54,24 +71,29 @@ void Log::OpenFile()
|
||||
}
|
||||
|
||||
|
||||
void Log::PutDate(LogManipulators m)
|
||||
void Log::PrintDate(const PT::Date & date, size_t time_zone_id)
|
||||
{
|
||||
// logs are related to localtime
|
||||
if( time_zones )
|
||||
{
|
||||
TimeZone * tz = time_zones->GetZone(time_zone_id);
|
||||
|
||||
time_t t = std::time(0);
|
||||
std::tm * loct = std::localtime(&t);
|
||||
|
||||
char buffer[70];
|
||||
sprintf(buffer, "%d.%02d.%02d %02d:%02d:%02d ", int(loct->tm_year + 1900),
|
||||
int(loct->tm_mon + 1),
|
||||
int(loct->tm_mday),
|
||||
int(loct->tm_hour),
|
||||
int(loct->tm_min),
|
||||
int(loct->tm_sec));
|
||||
|
||||
(*this) << m << buffer;
|
||||
if( tz )
|
||||
{
|
||||
PT::Date local_date = tz->ToLocal(date);
|
||||
log << local_date;
|
||||
}
|
||||
else
|
||||
{
|
||||
(*this) << date << " UTC"; // unknown time zone identifier
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
(*this) << date << " UTC"; // time_zones object was not set
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
Log & Log::operator<<(const void * s)
|
||||
{
|
||||
@@ -234,6 +256,30 @@ Log & Log::operator<<(double s)
|
||||
|
||||
|
||||
|
||||
Log & Log::operator<<(const PT::Space & s)
|
||||
{
|
||||
if( current_level <= log_level )
|
||||
{
|
||||
buffer << s;
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
|
||||
Log & Log::operator<<(const PT::Date & date)
|
||||
{
|
||||
if( current_level <= log_level )
|
||||
{
|
||||
buffer << date;
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
|
||||
Log & Log::operator<<(LogManipulators m)
|
||||
{
|
||||
switch(m)
|
||||
@@ -283,6 +329,79 @@ return *this;
|
||||
|
||||
|
||||
|
||||
|
||||
char Log::GetHEXdigit(unsigned char c)
|
||||
{
|
||||
if( c < 10 )
|
||||
return c + '0';
|
||||
|
||||
return c - 10 + 'A';
|
||||
}
|
||||
|
||||
|
||||
|
||||
void Log::ToHEX(char * buf, unsigned char c)
|
||||
{
|
||||
buf[0] = GetHEXdigit(c >> 4);
|
||||
buf[1] = GetHEXdigit(c & 0xf);
|
||||
buf[2] = 0;
|
||||
}
|
||||
|
||||
|
||||
void Log::LogBinary(const char * blob, size_t blob_len)
|
||||
{
|
||||
size_t i=0;
|
||||
char buf[3];
|
||||
|
||||
|
||||
while( i < blob_len )
|
||||
{
|
||||
size_t oldi = i;
|
||||
|
||||
for(size_t a=0 ; a<16 ; ++a)
|
||||
{
|
||||
if( i < blob_len )
|
||||
{
|
||||
ToHEX(buf, blob[i]);
|
||||
buffer << buf << ' ';
|
||||
++i;
|
||||
}
|
||||
else
|
||||
{
|
||||
buffer << " ";
|
||||
}
|
||||
|
||||
if( a == 7 )
|
||||
{
|
||||
if( i < blob_len )
|
||||
buffer << "- ";
|
||||
else
|
||||
buffer << " ";
|
||||
}
|
||||
}
|
||||
|
||||
i = oldi;
|
||||
buffer << ' ';
|
||||
|
||||
for(size_t a=0 ; a<16 && i<blob_len ; ++a, ++i)
|
||||
{
|
||||
if( blob[i] > 31 && blob[i] < 127 )
|
||||
buffer << blob[i];
|
||||
else
|
||||
buffer << '.';
|
||||
}
|
||||
|
||||
(*this) << logend;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Log::LogBinary(const std::string & blob)
|
||||
{
|
||||
LogBinary(blob.c_str(), blob.size());
|
||||
}
|
||||
|
||||
|
||||
void Log::SystemErr(int err)
|
||||
{
|
||||
(*this) << "errno: " << err;
|
||||
@@ -310,7 +429,7 @@ void Log::SaveLog()
|
||||
return;
|
||||
|
||||
if( log_stdout )
|
||||
Ezc::WideToUTF8(buffer.Str(), std::cout);
|
||||
PT::WideToUTF8(buffer.Str(), std::cout);
|
||||
|
||||
if( log_file.empty() )
|
||||
return;
|
||||
@@ -326,7 +445,7 @@ void Log::SaveLog()
|
||||
return;
|
||||
}
|
||||
|
||||
Ezc::WideToUTF8(buffer.Str(), file);
|
||||
PT::WideToUTF8(buffer.Str(), file);
|
||||
file.flush();
|
||||
}
|
||||
|
||||
|
||||
41
core/log.h
41
core/log.h
@@ -2,7 +2,7 @@
|
||||
* This file is a part of Winix
|
||||
* and is not publicly distributed
|
||||
*
|
||||
* Copyright (c) 2008-2011, Tomasz Sowa
|
||||
* Copyright (c) 2008-2012, Tomasz Sowa
|
||||
* All rights reserved.
|
||||
*
|
||||
*/
|
||||
@@ -17,6 +17,10 @@
|
||||
#include <string>
|
||||
#include "textstream.h"
|
||||
#include "logmanipulators.h"
|
||||
#include "textstream/textstream.h"
|
||||
|
||||
|
||||
class TimeZones;
|
||||
|
||||
|
||||
|
||||
@@ -27,9 +31,9 @@ public:
|
||||
Log();
|
||||
~Log();
|
||||
|
||||
void SetTimeZones(TimeZones * ptime_zones);
|
||||
void Init(int log_level_, bool save_each_line_, const std::string & log_file_, bool log_std, int log_max_requests);
|
||||
|
||||
void PutDate(LogManipulators m);
|
||||
Log & operator<<(const void * s);
|
||||
Log & operator<<(const char * s);
|
||||
Log & operator<<(const std::string * s);
|
||||
@@ -43,17 +47,35 @@ public:
|
||||
Log & operator<<(wchar_t s);
|
||||
Log & operator<<(size_t s);
|
||||
Log & operator<<(double s);
|
||||
Log & operator<<(const PT::Space & space);
|
||||
Log & operator<<(LogManipulators m);
|
||||
Log & operator<<(const PT::Date & date);
|
||||
|
||||
void PrintDate(const PT::Date & date, size_t time_zone_id);
|
||||
|
||||
template<typename char_type, size_t stack_size, size_t heap_block_size>
|
||||
Log & operator<<(const PT::TextStreamBase<char_type, stack_size, heap_block_size> & buf);
|
||||
|
||||
|
||||
template<class StringType>
|
||||
void LogString(const StringType & value, size_t max_size);
|
||||
|
||||
void LogBinary(const char * blob, size_t blob_len);
|
||||
void LogBinary(const std::string & blob);
|
||||
|
||||
|
||||
void SystemErr(int err);
|
||||
void SaveLog();
|
||||
void SaveLogAndClear();
|
||||
|
||||
int LogLevel();
|
||||
|
||||
|
||||
private:
|
||||
|
||||
// time zones for printing the time in the log file
|
||||
TimeZones * time_zones;
|
||||
|
||||
// buffer for the log
|
||||
TextStream<std::wstring> buffer;
|
||||
|
||||
@@ -91,6 +113,8 @@ private:
|
||||
bool save_each_line;
|
||||
|
||||
void OpenFile();
|
||||
char GetHEXdigit(unsigned char c);
|
||||
void ToHEX(char * buf, unsigned char c);
|
||||
|
||||
};
|
||||
|
||||
@@ -115,6 +139,19 @@ size_t min_size = value.size() < max_size ? value.size() : max_size;
|
||||
|
||||
|
||||
|
||||
template<typename char_type, size_t stack_size, size_t heap_block_size>
|
||||
Log & Log::operator<<(const PT::TextStreamBase<char_type, stack_size, heap_block_size> & buf)
|
||||
{
|
||||
if( current_level <= log_level )
|
||||
buffer << buf;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
extern Log log;
|
||||
extern Log nlog;
|
||||
|
||||
|
||||
481
core/misc.cpp
481
core/misc.cpp
@@ -2,17 +2,35 @@
|
||||
* This file is a part of Winix
|
||||
* and is not publicly distributed
|
||||
*
|
||||
* Copyright (c) 2008-2011, Tomasz Sowa
|
||||
* Copyright (c) 2008-2012, Tomasz Sowa
|
||||
* All rights reserved.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fstream>
|
||||
#include "misc.h"
|
||||
#include "log.h"
|
||||
#include "templates/templates.h"
|
||||
#include "utf8.h"
|
||||
|
||||
|
||||
|
||||
namespace misc_private
|
||||
{
|
||||
// white_chars table should be sorted
|
||||
// we do not treat a new line character (10) as a white character
|
||||
static const wchar_t white_chars[] = { 0x0009, 0x000B, 0x000C, 0x000D, 0x0020, 0x0085, 0x00A0,
|
||||
0x1680, 0x180E, 0x2000, 0x2001, 0x2002, 0x2003, 0x2004,
|
||||
0x2005, 0x2006, 0x2007, 0x2008, 0x2009, 0x200A, 0x2028,
|
||||
0x2029, 0x202F, 0x205F, 0x3000 };
|
||||
|
||||
std::ifstream get_file_content;
|
||||
std::string get_file_content_ansi;
|
||||
|
||||
PT::WTextStream tmp_qencode;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int Toi(const std::string & str, int base)
|
||||
@@ -328,7 +346,7 @@ std::wstring::iterator i;
|
||||
{
|
||||
if( !CorrectUrlChar(*i) )
|
||||
{
|
||||
wchar_t c = TemplatesFunctions::locale.Subst(*i);
|
||||
wchar_t c = TemplatesFunctions::locale.UrlSubst(*i);
|
||||
|
||||
if( CorrectUrlChar(c) )
|
||||
*i = c;
|
||||
@@ -421,43 +439,34 @@ static wchar_t buffer[100];
|
||||
}
|
||||
|
||||
|
||||
const wchar_t * DateToStr(const tm * ptm)
|
||||
{
|
||||
return DateToStr(ptm->tm_year + 1900, ptm->tm_mon+1, ptm->tm_mday, ptm->tm_hour, ptm->tm_min, ptm->tm_sec);
|
||||
}
|
||||
|
||||
|
||||
const wchar_t * DateToStr(const tm & rtm)
|
||||
const wchar_t * DateToStr(const PT::Date & d)
|
||||
{
|
||||
return DateToStr(rtm.tm_year + 1900, rtm.tm_mon+1, rtm.tm_mday, rtm.tm_hour, rtm.tm_min, rtm.tm_sec);
|
||||
return DateToStr(d.year, d.month, d.day, d.hour, d.min, d.sec);
|
||||
}
|
||||
|
||||
|
||||
const wchar_t * DateToStr(time_t t)
|
||||
{
|
||||
tm rtm = Time(t);
|
||||
PT::Date date = t;
|
||||
|
||||
return DateToStr(rtm);
|
||||
return DateToStr(date);
|
||||
}
|
||||
|
||||
|
||||
const wchar_t * DateToStrWithoutHours(const tm * ptm)
|
||||
{
|
||||
return DateToStr(ptm->tm_year + 1900, ptm->tm_mon+1, ptm->tm_mday);
|
||||
}
|
||||
|
||||
|
||||
const wchar_t * DateToStrWithoutHours(const tm & rtm)
|
||||
const wchar_t * DateToStrWithoutHours(const PT::Date & d)
|
||||
{
|
||||
return DateToStr(rtm.tm_year + 1900, rtm.tm_mon+1, rtm.tm_mday);
|
||||
return DateToStr(d.year, d.month, d.day);
|
||||
}
|
||||
|
||||
|
||||
const wchar_t * DateToStrWithoutHours(time_t t)
|
||||
{
|
||||
tm rtm = Time(t);
|
||||
PT::Date date = t;
|
||||
|
||||
return DateToStrWithoutHours(rtm);
|
||||
return DateToStrWithoutHours(date);
|
||||
}
|
||||
|
||||
|
||||
@@ -482,23 +491,19 @@ return buffer;
|
||||
}
|
||||
|
||||
|
||||
const char * DateToStrCookie(const tm * ptm)
|
||||
{
|
||||
return DateToStrCookie(ptm->tm_year + 1900, ptm->tm_mon+1, ptm->tm_mday, ptm->tm_hour, ptm->tm_min, ptm->tm_sec);
|
||||
}
|
||||
|
||||
|
||||
const char * DateToStrCookie(const tm & rtm)
|
||||
const char * DateToStrCookie(const PT::Date & d)
|
||||
{
|
||||
return DateToStrCookie(rtm.tm_year + 1900, rtm.tm_mon+1, rtm.tm_mday, rtm.tm_hour, rtm.tm_min, rtm.tm_sec);
|
||||
return DateToStrCookie(d.year, d.month, d.day, d.hour, d.min, d.sec);
|
||||
}
|
||||
|
||||
|
||||
const char * DateToStrCookie(time_t t)
|
||||
{
|
||||
tm rtm = Time(t);
|
||||
PT::Date date = t;
|
||||
|
||||
return DateToStrCookie(rtm);
|
||||
return DateToStrCookie(date);
|
||||
}
|
||||
|
||||
|
||||
@@ -521,17 +526,107 @@ return buffer;
|
||||
|
||||
|
||||
|
||||
|
||||
bool IsWhite(wchar_t s)
|
||||
PT::WTextStream IPToStr(unsigned int ip)
|
||||
{
|
||||
if( s==' ' || s=='\t' || s==13 || s==160 )
|
||||
PT::WTextStream buf;
|
||||
|
||||
for(int i=0 ; i<4 ; ++i, ip >>= 8)
|
||||
{
|
||||
buf << (ip & 0xff);
|
||||
|
||||
if( i<3 )
|
||||
buf << '.';
|
||||
}
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
|
||||
PT::WTextStream IPToStr(int ip)
|
||||
{
|
||||
return IPToStr(static_cast<unsigned int>(ip));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
we do not treat a new line character (10) as a white character
|
||||
*/
|
||||
bool IsWhite(wchar_t c)
|
||||
{
|
||||
using misc_private::white_chars;
|
||||
|
||||
size_t len = sizeof(white_chars) / sizeof(wchar_t);
|
||||
size_t o1 = 0;
|
||||
size_t o2 = len - 1;
|
||||
|
||||
if( c < white_chars[o1] || c > white_chars[o2] )
|
||||
return false;
|
||||
|
||||
if( c == white_chars[o1] || c == white_chars[o2] )
|
||||
return true;
|
||||
|
||||
|
||||
while( o1 + 1 < o2 )
|
||||
{
|
||||
size_t o = (o2 - o1)/2 + o1;
|
||||
|
||||
if( c == white_chars[o] )
|
||||
return true;
|
||||
|
||||
if( c > white_chars[o] )
|
||||
o1 = o;
|
||||
else
|
||||
o2 = o;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
return true if the whole string has only white characters
|
||||
an empty string is treated as white
|
||||
*/
|
||||
bool IsWhite(const wchar_t * str, bool treat_new_line_as_white)
|
||||
{
|
||||
for( ; *str != 0 ; ++str )
|
||||
{
|
||||
if( *str == '\n' )
|
||||
{
|
||||
if( !treat_new_line_as_white )
|
||||
return false;
|
||||
}
|
||||
else
|
||||
if( !IsWhite(*str) )
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
return true if the whole string has only white characters
|
||||
*/
|
||||
bool IsWhite(const std::wstring & str, bool treat_new_line_as_white)
|
||||
{
|
||||
return IsWhite(str.c_str(), treat_new_line_as_white);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
bool IsLastSlash(const std::wstring & path)
|
||||
{
|
||||
if( path.empty() )
|
||||
return false;
|
||||
|
||||
return path[path.size()-1] == '/';
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -573,56 +668,73 @@ std::wstring::size_type i;
|
||||
|
||||
|
||||
|
||||
bool ValidateEmail(const std::wstring & email)
|
||||
bool IsEmailCorrectChar(wchar_t c)
|
||||
{
|
||||
if( email.empty() )
|
||||
return false;
|
||||
|
||||
bool correct = true;
|
||||
size_t i;
|
||||
wchar_t allowed_chars[] = L"!#$%&'*+-/=?^_`{|}~.@";
|
||||
int at = 0;
|
||||
|
||||
for(i=0 ; i<email.length() && correct ; ++i)
|
||||
bool correct = false;
|
||||
|
||||
const wchar_t * allowed_chars = L"@.!#$%&'*+-/=?^_`{|}~";
|
||||
|
||||
if( (c >= 'A' && c<='Z') ||
|
||||
(c >= 'a' && c<='z') ||
|
||||
(c >= '0' && c<='9') )
|
||||
{
|
||||
correct = false;
|
||||
|
||||
if( (email[i] >= 'A' && email[i]<='Z') ||
|
||||
(email[i] >= 'a' && email[i]<='z') ||
|
||||
(email[i] >= '0' && email[i]<='9') )
|
||||
correct = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
for(size_t a=0 ; allowed_chars[a] != 0 ; ++a)
|
||||
{
|
||||
correct = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
for(size_t a=0 ; a < sizeof(allowed_chars)-1 ; ++a)
|
||||
if( c == allowed_chars[a] )
|
||||
{
|
||||
if( email[i] == allowed_chars[a] )
|
||||
{
|
||||
correct = true;
|
||||
break;
|
||||
}
|
||||
correct = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if( email[i] == '@' )
|
||||
++at;
|
||||
}
|
||||
|
||||
if( at != 1 )
|
||||
return correct;
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool ValidateEmail(const wchar_t * email)
|
||||
{
|
||||
int at = 0; // how many '@'
|
||||
int dots_after_at = 0; // how many dots in the domain part
|
||||
|
||||
for(size_t i=0 ; email[i] != 0 ; ++i)
|
||||
{
|
||||
if( !IsEmailCorrectChar(email[i]) )
|
||||
return false;
|
||||
|
||||
if( email[i] == '@' )
|
||||
++at;
|
||||
|
||||
if( email[i] == '.' && at > 0 )
|
||||
++dots_after_at;
|
||||
}
|
||||
|
||||
if( at != 1 || dots_after_at == 0 )
|
||||
return false;
|
||||
|
||||
return correct;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool ValidateEmail(const std::wstring & email)
|
||||
{
|
||||
return ValidateEmail(email.c_str());
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
bool IsFile(const wchar_t * file)
|
||||
{
|
||||
struct stat sb;
|
||||
static std::string afile;
|
||||
|
||||
Ezc::WideToUTF8(file, afile);
|
||||
PT::WideToUTF8(file, afile);
|
||||
|
||||
return (stat(afile.c_str(), &sb) == 0);
|
||||
}
|
||||
@@ -640,7 +752,7 @@ static std::string adir;
|
||||
|
||||
if( !IsFile(dir) )
|
||||
{
|
||||
Ezc::WideToUTF8(dir, adir);
|
||||
PT::WideToUTF8(dir, adir);
|
||||
|
||||
if( mkdir(adir.c_str(), priv) < 0 )
|
||||
{
|
||||
@@ -733,8 +845,8 @@ bool CopyFile(const wchar_t * src, const wchar_t * dst)
|
||||
static std::string asrc, adst;
|
||||
FILE * in, * out;
|
||||
|
||||
Ezc::WideToUTF8(src, asrc);
|
||||
Ezc::WideToUTF8(dst, adst);
|
||||
PT::WideToUTF8(src, asrc);
|
||||
PT::WideToUTF8(dst, adst);
|
||||
|
||||
in = fopen(asrc.c_str(), "rb");
|
||||
|
||||
@@ -775,7 +887,7 @@ bool RemoveFile(const wchar_t * file)
|
||||
{
|
||||
static std::string afile;
|
||||
|
||||
Ezc::WideToUTF8(file, afile);
|
||||
PT::WideToUTF8(file, afile);
|
||||
|
||||
return unlink(afile.c_str()) == 0;
|
||||
}
|
||||
@@ -792,8 +904,8 @@ bool RenameFile(const wchar_t * from, const wchar_t * to)
|
||||
{
|
||||
static std::string afrom, ato;
|
||||
|
||||
Ezc::WideToUTF8(from, afrom);
|
||||
Ezc::WideToUTF8(to, ato);
|
||||
PT::WideToUTF8(from, afrom);
|
||||
PT::WideToUTF8(to, ato);
|
||||
|
||||
return rename(afrom.c_str(), ato.c_str()) == 0;
|
||||
}
|
||||
@@ -805,6 +917,50 @@ bool RenameFile(const std::wstring & from, const std::wstring & to)
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
bool GetUTF8File(const char * file_path, std::wstring & content, bool clear_content)
|
||||
{
|
||||
using namespace misc_private;
|
||||
|
||||
if( clear_content )
|
||||
content.clear();
|
||||
|
||||
get_file_content.clear();
|
||||
get_file_content.open(file_path, std::ios_base::in | std::ios_base::binary);
|
||||
|
||||
if( !get_file_content )
|
||||
return false;
|
||||
|
||||
PT::UTF8ToWide(get_file_content, content);
|
||||
get_file_content.close();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool GetUTF8File(const wchar_t * file_path, std::wstring & content, bool clear_content)
|
||||
{
|
||||
using namespace misc_private;
|
||||
|
||||
PT::WideToUTF8(file_path, get_file_content_ansi);
|
||||
return GetUTF8File(get_file_content_ansi.c_str(), content, clear_content);
|
||||
}
|
||||
|
||||
|
||||
bool GetUTF8File(const std::string & file_path, std::wstring & content, bool clear_content)
|
||||
{
|
||||
return GetUTF8File(file_path.c_str(), content, clear_content);
|
||||
}
|
||||
|
||||
|
||||
bool GetUTF8File(const std::wstring & file_path, std::wstring & content, bool clear_content)
|
||||
{
|
||||
return GetUTF8File(file_path.c_str(), content, clear_content);
|
||||
}
|
||||
|
||||
|
||||
// if there is not an extension it returns a pointer to the last '\0' character
|
||||
const wchar_t * GetFileExt(const wchar_t * name)
|
||||
{
|
||||
@@ -856,6 +1012,15 @@ int SelectFileType(const wchar_t * file_name)
|
||||
EqualNoCase(ext, L"odt") )
|
||||
return WINIX_ITEM_FILETYPE_DOCUMENT;
|
||||
|
||||
if( EqualNoCase(ext, L"avi") ||
|
||||
EqualNoCase(ext, L"mp4") ||
|
||||
EqualNoCase(ext, L"flv") ||
|
||||
EqualNoCase(ext, L"mpg") ||
|
||||
EqualNoCase(ext, L"mpeg") ||
|
||||
EqualNoCase(ext, L"mkv") ||
|
||||
EqualNoCase(ext, L"wmv") )
|
||||
return WINIX_ITEM_FILETYPE_VIDEO;
|
||||
|
||||
return WINIX_ITEM_FILETYPE_UNKNOWN;
|
||||
}
|
||||
|
||||
@@ -866,153 +1031,99 @@ int SelectFileType(const std::wstring & file_name)
|
||||
}
|
||||
|
||||
|
||||
time_t Time(const tm & par)
|
||||
|
||||
|
||||
|
||||
void UrlEncode(const char * in, std::string & out, bool clear_out)
|
||||
{
|
||||
tm t;
|
||||
if( clear_out )
|
||||
out.clear();
|
||||
|
||||
memset(&t, 0, sizeof(t));
|
||||
|
||||
t.tm_year = par.tm_year;
|
||||
t.tm_mon = par.tm_mon;
|
||||
t.tm_mday = par.tm_mday;
|
||||
t.tm_hour = par.tm_hour;
|
||||
t.tm_min = par.tm_min;
|
||||
t.tm_sec = par.tm_sec;
|
||||
|
||||
return timegm(&t);
|
||||
for(size_t i=0 ; in[i] != 0 ; ++i)
|
||||
UrlEncode(in[i], out, false);
|
||||
}
|
||||
|
||||
|
||||
time_t Time(const tm * par)
|
||||
{
|
||||
return Time(*par);
|
||||
}
|
||||
|
||||
|
||||
tm Time(time_t par)
|
||||
{
|
||||
tm * ptm = gmtime(&par);
|
||||
tm res;
|
||||
|
||||
memset(&res, 0, sizeof(res));
|
||||
|
||||
if( ptm )
|
||||
{
|
||||
res.tm_year = ptm->tm_year;
|
||||
res.tm_mon = ptm->tm_mon;
|
||||
res.tm_mday = ptm->tm_mday;
|
||||
res.tm_hour = ptm->tm_hour;
|
||||
res.tm_min = ptm->tm_min;
|
||||
res.tm_sec = ptm->tm_sec;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void UrlEncode(const std::string & in, std::string & out, bool clear_out)
|
||||
{
|
||||
char buffer[10];
|
||||
UrlEncode(in.c_str(), out, clear_out);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void UrlEncode(const wchar_t * in, std::string & out, bool clear_out)
|
||||
{
|
||||
static std::string ain;
|
||||
|
||||
PT::WideToUTF8(in, ain);
|
||||
|
||||
if( clear_out )
|
||||
out.clear();
|
||||
|
||||
for(size_t i=0 ; i<in.size() ; ++i)
|
||||
{
|
||||
if( (in[i] >= 'a' && in[i] <= 'z') ||
|
||||
(in[i] >= 'A' && in[i] <= 'Z') ||
|
||||
(in[i] >= '0' && in[i] <= '9') ||
|
||||
in[i] == '.' || in[i] == ',' || in[i] == '/' || in[i] == ':' || in[i] == '#' ||
|
||||
in[i] == '-' || in[i] == '_' || in[i] == '(' || in[i] == ')' )
|
||||
{
|
||||
out += in[i];
|
||||
}
|
||||
else
|
||||
{
|
||||
Toa(static_cast<unsigned char>(in[i]), buffer, 10, 16);
|
||||
out += '%';
|
||||
|
||||
if( buffer[1] == 0 )
|
||||
out += '0'; // there is only one characters in the buffer
|
||||
|
||||
out += buffer;
|
||||
}
|
||||
}
|
||||
for(size_t i=0 ; i < ain.size() ; ++i)
|
||||
UrlEncode(ain[i], out, false);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void UrlEncode(const std::wstring & in, std::string & out, bool clear_out)
|
||||
{
|
||||
UrlEncode(in.c_str(), out, clear_out);
|
||||
}
|
||||
|
||||
|
||||
void UrlEncode(const wchar_t * in, std::wstring & out, bool clear_out)
|
||||
{
|
||||
static std::string ain;
|
||||
|
||||
Ezc::WideToUTF8(in, ain);
|
||||
UrlEncode(ain, out, clear_out);
|
||||
PT::WideToUTF8(in, ain);
|
||||
|
||||
if( clear_out )
|
||||
out.clear();
|
||||
|
||||
for(size_t i=0 ; i < ain.size() ; ++i)
|
||||
UrlEncode(ain[i], out, false);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void QEncodeAddChar(wchar_t c, std::string & out)
|
||||
void UrlEncode(const std::wstring & in, std::wstring & out, bool clear_out)
|
||||
{
|
||||
if( (c>='A' && c<='Z') ||
|
||||
(c>='a' && c<='z') ||
|
||||
(c>='0' && c<='9') )
|
||||
{
|
||||
out += char(c);
|
||||
}
|
||||
else
|
||||
{
|
||||
char buf1[10];
|
||||
char buf2[10];
|
||||
|
||||
size_t len1 = sizeof(buf1) / sizeof(char);
|
||||
size_t len2 = sizeof(buf2) / sizeof(char);
|
||||
size_t len = Ezc::IntToUTF8(int(c), buf1, len1);
|
||||
|
||||
for(size_t i=0 ; i<len ; ++i)
|
||||
{
|
||||
// make sure that it produces *capital* letters (ABC...)
|
||||
Toa((unsigned long)(unsigned char)buf1[i], buf2, len2, 16);
|
||||
out += '=';
|
||||
out += buf2;
|
||||
}
|
||||
}
|
||||
UrlEncode(in.c_str(), out, clear_out);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void QEncode(const std::wstring & in, std::string & out, bool clear)
|
||||
{
|
||||
using namespace misc_private;
|
||||
|
||||
tmp_qencode.clear();
|
||||
QEncode(in, tmp_qencode);
|
||||
tmp_qencode.to_string(out, clear);
|
||||
tmp_qencode.clear();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
this encoding is used in mails headers
|
||||
encoded-word = "=?" charset "?" encoding "?" encoded-text "?="
|
||||
http://www.faqs.org/rfcs/rfc1522.html
|
||||
|
||||
we have:
|
||||
charset = UTF-8
|
||||
encoding = Q
|
||||
|
||||
current limitation:
|
||||
we do not support checking the maximum length:
|
||||
"An encoded-word may not be more than 75 characters long, including
|
||||
charset, encoding, encoded-text, and delimiters."
|
||||
deleting all post temporary files
|
||||
*/
|
||||
void QEncode(const std::wstring & in, std::string & out, bool clear)
|
||||
void RemovePostFileTmp(PostFileTab & post_file_tab)
|
||||
{
|
||||
if( clear )
|
||||
out.clear();
|
||||
PostFileTab::iterator i = post_file_tab.begin();
|
||||
|
||||
out += "=?UTF-8?Q?";
|
||||
|
||||
for(size_t i=0 ; i<in.size() ; ++i)
|
||||
QEncodeAddChar(in[i], out);
|
||||
|
||||
out += "?=";
|
||||
for( ; i != post_file_tab.end() ; ++i )
|
||||
{
|
||||
const std::wstring & tmp_filename = i->second.tmp_filename;
|
||||
|
||||
if( !tmp_filename.empty() && RemoveFile(tmp_filename) )
|
||||
log << log3 << "Deleted tmp file: " << tmp_filename << logend;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
419
core/misc.h
419
core/misc.h
@@ -2,7 +2,7 @@
|
||||
* This file is a part of Winix
|
||||
* and is not publicly distributed
|
||||
*
|
||||
* Copyright (c) 2008-2011, Tomasz Sowa
|
||||
* Copyright (c) 2008-2012, Tomasz Sowa
|
||||
* All rights reserved.
|
||||
*
|
||||
*/
|
||||
@@ -16,6 +16,11 @@
|
||||
#include <ctime>
|
||||
#include <cstdio>
|
||||
#include "item.h"
|
||||
#include "requesttypes.h"
|
||||
#include "date/date.h"
|
||||
#include "textstream/textstream.h"
|
||||
#include "utf8/utf8.h"
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -118,14 +123,55 @@ bool Toa(int value, CharType * buffer, size_t buf_len, int base = 10)
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
these methos don't take the buffer size
|
||||
make sure the buffer size is sufficient big
|
||||
2^64 - 1 = 18446744073709551615 = 20 characters (plus minus sign and plus terminating zero)
|
||||
so the buffer should have at least 22 characters
|
||||
!! CHECK ME check the size whether is correct
|
||||
*/
|
||||
template<class CharType>
|
||||
bool Toa(unsigned long value, CharType * buffer)
|
||||
{
|
||||
size_t sufficient_space = 25;
|
||||
return Toa(value, buffer, sufficient_space);
|
||||
}
|
||||
|
||||
template<class CharType>
|
||||
bool Toa(long value, CharType * buffer)
|
||||
{
|
||||
size_t sufficient_space = 25;
|
||||
return Toa(value, buffer, sufficient_space);
|
||||
}
|
||||
|
||||
template<class CharType>
|
||||
bool Toa(unsigned int value, CharType * buffer)
|
||||
{
|
||||
size_t sufficient_space = 25;
|
||||
return Toa(value, buffer, sufficient_space);
|
||||
}
|
||||
|
||||
template<class CharType>
|
||||
bool Toa(int value, CharType * buffer)
|
||||
{
|
||||
size_t sufficient_space = 25;
|
||||
return Toa(value, buffer, sufficient_space);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// warning: it uses its own static buffer
|
||||
// one buffer for both these functions
|
||||
// !! REMOVE ME they are deprecated (don't use it)
|
||||
const wchar_t * Toa(unsigned int value, int base = 10);
|
||||
const wchar_t * Toa(unsigned long value, int base = 10);
|
||||
const wchar_t * Toa(int value, int base = 10);
|
||||
const wchar_t * Toa(long value, int base = 10);
|
||||
|
||||
|
||||
void Toa(int value, std::string & res, int base = 10, bool clear = true);
|
||||
void Toa(long value, std::string & res, int base = 10, bool clear = true);
|
||||
void Toa(int value, std::wstring & res, int base = 10, bool clear = true);
|
||||
@@ -169,21 +215,30 @@ void CorrectUrlOnlyAllowedChar(std::wstring & url);
|
||||
|
||||
const wchar_t * DateToStr(int year, int month, int day);
|
||||
const wchar_t * DateToStr(int year, int month, int day, int hour, int min, int sec);
|
||||
const wchar_t * DateToStr(const tm * ptm);
|
||||
const wchar_t * DateToStr(const tm & rtm);
|
||||
const wchar_t * DateToStr(const PT::Date & d);
|
||||
const wchar_t * DateToStr(time_t t);
|
||||
const wchar_t * DateToStrWithoutHours(const tm * ptm);
|
||||
const wchar_t * DateToStrWithoutHours(const tm & rtm);
|
||||
const wchar_t * DateToStrWithoutHours(const PT::Date & d);
|
||||
const wchar_t * DateToStrWithoutHours(time_t t);
|
||||
|
||||
const char * DateToStrCookie(int year, int month, int day, int hour, int min, int sec);
|
||||
const char * DateToStrCookie(const tm * ptm);
|
||||
const char * DateToStrCookie(const tm & rtm);
|
||||
const char * DateToStrCookie(const PT::Date & d);
|
||||
const char * DateToStrCookie(time_t t);
|
||||
|
||||
// depracated
|
||||
// not thread safe
|
||||
const wchar_t * IpToStr(unsigned int ip_);
|
||||
|
||||
// in a new code we can use WTextStream in such a way
|
||||
// DateToStr() etc can use it too
|
||||
PT::WTextStream IPToStr(unsigned int ip);
|
||||
PT::WTextStream IPToStr(int ip);
|
||||
|
||||
|
||||
|
||||
bool IsWhite(wchar_t s);
|
||||
bool IsWhite(const wchar_t * str, bool treat_new_line_as_white = false);
|
||||
bool IsWhite(const std::wstring & str, bool treat_new_line_as_white = false);
|
||||
bool IsLastSlash(const std::wstring & path);
|
||||
|
||||
template<class StringType>
|
||||
void TrimWhite(StringType & s)
|
||||
@@ -247,6 +302,56 @@ typename StringType::size_type i;
|
||||
}
|
||||
|
||||
|
||||
template<class StringType>
|
||||
void MaxSize(StringType & str, size_t max_size)
|
||||
{
|
||||
if( str.size() > max_size )
|
||||
str.erase(max_size);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
this method removing all characters from given string
|
||||
only digits are allowed and if allow_comma then one comma (or dot)
|
||||
character is allowed
|
||||
|
||||
if change_to_dot is true then if a comma exists then it is changed to a dot
|
||||
*/
|
||||
template<class StringType>
|
||||
void OnlyDigit(StringType & s, bool allow_comma = true, bool change_to_dot = true)
|
||||
{
|
||||
typename StringType::size_type i;
|
||||
bool was_comma = false;
|
||||
|
||||
if( s.empty() )
|
||||
{
|
||||
s = '0';
|
||||
return;
|
||||
}
|
||||
|
||||
for(i=0 ; i<s.size() ; )
|
||||
{
|
||||
if( (s[i]>='0' && s[i]<='9') ||
|
||||
(allow_comma && !was_comma && (s[i]=='.' || s[i]==',')) )
|
||||
{
|
||||
if( change_to_dot && s[i] == ',' )
|
||||
s[i] = '.';
|
||||
|
||||
if( s[i]=='.' || s[i]==',' )
|
||||
was_comma = true;
|
||||
|
||||
i += 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
s.erase(i, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
wchar_t ToSmall(wchar_t c);
|
||||
void ToSmall(std::wstring & s);
|
||||
|
||||
@@ -256,7 +361,7 @@ const wchar_t * SkipWhite(const wchar_t * s);
|
||||
|
||||
|
||||
template<class StringType1, class StringType2>
|
||||
bool IsSubString(const StringType1 * short_str, const StringType2 * long_str)
|
||||
bool IsSubStringp(const StringType1 * short_str, const StringType2 * long_str)
|
||||
{
|
||||
while( *short_str && *long_str && wchar_t(*short_str) == wchar_t(*long_str) )
|
||||
{
|
||||
@@ -272,12 +377,18 @@ return false;
|
||||
|
||||
|
||||
template<class StringType1, class StringType2>
|
||||
bool IsSubString(const StringType1 & short_str, const StringType2 & long_str)
|
||||
bool IsSubString(const StringType1 * short_str, const StringType2 * long_str)
|
||||
{
|
||||
return IsSubString(short_str.c_str(), long_str.c_str());
|
||||
return IsSubStringp(short_str, long_str);
|
||||
}
|
||||
|
||||
|
||||
template<class StringType1, class StringType2>
|
||||
bool IsSubString(const StringType1 & short_str, const StringType2 & long_str)
|
||||
{
|
||||
return IsSubStringp(short_str.c_str(), long_str.c_str());
|
||||
}
|
||||
|
||||
|
||||
template<class StringType1, class StringType2>
|
||||
bool IsSubStringNoCase(const StringType1 * short_str, const StringType2 * long_str)
|
||||
@@ -351,6 +462,36 @@ bool EqualNoCase(const StringType1 & str1, const StringType2 & str2)
|
||||
|
||||
|
||||
|
||||
/*
|
||||
looking for 'look_for' string in 'buf' and replacing it with 'replace'
|
||||
'replace' can be empty (so only 'look_for' will be deleted)
|
||||
*/
|
||||
template<class StringType>
|
||||
void ReplaceString(StringType & buf, const StringType & look_for, const StringType & replace)
|
||||
{
|
||||
size_t i = 0;
|
||||
|
||||
if( look_for.empty() )
|
||||
return;
|
||||
|
||||
while( i < buf.size() )
|
||||
{
|
||||
if( IsSubString(look_for.c_str(), buf.c_str() + i) )
|
||||
{
|
||||
buf.erase(i, look_for.size());
|
||||
buf.insert(i, replace);
|
||||
i += replace.size();
|
||||
}
|
||||
else
|
||||
{
|
||||
i += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
template<class StringType>
|
||||
void NoLastSlash(StringType & s)
|
||||
{
|
||||
@@ -544,7 +685,8 @@ return str + i;
|
||||
|
||||
|
||||
|
||||
|
||||
bool IsEmailCorrectChar(wchar_t c);
|
||||
bool ValidateEmail(const wchar_t * email);
|
||||
bool ValidateEmail(const std::wstring & email);
|
||||
|
||||
bool IsFile(const wchar_t * file);
|
||||
@@ -567,21 +709,266 @@ bool RemoveFile(const std::wstring & file);
|
||||
bool RenameFile(const wchar_t * from, const wchar_t * to);
|
||||
bool RenameFile(const std::wstring & from, const std::wstring & to);
|
||||
|
||||
bool GetUTF8File(const char * file_path, std::wstring & content, bool clear_content = true);
|
||||
bool GetUTF8File(const wchar_t * file_path, std::wstring & content, bool clear_content = true);
|
||||
bool GetUTF8File(const std::string & file_path, std::wstring & content, bool clear_content = true);
|
||||
bool GetUTF8File(const std::wstring & file_path, std::wstring & content, bool clear_content = true);
|
||||
|
||||
|
||||
const wchar_t * GetFileExt(const wchar_t * name);
|
||||
int SelectFileType(const wchar_t * file_name);
|
||||
int SelectFileType(const std::wstring & file_name);
|
||||
|
||||
|
||||
time_t Time(const tm & par);
|
||||
time_t Time(const tm * par);
|
||||
tm Time(time_t par);
|
||||
|
||||
|
||||
void UrlEncode(const std::string & in, std::string & out, bool clear_out = true);
|
||||
|
||||
|
||||
|
||||
// thread safe
|
||||
template<typename char_type, size_t stack_size, size_t heap_block_size>
|
||||
void UrlEncode(char c,
|
||||
PT::TextStreamBase<char_type, stack_size, heap_block_size> & out,
|
||||
bool clear_out = true)
|
||||
{
|
||||
char buffer[10];
|
||||
size_t buflen = sizeof(buffer)/sizeof(char);
|
||||
|
||||
if( clear_out )
|
||||
out.clear();
|
||||
|
||||
if( (c >= 'a' && c <= 'z') ||
|
||||
(c >= 'A' && c <= 'Z') ||
|
||||
(c >= '0' && c <= '9') ||
|
||||
c == '.' || c == ',' || c == '-' || c == '_' || c == '(' || c == ')' )
|
||||
{
|
||||
out << c;
|
||||
}
|
||||
else
|
||||
{
|
||||
Toa(static_cast<unsigned char>(c), buffer, buflen, 16);
|
||||
out << '%';
|
||||
|
||||
if( buffer[1] == 0 )
|
||||
out << '0'; // there is only one character in the buffer
|
||||
|
||||
out << buffer;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// thread safe
|
||||
template<typename char_type, size_t stack_size, size_t heap_block_size>
|
||||
void UrlEncode(const char * in,
|
||||
PT::TextStreamBase<char_type, stack_size, heap_block_size> & out,
|
||||
bool clear_out = true)
|
||||
{
|
||||
if( clear_out )
|
||||
out.clear();
|
||||
|
||||
for(size_t i=0 ; in[i] != 0 ; ++i)
|
||||
UrlEncode(in[i], out, false);
|
||||
}
|
||||
|
||||
|
||||
// thread safe
|
||||
template<typename char_type, size_t stack_size, size_t heap_block_size>
|
||||
void UrlEncode(const std::string & in,
|
||||
PT::TextStreamBase<char_type, stack_size, heap_block_size> & out,
|
||||
bool clear_out = true)
|
||||
{
|
||||
UrlEncode(in.c_str(), out, clear_out);
|
||||
}
|
||||
|
||||
|
||||
|
||||
// not thread safe
|
||||
template<typename char_type, size_t stack_size, size_t heap_block_size>
|
||||
void UrlEncode(const wchar_t * in,
|
||||
PT::TextStreamBase<char_type, stack_size, heap_block_size> & out,
|
||||
bool clear_out = true)
|
||||
{
|
||||
static std::string ain;
|
||||
|
||||
PT::WideToUTF8(in, ain);
|
||||
|
||||
if( clear_out )
|
||||
out.clear();
|
||||
|
||||
for(size_t i=0 ; i < ain.size() ; ++i)
|
||||
UrlEncode(ain[i], out, false);
|
||||
}
|
||||
|
||||
|
||||
// not thread safe
|
||||
template<typename char_type, size_t stack_size, size_t heap_block_size>
|
||||
void UrlEncode(const std::wstring & in,
|
||||
PT::TextStreamBase<char_type, stack_size, heap_block_size> & out,
|
||||
bool clear_out = true)
|
||||
{
|
||||
UrlEncode(in.c_str(), out, clear_out);
|
||||
}
|
||||
|
||||
|
||||
|
||||
// no thread safe
|
||||
template<class StringType>
|
||||
void UrlEncode(char c, StringType & out, bool clear_out = true)
|
||||
{
|
||||
static PT::TextStream tmp;
|
||||
|
||||
UrlEncode(c, tmp);
|
||||
tmp.to_string(out, clear_out);
|
||||
}
|
||||
|
||||
|
||||
// !! IMROVE ME we need some UrlEncode methods with PT::TextBuffer instead of std::string
|
||||
|
||||
|
||||
void UrlEncode(const char * in, std::string & out, bool clear_out = true);
|
||||
void UrlEncode(const std::string & in, std::string & out, bool clear_out = true);
|
||||
void UrlEncode(const wchar_t * in, std::string & out, bool clear_out = true);
|
||||
void UrlEncode(const std::wstring & in, std::string & out, bool clear_out = true);
|
||||
void UrlEncode(const wchar_t * in, std::wstring & out, bool clear_out = true);
|
||||
void UrlEncode(const std::wstring & in, std::wstring & out, bool clear_out = true);
|
||||
|
||||
|
||||
|
||||
|
||||
template<typename char_type, size_t stack_size, size_t heap_block_size>
|
||||
void QEncodeAddChar(char_type c, PT::TextStreamBase<char_type, stack_size, heap_block_size> & out)
|
||||
{
|
||||
if( (c>='A' && c<='Z') ||
|
||||
(c>='a' && c<='z') ||
|
||||
(c>='0' && c<='9') )
|
||||
{
|
||||
out << c;
|
||||
}
|
||||
else
|
||||
{
|
||||
char buf1[10];
|
||||
char buf2[10];
|
||||
|
||||
size_t len1 = sizeof(buf1) / sizeof(char);
|
||||
size_t len2 = sizeof(buf2) / sizeof(char);
|
||||
size_t len = PT::IntToUTF8(int(c), buf1, len1);
|
||||
|
||||
for(size_t i=0 ; i<len ; ++i)
|
||||
{
|
||||
// make sure that it produces *capital* letters (ABC...)
|
||||
Toa((unsigned long)(unsigned char)buf1[i], buf2, len2, 16);
|
||||
out << '=';
|
||||
|
||||
if( buf2[1] == 0 )
|
||||
out << '0';
|
||||
|
||||
out << buf2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
this encoding is used in mails headers
|
||||
encoded-word = "=?" charset "?" encoding "?" encoded-text "?="
|
||||
http://www.faqs.org/rfcs/rfc1522.html
|
||||
|
||||
we have:
|
||||
charset = UTF-8
|
||||
encoding = Q
|
||||
|
||||
current limitation:
|
||||
we do not support checking the maximum length:
|
||||
"An encoded-word may not be more than 75 characters long, including
|
||||
charset, encoding, encoded-text, and delimiters."
|
||||
*/
|
||||
template<typename char_type, size_t stack_size, size_t heap_block_size>
|
||||
void QEncode(const wchar_t * in, PT::TextStreamBase<char_type, stack_size, heap_block_size> & out,
|
||||
bool clear = true)
|
||||
{
|
||||
if( clear )
|
||||
out.clear();
|
||||
|
||||
out << "=?UTF-8?Q?";
|
||||
|
||||
for( ; *in ; ++in)
|
||||
QEncodeAddChar(*in, out);
|
||||
|
||||
out << "?=";
|
||||
}
|
||||
|
||||
|
||||
template<typename char_type, size_t stack_size, size_t heap_block_size>
|
||||
void QEncode(const std::wstring & in, PT::TextStreamBase<char_type, stack_size, heap_block_size> & out,
|
||||
bool clear = true)
|
||||
{
|
||||
if( clear )
|
||||
out.clear();
|
||||
|
||||
out << "=?UTF-8?Q?";
|
||||
|
||||
// do not use QEncode(in.c_str()) as 'in' can have a zero byte
|
||||
for(size_t i=0 ; i<in.size() ; ++i)
|
||||
QEncodeAddChar(in[i], out);
|
||||
|
||||
out << "?=";
|
||||
}
|
||||
|
||||
|
||||
void QEncode(const std::wstring & in, std::string & out, bool clear = true);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void RemovePostFileTmp(PostFileTab & post_file_tab);
|
||||
|
||||
|
||||
|
||||
/*
|
||||
short_str is removed from long_str (and a last dots are removed too)
|
||||
and the result is stored in out
|
||||
|
||||
sample:
|
||||
short_str: "mydomain.tld"
|
||||
long_str: "www.subdomain.mydomain.tld"
|
||||
out: "www.subdomain"
|
||||
|
||||
short_str: "mydomain.tld"
|
||||
long_str: "otherdifferentstring"
|
||||
out: ""
|
||||
*/
|
||||
template<class StringType1, class StringType2, class StringType3>
|
||||
void CreateSubdomain(const StringType1 * short_str, const StringType2 * long_str, StringType3 & out)
|
||||
{
|
||||
size_t i1, i2;
|
||||
|
||||
out.clear();
|
||||
|
||||
for(i1=0 ; short_str[i1] != 0 ; ++i1);
|
||||
for(i2=0 ; long_str[i2] != 0 ; ++i2);
|
||||
|
||||
if( i1 >= i2 )
|
||||
return;
|
||||
|
||||
// i1 is < i2
|
||||
|
||||
while( i1-- > 0 )
|
||||
{
|
||||
i2 -= 1;
|
||||
|
||||
if( short_str[i1] != long_str[i2] )
|
||||
return; // short_str is not a last substring of long_str
|
||||
}
|
||||
|
||||
while( i2>0 && long_str[i2-1] == '.' )
|
||||
i2 -= 1;
|
||||
|
||||
for(i1=0 ; i1 < i2 ; ++i1)
|
||||
out += long_str[i1];
|
||||
}
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
@@ -360,7 +360,84 @@ void MountParser::ReadMountParams()
|
||||
|
||||
|
||||
|
||||
void MountParser::ReadRow(std::map<long, Mount> & output)
|
||||
void MountParser::AddParams(Mount::Param & src, Mount::Param & dst)
|
||||
{
|
||||
if( src.size() != dst.size() )
|
||||
{
|
||||
log << log1 << "MP: addparams: incorrect sizes" << logend;
|
||||
return;
|
||||
}
|
||||
|
||||
for(size_t p=0 ; p < src.size() ; ++p)
|
||||
{
|
||||
if( src[p].defined && !dst[p].defined )
|
||||
dst[p] = src[p];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
bool MountParser::AddParamsBefore(long dir_id)
|
||||
{
|
||||
std::map<long, Mount>::iterator i = poutput->find(dir_id);
|
||||
|
||||
if( i == poutput->end() )
|
||||
return false;
|
||||
|
||||
AddParams(i->second.param, mount_inserted.first->second.param);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
adding all non-existing parameters to this mount point from parents
|
||||
*/
|
||||
void MountParser::AddParamsBefore()
|
||||
{
|
||||
if( !pdir )
|
||||
return;
|
||||
|
||||
Item * dir;
|
||||
long dir_id = pdir->parent_id;
|
||||
|
||||
while( dir_id != -1 )
|
||||
{
|
||||
if( AddParamsBefore(dir_id) )
|
||||
{
|
||||
// we don't have to check others parents
|
||||
// the parameters are already copied
|
||||
break;
|
||||
}
|
||||
|
||||
dir = dirs->GetDir(dir_id);
|
||||
|
||||
if( !dir )
|
||||
break;
|
||||
|
||||
dir_id = dir->parent_id;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
adding all non-existing parameters to childs (childs to this mount point)
|
||||
*/
|
||||
void MountParser::AddParamsAfter()
|
||||
{
|
||||
std::map<long, Mount>::iterator i = poutput->begin();
|
||||
|
||||
for( ; i != poutput->end() ; ++i)
|
||||
{
|
||||
if( dirs->IsChild(mount_inserted.first->second.dir_id, i->first) )
|
||||
AddParams(mount_inserted.first->second.param, i->second.param);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void MountParser::ReadRow()
|
||||
{
|
||||
if( ReadMountType() && ReadMountPoint() && ReadFs() )
|
||||
{
|
||||
@@ -373,13 +450,19 @@ void MountParser::ReadRow(std::map<long, Mount> & output)
|
||||
}
|
||||
else
|
||||
{
|
||||
std::pair<std::map<long, Mount>::iterator, bool> res = output.insert( std::make_pair(mount.dir_id, mount) );
|
||||
|
||||
if( !res.second )
|
||||
mount_inserted = poutput->insert( std::make_pair(mount.dir_id, mount) );
|
||||
|
||||
if( mount_inserted.second )
|
||||
{
|
||||
AddParamsBefore();
|
||||
AddParamsAfter();
|
||||
}
|
||||
else
|
||||
{
|
||||
log << log1 << "MP: this mount point exists (skipped)" << logend;
|
||||
slog << logwarning << T("mount_exists") << ": " << last_dir << " (" << T("skipped") << ")" << logend;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -397,13 +480,14 @@ void MountParser::Parse(const std::wstring & input, std::map<long, Mount> & outp
|
||||
return;
|
||||
}
|
||||
|
||||
pinput = input.c_str();
|
||||
pinput = input.c_str();
|
||||
poutput = &output;
|
||||
mount.param.resize(mount_par_tab->size());
|
||||
mount.ClearParams();
|
||||
output.clear();
|
||||
poutput->clear();
|
||||
|
||||
while( *pinput )
|
||||
ReadRow(output);
|
||||
ReadRow();
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -64,7 +64,11 @@ private:
|
||||
bool ReadFs();
|
||||
void LogMountParams();
|
||||
void ReadMountParams();
|
||||
void ReadRow(std::map<long, Mount> & output);
|
||||
void ReadRow();
|
||||
void AddParams(Mount::Param & src, Mount::Param & dst);
|
||||
bool AddParamsBefore(long dir_id);
|
||||
void AddParamsBefore();
|
||||
void AddParamsAfter();
|
||||
|
||||
const wchar_t * pinput;
|
||||
std::wstring temp;
|
||||
@@ -73,6 +77,8 @@ private:
|
||||
Mount::ParamRow::ParamArg param_args;
|
||||
Mount mount;
|
||||
Item * pdir;
|
||||
std::map<long, Mount> * poutput;
|
||||
std::pair<std::map<long, Mount>::iterator, bool> mount_inserted;
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* This file is a part of Winix
|
||||
* and is not publicly distributed
|
||||
*
|
||||
* Copyright (c) 2009-2011, Tomasz Sowa
|
||||
* Copyright (c) 2009-2012, Tomasz Sowa
|
||||
* All rights reserved.
|
||||
*
|
||||
*/
|
||||
@@ -49,15 +49,18 @@ void Mounts::CreateMountPar()
|
||||
mount_par_page = AddMountPar(L"page");
|
||||
mount_par_thumb_size = AddMountPar(L"thumb_size");
|
||||
mount_par_thumb_mode = AddMountPar(L"thumb_mode");
|
||||
//mount_par_thread = AddMountPar(L"thread");
|
||||
//mount_par_createthread_on = AddMountPar(L"createthread_on");
|
||||
mount_par_only_root_remove = AddMountPar(L"only_root_remove");
|
||||
mount_par_thumb_quality = AddMountPar(L"thumb_quality");
|
||||
mount_par_image_size = AddMountPar(L"image_size");
|
||||
mount_par_image_mode = AddMountPar(L"image_mode");
|
||||
mount_par_image_quality = AddMountPar(L"image_quality");
|
||||
mount_par_emacs_on = AddMountPar(L"emacs_on");
|
||||
mount_par_mkdir_on = AddMountPar(L"mkdir_on");
|
||||
mount_par_app = AddMountPar(L"app");
|
||||
mount_par_html_template = AddMountPar(L"html_template");
|
||||
mount_par_change_template = AddMountPar(L"change_template");
|
||||
mount_par_static = AddMountPar(L"static");
|
||||
mount_par_css = AddMountPar(L"css");
|
||||
mount_par_lang = AddMountPar(L"lang");
|
||||
}
|
||||
|
||||
|
||||
@@ -67,7 +70,7 @@ void Mounts::CreateMounts()
|
||||
CreateMountFs();
|
||||
CreateMountPar();
|
||||
|
||||
plugin.Call(WINIX_ADD_MOUNTS);
|
||||
plugin.Call((Session*)0, WINIX_ADD_MOUNTS);
|
||||
|
||||
empty_mount.param.resize(mount_par_tab.size());
|
||||
empty_mount.ClearParams();
|
||||
@@ -188,7 +191,7 @@ void Mounts::ReadMounts(const std::wstring & mounts)
|
||||
mount_parser.Parse(mounts, mount_tab);
|
||||
|
||||
CalcCurMount();
|
||||
plugin.Call(WINIX_FSTAB_CHANGED);
|
||||
plugin.Call((Session*)0, WINIX_FSTAB_CHANGED);
|
||||
}
|
||||
|
||||
|
||||
@@ -253,7 +256,7 @@ void Mounts::MountCmsForRoot()
|
||||
|
||||
|
||||
|
||||
void Mounts::CalcCurMount()
|
||||
Mount * Mounts::CalcCurMount()
|
||||
{
|
||||
std::vector<Item*>::reverse_iterator i;
|
||||
|
||||
@@ -262,7 +265,7 @@ std::vector<Item*>::reverse_iterator i;
|
||||
// when the program starts (when the dir_tab is empty()
|
||||
// we don't want to call MountCmsForRoot()
|
||||
if( cur->request->dir_tab.empty() )
|
||||
return;
|
||||
return pmount;
|
||||
|
||||
for(i = cur->request->dir_tab.rbegin() ; i!=cur->request->dir_tab.rend() ; ++i)
|
||||
{
|
||||
@@ -273,7 +276,7 @@ std::vector<Item*>::reverse_iterator i;
|
||||
pmount = &(m->second);
|
||||
log << log2 << "M: current mount point is: " << GetMountType(pmount->type)
|
||||
<< ", fs: " << GetMountFs(pmount->fs) << logend;
|
||||
return;
|
||||
return pmount;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -282,6 +285,8 @@ std::vector<Item*>::reverse_iterator i;
|
||||
MountCmsForRoot();
|
||||
log << log2 << "M: current mount point is: " << GetMountType(pmount->type) << " (default)"
|
||||
<< ", fs: " << GetMountFs(pmount->fs) << logend;
|
||||
|
||||
return pmount;
|
||||
}
|
||||
|
||||
|
||||
@@ -312,3 +317,7 @@ const Mounts::MountTab * Mounts::GetMountTab()
|
||||
}
|
||||
|
||||
|
||||
Mount * Mounts::GetEmptyMount()
|
||||
{
|
||||
return &empty_mount;
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* This file is a part of Winix
|
||||
* and is not publicly distributed
|
||||
*
|
||||
* Copyright (c) 2009-2011, Tomasz Sowa
|
||||
* Copyright (c) 2009-2012, Tomasz Sowa
|
||||
* All rights reserved.
|
||||
*
|
||||
*/
|
||||
@@ -69,15 +69,18 @@ public:
|
||||
int MountParPage() { return mount_par_page; }
|
||||
int MountParThumbSize() { return mount_par_thumb_size; }
|
||||
int MountParThumbMode() { return mount_par_thumb_mode; }
|
||||
//int MountParThread() { return mount_par_thread; }
|
||||
//int MountParCreatethreadOn() { return mount_par_createthread_on; }
|
||||
int MountParOnlyRootRemove() { return mount_par_only_root_remove; }
|
||||
int MountParThumbQuality() { return mount_par_thumb_quality; }
|
||||
int MountParImageSize() { return mount_par_image_size; }
|
||||
int MountParImageMode() { return mount_par_image_mode; }
|
||||
int MountParImageQuality() { return mount_par_image_quality; }
|
||||
int MountParEmacsOn() { return mount_par_emacs_on; }
|
||||
int MountParMkdirOn() { return mount_par_mkdir_on; }
|
||||
int MountParApp() { return mount_par_app; }
|
||||
int MountParHtmlTemplate() { return mount_par_html_template; }
|
||||
int MountParChangeTemplate() { return mount_par_change_template; }
|
||||
int MountParStatic() { return mount_par_static; }
|
||||
int MountParCss() { return mount_par_css; }
|
||||
int MountParLang() { return mount_par_lang; }
|
||||
|
||||
void SetDirs(Dirs * pdirs);
|
||||
void SetDb(Db * pdb);
|
||||
@@ -92,16 +95,22 @@ public:
|
||||
void ReadMounts(const std::wstring & mounts);
|
||||
Error ReadMounts();
|
||||
|
||||
void CalcCurMount();
|
||||
Mount * CalcCurMount();
|
||||
Mount * CalcMount(long dir_id);
|
||||
|
||||
// current mount point
|
||||
// will not be null after calling CalcCurMount() or ReadMounts([...])
|
||||
// !! nie korzystac obecnie z niego
|
||||
// korzystac z cur->mount
|
||||
// a tez zostanie wycofany
|
||||
Mount * pmount;
|
||||
|
||||
|
||||
const MountTab * GetMountTab();
|
||||
|
||||
// at the beginning used to initialize cur->mount
|
||||
Mount * GetEmptyMount();
|
||||
|
||||
private:
|
||||
|
||||
Db * db;
|
||||
@@ -132,15 +141,18 @@ private:
|
||||
int mount_par_page;
|
||||
int mount_par_thumb_size;
|
||||
int mount_par_thumb_mode;
|
||||
//int mount_par_thread;
|
||||
//int mount_par_createthread_on;
|
||||
int mount_par_only_root_remove;
|
||||
int mount_par_thumb_quality;
|
||||
int mount_par_image_size;
|
||||
int mount_par_image_mode;
|
||||
int mount_par_image_quality;
|
||||
int mount_par_emacs_on;
|
||||
int mount_par_mkdir_on;
|
||||
int mount_par_app;
|
||||
int mount_par_html_template;
|
||||
int mount_par_change_template;
|
||||
int mount_par_static;
|
||||
int mount_par_css;
|
||||
int mount_par_lang;
|
||||
|
||||
|
||||
MountTab mount_tab;
|
||||
|
||||
180
core/plugin.cpp
180
core/plugin.cpp
@@ -2,7 +2,7 @@
|
||||
* This file is a part of Winix
|
||||
* and is not publicly distributed
|
||||
*
|
||||
* Copyright (c) 2008-2010, Tomasz Sowa
|
||||
* Copyright (c) 2008-2012, Tomasz Sowa
|
||||
* All rights reserved.
|
||||
*
|
||||
*/
|
||||
@@ -41,9 +41,6 @@ Plugin::Plugin()
|
||||
templates = 0;
|
||||
synchro = 0;
|
||||
session_manager = 0;
|
||||
|
||||
ret_false = 0;
|
||||
ret_true = 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -101,6 +98,21 @@ void Plugin::SetSessionManager(SessionManager * psession_manager)
|
||||
|
||||
|
||||
|
||||
void Plugin::Lock()
|
||||
{
|
||||
if( synchro )
|
||||
synchro->Lock();
|
||||
}
|
||||
|
||||
|
||||
void Plugin::Unlock()
|
||||
{
|
||||
if( synchro )
|
||||
synchro->Unlock();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
bool Plugin::SetPointers(PluginInfo & info)
|
||||
{
|
||||
@@ -108,7 +120,11 @@ bool Plugin::SetPointers(PluginInfo & info)
|
||||
bool res = (db && config && cur && system && functions && templates && synchro && session_manager);
|
||||
|
||||
if( !res )
|
||||
{
|
||||
Lock();
|
||||
log << log1 << "Plugin: cannot call a function - some of the winix pointers are null" << logend;
|
||||
Unlock();
|
||||
}
|
||||
|
||||
info.db = db;
|
||||
info.config = config;
|
||||
@@ -148,7 +164,8 @@ void Plugin::LoadPlugin(const std::string & filename)
|
||||
}
|
||||
|
||||
|
||||
|
||||
// we don't have to use Lock() here because plusings are read
|
||||
// before threads are started
|
||||
void * Plugin::LoadInitFun(const char * filename, Fun1 & fun_init)
|
||||
{
|
||||
void * p = dlopen(filename, RTLD_NOW | RTLD_LOCAL);
|
||||
@@ -245,24 +262,34 @@ bool Plugin::HasPlugin(const std::wstring & name)
|
||||
}
|
||||
|
||||
|
||||
bool Plugin::HasMessage(int message)
|
||||
{
|
||||
return (slots.find(message) != slots.end());
|
||||
}
|
||||
|
||||
void Plugin::Call(int message, Slots::iterator & slot, PluginInfo & info)
|
||||
|
||||
void Plugin::Call(Session * ses, int message, Slots::iterator & slot, PluginInfo & info)
|
||||
{
|
||||
if( !SetPointers(info) )
|
||||
return;
|
||||
|
||||
current_plugin = slot->second.index;
|
||||
info.plugin_id = current_plugin;
|
||||
info.session = ses;
|
||||
|
||||
if( current_plugin != -1 )
|
||||
info.plugin_data_base = cur->session->plugin_data.Get(current_plugin);
|
||||
if( current_plugin != -1 && ses )
|
||||
info.plugin_data_base = ses->plugin_data.Get(current_plugin);
|
||||
else
|
||||
info.plugin_data_base = 0;
|
||||
|
||||
if( !slot->second.is_running )
|
||||
{
|
||||
if( config->log_plugin_call )
|
||||
{
|
||||
Lock();
|
||||
log << log1 << "Plugin: calling plugin id: " << slot->second.index << ", message: " << message << logend;
|
||||
Unlock();
|
||||
}
|
||||
|
||||
slot->second.is_running = true;
|
||||
|
||||
@@ -275,27 +302,30 @@ void Plugin::Call(int message, Slots::iterator & slot, PluginInfo & info)
|
||||
slot->second.is_running = false;
|
||||
|
||||
if( config->log_plugin_call )
|
||||
log << log1 << "Plugin: returning from plugin id: " << slot->second.index << ", message: " << message << logend;
|
||||
{
|
||||
Lock();
|
||||
log << log1 << "Plugin: returning from plugin id: " << slot->second.index << ", message: " << message
|
||||
<< ", result: " << (info.res? "true" : "false") << logend;
|
||||
Unlock();
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
Lock();
|
||||
log << log1 << "Plugin: id: " << slot->second.index
|
||||
<< ", message: " << message
|
||||
<< ", recurrences are not allowed" << logend;
|
||||
Unlock();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void Plugin::Call(int message, void * p1_, void * p2_, long l1_, long l2_)
|
||||
PluginRes Plugin::Call(Session * ses, int message, void * p1_, void * p2_, long l1_, long l2_)
|
||||
{
|
||||
// how many plugins return 'false' and 'true'
|
||||
// we are using local variables because Call() method can be called
|
||||
// from a plugin too (one Call() can execute another Call())
|
||||
int ret_false_loc = 0;
|
||||
int ret_true_loc = 0;
|
||||
PluginRes res;
|
||||
int old_current_plugin = current_plugin;
|
||||
PluginInfo info;
|
||||
|
||||
@@ -309,88 +339,132 @@ PluginInfo info;
|
||||
info.l1 = l1_;
|
||||
info.l2 = l2_;
|
||||
|
||||
Call(message, i, info);
|
||||
Call(ses, message, i, info);
|
||||
|
||||
if( info.res )
|
||||
++ret_true_loc;
|
||||
++res.res_true;
|
||||
else
|
||||
++ret_false_loc;
|
||||
++res.res_false;
|
||||
}
|
||||
|
||||
current_plugin = old_current_plugin;
|
||||
ret_false = ret_false_loc;
|
||||
ret_true = ret_true_loc;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
void Plugin::Call(int message)
|
||||
PluginRes Plugin::Call(int message)
|
||||
{
|
||||
Call(message, 0, 0, 0, 0);
|
||||
return Call(cur->session, message, 0, 0, 0, 0);
|
||||
}
|
||||
|
||||
|
||||
void Plugin::Call(int message, void * p1_)
|
||||
PluginRes Plugin::Call(int message, void * p1_)
|
||||
{
|
||||
Call(message, p1_, 0, 0, 0);
|
||||
return Call(cur->session, message, p1_, 0, 0, 0);
|
||||
}
|
||||
|
||||
|
||||
void Plugin::Call(int message, void * p1_, void * p2_)
|
||||
PluginRes Plugin::Call(int message, void * p1_, void * p2_)
|
||||
{
|
||||
Call(message, p1_, p2_, 0, 0);
|
||||
return Call(cur->session, message, p1_, p2_, 0, 0);
|
||||
}
|
||||
|
||||
|
||||
void Plugin::Call(int message, long l1_)
|
||||
PluginRes Plugin::Call(int message, long l1_)
|
||||
{
|
||||
Call(message, 0, 0, l1_, 0);
|
||||
return Call(cur->session, message, 0, 0, l1_, 0);
|
||||
}
|
||||
|
||||
|
||||
void Plugin::Call(int message, long l1_, long l2_)
|
||||
PluginRes Plugin::Call(int message, long l1_, long l2_)
|
||||
{
|
||||
Call(message, 0, 0, l1_, l2_);
|
||||
return Call(cur->session, message, 0, 0, l1_, l2_);
|
||||
}
|
||||
|
||||
|
||||
void Plugin::Call(int message, void * p1_, long l1_)
|
||||
PluginRes Plugin::Call(int message, void * p1_, long l1_)
|
||||
{
|
||||
Call(message, p1_, 0, l1_, 0);
|
||||
return Call(cur->session, message, p1_, 0, l1_, 0);
|
||||
}
|
||||
|
||||
|
||||
void Plugin::Call(int message, void * p1_, long l1_, long l2_)
|
||||
PluginRes Plugin::Call(int message, void * p1_, long l1_, long l2_)
|
||||
{
|
||||
Call(message, p1_, 0, l1_, l2_);
|
||||
return Call(cur->session, message, p1_, 0, l1_, l2_);
|
||||
}
|
||||
|
||||
|
||||
void Plugin::Call(int message, void * p1_, void * p2_, long l1_)
|
||||
PluginRes Plugin::Call(int message, void * p1_, void * p2_, long l1_)
|
||||
{
|
||||
Call(message, p1_, p2_, l1_, 0);
|
||||
return Call(cur->session, message, p1_, p2_, l1_, 0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
PluginRes Plugin::Call(Session * ses, int message)
|
||||
{
|
||||
return Call(ses, message, 0, 0, 0, 0);
|
||||
}
|
||||
|
||||
|
||||
PluginRes Plugin::Call(Session * ses, int message, void * p1_)
|
||||
{
|
||||
return Call(ses, message, p1_, 0, 0, 0);
|
||||
}
|
||||
|
||||
|
||||
PluginRes Plugin::Call(Session * ses, int message, void * p1_, void * p2_)
|
||||
{
|
||||
return Call(ses, message, p1_, p2_, 0, 0);
|
||||
}
|
||||
|
||||
|
||||
PluginRes Plugin::Call(Session * ses, int message, long l1_)
|
||||
{
|
||||
return Call(ses, message, 0, 0, l1_, 0);
|
||||
}
|
||||
|
||||
|
||||
PluginRes Plugin::Call(Session * ses, int message, long l1_, long l2_)
|
||||
{
|
||||
return Call(ses, message, 0, 0, l1_, l2_);
|
||||
}
|
||||
|
||||
|
||||
PluginRes Plugin::Call(Session * ses, int message, void * p1_, long l1_)
|
||||
{
|
||||
return Call(ses, message, p1_, 0, l1_, 0);
|
||||
}
|
||||
|
||||
|
||||
PluginRes Plugin::Call(Session * ses, int message, void * p1_, long l1_, long l2_)
|
||||
{
|
||||
return Call(ses, message, p1_, 0, l1_, l2_);
|
||||
}
|
||||
|
||||
|
||||
PluginRes Plugin::Call(Session * ses, int message, void * p1_, void * p2_, long l1_)
|
||||
{
|
||||
return Call(ses, message, p1_, p2_, l1_, 0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
size_t Plugin::Size()
|
||||
{
|
||||
return plugins.size();
|
||||
}
|
||||
|
||||
|
||||
|
||||
int Plugin::True()
|
||||
{
|
||||
return ret_true;
|
||||
}
|
||||
|
||||
|
||||
int Plugin::False()
|
||||
{
|
||||
return ret_false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
!! IMPROVE ME
|
||||
Assign() can work only if other threads are not started
|
||||
we can add some barrier/flag so when other threads starts
|
||||
then we cannot use Assign() method
|
||||
*/
|
||||
void Plugin::Assign(int message, Fun1 fun1)
|
||||
{
|
||||
Slot s;
|
||||
@@ -420,3 +494,9 @@ Slot s;
|
||||
log << log3 << "Plugin: added function for message: " << message << ", plugin index: " << s.index << logend;
|
||||
}
|
||||
|
||||
|
||||
const Plugin::Plugins * Plugin::GetPlugins()
|
||||
{
|
||||
return &plugins;
|
||||
}
|
||||
|
||||
|
||||
103
core/plugin.h
103
core/plugin.h
@@ -2,7 +2,7 @@
|
||||
* This file is a part of Winix
|
||||
* and is not publicly distributed
|
||||
*
|
||||
* Copyright (c) 2008-2010, Tomasz Sowa
|
||||
* Copyright (c) 2008-2012, Tomasz Sowa
|
||||
* All rights reserved.
|
||||
*
|
||||
*/
|
||||
@@ -67,8 +67,17 @@ struct PluginInfo
|
||||
Synchro * synchro;
|
||||
SessionManager * session_manager;
|
||||
|
||||
// pointer to the plugin session (can be null if not set by the plugin)
|
||||
// you should use WINIX_SESSION_CREATED and WINIX_SESSION_REMOVE
|
||||
// a session
|
||||
// some messages are sent in a session's context e.g. logging a user
|
||||
// this pointer in not always the same as cur->session, it is preferred
|
||||
// to use this pointer instead of cur->session
|
||||
// (cur->session can point at a temporary object)
|
||||
// this pointer can be null
|
||||
Session * session;
|
||||
|
||||
// pointer to the plugin session (can be null if not set by the plugin or if session is null)
|
||||
// this is taken from session->plugin_data.Get()
|
||||
// you should use WINIX_SESSION_CREATED and WINIX_PLUGIN_SESSION_DATA_REMOVE
|
||||
// to create your plugin's session data
|
||||
PluginDataBase * plugin_data_base; // !! zmienic nazwe na plugin_session_base ? a moze session_base; a moze plugin_session?
|
||||
|
||||
@@ -86,14 +95,31 @@ struct PluginInfo
|
||||
l1 = 0;
|
||||
l2 = 0;
|
||||
|
||||
plugin_id = -1;
|
||||
plugin_data_base = 0;
|
||||
plugin_id = -1;
|
||||
session = 0;
|
||||
plugin_data_base = 0;
|
||||
|
||||
res = false;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
this structure tells how many plugins returned true and false
|
||||
*/
|
||||
struct PluginRes
|
||||
{
|
||||
int res_false;
|
||||
int res_true;
|
||||
|
||||
PluginRes()
|
||||
{
|
||||
res_false = 0;
|
||||
res_true = 0;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
class Plugin
|
||||
{
|
||||
@@ -124,6 +150,14 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
struct PluginsItem
|
||||
{
|
||||
void * handle;
|
||||
const wchar_t * plugin_name; // plugin name (can be null if was not set by the plugin)
|
||||
};
|
||||
|
||||
typedef std::vector<PluginsItem> Plugins;
|
||||
|
||||
|
||||
Plugin();
|
||||
~Plugin();
|
||||
@@ -148,32 +182,38 @@ public:
|
||||
bool HasPlugin(const wchar_t * name);
|
||||
bool HasPlugin(const std::wstring & name);
|
||||
|
||||
void Call(int message);
|
||||
void Call(int message, void * p1_);
|
||||
void Call(int message, void * p1_, void * p2_);
|
||||
void Call(int message, long l1_);
|
||||
void Call(int message, long l1_, long l2_);
|
||||
void Call(int message, void * p1_, long l1_);
|
||||
void Call(int message, void * p1_, long l1_, long l2_);
|
||||
void Call(int message, void * p1_, void * p2_, long l1_);
|
||||
void Call(int message, void * p1_, void * p2_, long l1_, long l2_);
|
||||
bool HasMessage(int message);
|
||||
|
||||
PluginRes Call(int message);
|
||||
PluginRes Call(int message, void * p1_);
|
||||
PluginRes Call(int message, void * p1_, void * p2_);
|
||||
PluginRes Call(int message, long l1_);
|
||||
PluginRes Call(int message, long l1_, long l2_);
|
||||
PluginRes Call(int message, void * p1_, long l1_);
|
||||
PluginRes Call(int message, void * p1_, long l1_, long l2_);
|
||||
PluginRes Call(int message, void * p1_, void * p2_, long l1_);
|
||||
PluginRes Call(Session * ses, int message, void * p1_, void * p2_, long l1_, long l2_);
|
||||
|
||||
PluginRes Call(Session * ses, int message);
|
||||
PluginRes Call(Session * ses, int message, void * p1_);
|
||||
PluginRes Call(Session * ses, int message, void * p1_, void * p2_);
|
||||
PluginRes Call(Session * ses, int message, long l1_);
|
||||
PluginRes Call(Session * ses, int message, long l1_, long l2_);
|
||||
PluginRes Call(Session * ses, int message, void * p1_, long l1_);
|
||||
PluginRes Call(Session * ses, int message, void * p1_, long l1_, long l2_);
|
||||
PluginRes Call(Session * ses, int message, void * p1_, void * p2_, long l1_);
|
||||
|
||||
// how many plugins there are
|
||||
size_t Size();
|
||||
|
||||
// how many plugins returned 'true'
|
||||
// from last Call()
|
||||
int True();
|
||||
|
||||
// how many plugins returned 'false'
|
||||
// from last Call()
|
||||
int False();
|
||||
|
||||
// assign a function to a message
|
||||
// you can assign more than one function to a specific message
|
||||
void Assign(int message, Fun1);
|
||||
void Assign(int message, Fun2);
|
||||
|
||||
// return a const pointer to the plugin tab
|
||||
const Plugins * GetPlugins();
|
||||
|
||||
private:
|
||||
|
||||
Db * db;
|
||||
@@ -185,29 +225,20 @@ private:
|
||||
Synchro * synchro;
|
||||
SessionManager * session_manager;
|
||||
|
||||
int ret_false;
|
||||
int ret_true;
|
||||
std::wstring temp_path; // used when loading plugins
|
||||
std::string afilename;
|
||||
|
||||
std::wstring temp_path;
|
||||
|
||||
struct PluginsItem
|
||||
{
|
||||
void * handle;
|
||||
const wchar_t * plugin_name; // plugin name (can be null if was not set by the plugin)
|
||||
};
|
||||
|
||||
typedef std::vector<PluginsItem> Plugins;
|
||||
Plugins plugins;
|
||||
|
||||
typedef std::multimap<int, Slot> Slots;
|
||||
Slots slots;
|
||||
|
||||
std::string afilename;
|
||||
|
||||
void * LoadInitFun(const char * filename, Fun1 & fun_init);
|
||||
void Call(int message, Slots::iterator & slot, PluginInfo & info);
|
||||
void Call(Session * ses, int message, Slots::iterator & slot, PluginInfo & info);
|
||||
|
||||
bool SetPointers(PluginInfo & info);
|
||||
void Lock();
|
||||
void Unlock();
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* This file is a part of Winix
|
||||
* and is not publicly distributed
|
||||
*
|
||||
* Copyright (c) 2008-2010, Tomasz Sowa
|
||||
* Copyright (c) 2008-2012, Tomasz Sowa
|
||||
* All rights reserved.
|
||||
*
|
||||
*/
|
||||
@@ -10,10 +10,49 @@
|
||||
#include "plugindata.h"
|
||||
#include "plugin.h"
|
||||
#include "log.h"
|
||||
#include "session.h"
|
||||
|
||||
|
||||
|
||||
|
||||
PluginData::PluginData()
|
||||
{
|
||||
session = 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
PluginData::PluginData(const PluginData & p)
|
||||
{
|
||||
operator=(p);
|
||||
}
|
||||
|
||||
|
||||
|
||||
PluginData & PluginData::operator=(const PluginData & p)
|
||||
{
|
||||
// we don't copy all pointers - only resize the table
|
||||
// pointers will be set to zero
|
||||
Resize(p.Size());
|
||||
session = 0;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
|
||||
PluginData::~PluginData()
|
||||
{
|
||||
DeleteAll();
|
||||
}
|
||||
|
||||
|
||||
void PluginData::SetSession(Session * ses)
|
||||
{
|
||||
session = ses;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void PluginData::Assign(size_t index, PluginDataBase * data)
|
||||
{
|
||||
@@ -62,46 +101,37 @@ return Get(plugin.current_plugin);
|
||||
|
||||
void PluginData::DeleteAll()
|
||||
{
|
||||
if( table.empty() )
|
||||
return;
|
||||
bool all_null = true;
|
||||
|
||||
plugin.Call(WINIX_SESSION_REMOVE);
|
||||
/*
|
||||
when we copy a session's object (and this object then)
|
||||
we resize the table and there are only null pointers there
|
||||
consequently if all pointers are null there is no sens
|
||||
to send WINIX_PLUGIN_SESSION_DATA_REMOVE
|
||||
*/
|
||||
|
||||
for(size_t i=0 ; i<table.size() ; ++i)
|
||||
table[i] = 0;
|
||||
{
|
||||
if( table[i] != 0 )
|
||||
{
|
||||
all_null = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
in the future this message may be removed
|
||||
and we directly 'delete' the pointers
|
||||
*/
|
||||
|
||||
if( !all_null )
|
||||
plugin.Call(session, WINIX_PLUGIN_SESSION_DATA_REMOVE);
|
||||
|
||||
table.clear();
|
||||
}
|
||||
|
||||
|
||||
|
||||
PluginData::PluginData()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
PluginData::PluginData(const PluginData & p)
|
||||
{
|
||||
operator=(p);
|
||||
}
|
||||
|
||||
|
||||
|
||||
PluginData & PluginData::operator=(const PluginData & p)
|
||||
{
|
||||
// we don't copy all pointers - only resize the table
|
||||
// pointers will be set to zero
|
||||
Resize(p.Size());
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
|
||||
PluginData::~PluginData()
|
||||
{
|
||||
DeleteAll();
|
||||
}
|
||||
|
||||
|
||||
|
||||
size_t PluginData::Size() const
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* This file is a part of Winix
|
||||
* and is not publicly distributed
|
||||
*
|
||||
* Copyright (c) 2008-2010, Tomasz Sowa
|
||||
* Copyright (c) 2008-2012, Tomasz Sowa
|
||||
* All rights reserved.
|
||||
*
|
||||
*/
|
||||
@@ -13,12 +13,22 @@
|
||||
#include <vector>
|
||||
|
||||
|
||||
|
||||
struct Session;
|
||||
|
||||
|
||||
struct PluginDataBase
|
||||
{
|
||||
virtual ~PluginDataBase() {}
|
||||
|
||||
/*
|
||||
!! CHECK ME
|
||||
it is still in use?
|
||||
|
||||
when deleting sessions we first call Clear() method
|
||||
consequently the destructor has nothing to do
|
||||
(and it does not throw an exception)
|
||||
*/
|
||||
virtual void Clear() {}
|
||||
};
|
||||
|
||||
|
||||
@@ -28,6 +38,13 @@ class PluginData
|
||||
{
|
||||
public:
|
||||
|
||||
PluginData();
|
||||
PluginData(const PluginData & p);
|
||||
PluginData & operator=(const PluginData & p);
|
||||
~PluginData();
|
||||
|
||||
void SetSession(Session * ses);
|
||||
|
||||
void Assign(size_t index, PluginDataBase * data);
|
||||
void Assign(PluginDataBase * data);
|
||||
|
||||
@@ -36,17 +53,13 @@ public:
|
||||
|
||||
void DeleteAll();
|
||||
|
||||
PluginData();
|
||||
PluginData(const PluginData & p);
|
||||
PluginData & operator=(const PluginData & p);
|
||||
~PluginData();
|
||||
|
||||
size_t Size() const;
|
||||
void Resize(size_t new_size);
|
||||
|
||||
|
||||
private:
|
||||
|
||||
Session * session;
|
||||
std::vector<PluginDataBase*> table;
|
||||
};
|
||||
|
||||
|
||||
236
core/pluginmsg.h
236
core/pluginmsg.h
@@ -2,7 +2,7 @@
|
||||
* This file is a part of Winix
|
||||
* and is not publicly distributed
|
||||
*
|
||||
* Copyright (c) 2008-2011, Tomasz Sowa
|
||||
* Copyright (c) 2008-2012, Tomasz Sowa
|
||||
* All rights reserved.
|
||||
*
|
||||
*/
|
||||
@@ -11,8 +11,10 @@
|
||||
#ifndef headerfile_winix_core_pluginmsg
|
||||
#define headerfile_winix_core_pluginmsg
|
||||
|
||||
|
||||
// here you can add your own EZC functions ([function])
|
||||
// PluginInfo.p1 is a pointer to Ezc::Functions object
|
||||
// session pointer is null
|
||||
#define WINIX_TEMPLATES_CREATEFUNCTIONS 999
|
||||
|
||||
// here you can add your own EZC functions to notify system
|
||||
@@ -24,79 +26,255 @@
|
||||
// Ezc::Functions<NotifyStream> ezc_functions;
|
||||
// and Notify Stream is:
|
||||
// typedef TextStream<std::wstring> NotifyStream;
|
||||
// session pointer is null
|
||||
#define WINIX_NOTIFY_TEMPLATES_CREATEFUNCTIONS 998
|
||||
|
||||
// winix function and parameters have been parsed
|
||||
// the request.status is OK
|
||||
// (the winix function was not called yet)
|
||||
#define WINIX_PREPARE_REQUEST 2000
|
||||
#define WINIX_PREPARE_REQUEST 20000
|
||||
|
||||
// post and get functions have done their jobs
|
||||
// now you can act
|
||||
// this is called only if the request.status is OK
|
||||
#define WINIX_PROCESS_REQUEST 2001
|
||||
#define WINIX_PROCESS_REQUEST 20010
|
||||
|
||||
// prepere your content for displaying
|
||||
// this is called after WINIX_PROCESS_REQUEST
|
||||
// and when there is not a redirect
|
||||
// request.status is not checked here
|
||||
#define WINIX_CONTENT_MAKE 2002
|
||||
#define WINIX_CONTENT_MAKE 20020
|
||||
|
||||
// here you can attach your own session data (based on PluginDataBase class)
|
||||
// call request.session->plugin_data.Assign(pointer)
|
||||
#define WINIX_SESSION_CREATED 3000
|
||||
// call cur->session->plugin_data.Assign(pointer)
|
||||
#define WINIX_SESSION_CREATED 30000
|
||||
|
||||
// here you should remove your session data
|
||||
#define WINIX_SESSION_REMOVE 3001
|
||||
// this message can be sent even if you don't assing your plugin data
|
||||
#define WINIX_PLUGIN_SESSION_DATA_REMOVE 30010
|
||||
|
||||
// when a session is changed (you can save a pointer to your data here)
|
||||
#define WINIX_SESSION_CHANGED 3002
|
||||
// 'session changed' means that there is a new request
|
||||
// !! IMPROVE ME it has to be changed to a better name
|
||||
#define WINIX_SESSION_CHANGED 30020
|
||||
|
||||
// a session has changed its id
|
||||
// it is typically when you are logging in
|
||||
// 'login' winix function will change the session id (for security reasons)
|
||||
// in l1 you have the old id, in l2 you have the new id
|
||||
#define WINIX_SESSION_CHANGED_ID 30025
|
||||
|
||||
// a session is going to be removed
|
||||
// it is called from session manager's thread (with lock/unlock)
|
||||
#define WINIX_PREPARE_SESSION_TO_REMOVE 30027
|
||||
|
||||
// a session has been removed
|
||||
// it is called from session manager's thread (with lock/unlock)
|
||||
// in l1 you have the old session id
|
||||
#define WINIX_SESSION_REMOVED 30029
|
||||
|
||||
// the winix is closing
|
||||
// the is not any session available (cur->session is null)
|
||||
#define WINIX_CLOSE 3004
|
||||
// there is not any sessions available (cur->session is null)
|
||||
// session pointer is null
|
||||
#define WINIX_CLOSE 30040
|
||||
|
||||
// preparing to remove a file (rm function)
|
||||
// in p1 you have a pointer to the Item struct (file)
|
||||
// valid members are:
|
||||
// id, parent_id, type, url, file_path, file_fs, file_type, has_thumb, hash, hash_type, file_size
|
||||
// user_id, group_id, privileges
|
||||
// (sometimes rest members can be valid as well -- when you call directly fun_rm->RemoveFileOrSymlink() method)
|
||||
#define WINIX_FILE_PREPARE_TO_REMOVE 30045
|
||||
|
||||
// a file or symlink was removed (rm function)
|
||||
// PluginInfo::l1 is the file (item) id
|
||||
// !! moze zmienic nazwe i dodac symlink w nazwie?
|
||||
#define WINIX_FILE_REMOVED 3005
|
||||
|
||||
// directory was removed (rm function)
|
||||
// PluginInfo::l1 is the dir id
|
||||
#define WINIX_DIR_REMOVED 3006
|
||||
// in p1 you have a pointer to the Item struct (old file)
|
||||
// valid members are the same as in WINIX_FILE_PREPARE_TO_REMOVE
|
||||
#define WINIX_FILE_REMOVED 30050
|
||||
|
||||
// preparing to remove a directory (rm function)
|
||||
// PluginInfo::l1 is the dir id
|
||||
#define WINIX_DIR_PREPARE_TO_REMOVE 3007
|
||||
// in p1 you have a pointer to the Item struct (directory)
|
||||
// this message is sent after checking the directory permissions
|
||||
// so consequently if there is no any database error then the
|
||||
// directory will be removed
|
||||
// and after removed WINIX_DIR_REMOVED message is sent
|
||||
#define WINIX_DIR_PREPARE_TO_REMOVE 30070
|
||||
|
||||
// directory was removed (rm function)
|
||||
// PluginInfo::l1 is the directory id
|
||||
#define WINIX_DIR_REMOVED 30060
|
||||
|
||||
// winix is initialized,
|
||||
// now you can initialize your plugin
|
||||
#define WINIX_PLUGIN_INIT 3008
|
||||
// session pointer is null
|
||||
#define WINIX_PLUGIN_INIT 30080
|
||||
|
||||
// here you can add your own mount point, file systems, mount parameters
|
||||
// for adding a new mount type call: system->mounts.AddMountType("new_mount_name")
|
||||
#define WINIX_ADD_MOUNTS 3009
|
||||
// session pointer is null
|
||||
#define WINIX_ADD_MOUNTS 30090
|
||||
|
||||
// add plugin functions here
|
||||
#define WINIX_CREATE_FUNCTIONS 3010
|
||||
// add plugin functions (winix functions) here
|
||||
// call info.functions->Add() to add a function
|
||||
// session pointer is null
|
||||
#define WINIX_CREATE_FUNCTIONS 30100
|
||||
|
||||
// choose a default function
|
||||
// if you do not select it then it will be choosen by winix
|
||||
#define WINIX_SELECT_DEFAULT_FUNCTION 3011
|
||||
#define WINIX_SELECT_DEFAULT_FUNCTION 30110
|
||||
|
||||
// /etc/fstab has been changed
|
||||
// now we have new mount points
|
||||
#define WINIX_FSTAB_CHANGED 3012
|
||||
// session pointer is null
|
||||
#define WINIX_FSTAB_CHANGED 30120
|
||||
|
||||
// here you add your own template to notification system
|
||||
// call system->notify.AddTemplate() method
|
||||
// with a template file name
|
||||
#define WINIX_NOTIFY_ADD_TEMPLATE 3013
|
||||
// session pointer is null
|
||||
#define WINIX_NOTIFY_ADD_TEMPLATE 30130
|
||||
|
||||
// the request is being ended
|
||||
// you can clear some of your objects here
|
||||
#define WINIX_END_REQUEST 30140
|
||||
|
||||
// a new file (page) has been added
|
||||
// in p1 you have a pointer to the Item struct
|
||||
#define WINIX_FILE_ADDED 30150
|
||||
|
||||
// a file (page) has been changed (edited)
|
||||
// in p1 you have a pointer to the Item struct
|
||||
#define WINIX_FILE_CHANGED 30160
|
||||
|
||||
// a new directory has been added
|
||||
// in p1 you have a pointer to the Item struct
|
||||
#define WINIX_DIR_ADDED 30155
|
||||
|
||||
// a file (page) has been copied
|
||||
// in p1 you have a pointer to the Item struct
|
||||
// not every fields of Item struct are filled
|
||||
#define WINIX_FILE_COPIED 30170
|
||||
|
||||
// a file will be moved
|
||||
// in p1 you have a pointer to the Item struct
|
||||
// valid members are:
|
||||
// id, parent_id, type, url, file_path, file_fs, file_type, has_thumb, hash, hash_type, file_size
|
||||
// user_id, group_id, privileges, meta
|
||||
// (sometimes rest members can be valid as well -- when you call directly fun_rm->RemoveFileOrSymlink() method)
|
||||
#define WINIX_FILE_PREPARE_TO_MOVE 30180
|
||||
|
||||
// a file has been moved
|
||||
// in p1 you have a pointer to the Item struct (new file)
|
||||
// valid members are the same as in WINIX_FILE_PREPARE_TO_MOVE
|
||||
#define WINIX_FILE_MOVED 30190
|
||||
|
||||
// a thumbnail was created
|
||||
// this message is called from another thread
|
||||
// the thread called Lock() before sending this message
|
||||
// in p1 you have a pointer to the Item struct
|
||||
// session pointer is null
|
||||
#define WINIX_CREATED_THUMB 30500
|
||||
|
||||
// an image has been resized
|
||||
// this message is called from another thread
|
||||
// the thread called Lock() before sending this message
|
||||
// in p1 you have a pointer to the Item struct
|
||||
// session pointer is null
|
||||
#define WINIX_IMAGE_RESIZED 30520
|
||||
|
||||
// content of a directory was sorted
|
||||
// (winix 'sort' function was used)
|
||||
// in p1 you have a pointer to the Item struct (of the directory)
|
||||
// this is from system->dirs so you should not change the item
|
||||
#define WINIX_DIR_CONTENT_SORTED 30500
|
||||
|
||||
// a user will be logged in
|
||||
// set PluginInfo::res to false (it is by default) to prevent logging the user
|
||||
// directly after this message (if you do not return false)
|
||||
// a WINIX_USER_LOGGED is sent
|
||||
// in p1 you have a pointer to User struct
|
||||
// (if at least one plugin returns false then the user will not be logged)
|
||||
// this message is not sent when winix starts and sessions are read from a sessions file
|
||||
// in such a case only WINIX_USER_LOGGED will be sent
|
||||
#define WINIX_PREPARE_USER_TO_LOGIN 30550
|
||||
|
||||
// a user has been logged
|
||||
// send from 'login' winix function
|
||||
// this message is also called when winix starts and reads sessions
|
||||
// from the session file
|
||||
#define WINIX_USER_LOGGED 30600
|
||||
|
||||
// a user is going to logout
|
||||
// in p1 you have a pointer to User struct
|
||||
// the message is also sent from the session GC (special thread for deleting sessions)
|
||||
// in such a case is sent with Lock() and Unlock()
|
||||
// so *don't* use Lock() in your procedure
|
||||
#define WINIX_PREPARE_USER_TO_LOGOUT 30610
|
||||
|
||||
// here you add your own html templates
|
||||
// call TemplatesFunctions::patterns.Add(L"file_name.html")
|
||||
// the method returns an index which you have to remember
|
||||
// and you can get the template with patterns.Get(index, lang_index)
|
||||
// it returns a pointer to Ezc::Pattern (or null pointer if the index is wrong)
|
||||
// the message will be sent too whenever 'reload/templates' winix function is called
|
||||
// templates you should add only in this message
|
||||
// in other cases after 'reload' function the indexes would be wrong
|
||||
// session pointer is null
|
||||
#define WINIX_ADD_TEMPLATE 31000
|
||||
|
||||
// a user will be removed
|
||||
// in p1 you have a pointer to the User struct
|
||||
// directly after this message a WINIX_USER_REMOVED will be sent
|
||||
#define WINIX_PREPARE_TO_REMOVE_USER 31010
|
||||
|
||||
// a user has been removed
|
||||
// in l1 you have the old user_id
|
||||
#define WINIX_USER_REMOVED 31020
|
||||
|
||||
// here you can check if the domain part of the URL address is correct
|
||||
// if no then set cur-request->redirect_to
|
||||
// and winix will do a 'base url redirect' without making any winix functions
|
||||
// the session pointer in info is null
|
||||
#define WINIX_BASE_URL_REDIRECT 31030
|
||||
|
||||
// raw POST parameters
|
||||
// in p1 there is a pointer to std::string meaning a parameter's name
|
||||
// in p2 there is a pointer to std::string value
|
||||
// this is sent only from PostParser
|
||||
// PostMultiParser (multipart/form-data html forms) doesn't send this messsage
|
||||
// there is no a session set (session pointer is null)
|
||||
// this message is sent for each name value pairs
|
||||
//
|
||||
#define WINIX_POST_PARAMS 31040
|
||||
|
||||
// this is the raw string sent in POST method
|
||||
// in p1 there is a pointer to std::string object
|
||||
#define WINIX_RAW_POST_STRING 31050
|
||||
|
||||
// this message is sent before calling MakePost() or MakeGet()
|
||||
// if you return false (which is default) you can prevent the access
|
||||
// to the resource
|
||||
#define WINIX_CHECK_PLUGIN_ACCESS 31060
|
||||
|
||||
|
||||
|
||||
/*
|
||||
messages sent from other threads
|
||||
!! IMPROVE ME check if some above messages should be moved here
|
||||
*/
|
||||
|
||||
|
||||
// a job has to be done
|
||||
// this is sent from the other thread (without locking)
|
||||
// in p1 you have a pointer to PT::Space
|
||||
// session is null
|
||||
// if you process the job then return 'true' from the processing method (from plugin call)
|
||||
// so this prevent to make a standard (system) job
|
||||
#define WINIX_JOB 31200
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// the request is ended
|
||||
// you can clear some of your object here
|
||||
#define WINIX_END_REQUEST 3014
|
||||
|
||||
// values from 4000 - 4099 reserved for 'thread' plugin
|
||||
// see plugins/thread/pluginmsg.h
|
||||
|
||||
@@ -2,15 +2,15 @@
|
||||
* This file is a part of Winix
|
||||
* and is not publicly distributed
|
||||
*
|
||||
* Copyright (c) 2008-2011, Tomasz Sowa
|
||||
* Copyright (c) 2008-2012, Tomasz Sowa
|
||||
* All rights reserved.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "postmultiparser.h"
|
||||
#include "log.h"
|
||||
#include "utf8.h"
|
||||
#include "misc.h"
|
||||
#include "utf8/utf8.h"
|
||||
|
||||
|
||||
|
||||
PostMultiParser::PostMultiParser()
|
||||
@@ -353,6 +353,15 @@ void PostMultiParser::ReadContent()
|
||||
}
|
||||
|
||||
|
||||
void PostMultiParser::ConvStr(const std::string & src, std::wstring & dst)
|
||||
{
|
||||
if( config->utf8 )
|
||||
PT::UTF8ToWide(src, dst);
|
||||
else
|
||||
AssignString(src, dst);
|
||||
}
|
||||
|
||||
|
||||
void PostMultiParser::AddNormalPostVar()
|
||||
{
|
||||
if( post_tab->size() >= WINIX_POSTTABLE_MAXSIZE )
|
||||
@@ -362,20 +371,10 @@ void PostMultiParser::AddNormalPostVar()
|
||||
return;
|
||||
}
|
||||
|
||||
ConvStr(name, namew);
|
||||
ConvStr(content, contentw);
|
||||
|
||||
if( config->utf8 )
|
||||
{
|
||||
Ezc::UTF8ToWide(name, namew);
|
||||
Ezc::UTF8ToWide(content, contentw);
|
||||
}
|
||||
else
|
||||
{
|
||||
AssignString(name, namew);
|
||||
AssignString(content, contentw);
|
||||
}
|
||||
|
||||
std::pair<PostTab::iterator, bool> res = post_tab->insert( std::make_pair(namew, contentw) );
|
||||
bool added = res.second;
|
||||
bool added = InsertPostVar(*post_tab, namew, contentw);
|
||||
|
||||
log << log2 << "PMP: POST var, name: \"" << namew << "\"";
|
||||
|
||||
@@ -395,20 +394,12 @@ void PostMultiParser::AddFilePostVar()
|
||||
return;
|
||||
}
|
||||
|
||||
if( config->utf8 )
|
||||
{
|
||||
Ezc::UTF8ToWide(name, namew);
|
||||
Ezc::UTF8ToWide(filename, post_file_temp.filename);
|
||||
}
|
||||
else
|
||||
{
|
||||
AssignString(name, namew);
|
||||
AssignString(filename, post_file_temp.filename);
|
||||
}
|
||||
|
||||
ConvStr(name, namew);
|
||||
ConvStr(filename, post_file_temp.filename);
|
||||
post_file_temp.tmp_filename = tmp_filename;
|
||||
std::pair<PostFileTab::iterator, bool> res = post_file_tab->insert( std::make_pair(namew, post_file_temp) );
|
||||
bool added = res.second;
|
||||
post_file_temp.file_size = content_len;
|
||||
|
||||
bool added = InsertPostVar(*post_file_tab, namew, post_file_temp);
|
||||
|
||||
log << log2 << "PMP: POST FILE var, name: \"" << namew << "\"";
|
||||
|
||||
@@ -424,15 +415,10 @@ void PostMultiParser::AddPostVar()
|
||||
if( name.empty() )
|
||||
return;
|
||||
|
||||
|
||||
if( filename.empty() )
|
||||
{
|
||||
AddNormalPostVar();
|
||||
}
|
||||
else
|
||||
{
|
||||
AddFilePostVar();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -479,7 +465,7 @@ size_t buf_len = sizeof(buf)/sizeof(wchar_t);
|
||||
tmp_filename_postfix += 1;
|
||||
|
||||
tmp_filename = buf;
|
||||
Ezc::WideToUTF8(tmp_filename, atmp_filename);
|
||||
PT::WideToUTF8(tmp_filename, atmp_filename);
|
||||
|
||||
tmp_file.open(atmp_filename.c_str(), std::ios_base::binary | std::ios_base::out);
|
||||
// !! dodac ustawienie chmod config.upload_files_chmod dla tymczasowego pliku
|
||||
@@ -569,6 +555,7 @@ Error PostMultiParser::Parse(FCGX_Stream * in_, PostTab & post_tab_, PostFileTab
|
||||
in = in_;
|
||||
last = 0;
|
||||
err = WINIX_ERR_OK;
|
||||
var_index = 1;
|
||||
line_end_dos = false;
|
||||
in_buffer_ind = WINIX_POSTMULTI_INPUT_BUFFER;
|
||||
in_buffer_len = WINIX_POSTMULTI_INPUT_BUFFER;
|
||||
@@ -587,6 +574,7 @@ Error PostMultiParser::Parse(FCGX_Stream * in_, PostTab & post_tab_, PostFileTab
|
||||
|
||||
if( err != WINIX_ERR_OK )
|
||||
{
|
||||
RemovePostFileTmp(*post_file_tab);
|
||||
post_tab->clear();
|
||||
post_file_tab->clear();
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* This file is a part of Winix
|
||||
* and is not publicly distributed
|
||||
*
|
||||
* Copyright (c) 2008-2010, Tomasz Sowa
|
||||
* Copyright (c) 2008-2011, Tomasz Sowa
|
||||
* All rights reserved.
|
||||
*
|
||||
*/
|
||||
@@ -16,6 +16,7 @@
|
||||
#include "error.h"
|
||||
#include "requesttypes.h"
|
||||
#include "config.h"
|
||||
#include "misc.h"
|
||||
|
||||
|
||||
// 2 MB
|
||||
@@ -53,6 +54,7 @@ private:
|
||||
PostFileTab * post_file_tab;
|
||||
|
||||
int last; // last read character
|
||||
int var_index; // used as a postfix to the same name (is auto increment)
|
||||
|
||||
bool line_end_dos;
|
||||
std::string boundary;
|
||||
@@ -67,6 +69,7 @@ private:
|
||||
PostFile post_file_temp;
|
||||
|
||||
void LogFirst(const std::string & to_log, size_t len);
|
||||
void ConvStr(const std::string & src, std::wstring & dst);
|
||||
|
||||
bool IsWhite(int c);
|
||||
void SkipWhite();
|
||||
@@ -94,7 +97,36 @@ private:
|
||||
|
||||
void ReadChar();
|
||||
|
||||
|
||||
template<class Container, class Value>
|
||||
bool InsertPostVar(Container & container, std::wstring & key, const Value & value);
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
template<class Container, class Value>
|
||||
bool PostMultiParser::InsertPostVar(Container & container, std::wstring & key, const Value & value)
|
||||
{
|
||||
bool added;
|
||||
std::pair<typename Container::iterator, bool> res;
|
||||
|
||||
res = container.insert( std::make_pair(key, value) );
|
||||
added = res.second;
|
||||
|
||||
if( !added )
|
||||
{
|
||||
key += L"_inc";
|
||||
key += Toa(var_index);
|
||||
res = container.insert( std::make_pair(key, value) );
|
||||
added = res.second;
|
||||
var_index += 1;
|
||||
}
|
||||
|
||||
return added;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* This file is a part of Winix
|
||||
* and is not publicly distributed
|
||||
*
|
||||
* Copyright (c) 2008-2011, Tomasz Sowa
|
||||
* Copyright (c) 2008-2012, Tomasz Sowa
|
||||
* All rights reserved.
|
||||
*
|
||||
*/
|
||||
@@ -15,9 +15,10 @@
|
||||
#include "httpsimpleparser.h"
|
||||
#include "requesttypes.h"
|
||||
#include "misc.h"
|
||||
#include "utf8.h"
|
||||
#include "utf8/utf8.h"
|
||||
#include "log.h"
|
||||
#include "config.h"
|
||||
#include "plugin.h"
|
||||
|
||||
|
||||
|
||||
@@ -29,6 +30,10 @@ class PostParser : public HttpSimpleParser
|
||||
std::wstring temp_name, temp_value;
|
||||
bool input_as_utf8;
|
||||
size_t log_value_size;
|
||||
int var_index;
|
||||
bool has_winix_post_params_msg;
|
||||
bool has_winix_raw_post_msg;
|
||||
std::string raw_post;
|
||||
|
||||
|
||||
protected:
|
||||
@@ -36,7 +41,12 @@ protected:
|
||||
|
||||
virtual int GetChar()
|
||||
{
|
||||
return FCGX_GetChar(in);
|
||||
int c = FCGX_GetChar(in);
|
||||
|
||||
if( c != -1 && has_winix_raw_post_msg )
|
||||
raw_post += c;
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
|
||||
@@ -63,21 +73,39 @@ protected:
|
||||
}
|
||||
|
||||
|
||||
virtual void Parameter(std::string & name, std::string & value)
|
||||
void ConvStr(const std::string & src, std::wstring & dst)
|
||||
{
|
||||
if( input_as_utf8 )
|
||||
{
|
||||
Ezc::UTF8ToWide(name, temp_name);
|
||||
Ezc::UTF8ToWide(value, temp_value);
|
||||
}
|
||||
PT::UTF8ToWide(src, dst);
|
||||
else
|
||||
AssignString(src, dst);
|
||||
}
|
||||
|
||||
|
||||
virtual void Parameter(std::string & name, std::string & value)
|
||||
{
|
||||
bool added;
|
||||
std::pair<PostTab::iterator, bool> res;
|
||||
|
||||
if( has_winix_post_params_msg )
|
||||
plugin.Call(0, WINIX_POST_PARAMS, &name, &value);
|
||||
|
||||
ConvStr(name, temp_name);
|
||||
ConvStr(value, temp_value);
|
||||
|
||||
res = post_tab->insert( std::make_pair(temp_name, temp_value) );
|
||||
added = res.second;
|
||||
|
||||
if( !added )
|
||||
{
|
||||
AssignString(name, temp_name);
|
||||
AssignString(value, temp_value);
|
||||
temp_name += L"_inc";
|
||||
temp_name += Toa(var_index);
|
||||
res = post_tab->insert( std::make_pair(temp_name, temp_value) );
|
||||
added = res.second;
|
||||
var_index += 1;
|
||||
}
|
||||
|
||||
std::pair<PostTab::iterator, bool> res = post_tab->insert( std::make_pair(temp_name, temp_value) );
|
||||
CreateLog(res.second);
|
||||
CreateLog(added);
|
||||
}
|
||||
|
||||
|
||||
@@ -89,7 +117,6 @@ public:
|
||||
log_value_size = 0;
|
||||
}
|
||||
|
||||
|
||||
void UTF8(bool utf)
|
||||
{
|
||||
input_as_utf8 = utf;
|
||||
@@ -104,8 +131,18 @@ public:
|
||||
{
|
||||
in = in_;
|
||||
post_tab = &post_tab_;
|
||||
var_index = 1;
|
||||
raw_post.clear();
|
||||
|
||||
has_winix_post_params_msg = plugin.HasMessage(WINIX_POST_PARAMS);
|
||||
has_winix_raw_post_msg = plugin.HasMessage(WINIX_RAW_POST_STRING);
|
||||
|
||||
HttpSimpleParser::Parse();
|
||||
|
||||
if( has_winix_raw_post_msg )
|
||||
plugin.Call(0, WINIX_RAW_POST_STRING, &raw_post);
|
||||
|
||||
raw_post.clear();
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
162
core/request.cpp
162
core/request.cpp
@@ -2,7 +2,7 @@
|
||||
* This file is a part of Winix
|
||||
* and is not publicly distributed
|
||||
*
|
||||
* Copyright (c) 2008-2010, Tomasz Sowa
|
||||
* Copyright (c) 2008-2012, Tomasz Sowa
|
||||
* All rights reserved.
|
||||
*
|
||||
*/
|
||||
@@ -30,33 +30,44 @@ void Request::SetConfig(Config * pconfig)
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void Request::ClearPostFileTmp()
|
||||
void Request::ClearAjax()
|
||||
{
|
||||
// deleting temporary files (if exists)
|
||||
size_t i = ajax.spaces.size();
|
||||
|
||||
while( !post_file_tab.empty() )
|
||||
while( i-- > 0 )
|
||||
ajax.RemoveSpace(i);
|
||||
|
||||
ajax.table.clear();
|
||||
|
||||
PT::Space::TableSingle::iterator s = ajax.table_single.begin();
|
||||
|
||||
while( s != ajax.table_single.end() )
|
||||
{
|
||||
const std::wstring & tmp_filename = post_file_tab.begin()->second.tmp_filename;
|
||||
|
||||
if( RemoveFile(tmp_filename) )
|
||||
log << log3 << "Request: deleted tmp file: " << tmp_filename << logend;
|
||||
if( s->first != L"content" && s->first != L"http_status" )
|
||||
{
|
||||
ajax.table_single.erase(s++);
|
||||
}
|
||||
else
|
||||
{
|
||||
// small optimization when deleting
|
||||
// the memory for "content" and "http_status" will be reused
|
||||
s->second.clear();
|
||||
|
||||
post_file_tab.erase(post_file_tab.begin());
|
||||
++s;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void Request::Clear()
|
||||
{
|
||||
// id is never 0
|
||||
if( ++id == 0 )
|
||||
++id;
|
||||
|
||||
ClearPostFileTmp();
|
||||
RemovePostFileTmp(post_file_tab);
|
||||
|
||||
get_tab.clear();
|
||||
post_tab.clear();
|
||||
post_file_tab.clear();
|
||||
cookie_tab.clear();
|
||||
@@ -66,7 +77,11 @@ void Request::Clear()
|
||||
|
||||
headers.Clear();
|
||||
page.Clear();
|
||||
ajaxpage.Clear();
|
||||
debug.Clear();
|
||||
|
||||
page_generated = false;
|
||||
use_html_filter = true;
|
||||
|
||||
env_request_method = &char_empty;
|
||||
env_request_uri = &char_empty;
|
||||
@@ -77,6 +92,7 @@ void Request::Clear()
|
||||
env_fcgi_role = &char_empty;
|
||||
env_content_type = &char_empty;
|
||||
env_http_accept_encoding = &char_empty;
|
||||
env_https = &char_empty;
|
||||
|
||||
item_tab.clear();
|
||||
item.Clear();
|
||||
@@ -85,20 +101,51 @@ void Request::Clear()
|
||||
is_item = false;
|
||||
function = 0; // !! dodac jakas empty funkcje
|
||||
param_tab.clear();
|
||||
anchor.clear();
|
||||
|
||||
status = WINIX_ERR_OK;
|
||||
|
||||
browser_msie = false;
|
||||
redirect_to.clear();
|
||||
redirect_type = 303;
|
||||
x_sendfile.clear();
|
||||
send_as_attachment = false;
|
||||
|
||||
using_ssl = false;
|
||||
|
||||
start_time = 0;
|
||||
start_date.Clear();
|
||||
|
||||
subdomain.clear();
|
||||
ClearAjax();
|
||||
ajax_serializer = 0;
|
||||
|
||||
binary_page.clear();
|
||||
compressed_page.clear();
|
||||
use_text_page = true;
|
||||
|
||||
gen_trim_white = false;
|
||||
gen_skip_new_line = false;
|
||||
gen_use_special_chars = false;
|
||||
|
||||
ip = 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void Request::RequestStarts()
|
||||
{
|
||||
// clearing it is better to use at the end of a request
|
||||
// so starting is much faster
|
||||
|
||||
start_time = std::time(0);
|
||||
start_date = start_time;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// value can be null
|
||||
void Request::SetCookie(const char * name, const char * value, tm * expires)
|
||||
void Request::SetCookie(const char * name, const char * value, PT::Date * expires)
|
||||
{
|
||||
headers << "Set-Cookie: " << name << "=";
|
||||
|
||||
@@ -108,21 +155,29 @@ void Request::SetCookie(const char * name, const char * value, tm * expires)
|
||||
headers << "\"\"";
|
||||
|
||||
if( expires )
|
||||
headers << "; expires=" << DateToStrCookie(expires) << " GMT";
|
||||
headers << "; expires=" << DateToStrCookie(*expires) << " GMT";
|
||||
|
||||
headers << "; path=/; domain=." << config->base_server << "\r\n";
|
||||
headers << "; path=/; domain=" << config->base_url << "\r\n";
|
||||
|
||||
/*
|
||||
don't use '; secure' flag if you are using both sites (with SSL
|
||||
and without SSL) -- with secure flag the cookie is sent only through
|
||||
SSL and if you accidentally open a new window without SSL (http://)
|
||||
then winix will create a new session for you and the previous session (https://)
|
||||
will be lost (cookie is overwritten on the client browser)
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
|
||||
void Request::SetCookie(const char * name, long value, tm * expires)
|
||||
void Request::SetCookie(const char * name, long value, PT::Date * expires)
|
||||
{
|
||||
headers << "Set-Cookie: " << name << "=" << value;
|
||||
|
||||
if( expires )
|
||||
headers << "; expires=" << DateToStrCookie(expires) << " GMT";
|
||||
headers << "; expires=" << DateToStrCookie(*expires) << " GMT";
|
||||
|
||||
headers << "; path=/; domain=." << config->base_server << "\r\n";
|
||||
headers << "; path=/; domain=" << config->base_url << "\r\n";
|
||||
}
|
||||
|
||||
|
||||
@@ -140,6 +195,18 @@ return true;
|
||||
}
|
||||
|
||||
|
||||
bool Request::IsPostVar(const std::wstring & var)
|
||||
{
|
||||
PostTab::iterator p;
|
||||
|
||||
p = post_tab.find(var);
|
||||
|
||||
if( p == post_tab.end() )
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
const std::wstring & Request::PostVar(const wchar_t * var)
|
||||
{
|
||||
@@ -152,6 +219,17 @@ return p->second;
|
||||
}
|
||||
|
||||
|
||||
const std::wstring & Request::PostVar(const std::wstring & var)
|
||||
{
|
||||
PostTab::iterator p = post_tab.find(var);
|
||||
|
||||
if( p == post_tab.end() )
|
||||
return str_empty;
|
||||
|
||||
return p->second;
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool Request::PostVar(const wchar_t * var, std::wstring & result)
|
||||
{
|
||||
@@ -169,6 +247,23 @@ return true;
|
||||
}
|
||||
|
||||
|
||||
bool Request::PostVar(const std::wstring & var, std::wstring & result)
|
||||
{
|
||||
PostTab::iterator p = post_tab.find(var);
|
||||
|
||||
if( p == post_tab.end() )
|
||||
{
|
||||
result.clear();
|
||||
return false;
|
||||
}
|
||||
|
||||
result = p->second;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
std::wstring * Request::PostVarp(const wchar_t * var)
|
||||
{
|
||||
PostTab::iterator p = post_tab.find(var);
|
||||
@@ -180,30 +275,17 @@ return &p->second;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void Request::PrintGetTab()
|
||||
std::wstring * Request::PostVarp(const std::wstring & var)
|
||||
{
|
||||
debug << "get_tab: " << get_tab.size() << "\n";
|
||||
|
||||
for(GetTab::iterator i = get_tab.begin() ; i != get_tab.end() ; ++i)
|
||||
debug << " \"" << *i << "\"\n";
|
||||
|
||||
debug << '\n';
|
||||
PostTab::iterator p = post_tab.find(var);
|
||||
|
||||
if( p == post_tab.end() )
|
||||
return 0;
|
||||
|
||||
return &p->second;
|
||||
}
|
||||
|
||||
/*
|
||||
void Request::PrintEnv()
|
||||
{
|
||||
char ** e;
|
||||
|
||||
debug << "environment variables:\n";
|
||||
|
||||
for( e = env ; *e ; ++e )
|
||||
debug << ' ' << *e << "\n";
|
||||
|
||||
debug << '\n';
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
|
||||
bool Request::AllPostVarEmpty()
|
||||
|
||||
102
core/request.h
102
core/request.h
@@ -2,7 +2,7 @@
|
||||
* This file is a part of Winix
|
||||
* and is not publicly distributed
|
||||
*
|
||||
* Copyright (c) 2008-2010, Tomasz Sowa
|
||||
* Copyright (c) 2008-2012, Tomasz Sowa
|
||||
* All rights reserved.
|
||||
*
|
||||
*/
|
||||
@@ -19,6 +19,10 @@
|
||||
#include "config.h"
|
||||
#include "textstream.h"
|
||||
#include "templates/htmltextstream.h"
|
||||
#include "date/date.h"
|
||||
#include "space/space.h"
|
||||
#include "space/spacetojson.h"
|
||||
|
||||
|
||||
|
||||
class FunctionBase;
|
||||
@@ -42,13 +46,35 @@ struct Request
|
||||
//std::ostringstream headers, page, debug;
|
||||
TextStream<std::string> headers;
|
||||
HtmlTextStream page, debug;
|
||||
TextStream<std::wstring> ajaxpage;
|
||||
|
||||
// binary page
|
||||
BinaryPage binary_page;
|
||||
|
||||
// a compressed page ready to send to the client
|
||||
BinaryPage compressed_page;
|
||||
|
||||
// if true then either page or ajaxpage will be sent to the client
|
||||
// if false then binary_page is sent
|
||||
// default: true
|
||||
bool use_text_page;
|
||||
|
||||
// if set to true then the standard template system will not be generated
|
||||
// default: false
|
||||
bool page_generated;
|
||||
|
||||
// whether or not the html filter should be used
|
||||
// default: true
|
||||
bool use_html_filter;
|
||||
|
||||
// raw parameters
|
||||
GetTab get_tab;
|
||||
PostTab post_tab;
|
||||
PostFileTab post_file_tab;
|
||||
CookieTab cookie_tab;
|
||||
|
||||
// html anchor (those part of URI after '#' character)
|
||||
std::wstring anchor;
|
||||
|
||||
// environment variables
|
||||
// they are not null -- when the server doesn't have such a variable
|
||||
// it will be pointing into 'char_empty' which is default '\0'
|
||||
@@ -61,13 +87,21 @@ struct Request
|
||||
const char * env_http_accept_encoding;
|
||||
const char * env_fcgi_role;
|
||||
const char * env_content_type;
|
||||
const char * env_https;
|
||||
|
||||
// current IP address of the remote host (read from REMOTE_ADDR environment variable)
|
||||
// (at the moment only IPv4 are supported)
|
||||
int ip;
|
||||
|
||||
// true if the browser is Microsoft Internet Explorer
|
||||
bool browser_msie;
|
||||
|
||||
// true if the browser is Konqueror
|
||||
bool browser_konqueror;
|
||||
|
||||
// true if we are using encrypted connection (SSL)
|
||||
bool using_ssl;
|
||||
|
||||
// current directory
|
||||
std::vector<Item*> dir_tab;
|
||||
|
||||
@@ -91,40 +125,81 @@ struct Request
|
||||
std::vector<Item> item_tab;
|
||||
|
||||
// if not empty means an address for redirecting to
|
||||
// it should be url-encoded
|
||||
std::wstring redirect_to;
|
||||
std::string aredirect_to;
|
||||
|
||||
// a redirect type
|
||||
// following redirect types are supported:
|
||||
// 300 Multiple Choices
|
||||
// 301 Moved Permanently
|
||||
// 302 Found
|
||||
// 303 See Other (default)
|
||||
// 307 Temporary Redirect
|
||||
int redirect_type;
|
||||
|
||||
// send header X-LIGHTTPD-send-file with path to a file
|
||||
std::wstring x_sendfile;
|
||||
|
||||
// send as attachment (causing header: content-disposition: attachment)
|
||||
// send as attachment (causes header: content-disposition: attachment)
|
||||
bool send_as_attachment;
|
||||
|
||||
// this is a pointer either to the item (if exists) or to the last directory
|
||||
Item * last_item;
|
||||
|
||||
// request start time
|
||||
// Time() methods are very slow so it is better to directly use those two values
|
||||
// they are set when a request starts
|
||||
time_t start_time;
|
||||
PT::Date start_date;
|
||||
|
||||
// a subdomain
|
||||
// subdomain = HTTP_HOST environment variable - config->base_url
|
||||
std::wstring subdomain;
|
||||
|
||||
// used as a JSON output (when ajax_serializer is defined)
|
||||
// it will be serialized and have at least:
|
||||
// 'content' string - the whole html content
|
||||
// 'http_status' integer - http status code (e.g. 200)
|
||||
PT::Space ajax;
|
||||
|
||||
// if not null then the request will have a JSON as an output
|
||||
PT::SpaceToJSON * ajax_serializer;
|
||||
|
||||
// options used by ezc generators
|
||||
bool gen_trim_white;
|
||||
bool gen_skip_new_line;
|
||||
bool gen_use_special_chars;
|
||||
|
||||
|
||||
Request();
|
||||
void SetConfig(Config * pconfig);
|
||||
void RequestStarts();
|
||||
void Clear();
|
||||
|
||||
// for debugging
|
||||
void PrintGetTab();
|
||||
//void PrintEnv();
|
||||
|
||||
|
||||
bool IsParam(const wchar_t * param_name);
|
||||
bool IsParam(const std::wstring & param_name);
|
||||
const std::wstring & ParamValue(const wchar_t * param_name); // returns empty string if there is no such a parameter
|
||||
const std::wstring & ParamValue(const std::wstring & param_name); // returns empty string if there is no such a parameter
|
||||
|
||||
void SetCookie(const char * name, const char * value, tm * expires = 0);
|
||||
void SetCookie(const char * name, long value, tm * expires = 0);
|
||||
const std::wstring & ParamValue(const wchar_t * param_name); // returns an empty string if there is no such a parameter
|
||||
const std::wstring & ParamValue(const std::wstring & param_name); // returns an empty string if there is no such a parameter
|
||||
|
||||
void SetCookie(const char * name, const char * value, PT::Date * expires = 0);
|
||||
void SetCookie(const char * name, long value, PT::Date * expires = 0);
|
||||
|
||||
bool IsPostVar(const wchar_t * var);
|
||||
const std::wstring & PostVar(const wchar_t * var); // !! zamienic na referencje nie do sta³ej (bez const)
|
||||
bool IsPostVar(const std::wstring & var);
|
||||
|
||||
const std::wstring & PostVar(const wchar_t * var); // returns an empty string if there is no such a parameter
|
||||
const std::wstring & PostVar(const std::wstring & var); // returns an empty string if there is no such a parameter
|
||||
|
||||
|
||||
bool PostVar(const wchar_t * var, std::wstring & result);
|
||||
bool PostVar(const std::wstring & var, std::wstring & result);
|
||||
|
||||
std::wstring * PostVarp(const wchar_t * var);
|
||||
std::wstring * PostVarp(const std::wstring & var);
|
||||
|
||||
bool AllPostVarEmpty(); // returning true if all post vars are empty
|
||||
|
||||
@@ -135,14 +210,15 @@ private:
|
||||
|
||||
Config * config;
|
||||
|
||||
void ClearPostFileTmp();
|
||||
|
||||
// contains '\0'
|
||||
// used to set env_* pointers to the empty value
|
||||
const char char_empty;
|
||||
|
||||
// used in ParamValue() and PostVar() when there is no such a param
|
||||
const std::wstring str_empty;
|
||||
|
||||
void ClearAjax();
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* This file is a part of Winix
|
||||
* and is not publicly distributed
|
||||
*
|
||||
* Copyright (c) 2008-2010, Tomasz Sowa
|
||||
* Copyright (c) 2008-2011, Tomasz Sowa
|
||||
* All rights reserved.
|
||||
*
|
||||
*/
|
||||
@@ -13,6 +13,7 @@
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include "textstream/textstream.h"
|
||||
|
||||
|
||||
// !! narazie uzywane tylko w post multi parserze
|
||||
@@ -20,10 +21,12 @@
|
||||
#define WINIX_POSTTABLE_MAXSIZE 50
|
||||
|
||||
|
||||
|
||||
struct PostFile
|
||||
{
|
||||
std::wstring filename; // original file name
|
||||
std::wstring tmp_filename; // file with content (in /tmp)
|
||||
size_t file_size;
|
||||
};
|
||||
|
||||
|
||||
@@ -36,7 +39,6 @@ struct Param
|
||||
|
||||
|
||||
// some global types used by Request class
|
||||
typedef std::vector<std::wstring> GetTab;
|
||||
typedef std::map<std::wstring, std::wstring> PostTab;
|
||||
typedef std::map<std::wstring, PostFile> PostFileTab;
|
||||
typedef std::vector<Param> ParamTab;
|
||||
@@ -44,5 +46,7 @@ typedef std::vector<Param> ParamTab;
|
||||
typedef std::map<std::string, std::string> CookieTab;
|
||||
|
||||
|
||||
typedef PT::TextStreamBase<char, 1, 4096> BinaryPage;
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
@@ -181,6 +181,7 @@ void Run::ChildThrow()
|
||||
|
||||
execve(command, par, env);
|
||||
// if we are here then there is something wrong (execve failed)
|
||||
// !! IMPROVE ME may add exit() ?
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* This file is a part of Winix
|
||||
* and is not publicly distributed
|
||||
*
|
||||
* Copyright (c) 2008-2010, Tomasz Sowa
|
||||
* Copyright (c) 2008-2012, Tomasz Sowa
|
||||
* All rights reserved.
|
||||
*
|
||||
*/
|
||||
@@ -15,36 +15,80 @@
|
||||
|
||||
Session::Session()
|
||||
{
|
||||
SetTimeToNow();
|
||||
Clear();
|
||||
plugin_data.SetSession(this);
|
||||
}
|
||||
|
||||
|
||||
void Session::SetTimeToNow()
|
||||
|
||||
Session::Session(const Session & ses)
|
||||
{
|
||||
time = std::time(0);
|
||||
tm_time = Time(time);
|
||||
|
||||
last_time = time;
|
||||
tm_last_time = tm_time;
|
||||
operator=(ses);
|
||||
}
|
||||
|
||||
// the first request can be a POST (it doesn't matter)
|
||||
last_time_get = time;
|
||||
Session & Session::operator=(const Session & ses)
|
||||
{
|
||||
/*
|
||||
we can only copy ses.id because it is needen in SessionContainer
|
||||
it have indexes to id
|
||||
*/
|
||||
|
||||
Clear();
|
||||
id = ses.id;
|
||||
plugin_data.SetSession(this);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
// this doesn't clear times
|
||||
void Session::Clear()
|
||||
|
||||
|
||||
|
||||
void Session::SetTimesTo(time_t time)
|
||||
{
|
||||
start_time = time;
|
||||
start_date = time;
|
||||
|
||||
last_time = start_time;
|
||||
last_date = start_date;
|
||||
|
||||
// the first request can be a POST (it doesn't matter)
|
||||
last_time_get = start_time;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// clear_plugin_data is used when clearing the temporary session
|
||||
void Session::Clear(bool clear_plugin_data)
|
||||
{
|
||||
id = 0;
|
||||
time = 0;
|
||||
puser = 0;
|
||||
rebus_item = 0;
|
||||
rebus_checked = false;
|
||||
remember_me = false;
|
||||
new_session = true;
|
||||
spam_score = 0;
|
||||
plugin_data.Resize(0);
|
||||
remove_me = false;
|
||||
|
||||
start_time = 0;
|
||||
last_time = 0;
|
||||
last_time_get = 0;
|
||||
start_date.Clear();
|
||||
last_date.Clear();
|
||||
|
||||
log_buffer.Clear();
|
||||
last_css.clear();
|
||||
ip_ban = 0;
|
||||
|
||||
if( clear_plugin_data )
|
||||
plugin_data.Resize(0);
|
||||
}
|
||||
|
||||
|
||||
// clearing some variables when a request is ended (just for safety)
|
||||
void Session::ClearOnEndRequest()
|
||||
{
|
||||
// ip_ban list can be sorted by SessionManager (in the special thread)
|
||||
ip_ban = 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* This file is a part of Winix
|
||||
* and is not publicly distributed
|
||||
*
|
||||
* Copyright (c) 2008-2011, Tomasz Sowa
|
||||
* Copyright (c) 2008-2012, Tomasz Sowa
|
||||
* All rights reserved.
|
||||
*
|
||||
*/
|
||||
@@ -10,6 +10,8 @@
|
||||
#ifndef headerfile_winix_core_session
|
||||
#define headerfile_winix_core_session
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <ctime>
|
||||
#include "item.h"
|
||||
#include "error.h"
|
||||
@@ -17,14 +19,22 @@
|
||||
#include "plugindata.h"
|
||||
#include "rebus.h"
|
||||
#include "textstream.h"
|
||||
#include "date/date.h"
|
||||
#include "ipban.h"
|
||||
|
||||
|
||||
|
||||
// when deleting Sessions you should set request.session into the session object as well
|
||||
// this allows to delete plugins session data
|
||||
// because a session object has plugin_data object
|
||||
// and in its destructor the plugin.Call(WINIX_SESSION_REMOVE) is called
|
||||
struct Session
|
||||
{
|
||||
Session();
|
||||
Session(const Session & ses);
|
||||
Session & operator=(const Session & ses);
|
||||
|
||||
void SetTimesTo(time_t time);
|
||||
void Clear(bool clear_plugin_data = true);
|
||||
void ClearOnEndRequest();
|
||||
|
||||
|
||||
// 0 - means that there is a temporary session
|
||||
long id;
|
||||
|
||||
@@ -33,18 +43,19 @@ struct Session
|
||||
|
||||
// when this session was created
|
||||
// (the same values)
|
||||
time_t time;
|
||||
tm tm_time;
|
||||
time_t start_time;
|
||||
PT::Date start_date;
|
||||
|
||||
// when this session was last used
|
||||
// (the same values)
|
||||
time_t last_time;
|
||||
tm tm_last_time;
|
||||
time_t last_time;
|
||||
PT::Date last_date;
|
||||
|
||||
// when there was a last get request
|
||||
// (used to calculate spam)
|
||||
// (used to calculate spam or invalid login attempts etc.)
|
||||
time_t last_time_get;
|
||||
|
||||
|
||||
// 0 - means that nobody is logged
|
||||
User * puser;
|
||||
|
||||
@@ -59,6 +70,9 @@ struct Session
|
||||
|
||||
int spam_score;
|
||||
|
||||
// if true then this session will be removed by SessionManager
|
||||
// without checking the time expiration
|
||||
bool remove_me;
|
||||
|
||||
PluginData plugin_data;
|
||||
|
||||
@@ -66,10 +80,17 @@ struct Session
|
||||
// buffer for the session log
|
||||
TextStream<std::wstring> log_buffer;
|
||||
|
||||
// !! IMPROVE ME it is still needed?
|
||||
// css cannot be taken directly from the mountpoint?
|
||||
// table with css files
|
||||
// used by some javascript wysiwyg editors (ckeditor, tinymce)
|
||||
std::vector<std::wstring> last_css;
|
||||
|
||||
// pointer to IPBan struct if exists for this IP
|
||||
// many sessions can pointer to the same IPBan struct
|
||||
// (it can be null)
|
||||
IPBan * ip_ban;
|
||||
|
||||
Session();
|
||||
void SetTimeToNow();
|
||||
void Clear();
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* This file is a part of Winix
|
||||
* and is not publicly distributed
|
||||
*
|
||||
* Copyright (c) 2008-2010, Tomasz Sowa
|
||||
* Copyright (c) 2008-2012, Tomasz Sowa
|
||||
* All rights reserved.
|
||||
*
|
||||
*/
|
||||
@@ -44,38 +44,52 @@ Table::iterator i = table.begin();
|
||||
|
||||
log << log3 << "SC: deleting all sessions" << logend;
|
||||
|
||||
cur->session = tmp_session;
|
||||
|
||||
// don't use table.clear();
|
||||
// because plugins session data would not be erased
|
||||
// we must set cur->session for each session and then delete it
|
||||
while( i != table.end() )
|
||||
{
|
||||
cur->session = &(*i);
|
||||
i->plugin_data.DeleteAll(); // it's better to call it here instead in the destructor
|
||||
table.erase(i++);
|
||||
}
|
||||
|
||||
// erasing indexes
|
||||
index_id.clear();
|
||||
table_size = 0;
|
||||
cur->session = tmp_session;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void SessionContainer::EraseById(IdIterator i)
|
||||
void SessionContainer::EraseById(long id)
|
||||
{
|
||||
Session * old_session = tmp_session;
|
||||
IndexId::iterator i = index_id.find(id);
|
||||
|
||||
if( cur->session != &(*i->second) )
|
||||
old_session = cur->session;
|
||||
if( i != index_id.end() )
|
||||
{
|
||||
Session * old_session = tmp_session;
|
||||
|
||||
cur->session = &(*i->second);
|
||||
if( cur->session != &(*i->second) )
|
||||
old_session = cur->session;
|
||||
|
||||
log << log4 << "SC: deleting session, id: " << i->second->id << logend;
|
||||
table.erase(i->second);
|
||||
index_id.erase(i);
|
||||
table_size -= 1;
|
||||
cur->session = &(*i->second);
|
||||
|
||||
cur->session = old_session;
|
||||
log << log4 << "SC: deleting session, id: " << i->second->id << logend;
|
||||
|
||||
// call first DeleteAll() because if not then it would be called from the destructor
|
||||
// and there'll be a problem if it throws an exception there
|
||||
i->second->plugin_data.DeleteAll();
|
||||
table.erase(i->second);
|
||||
index_id.erase(i);
|
||||
table_size -= 1;
|
||||
|
||||
cur->session = old_session;
|
||||
}
|
||||
else
|
||||
{
|
||||
log << log1 << "SC: I cannot delete a session with id: " << id
|
||||
<< " (there is no such a session)" << logend;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -118,23 +132,24 @@ SessionContainer::IdIterator SessionContainer::IdEnd()
|
||||
|
||||
|
||||
|
||||
bool SessionContainer::PushBack(const Session & session)
|
||||
SessionContainer::Iterator SessionContainer::AddSession(long id)
|
||||
{
|
||||
std::pair<IndexId::iterator, bool> index_id_res = index_id.insert( std::make_pair(session.id, table.end()) );
|
||||
std::pair<IndexId::iterator, bool> index_id_res = index_id.insert( std::make_pair(id, table.end()) );
|
||||
|
||||
if( !index_id_res.second )
|
||||
{
|
||||
// that element already exists (was not inserted now)
|
||||
return false;
|
||||
return End();
|
||||
}
|
||||
|
||||
Iterator last = table.insert(table.end(), session);
|
||||
Iterator last = table.insert(table.end(), empty_session);
|
||||
last->id = id;
|
||||
index_id_res.first->second = last;
|
||||
table_size += 1;
|
||||
|
||||
log << log3 << "SC: added session, id: " << session.id << logend;
|
||||
log << log3 << "SC: added session, id: " << id << logend;
|
||||
|
||||
return true;
|
||||
return last;
|
||||
}
|
||||
|
||||
|
||||
@@ -153,6 +168,41 @@ return i->second;
|
||||
}
|
||||
|
||||
|
||||
bool SessionContainer::ChangeSessionId(SessionContainer::Iterator ses, long new_id)
|
||||
{
|
||||
std::pair<IndexId::iterator, bool> index_id_res = index_id.insert( std::make_pair(new_id, ses) );
|
||||
|
||||
if( !index_id_res.second )
|
||||
{
|
||||
log << log1 << "SC: session with id: " << new_id << " already exists" << logend;
|
||||
return false;
|
||||
}
|
||||
|
||||
long old_id = ses->id;
|
||||
index_id.erase(old_id); // remove the old index
|
||||
ses->id = new_id;
|
||||
log << log3 << "SC: changed session id from: " << old_id << " to " << new_id << logend;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool SessionContainer::ChangeSessionId(long old_id, long new_id)
|
||||
{
|
||||
IndexId::iterator i = index_id.find(old_id);
|
||||
|
||||
if( i != index_id.end() )
|
||||
{
|
||||
return ChangeSessionId(i->second, new_id);
|
||||
}
|
||||
else
|
||||
{
|
||||
log << log2 << "SC: there is no a session with id: " << old_id << logend;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* This file is a part of Winix
|
||||
* and is not publicly distributed
|
||||
*
|
||||
* Copyright (c) 2008-2010, Tomasz Sowa
|
||||
* Copyright (c) 2008-2012, Tomasz Sowa
|
||||
* All rights reserved.
|
||||
*
|
||||
*/
|
||||
@@ -24,10 +24,6 @@ class SessionContainer
|
||||
{
|
||||
public:
|
||||
|
||||
// when deleting Sessions you should set request.session into the session object
|
||||
// this allows to delete plugins session data
|
||||
// because a session object has plugin_data object
|
||||
// and in its destructor the plugin.Call(WINIX_SESSION_REMOVE) is called
|
||||
typedef std::list<Session> Table;
|
||||
typedef Table::iterator Iterator;
|
||||
typedef std::map<long, Iterator> IndexId;
|
||||
@@ -46,13 +42,16 @@ public:
|
||||
Iterator Begin();
|
||||
Iterator End();
|
||||
Session & Back();
|
||||
bool PushBack(const Session & session);
|
||||
Iterator AddSession(long id);
|
||||
Iterator FindById(long);
|
||||
|
||||
IdIterator IdBegin();
|
||||
IdIterator IdEnd();
|
||||
|
||||
void EraseById(IdIterator i);
|
||||
void EraseById(long id);
|
||||
|
||||
bool ChangeSessionId(Iterator ses, long new_id);
|
||||
bool ChangeSessionId(long old_id, long new_id);
|
||||
|
||||
private:
|
||||
|
||||
@@ -63,6 +62,8 @@ private:
|
||||
Config * config;
|
||||
Session * tmp_session;
|
||||
|
||||
Session empty_session;
|
||||
|
||||
// in FreeBSD implementation (GCC) list::size() has linear complexity
|
||||
// so we use our own table_size with O(1)
|
||||
size_t table_size;
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* This file is a part of Winix
|
||||
* and is not publicly distributed
|
||||
*
|
||||
* Copyright (c) 2008-2010, Tomasz Sowa
|
||||
* Copyright (c) 2008-2012, Tomasz Sowa
|
||||
* All rights reserved.
|
||||
*
|
||||
*/
|
||||
@@ -57,6 +57,11 @@ void SessionManager::SetLastContainer(LastContainer * plast_container)
|
||||
}
|
||||
|
||||
|
||||
void SessionManager::InitBanList()
|
||||
{
|
||||
ban_tab.SetMaxSize(config->ban_list_soft_max_size, config->ban_list_max_size);
|
||||
}
|
||||
|
||||
|
||||
size_t SessionManager::Size()
|
||||
{
|
||||
@@ -108,18 +113,15 @@ return id;
|
||||
|
||||
void SessionManager::CreateSession()
|
||||
{
|
||||
int attempts = 100;
|
||||
bool added = false;
|
||||
|
||||
new_session.SetTimeToNow();
|
||||
new_session.Clear();
|
||||
int attempts = 100;
|
||||
SessionContainer::Iterator i = session_tab.End();
|
||||
|
||||
if( config->session_max == 0 || session_tab.Size() < config->session_max )
|
||||
{
|
||||
for( ; !added && attempts > 0 ; --attempts )
|
||||
for( ; i == session_tab.End() && attempts > 0 ; --attempts )
|
||||
{
|
||||
new_session.id = CreateSessionId();
|
||||
added = session_tab.PushBack(new_session);
|
||||
long id = CreateSessionId();
|
||||
i = session_tab.AddSession(id);
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -127,25 +129,32 @@ bool added = false;
|
||||
log << log2 << "SM: sessions limit exceeded (" << config->session_max << ")" << logend;
|
||||
}
|
||||
|
||||
if( added )
|
||||
if( i != session_tab.End() )
|
||||
{
|
||||
session = &session_tab.Back();
|
||||
session = &(*i);
|
||||
session->new_session = true;
|
||||
session->SetTimesTo(cur->request->start_time);
|
||||
|
||||
log << log2 << "SM: created a new session: " << session->id << logend;
|
||||
}
|
||||
else
|
||||
{
|
||||
// there is a problem with generating a new session id
|
||||
// we do not set a session cookie
|
||||
session = &temporary_session;
|
||||
session->SetTimeToNow();
|
||||
session->Clear(); // !! uwaga ten Clear wyczysci plugins data
|
||||
session->new_session = false; // temporary session was initialized at the beginning
|
||||
log << log1 << "SM: cannot create a session id (temporary used: with id 0)" << logend;
|
||||
SetTemporarySession();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void SessionManager::SetTemporarySession()
|
||||
{
|
||||
session = &temporary_session;
|
||||
session->Clear(false);
|
||||
session->SetTimesTo(cur->request->start_time);
|
||||
session->new_session = false; // temporary session was initialized at the beginning
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool SessionManager::SetSessionFromCookie(const std::string & cookie)
|
||||
@@ -153,17 +162,17 @@ bool SessionManager::SetSessionFromCookie(const std::string & cookie)
|
||||
long id = Tol(cookie.c_str());
|
||||
SessionContainer::Iterator s = session_tab.FindById(id);
|
||||
|
||||
if( s == session_tab.End() )
|
||||
if( s == session_tab.End() || s->remove_me )
|
||||
return false;
|
||||
|
||||
// that session is in the table
|
||||
session = &(*s);
|
||||
session->new_session = false;
|
||||
session->last_time = std::time(0);
|
||||
session->tm_last_time = Time(session->last_time);
|
||||
session->new_session = false;
|
||||
session->last_time = cur->request->start_time;
|
||||
session->last_date = cur->request->start_time;
|
||||
|
||||
if( cur->request->method == Request::get )
|
||||
session->last_time_get = session->last_time;
|
||||
session->last_time_get = cur->request->start_time;
|
||||
|
||||
log << log2 << "SM: session: " << session->id;
|
||||
|
||||
@@ -179,6 +188,24 @@ return true;
|
||||
|
||||
void SessionManager::SetSession()
|
||||
{
|
||||
current_ip_ban = ban_tab.FindIP(cur->request->ip);
|
||||
|
||||
if( current_ip_ban && current_ip_ban->IsIPBanned() )
|
||||
{
|
||||
if( current_ip_ban->expires != 0 && cur->request->start_time >= current_ip_ban->expires )
|
||||
{
|
||||
log << log2 << "SM: removing a ban from this IP and resetting events counter" << logend;
|
||||
current_ip_ban->ClearAfterRemovingBan();
|
||||
}
|
||||
else
|
||||
{
|
||||
log << log2 << "SM: this ip is bannned, using a temporary session" << logend;
|
||||
SetTemporarySession();
|
||||
session->ip_ban = current_ip_ban;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
CookieTab::iterator i = cur->request->cookie_tab.find(config->http_session_id_name);
|
||||
|
||||
if( i == cur->request->cookie_tab.end() )
|
||||
@@ -197,10 +224,23 @@ void SessionManager::SetSession()
|
||||
CreateSession();
|
||||
}
|
||||
}
|
||||
|
||||
session->ip_ban = current_ip_ban;
|
||||
}
|
||||
|
||||
|
||||
|
||||
Session * SessionManager::FindSession(long id)
|
||||
{
|
||||
SessionContainer::Iterator i = session_tab.FindById(id);
|
||||
|
||||
if( i != session_tab.End() )
|
||||
return &*i;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
SessionContainer::Iterator SessionManager::SessionBegin()
|
||||
{
|
||||
return session_tab.Begin();
|
||||
@@ -220,11 +260,57 @@ SessionContainer::Iterator SessionManager::SessionEnd()
|
||||
|
||||
void SessionManager::DeleteSessions()
|
||||
{
|
||||
SessionContainer::Iterator i;
|
||||
|
||||
for(i=session_tab.Begin() ; i!=session_tab.End() ; ++i)
|
||||
{
|
||||
if( i->puser && !i->remember_me )
|
||||
{
|
||||
plugin.Call(&(*i), WINIX_PREPARE_USER_TO_LOGOUT, i->puser);
|
||||
last_container->UserLogout(i->puser->id, i->id);
|
||||
}
|
||||
}
|
||||
|
||||
session_tab.Clear();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
don't change a session's id when a user is logged
|
||||
the session id is in last_container and the user would not be
|
||||
correctly removed from the container
|
||||
*/
|
||||
bool SessionManager::ChangeSessionId(long old_id)
|
||||
{
|
||||
int attempts = 100;
|
||||
bool changed = false;
|
||||
long new_id;
|
||||
SessionContainer::Iterator i = session_tab.FindById(old_id);
|
||||
|
||||
if( i != session_tab.End() )
|
||||
{
|
||||
for( ; !changed && attempts > 0 ; --attempts )
|
||||
{
|
||||
new_id = CreateSessionId();
|
||||
changed = session_tab.ChangeSessionId(i, new_id);
|
||||
}
|
||||
|
||||
if( changed )
|
||||
plugin.Call(&(*i), WINIX_SESSION_CHANGED_ID, old_id, new_id);
|
||||
else
|
||||
log << log1 << "SM: I cannot create a new session id (still uses old one)" << logend;
|
||||
}
|
||||
else
|
||||
{
|
||||
log << log2 << "SM: there is no a session with id: " << old_id << logend;
|
||||
}
|
||||
|
||||
return changed;
|
||||
}
|
||||
|
||||
|
||||
void SessionManager::InitTmpSession()
|
||||
{
|
||||
Session * old_session = cur->session;
|
||||
@@ -244,7 +330,7 @@ void SessionManager::UninitTmpSession()
|
||||
|
||||
log << log4 << "SM: uninitializing temporary session" << logend;
|
||||
cur->session = &temporary_session;
|
||||
cur->session->plugin_data.DeleteAll(); // this will call plugin.Call(WINIX_SESSION_REMOVE);
|
||||
cur->session->plugin_data.DeleteAll(); // this will call plugin.Call(WINIX_PLUGIN_SESSION_DATA_REMOVE);
|
||||
cur->session->plugin_data.Resize(0);
|
||||
|
||||
cur->session = old_session;
|
||||
@@ -266,8 +352,15 @@ SessionContainer::Iterator i;
|
||||
for(i=session_tab.Begin() ; i != session_tab.End() ; ++i)
|
||||
{
|
||||
i->plugin_data.Resize(plugin.Size());
|
||||
cur->session = &(*i);
|
||||
plugin.Call(WINIX_SESSION_CREATED);
|
||||
plugin.Call(&(*i), WINIX_SESSION_CREATED);
|
||||
|
||||
/*
|
||||
!! IMPROVE ME
|
||||
we do not add it to the last_container (we don't have IP address stored yet)
|
||||
*/
|
||||
|
||||
if( i->puser )
|
||||
plugin.Call(&(*i), WINIX_USER_LOGGED);
|
||||
}
|
||||
|
||||
cur->session = &temporary_session;
|
||||
@@ -297,10 +390,10 @@ void SessionManager::SaveSessions()
|
||||
|
||||
for( ; i!=session_tab.End() ; ++i )
|
||||
{
|
||||
if( i->id != 0 && i->puser )
|
||||
if( i->id != 0 && i->puser && !i->remove_me )
|
||||
{
|
||||
file << i->id << ' ' << i->puser->id << ' ' << i->remember_me << ' ';
|
||||
file << (long)i->time << ' ' << (long)i->last_time << std::endl;
|
||||
file << (long)i->start_time << ' ' << (long)i->last_time << std::endl;
|
||||
|
||||
++len;
|
||||
}
|
||||
@@ -327,32 +420,83 @@ Session * SessionManager::GetCurSession()
|
||||
}
|
||||
|
||||
|
||||
// returns how many sessions was marked to remove
|
||||
size_t SessionManager::MarkAllSessionsToRemove(long user_id)
|
||||
{
|
||||
size_t how_many = 0;
|
||||
SessionContainer::Iterator i;
|
||||
|
||||
for(i=session_tab.Begin() ; i!=session_tab.End() ; ++i)
|
||||
{
|
||||
if( i->puser && i->puser->id == user_id )
|
||||
{
|
||||
plugin.Call(&(*i), WINIX_PREPARE_USER_TO_LOGOUT, i->puser);
|
||||
last_container->UserLogout(i->puser->id, i->id);
|
||||
i->remove_me = true;
|
||||
i->puser = 0;
|
||||
how_many += 1;
|
||||
}
|
||||
}
|
||||
|
||||
return how_many;
|
||||
}
|
||||
|
||||
|
||||
IPBan & SessionManager::AddIPToBanList(int ip)
|
||||
{
|
||||
return ban_tab.AddIP(ip);
|
||||
}
|
||||
|
||||
|
||||
size_t SessionManager::BanListSize()
|
||||
{
|
||||
return ban_tab.Size();
|
||||
}
|
||||
|
||||
|
||||
IPBan & SessionManager::GetIPBan(size_t index)
|
||||
{
|
||||
return ban_tab.GetIPBan(index);
|
||||
}
|
||||
|
||||
|
||||
void SessionManager::RemoveIPBan(int ip)
|
||||
{
|
||||
ban_tab.RemoveIP(ip);
|
||||
}
|
||||
|
||||
|
||||
void SessionManager::ClearIPBanList()
|
||||
{
|
||||
ban_tab.Clear();
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
*
|
||||
*
|
||||
* sessions gc (second thread)
|
||||
*
|
||||
* sessions are only removed here
|
||||
* SessionContainer::IndexId can be removed from the other thread
|
||||
* (when ChangeSessionId() method is called)
|
||||
*
|
||||
*/
|
||||
void SessionManager::Work()
|
||||
{
|
||||
bool exit = false;
|
||||
SessionContainer::IndexId::iterator i;
|
||||
SessionContainer::Iterator i;
|
||||
|
||||
deleted = 0;
|
||||
|
||||
Lock();
|
||||
i = session_tab.IdBegin();
|
||||
i = session_tab.Begin();
|
||||
Unlock();
|
||||
|
||||
while( !exit )
|
||||
{
|
||||
Lock();
|
||||
|
||||
CheckWheterIPListIsSorted();
|
||||
CheckSession(i);
|
||||
exit = synchro->was_stop_signal;
|
||||
|
||||
@@ -361,12 +505,23 @@ SessionContainer::IndexId::iterator i;
|
||||
}
|
||||
|
||||
|
||||
// objects locked
|
||||
void SessionManager::CheckWheterIPListIsSorted()
|
||||
{
|
||||
if( !ban_tab.IsSorted() )
|
||||
{
|
||||
log << log4 << "SM: sorting the ban list" << logend;
|
||||
ban_tab.Sort();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// it's called from the other thread (with Lock and Unlock)
|
||||
void SessionManager::CheckSession(SessionContainer::IndexId::iterator & i)
|
||||
void SessionManager::CheckSession(SessionContainer::Iterator & i)
|
||||
{
|
||||
const int deleted_max_at_once = 10;
|
||||
|
||||
if( i == session_tab.IdEnd() )
|
||||
if( i == session_tab.End() )
|
||||
{
|
||||
if( deleted > 0 )
|
||||
{
|
||||
@@ -374,14 +529,16 @@ const int deleted_max_at_once = 10;
|
||||
log << logsave;
|
||||
}
|
||||
|
||||
i = session_tab.IdBegin();
|
||||
i = session_tab.Begin();
|
||||
WaitForSignalSleep(10);
|
||||
}
|
||||
else
|
||||
{
|
||||
if( IsSessionOutdated(*i->second) )
|
||||
if( i->remove_me || IsSessionOutdated(*i) )
|
||||
{
|
||||
DeleteSession(i++);
|
||||
Session * ses = &(*i);
|
||||
++i;
|
||||
DeleteSession(ses);
|
||||
++deleted;
|
||||
}
|
||||
else
|
||||
@@ -405,9 +562,13 @@ bool SessionManager::IsSessionOutdated(const Session & s) const
|
||||
bool outdated;
|
||||
|
||||
if( s.remember_me )
|
||||
{
|
||||
outdated = s.last_time < std::time(0) - config->session_remember_max_idle;
|
||||
}
|
||||
else
|
||||
{
|
||||
outdated = s.last_time < std::time(0) - config->session_max_idle;
|
||||
}
|
||||
|
||||
return outdated;
|
||||
}
|
||||
@@ -415,14 +576,20 @@ return outdated;
|
||||
|
||||
|
||||
// it's called from the other thread (with Lock and Unlock)
|
||||
void SessionManager::DeleteSession(SessionContainer::IdIterator i)
|
||||
void SessionManager::DeleteSession(Session * del_session)
|
||||
{
|
||||
Session * del_session = &(*i->second);
|
||||
|
||||
if( del_session->puser )
|
||||
{
|
||||
plugin.Call(del_session, WINIX_PREPARE_USER_TO_LOGOUT, del_session->puser);
|
||||
last_container->UserLogout(del_session->puser->id, del_session->id);
|
||||
del_session->puser = 0;
|
||||
}
|
||||
|
||||
session_tab.EraseById(i);
|
||||
long id = del_session->id;
|
||||
|
||||
plugin.Call(del_session, WINIX_PREPARE_SESSION_TO_REMOVE);
|
||||
session_tab.EraseById(del_session->id);
|
||||
plugin.Call((Session*)0, WINIX_SESSION_REMOVED, id);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* This file is a part of Winix
|
||||
* and is not publicly distributed
|
||||
*
|
||||
* Copyright (c) 2008-2010, Tomasz Sowa
|
||||
* Copyright (c) 2008-2012, Tomasz Sowa
|
||||
* All rights reserved.
|
||||
*
|
||||
*/
|
||||
@@ -14,6 +14,7 @@
|
||||
#include <ctime>
|
||||
|
||||
#include "sessioncontainer.h"
|
||||
#include "ipbancontainer.h"
|
||||
#include "config.h"
|
||||
#include "request.h"
|
||||
#include "lastcontainer.h"
|
||||
@@ -34,9 +35,15 @@ public:
|
||||
void SetSystem(System * psystem);
|
||||
void SetLastContainer(LastContainer * plast_container);
|
||||
|
||||
|
||||
// can return a null pointer
|
||||
Session * FindSession(long id);
|
||||
|
||||
void SetSession();
|
||||
void DeleteSessions(); // deleting all sessions
|
||||
bool ChangeSessionId(long old_id);
|
||||
|
||||
void InitBanList();
|
||||
void InitTmpSession();
|
||||
void UninitTmpSession();
|
||||
|
||||
@@ -50,6 +57,13 @@ public:
|
||||
SessionContainer::Iterator SessionEnd();
|
||||
|
||||
size_t Size();
|
||||
size_t MarkAllSessionsToRemove(long user_id);
|
||||
|
||||
IPBan & AddIPToBanList(int ip);
|
||||
size_t BanListSize();
|
||||
IPBan & GetIPBan(size_t index);
|
||||
void RemoveIPBan(int ip);
|
||||
void ClearIPBanList();
|
||||
|
||||
private:
|
||||
|
||||
@@ -63,26 +77,27 @@ private:
|
||||
Session * session;
|
||||
|
||||
SessionContainer session_tab;
|
||||
IPBanContainer ban_tab;
|
||||
|
||||
IPBan * current_ip_ban;
|
||||
|
||||
// session with id 0
|
||||
Session temporary_session;
|
||||
|
||||
// for adding a new session to the container
|
||||
Session new_session;
|
||||
|
||||
bool IsSession(long s);
|
||||
|
||||
long CreateSessionId();
|
||||
void CreateSession();
|
||||
bool SetSessionFromCookie(const std::string & cookie);
|
||||
|
||||
void SetTemporarySession();
|
||||
|
||||
// second thread
|
||||
int deleted;
|
||||
virtual void Work();
|
||||
void CheckSession(SessionContainer::IndexId::iterator & i);
|
||||
void CheckSession(SessionContainer::Iterator & i);
|
||||
bool IsSessionOutdated(const Session & s) const;
|
||||
void DeleteSession(SessionContainer::IdIterator i);
|
||||
void DeleteSession(Session * del_session);
|
||||
void CheckWheterIPListIsSorted();
|
||||
|
||||
};
|
||||
|
||||
|
||||
@@ -51,33 +51,19 @@ bool SessionParser::Parse(SessionContainer & container)
|
||||
file format, each rows:
|
||||
session_id(long) user_id(long) remember_me(0|1) time(long) last_time(long)
|
||||
*/
|
||||
|
||||
long user_id;
|
||||
|
||||
session.Clear();
|
||||
last = file.get();
|
||||
|
||||
log << log2 << "SP: reading sessions from the session file" << logend;
|
||||
|
||||
while( true )
|
||||
{
|
||||
session.id = ReadLong();
|
||||
long id = ReadLong();
|
||||
|
||||
if( file.eof() )
|
||||
break;
|
||||
|
||||
user_id = ReadLong();
|
||||
session.remember_me = ReadLong();
|
||||
session.time = ReadLong();
|
||||
session.last_time = ReadLong();
|
||||
|
||||
if( MakeSession(user_id) )
|
||||
{
|
||||
users->IncrementLoggedUsers();
|
||||
container.PushBack(session);
|
||||
log << log2 << "SP: read session id: " << session.id << " for user: " << session.puser->name << logend;
|
||||
}
|
||||
|
||||
long user_id = ReadLong();
|
||||
MakeSession(id, user_id, container);
|
||||
SkipLine();
|
||||
}
|
||||
|
||||
@@ -87,22 +73,38 @@ return true;
|
||||
}
|
||||
|
||||
|
||||
bool SessionParser::MakeSession(long user_id)
|
||||
void SessionParser::MakeSession(long id, long user_id, SessionContainer & container)
|
||||
{
|
||||
User * puser = users->GetUser(user_id);
|
||||
|
||||
if( !puser )
|
||||
{
|
||||
log << log1 << "SP: there is no a user with id: " << user_id << " (skipped)" << logend;
|
||||
return false;
|
||||
return;
|
||||
}
|
||||
|
||||
session.puser = puser;
|
||||
session.new_session = true;
|
||||
session.tm_time = Time(session.time);
|
||||
session.tm_last_time = Time(session.last_time);
|
||||
SessionContainer::Iterator i = container.AddSession(id);
|
||||
|
||||
return true;
|
||||
if( i != container.End() )
|
||||
{
|
||||
i->Clear();
|
||||
i->id = id;
|
||||
i->puser = puser;
|
||||
i->new_session = true;
|
||||
i->remember_me = ReadLong();
|
||||
i->start_time = ReadLong();
|
||||
i->last_time = ReadLong();
|
||||
i->start_date = i->start_time;
|
||||
i->last_date = i->last_time;
|
||||
// !! IMPROVE ME we do not save last_time_get
|
||||
|
||||
users->IncrementLoggedUsers();
|
||||
log << log2 << "SP: read session id: " << id << " for user: " << puser->name << logend;
|
||||
}
|
||||
else
|
||||
{
|
||||
log << log1 << "SP: session with id: " << id << " already exists (skipping)" << logend;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -31,7 +31,7 @@ private:
|
||||
Users * users;
|
||||
|
||||
bool Parse(SessionContainer & container);
|
||||
bool MakeSession(long user_id);
|
||||
void MakeSession(long id, long user_id, SessionContainer & container);
|
||||
|
||||
bool IsWhite(int c);
|
||||
bool IsDigit(int c);
|
||||
@@ -42,7 +42,6 @@ private:
|
||||
|
||||
std::ifstream file;
|
||||
int last; // last character
|
||||
Session session;
|
||||
|
||||
};
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* This file is a part of Winix
|
||||
* and is not publicly distributed
|
||||
*
|
||||
* Copyright (c) 2011, Tomasz Sowa
|
||||
* Copyright (c) 2011-2012, Tomasz Sowa
|
||||
* All rights reserved.
|
||||
*
|
||||
*/
|
||||
@@ -114,6 +114,13 @@ SLog & SLog::operator<<(double s)
|
||||
}
|
||||
|
||||
|
||||
SLog & SLog::operator<<(const PT::Date & date)
|
||||
{
|
||||
return PutLog(date);
|
||||
}
|
||||
|
||||
|
||||
|
||||
SLog & SLog::operator<<(LogManipulators m)
|
||||
{
|
||||
if( cur && cur->session )
|
||||
@@ -166,6 +173,7 @@ SLog & SLog::TranslateText(const wchar_t * str)
|
||||
if( locale )
|
||||
trans = &locale->Get(str);
|
||||
|
||||
// !! IMPROVE ME "Not translated" add to locale
|
||||
if( !trans || trans->empty() )
|
||||
cur->session->log_buffer << "Not translated: " << str;
|
||||
else
|
||||
|
||||
25
core/slog.h
25
core/slog.h
@@ -2,7 +2,7 @@
|
||||
* This file is a part of Winix
|
||||
* and is not publicly distributed
|
||||
*
|
||||
* Copyright (c) 2011, Tomasz Sowa
|
||||
* Copyright (c) 2011-2012, Tomasz Sowa
|
||||
* All rights reserved.
|
||||
*
|
||||
*/
|
||||
@@ -13,6 +13,7 @@
|
||||
#include "cur.h"
|
||||
#include "logmanipulators.h"
|
||||
#include "templates/locale.h"
|
||||
#include "textstream/textstream.h"
|
||||
|
||||
|
||||
#define WINIX_SLOG_MAX_LOG_SIZE 10240
|
||||
@@ -68,10 +69,21 @@ public:
|
||||
SLog & operator<<(size_t s);
|
||||
SLog & operator<<(double s);
|
||||
SLog & operator<<(LogManipulators m);
|
||||
SLog & operator<<(const PT::Date & date);
|
||||
|
||||
template<typename char_type, size_t stack_size, size_t heap_block_size>
|
||||
SLog & operator<<(const PT::TextStreamBase<char_type, stack_size, heap_block_size> & buf);
|
||||
|
||||
|
||||
SLog & TranslateText(const char * str);
|
||||
SLog & TranslateText(const wchar_t * str);
|
||||
|
||||
template<size_t str_size>
|
||||
SLog & operator<<(const TranslateTextHelper<const char [str_size]> & raw) { return TranslateText(raw.par); }
|
||||
|
||||
template<size_t str_size>
|
||||
SLog & operator<<(const TranslateTextHelper<const wchar_t [str_size]> & raw){ return TranslateText(raw.par); }
|
||||
|
||||
template<size_t str_size>
|
||||
SLog & operator<<(const TranslateTextHelper<char [str_size]> & raw) { return TranslateText(raw.par); }
|
||||
|
||||
@@ -89,7 +101,7 @@ public:
|
||||
private:
|
||||
|
||||
template<class LogParam>
|
||||
SLog & PutLog(LogParam par);
|
||||
SLog & PutLog(const LogParam & par);
|
||||
|
||||
Cur * cur;
|
||||
Locale * locale;
|
||||
@@ -105,8 +117,15 @@ SLog::TranslateTextHelper<RawType> T(const RawType & par)
|
||||
}
|
||||
|
||||
|
||||
template<typename char_type, size_t stack_size, size_t heap_block_size>
|
||||
SLog & SLog::operator<<(const PT::TextStreamBase<char_type, stack_size, heap_block_size> & buf)
|
||||
{
|
||||
return PutLog(buf);
|
||||
}
|
||||
|
||||
|
||||
template<class LogParam>
|
||||
SLog & SLog::PutLog(LogParam par)
|
||||
SLog & SLog::PutLog(const LogParam & par)
|
||||
{
|
||||
if( cur && cur->session )
|
||||
cur->session->log_buffer << par;
|
||||
|
||||
@@ -2,31 +2,53 @@
|
||||
* This file is a part of Winix
|
||||
* and is not publicly distributed
|
||||
*
|
||||
* Copyright (c) 2010, Tomasz Sowa
|
||||
* Copyright (c) 2010-2012, Tomasz Sowa
|
||||
* All rights reserved.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "synchro.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include "synchro.h"
|
||||
|
||||
|
||||
Synchro::Synchro() : mutex(PTHREAD_MUTEX_INITIALIZER)
|
||||
{
|
||||
was_stop_signal = false;
|
||||
ref = 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool Synchro::Lock()
|
||||
{
|
||||
return pthread_mutex_lock(&mutex) == 0;
|
||||
int res = pthread_mutex_lock(&mutex);
|
||||
|
||||
if( res == EDEADLK )
|
||||
{
|
||||
// Lock() method in this thread was called before
|
||||
ref += 1;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
ref = 0;
|
||||
}
|
||||
|
||||
return res == 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void Synchro::Unlock()
|
||||
{
|
||||
pthread_mutex_unlock(&mutex);
|
||||
if( ref > 0 )
|
||||
{
|
||||
ref -= 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
pthread_mutex_unlock(&mutex);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* This file is a part of Winix
|
||||
* and is not publicly distributed
|
||||
*
|
||||
* Copyright (c) 2010, Tomasz Sowa
|
||||
* Copyright (c) 2010-2012, Tomasz Sowa
|
||||
* All rights reserved.
|
||||
*
|
||||
*/
|
||||
@@ -28,6 +28,13 @@ struct Synchro
|
||||
|
||||
bool Lock();
|
||||
void Unlock();
|
||||
|
||||
private:
|
||||
|
||||
// deadlock counter
|
||||
// we can call Lock() more than one in the same thread
|
||||
int ref;
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
484
core/system.cpp
484
core/system.cpp
@@ -2,7 +2,7 @@
|
||||
* This file is a part of Winix
|
||||
* and is not publicly distributed
|
||||
*
|
||||
* Copyright (c) 2010-2011, Tomasz Sowa
|
||||
* Copyright (c) 2010-2012, Tomasz Sowa
|
||||
* All rights reserved.
|
||||
*
|
||||
*/
|
||||
@@ -11,7 +11,8 @@
|
||||
#include "misc.h"
|
||||
#include "error.h"
|
||||
#include "templates/templates.h"
|
||||
#include "functions/functionbase.h"
|
||||
#include "functions/functions.h"
|
||||
#include "plugin.h"
|
||||
|
||||
|
||||
|
||||
@@ -39,10 +40,45 @@ void System::SetSynchro(Synchro * psynchro)
|
||||
}
|
||||
|
||||
|
||||
void System::SetFunctions(Functions * pfunctions)
|
||||
{
|
||||
functions = pfunctions;
|
||||
}
|
||||
|
||||
void System::SetSessionManager(SessionManager * sm)
|
||||
{
|
||||
session_manager = sm;
|
||||
}
|
||||
|
||||
|
||||
void System::ReadTimeZones()
|
||||
{
|
||||
if( config->etc_dir.empty() )
|
||||
{
|
||||
log << log1 << "System: I cannot read time zones, set etc_dir directory in the config" << logend;
|
||||
return;
|
||||
}
|
||||
|
||||
if( config->time_zones_file.empty() )
|
||||
{
|
||||
log << log1 << "System:: I cannot read time zones, set time_zones_file in the config" << logend;
|
||||
return;
|
||||
}
|
||||
|
||||
name_temp = config->etc_dir;
|
||||
name_temp += '/';
|
||||
name_temp += config->time_zones_file;
|
||||
|
||||
time_zones.SetTimeZoneMaxId(config->time_zone_max_id);
|
||||
time_zones.ReadTimeZones(name_temp);
|
||||
}
|
||||
|
||||
|
||||
void System::Init()
|
||||
{
|
||||
thread_manager.SetSynchro(synchro);
|
||||
thread_manager.Init();
|
||||
|
||||
dirs.SetDb(db);
|
||||
dirs.SetCur(cur);
|
||||
dirs.SetNotify(¬ify);
|
||||
@@ -56,34 +92,75 @@ void System::Init()
|
||||
mounts.ReadMounts();
|
||||
|
||||
users.SetCur(cur);
|
||||
users.SetSessionManager(session_manager);
|
||||
users.ReadUsers(db);
|
||||
users.SetTimeZoneOffset(config->time_zone_offset);
|
||||
groups.ReadGroups(db); // !! chwilowe przekazanie argumentu, db bedzie zmienione
|
||||
|
||||
rebus.SetCur(cur);
|
||||
rebus.Init();
|
||||
|
||||
notify.SetSynchro(synchro);
|
||||
notify.SetCur(cur);
|
||||
notify.SetConfig(config);
|
||||
notify.SetUsers(&users);
|
||||
notify.SetDirs(&dirs);
|
||||
notify.SetThreadManager(&thread_manager);
|
||||
notify.Init();
|
||||
|
||||
thumb.SetSynchro(synchro);
|
||||
thumb.SetDb(db);
|
||||
thumb.SetConfig(config);
|
||||
thumb.SetSystem(this);
|
||||
image.SetDb(db);
|
||||
image.SetConfig(config);
|
||||
image.SetSystem(this);
|
||||
thread_manager.Add(&image, L"image");
|
||||
|
||||
crypt.SetConfig(config);
|
||||
|
||||
// SetSynchro will be called by ThreadManager itself
|
||||
// job.ReadFromFile();
|
||||
thread_manager.Add(&job, L"job");
|
||||
|
||||
ReadTimeZones();
|
||||
}
|
||||
|
||||
|
||||
void System::PutUrlProto(bool can_use_ssl, std::wstring & str, bool clear_str)
|
||||
{
|
||||
bool ssl = false;
|
||||
|
||||
if( clear_str )
|
||||
str.clear();
|
||||
|
||||
if( can_use_ssl )
|
||||
{
|
||||
if( !config->use_ssl_only_for_logged_users ||
|
||||
cur->session->puser ||
|
||||
(cur->request->function && cur->request->function->need_ssl) )
|
||||
{
|
||||
str += config->url_ssl_proto;
|
||||
ssl = true;
|
||||
}
|
||||
}
|
||||
|
||||
if( !ssl )
|
||||
str += config->url_proto;
|
||||
}
|
||||
|
||||
|
||||
// !! IMPROVE ME
|
||||
// !! mozna zrobic jakas obsluge kiedy nie mozemy sie redirectnac, np gdy wystapil blad
|
||||
// !! moze zwracac jakas wartosc?
|
||||
/*
|
||||
postfix will not be UrlEncoded
|
||||
*/
|
||||
void System::RedirectTo(const Item & item, const wchar_t * postfix)
|
||||
{
|
||||
cur->request->redirect_to = config->base_url;
|
||||
PutUrlProto(config->use_ssl, cur->request->redirect_to);
|
||||
|
||||
if( !cur->request->subdomain.empty() )
|
||||
{
|
||||
cur->request->redirect_to += cur->request->subdomain;
|
||||
cur->request->redirect_to += '.';
|
||||
}
|
||||
|
||||
cur->request->redirect_to += config->base_url;
|
||||
|
||||
if( item.type == Item::dir )
|
||||
{
|
||||
@@ -103,9 +180,20 @@ void System::RedirectTo(const Item & item, const wchar_t * postfix)
|
||||
|
||||
|
||||
|
||||
/*
|
||||
postfix will not be UrlEncoded
|
||||
*/
|
||||
void System::RedirectTo(long item_id, const wchar_t * postfix)
|
||||
{
|
||||
cur->request->redirect_to = config->base_url;
|
||||
PutUrlProto(config->use_ssl, cur->request->redirect_to);
|
||||
|
||||
if( !cur->request->subdomain.empty() )
|
||||
{
|
||||
cur->request->redirect_to += cur->request->subdomain;
|
||||
cur->request->redirect_to += '.';
|
||||
}
|
||||
|
||||
cur->request->redirect_to += config->base_url;
|
||||
Item * pdir = dirs.GetDir(item_id);
|
||||
|
||||
if( pdir )
|
||||
@@ -139,11 +227,23 @@ void System::RedirectTo(long item_id, const wchar_t * postfix)
|
||||
}
|
||||
|
||||
|
||||
void System::RedirectTo(const std::wstring & url)
|
||||
{
|
||||
cur->request->redirect_to = config->base_url;
|
||||
|
||||
if( !url.empty() && url[0] == '/' )
|
||||
/*
|
||||
url will not be UrlEncoded
|
||||
*/
|
||||
void System::RedirectTo(const wchar_t * url)
|
||||
{
|
||||
PutUrlProto(config->use_ssl, cur->request->redirect_to);
|
||||
|
||||
if( !cur->request->subdomain.empty() )
|
||||
{
|
||||
cur->request->redirect_to += cur->request->subdomain;
|
||||
cur->request->redirect_to += '.';
|
||||
}
|
||||
|
||||
cur->request->redirect_to += config->base_url;
|
||||
|
||||
if( url[0] == '/' )
|
||||
{
|
||||
// absolute path
|
||||
cur->request->redirect_to += url;
|
||||
@@ -165,6 +265,19 @@ void System::RedirectTo(const std::wstring & url)
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
url will not be UrlEncoded
|
||||
*/
|
||||
void System::RedirectTo(const std::wstring & url)
|
||||
{
|
||||
RedirectTo(url.c_str());
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
params will be UrlEncoded
|
||||
*/
|
||||
void System::AddParams(const ParamTab & param_tab, std::wstring & str, bool clear_str)
|
||||
{
|
||||
if( clear_str )
|
||||
@@ -173,19 +286,22 @@ void System::AddParams(const ParamTab & param_tab, std::wstring & str, bool clea
|
||||
for(size_t i=0 ; i<param_tab.size() ; ++i)
|
||||
{
|
||||
str += '/';
|
||||
str += param_tab[i].name;
|
||||
UrlEncode(param_tab[i].name, str, false);
|
||||
|
||||
if( !param_tab[i].value.empty() )
|
||||
{
|
||||
str += ':';
|
||||
str += param_tab[i].value;
|
||||
UrlEncode(param_tab[i].value, str, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void System::RedirectWithFunctionAndParamsTo(const std::wstring & url)
|
||||
/*
|
||||
url will not be UrlEncoded
|
||||
params will be UrlEncoded
|
||||
*/
|
||||
void System::RedirectWithFunctionAndParamsTo(const wchar_t * url)
|
||||
{
|
||||
RedirectTo(url);
|
||||
|
||||
@@ -193,26 +309,55 @@ void System::RedirectWithFunctionAndParamsTo(const std::wstring & url)
|
||||
return;
|
||||
|
||||
cur->request->redirect_to += '/';
|
||||
cur->request->redirect_to += cur->request->function->fun.url;
|
||||
|
||||
cur->request->redirect_to += cur->request->function->fun.url;
|
||||
AddParams(cur->request->param_tab, cur->request->redirect_to, false);
|
||||
}
|
||||
|
||||
|
||||
void System::RedirectToLastDir()
|
||||
/*
|
||||
url will not be UrlEncoded
|
||||
params will be UrlEncoded
|
||||
*/
|
||||
void System::RedirectWithFunctionAndParamsTo(const std::wstring & url)
|
||||
{
|
||||
RedirectWithFunctionAndParamsTo(url.c_str());
|
||||
}
|
||||
|
||||
|
||||
void System::RedirectToLastDir(const wchar_t * postfix)
|
||||
{
|
||||
if( !cur->request->dir_tab.empty() )
|
||||
RedirectTo( *cur->request->dir_tab.back() );
|
||||
RedirectTo( *cur->request->dir_tab.back(), postfix );
|
||||
}
|
||||
|
||||
|
||||
void System::RedirectToLastItem()
|
||||
void System::RedirectToLastItem(const wchar_t * postfix)
|
||||
{
|
||||
if( cur->request->last_item )
|
||||
RedirectTo( *cur->request->last_item );
|
||||
RedirectTo( *cur->request->last_item, postfix );
|
||||
}
|
||||
|
||||
|
||||
void System::RedirectToLastFunction(const wchar_t * postfix)
|
||||
{
|
||||
RedirectToLastDir();
|
||||
|
||||
if( cur->request->is_item )
|
||||
{
|
||||
cur->request->redirect_to += cur->request->item.url;
|
||||
cur->request->redirect_to += '/';
|
||||
}
|
||||
|
||||
if( cur->request->function )
|
||||
cur->request->redirect_to += cur->request->function->fun.url;
|
||||
|
||||
if( postfix )
|
||||
{
|
||||
cur->request->redirect_to += '/';
|
||||
cur->request->redirect_to += postfix;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool System::CanChangeUser(const Item & item, long new_user_id)
|
||||
{
|
||||
@@ -224,12 +369,12 @@ bool System::CanChangeUser(const Item & item, long new_user_id)
|
||||
// super user is allowed everything
|
||||
return true;
|
||||
|
||||
// !! przeciez to prosciej mozna zapisac
|
||||
// albo dac od razu return false
|
||||
if( item.user_id != new_user_id )
|
||||
if( item.user_id == -1 || new_user_id == -1 || item.user_id != new_user_id )
|
||||
// only super user can change the owner of an item
|
||||
return false;
|
||||
|
||||
// item.user_id is equal new_user_id -- we return true
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -249,10 +394,10 @@ bool System::CanChangeGroup(const Item & item, long new_group_id)
|
||||
// user is allowed to change the group only if he is an owner of the item
|
||||
// he can change only into a group in which he is a member of, or into a 'no_group'
|
||||
|
||||
if( !cur->session->puser )
|
||||
if( !cur->session->puser || cur->session->puser->id == -1 )
|
||||
return false;
|
||||
|
||||
if( cur->session->puser->id != item.user_id )
|
||||
if( item.user_id == -1 || cur->session->puser->id != item.user_id )
|
||||
return false;
|
||||
|
||||
if( new_group_id == -1 )
|
||||
@@ -280,12 +425,12 @@ bool System::CanChangePrivileges(const Item & item, int new_priv)
|
||||
|
||||
if( item.privileges != new_priv )
|
||||
{
|
||||
// the owner of an item is allowed to change the privileges
|
||||
|
||||
if( !cur->session->puser )
|
||||
// the owner of an item is allowed to change the privileges
|
||||
|
||||
if( !cur->session->puser || cur->session->puser->id == -1 )
|
||||
return false;
|
||||
|
||||
if( cur->session->puser->id != item.user_id )
|
||||
|
||||
if( item.user_id == -1 || cur->session->puser->id != item.user_id )
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -293,7 +438,7 @@ return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// private
|
||||
bool System::HasAccess(const Item & item, int mask)
|
||||
{
|
||||
if( !cur->session )
|
||||
@@ -304,20 +449,26 @@ bool System::HasAccess(const Item & item, int mask)
|
||||
// super user is allowed everything
|
||||
return true;
|
||||
|
||||
if( cur->session->puser && cur->session->puser->id == item.user_id )
|
||||
if( cur->session->puser && item.user_id != -1 && cur->session->puser->id == item.user_id )
|
||||
{
|
||||
// the owner
|
||||
return ((item.privileges >> 9) & mask) == mask;
|
||||
}
|
||||
|
||||
if( cur->session->puser && item.group_id != -1 && cur->session->puser->IsMemberOf(item.group_id) )
|
||||
{
|
||||
// group
|
||||
return ((item.privileges >> 6) & mask) == mask;
|
||||
}
|
||||
|
||||
if( cur->session->puser && cur->session->puser->IsMemberOf(item.group_id) )
|
||||
if( cur->session->puser )
|
||||
{
|
||||
// group
|
||||
// others -- others logged people
|
||||
return ((item.privileges >> 3) & mask) == mask;
|
||||
}
|
||||
|
||||
// others
|
||||
|
||||
|
||||
// guests -- not logged people
|
||||
|
||||
return (item.privileges & mask) == mask;
|
||||
}
|
||||
|
||||
@@ -345,8 +496,8 @@ bool System::HasReadExecAccess(const Item & item)
|
||||
if( cur->session && cur->session->puser && cur->session->puser->super_user )
|
||||
{
|
||||
// there must be at least one 'x' (for the root)
|
||||
|
||||
return (item.privileges & 0111) != 0;
|
||||
// !! CHECK ME: is it applicable to directories too?
|
||||
return (item.privileges & 01111) != 0;
|
||||
}
|
||||
|
||||
return HasAccess(item, 5); // r+x
|
||||
@@ -395,6 +546,7 @@ bool System::DirsHaveReadExecPerm()
|
||||
|
||||
|
||||
// if we don't have access we only remove the item from the table
|
||||
// !! moze zamienic nazwe na CheckReadAccessToItems ?
|
||||
void System::CheckAccessToItems(std::vector<Item> & item_tab)
|
||||
{
|
||||
size_t i = 0;
|
||||
@@ -413,6 +565,93 @@ size_t i = 0;
|
||||
}
|
||||
|
||||
|
||||
void System::CheckWriteAccessToItems(std::vector<Item> & item_tab)
|
||||
{
|
||||
size_t i = 0;
|
||||
|
||||
while( i < item_tab.size() )
|
||||
{
|
||||
if( !HasWriteAccess(item_tab[i]) )
|
||||
{
|
||||
item_tab.erase(item_tab.begin() + i);
|
||||
}
|
||||
else
|
||||
{
|
||||
i += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int System::NewPrivileges(int creation_mask)
|
||||
{
|
||||
if( cur && cur->session && cur->session->puser )
|
||||
{
|
||||
int umask = cur->session->puser->env.Int(L"umask", config->umask);
|
||||
return (~umask) & creation_mask;
|
||||
}
|
||||
else
|
||||
{
|
||||
return (~config->umask) & creation_mask;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
from man sticky:
|
||||
A directory whose `sticky bit' is set becomes an append-only directory,
|
||||
or, more accurately, a directory in which the deletion of files is
|
||||
restricted. A file in a sticky directory may only be removed or renamed
|
||||
by a user if the user has write permission for the directory and the user
|
||||
is the owner of the file, the owner of the directory, or the super-user.
|
||||
This feature is usefully applied to directories such as /tmp which must
|
||||
be publicly writable but should deny users the license to arbitrarily
|
||||
delete or rename each others' files.
|
||||
*/
|
||||
bool System::CanRemoveRenameChild(const Item & dir, long child_item_user_id)
|
||||
{
|
||||
if( dir.type != Item::dir )
|
||||
return false;
|
||||
|
||||
if( !HasWriteAccess(dir) )
|
||||
return false;
|
||||
|
||||
if( (dir.privileges & 010000) == 0 )
|
||||
// there is no a sticky bit set to this directory
|
||||
return true;
|
||||
|
||||
if( cur->session->puser )
|
||||
{
|
||||
if( cur->session->puser->super_user )
|
||||
return true;
|
||||
|
||||
if( dir.user_id != -1 && cur->session->puser->id != -1 && child_item_user_id != -1 )
|
||||
{
|
||||
if( cur->session->puser->id == child_item_user_id ||
|
||||
cur->session->puser->id == dir.user_id )
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
int System::NewFilePrivileges()
|
||||
{
|
||||
return NewPrivileges(06666);
|
||||
}
|
||||
|
||||
|
||||
int System::NewDirPrivileges()
|
||||
{
|
||||
return NewPrivileges(07777);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
bool System::CanUseHtml(long user_id)
|
||||
{
|
||||
@@ -618,7 +857,7 @@ return res;
|
||||
|
||||
|
||||
|
||||
Error System::AddFile(Item & item, int notify_code)
|
||||
Error System::AddFile(Item & item, int notify_code, bool call_plugins)
|
||||
{
|
||||
if( item.type != Item::file )
|
||||
return WINIX_ERR_FILE_EXPECTED;
|
||||
@@ -632,6 +871,9 @@ Error System::AddFile(Item & item, int notify_code)
|
||||
|
||||
if( notify_code )
|
||||
notify.ItemChanged(notify_code, item);
|
||||
|
||||
if( call_plugins )
|
||||
plugin.Call(WINIX_FILE_ADDED, &item);
|
||||
}
|
||||
|
||||
return status;
|
||||
@@ -640,7 +882,7 @@ return status;
|
||||
|
||||
|
||||
|
||||
Error System::EditFile(Item & item, bool with_url, int notify_code)
|
||||
Error System::EditFile(Item & item, bool with_url, int notify_code, bool call_plugins)
|
||||
{
|
||||
if( item.type != Item::file )
|
||||
return WINIX_ERR_FILE_EXPECTED;
|
||||
@@ -661,6 +903,9 @@ Error System::EditFile(Item & item, bool with_url, int notify_code)
|
||||
|
||||
if( notify_code )
|
||||
notify.ItemChanged(notify_code, item);
|
||||
|
||||
if( call_plugins )
|
||||
plugin.Call(WINIX_FILE_CHANGED, &item);
|
||||
}
|
||||
|
||||
|
||||
@@ -668,39 +913,85 @@ return status;
|
||||
}
|
||||
|
||||
|
||||
time_t System::LocalTime(time_t gmt_time)
|
||||
|
||||
time_t System::ToLocal(time_t utc_time)
|
||||
{
|
||||
int time_offset;
|
||||
size_t tz_id;
|
||||
|
||||
if( cur->session && cur->session->puser )
|
||||
time_offset = cur->session->puser->time_zone_offset;
|
||||
tz_id = cur->session->puser->time_zone_id;
|
||||
else
|
||||
time_offset = config->time_zone_offset_guest;
|
||||
tz_id = config->time_zone_default_id;
|
||||
|
||||
return gmt_time + (time_t)time_offset;
|
||||
TimeZone * tz = time_zones.GetZone(tz_id);
|
||||
|
||||
if( tz )
|
||||
return tz->ToLocal(utc_time);
|
||||
|
||||
return utc_time;
|
||||
}
|
||||
|
||||
|
||||
tm System::LocalTime(const tm * ptm)
|
||||
|
||||
PT::Date System::ToLocal(const PT::Date & utc_date)
|
||||
{
|
||||
time_t t;
|
||||
tm rtm;
|
||||
size_t tz_id;
|
||||
|
||||
t = Time(ptm);
|
||||
t = LocalTime(t);
|
||||
rtm = Time(t);
|
||||
if( cur->session && cur->session->puser )
|
||||
tz_id = cur->session->puser->time_zone_id;
|
||||
else
|
||||
tz_id = config->time_zone_default_id;
|
||||
|
||||
return rtm;
|
||||
TimeZone * tz = time_zones.GetZone(tz_id);
|
||||
|
||||
if( tz )
|
||||
return tz->ToLocal(utc_date);
|
||||
|
||||
return utc_date;
|
||||
}
|
||||
|
||||
|
||||
tm System::LocalTime(const tm & ptm)
|
||||
|
||||
|
||||
time_t System::ToUTC(time_t local_time)
|
||||
{
|
||||
return LocalTime(&ptm);
|
||||
size_t tz_id;
|
||||
|
||||
if( cur->session && cur->session->puser )
|
||||
tz_id = cur->session->puser->time_zone_id;
|
||||
else
|
||||
tz_id = config->time_zone_default_id;
|
||||
|
||||
TimeZone * tz = time_zones.GetZone(tz_id);
|
||||
|
||||
if( tz )
|
||||
return tz->ToUTC(local_time);
|
||||
|
||||
return local_time;
|
||||
}
|
||||
|
||||
|
||||
|
||||
PT::Date System::ToUTC(const PT::Date & local_date)
|
||||
{
|
||||
size_t tz_id;
|
||||
|
||||
if( cur->session && cur->session->puser )
|
||||
tz_id = cur->session->puser->time_zone_id;
|
||||
else
|
||||
tz_id = config->time_zone_default_id;
|
||||
|
||||
TimeZone * tz = time_zones.GetZone(tz_id);
|
||||
|
||||
if( tz )
|
||||
return tz->ToUTC(local_date);
|
||||
|
||||
return local_date;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
return codes:
|
||||
ok:
|
||||
@@ -785,6 +1076,12 @@ bool System::FollowAllLinksFileOrSymlinkFound(std::vector<Item*> & out_dir_tab,
|
||||
return false;
|
||||
}
|
||||
|
||||
if( check_access && !HasReadAccess(out_item) )
|
||||
{
|
||||
log << log1 << "System: no read access to the file or symlink" << logend;
|
||||
return false;
|
||||
}
|
||||
|
||||
if( out_item.type == Item::symlink )
|
||||
{
|
||||
if( out_item.link_to.empty() )
|
||||
@@ -794,16 +1091,8 @@ bool System::FollowAllLinksFileOrSymlinkFound(std::vector<Item*> & out_dir_tab,
|
||||
}
|
||||
else
|
||||
{
|
||||
if( !check_access || HasReadAccess(out_item) )
|
||||
{
|
||||
if( !(stop_on_link_redirect && out_item.link_redirect==1) )
|
||||
link_to_temp = out_item.link_to;
|
||||
}
|
||||
else
|
||||
{
|
||||
log << log1 << "System: no read access to the symlink" << logend;
|
||||
return false;
|
||||
}
|
||||
if( !(stop_on_link_redirect && out_item.link_redirect==1) )
|
||||
link_to_temp = out_item.link_to;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -965,3 +1254,60 @@ return ok;
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
adding a new file to winix
|
||||
file_path - a name of a static file (from common directory)
|
||||
url - url of a file which will be inserted (in /var directory)
|
||||
|
||||
current limitation:
|
||||
warning: the url is not prepared by PrepareUrl() (PrepareUrl is from functions)
|
||||
*/
|
||||
bool System::AddCommonFileToVar(const wchar_t * file_path, const wchar_t * url, bool overwrite_existing)
|
||||
{
|
||||
if( config->common_dir.empty() )
|
||||
{
|
||||
log << log1 << "System: can't open a file from common directory, common_dir not set in the config" << logend;
|
||||
return false;
|
||||
}
|
||||
|
||||
file_name = config->common_dir;
|
||||
file_name += '/';
|
||||
file_name += file_path;
|
||||
|
||||
if( !GetUTF8File(file_name, file_content) )
|
||||
{
|
||||
log << log1 << "System: can't open a file: " << file_name << logend;
|
||||
return false;
|
||||
}
|
||||
|
||||
Item * var = dirs.CreateVarDir();
|
||||
|
||||
if( !var )
|
||||
{
|
||||
log << log1 << "System: can't create /var directory" << logend;
|
||||
return false;
|
||||
}
|
||||
|
||||
if( db->GetItem(var->id, url, file_content_item) == WINIX_ERR_OK )
|
||||
{
|
||||
if( overwrite_existing )
|
||||
db->DelItem(file_content_item);
|
||||
else
|
||||
return true;
|
||||
}
|
||||
|
||||
file_content_item.Clear();
|
||||
file_content_item.parent_id = var->id;
|
||||
file_content_item.user_id = var->user_id;
|
||||
file_content_item.group_id = var->group_id;
|
||||
file_content_item.privileges = 07555; // !! IMPROVE ME: may it should be added as a parameter to this function?
|
||||
file_content_item.subject = url;
|
||||
file_content_item.url = url;
|
||||
file_content_item.type = Item::file;
|
||||
file_content_item.content_type = Item::ct_raw;
|
||||
file_content_item.content = file_content;
|
||||
|
||||
return AddFile(file_content_item, false) == WINIX_ERR_OK;
|
||||
}
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* This file is a part of Winix
|
||||
* and is not publicly distributed
|
||||
*
|
||||
* Copyright (c) 2010, Tomasz Sowa
|
||||
* Copyright (c) 2010-2012, Tomasz Sowa
|
||||
* All rights reserved.
|
||||
*
|
||||
*/
|
||||
@@ -11,6 +11,7 @@
|
||||
#define headerfile_winix_core_system
|
||||
|
||||
#include <ctime>
|
||||
#include "job.h"
|
||||
#include "dirs.h"
|
||||
#include "mounts.h"
|
||||
#include "db/db.h"
|
||||
@@ -22,10 +23,14 @@
|
||||
#include "rebus.h"
|
||||
#include "loadavg.h"
|
||||
#include "synchro.h"
|
||||
#include "thumb.h"
|
||||
#include "image.h"
|
||||
#include "threadmanager.h"
|
||||
#include "notify/notify.h"
|
||||
#include "timezones.h"
|
||||
|
||||
|
||||
class Functions;
|
||||
class SessionManager;
|
||||
|
||||
|
||||
// file system
|
||||
@@ -54,8 +59,8 @@ public:
|
||||
// notifications (by emails)
|
||||
Notify notify;
|
||||
|
||||
// thumbnails (special thread)
|
||||
Thumb thumb;
|
||||
// images (resizing, generating thumbnails)
|
||||
Image image;
|
||||
|
||||
// the time when the winix starts
|
||||
time_t system_start;
|
||||
@@ -63,25 +68,44 @@ public:
|
||||
// cryptography and hashes
|
||||
Crypt crypt;
|
||||
|
||||
// thread management
|
||||
ThreadManager thread_manager;
|
||||
|
||||
// jobs
|
||||
Job job;
|
||||
|
||||
// time zones read from etc/time_zones.conf
|
||||
// when winix starts
|
||||
TimeZones time_zones;
|
||||
|
||||
|
||||
void SetCur(Cur * pcur);
|
||||
void SetConfig(Config * pconfig);
|
||||
void SetDb(Db * pdb);
|
||||
void SetSynchro(Synchro * psynchro);
|
||||
void SetFunctions(Functions * pfunctions);
|
||||
void SetSessionManager(SessionManager * sm);
|
||||
void Init();
|
||||
|
||||
void AddParams(const ParamTab & param_tab, std::wstring & str, bool clear_str = true);
|
||||
|
||||
void PutUrlProto(bool can_use_ssl, std::wstring & str, bool clear_str = true);
|
||||
void RedirectTo(const Item & item, const wchar_t * postfix = 0);
|
||||
void RedirectTo(long item_id, const wchar_t * postfix = 0);
|
||||
void RedirectTo(const wchar_t * url);
|
||||
void RedirectTo(const std::wstring & url);
|
||||
void RedirectWithFunctionAndParamsTo(const wchar_t * url);
|
||||
void RedirectWithFunctionAndParamsTo(const std::wstring & url);
|
||||
void RedirectToLastDir();
|
||||
void RedirectToLastItem(); // redirect to an item if exists or to the last directory
|
||||
void RedirectToLastDir(const wchar_t * postfix = 0);
|
||||
void RedirectToLastItem(const wchar_t * postfix = 0); // redirect to an item if exists or to the last directory
|
||||
void RedirectToLastFunction(const wchar_t * postfix = 0);
|
||||
|
||||
|
||||
bool CanChangeUser(const Item & item, long new_user_id);
|
||||
bool CanChangeGroup(const Item & item, long new_group_id);
|
||||
bool CanChangePrivileges(const Item & item, int new_priv);
|
||||
bool HasAccess(const Item & item, int mask);
|
||||
|
||||
|
||||
bool HasReadAccess(const Item & item);
|
||||
bool HasWriteAccess(const Item & item);
|
||||
bool HasReadWriteAccess(const Item & item);
|
||||
@@ -90,6 +114,17 @@ public:
|
||||
bool HasReadExecAccessToPath(const std::vector<Item*> & dir_tab);
|
||||
bool DirsHaveReadExecPerm();
|
||||
void CheckAccessToItems(std::vector<Item> & item_tab);
|
||||
void CheckWriteAccessToItems(std::vector<Item> & item_tab);
|
||||
|
||||
/*
|
||||
this method checks the sticky bit and write permissions
|
||||
it returns true if we can remove/rename an item for the given child_item_user_id user id
|
||||
*/
|
||||
bool CanRemoveRenameChild(const Item & dir, long child_item_user_id);
|
||||
|
||||
int NewFilePrivileges();
|
||||
int NewDirPrivileges();
|
||||
|
||||
|
||||
bool CanUseHtml(long user_id);
|
||||
bool CanUseBBCode(long user_id);
|
||||
@@ -103,13 +138,16 @@ public:
|
||||
|
||||
bool MakePath(const Item & item, std::wstring & path, bool clear_path = true);
|
||||
|
||||
Error AddFile(Item & item, int notify_code = 0);
|
||||
Error EditFile(Item & item, bool with_url = true, int notify_code = 0);
|
||||
Error AddFile(Item & item, int notify_code = 0, bool call_plugins = true);
|
||||
Error EditFile(Item & item, bool with_url = true, int notify_code = 0, bool call_plugins = true);
|
||||
|
||||
|
||||
time_t ToLocal(time_t utc_time);
|
||||
PT::Date ToLocal(const PT::Date & utc_date);
|
||||
|
||||
time_t ToUTC(time_t local_time);
|
||||
PT::Date ToUTC(const PT::Date & local_date);
|
||||
|
||||
// converting GMT time to local time (different for each user)
|
||||
time_t LocalTime(time_t gmt_time);
|
||||
tm LocalTime(const tm * ptm);
|
||||
tm LocalTime(const tm & ptm);
|
||||
|
||||
int FollowLink(const std::vector<Item*> & current_dir_tab, const std::wstring & link_to,
|
||||
std::vector<Item*> & out_dir_tab, Item & out_item);
|
||||
@@ -127,21 +165,34 @@ public:
|
||||
bool FollowAllLinks(const std::wstring & link_to,
|
||||
bool follow_dir_default = false, bool stop_on_link_redirect = false, bool check_access = true);
|
||||
|
||||
|
||||
bool AddCommonFileToVar(const wchar_t * file_path, const wchar_t * url, bool overwrite_existing = true);
|
||||
|
||||
// reloading time zones
|
||||
void ReadTimeZones();
|
||||
|
||||
private:
|
||||
|
||||
Cur * cur;
|
||||
Db * db;
|
||||
Config * config;
|
||||
Synchro * synchro;
|
||||
Functions * functions;
|
||||
SessionManager * session_manager;
|
||||
|
||||
Item item_temp;
|
||||
std::wstring link_to_temp, name_temp;
|
||||
std::wstring file_content, file_name;
|
||||
Item file_content_item;
|
||||
|
||||
// for FollowAllLinks
|
||||
std::vector<Item*> temp_follow_dir_tab;
|
||||
std::vector<Item*> root_follow_dir_tab;
|
||||
Item temp_follow_item;
|
||||
|
||||
bool HasAccess(const Item & item, int mask);
|
||||
int NewPrivileges(int creation_mask);
|
||||
|
||||
bool CreateNewFileSimpleFs(Item & item);
|
||||
bool CreateNewFileHashFs(Item & item);
|
||||
|
||||
|
||||
@@ -1,13 +0,0 @@
|
||||
/*
|
||||
* This file is a part of Winix
|
||||
* and is not publicly distributed
|
||||
*
|
||||
* Copyright (c) 2010, Tomasz Sowa
|
||||
* All rights reserved.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "textstream.h"
|
||||
#include "misc.h"
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* This file is a part of Winix
|
||||
* and is not publicly distributed
|
||||
*
|
||||
* Copyright (c) 2010, Tomasz Sowa
|
||||
* Copyright (c) 2010-2012, Tomasz Sowa
|
||||
* All rights reserved.
|
||||
*
|
||||
*/
|
||||
@@ -11,7 +11,12 @@
|
||||
#define headerfile_winix_core_textstream
|
||||
|
||||
#include <string>
|
||||
#include <ctime>
|
||||
#include "misc.h"
|
||||
#include "space/space.h"
|
||||
#include "date/date.h"
|
||||
#include "textstream/textstream.h"
|
||||
|
||||
|
||||
|
||||
/*
|
||||
@@ -55,6 +60,11 @@ public:
|
||||
TextStream & operator<<(unsigned long);
|
||||
TextStream & operator<<(double);
|
||||
TextStream & operator<<(const void *);// printing a pointer
|
||||
TextStream & operator<<(const PT::Space & space);
|
||||
TextStream & operator<<(const PT::Date & date);
|
||||
|
||||
template<typename arg_char_type, size_t arg_stack_size, size_t arg_heap_block_size>
|
||||
TextStream & operator<<(const PT::TextStreamBase<arg_char_type, arg_stack_size, arg_heap_block_size> & arg);
|
||||
|
||||
TextStream & Write(const char * buf, size_t len);
|
||||
TextStream & Write(const wchar_t * buf, size_t len);
|
||||
@@ -64,7 +74,7 @@ public:
|
||||
protected:
|
||||
|
||||
StringType buffer;
|
||||
|
||||
std::wstring space_str; // for using with spaces
|
||||
};
|
||||
|
||||
|
||||
@@ -301,5 +311,39 @@ TextStream<StringType> & TextStream<StringType>::write(const wchar_t * buf, size
|
||||
return Write(buf, len);
|
||||
}
|
||||
|
||||
|
||||
template<class StringType>
|
||||
TextStream<StringType> & TextStream<StringType>::operator<<(const PT::Space & space)
|
||||
{
|
||||
space.Serialize(*this, true, false);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
|
||||
template<class StringType>
|
||||
TextStream<StringType> & TextStream<StringType>::operator<<(const PT::Date & date)
|
||||
{
|
||||
date.Serialize(*this);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
template<class StringType>
|
||||
template<typename arg_char_type, size_t arg_stack_size, size_t arg_heap_block_size>
|
||||
TextStream<StringType> & TextStream<StringType>::operator<<(
|
||||
const PT::TextStreamBase<arg_char_type, arg_stack_size, arg_heap_block_size> & arg)
|
||||
{
|
||||
typename PT::TextStreamBase<arg_char_type, arg_stack_size, arg_heap_block_size>::const_iterator i;
|
||||
|
||||
for(i=arg.begin() ; i != arg.end() ; ++i)
|
||||
buffer += static_cast<char_type>(*i);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
136
core/threadmanager.cpp
Executable file
136
core/threadmanager.cpp
Executable file
@@ -0,0 +1,136 @@
|
||||
/*
|
||||
* This file is a part of Winix
|
||||
* and is not publicly distributed
|
||||
*
|
||||
* Copyright (c) 2011-2012, Tomasz Sowa
|
||||
* All rights reserved.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <signal.h>
|
||||
#include "threadmanager.h"
|
||||
#include "log.h"
|
||||
|
||||
|
||||
ThreadManager::ThreadManager()
|
||||
{
|
||||
were_started = false;
|
||||
}
|
||||
|
||||
|
||||
void ThreadManager::SetSynchro(Synchro * psynchro)
|
||||
{
|
||||
synchro = psynchro;
|
||||
}
|
||||
|
||||
|
||||
void ThreadManager::Init()
|
||||
{
|
||||
sigset_t set;
|
||||
|
||||
sigemptyset(&set);
|
||||
sigaddset(&set, SIGTERM);
|
||||
sigaddset(&set, SIGINT);
|
||||
|
||||
// blocking SIGTERM and SIGINT
|
||||
// new threads will have the signals blocked too
|
||||
pthread_sigmask(SIG_BLOCK, &set, 0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void ThreadManager::Add(BaseThread * pbase, const wchar_t * thread_name)
|
||||
{
|
||||
ThreadItem item;
|
||||
|
||||
item.object = pbase;
|
||||
item.name = thread_name;
|
||||
thread_tab.push_back(item);
|
||||
|
||||
if( were_started )
|
||||
Start(thread_tab.size() - 1);
|
||||
else
|
||||
log << log4 << "TM: added a thread to the queue, number: " << (thread_tab.size()-1)
|
||||
<< ", name: " << thread_name << logend;
|
||||
}
|
||||
|
||||
|
||||
void ThreadManager::Add(BaseThread & pbase, const wchar_t * thread_name)
|
||||
{
|
||||
Add(&pbase, thread_name);
|
||||
}
|
||||
|
||||
|
||||
void ThreadManager::Add(BaseThread * pbase, const std::wstring & thread_name)
|
||||
{
|
||||
Add(pbase, thread_name.c_str());
|
||||
}
|
||||
|
||||
void ThreadManager::Add(BaseThread & pbase, const std::wstring & thread_name)
|
||||
{
|
||||
Add(&pbase, thread_name.c_str());
|
||||
}
|
||||
|
||||
|
||||
|
||||
void ThreadManager::StartAll()
|
||||
{
|
||||
synchro->Lock();
|
||||
|
||||
for(size_t i=0 ; i<thread_tab.size() ; ++i)
|
||||
Start(i);
|
||||
|
||||
synchro->Unlock();
|
||||
|
||||
were_started = true;
|
||||
}
|
||||
|
||||
|
||||
void ThreadManager::Start(size_t i)
|
||||
{
|
||||
if( i < thread_tab.size() )
|
||||
{
|
||||
thread_tab[i].object->SetSynchro(synchro);
|
||||
|
||||
if( thread_tab[i].object->StartThread() )
|
||||
{
|
||||
log << log4 << "TM: thread " << i << " (" << thread_tab[i].object->ThreadId() << ", name: "
|
||||
<< thread_tab[i].name << ") started" << logend;
|
||||
}
|
||||
else
|
||||
{
|
||||
log << log4 << "TM: cannot run a thread, thread number: " << i
|
||||
<< ", name: " << thread_tab[i].name << logend;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void ThreadManager::StopAll()
|
||||
{
|
||||
if( !were_started )
|
||||
return;
|
||||
|
||||
// WakeUpThread() should be used with Lock/Unlock
|
||||
synchro->Lock();
|
||||
|
||||
for(size_t i=0 ; i<thread_tab.size() ; ++i)
|
||||
thread_tab[i].object->WakeUpThread();
|
||||
|
||||
synchro->Unlock();
|
||||
|
||||
|
||||
for(size_t i=0 ; i<thread_tab.size() ; ++i)
|
||||
{
|
||||
log << log4 << "TM: waiting for thread " << i << " (" << thread_tab[i].object->ThreadId()
|
||||
<< ", name: " << thread_tab[i].name << ")" << logend;
|
||||
|
||||
thread_tab[i].object->WaitForThread();
|
||||
|
||||
log << log4 << "TM: thread " << i << " terminated" << logend;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
65
core/threadmanager.h
Executable file
65
core/threadmanager.h
Executable file
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
* This file is a part of Winix
|
||||
* and is not publicly distributed
|
||||
*
|
||||
* Copyright (c) 2011-2012, Tomasz Sowa
|
||||
* All rights reserved.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef headerfile_winix_core_threadmanager
|
||||
#define headerfile_winix_core_threadmanager
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include "basethread.h"
|
||||
#include "synchro.h"
|
||||
|
||||
|
||||
|
||||
class ThreadManager
|
||||
{
|
||||
public:
|
||||
|
||||
ThreadManager();
|
||||
|
||||
// synchro object
|
||||
void SetSynchro(Synchro * psynchro);
|
||||
|
||||
// initializing
|
||||
void Init();
|
||||
|
||||
// adding a new thread to the queue
|
||||
// the thread will be running only if we call StartAll() before
|
||||
// otherwise the thread will be waiting for StartAll()
|
||||
void Add(BaseThread * pbase, const wchar_t * thread_name);
|
||||
void Add(BaseThread & pbase, const wchar_t * thread_name);
|
||||
void Add(BaseThread * pbase, const std::wstring & thread_name);
|
||||
void Add(BaseThread & pbase, const std::wstring & thread_name);
|
||||
|
||||
// starting all threads
|
||||
void StartAll();
|
||||
|
||||
// sending a stop signal to all threads
|
||||
// and waiting until they finish
|
||||
void StopAll();
|
||||
|
||||
private:
|
||||
|
||||
struct ThreadItem
|
||||
{
|
||||
BaseThread * object;
|
||||
std::wstring name;
|
||||
};
|
||||
|
||||
Synchro * synchro;
|
||||
typedef std::vector<ThreadItem> ThreadTab;
|
||||
ThreadTab thread_tab;
|
||||
bool were_started;
|
||||
|
||||
void Start(size_t i);
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
309
core/thumb.cpp
309
core/thumb.cpp
@@ -1,309 +0,0 @@
|
||||
/*
|
||||
* This file is a part of Winix
|
||||
* and is not publicly distributed
|
||||
*
|
||||
* Copyright (c) 2010, Tomasz Sowa
|
||||
* All rights reserved.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <ctime>
|
||||
#include "thumb.h"
|
||||
#include "utf8.h"
|
||||
#include "log.h"
|
||||
#include "system.h"
|
||||
|
||||
|
||||
|
||||
|
||||
void Thumb::SetDb(Db * pdb)
|
||||
{
|
||||
db = pdb;
|
||||
}
|
||||
|
||||
|
||||
void Thumb::SetConfig(Config * pconfig)
|
||||
{
|
||||
config = pconfig;
|
||||
}
|
||||
|
||||
|
||||
void Thumb::SetSystem(System * psystem)
|
||||
{
|
||||
system = psystem;
|
||||
}
|
||||
|
||||
|
||||
// first thread (objects locked)
|
||||
void Thumb::CreateThumb(const Item & item, size_t cx, size_t cy, int aspect_mode)
|
||||
{
|
||||
item_temp.file = item;
|
||||
item_temp.cx = cx;
|
||||
item_temp.cy = cy;
|
||||
item_temp.aspect_mode = aspect_mode;
|
||||
|
||||
thumb_tab.insert(thumb_tab.end(), item_temp);
|
||||
WakeUpThread();
|
||||
}
|
||||
|
||||
|
||||
|
||||
// second thread (objects locked)
|
||||
bool Thumb::SignalReceived()
|
||||
{
|
||||
return !thumb_tab.empty();
|
||||
}
|
||||
|
||||
|
||||
|
||||
// second thread (objects not locked)
|
||||
void Thumb::Do()
|
||||
{
|
||||
ThumbTab::iterator i;
|
||||
bool end;
|
||||
|
||||
Lock();
|
||||
i = thumb_tab.begin();
|
||||
Unlock();
|
||||
|
||||
do
|
||||
{
|
||||
Lock();
|
||||
|
||||
if( i != thumb_tab.end() )
|
||||
{
|
||||
item_work = *i;
|
||||
thumb_tab.erase(i++);
|
||||
end = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
end = true;
|
||||
}
|
||||
|
||||
Unlock();
|
||||
|
||||
if( !end )
|
||||
CreateThumbnail();
|
||||
|
||||
}
|
||||
while( !end && !IsExitSignal() );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void Thumb::EscapePath(const std::string & path)
|
||||
{
|
||||
command << '"';
|
||||
|
||||
for(size_t i=0 ; i<path.size() ; ++i)
|
||||
{
|
||||
if( path[i] == '"' )
|
||||
command << '\\';
|
||||
|
||||
command << path[i];
|
||||
}
|
||||
|
||||
command << "\" ";
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
from: http://www.imagemagick.org/script/command-line-processing.php#geometry
|
||||
|
||||
scale% Height and width both scaled by specified percentage.
|
||||
scale-x%xscale-y% Height and width individually scaled by specified percentages. (Only one % symbol needed.)
|
||||
width Width given, height automagically selected to preserve aspect ratio.
|
||||
xheight Height given, width automagically selected to preserve aspect ratio.
|
||||
widthxheight Maximum values of height and width given, aspect ratio preserved.
|
||||
widthxheight^ Minimum values of width and height given, aspect ratio preserved.
|
||||
widthxheight! Width and height emphatically given, original aspect ratio ignored.
|
||||
widthxheight> Change as per widthxheight but only if an image dimension exceeds a specified dimension.
|
||||
widthxheight< Change dimensions only if both image dimensions exceed specified dimensions.
|
||||
*/
|
||||
void Thumb::SelectAspect()
|
||||
{
|
||||
switch( item_work.aspect_mode )
|
||||
{
|
||||
case WINIX_THUMB_MODE_1:
|
||||
command << item_work.cx;
|
||||
break;
|
||||
|
||||
case WINIX_THUMB_MODE_3:
|
||||
command << item_work.cx << "x" << item_work.cy;
|
||||
break;
|
||||
|
||||
case WINIX_THUMB_MODE_4:
|
||||
command << '"' << item_work.cx << "x" << item_work.cy << "^\"";
|
||||
break;
|
||||
|
||||
case WINIX_THUMB_MODE_5:
|
||||
command << '"' << item_work.cx << "x" << item_work.cy << "!\"";
|
||||
break;
|
||||
|
||||
case WINIX_THUMB_MODE_6:
|
||||
command << '"' << item_work.cx << "x" << item_work.cy << ">\"";
|
||||
break;
|
||||
|
||||
case WINIX_THUMB_MODE_7:
|
||||
command << '"' << item_work.cx << "x" << item_work.cy << "<\"";
|
||||
break;
|
||||
|
||||
case WINIX_THUMB_MODE_2:
|
||||
default:
|
||||
command << "x" << item_work.cy;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// second thread (objects are not locked)
|
||||
bool Thumb::CreateCommand()
|
||||
{
|
||||
bool res;
|
||||
|
||||
command.Clear();
|
||||
stream_tmp_path.Clear();
|
||||
|
||||
Lock();
|
||||
|
||||
Ezc::WideToUTF8(config->convert_cmd, tempa);
|
||||
command << tempa << " -quiet -strip -thumbnail ";
|
||||
SelectAspect();
|
||||
command << " ";
|
||||
|
||||
if( system->MakeFilePath(item_work.file, src_path) )
|
||||
{
|
||||
Ezc::WideToUTF8(src_path, tempa);
|
||||
EscapePath(tempa);
|
||||
|
||||
stream_tmp_path << config->upload_dir << L"/tmp/thumb_" << std::time(0);
|
||||
Ezc::WideToUTF8(stream_tmp_path.Str(), string_tmp_patha);
|
||||
EscapePath(string_tmp_patha);
|
||||
|
||||
res = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
log << log1 << "Thumb: cannot create a source path" << logend;
|
||||
res = false;
|
||||
}
|
||||
|
||||
Unlock();
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// second thread (objects are not locked)
|
||||
void Thumb::SaveTmpThumbnail()
|
||||
{
|
||||
bool moved = false;
|
||||
|
||||
Lock();
|
||||
|
||||
// the file could have been changed especially when creating thumbnail lasted too long
|
||||
iq.SetAll(false, false);
|
||||
iq.sel_parent_id = true;
|
||||
iq.sel_file = true;
|
||||
iq.sel_url = true;
|
||||
iq.sel_type = true;
|
||||
iq.WhereId(item_work.file.id);
|
||||
|
||||
if( db->GetItem(item_work.file, iq) == WINIX_ERR_OK )
|
||||
{
|
||||
if( system->MakeFilePath(item_work.file, dst_path, true, true, config->upload_dirs_chmod) )
|
||||
{
|
||||
if( RenameFile(stream_tmp_path.Str(), dst_path) )
|
||||
{
|
||||
log << log3 << "Thumb: created a thumbnail: " << dst_path << logend;
|
||||
db->EditHasThumbById(true, item_work.file.id);
|
||||
moved = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
log << log1 << "Thumb: cannot move a temporary file: " << stream_tmp_path.Str() << ", to: " << dst_path << logend;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
log << log1 << "Thumb: cannot create a destination path" << logend;
|
||||
}
|
||||
}
|
||||
|
||||
if( !moved )
|
||||
::RemoveFile(stream_tmp_path.Str());
|
||||
|
||||
Unlock();
|
||||
}
|
||||
|
||||
|
||||
|
||||
// second thread (objects are not locked)
|
||||
void Thumb::CreateThumbnail()
|
||||
{
|
||||
if( !CreateCommand() )
|
||||
return;
|
||||
|
||||
int res = std::system(command.CStr());
|
||||
|
||||
if( res == 0 )
|
||||
{
|
||||
SaveTmpThumbnail();
|
||||
}
|
||||
else
|
||||
{
|
||||
Lock();
|
||||
log << log3 << "Thumb: some problems with creating a thumbnail " << tempa
|
||||
<< ", 'convert' process returned: " << res << logend;
|
||||
Unlock();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// second thread (objects are not locked)
|
||||
// !! there is a problem with GIF files
|
||||
// Bus error (core dumped)
|
||||
/*
|
||||
#include "wand/MagickWand.h"
|
||||
|
||||
// compiler options:
|
||||
// include: -I/usr/local/include/ImageMagick
|
||||
// link with: `MagickWand-config --ldflags --libs`
|
||||
|
||||
void Thumb::CreateThumbnail()
|
||||
{
|
||||
Ezc::WideToUTF8(item_work.source, sourcea);
|
||||
Ezc::WideToUTF8(item_work.dst, dsta);
|
||||
|
||||
MagickWandGenesis();
|
||||
|
||||
MagickWand * wand = NewMagickWand();
|
||||
|
||||
if( MagickReadImage(wand, sourcea.c_str()) )
|
||||
{
|
||||
MagickThumbnailImage(wand, item_work.cx, item_work.cy);
|
||||
|
||||
if( MagickWriteImage(wand, dsta.c_str()) )
|
||||
{
|
||||
Lock();
|
||||
log << log3 << "Thumb: created a thumbnail: " << dsta << logend;
|
||||
Unlock();
|
||||
}
|
||||
}
|
||||
|
||||
DestroyMagickWand(wand);
|
||||
|
||||
MagickWandTerminus();
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
289
core/timezone.cpp
Normal file
289
core/timezone.cpp
Normal file
@@ -0,0 +1,289 @@
|
||||
/*
|
||||
* This file is a part of Winix
|
||||
* and is not publicly distributed
|
||||
*
|
||||
* Copyright (c) 2012, Tomasz Sowa
|
||||
* All rights reserved.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "timezone.h"
|
||||
#include "misc.h"
|
||||
|
||||
|
||||
|
||||
|
||||
TimeZone::Dst::Dst()
|
||||
{
|
||||
Clear();
|
||||
}
|
||||
|
||||
|
||||
void TimeZone::Dst::Clear()
|
||||
{
|
||||
has_dst = false;
|
||||
start.Clear();
|
||||
end.Clear();
|
||||
offset = 0;
|
||||
}
|
||||
|
||||
|
||||
bool TimeZone::Dst::IsDstUsed(const PT::Date & date) const
|
||||
{
|
||||
if( !has_dst )
|
||||
return false;
|
||||
|
||||
if( Compare(start, date) <= 0 ) // !! CHECK ME <= or < ? (what about the one second?)
|
||||
if( Compare(date, end) < 0 )
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
int TimeZone::Dst::Compare(const PT::Date & date1, const PT::Date & date2) const
|
||||
{
|
||||
// year is ignored
|
||||
|
||||
if( date1.month != date2.month )
|
||||
return date1.month - date2.month;
|
||||
|
||||
if( date1.day != date2.day )
|
||||
return date1.day - date2.day;
|
||||
|
||||
if( date1.hour != date2.hour )
|
||||
return date1.hour - date2.hour;
|
||||
|
||||
if( date1.min != date2.min )
|
||||
return date1.min - date2.min;
|
||||
|
||||
if( date1.sec != date2.sec )
|
||||
return date1.sec - date2.sec;
|
||||
|
||||
// dates are equal
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
TimeZone::TimeZone()
|
||||
{
|
||||
Clear();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void TimeZone::Clear()
|
||||
{
|
||||
name.clear();
|
||||
id = 0;
|
||||
offset = 0;
|
||||
dst_map.clear();
|
||||
}
|
||||
|
||||
|
||||
|
||||
TimeZone::Dst * TimeZone::FindDst(int year)
|
||||
{
|
||||
if( dst_map.empty() )
|
||||
return 0;
|
||||
|
||||
DstMap::iterator i = dst_map.lower_bound(year);
|
||||
|
||||
if( i == dst_map.begin() && i->first > year )
|
||||
return 0;
|
||||
|
||||
if( i == dst_map.end() )
|
||||
return &(--i)->second;
|
||||
|
||||
if( i != dst_map.begin() && i->first > year )
|
||||
return &(--i)->second;
|
||||
|
||||
return &i->second;
|
||||
}
|
||||
|
||||
|
||||
|
||||
time_t TimeZone::CalcLocalOffset(const PT::Date & utc_date)
|
||||
{
|
||||
time_t dst_offset = 0;
|
||||
|
||||
Dst * dst = FindDst(utc_date.year);
|
||||
|
||||
if( dst && dst->IsDstUsed(utc_date) )
|
||||
dst_offset = dst->offset;
|
||||
|
||||
return offset + dst_offset;
|
||||
}
|
||||
|
||||
|
||||
|
||||
time_t TimeZone::ToLocal(time_t utc_time)
|
||||
{
|
||||
time_t offset = CalcLocalOffset(PT::Date(utc_time));
|
||||
|
||||
return utc_time + offset;
|
||||
}
|
||||
|
||||
|
||||
PT::Date TimeZone::ToLocal(const PT::Date & utc_date)
|
||||
{
|
||||
PT::Date local(utc_date);
|
||||
local += CalcLocalOffset(utc_date);
|
||||
|
||||
return local;
|
||||
}
|
||||
|
||||
|
||||
time_t TimeZone::CalcUTCOffset(const PT::Date & local_date)
|
||||
{
|
||||
time_t dst_offset = 0;
|
||||
|
||||
Dst * dst = FindDst(local_date.year);
|
||||
|
||||
if( dst && dst->has_dst )
|
||||
{
|
||||
// dst date ranges we have in UTC
|
||||
PT::Date utc(local_date);
|
||||
utc -= (offset + dst->offset);
|
||||
|
||||
if( dst->IsDstUsed(utc) )
|
||||
dst_offset = dst->offset;
|
||||
}
|
||||
|
||||
return offset + dst_offset;
|
||||
}
|
||||
|
||||
|
||||
|
||||
time_t TimeZone::ToUTC(time_t local_time)
|
||||
{
|
||||
time_t offset = CalcUTCOffset(PT::Date(local_time));
|
||||
|
||||
return local_time - offset;
|
||||
}
|
||||
|
||||
|
||||
|
||||
PT::Date TimeZone::ToUTC(const PT::Date & local_date)
|
||||
{
|
||||
time_t offset;
|
||||
PT::Date utc(local_date);
|
||||
|
||||
offset = CalcUTCOffset(local_date);
|
||||
utc -= offset;
|
||||
|
||||
return utc;
|
||||
}
|
||||
|
||||
|
||||
|
||||
time_t TimeZone::ParseStrOffset(const wchar_t * str)
|
||||
{
|
||||
PT::Date date;
|
||||
bool is_sign = false;
|
||||
time_t offset = 0;
|
||||
|
||||
str = SkipWhite(str);
|
||||
|
||||
if( *str == '-' )
|
||||
{
|
||||
is_sign = true;
|
||||
str += 1;
|
||||
}
|
||||
else
|
||||
if( *str == '+' )
|
||||
{
|
||||
str += 1;
|
||||
}
|
||||
|
||||
if( date.ParseTime(str) )
|
||||
{
|
||||
offset = date.hour * 60 * 60 + date.min * 60 + date.sec;
|
||||
|
||||
if( is_sign )
|
||||
offset = -offset;
|
||||
}
|
||||
|
||||
return offset;
|
||||
}
|
||||
|
||||
|
||||
time_t TimeZone::GetOffset(PT::Space & space)
|
||||
{
|
||||
std::wstring * offset_str = space.GetValue(L"offset_str");
|
||||
|
||||
if( offset_str )
|
||||
return ParseStrOffset(offset_str->c_str());
|
||||
|
||||
return space.Long(L"offset");
|
||||
}
|
||||
|
||||
|
||||
bool TimeZone::SetTzDst(PT::Space & year)
|
||||
{
|
||||
time_t h24 = 60 * 60 * 24; // 24 hours
|
||||
bool result = true;
|
||||
Dst dst;
|
||||
|
||||
int year_int = Toi(year.name);
|
||||
|
||||
if( year_int < 1970 && year_int > 10000 )
|
||||
return false;
|
||||
|
||||
dst.has_dst = year.Bool(L"has_dst", false);
|
||||
|
||||
if( dst.has_dst )
|
||||
{
|
||||
dst.start.year = year_int;
|
||||
dst.end.year = year_int;
|
||||
|
||||
if( !dst.start.ParseMonthDayTime(year.Text(L"start")) )
|
||||
result = false;
|
||||
|
||||
if( !dst.end.ParseMonthDayTime(year.Text(L"end")) )
|
||||
result = false;
|
||||
|
||||
dst.offset = GetOffset(year);
|
||||
|
||||
if( dst.offset < -h24 || dst.offset > h24 )
|
||||
result = false;
|
||||
}
|
||||
|
||||
if( result )
|
||||
dst_map[year_int] = dst;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
bool TimeZone::SetTz(PT::Space & space)
|
||||
{
|
||||
bool result = true;
|
||||
name = space.name;
|
||||
id = space.Int(L"id", -1);
|
||||
offset = GetOffset(space);
|
||||
time_t h24 = 60 * 60 * 24; // 24 hours
|
||||
|
||||
if( offset < -h24 || offset > h24 )
|
||||
result = false;
|
||||
|
||||
PT::Space & dst = space.FindAddSpace(L"dst");
|
||||
|
||||
for(size_t i=0 ; i<dst.spaces.size() ; ++i)
|
||||
{
|
||||
PT::Space & year = *dst.spaces[i];
|
||||
|
||||
if( !SetTzDst(year) )
|
||||
{
|
||||
result = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
142
core/timezone.h
Normal file
142
core/timezone.h
Normal file
@@ -0,0 +1,142 @@
|
||||
/*
|
||||
* This file is a part of Winix
|
||||
* and is not publicly distributed
|
||||
*
|
||||
* Copyright (c) 2012, Tomasz Sowa
|
||||
* All rights reserved.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef headerfile_winix_core_timezone
|
||||
#define headerfile_winix_core_timezone
|
||||
|
||||
#include <ctime>
|
||||
#include <map>
|
||||
#include "date/date.h"
|
||||
#include "space/space.h"
|
||||
|
||||
|
||||
|
||||
class TimeZone
|
||||
{
|
||||
public:
|
||||
|
||||
|
||||
struct Dst
|
||||
{
|
||||
// true if a time zone has daylight saving time
|
||||
bool has_dst;
|
||||
|
||||
// time zone daylight saving time (used if has_dst is true)
|
||||
// the 'year' field is the same in 'start' and 'end'
|
||||
// start and end are represented in UTC time
|
||||
PT::Date start, end;
|
||||
|
||||
// time zone daylight saving time offset
|
||||
// used when has_dst is true and the date is whithin start and end
|
||||
// this offset should be added to time zone offset
|
||||
time_t offset;
|
||||
|
||||
Dst();
|
||||
void Clear();
|
||||
|
||||
// checking whether specified 'date' is in the range of <start, end>
|
||||
// the year field in date, start and end is ignored
|
||||
// has_dst must be true
|
||||
bool IsDstUsed(const PT::Date & date) const;
|
||||
|
||||
|
||||
private:
|
||||
|
||||
// Compare returns zero if date1 and date2 are equal
|
||||
// return value less than zero if date1 is lower than date2
|
||||
// and a value greater than zero if date1 is greater than date2
|
||||
// the year field is ignored
|
||||
int Compare(const PT::Date & date1, const PT::Date & date2) const;
|
||||
|
||||
};
|
||||
|
||||
|
||||
TimeZone();
|
||||
|
||||
|
||||
/*
|
||||
*/
|
||||
void Clear();
|
||||
|
||||
|
||||
/*
|
||||
reading zime zone values from Space struct (tz_id is skipped)
|
||||
the space struct should have:
|
||||
"tz_offset" (long)
|
||||
"tz_has_dst" (bool)
|
||||
if tz_has_dst is true then also:
|
||||
"tz_dst_start" date in the following format: MM:DD HH[:MM[:SS]]
|
||||
"tz_dst_end" the same as above
|
||||
"tz_dst_offset" (long)
|
||||
*/
|
||||
bool SetTz(PT::Space & space);
|
||||
|
||||
|
||||
/*
|
||||
converting from UTC to local time
|
||||
*/
|
||||
time_t CalcLocalOffset(const PT::Date & utc_date);
|
||||
time_t ToLocal(time_t utc_time);
|
||||
PT::Date ToLocal(const PT::Date & utc_date);
|
||||
|
||||
|
||||
/*
|
||||
converting from local time to UTC
|
||||
*/
|
||||
time_t CalcUTCOffset(const PT::Date & local_date);
|
||||
time_t ToUTC(time_t local_time);
|
||||
PT::Date ToUTC(const PT::Date & local_date);
|
||||
|
||||
// return a Dst structure for the specified year
|
||||
// or null if it not exists
|
||||
// this method can return a Dst structure for earlier year than 'year'
|
||||
// if 'year' doesn't exist
|
||||
Dst * FindDst(int year);
|
||||
|
||||
|
||||
|
||||
// a time zone name
|
||||
// this is a key to locale
|
||||
std::wstring name;
|
||||
|
||||
// each locale has its own identifier
|
||||
size_t id;
|
||||
|
||||
// time zone offset (in seconds)
|
||||
time_t offset;
|
||||
|
||||
// daylight saving time map
|
||||
// year -> Dst
|
||||
// if there is not a specified year we are taking the lower year, e.g.
|
||||
// if we are looking for 2010 and there is no such a year then we take 2009
|
||||
// (or 2008 if 2009 not exists etc)
|
||||
typedef std::map<int, Dst> DstMap;
|
||||
DstMap dst_map;
|
||||
|
||||
|
||||
|
||||
private:
|
||||
|
||||
time_t ParseStrOffset(const wchar_t * str);
|
||||
time_t GetOffset(PT::Space & space);
|
||||
bool SetTzDst(PT::Space & year);
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
178
core/timezones.cpp
Normal file
178
core/timezones.cpp
Normal file
@@ -0,0 +1,178 @@
|
||||
/*
|
||||
* This file is a part of Winix
|
||||
* and is not publicly distributed
|
||||
*
|
||||
* Copyright (c) 2012, Tomasz Sowa
|
||||
* All rights reserved.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "timezones.h"
|
||||
#include "misc.h"
|
||||
#include "log.h"
|
||||
|
||||
|
||||
|
||||
TimeZones::TimeZones()
|
||||
{
|
||||
Clear();
|
||||
}
|
||||
|
||||
|
||||
void TimeZones::Clear()
|
||||
{
|
||||
zone_tab.clear();
|
||||
|
||||
for(size_t i=0 ; i<zone_indices.size() ; ++i)
|
||||
zone_indices[i] = size_t(-1);
|
||||
}
|
||||
|
||||
|
||||
void TimeZones::SetTimeZoneMaxId(size_t max_id)
|
||||
{
|
||||
if( max_id > 1000 )
|
||||
{
|
||||
max_id = 1000;
|
||||
log << log1 << "TZ: time_zone_max_id is too big (changed to 1000)" << logend;
|
||||
}
|
||||
|
||||
size_t old_size = zone_indices.size();
|
||||
zone_indices.resize(max_id + 1);
|
||||
|
||||
for(size_t i=old_size ; i<zone_indices.size() ; ++i)
|
||||
zone_indices[i] = size_t(-1);
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool TimeZones::HasZone(size_t zone_id)
|
||||
{
|
||||
if( zone_id < zone_indices.size() )
|
||||
return zone_indices[zone_id] < zone_tab.size();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
TimeZone * TimeZones::GetZone(size_t zone_id)
|
||||
{
|
||||
if( zone_id < zone_indices.size() )
|
||||
{
|
||||
size_t index = zone_indices[zone_id];
|
||||
|
||||
if( index < zone_tab.size() )
|
||||
return &zone_tab[index];
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
TimeZone * TimeZones::GetZoneByIndex(size_t zone_index)
|
||||
{
|
||||
if( zone_index < zone_tab.size() )
|
||||
return &zone_tab[zone_index];
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
size_t TimeZones::Size() const
|
||||
{
|
||||
return zone_tab.size();
|
||||
}
|
||||
|
||||
|
||||
bool TimeZones::Empty() const
|
||||
{
|
||||
return zone_tab.empty();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void TimeZones::ParseZones()
|
||||
{
|
||||
for(size_t i=0 ; i<temp_space.spaces.size() ; ++i)
|
||||
{
|
||||
PT::Space & zone = *temp_space.spaces[i];
|
||||
temp_zone.Clear();
|
||||
|
||||
if( temp_zone.SetTz(zone) )
|
||||
{
|
||||
if( !HasZone(temp_zone.id) )
|
||||
{
|
||||
if( temp_zone.id < zone_indices.size() )
|
||||
{
|
||||
zone_tab.push_back(temp_zone);
|
||||
zone_indices[temp_zone.id] = zone_tab.size() - 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
log << log1 << "Tz: zone: " << temp_zone.name << " has too big id: "
|
||||
<< temp_zone.id << " (skipping)" << logend;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
log << log1 << "Tz: zone with id: " << temp_zone.id
|
||||
<< " already exists (skipping)" << logend;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
log << log1 << "System: problem with reading time zone info from time zone: "
|
||||
<< zone.name << " (skipping) " << logend;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// !! IMPROVE ME
|
||||
// in the future we do not have to read the whole file
|
||||
// just space by space (not implemented in Space at the moment)
|
||||
bool TimeZones::ReadTimeZones(const wchar_t * path)
|
||||
{
|
||||
parser.UTF8(true);
|
||||
parser.SetSpace(temp_space);
|
||||
zone_tab.clear();
|
||||
temp_space.Clear();
|
||||
|
||||
PT::SpaceParser::Status status = parser.Parse(path);
|
||||
|
||||
if( status == PT::SpaceParser::ok )
|
||||
{
|
||||
ParseZones();
|
||||
log << log2 << "Tz: time zones loaded, there are " << zone_tab.size() << " zones" << logend;
|
||||
}
|
||||
else
|
||||
if( status == PT::SpaceParser::syntax_error )
|
||||
{
|
||||
log << log1 << "TZ: error in time zone file, line: " << parser.line << logend;
|
||||
}
|
||||
else
|
||||
if( status == PT::SpaceParser::cant_open_file )
|
||||
{
|
||||
log << log1 << "TZ: I cannot open the time zone file: " << path << logend;
|
||||
}
|
||||
|
||||
temp_space.Clear();
|
||||
|
||||
return status == PT::SpaceParser::ok;
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool TimeZones::ReadTimeZones(const std::wstring & path)
|
||||
{
|
||||
return ReadTimeZones(path.c_str());
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
81
core/timezones.h
Normal file
81
core/timezones.h
Normal file
@@ -0,0 +1,81 @@
|
||||
/*
|
||||
* This file is a part of Winix
|
||||
* and is not publicly distributed
|
||||
*
|
||||
* Copyright (c) 2012, Tomasz Sowa
|
||||
* All rights reserved.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef headerfile_winix_core_timezones
|
||||
#define headerfile_winix_core_timezones
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include "timezone.h"
|
||||
#include "space/spaceparser.h"
|
||||
|
||||
|
||||
|
||||
class TimeZones
|
||||
{
|
||||
public:
|
||||
|
||||
TimeZones();
|
||||
|
||||
// maximum allowed time zone's identifier
|
||||
void SetTimeZoneMaxId(size_t max_id);
|
||||
|
||||
// reading time zone from a file
|
||||
bool ReadTimeZones(const wchar_t * path);
|
||||
bool ReadTimeZones(const std::wstring & path);
|
||||
|
||||
// returning true if there is a time zone with the zone_id identifier
|
||||
bool HasZone(size_t zone_id);
|
||||
|
||||
// returning a time zone by time zone's identifier
|
||||
// can return a null pointer if there is no such a zone
|
||||
TimeZone * GetZone(size_t zone_id);
|
||||
|
||||
// returning the number of all time zones
|
||||
size_t Size() const;
|
||||
|
||||
// returning a time zone by an internal index
|
||||
// usuful for iterating through all zones
|
||||
// this index is in a range of <0, Size()-1>
|
||||
// can return a null pointer if the index is out of range
|
||||
TimeZone * GetZoneByIndex(size_t zone_index);
|
||||
|
||||
// return true if there are not any time zones
|
||||
bool Empty() const;
|
||||
|
||||
// clears all time zones
|
||||
// this does not affect SetTimeZoneMaxId()
|
||||
// so the size of zone_indices is not changed but all indices are invalidated
|
||||
void Clear();
|
||||
|
||||
|
||||
private:
|
||||
|
||||
// indices to 'tab'
|
||||
// with this we have O(1) time to find a time zone in 'tab'
|
||||
// everywhere we use zone_id we refer to this table
|
||||
// SetTimeZoneMaxId(size_t max_id) sets size of this table to max_id+1
|
||||
std::vector<size_t> zone_indices;
|
||||
|
||||
// time zones
|
||||
// everywhere we use zone_index we refer to this table
|
||||
std::vector<TimeZone> zone_tab;
|
||||
|
||||
PT::SpaceParser parser;
|
||||
PT::Space temp_space;
|
||||
TimeZone temp_zone;
|
||||
|
||||
void ParseZones();
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
@@ -2,7 +2,7 @@
|
||||
* This file is a part of Winix
|
||||
* and is not publicly distributed
|
||||
*
|
||||
* Copyright (c) 2008-2010, Tomasz Sowa
|
||||
* Copyright (c) 2008-2012, Tomasz Sowa
|
||||
* All rights reserved.
|
||||
*
|
||||
*/
|
||||
@@ -10,10 +10,8 @@
|
||||
#ifndef headerfile_winix_core_ugcontainer
|
||||
#define headerfile_winix_core_ugcontainer
|
||||
|
||||
#include <vector>
|
||||
#include <list>
|
||||
#include <map>
|
||||
#include <stdexcept>
|
||||
|
||||
#include "log.h"
|
||||
|
||||
|
||||
@@ -21,17 +19,18 @@
|
||||
template<class Type>
|
||||
class UGContainer
|
||||
{
|
||||
|
||||
public:
|
||||
typedef typename std::vector<Type> Table;
|
||||
typedef typename Table::iterator Iterator;
|
||||
typedef typename Table::size_type SizeType;
|
||||
|
||||
typedef typename std::map<long, SizeType> TableId;
|
||||
typedef typename std::map<std::wstring, SizeType> TableName;
|
||||
|
||||
|
||||
UGContainer();
|
||||
~UGContainer();
|
||||
|
||||
typedef typename std::list<Type> Table;
|
||||
typedef typename Table::iterator Iterator;
|
||||
typedef typename Table::size_type SizeType;
|
||||
|
||||
typedef typename std::map<long, Iterator> TableId;
|
||||
typedef typename std::map<std::wstring, Iterator> TableName;
|
||||
|
||||
|
||||
Iterator Begin();
|
||||
Iterator End();
|
||||
@@ -46,17 +45,25 @@ public:
|
||||
Iterator FindId(long id);
|
||||
Iterator FindName(const std::wstring & name);
|
||||
|
||||
Type & operator[](SizeType pos);
|
||||
bool Remove(long id);
|
||||
|
||||
|
||||
|
||||
private:
|
||||
|
||||
void AddIndexes(SizeType pos);
|
||||
// don't copy these objects
|
||||
UGContainer(const UGContainer<Type> &);
|
||||
UGContainer<Type> & operator=(const UGContainer<Type> &);
|
||||
|
||||
void AddIndexes(Iterator iter);
|
||||
void RebuildIndexes();
|
||||
|
||||
// main table
|
||||
Table table;
|
||||
|
||||
// table.size() has O(n) complexity
|
||||
size_t table_size;
|
||||
|
||||
// indexes
|
||||
TableId table_id;
|
||||
TableName table_name;
|
||||
@@ -65,8 +72,32 @@ private:
|
||||
|
||||
|
||||
template<class Type>
|
||||
UGContainer<Type>::UGContainer() // : table(100)
|
||||
UGContainer<Type>::~UGContainer()
|
||||
{
|
||||
Clear();
|
||||
}
|
||||
|
||||
|
||||
template<class Type>
|
||||
UGContainer<Type>::UGContainer()
|
||||
{
|
||||
Clear();
|
||||
}
|
||||
|
||||
|
||||
// is private
|
||||
template<class Type>
|
||||
UGContainer<Type>::UGContainer(const UGContainer<Type> &)
|
||||
{
|
||||
Clear();
|
||||
}
|
||||
|
||||
// is private
|
||||
template<class Type>
|
||||
UGContainer<Type> & UGContainer<Type>::operator=(const UGContainer<Type> &)
|
||||
{
|
||||
Clear();
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
@@ -89,7 +120,7 @@ typename UGContainer<Type>::Iterator UGContainer<Type>::End()
|
||||
template<class Type>
|
||||
typename UGContainer<Type>::SizeType UGContainer<Type>::Size()
|
||||
{
|
||||
return table.size();
|
||||
return table_size;
|
||||
}
|
||||
|
||||
|
||||
@@ -109,11 +140,12 @@ typename UGContainer<Type>::Iterator UGContainer<Type>::PushBack(const Type & ty
|
||||
return End();
|
||||
|
||||
table.push_back(type);
|
||||
log << log2 << "UGCont: added, id: " << type.id << ", name: " << type.name << logend;
|
||||
|
||||
AddIndexes( table.size() - 1 );
|
||||
table_size += 1;
|
||||
Iterator i = --table.end();
|
||||
log << log3 << "UGCont: added, id: " << type.id << ", name: " << type.name << logend;
|
||||
AddIndexes(i);
|
||||
|
||||
return --table.end();
|
||||
return i;
|
||||
}
|
||||
|
||||
|
||||
@@ -121,6 +153,7 @@ return --table.end();
|
||||
template<class Type>
|
||||
void UGContainer<Type>::Clear()
|
||||
{
|
||||
table_size = 0;
|
||||
table.clear();
|
||||
table_id.clear();
|
||||
table_name.clear();
|
||||
@@ -161,7 +194,7 @@ typename UGContainer<Type>::Iterator UGContainer<Type>::FindId(long id)
|
||||
if( i == table_id.end() )
|
||||
return table.end();
|
||||
|
||||
return table.begin() + i->second;
|
||||
return i->second;
|
||||
}
|
||||
|
||||
|
||||
@@ -174,18 +207,18 @@ typename UGContainer<Type>::Iterator UGContainer<Type>::FindName(const std::wstr
|
||||
if( i == table_name.end() )
|
||||
return table.end();
|
||||
|
||||
return table.begin() + i->second;
|
||||
return i->second;
|
||||
}
|
||||
|
||||
|
||||
|
||||
template<class Type>
|
||||
void UGContainer<Type>::AddIndexes(UGContainer<Type>::SizeType pos)
|
||||
void UGContainer<Type>::AddIndexes(UGContainer<Type>::Iterator iter)
|
||||
{
|
||||
table_id.insert( std::make_pair(table[pos].id, pos) );
|
||||
table_name.insert( std::make_pair(table[pos].name, pos) );
|
||||
table_id.insert( std::make_pair(iter->id, iter) );
|
||||
table_name.insert( std::make_pair(iter->name, iter) );
|
||||
|
||||
log << log4 << "UGCont: added indexes to: id: " << table[pos].id << ", name: " << table[pos].name << logend;
|
||||
log << log4 << "UGCont: added indexes to: id: " << iter->id << ", name: " << iter->name << logend;
|
||||
}
|
||||
|
||||
|
||||
@@ -193,30 +226,51 @@ void UGContainer<Type>::AddIndexes(UGContainer<Type>::SizeType pos)
|
||||
template<class Type>
|
||||
void UGContainer<Type>::RebuildIndexes()
|
||||
{
|
||||
Iterator i;
|
||||
|
||||
log << log4 << "UGCont: rebuilding indexes" << logend;
|
||||
|
||||
table_id.clear();
|
||||
table_name.clear();
|
||||
|
||||
SizeType i, len = table.size();
|
||||
|
||||
|
||||
for(i=0 ; i!=len ; ++i)
|
||||
AddIndexes( i );
|
||||
|
||||
for(i=table.begin() ; i!=table.end() ; ++i)
|
||||
AddIndexes(i);
|
||||
|
||||
log << log4 << "UGCont: indexes rebuilt, table.size: " << table.size() << ", table_id.size: "
|
||||
log << log4 << "UGCont: indexes rebuilt, table.size: " << table_size << ", table_id.size: "
|
||||
<< table_id.size() << ", table_name.size: " << table_name.size() << logend;
|
||||
}
|
||||
|
||||
|
||||
|
||||
template<class Type>
|
||||
Type & UGContainer<Type>::operator[](UGContainer<Type>::SizeType pos)
|
||||
{
|
||||
if( pos >= table.size() )
|
||||
throw std::out_of_range("UGContainer: operator[]: index is out of range");
|
||||
|
||||
return table[pos];
|
||||
|
||||
template<class Type>
|
||||
bool UGContainer<Type>::Remove(long id)
|
||||
{
|
||||
typename TableId::iterator i = table_id.find(id);
|
||||
typename TableName::iterator n;
|
||||
bool result = false;
|
||||
|
||||
if( i != table_id.end() )
|
||||
{
|
||||
for(n=table_name.begin() ; n != table_name.end() ; ++n)
|
||||
{
|
||||
if( n->second == i->second )
|
||||
{
|
||||
table_name.erase(n);
|
||||
log << log4 << "UGCont: removed index_id to: id: " << i->second->id << ", name: " << i->second->name << logend;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
log << log4 << "UGCont: removed index_name to: id: " << i->second->id << ", name: " << i->second->name << logend;
|
||||
log << log3 << "UGCont: removed: id: " << i->second->id << ", name: " << i->second->name << logend;
|
||||
table.erase(i->second);
|
||||
table_id.erase(i);
|
||||
result = true;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
65
core/user.cpp
Executable file
65
core/user.cpp
Executable file
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
* This file is a part of Winix
|
||||
* and is not publicly distributed
|
||||
*
|
||||
* Copyright (c) 2012, Tomasz Sowa
|
||||
* All rights reserved.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "user.h"
|
||||
|
||||
|
||||
User::User()
|
||||
{
|
||||
Clear();
|
||||
}
|
||||
|
||||
|
||||
void User::Clear()
|
||||
{
|
||||
id = -1;
|
||||
name.clear();
|
||||
super_user = false;
|
||||
groups.clear();
|
||||
email.clear();
|
||||
notify = 0;
|
||||
env.Clear();
|
||||
aenv.Clear();
|
||||
status = WINIX_ACCOUNT_BLOCKED;
|
||||
locale_id = 0;
|
||||
time_zone_id = 0;
|
||||
}
|
||||
|
||||
|
||||
bool User::IsMemberOf(long group)
|
||||
{
|
||||
std::vector<long>::iterator i;
|
||||
|
||||
for(i=groups.begin() ; i!=groups.end() ; ++i)
|
||||
if( *i == group )
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
95
core/user.h
95
core/user.h
@@ -2,7 +2,7 @@
|
||||
* This file is a part of Winix
|
||||
* and is not publicly distributed
|
||||
*
|
||||
* Copyright (c) 2008-2011, Tomasz Sowa
|
||||
* Copyright (c) 2008-2012, Tomasz Sowa
|
||||
* All rights reserved.
|
||||
*
|
||||
*/
|
||||
@@ -12,8 +12,45 @@
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include "space/space.h"
|
||||
#include "date/date.h"
|
||||
|
||||
|
||||
#define WINIX_ACCOUNT_MAX_LOGIN_SIZE 250
|
||||
#define WINIX_ACCOUNT_MAX_PASSWORD_SIZE 250
|
||||
#define WINIX_ACCOUNT_MAX_EMAIL_SIZE 250
|
||||
|
||||
|
||||
|
||||
// account status
|
||||
// 1 - a user has created its account -- an email was sent back to him
|
||||
#define WINIX_ACCOUNT_NOT_ACTIVATED 1
|
||||
|
||||
// 2 - a user clicked on the link in the mail and now can normally use his account
|
||||
#define WINIX_ACCOUNT_READY 2
|
||||
|
||||
// 3 - account was suspended
|
||||
#define WINIX_ACCOUNT_SUSPENDED 3
|
||||
|
||||
// 4 - account was banned
|
||||
#define WINIX_ACCOUNT_BLOCKED 4
|
||||
|
||||
|
||||
/*
|
||||
a user can login only to an account which status is equal to WINIX_ACCOUNT_READY
|
||||
|
||||
actually there is no difference between WINIX_ACCOUNT_SUSPENDED and WINIX_ACCOUNT_BANNED
|
||||
only a different message will be present on the website
|
||||
|
||||
you can use other values of status in your plugins - this not have any impact on winix
|
||||
the default 'login' winix function only allowes to login a user who has WINIX_ACCOUNT_READY value
|
||||
but you can provide your own 'login' function which can work in a different way
|
||||
|
||||
winix knows that user is login when cur->session->puser pointer is set
|
||||
(when the pointer is not null then winix do not check what the value of 'status' is --
|
||||
the status is only tested in 'login' function)
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
a temporary struct used for hashing and encrypting a user's password
|
||||
@@ -38,41 +75,33 @@ struct User
|
||||
int notify;
|
||||
|
||||
|
||||
// !! currently all users have the same offset
|
||||
// option in config: time_zone_offset
|
||||
int time_zone_offset;
|
||||
|
||||
// environment variables which can be set by this user
|
||||
// use 'env' winix function
|
||||
PT::Space env;
|
||||
|
||||
// environment variables set only by an administrator
|
||||
// an administrator can use 'env' winix function with 'a' parameter
|
||||
PT::Space aenv;
|
||||
|
||||
// account status
|
||||
// WINIX_ACCOUNT_*
|
||||
// a user can normally login only when status is WINIX_ACCOUNT_READY
|
||||
int status;
|
||||
|
||||
// locale identifier
|
||||
size_t locale_id;
|
||||
|
||||
// time zone identifier
|
||||
size_t time_zone_id;
|
||||
|
||||
|
||||
User()
|
||||
{
|
||||
Clear();
|
||||
}
|
||||
|
||||
|
||||
void Clear()
|
||||
{
|
||||
id = -1;
|
||||
name.clear();
|
||||
super_user = false;
|
||||
groups.clear();
|
||||
email.clear();
|
||||
notify = 0;
|
||||
time_zone_offset = 0;
|
||||
}
|
||||
|
||||
|
||||
bool IsMemberOf(long group)
|
||||
{
|
||||
std::vector<long>::iterator i;
|
||||
|
||||
for(i=groups.begin() ; i!=groups.end() ; ++i)
|
||||
if( *i == group )
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
User();
|
||||
|
||||
void Clear();
|
||||
bool IsMemberOf(long group);
|
||||
bool ReadMonthDayTime(PT::Date & date, const wchar_t * str);
|
||||
bool SetTzFromEnv();
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
155
core/users.cpp
155
core/users.cpp
@@ -2,19 +2,21 @@
|
||||
* This file is a part of Winix
|
||||
* and is not publicly distributed
|
||||
*
|
||||
* Copyright (c) 2008-2010, Tomasz Sowa
|
||||
* Copyright (c) 2008-2012, Tomasz Sowa
|
||||
* All rights reserved.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <arpa/inet.h>
|
||||
#include "users.h"
|
||||
#include "sessionmanager.h"
|
||||
#include "plugin.h"
|
||||
|
||||
|
||||
|
||||
Users::Users()
|
||||
{
|
||||
how_many_logged = 0;
|
||||
how_many_logged = 0; // !! CHECK ME may it should be moved to Clear() method?
|
||||
Clear();
|
||||
}
|
||||
|
||||
@@ -25,6 +27,12 @@ void Users::SetCur(Cur * pcur)
|
||||
}
|
||||
|
||||
|
||||
void Users::SetSessionManager(SessionManager * sm)
|
||||
{
|
||||
session_manager = sm;
|
||||
}
|
||||
|
||||
|
||||
void Users::Clear()
|
||||
{
|
||||
table.Clear();
|
||||
@@ -39,15 +47,6 @@ void Users::ReadUsers(Db * db)
|
||||
}
|
||||
|
||||
|
||||
void Users::SetTimeZoneOffset(int offset)
|
||||
{
|
||||
Table::Iterator i;
|
||||
|
||||
for(i=table.Begin() ; i!=table.End() ; ++i)
|
||||
{
|
||||
i->time_zone_offset = offset;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool Users::AddUser(const User & user)
|
||||
@@ -119,42 +118,145 @@ Users::SizeType Users::Size()
|
||||
}
|
||||
|
||||
|
||||
|
||||
User & Users::operator[](Users::SizeType pos)
|
||||
bool Users::Remove(long user_id)
|
||||
{
|
||||
return table[pos];
|
||||
bool result = false;
|
||||
User * puser = GetUser(user_id);
|
||||
|
||||
if( puser )
|
||||
{
|
||||
LogoutUser(user_id);
|
||||
plugin.Call(WINIX_PREPARE_TO_REMOVE_USER, puser);
|
||||
result = table.Remove(user_id);
|
||||
|
||||
if( result )
|
||||
plugin.Call(WINIX_USER_REMOVED, user_id);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
void Users::LoginUser(long user_id, bool remember_me)
|
||||
// private
|
||||
bool Users::LoginUserCheckSession(bool use_ses_log)
|
||||
{
|
||||
if( !cur->session )
|
||||
return;
|
||||
return false;
|
||||
|
||||
if( cur->session->id == 0 )
|
||||
{
|
||||
log << log1 << "Users: cannot login a user on a temporary session" << logend;
|
||||
return;
|
||||
log << log1 << "Users: I cannot login a user on a temporary session" << logend;
|
||||
|
||||
if( use_ses_log )
|
||||
slog << logerror << T(L"service_unavailable") << logend;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
cur->session->puser = GetUser(user_id);
|
||||
cur->session->spam_score = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
if( !cur->session->puser )
|
||||
|
||||
// private
|
||||
User * Users::LoginUserCheckStatus(long user_id, bool use_ses_log)
|
||||
{
|
||||
User * puser = GetUser(user_id);
|
||||
|
||||
if( !puser )
|
||||
{
|
||||
log << log1 << "Users: user id: " << user_id << " is not in system.users table" << logend;
|
||||
return;
|
||||
log << log1 << "Users: user id: " << user_id << " is not in system.users table" << logend;
|
||||
|
||||
if( use_ses_log )
|
||||
slog << logerror << T(L"service_unavailable") << logend;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
if( puser->status != WINIX_ACCOUNT_READY )
|
||||
{
|
||||
log << log1 << "Users: user id: " << user_id << " is not ready for logging in (status: "
|
||||
<< puser->status << ")" << logend;
|
||||
|
||||
if( use_ses_log )
|
||||
{
|
||||
if( puser->status == WINIX_ACCOUNT_NOT_ACTIVATED )
|
||||
slog << logerror << T(L"account_not_activated") << logend;
|
||||
else
|
||||
if( puser->status == WINIX_ACCOUNT_SUSPENDED )
|
||||
slog << logerror << T(L"account_suspended") << logend;
|
||||
else
|
||||
if( puser->status == WINIX_ACCOUNT_BLOCKED )
|
||||
slog << logerror << T(L"account_banned") << logend;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
return puser;
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool Users::LoginUser(long user_id, bool remember_me, bool use_ses_log)
|
||||
{
|
||||
if( !LoginUserCheckSession(use_ses_log) )
|
||||
return false;
|
||||
|
||||
User * puser = LoginUserCheckStatus(user_id, use_ses_log);
|
||||
|
||||
if( !puser )
|
||||
return false;
|
||||
|
||||
PluginRes res = plugin.Call(WINIX_PREPARE_USER_TO_LOGIN, puser);
|
||||
|
||||
if( res.res_false > 0 )
|
||||
{
|
||||
log << log3 << "Users: login prevented by a plugin" << logend;
|
||||
return false;
|
||||
}
|
||||
|
||||
if( cur->session->puser )
|
||||
LogoutCurrentUser();
|
||||
|
||||
cur->session->puser = puser;
|
||||
cur->session->spam_score = 0;
|
||||
cur->session->remember_me = remember_me;
|
||||
|
||||
// change session id before last.UserLogin()
|
||||
if( !cur->session->new_session )
|
||||
session_manager->ChangeSessionId(cur->session->id);
|
||||
|
||||
last.UserLogin(user_id, cur->session->puser->name, inet_addr(cur->request->env_remote_addr), cur->session->id);
|
||||
how_many_logged += 1;
|
||||
|
||||
log << log2 << "User " << cur->session->puser->name << " (id: " << user_id << ") logged" << logend;
|
||||
log << log2 << "Users: user " << cur->session->puser->name << " (id: " << user_id << ") logged" << logend;
|
||||
plugin.Call(WINIX_USER_LOGGED);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
size_t Users::LogoutUser(long user_id)
|
||||
{
|
||||
size_t how_many = 0;
|
||||
User * puser = GetUser(user_id);
|
||||
|
||||
if( puser )
|
||||
{
|
||||
log << log2 << "Users: logging out user " << puser->name << ", id: "
|
||||
<< puser->id << " from all sessions" << logend;
|
||||
|
||||
// WINIX_PREPARE_USER_TO_LOGOUT will be sent by MarkAllSessionsToRemove()
|
||||
how_many = session_manager->MarkAllSessionsToRemove(user_id);
|
||||
how_many_logged -= how_many;
|
||||
|
||||
if( how_many )
|
||||
log << log3 << "Users: " << how_many << " user(s) were logged out" << logend;
|
||||
}
|
||||
|
||||
return how_many;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void Users::LogoutCurrentUser()
|
||||
@@ -165,13 +267,14 @@ void Users::LogoutCurrentUser()
|
||||
log << log2 << "Users: user " << cur->session->puser->name << ", id: "
|
||||
<< cur->session->puser->id << " logged out" << logend;
|
||||
|
||||
plugin.Call(WINIX_PREPARE_USER_TO_LOGOUT, cur->session->puser);
|
||||
last.UserLogout(cur->session->puser->id, cur->session->id);
|
||||
|
||||
if( how_many_logged > 0 ) // for safety
|
||||
how_many_logged -= 1;
|
||||
|
||||
cur->session->puser = 0;
|
||||
cur->session->remember_me = 0;
|
||||
cur->session->remember_me = false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
31
core/users.h
31
core/users.h
@@ -2,7 +2,7 @@
|
||||
* This file is a part of Winix
|
||||
* and is not publicly distributed
|
||||
*
|
||||
* Copyright (c) 2008-2010, Tomasz Sowa
|
||||
* Copyright (c) 2008-2012, Tomasz Sowa
|
||||
* All rights reserved.
|
||||
*
|
||||
*/
|
||||
@@ -17,14 +17,12 @@
|
||||
#include "cur.h"
|
||||
#include "db/db.h"
|
||||
|
||||
class SessionManager;
|
||||
|
||||
|
||||
class Users
|
||||
{
|
||||
typedef UGContainer<User> Table;
|
||||
Table table;
|
||||
|
||||
Cur * cur;
|
||||
long how_many_logged;
|
||||
typedef UGContainer<User> Table;
|
||||
|
||||
public:
|
||||
|
||||
@@ -36,10 +34,10 @@ public:
|
||||
Users();
|
||||
|
||||
void SetCur(Cur * pcur);
|
||||
void SetSessionManager(SessionManager * sm);
|
||||
|
||||
void Clear();
|
||||
void ReadUsers(Db * db);
|
||||
void SetTimeZoneOffset(int offset); // !! temporarily one time_zone for all users
|
||||
bool AddUser(const User & user);
|
||||
bool IsUser(const std::wstring & name);
|
||||
User * GetUser(long user_id);
|
||||
@@ -48,13 +46,26 @@ public:
|
||||
Iterator Begin();
|
||||
Iterator End();
|
||||
SizeType Size();
|
||||
User & operator[](SizeType pos);
|
||||
bool Remove(long user_id);
|
||||
|
||||
void LoginUser(long user_id, bool remember_me);
|
||||
void LogoutCurrentUser();
|
||||
bool LoginUser(long user_id, bool remember_me, bool use_ses_log = false);
|
||||
size_t LogoutUser(long user_id);
|
||||
void LogoutCurrentUser();
|
||||
|
||||
void IncrementLoggedUsers();
|
||||
long HowManyLogged();
|
||||
|
||||
|
||||
private:
|
||||
|
||||
Table table;
|
||||
Cur * cur;
|
||||
SessionManager * session_manager;
|
||||
long how_many_logged;
|
||||
|
||||
bool LoginUserCheckSession(bool use_ses_log);
|
||||
User * LoginUserCheckStatus(long user_id, bool use_ses_log);
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* This file is a part of Winix
|
||||
* and is not publicly distributed
|
||||
*
|
||||
* Copyright (c) 2008-2011, Tomasz Sowa
|
||||
* Copyright (c) 2008-2012, Tomasz Sowa
|
||||
* All rights reserved.
|
||||
*
|
||||
*/
|
||||
@@ -12,8 +12,8 @@
|
||||
|
||||
|
||||
#define WINIX_VER_MAJOR 0
|
||||
#define WINIX_VER_MINOR 4
|
||||
#define WINIX_VER_REVISION 8
|
||||
#define WINIX_VER_MINOR 5
|
||||
#define WINIX_VER_REVISION 2
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
@@ -9,7 +9,7 @@ all: $(o)
|
||||
|
||||
|
||||
depend:
|
||||
makedepend -Y. -I.. -I../../ezc/src -f- *.cpp > Makefile.dep
|
||||
makedepend -Y. -I.. -I../../ezc/src -I../../pikotools -I../../tito/src -f- *.cpp > Makefile.dep
|
||||
echo -n "o = " > Makefile.o.dep
|
||||
ls -1 *.cpp | xargs -I foo echo -n foo " " | sed -E "s/([^\.]*)\.cpp[ ]/\1\.o/g" >> Makefile.o.dep
|
||||
|
||||
|
||||
@@ -1,23 +1,62 @@
|
||||
# DO NOT DELETE
|
||||
|
||||
db.o: db.h dbbase.h dbconn.h dbtextstream.h ../core/textstream.h
|
||||
db.o: ../core/misc.h ../core/item.h ../core/error.h dbitemquery.h
|
||||
db.o: ../core/item.h dbitemcolumns.h ../core/user.h ../core/group.h
|
||||
db.o: ../core/dircontainer.h ../core/ugcontainer.h ../core/log.h
|
||||
db.o: ../core/textstream.h ../core/logmanipulators.h ../core/slog.h
|
||||
db.o: ../core/cur.h ../core/request.h ../core/requesttypes.h ../core/error.h
|
||||
db.o: ../core/config.h ../core/confparser.h ../core/htmlfilter.h
|
||||
db.o: ../templates/htmltextstream.h ../core/session.h ../core/user.h
|
||||
db.o: ../core/plugindata.h ../core/rebus.h ../templates/locale.h
|
||||
db.o: ../core/confparser.h ../core/log.h ../core/misc.h
|
||||
db.o: ../core/misc.h ../core/item.h ../../pikotools/space/space.h
|
||||
db.o: ../../pikotools/textstream/types.h ../../pikotools/date/date.h
|
||||
db.o: ../core/requesttypes.h ../../pikotools/textstream/textstream.h
|
||||
db.o: ../../pikotools/convert/convert.h ../../pikotools/convert/inttostr.h
|
||||
db.o: ../../pikotools/membuffer/membuffer.h
|
||||
db.o: ../../pikotools/textstream/types.h ../../pikotools/utf8/utf8.h
|
||||
db.o: ../core/error.h ../../pikotools/space/spaceparser.h
|
||||
db.o: ../../pikotools/space/space.h dbitemquery.h ../core/item.h
|
||||
db.o: dbitemcolumns.h ../core/user.h ../core/group.h ../core/dircontainer.h
|
||||
db.o: ../core/ugcontainer.h ../core/log.h ../core/textstream.h
|
||||
db.o: ../core/logmanipulators.h ../core/slog.h ../core/cur.h
|
||||
db.o: ../core/request.h ../core/error.h ../core/config.h ../core/htmlfilter.h
|
||||
db.o: ../templates/htmltextstream.h ../../pikotools/space/spacetojson.h
|
||||
db.o: ../core/session.h ../core/user.h ../core/plugindata.h ../core/rebus.h
|
||||
db.o: ../core/ipban.h ../core/mount.h ../templates/locale.h ../core/log.h
|
||||
db.o: ../core/misc.h
|
||||
dbbase.o: dbbase.h dbconn.h dbtextstream.h ../core/textstream.h
|
||||
dbbase.o: ../core/misc.h ../core/item.h ../core/error.h ../core/log.h
|
||||
dbbase.o: ../core/misc.h ../../ezc/src/utf8.h
|
||||
dbbase.o: ../core/misc.h ../core/item.h ../../pikotools/space/space.h
|
||||
dbbase.o: ../../pikotools/textstream/types.h ../../pikotools/date/date.h
|
||||
dbbase.o: ../core/requesttypes.h ../../pikotools/textstream/textstream.h
|
||||
dbbase.o: ../../pikotools/convert/convert.h
|
||||
dbbase.o: ../../pikotools/convert/inttostr.h
|
||||
dbbase.o: ../../pikotools/membuffer/membuffer.h
|
||||
dbbase.o: ../../pikotools/textstream/types.h ../../pikotools/utf8/utf8.h
|
||||
dbbase.o: ../core/error.h ../../pikotools/space/spaceparser.h
|
||||
dbbase.o: ../../pikotools/space/space.h ../core/log.h ../core/misc.h
|
||||
dbconn.o: dbconn.h dbtextstream.h ../core/textstream.h ../core/misc.h
|
||||
dbconn.o: ../core/item.h ../core/log.h ../core/error.h
|
||||
dbconn.o: ../core/item.h ../../pikotools/space/space.h
|
||||
dbconn.o: ../../pikotools/textstream/types.h ../../pikotools/date/date.h
|
||||
dbconn.o: ../core/requesttypes.h ../../pikotools/textstream/textstream.h
|
||||
dbconn.o: ../../pikotools/convert/convert.h
|
||||
dbconn.o: ../../pikotools/convert/inttostr.h
|
||||
dbconn.o: ../../pikotools/membuffer/membuffer.h
|
||||
dbconn.o: ../../pikotools/textstream/types.h ../../pikotools/utf8/utf8.h
|
||||
dbconn.o: ../core/log.h ../core/error.h
|
||||
dbitemcolumns.o: dbitemcolumns.h ../core/item.h dbbase.h dbconn.h
|
||||
dbitemcolumns.o: dbtextstream.h ../core/textstream.h ../core/misc.h
|
||||
dbitemcolumns.o: ../core/item.h ../core/error.h
|
||||
dbitemcolumns.o: ../core/item.h ../../pikotools/space/space.h
|
||||
dbitemcolumns.o: ../../pikotools/textstream/types.h
|
||||
dbitemcolumns.o: ../../pikotools/date/date.h ../core/requesttypes.h
|
||||
dbitemcolumns.o: ../../pikotools/textstream/textstream.h
|
||||
dbitemcolumns.o: ../../pikotools/convert/convert.h
|
||||
dbitemcolumns.o: ../../pikotools/convert/inttostr.h
|
||||
dbitemcolumns.o: ../../pikotools/membuffer/membuffer.h
|
||||
dbitemcolumns.o: ../../pikotools/textstream/types.h
|
||||
dbitemcolumns.o: ../../pikotools/utf8/utf8.h ../core/error.h
|
||||
dbitemcolumns.o: ../../pikotools/space/spaceparser.h
|
||||
dbitemcolumns.o: ../../pikotools/space/space.h ../core/log.h
|
||||
dbitemquery.o: dbitemquery.h ../core/item.h
|
||||
dbtextstream.o: dbtextstream.h ../core/textstream.h ../core/misc.h
|
||||
dbtextstream.o: ../core/item.h ../../ezc/src/utf8.h
|
||||
dbtextstream.o: ../core/item.h ../../pikotools/space/space.h
|
||||
dbtextstream.o: ../../pikotools/textstream/types.h
|
||||
dbtextstream.o: ../../pikotools/date/date.h ../core/requesttypes.h
|
||||
dbtextstream.o: ../../pikotools/textstream/textstream.h
|
||||
dbtextstream.o: ../../pikotools/convert/convert.h
|
||||
dbtextstream.o: ../../pikotools/convert/inttostr.h
|
||||
dbtextstream.o: ../../pikotools/membuffer/membuffer.h
|
||||
dbtextstream.o: ../../pikotools/textstream/types.h
|
||||
dbtextstream.o: ../../pikotools/utf8/utf8.h
|
||||
|
||||
348
db/db.cpp
348
db/db.cpp
@@ -2,7 +2,7 @@
|
||||
* This file is a part of Winix
|
||||
* and is not publicly distributed
|
||||
*
|
||||
* Copyright (c) 2008-2011, Tomasz Sowa
|
||||
* Copyright (c) 2008-2012, Tomasz Sowa
|
||||
* All rights reserved.
|
||||
*
|
||||
*/
|
||||
@@ -68,8 +68,7 @@ return user_ok;
|
||||
|
||||
|
||||
|
||||
Error Db::AddUser(User & user, const std::wstring & password, const std::string & password_encrypted,
|
||||
int pass_type, bool pass_hash_salted)
|
||||
Error Db::AddUser(User & user, const UserPass & up)
|
||||
{
|
||||
PGresult * r = 0;
|
||||
Error status = WINIX_ERR_OK;
|
||||
@@ -78,22 +77,28 @@ Error Db::AddUser(User & user, const std::wstring & password, const std::string
|
||||
{
|
||||
query.Clear();
|
||||
query << R("insert into core.user (login, password, pass_encrypted, super_user, email,"
|
||||
"notify, pass_type, pass_hash_salted) values (")
|
||||
"notify, pass_type, pass_hash_salted, env, aenv, status, locale_id, time_zone_id) values (")
|
||||
<< user.name;
|
||||
|
||||
// for safety
|
||||
if( password_encrypted.empty() )
|
||||
query << password;
|
||||
// for safety we put up.pass only if there is not an encrypted version
|
||||
// someone could have forgotten to clear up.pass
|
||||
if( up.pass_encrypted.empty() )
|
||||
query << up.pass;
|
||||
else
|
||||
query << "";
|
||||
|
||||
query.EPutBin(password_encrypted);
|
||||
query.EPutBin(up.pass_encrypted);
|
||||
|
||||
query << user.super_user
|
||||
<< user.email
|
||||
<< user.notify
|
||||
<< pass_type
|
||||
<< pass_hash_salted
|
||||
<< up.pass_type
|
||||
<< up.pass_hash_salted
|
||||
<< user.env
|
||||
<< user.aenv
|
||||
<< user.status
|
||||
<< user.locale_id
|
||||
<< user.time_zone_id
|
||||
<< R(");");
|
||||
|
||||
r = AssertQuery(query);
|
||||
@@ -114,7 +119,118 @@ return status;
|
||||
|
||||
|
||||
|
||||
Error Db::ChangeUserPass(long user_id, const UserPass & up)
|
||||
{
|
||||
query.Clear();
|
||||
query << R("update core.user set(password, pass_encrypted,"
|
||||
"pass_type, pass_hash_salted) = (");
|
||||
|
||||
// for safety
|
||||
if( up.pass_encrypted.empty() )
|
||||
query << up.pass;
|
||||
else
|
||||
query << "";
|
||||
|
||||
query.EPutBin(up.pass_encrypted);
|
||||
|
||||
query << up.pass_type
|
||||
<< up.pass_hash_salted
|
||||
<< R(") where id=")
|
||||
<< user_id
|
||||
<< R(";");
|
||||
|
||||
return DoCommand(query);
|
||||
}
|
||||
|
||||
|
||||
Error Db::ChangeUserEnv(long user_id, const PT::Space & space)
|
||||
{
|
||||
query.Clear();
|
||||
query << R("update core.user set(env) = (")
|
||||
<< space
|
||||
<< R(") where id = ")
|
||||
<< user_id
|
||||
<< R(";");
|
||||
|
||||
return DoCommand(query);
|
||||
}
|
||||
|
||||
|
||||
Error Db::ChangeUserAdminEnv(long user_id, const PT::Space & space)
|
||||
{
|
||||
query.Clear();
|
||||
query << R("update core.user set(aenv) = (")
|
||||
<< space
|
||||
<< R(") where id = ")
|
||||
<< user_id
|
||||
<< R(";");
|
||||
|
||||
return DoCommand(query);
|
||||
}
|
||||
|
||||
|
||||
Error Db::ChangeUserStatus(long user_id, int status)
|
||||
{
|
||||
query.Clear();
|
||||
query << R("update core.user set(status) = (")
|
||||
<< status
|
||||
<< R(") where id = ")
|
||||
<< user_id
|
||||
<< R(";");
|
||||
|
||||
return DoCommand(query);
|
||||
}
|
||||
|
||||
|
||||
|
||||
Error Db::ChangeUserEmail(long user_id, const std::wstring & email)
|
||||
{
|
||||
query.Clear();
|
||||
query << R("update core.user set(email) = (")
|
||||
<< email
|
||||
<< R(") where id = ")
|
||||
<< user_id
|
||||
<< R(";");
|
||||
|
||||
return DoCommand(query);
|
||||
}
|
||||
|
||||
|
||||
Error Db::ChangeUserLocale(long user_id, size_t locale_id)
|
||||
{
|
||||
query.Clear();
|
||||
query << R("update core.user set(locale_id) = (")
|
||||
<< locale_id
|
||||
<< R(") where id = ")
|
||||
<< user_id
|
||||
<< R(";");
|
||||
|
||||
return DoCommand(query);
|
||||
}
|
||||
|
||||
|
||||
Error Db::ChangeUserTimeZone(long user_id, size_t time_zone_id)
|
||||
{
|
||||
query.Clear();
|
||||
query << R("update core.user set(time_zone_id) = (")
|
||||
<< time_zone_id
|
||||
<< R(") where id = ")
|
||||
<< user_id
|
||||
<< R(";");
|
||||
|
||||
return DoCommand(query);
|
||||
}
|
||||
|
||||
|
||||
Error Db::RemoveUser(long user_id)
|
||||
{
|
||||
query.Clear();
|
||||
query << R("delete from core.user where id = ")
|
||||
<< user_id
|
||||
<< R(";");
|
||||
|
||||
return DoCommand(query);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -195,7 +311,7 @@ Error Db::AddItemIntoItem(Item & item)
|
||||
query.Clear();
|
||||
query << R("insert into core.item (user_id, modification_user_id, group_id, privileges, "
|
||||
"date_creation, date_modification, type, parent_id, content_id, "
|
||||
"link_to, link_redirect, subject, guest_name, template, url) values (")
|
||||
"link_to, link_redirect, subject, guest_name, template, sort_index, meta, ameta, url) values (")
|
||||
<< item.user_id
|
||||
<< item.modification_user_id
|
||||
<< item.group_id
|
||||
@@ -209,7 +325,10 @@ Error Db::AddItemIntoItem(Item & item)
|
||||
<< item.link_redirect
|
||||
<< item.subject
|
||||
<< item.guest_name
|
||||
<< item.html_template;
|
||||
<< item.html_template
|
||||
<< item.sort_index
|
||||
<< item.meta
|
||||
<< item.ameta;
|
||||
|
||||
url_without_id = AddItemCreateUrlSubject(item);
|
||||
|
||||
@@ -250,13 +369,16 @@ Error Db::AddItemIntoContent(Item & item)
|
||||
{
|
||||
query.Clear();
|
||||
query << R("insert into core.content (content, content_type, file_path, file_fs, "
|
||||
"file_type, has_thumb, ref, modify_index) values (")
|
||||
"file_type, has_thumb, hash, hash_type, file_size, ref, modify_index) values (")
|
||||
<< item.content
|
||||
<< static_cast<int>(item.content_type)
|
||||
<< item.file_path
|
||||
<< item.file_fs
|
||||
<< item.file_type
|
||||
<< static_cast<int>(item.has_thumb)
|
||||
<< item.hash
|
||||
<< item.hash_type
|
||||
<< item.file_size
|
||||
<< first_ref
|
||||
<< item.modify_index
|
||||
<< R(");");
|
||||
@@ -348,7 +470,7 @@ Error Db::EditItemInItem(Item & item, bool with_url)
|
||||
query.Clear();
|
||||
query << R("update core.item set (user_id, modification_user_id, group_id, privileges, "
|
||||
"date_creation, date_modification, type, link_to, link_redirect, parent_id, subject, "
|
||||
"guest_name, template");
|
||||
"guest_name, template, sort_index, meta, ameta");
|
||||
|
||||
if( with_url )
|
||||
query << R(", url");
|
||||
@@ -366,7 +488,10 @@ Error Db::EditItemInItem(Item & item, bool with_url)
|
||||
<< item.parent_id
|
||||
<< item.subject
|
||||
<< item.guest_name
|
||||
<< item.html_template;
|
||||
<< item.html_template
|
||||
<< item.sort_index
|
||||
<< item.meta
|
||||
<< item.ameta;
|
||||
|
||||
if( with_url )
|
||||
{
|
||||
@@ -408,13 +533,16 @@ Error Db::EditItemInContent(Item & item)
|
||||
// we don't change 'ref' here
|
||||
query.Clear();
|
||||
query << R("update core.content set (content, content_type, file_path, file_fs, "
|
||||
"file_type, has_thumb, modify_index) = (")
|
||||
"file_type, has_thumb, hash, hash_type, file_size, modify_index) = (")
|
||||
<< item.content
|
||||
<< static_cast<int>(item.content_type)
|
||||
<< item.file_path
|
||||
<< item.file_fs
|
||||
<< item.file_type
|
||||
<< static_cast<int>(item.has_thumb)
|
||||
<< item.hash
|
||||
<< item.hash_type
|
||||
<< item.file_size
|
||||
<< item.modify_index
|
||||
<< R(") where id=")
|
||||
<< item.content_id
|
||||
@@ -611,9 +739,22 @@ return result;
|
||||
|
||||
|
||||
|
||||
PGresult * Db::GetItemsQuery(const DbItemQuery & iq, bool skip_other_sel)
|
||||
Error Db::EditSortIndexItemById(long id, int sort_index)
|
||||
{
|
||||
query.Clear();
|
||||
query << R("update core.item set (sort_index) = (")
|
||||
<< sort_index
|
||||
<< R(") where id=")
|
||||
<< id
|
||||
<< R(";");
|
||||
|
||||
return DoCommand(query);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void Db::GetItemsQuerySelect(const DbItemQuery & iq, DbTextStream & query, bool skip_other_sel)
|
||||
{
|
||||
query << R("select item.id, content_id");
|
||||
|
||||
if( !skip_other_sel )
|
||||
@@ -629,15 +770,26 @@ PGresult * Db::GetItemsQuery(const DbItemQuery & iq, bool skip_other_sel)
|
||||
if( iq.sel_url ) query << R(", url");
|
||||
if( iq.sel_type ) query << R(", type");
|
||||
if( iq.sel_link ) query << R(", link_to, link_redirect");
|
||||
if( iq.sel_file ) query << R(", file_path, file_fs, file_type, has_thumb");
|
||||
if( iq.sel_file ) query << R(", file_path, file_fs, file_type, has_thumb, hash, hash_type, file_size");
|
||||
if( iq.sel_html_template ) query << R(", template");
|
||||
if( iq.sel_sort_index ) query << R(", sort_index");
|
||||
if( iq.sel_meta ) query << R(", meta, ameta");
|
||||
}
|
||||
|
||||
query << R(" from core.item");
|
||||
|
||||
}
|
||||
|
||||
|
||||
void Db::GetItemsQueryJoin(const DbItemQuery & iq, DbTextStream & query)
|
||||
{
|
||||
if( iq.sel_content || iq.sel_file || iq.where_file_type )
|
||||
query << R(" left join core.content on item.content_id = content.id");
|
||||
}
|
||||
|
||||
|
||||
|
||||
void Db::GetItemsQueryWhere(const DbItemQuery & iq, DbTextStream & query)
|
||||
{
|
||||
if( iq.where_id || iq.where_parent_id || iq.where_type || iq.where_file_type )
|
||||
{
|
||||
query << R(" where ");
|
||||
@@ -682,19 +834,53 @@ PGresult * Db::GetItemsQuery(const DbItemQuery & iq, bool skip_other_sel)
|
||||
if_and = add_and;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
query << R(" order by item.date_creation");
|
||||
|
||||
if( iq.sort_asc )
|
||||
query << R(" asc");
|
||||
else
|
||||
query << R(" desc");
|
||||
|
||||
void Db::GetItemsQueryOrder(const DbItemQuery & iq, DbTextStream & query)
|
||||
{
|
||||
if( iq.sel_sort_index || iq.sel_date )
|
||||
{
|
||||
query << R(" order by");
|
||||
|
||||
if( iq.sel_sort_index )
|
||||
query << R(" sort_index");
|
||||
|
||||
if( iq.sel_date )
|
||||
{
|
||||
if( iq.sel_sort_index )
|
||||
query << R(",");
|
||||
|
||||
query << R(" item.date_creation");
|
||||
}
|
||||
|
||||
if( iq.sort_asc )
|
||||
query << R(" asc");
|
||||
else
|
||||
query << R(" desc");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Db::GetItemsQueryLimit(const DbItemQuery & iq, DbTextStream & query)
|
||||
{
|
||||
if( iq.limit != 0 )
|
||||
query << R(" limit ") << iq.limit;
|
||||
|
||||
if( iq.offset != 0 )
|
||||
query << R(" offset ") << iq.offset;
|
||||
}
|
||||
|
||||
|
||||
PGresult * Db::GetItemsQuery(const DbItemQuery & iq, DbTextStream & query, bool skip_other_sel)
|
||||
{
|
||||
query.Clear();
|
||||
|
||||
GetItemsQuerySelect(iq, query, skip_other_sel);
|
||||
GetItemsQueryJoin(iq, query);
|
||||
GetItemsQueryWhere(iq, query);
|
||||
GetItemsQueryOrder(iq, query);
|
||||
GetItemsQueryLimit(iq, query);
|
||||
|
||||
query << R(";");
|
||||
|
||||
@@ -703,6 +889,13 @@ return AssertQuery(query);
|
||||
|
||||
|
||||
|
||||
PGresult * Db::GetItemsQuery(const DbItemQuery & iq, bool skip_other_sel)
|
||||
{
|
||||
return GetItemsQuery(iq, query, skip_other_sel);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void Db::GetItems(std::vector<Item> & item_tab, const DbItemQuery & item_query)
|
||||
{
|
||||
@@ -714,16 +907,18 @@ void Db::GetItems(std::vector<Item> & item_tab, const DbItemQuery & item_query)
|
||||
r = GetItemsQuery(item_query);
|
||||
AssertResult(r, PGRES_TUPLES_OK);
|
||||
|
||||
Item item;
|
||||
get_item_temp.Clear();
|
||||
int rows = Rows(r);
|
||||
|
||||
DbItemColumns col;
|
||||
col.SetColumns(r);
|
||||
if( rows > 0 && size_t(rows) > item_tab.capacity() )
|
||||
item_tab.reserve(rows);
|
||||
|
||||
item_cols.SetColumns(r);
|
||||
|
||||
for(int i = 0 ; i<rows ; ++i)
|
||||
for(int i=0 ; i<rows ; ++i)
|
||||
{
|
||||
col.SetItem(r, i, item);
|
||||
item_tab.push_back(item);
|
||||
item_tab.push_back(get_item_temp);
|
||||
item_cols.SetItem(r, i, item_tab.back());
|
||||
}
|
||||
}
|
||||
catch(const Error &)
|
||||
@@ -777,9 +972,8 @@ Error Db::GetItem(Item & item, const DbItemQuery & item_query)
|
||||
|
||||
if( rows == 1 )
|
||||
{
|
||||
DbItemColumns col;
|
||||
col.SetColumns(r);
|
||||
col.SetItem(r, 0, item);
|
||||
item_cols.SetColumns(r);
|
||||
item_cols.SetItem(r, 0, item);
|
||||
}
|
||||
else
|
||||
if( rows == 0 )
|
||||
@@ -860,9 +1054,8 @@ Error Db::GetItem(long parent_id, const std::wstring & url, Item & item)
|
||||
if( Rows(r) == 0 )
|
||||
throw Error(WINIX_ERR_NO_ITEM);
|
||||
|
||||
DbItemColumns col;
|
||||
col.SetColumns(r);
|
||||
col.SetItem(r, 0, item);
|
||||
item_cols.SetColumns(r);
|
||||
item_cols.SetItem(r, 0, item);
|
||||
}
|
||||
catch(const Error & e)
|
||||
{
|
||||
@@ -894,9 +1087,8 @@ Error Db::GetItemById(long item_id, Item & item)
|
||||
if( Rows(r) == 0 )
|
||||
throw Error(WINIX_ERR_NO_ITEM);
|
||||
|
||||
DbItemColumns col;
|
||||
col.SetColumns(r);
|
||||
col.SetItem(r, 0, item);
|
||||
item_cols.SetColumns(r);
|
||||
item_cols.SetItem(r, 0, item);
|
||||
}
|
||||
catch(const Error & e)
|
||||
{
|
||||
@@ -979,9 +1171,8 @@ bool result = false;
|
||||
if( Rows(r) != 1 )
|
||||
throw Error();
|
||||
|
||||
DbItemColumns col;
|
||||
col.SetColumns(r);
|
||||
col.SetItem(r, 0, item);
|
||||
item_cols.SetColumns(r);
|
||||
item_cols.SetItem(r, 0, item);
|
||||
|
||||
result = true;
|
||||
}
|
||||
@@ -1082,11 +1273,14 @@ Error Db::EditFileById(const Item & item, long id)
|
||||
throw Error(WINIX_ERR_NO_ITEM);
|
||||
|
||||
query.Clear();
|
||||
query << R("update core.content set (file_path, file_fs, file_type, has_thumb) = (")
|
||||
query << R("update core.content set (file_path, file_fs, file_type, has_thumb, hash, hash_type, file_size) = (")
|
||||
<< item.file_path
|
||||
<< item.file_fs
|
||||
<< item.file_type
|
||||
<< static_cast<int>(item.has_thumb)
|
||||
<< item.hash
|
||||
<< item.hash_type
|
||||
<< item.file_size
|
||||
<< R(") where id=") << content_id << R(";");
|
||||
|
||||
r = AssertQuery(query);
|
||||
@@ -1138,6 +1332,31 @@ return EndTrans(result);
|
||||
|
||||
|
||||
|
||||
Error Db::EditMetaById(const PT::Space & meta, long id)
|
||||
{
|
||||
query.Clear();
|
||||
query << R("update core.item set (meta) = (")
|
||||
<< meta
|
||||
<< R(") where id=")
|
||||
<< id
|
||||
<< R(";");
|
||||
|
||||
return DoCommand(query);
|
||||
}
|
||||
|
||||
|
||||
Error Db::EditAdminMetaById(const PT::Space & ameta, long id)
|
||||
{
|
||||
query.Clear();
|
||||
query << R("update core.item set (ameta) = (")
|
||||
<< ameta
|
||||
<< R(") where id=")
|
||||
<< id
|
||||
<< R(";");
|
||||
|
||||
return DoCommand(query);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1366,13 +1585,11 @@ void Db::GetDirs(DirContainer & dir_tab)
|
||||
|
||||
dir_temp.Clear();
|
||||
int rows = Rows(r);
|
||||
item_cols.SetColumns(r);
|
||||
|
||||
DbItemColumns col;
|
||||
col.SetColumns(r);
|
||||
|
||||
for(int i = 0 ; i<rows ; ++i)
|
||||
for(int i=0 ; i<rows ; ++i)
|
||||
{
|
||||
col.SetItem(r, i, dir_temp);
|
||||
item_cols.SetItem(r, i, dir_temp);
|
||||
dir_tab.PushBack(dir_temp);
|
||||
}
|
||||
}
|
||||
@@ -1392,7 +1609,8 @@ void Db::GetUsers(UGContainer<User> & user_tab)
|
||||
try
|
||||
{
|
||||
query.Clear();
|
||||
query << R("select id, login, super_user, group_id, email, notify"
|
||||
query << R("select id, login, super_user, group_id, email, notify,"
|
||||
" env, aenv, status, locale_id, time_zone_id"
|
||||
" from core.user left outer join core.group_mem on"
|
||||
" core.user.id = core.group_mem.user_id order by id asc;");
|
||||
|
||||
@@ -1407,25 +1625,35 @@ void Db::GetUsers(UGContainer<User> & user_tab)
|
||||
int cgroup_id = AssertColumn(r, "group_id");
|
||||
int cemail = AssertColumn(r, "email");
|
||||
int cnotify = AssertColumn(r, "notify");
|
||||
int cenv = AssertColumn(r, "env");
|
||||
int caenv = AssertColumn(r, "aenv");
|
||||
int cstatus = AssertColumn(r, "status");
|
||||
int clocale_id = AssertColumn(r, "locale_id");
|
||||
int ctzone_id = AssertColumn(r, "time_zone_id");
|
||||
|
||||
User u;
|
||||
long last_id = -1;
|
||||
UGContainer<User>::Iterator iter = user_tab.End();
|
||||
|
||||
for(int i = 0 ; i<rows ; ++i)
|
||||
for(int i=0 ; i<rows ; ++i)
|
||||
{
|
||||
u.id = AssertValueLong(r, i, cid);
|
||||
|
||||
if( u.id != last_id )
|
||||
{
|
||||
u.name = AssertValueWide(r, i, cname);
|
||||
u.super_user = AssertValueBool(r, i, csuper_user);
|
||||
u.email = AssertValueWide(r, i, cemail);
|
||||
u.notify = AssertValueInt(r, i, cnotify);
|
||||
u.name = AssertValueWide(r, i, cname);
|
||||
u.super_user = AssertValueBool(r, i, csuper_user);
|
||||
u.email = AssertValueWide(r, i, cemail);
|
||||
u.notify = AssertValueInt(r, i, cnotify);
|
||||
u.status = AssertValueInt(r, i, cstatus);
|
||||
u.locale_id = (size_t)AssertValueInt(r, i, clocale_id);
|
||||
u.time_zone_id = (size_t)AssertValueInt(r, i, ctzone_id);
|
||||
AssertValueSpace(r, i, cenv, u.env);
|
||||
AssertValueSpace(r, i, caenv, u.aenv);
|
||||
|
||||
log << log2 << "Db: user: id:" << u.id << ", name:" << u.name << ", super_user:" << u.super_user << logend;
|
||||
log << log2 << "Db: user: id: " << u.id << ", name: " << u.name << ", super_user: " << u.super_user << logend;
|
||||
|
||||
iter = user_tab.PushBack( u );
|
||||
iter = user_tab.PushBack(u);
|
||||
|
||||
if( iter == user_tab.End() )
|
||||
log << log1 << "Db: can't add a user: " << u.name << logend;
|
||||
@@ -1438,7 +1666,7 @@ void Db::GetUsers(UGContainer<User> & user_tab)
|
||||
if( !IsNull(r, i, cgroup_id) && group_id!=-1 && iter!=user_tab.End() )
|
||||
{
|
||||
iter->groups.push_back(group_id);
|
||||
log << log3 << "Db: user:" << iter->name << " is a member of group_id:" << group_id << logend;
|
||||
log << log3 << "Db: user:" << iter->name << " is a member of group_id: " << group_id << logend;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1481,7 +1709,7 @@ void Db::GetGroups(UGContainer<Group> & group_tab)
|
||||
if( g.id != last_id )
|
||||
{
|
||||
g.name = AssertValueWide(r, i, cname);
|
||||
log << log3 << "Db: get group, id:" << g.id << ", group:" << g.name << logend;
|
||||
log << log3 << "Db: get group, id: " << g.id << ", group: " << g.name << logend;
|
||||
|
||||
iter = group_tab.PushBack( g );
|
||||
last_id = g.id;
|
||||
@@ -1492,7 +1720,7 @@ void Db::GetGroups(UGContainer<Group> & group_tab)
|
||||
if( !IsNull(r, i, cuser_id) && user_id!=-1 && !group_tab.Empty() )
|
||||
{
|
||||
iter->members.push_back(user_id);
|
||||
log << log3 << "Db: get group member: user_id:" << user_id << logend;
|
||||
log << log3 << "Db: get group member: user_id: " << user_id << logend;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
38
db/db.h
38
db/db.h
@@ -2,7 +2,7 @@
|
||||
* This file is a part of Winix
|
||||
* and is not publicly distributed
|
||||
*
|
||||
* Copyright (c) 2008-2011, Tomasz Sowa
|
||||
* Copyright (c) 2008-2012, Tomasz Sowa
|
||||
* All rights reserved.
|
||||
*
|
||||
*/
|
||||
@@ -39,10 +39,21 @@ public:
|
||||
// !! GetDir tylko dla katalogow
|
||||
// !! GetFile i GetDir beda uzywac GetItem
|
||||
|
||||
|
||||
Db() : item_cols(*this)
|
||||
{
|
||||
}
|
||||
|
||||
bool GetUserPass(const std::wstring & login, long & user_id, UserPass & up);
|
||||
Error AddUser(User & user, const std::wstring & password, const std::string & password_encrypted, int pass_type, bool pass_hash_salted);
|
||||
|
||||
bool GetUserPass(const std::wstring & login, long & user_id, UserPass & up);
|
||||
Error AddUser(User & user, const UserPass & up);
|
||||
Error ChangeUserPass(long user_id, const UserPass & up);
|
||||
Error ChangeUserEnv(long user_id, const PT::Space & space);
|
||||
Error ChangeUserAdminEnv(long user_id, const PT::Space & space);
|
||||
Error ChangeUserStatus(long user_id, int status);
|
||||
Error ChangeUserEmail(long user_id, const std::wstring & email);
|
||||
Error ChangeUserLocale(long user_id, size_t locale_id);
|
||||
Error ChangeUserTimeZone(long user_id, size_t time_zone_id);
|
||||
Error RemoveUser(long user_id);
|
||||
|
||||
Error AddItem(Item & item);
|
||||
Error EditItemById(Item & item, bool with_url = true);
|
||||
@@ -56,10 +67,12 @@ public:
|
||||
Error GetItem(Item & item, const DbItemQuery & item_query);
|
||||
|
||||
bool GetPriv(Item & item, long id);
|
||||
Error EditPrivById(Item & item, long id);
|
||||
Error EditPrivById(Item & item, long id); // !! dlaczego tu nie ma const?
|
||||
Error EditParentUrlById(Item & item, long id);
|
||||
Error EditFileById(const Item & item, long id); // file_path, file_fs, file_type
|
||||
Error EditHasThumbById(bool has_thumb, long id);
|
||||
Error EditMetaById(const PT::Space & meta, long id);
|
||||
Error EditAdminMetaById(const PT::Space & meta, long id);
|
||||
|
||||
Error DelDirById(long id);
|
||||
Error DelFileById(long file_id);
|
||||
@@ -86,7 +99,7 @@ public:
|
||||
long GetDirId(long parent_id, const std::wstring & url);
|
||||
|
||||
Error AddHardLink(Item & item);
|
||||
|
||||
Error EditSortIndexItemById(long id, int sort_index);
|
||||
|
||||
|
||||
|
||||
@@ -95,7 +108,10 @@ protected:
|
||||
DbTextStream query, query_create_url;
|
||||
std::wstring temp_url;
|
||||
Item dir_temp;
|
||||
Item get_item_temp;
|
||||
std::wstring iq_id_list;
|
||||
DbItemColumns item_cols;
|
||||
|
||||
|
||||
bool AddItemCreateUrlSubject(Item & item);
|
||||
|
||||
@@ -107,13 +123,21 @@ protected:
|
||||
Error EditItemGetIdsByUrl(Item & item);
|
||||
long GetContentId(long item_id);
|
||||
|
||||
PGresult * GetItemsQuery(const DbItemQuery & iq, bool skip_other_sel = false);
|
||||
|
||||
Error DelItemDelItem(long item_id, int type);
|
||||
Error DelItemDelContent(long content_id);
|
||||
|
||||
Error IncrementContentRef(long content_id);
|
||||
Error DecrementContentRef(long content_id);
|
||||
|
||||
void GetItemsQuerySelect(const DbItemQuery & iq, DbTextStream & query, bool skip_other_sel);
|
||||
void GetItemsQueryJoin(const DbItemQuery & iq, DbTextStream & query);
|
||||
void GetItemsQueryWhere(const DbItemQuery & iq, DbTextStream & query);
|
||||
void GetItemsQueryOrder(const DbItemQuery & iq, DbTextStream & query);
|
||||
void GetItemsQueryLimit(const DbItemQuery & iq, DbTextStream & query);
|
||||
PGresult * GetItemsQuery(const DbItemQuery & iq, DbTextStream & query, bool skip_other_sel = false);
|
||||
PGresult * GetItemsQuery(const DbItemQuery & iq, bool skip_other_sel = false);
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
186
db/dbbase.cpp
186
db/dbbase.cpp
@@ -2,7 +2,7 @@
|
||||
* This file is a part of Winix
|
||||
* and is not publicly distributed
|
||||
*
|
||||
* Copyright (c) 2010-2011, Tomasz Sowa
|
||||
* Copyright (c) 2010-2012, Tomasz Sowa
|
||||
* All rights reserved.
|
||||
*
|
||||
*/
|
||||
@@ -14,7 +14,7 @@
|
||||
#include "core/log.h"
|
||||
#include "core/error.h"
|
||||
#include "core/misc.h"
|
||||
#include "utf8.h"
|
||||
#include "utf8/utf8.h"
|
||||
|
||||
|
||||
|
||||
@@ -88,10 +88,6 @@ return r;
|
||||
}
|
||||
|
||||
|
||||
PGresult * DbBase::AssertQuery(const std::wstring & q)
|
||||
{
|
||||
return AssertQuery(q.c_str());
|
||||
}
|
||||
|
||||
|
||||
PGresult * DbBase::AssertQuery(const DbTextStream & query)
|
||||
@@ -100,11 +96,28 @@ PGresult * DbBase::AssertQuery(const DbTextStream & query)
|
||||
}
|
||||
|
||||
|
||||
|
||||
PGresult * DbBase::AssertQuery(const char * q, ExecStatusType t)
|
||||
{
|
||||
PGresult * r = AssertQuery(q);
|
||||
AssertResult(r, t);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
PGresult * DbBase::AssertQuery(const DbTextStream & query, ExecStatusType t)
|
||||
{
|
||||
return AssertQuery(query.CStr(), t);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void DbBase::AssertResult(PGresult * r, ExecStatusType t)
|
||||
{
|
||||
if( PQresultStatus(r) != t )
|
||||
{
|
||||
log << "Db: Incorrect result status: " << PQerrorMessage(db_conn->GetPgConn()) << logend;
|
||||
log << log1 << "Db: Incorrect result status: " << PQerrorMessage(db_conn->GetPgConn()) << logend;
|
||||
|
||||
throw Error(WINIX_ERR_DB_INCORRENT_RESULT_STATUS);
|
||||
}
|
||||
@@ -143,9 +156,9 @@ return res;
|
||||
const std::wstring & DbBase::AssertValueWide(PGresult * r, int row, int col)
|
||||
{
|
||||
const char * res = AssertValue(r, row, col);
|
||||
static std::wstring temp_wide_value;
|
||||
static std::wstring temp_wide_value; // !! IMPROVE ME add as a class field (nonstatic)
|
||||
|
||||
Ezc::UTF8ToWide(res, temp_wide_value);
|
||||
PT::UTF8ToWide(res, temp_wide_value);
|
||||
|
||||
return temp_wide_value;
|
||||
}
|
||||
@@ -169,7 +182,7 @@ void DbBase::AssertValueBin(PGresult * r, int row, int col, std::string & result
|
||||
void DbBase::AssertValueWide(PGresult * r, int row, int col, std::wstring & result)
|
||||
{
|
||||
const char * res = AssertValue(r, row, col);
|
||||
Ezc::UTF8ToWide(res, result);
|
||||
PT::UTF8ToWide(res, result);
|
||||
}
|
||||
|
||||
|
||||
@@ -204,12 +217,45 @@ unsigned int DbBase::AssertValueUInt(PGresult * r, int row, int col)
|
||||
}
|
||||
|
||||
|
||||
tm DbBase::AssertValueTm(PGresult * r, int row, int col)
|
||||
|
||||
PT::Date DbBase::AssertValueDate(PGresult * r, int row, int col)
|
||||
{
|
||||
return ConvertTime(AssertValue(r, row, col));
|
||||
PT::Date date = AssertValue(r, row, col);
|
||||
|
||||
return date;
|
||||
}
|
||||
|
||||
|
||||
bool DbBase::AssertValueSpace(PGresult * r, int row, int col, PT::Space & space, bool split_single)
|
||||
{
|
||||
const char * res = AssertValue(r, row, col);
|
||||
|
||||
conf_parser.UTF8(true);
|
||||
conf_parser.SplitSingle(split_single);
|
||||
conf_parser.SetSpace(space);
|
||||
space.Clear();
|
||||
|
||||
PT::SpaceParser::Status status = conf_parser.ParseString(res);
|
||||
|
||||
if( status != PT::SpaceParser::ok )
|
||||
{
|
||||
log << log1 << "Db: a problem with parsing a PT::Space";
|
||||
|
||||
if( status == PT::SpaceParser::syntax_error )
|
||||
log << ", syntax error at line: " << conf_parser.line;
|
||||
|
||||
log << logend;
|
||||
|
||||
space.Clear();
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void DbBase::ClearResult(PGresult * r)
|
||||
{
|
||||
@@ -287,55 +333,8 @@ return AssertValueLong(r, 0, 0);
|
||||
|
||||
|
||||
|
||||
tm DbBase::ConvertTime(const char * str)
|
||||
{
|
||||
tm t;
|
||||
|
||||
memset(&t, 0, sizeof(t));
|
||||
|
||||
if( !str )
|
||||
return t;
|
||||
|
||||
size_t len = strlen(str);
|
||||
|
||||
if( len != 19 )
|
||||
{
|
||||
// the format must be like this: 2008-12-31 22:30:00
|
||||
log << log1 << "DbBase: ConvertTime: unknown time format: \"" << str << "\"" << logend;
|
||||
return t;
|
||||
}
|
||||
|
||||
t.tm_year = Toi(str + 0) - 1900; /* year - 1900 */
|
||||
t.tm_mon = Toi(str + 5) - 1; /* month of year (0 - 11) */
|
||||
t.tm_mday = Toi(str + 8); /* day of month (1 - 31) */
|
||||
t.tm_hour = Toi(str + 11); /* hours (0 - 23) */
|
||||
t.tm_min = Toi(str + 14); /* minutes (0 - 59) */
|
||||
t.tm_sec = Toi(str + 17); /* seconds (0 - 60) */
|
||||
|
||||
// t.tm_wday = 0; /* day of week (Sunday = 0) */
|
||||
// t.tm_yday = 0; /* day of year (0 - 365) */
|
||||
// t.tm_isdst = 0; /* is summer time in effect? */
|
||||
// t.tm_zone = 0; // const_cast<char*>(""); /* abbreviation of timezone name */
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
|
||||
const char * DbBase::ConvertTime(const tm & t)
|
||||
{
|
||||
// not thread safe
|
||||
static char buffer[100];
|
||||
|
||||
sprintf(buffer, "%04d-%02d-%02d %02d:%02d:%02d",
|
||||
t.tm_year + 1900,
|
||||
t.tm_mon + 1,
|
||||
t.tm_mday,
|
||||
t.tm_hour,
|
||||
t.tm_min,
|
||||
t.tm_sec);
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -430,6 +429,25 @@ Error DbBase::CommitTrans()
|
||||
|
||||
|
||||
|
||||
bool DbBase::EndTrans(bool everything_ok)
|
||||
{
|
||||
bool result;
|
||||
|
||||
if( everything_ok )
|
||||
{
|
||||
result = (CommitTrans() == WINIX_ERR_OK);
|
||||
}
|
||||
else
|
||||
{
|
||||
RollbackTrans();
|
||||
// we return the old err code
|
||||
result = false;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
Error DbBase::EndTrans(Error err)
|
||||
{
|
||||
if( err == WINIX_ERR_OK )
|
||||
@@ -452,8 +470,9 @@ return err;
|
||||
|
||||
/*
|
||||
converting from a bytea
|
||||
the old way (escape format)
|
||||
*/
|
||||
|
||||
/*
|
||||
int DbBase::CharToInt(char c)
|
||||
{
|
||||
return (int)(unsigned char)(c-'0');
|
||||
@@ -519,6 +538,53 @@ size_t i = 0;
|
||||
out += c;
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
converting from a bytea
|
||||
the new way (hex format)
|
||||
*/
|
||||
|
||||
|
||||
char DbBase::UnescapeBinHexToDigit(char hex)
|
||||
{
|
||||
if( hex>='0' && hex<='9' )
|
||||
return hex - '0';
|
||||
|
||||
if( hex>='a' && hex<='z' )
|
||||
return hex - 'a' + 10;
|
||||
|
||||
if( hex>='A' && hex<='Z' )
|
||||
return hex - 'A' + 10;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void DbBase::UnescapeBin(const char * str, size_t len, std::string & out, bool clear_out)
|
||||
{
|
||||
if( clear_out )
|
||||
out.clear();
|
||||
|
||||
if( len < 2 || str[0]!='\\' || str[1]!='x' )
|
||||
{
|
||||
log << log1 << "Db: unsupported binary format (skipping)" << logend;
|
||||
return;
|
||||
}
|
||||
|
||||
for(size_t i=2 ; i + 1 < len ; i+=2 )
|
||||
{
|
||||
int c1 = UnescapeBinHexToDigit(str[i]);
|
||||
int c2 = UnescapeBinHexToDigit(str[i+1]);
|
||||
|
||||
out += ((c1 << 4) | c2);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
end of converting from bytea
|
||||
|
||||
28
db/dbbase.h
28
db/dbbase.h
@@ -2,7 +2,7 @@
|
||||
* This file is a part of Winix
|
||||
* and is not publicly distributed
|
||||
*
|
||||
* Copyright (c) 2010-2011, Tomasz Sowa
|
||||
* Copyright (c) 2010-2012, Tomasz Sowa
|
||||
* All rights reserved.
|
||||
*
|
||||
*/
|
||||
@@ -16,6 +16,9 @@
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include "core/error.h"
|
||||
#include "space/spaceparser.h"
|
||||
#include "date/date.h"
|
||||
|
||||
|
||||
|
||||
class DbBase
|
||||
@@ -31,11 +34,13 @@ public:
|
||||
void LogQueries(bool log_q);
|
||||
|
||||
PGresult * AssertQuery(const char * query);
|
||||
PGresult * AssertQuery(const std::wstring & query);
|
||||
PGresult * AssertQuery(const DbTextStream & query);
|
||||
PGresult * AssertQuery(const char * q, ExecStatusType t);
|
||||
PGresult * AssertQuery(const DbTextStream & query, ExecStatusType t);
|
||||
void AssertResult(PGresult * r, ExecStatusType t);
|
||||
static int AssertColumn(PGresult * r, const char * column_name);
|
||||
|
||||
// static assignments
|
||||
static const char * AssertValue(PGresult * r, int row, int col);
|
||||
static const std::wstring & AssertValueWide(PGresult * r, int row, int col); // warning: this method uses a static buffer
|
||||
static void AssertValueWide(PGresult * r, int row, int col, std::wstring & result);
|
||||
@@ -45,7 +50,10 @@ public:
|
||||
static bool AssertValueBool(PGresult * r, int row, int col);
|
||||
static unsigned long AssertValueULong(PGresult * r, int row, int col);
|
||||
static unsigned int AssertValueUInt(PGresult * r, int row, int col);
|
||||
static tm AssertValueTm(PGresult * r, int row, int col);
|
||||
static PT::Date AssertValueDate(PGresult * r, int row, int col);
|
||||
|
||||
// non static assignments
|
||||
bool AssertValueSpace(PGresult * r, int row, int col, PT::Space & space, bool split_single = true);
|
||||
|
||||
void ClearResult(PGresult * r);
|
||||
long AssertCurrval(const char * table);
|
||||
@@ -55,8 +63,6 @@ public:
|
||||
int Cols(PGresult * r);
|
||||
long AffectedRows(PGresult * r);
|
||||
|
||||
static tm ConvertTime(const char * str);
|
||||
static const char * ConvertTime(const tm & t); // warning: it uses its own static buffer
|
||||
void CreateIdList(const std::vector<long> & id_tab, std::wstring & list, bool add_parentheses = true);
|
||||
|
||||
Error DoCommand(const DbTextStream & command);
|
||||
@@ -66,6 +72,9 @@ public:
|
||||
Error CommitTrans();
|
||||
Error EndTrans(Error err);
|
||||
|
||||
// new API (returns only bool)
|
||||
bool EndTrans(bool everything_ok);
|
||||
|
||||
static void UnescapeBin(const char * str, size_t len, std::string & out, bool clear_out = true);
|
||||
|
||||
|
||||
@@ -84,11 +93,14 @@ protected:
|
||||
|
||||
private:
|
||||
|
||||
static int CharToInt(char c);
|
||||
static bool IsCorrectOctalDigit(char c);
|
||||
static int UnescapeBin(const char * str, size_t & i, size_t len);
|
||||
// static int CharToInt(char c);
|
||||
// static bool IsCorrectOctalDigit(char c);
|
||||
// static int UnescapeBin(const char * str, size_t & i, size_t len);
|
||||
|
||||
static char UnescapeBinHexToDigit(char hex);
|
||||
|
||||
DbTextStream bquery;
|
||||
PT::SpaceParser conf_parser;
|
||||
|
||||
};
|
||||
|
||||
|
||||
@@ -2,13 +2,15 @@
|
||||
* This file is a part of Winix
|
||||
* and is not publicly distributed
|
||||
*
|
||||
* Copyright (c) 2008-2010, Tomasz Sowa
|
||||
* Copyright (c) 2008-2012, Tomasz Sowa
|
||||
* All rights reserved.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "dbitemcolumns.h"
|
||||
#include "dbbase.h"
|
||||
#include "core/log.h"
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -37,20 +39,25 @@ void DbItemColumns::SetColumns(PGresult * r)
|
||||
file_fs = PQfnumber(r, "file_fs");
|
||||
file_type = PQfnumber(r, "file_type");
|
||||
has_thumb = PQfnumber(r, "has_thumb");
|
||||
hash = PQfnumber(r, "hash");
|
||||
hash_type = PQfnumber(r, "hash_type");
|
||||
file_size = PQfnumber(r, "file_size");
|
||||
ref = PQfnumber(r, "ref");
|
||||
modify_index = PQfnumber(r, "modify_index");
|
||||
sort_index = PQfnumber(r, "sort_index");
|
||||
meta = PQfnumber(r, "meta");
|
||||
ameta = PQfnumber(r, "ameta");
|
||||
}
|
||||
|
||||
|
||||
|
||||
void DbItemColumns::SetItem(PGresult * r, long row, Item & item)
|
||||
{
|
||||
if( id != -1 ) item.id = DbBase::AssertValueLong(r, row, id);
|
||||
if( user_id != -1 ) item.user_id = DbBase::AssertValueLong(r, row, user_id);
|
||||
if( group_id != -1 ) item.group_id = DbBase::AssertValueLong(r, row, group_id);
|
||||
if( privileges != -1 ) item.privileges = DbBase::AssertValueInt(r, row, privileges);
|
||||
if( date_creation != -1 ) item.date_creation = DbBase::AssertValueTm(r, row, date_creation);
|
||||
if( date_modification != -1 ) item.date_modification = DbBase::AssertValueTm(r, row, date_modification);
|
||||
if( date_creation != -1 ) item.date_creation = DbBase::AssertValueDate(r, row, date_creation);
|
||||
if( date_modification != -1 ) item.date_modification = DbBase::AssertValueDate(r, row, date_modification);
|
||||
if( type != -1 ) item.type = static_cast<Item::Type>( DbBase::AssertValueInt(r, row, type) );
|
||||
if( parent_id != -1 ) item.parent_id = DbBase::AssertValueLong(r, row, parent_id);
|
||||
if( content_id != -1 ) item.content_id = DbBase::AssertValueLong(r, row, content_id);
|
||||
@@ -60,6 +67,10 @@ void DbItemColumns::SetItem(PGresult * r, long row, Item & item)
|
||||
if( file_fs != -1 ) item.file_fs = DbBase::AssertValueInt(r, row, file_fs);
|
||||
if( file_type != -1 ) item.file_type = DbBase::AssertValueInt(r, row, file_type);
|
||||
if( has_thumb != -1 ) item.has_thumb = DbBase::AssertValueBool(r, row, has_thumb);
|
||||
if( hash != -1 ) DbBase::AssertValueWide(r, row, hash, item.hash);
|
||||
if( hash_type != -1 ) item.hash_type = DbBase::AssertValueInt(r, row, hash_type);
|
||||
if( file_size != -1 ) item.file_size = DbBase::AssertValueLong(r, row, file_size);
|
||||
|
||||
if( ref != -1 ) item.ref = DbBase::AssertValueInt(r, row, ref);
|
||||
if( modify_index != -1 ) item.modify_index = DbBase::AssertValueInt(r, row, modify_index);
|
||||
|
||||
@@ -70,6 +81,10 @@ void DbItemColumns::SetItem(PGresult * r, long row, Item & item)
|
||||
if( link_to != -1 ) DbBase::AssertValueWide(r, row, link_to, item.link_to);
|
||||
if( guest_name != -1 ) DbBase::AssertValueWide(r, row, guest_name, item.guest_name);
|
||||
if( html_template != -1 ) DbBase::AssertValueWide(r, row, html_template, item.html_template);
|
||||
if( sort_index != -1 ) item.sort_index = DbBase::AssertValueInt(r, row, sort_index);
|
||||
|
||||
if( meta != -1 ) db_base.AssertValueSpace(r, row, meta, item.meta);
|
||||
if( ameta != -1 ) db_base.AssertValueSpace(r, row, ameta, item.ameta);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* This file is a part of Winix
|
||||
* and is not publicly distributed
|
||||
*
|
||||
* Copyright (c) 2010, Tomasz Sowa
|
||||
* Copyright (c) 2010-2012, Tomasz Sowa
|
||||
* All rights reserved.
|
||||
*
|
||||
*/
|
||||
@@ -13,7 +13,7 @@
|
||||
|
||||
#include <libpq-fe.h>
|
||||
#include "core/item.h"
|
||||
|
||||
#include "dbbase.h"
|
||||
|
||||
|
||||
|
||||
@@ -41,11 +41,26 @@ struct DbItemColumns
|
||||
int file_fs;
|
||||
int file_type;
|
||||
int has_thumb;
|
||||
int hash;
|
||||
int hash_type;
|
||||
int file_size;
|
||||
int ref;
|
||||
int modify_index;
|
||||
int sort_index;
|
||||
int meta;
|
||||
int ameta;
|
||||
|
||||
DbItemColumns(DbBase & db_base_) : db_base(db_base_)
|
||||
{
|
||||
}
|
||||
|
||||
void SetColumns(PGresult * r);
|
||||
void SetItem(PGresult * r, long row, Item & item);
|
||||
|
||||
private:
|
||||
|
||||
DbBase & db_base;
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* This file is a part of Winix
|
||||
* and is not publicly distributed
|
||||
*
|
||||
* Copyright (c) 2010, Tomasz Sowa
|
||||
* Copyright (c) 2010-2011, Tomasz Sowa
|
||||
* All rights reserved.
|
||||
*
|
||||
*/
|
||||
@@ -56,6 +56,8 @@ void DbItemQuery::SetAllSel(bool sel)
|
||||
sel_link = sel;
|
||||
sel_file = sel;
|
||||
sel_html_template = sel;
|
||||
sel_sort_index = sel;
|
||||
sel_meta = sel;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* This file is a part of Winix
|
||||
* and is not publicly distributed
|
||||
*
|
||||
* Copyright (c) 2010, Tomasz Sowa
|
||||
* Copyright (c) 2010-2012, Tomasz Sowa
|
||||
* All rights reserved.
|
||||
*
|
||||
*/
|
||||
@@ -30,8 +30,10 @@ struct DbItemQuery
|
||||
bool sel_url; // url
|
||||
bool sel_type; // type (dir, file, none)
|
||||
bool sel_link; // link_to, link_redirect
|
||||
bool sel_file; // file_path, file_fs, file_type, has_thumb
|
||||
bool sel_file; // file_path, file_fs, file_type, has_thumb, hash, hash_type, file_size
|
||||
bool sel_html_template; // template
|
||||
bool sel_sort_index; // sort_index
|
||||
bool sel_meta; // meta and ameta (PT::Space)
|
||||
|
||||
bool where_id; //
|
||||
bool where_parent_id; //
|
||||
|
||||
@@ -2,13 +2,13 @@
|
||||
* This file is a part of Winix
|
||||
* and is not publicly distributed
|
||||
*
|
||||
* Copyright (c) 2010-2011, Tomasz Sowa
|
||||
* Copyright (c) 2010-2012, Tomasz Sowa
|
||||
* All rights reserved.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "dbtextstream.h"
|
||||
#include "utf8.h"
|
||||
#include "utf8/utf8.h"
|
||||
|
||||
|
||||
DbTextStream::DbTextStream()
|
||||
@@ -56,7 +56,7 @@ DbTextStream & DbTextStream::PutText(const std::string & str)
|
||||
|
||||
DbTextStream & DbTextStream::PutText(const wchar_t * str)
|
||||
{
|
||||
Ezc::WideToUTF8(str, buffer, false);
|
||||
PT::WideToUTF8(str, buffer, false);
|
||||
was_param = false;
|
||||
|
||||
return *this;
|
||||
@@ -76,13 +76,13 @@ DbTextStream & DbTextStream::PutText(const std::wstring & str)
|
||||
|
||||
|
||||
|
||||
DbTextStream & DbTextStream::operator<<(const RawText<const char*> & raw)
|
||||
DbTextStream & DbTextStream::operator<<(RawText<const char*> raw)
|
||||
{
|
||||
return PutText(raw.par);
|
||||
}
|
||||
|
||||
|
||||
DbTextStream & DbTextStream::operator<<(const RawText<const wchar_t*> & raw)
|
||||
DbTextStream & DbTextStream::operator<<(RawText<const wchar_t*> raw)
|
||||
{
|
||||
return PutText(raw.par);
|
||||
}
|
||||
@@ -194,9 +194,15 @@ return *this;
|
||||
}
|
||||
|
||||
|
||||
DbTextStream & DbTextStream::operator<<(const RawText<tm> & t)
|
||||
|
||||
|
||||
DbTextStream & DbTextStream::operator<<(RawText<PT::Date> date)
|
||||
{
|
||||
buffer += ConvertTime(t.par);
|
||||
tmp_stream.Clear();
|
||||
date.par.Serialize(tmp_stream);
|
||||
AssignString(tmp_stream.CStr(), buffer, false);
|
||||
tmp_stream.Clear();
|
||||
|
||||
was_param = false;
|
||||
|
||||
return *this;
|
||||
@@ -206,12 +212,15 @@ return *this;
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
with escaping
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
old PostgreSQL Escape Format
|
||||
*/
|
||||
/*
|
||||
DbTextStream & DbTextStream::EBinPutChar(char c_)
|
||||
{
|
||||
char buf[20];
|
||||
@@ -230,6 +239,26 @@ char buf[20];
|
||||
|
||||
return *this;
|
||||
}
|
||||
*/
|
||||
|
||||
// get hex digit for c_ between <0, 15>
|
||||
char DbTextStream::EBinGetHex(char c)
|
||||
{
|
||||
if( c < 10 )
|
||||
return c + '0';
|
||||
|
||||
return c - 10 + 'A';
|
||||
}
|
||||
|
||||
|
||||
DbTextStream & DbTextStream::EBinPutChar(char c)
|
||||
{
|
||||
buffer += EBinGetHex(((unsigned char)c) >> 4);
|
||||
buffer += EBinGetHex(((unsigned char)c) & 0x0f);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
|
||||
DbTextStream & DbTextStream::ETextPutChar(char c)
|
||||
@@ -256,7 +285,7 @@ DbTextStream & DbTextStream::ETextPutChar(wchar_t c)
|
||||
buffer += "\\\'"; // don't use "''" because we use the method for PQconnectdb too
|
||||
else
|
||||
if( c != 0 )
|
||||
Ezc::IntToUTF8(int(c), buffer, false);
|
||||
PT::IntToUTF8(int(c), buffer, false);
|
||||
|
||||
return *this;
|
||||
}
|
||||
@@ -336,7 +365,7 @@ DbTextStream & DbTextStream::EPutBin(const char * str, size_t len)
|
||||
if( ext_escape )
|
||||
buffer += 'E';
|
||||
|
||||
buffer += '\'';
|
||||
buffer += "\'\\\\x";
|
||||
|
||||
for(size_t i = 0 ; i < len ; ++i)
|
||||
EBinPutChar(str[i]);
|
||||
@@ -521,14 +550,25 @@ return *this;
|
||||
|
||||
|
||||
|
||||
DbTextStream & DbTextStream::operator<<(const tm & t)
|
||||
|
||||
|
||||
DbTextStream & DbTextStream::operator<<(const std::vector<long> & tabid)
|
||||
{
|
||||
if( was_param )
|
||||
buffer += ", ";
|
||||
|
||||
buffer += '\'';
|
||||
buffer += ConvertTime(t);
|
||||
buffer += '\'';
|
||||
buffer += '(';
|
||||
|
||||
for(size_t i=0 ; i<tabid.size(); ++i)
|
||||
{
|
||||
TextStream<std::string>::operator<<(tabid[i]);
|
||||
|
||||
if( i + 1 < tabid.size() )
|
||||
buffer += ',';
|
||||
}
|
||||
|
||||
buffer += ')';
|
||||
|
||||
was_param = true;
|
||||
|
||||
return *this;
|
||||
@@ -536,22 +576,30 @@ return *this;
|
||||
|
||||
|
||||
|
||||
const char * DbTextStream::ConvertTime(const tm & t)
|
||||
|
||||
|
||||
|
||||
DbTextStream & DbTextStream::operator<<(const PT::Space & space)
|
||||
{
|
||||
// not thread safe
|
||||
static char buffer[100];
|
||||
tmp_stream.Clear();
|
||||
// !! IMPROVE ME
|
||||
// we can calculate how much memory is needed before serializing
|
||||
space.Serialize(tmp_stream, true, false);
|
||||
operator<<(tmp_stream.Str());
|
||||
tmp_stream.Clear();
|
||||
|
||||
sprintf(buffer, "%04d-%02d-%02d %02d:%02d:%02d",
|
||||
t.tm_year + 1900,
|
||||
t.tm_mon + 1,
|
||||
t.tm_mday,
|
||||
t.tm_hour,
|
||||
t.tm_min,
|
||||
t.tm_sec);
|
||||
|
||||
return buffer;
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
DbTextStream & DbTextStream::operator<<(const PT::Date & date)
|
||||
{
|
||||
tmp_stream.Clear();
|
||||
date.Serialize(tmp_stream);
|
||||
operator<<(tmp_stream.Str());
|
||||
tmp_stream.Clear();
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* This file is a part of Winix
|
||||
* and is not publicly distributed
|
||||
*
|
||||
* Copyright (c) 2010-2011, Tomasz Sowa
|
||||
* Copyright (c) 2010-2012, Tomasz Sowa
|
||||
* All rights reserved.
|
||||
*
|
||||
*/
|
||||
@@ -12,6 +12,7 @@
|
||||
|
||||
#include <ctime>
|
||||
#include "core/textstream.h"
|
||||
#include "textstream/textstream.h"
|
||||
|
||||
|
||||
|
||||
@@ -93,13 +94,13 @@ public:
|
||||
"some string" is actually a table (not a pointer)
|
||||
*/
|
||||
template<size_t str_size>
|
||||
DbTextStream & operator<<(const RawText<char [str_size]> & raw) { return PutText(raw.par); }
|
||||
DbTextStream & operator<<(RawText<char [str_size]> raw) { return PutText(raw.par); }
|
||||
|
||||
template<size_t str_size>
|
||||
DbTextStream & operator<<(const RawText<wchar_t [str_size]> & raw) { return PutText(raw.par); }
|
||||
DbTextStream & operator<<(RawText<wchar_t [str_size]> raw) { return PutText(raw.par); }
|
||||
|
||||
DbTextStream & operator<<(const RawText<const char*> & raw);
|
||||
DbTextStream & operator<<(const RawText<const wchar_t*> & raw);
|
||||
DbTextStream & operator<<(RawText<const char*> raw);
|
||||
DbTextStream & operator<<(RawText<const wchar_t*> raw);
|
||||
DbTextStream & operator<<(RawText<const std::string*> raw);
|
||||
DbTextStream & operator<<(RawText<const std::wstring*> raw);
|
||||
DbTextStream & operator<<(RawText<std::string> raw);
|
||||
@@ -113,8 +114,10 @@ public:
|
||||
DbTextStream & operator<<(RawText<unsigned long> raw);
|
||||
DbTextStream & operator<<(RawText<double> raw);
|
||||
DbTextStream & operator<<(RawText<void*> raw);
|
||||
DbTextStream & operator<<(const RawText<tm> & t);
|
||||
DbTextStream & operator<<(RawText<PT::Date> date);
|
||||
|
||||
template<typename arg_char_type, size_t arg_stack_size, size_t arg_heap_block_size>
|
||||
DbTextStream & operator<<(RawText<PT::TextStreamBase<arg_char_type, arg_stack_size, arg_heap_block_size> > raw);
|
||||
|
||||
/*
|
||||
with escaping
|
||||
@@ -150,20 +153,57 @@ public:
|
||||
DbTextStream & operator<<(unsigned long);
|
||||
DbTextStream & operator<<(double);
|
||||
DbTextStream & operator<<(const void *);
|
||||
DbTextStream & operator<<(const tm & t);
|
||||
DbTextStream & operator<<(const std::vector<long> & tabid);
|
||||
DbTextStream & operator<<(const PT::Space & space);
|
||||
DbTextStream & operator<<(const PT::Date & date);
|
||||
|
||||
|
||||
static const char * ConvertTime(const tm & t);
|
||||
template<typename arg_char_type, size_t arg_stack_size, size_t arg_heap_block_size>
|
||||
DbTextStream & operator<<(const PT::TextStreamBase<arg_char_type, arg_stack_size, arg_heap_block_size> & arg);
|
||||
|
||||
private:
|
||||
|
||||
bool was_param;
|
||||
bool ext_escape;
|
||||
TextStream<std::wstring> tmp_stream;
|
||||
|
||||
char EBinGetHex(char c);
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
template<typename arg_char_type, size_t arg_stack_size, size_t arg_heap_block_size>
|
||||
DbTextStream & DbTextStream::operator<<(RawText<PT::TextStreamBase<arg_char_type, arg_stack_size, arg_heap_block_size> > raw)
|
||||
{
|
||||
TextStream<std::string>::operator<<(raw.par);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
|
||||
template<typename arg_char_type, size_t arg_stack_size, size_t arg_heap_block_size>
|
||||
DbTextStream & DbTextStream::operator<<(const PT::TextStreamBase<arg_char_type, arg_stack_size, arg_heap_block_size> & arg)
|
||||
{
|
||||
typename PT::TextStreamBase<arg_char_type, arg_stack_size, arg_heap_block_size>::const_iterator i;
|
||||
|
||||
if( was_param )
|
||||
buffer += ", ";
|
||||
|
||||
if( ext_escape )
|
||||
buffer += 'E';
|
||||
|
||||
buffer += '\'';
|
||||
|
||||
for(i=arg.begin() ; i != arg.end() ; ++i)
|
||||
ETextPutChar(*i);
|
||||
|
||||
buffer += '\'';
|
||||
was_param = true;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
1700
etc/time_zones.conf
Normal file
1700
etc/time_zones.conf
Normal file
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user